Dimdam's
Dimdam’s Git

dimdams / dimdams-docs

Documentation de Dimdams

Public
00
2 commits
check-content.mjs HistoriqueBlame Télécharger
import fs from "node:fs";
import path from "node:path";

const ROOT = path.resolve(import.meta.dirname, "..");
const CONTENT_DIR = path.join(ROOT, "content");
const ALLOWED_VARS = new Set(["PUBLIC_URL", "MAIN_SITE_URL", "GIT_URL", "STATUS_URL"]);
const SECTIONS = ["hebergement", "api", "git", "status"];

let errors = 0;
let warnings = 0;
let totalPages = 0;

const pagesBySection = new Map();

for (const section of SECTIONS) {
  const dir = path.join(CONTENT_DIR, section);
  if (!fs.existsSync(dir)) {
    console.error(`❌ Dossier manquant : ${section}`);
    errors++;
    continue;
  }
  const files = fs.readdirSync(dir).filter((f) => f.endsWith(".md"));
  const slugs = new Set(files.map((f) => f.replace(/\.md$/, "")));
  pagesBySection.set(section, slugs);

  for (const file of files) {
    totalPages++;
    const fullPath = path.join(dir, file);
    const content = fs.readFileSync(fullPath, "utf8").replace(/\r\n/g, "\n");

    const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n?/);
    if (!fmMatch) {
      console.error(`❌ En-tête manquant : ${section}/${file}`);
      errors++;
      continue;
    }

    const meta = {};
    for (const line of fmMatch[1].split("\n")) {
      const kv = line.match(/^([a-zA-Z]+):\s*(.*)$/);
      if (kv) meta[kv[1]] = kv[2].trim().replace(/^"(.*)"$/, "$1");
    }

    if (!meta.title) {
      console.error(`❌ Titre manquant : ${section}/${file}`);
      errors++;
    }
    if (!meta.description) {
      console.warn(`⚠️ Description manquante : ${section}/${file}`);
      warnings++;
    }

    // Check variable substitutions
    const varMatches = content.matchAll(/\{\{([A-Z_]+)\}\}/g);
    for (const match of varMatches) {
      if (!ALLOWED_VARS.has(match[1])) {
        console.error(`❌ Variable inconnue {{${match[1]}}} dans ${section}/${file}`);
        errors++;
      }
    }
  }
}

// Check internal links
for (const section of SECTIONS) {
  const dir = path.join(CONTENT_DIR, section);
  if (!fs.existsSync(dir)) continue;
  const files = fs.readdirSync(dir).filter((f) => f.endsWith(".md"));

  for (const file of files) {
    const fullPath = path.join(dir, file);
    const content = fs.readFileSync(fullPath, "utf8");

    // Matches [text](/section/slug/) or (/section/)
    const linkMatches = content.matchAll(/\]\((\/[a-z0-9_-]+\/[a-z0-9_#-]*)\)/g);
    for (const match of linkMatches) {
      const rawHref = match[1].split("#")[0]; // remove anchor
      const parts = rawHref.split("/").filter(Boolean);
      if (parts.length >= 1) {
        const targetSection = parts[0];
        const targetSlug = parts[1] || "index";
        const sectionSlugs = pagesBySection.get(targetSection);
        if (!sectionSlugs) {
          console.error(`❌ Lien vers section inconnue : ${rawHref} dans ${section}/${file}`);
          errors++;
        } else if (!sectionSlugs.has(targetSlug)) {
          console.error(`❌ Lien brisé : ${rawHref} dans ${section}/${file} (page ${targetSlug}.md introuvable)`);
          errors++;
        }
      }
    }
  }
}

console.log(`\nVérification terminée : ${totalPages} pages analysées.`);
console.log(`Erreurs : ${errors}, Avertissements : ${warnings}`);

if (errors > 0) {
  process.exit(1);
} else {
  console.log("✅ Contenu valide !");
}