Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
123 lines
4.1 KiB
JavaScript
123 lines
4.1 KiB
JavaScript
#!/usr/bin/env node
|
|
// Generate the Developers sidebar from the migrated content tree under
|
|
// develop/. Output: docs-site/sidebars/developers.generated.json
|
|
//
|
|
// Usage: node docs-site/scripts/gen-developer-sidebar.mjs
|
|
|
|
import {readFileSync, writeFileSync, readdirSync, statSync, existsSync} from 'node:fs';
|
|
import {join, resolve, basename, dirname} from 'node:path';
|
|
import {fileURLToPath} from 'node:url';
|
|
|
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
const SITE_ROOT = resolve(HERE, '..');
|
|
const REPO_ROOT = resolve(SITE_ROOT, '..');
|
|
const SRC = join(REPO_ROOT, 'develop');
|
|
const OUT = join(SITE_ROOT, 'sidebars', 'developers.generated.json');
|
|
|
|
const TOP_LEVEL = [
|
|
{dir: 'contribute', label: 'Contribute'},
|
|
{dir: 'integrate', label: 'Integrate & Extend'},
|
|
{dir: 'internal', label: 'Internal'},
|
|
];
|
|
|
|
function humanize(name) {
|
|
return name.replace(/[-_]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
|
|
}
|
|
|
|
function readFm(filePath, key) {
|
|
try {
|
|
const text = readFileSync(filePath, 'utf8').slice(0, 2000);
|
|
const m = text.match(/^---\n([\s\S]*?)\n---/);
|
|
if (!m) return null;
|
|
const r = new RegExp(`^${key}:\\s*"?([^"\\n]+)"?`, 'm');
|
|
const x = m[1].match(r);
|
|
return x ? x[1].trim().replace(/^"|"$/g, '') : null;
|
|
} catch { return null; }
|
|
}
|
|
|
|
function pathToDocId(relPath) { return relPath.replace(/\.(md|mdx)$/, ''); }
|
|
|
|
function buildCategory(absDir, devRelDir) {
|
|
const items = [];
|
|
const entries = readdirSync(absDir);
|
|
const indexFile = entries.find((e) => /^index\.(md|mdx)$/.test(e));
|
|
let categoryLink = null;
|
|
if (indexFile) {
|
|
categoryLink = {type: 'doc', id: pathToDocId(join(devRelDir, indexFile))};
|
|
}
|
|
|
|
const subDirs = [];
|
|
const leafDocs = [];
|
|
for (const name of entries) {
|
|
if (/^index\.(md|mdx)$/.test(name)) continue;
|
|
const abs = join(absDir, name);
|
|
const st = statSync(abs);
|
|
if (st.isDirectory()) subDirs.push(name);
|
|
else if (st.isFile() && /\.(md|mdx)$/.test(name)) leafDocs.push(name);
|
|
}
|
|
|
|
function key(name, abs) {
|
|
const p = readFm(abs, 'sidebar_position');
|
|
return [p ? Number(p) : 9999, name.toLowerCase()];
|
|
}
|
|
leafDocs.sort((a, b) => {
|
|
const ka = key(a, join(absDir, a));
|
|
const kb = key(b, join(absDir, b));
|
|
return ka[0] - kb[0] || ka[1].localeCompare(kb[1]);
|
|
});
|
|
subDirs.sort((a, b) => {
|
|
const ka = key(a, join(absDir, a, 'index.md'));
|
|
const kb = key(b, join(absDir, b, 'index.md'));
|
|
return ka[0] - kb[0] || ka[1].localeCompare(kb[1]);
|
|
});
|
|
|
|
for (const name of leafDocs) {
|
|
const id = pathToDocId(join(devRelDir, name));
|
|
const label = readFm(join(absDir, name), 'title') || humanize(basename(name, /\.(md|mdx)$/.exec(name)[0]));
|
|
items.push({type: 'doc', id, label});
|
|
}
|
|
for (const name of subDirs) {
|
|
const sub = buildCategory(join(absDir, name), join(devRelDir, name));
|
|
// Skip empty subcategories — Docusaurus refuses sidebar categories that
|
|
// have neither a link nor any items.
|
|
if (sub) items.push(sub);
|
|
}
|
|
|
|
const label =
|
|
readFm(join(absDir, 'index.md'), 'title') ||
|
|
readFm(join(absDir, 'index.mdx'), 'title') ||
|
|
humanize(basename(absDir));
|
|
|
|
if (!categoryLink && items.length === 0) return null;
|
|
|
|
return {type: 'category', label, collapsed: true, ...(categoryLink ? {link: categoryLink} : {}), items};
|
|
}
|
|
|
|
function main() {
|
|
if (!existsSync(SRC)) { console.error(`develop/ not found at ${SRC}`); process.exit(1); }
|
|
|
|
const sidebar = [{type: 'doc', id: 'index', label: 'Welcome'}];
|
|
for (const {dir, label} of TOP_LEVEL) {
|
|
const abs = join(SRC, dir);
|
|
if (!existsSync(abs)) { console.warn(`[sidebar] skip ${dir}: missing`); continue; }
|
|
const cat = buildCategory(abs, dir);
|
|
cat.label = label;
|
|
cat.collapsed = true;
|
|
sidebar.push(cat);
|
|
}
|
|
writeFileSync(OUT, JSON.stringify(sidebar, null, 2));
|
|
|
|
let cats = 0, docs = 0;
|
|
(function walk(n) {
|
|
if (Array.isArray(n)) n.forEach(walk);
|
|
else if (n && typeof n === 'object') {
|
|
if (n.type === 'category') cats++;
|
|
if (n.type === 'doc') docs++;
|
|
if (n.items) walk(n.items);
|
|
}
|
|
})(sidebar);
|
|
console.log(`[sidebar] wrote ${OUT}: ${cats} categories, ${docs} docs`);
|
|
}
|
|
|
|
main();
|