// Transforms tests/README.md into a Docusaurus-ready markdown page and writes // it to tests/.docs-dist/. CI publishes that directory to the // `server-testing-docs` branch, which the docs site (opencloud-eu/docs) pulls // into docs/dev/server/testing via git-batch (.batchfile). // // Run locally with: node tests/scripts/generate-docs.mjs import { mkdir, readFile, rm, writeFile } from 'node:fs/promises' import path from 'node:path' import { fileURLToPath } from 'node:url' const HERE = path.dirname(fileURLToPath(import.meta.url)) const TESTS_DIR = path.resolve(HERE, '..') const REPO_ROOT = path.resolve(TESTS_DIR, '..') const INPUT = path.join(TESTS_DIR, 'README.md') const OUT_DIR = path.join(TESTS_DIR, '.docs-dist') // tests, relative to the repo root, used to resolve README-relative links. const TESTS_REL = path.relative(REPO_ROOT, TESTS_DIR).split(path.sep).join('/') const GH_BLOB = 'https://github.com/opencloud-eu/opencloud/blob/main' const FRONT_MATTER = `--- title: 'Acceptance Testing' sidebar_position: 1 id: acceptance-testing --- ` const CATEGORY = { label: 'Testing', position: 4 } // GitHub alert syntax -> Docusaurus admonitions. const ALERT_TYPES = { NOTE: 'note', TIP: 'tip', IMPORTANT: 'info', WARNING: 'warning', CAUTION: 'danger' } function stripTitleAndToc(md) { // Docusaurus renders the title from front matter, so drop the leading H1. md = md.replace(/^#\s+.*\r?\n+/, '') // Drop the hand-maintained "Table of Contents" section (auto-generated by Docusaurus). md = md.replace(/^##\s+Table of Contents\s*\r?\n[\s\S]*?(?=^##\s)/m, '') return md } function stripHugoShortcodes(md) { // Hugo shortcodes ({{< ref "x" >}}) are not valid in Docusaurus MDX and raw // "{{ }}" would break the build. Keep the link text, drop the broken target. md = md.replace(/\[([^\]]+)\]\(\s*\{\{[<%][\s\S]*?[%>]\}\}\s*\)/g, '$1') // Remove any remaining bare shortcodes. md = md.replace(/\{\{[<%][\s\S]*?[%>]\}\}/g, '') return md } function convertAlerts(md) { const lines = md.split('\n') const out = [] for (let i = 0; i < lines.length; i++) { const match = lines[i].match(/^>\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*$/) if (!match) { out.push(lines[i]) continue } const type = ALERT_TYPES[match[1]] const body = [] while (i + 1 < lines.length && lines[i + 1].startsWith('>')) { i++ body.push(lines[i].replace(/^>\s?/, '')) } out.push(`:::${type}`, ...body, ':::') } return out.join('\n') } function rewriteRelativeLinks(md) { // ](./foo) or ](../foo) -> absolute GitHub blob URL, resolved against tests/. return md.replace(/\]\((\.{1,2}\/[^)]+)\)/g, (_full, rel) => { const repoRelative = path.posix.join(TESTS_REL, rel) return `](${GH_BLOB}/${repoRelative})` }) } async function main() { const readme = await readFile(INPUT, 'utf8') const body = rewriteRelativeLinks( convertAlerts(stripHugoShortcodes(stripTitleAndToc(readme))) ) const page = `${FRONT_MATTER}\n${body.replace(/^\n+/, '')}` if (page.includes('{{')) { console.warn('Warning: unresolved "{{" remains in the output; Docusaurus MDX may fail.') } await rm(OUT_DIR, { recursive: true, force: true }) await mkdir(OUT_DIR, { recursive: true }) await writeFile(path.join(OUT_DIR, 'index.md'), page, 'utf8') await writeFile(path.join(OUT_DIR, '_category_.json'), JSON.stringify(CATEGORY, null, 2) + '\n', 'utf8') console.log(`Wrote ${path.relative(REPO_ROOT, OUT_DIR)}/{index.md,_category_.json}`) } main().catch((err) => { console.error(err) process.exit(1) })