const path = require("path"); const { DateTime } = require("luxon"); const { collectMarkdownFiles, collectSectionIndexDirs } = require("../content"); const { readFrontmatter } = require("../weather/frontmatter"); function parseDate(value) { if (!value) return null; if (value instanceof Date) { return DateTime.fromJSDate(value); } if (typeof value === "string") { let parsed = DateTime.fromISO(value); if (!parsed.isValid) { parsed = DateTime.fromRFC2822(value); } return parsed.isValid ? parsed : null; } return null; } function countWords(body) { if (!body) return 0; const cleaned = body .replace(/```[\s\S]*?```/g, " ") // fenced code blocks .replace(/`[^`]*`/g, " ") // inline code .replace(/<[^>]+>/g, " "); // html tags const words = cleaned.match(/[\p{L}\p{N}'-]+/gu); return words ? words.length : 0; } async function loadArticles(contentDir) { const files = await collectMarkdownFiles(contentDir); const sectionDirs = await collectSectionIndexDirs(contentDir); const rootDir = path.resolve(contentDir); const articles = []; function resolveSection(filePath) { const absolute = path.resolve(filePath); let current = path.dirname(absolute); while (current.startsWith(rootDir)) { if (sectionDirs.has(current)) { return path.relative(rootDir, current).replace(/\\/g, "/") || "."; } const parent = path.dirname(current); if (parent === current) break; current = parent; } return null; } for (const file of files) { const frontmatter = await readFrontmatter(file); if (!frontmatter) continue; const date = parseDate(frontmatter.doc.get("date")); const title = frontmatter.doc.get("title") || path.basename(file, ".md"); const body = frontmatter.body.trim(); const wordCount = countWords(body); const relativePath = path.relative(contentDir, file); const section = resolveSection(file); articles.push({ path: file, relativePath, title, date, body, wordCount, section, frontmatter: frontmatter.doc.toJS ? frontmatter.doc.toJS() : frontmatter.doc.toJSON(), }); } return articles; } module.exports = { collectMarkdownFiles, countWords, loadArticles, parseDate, };