Synchronisation du contenu avec lemmy
This commit is contained in:
@@ -46,6 +46,33 @@ function applyEnvOverrides(config = {}) {
|
||||
merged.goaccess.url = process.env.GOACCESS_URL;
|
||||
}
|
||||
|
||||
const lemmy = config.lemmy || {};
|
||||
const community = lemmy.community || {};
|
||||
merged.lemmy = {
|
||||
...lemmy,
|
||||
auth: { ...(lemmy.auth || {}) },
|
||||
community: {
|
||||
...community,
|
||||
prefixOverrides: { ...(community.prefixOverrides || {}) },
|
||||
},
|
||||
verificationTtlHours: { ...(lemmy.verificationTtlHours || {}) },
|
||||
};
|
||||
if (process.env.LEMMY_INSTANCE_URL) {
|
||||
merged.lemmy.instanceUrl = process.env.LEMMY_INSTANCE_URL;
|
||||
}
|
||||
if (process.env.LEMMY_SITE_URL) {
|
||||
merged.lemmy.siteUrl = process.env.LEMMY_SITE_URL;
|
||||
}
|
||||
if (process.env.LEMMY_JWT) {
|
||||
merged.lemmy.auth.jwt = process.env.LEMMY_JWT;
|
||||
}
|
||||
if (process.env.LEMMY_USERNAME) {
|
||||
merged.lemmy.auth.username = process.env.LEMMY_USERNAME;
|
||||
}
|
||||
if (process.env.LEMMY_PASSWORD) {
|
||||
merged.lemmy.auth.password = process.env.LEMMY_PASSWORD;
|
||||
}
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,8 +92,53 @@ async function resolveMarkdownTargets(inputs, { rootDir = process.cwd(), skipInd
|
||||
return Array.from(targets);
|
||||
}
|
||||
|
||||
async function collectBundles(rootDir) {
|
||||
const bundles = [];
|
||||
await walk(rootDir, rootDir, bundles);
|
||||
bundles.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
||||
return bundles;
|
||||
}
|
||||
|
||||
async function walk(rootDir, currentDir, bucket) {
|
||||
let entries;
|
||||
try {
|
||||
entries = await fs.readdir(currentDir, { withFileTypes: true });
|
||||
} catch (error) {
|
||||
console.warn(`⚠️ Lecture impossible de ${currentDir}: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let hasIndex = false;
|
||||
for (const entry of entries) {
|
||||
if (entry.isFile() && entry.name === "index.md") {
|
||||
hasIndex = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasIndex) {
|
||||
const relative = path.relative(rootDir, currentDir);
|
||||
const parts = relative.split(path.sep).filter(Boolean);
|
||||
const slug = parts[parts.length - 1] || path.basename(currentDir);
|
||||
bucket.push({
|
||||
dir: currentDir,
|
||||
indexPath: path.join(currentDir, "index.md"),
|
||||
relativePath: parts.join("/"),
|
||||
parts,
|
||||
slug,
|
||||
});
|
||||
}
|
||||
|
||||
for (const entry of entries) {
|
||||
if (!entry.isDirectory()) continue;
|
||||
if (entry.name === ".git" || entry.name === "node_modules") continue;
|
||||
await walk(rootDir, path.join(currentDir, entry.name), bucket);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
collectMarkdownFiles,
|
||||
collectSectionIndexDirs,
|
||||
resolveMarkdownTargets,
|
||||
collectBundles,
|
||||
};
|
||||
|
||||
@@ -100,8 +100,48 @@ function formatDateTime(value = null) {
|
||||
return formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit une valeur de frontmatter en DateTime si elle est valide.
|
||||
* @param {import("luxon").DateTime|Date|string|number|null|undefined} value Valeur lue depuis le frontmatter.
|
||||
* @returns {import("luxon").DateTime|null} DateTime utilisable ou null si invalide.
|
||||
*/
|
||||
function parseFrontmatterDate(value) {
|
||||
const zone = getHugoTimeZone();
|
||||
|
||||
if (DateTime.isDateTime(value)) {
|
||||
const zoned = value.setZone(zone);
|
||||
return zoned.isValid ? zoned : null;
|
||||
}
|
||||
|
||||
if (value instanceof Date) {
|
||||
const zoned = DateTime.fromJSDate(value, { zone });
|
||||
return zoned.isValid ? zoned : null;
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
const iso = DateTime.fromISO(trimmed, { setZone: true }).setZone(zone);
|
||||
if (iso.isValid) {
|
||||
return iso;
|
||||
}
|
||||
const rfc2822 = DateTime.fromRFC2822(trimmed, { setZone: true }).setZone(zone);
|
||||
return rfc2822.isValid ? rfc2822 : null;
|
||||
}
|
||||
|
||||
if (typeof value === "number" && Number.isFinite(value)) {
|
||||
const zoned = DateTime.fromMillis(value, { zone }).setZone(zone);
|
||||
return zoned.isValid ? zoned : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
formatDateTime,
|
||||
getHugoTimeZone,
|
||||
toHugoDateTime,
|
||||
parseFrontmatterDate,
|
||||
};
|
||||
|
||||
53
tools/lib/frontmatter.js
Normal file
53
tools/lib/frontmatter.js
Normal file
@@ -0,0 +1,53 @@
|
||||
const fs = require("node:fs");
|
||||
const yaml = require("js-yaml");
|
||||
|
||||
const FRONTMATTER_PATTERN = /^---\n([\s\S]*?)\n---\n?/;
|
||||
|
||||
/**
|
||||
* Lit le frontmatter d'un fichier Markdown et retourne son contenu brut.
|
||||
* La fonction préserve également le corps du fichier afin de permettre
|
||||
* une réécriture propre après modification.
|
||||
* @param {string} filePath Chemin absolu du fichier à analyser.
|
||||
* @returns {{ data: Record<string, any>, body: string, frontmatterText: string, raw: string }|null}
|
||||
*/
|
||||
function readFrontmatterFile(filePath) {
|
||||
const raw = fs.readFileSync(filePath, "utf8");
|
||||
const match = raw.match(FRONTMATTER_PATTERN);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const frontmatterText = match[1];
|
||||
const data = yaml.load(frontmatterText) || {};
|
||||
const body = raw.slice(match[0].length);
|
||||
return {
|
||||
data,
|
||||
body,
|
||||
frontmatterText,
|
||||
raw,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Réécrit complètement le fichier Markdown avec un frontmatter mis à jour.
|
||||
* @param {string} filePath Chemin absolu du fichier.
|
||||
* @param {Record<string, any>} frontmatter Objet contenant les métadonnées.
|
||||
* @param {string} body Corps Markdown déjà prêt à être réinséré.
|
||||
*/
|
||||
function writeFrontmatterFile(filePath, frontmatter, body) {
|
||||
if (
|
||||
typeof frontmatter !== "object" ||
|
||||
frontmatter === null ||
|
||||
Array.isArray(frontmatter)
|
||||
) {
|
||||
throw new Error(`Frontmatter invalide pour ${filePath}`);
|
||||
}
|
||||
const serialized = yaml.dump(frontmatter, { lineWidth: 120, sortKeys: false }).trimEnd();
|
||||
const contentBody = typeof body === "string" ? body : "";
|
||||
const rewritten = `---\n${serialized}\n---\n${contentBody}`;
|
||||
fs.writeFileSync(filePath, rewritten, "utf8");
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
readFrontmatterFile,
|
||||
writeFrontmatterFile,
|
||||
};
|
||||
Reference in New Issue
Block a user