← Files Ship24 Tracking APIARCHIVED FILE

scripts/lib/markdown.mjs

1.75 KB · Oct 2, 2026 · 00:34 UTC

↓ Download file

import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { dirname } from 'node:path';

function escapeCell(value) {
  return String(value ?? '')
    .replace(/\|/g, '\\|')
    .replace(/\r\n/g, ' ')
    .replace(/\n/g, '<br>');
}

export function table(headers, rows) {
  const headerLine = `| ${headers.map(escapeCell).join(' | ')} |`;
  const separatorLine = `| ${headers.map(() => '---').join(' | ')} |`;
  const bodyLines = rows.map((row) => `| ${row.map(escapeCell).join(' | ')} |`);
  return `${[headerLine, separatorLine, ...bodyLines].join('\n')}\n`;
}

export function banner({ sources }) {
  const sourceList = sources.join(', ');
  return `<!-- GENERATED by scripts/generate-references.mjs from ${sourceList}. Do not edit; run pnpm generate. -->`;
}

export function codeBlock(lang, text) {
  const body = text.endsWith('\n') ? text.slice(0, -1) : text;
  return `\`\`\`${lang}\n${body}\n\`\`\`\n`;
}

function normalizeContent(content) {
  const unixContent = content.replace(/\r\n/g, '\n');
  return `${unixContent.replace(/\n+$/, '')}\n`;
}

export async function writeOutputs(outputs, { check = false } = {}) {
  let allUpToDate = true;

  for (const [path, rawContent] of outputs) {
    const content = normalizeContent(rawContent);
    let existing = null;
    try {
      existing = await readFile(path, 'utf8');
    } catch {
      existing = null;
    }

    if (existing === content) {
      console.log(`unchanged ${path}`);
      continue;
    }

    if (check) {
      allUpToDate = false;
      console.log(existing === null ? `missing ${path}` : `stale ${path}`);
      continue;
    }

    await mkdir(dirname(path), { recursive: true });
    await writeFile(path, content, 'utf8');
    console.log(`wrote ${path}`);
  }

  return allUpToDate;
}

SHA-256: feb18d841b09f950857a4c0c81f1825375ec3baad3ca7a21f53bb35a09958347