126 lines
4.0 KiB
JavaScript
126 lines
4.0 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const fs = require("fs/promises");
|
|
const path = require("path");
|
|
const {
|
|
extractRawDate,
|
|
readFrontmatter,
|
|
writeFrontmatter,
|
|
} = require("./lib/weather/frontmatter");
|
|
const { parseFrontmatterDate, formatDateTime, getHugoTimeZone } = require("./lib/datetime");
|
|
|
|
const CONTENT_ROOT = path.join(process.cwd(), "content");
|
|
|
|
/**
|
|
* Liste récursivement tous les fichiers Markdown d'un dossier.
|
|
* @param {string} root Dossier racine à parcourir.
|
|
* @returns {Promise<string[]>} Chemins absolus des fichiers trouvés.
|
|
*/
|
|
async function listMarkdownFiles(root) {
|
|
const entries = await fs.readdir(root, { withFileTypes: true });
|
|
const results = [];
|
|
|
|
for (const entry of entries) {
|
|
const fullPath = path.join(root, entry.name);
|
|
if (entry.isDirectory()) {
|
|
const nested = await listMarkdownFiles(fullPath);
|
|
results.push(...nested);
|
|
continue;
|
|
}
|
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
results.push(fullPath);
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
/**
|
|
* Harmonise la date d'un fichier Markdown si nécessaire.
|
|
* @param {string} filePath Chemin absolu du fichier.
|
|
* @returns {Promise<"updated"|"unchanged"|"skipped"|"invalid">} Statut de traitement.
|
|
*/
|
|
async function normalizeFileDate(filePath) {
|
|
const frontmatter = await readFrontmatter(filePath);
|
|
if (!frontmatter) {
|
|
return "skipped";
|
|
}
|
|
|
|
const rawDate = extractRawDate(frontmatter.frontmatterText);
|
|
const dateValue = frontmatter.doc.get("date");
|
|
|
|
if (!rawDate && (dateValue === undefined || dateValue === null)) {
|
|
return "skipped";
|
|
}
|
|
|
|
const sourceValue = rawDate !== null ? rawDate : dateValue;
|
|
const parsed = parseFrontmatterDate(sourceValue);
|
|
if (!parsed) {
|
|
return "invalid";
|
|
}
|
|
|
|
let hasTime = false;
|
|
if (typeof rawDate === "string") {
|
|
const timeMatch = rawDate.match(/[T ](\d{2}):(\d{2})(?::(\d{2}))?/);
|
|
if (timeMatch) {
|
|
const hour = Number(timeMatch[1]);
|
|
const minute = Number(timeMatch[2]);
|
|
const second = Number(timeMatch[3] || "0");
|
|
hasTime = !(hour === 0 && minute === 0 && second === 0);
|
|
}
|
|
}
|
|
const normalized = hasTime
|
|
? parsed.set({ millisecond: 0 })
|
|
: parsed.set({ hour: 12, minute: 0, second: 0, millisecond: 0 });
|
|
const formatted = formatDateTime(normalized);
|
|
const current = typeof dateValue === "string" ? dateValue.trim() : rawDate;
|
|
const quotedFormatted = `"${formatted}"`;
|
|
const currentComparable = typeof current === "string" ? current.trim() : "";
|
|
|
|
if (currentComparable === formatted || currentComparable === quotedFormatted) {
|
|
return "unchanged";
|
|
}
|
|
|
|
frontmatter.doc.set("date", formatted);
|
|
await writeFrontmatter(filePath, frontmatter.doc, frontmatter.body);
|
|
const rewritten = await fs.readFile(filePath, "utf8");
|
|
const normalizedContent = rewritten.replace(/^date:\s*.+$/m, `date: ${quotedFormatted}`);
|
|
if (rewritten !== normalizedContent) {
|
|
await fs.writeFile(filePath, normalizedContent, "utf8");
|
|
}
|
|
return "updated";
|
|
}
|
|
|
|
/**
|
|
* Point d'entrée du script.
|
|
*/
|
|
async function main() {
|
|
const timezone = getHugoTimeZone();
|
|
console.log(`Fuseau horaire Hugo : ${timezone}`);
|
|
|
|
const files = await listMarkdownFiles(CONTENT_ROOT);
|
|
let updated = 0;
|
|
let unchanged = 0;
|
|
let skipped = 0;
|
|
let invalid = 0;
|
|
|
|
for (const file of files) {
|
|
const status = await normalizeFileDate(file);
|
|
if (status === "updated") updated += 1;
|
|
else if (status === "unchanged") unchanged += 1;
|
|
else if (status === "invalid") {
|
|
invalid += 1;
|
|
const relative = path.relative(process.cwd(), file);
|
|
console.warn(`Date invalide : ${relative}`);
|
|
} else {
|
|
skipped += 1;
|
|
}
|
|
}
|
|
|
|
console.log(
|
|
`Terminé. ${updated} mis à jour, ${unchanged} inchangés, ${skipped} ignorés, ${invalid} invalides.`
|
|
);
|
|
}
|
|
|
|
main();
|