Merge Docusaurus site: all content under docs/, align with gregFramework split layout

- Move markdown and wiki-import tree into docs/; keep app shell at repo root
- Point docusaurus docs path to docs/; edit links to mleem97/gregWiki
- Sync and i18n scripts use gregWiki root and ../.wiki under gregFramework
- Sidebars: workspace layout from root docs ids; plugins under mods/extensions
- Fix redirects, module catalog URLs, release note paths, and wiki-import category keys
- Update repo inventory for split repos; Dockerfile for single-repo context

Made-with: Cursor
This commit is contained in:
Marvin
2026-04-09 23:39:32 +02:00
parent 33636fde00
commit e2839584f4
320 changed files with 38803 additions and 97 deletions

View File

@@ -0,0 +1,36 @@
/**
* One-off helper: strip legacy -en suffixes from markdown links after i18n normalize.
* Run from gregWiki root: node scripts/fix-wiki-import-en-links.mjs
*/
import fs from 'node:fs';
import path from 'node:path';
function walk(dir) {
for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
const p = path.join(dir, ent.name);
if (ent.isDirectory()) walk(p);
else if (ent.name.endsWith('.md')) {
let s = fs.readFileSync(p, 'utf8');
const orig = s;
s = s.replace(/Troubleshooting\/Troubleshooting-en/g, 'Troubleshooting/overview');
s = s.replace(/\.\.\/Troubleshooting\/Troubleshooting-en/g, '../Troubleshooting/overview');
s = s.replace(/\(Troubleshooting-en\)/g, '(overview)');
s = s.replace(/([a-zA-Z0-9/_.-])-en\)/g, '$1)');
if (s !== orig) {
fs.writeFileSync(p, s);
console.log('updated', p);
}
}
}
}
const roots = [
path.resolve(import.meta.dirname, '../docs/wiki-import'),
path.resolve(
import.meta.dirname,
'../i18n/de/docusaurus-plugin-content-docs/current/wiki-import',
),
];
for (const r of roots) {
if (fs.existsSync(r)) walk(r);
}

View File

@@ -0,0 +1,163 @@
/**
* Split legacy wiki-import pairs (Base.md = DE, Base-en.md = EN) into:
* - docs/wiki-import/** → default locale (en), Docusaurus
* - wiki/i18n/de/docusaurus-plugin-content-docs/current/wiki-import/** → Deutsch
*
* German-only pages (no Base-en.md) → DE in i18n/de, EN stub in docs/wiki-import.
*
* Usage (from gregWiki repo root):
* node scripts/normalize-wiki-import-i18n.mjs
* node scripts/normalize-wiki-import-i18n.mjs --dry-run
*/
import {
existsSync,
mkdirSync,
readFileSync,
readdirSync,
rmSync,
statSync,
writeFileSync,
} from 'node:fs';
import { basename, dirname, join, relative, resolve } from 'node:path';
const repoRoot = resolve(import.meta.dirname, '..');
const docsWikiImport = join(repoRoot, 'docs', 'wiki-import');
const deWikiImport = join(
repoRoot,
'i18n',
'de',
'docusaurus-plugin-content-docs',
'current',
'wiki-import',
);
const dryRun = process.argv.includes('--dry-run');
function englishStub(title) {
return `---
title: ${title}
description: English translation pending; use the Deutsch locale for the full legacy page.
---
:::note
This page is available in **German** in the legacy wiki import. Use the language menu (**Deutsch**) for the full text, or contribute an English translation under \`docs/wiki-import\`.
:::
`;
}
function ensureDir(p) {
mkdirSync(p, { recursive: true });
}
function walkMarkdownFiles(root, base = root) {
const out = [];
for (const name of readdirSync(root)) {
const full = join(root, name);
const st = statSync(full);
if (st.isDirectory()) {
out.push(...walkMarkdownFiles(full, base));
} else if (st.isFile() && name.toLowerCase().endsWith('.md')) {
out.push(relative(base, full).replace(/\\/g, '/'));
}
}
return out;
}
function toEnSibling(rel) {
if (!rel.endsWith('.md')) return null;
const d = dirname(rel);
const base = basename(rel, '.md');
return d === '.' ? `${base}-en.md` : `${d}/${base}-en.md`;
}
function main() {
if (!existsSync(docsWikiImport)) {
console.error(`Missing ${docsWikiImport}`);
process.exit(1);
}
const allRel = new Set(walkMarkdownFiles(docsWikiImport));
const pairBases = new Set();
const germanOnly = [];
for (const rel of allRel) {
const file = basename(rel);
if (file.endsWith('-en.md')) continue;
const enRel = toEnSibling(rel);
if (enRel && allRel.has(enRel)) {
pairBases.add(rel);
continue;
}
germanOnly.push(rel);
}
// Paired: Base.md + Base-en.md
for (const relBase of pairBases) {
const enRel = toEnSibling(relBase);
const pathBase = join(docsWikiImport, relBase);
const pathEn = join(docsWikiImport, enRel);
const german = readFileSync(pathBase, 'utf8');
const english = readFileSync(pathEn, 'utf8');
const deTarget = join(deWikiImport, relBase);
const enTarget = join(docsWikiImport, relBase);
if (dryRun) {
console.log(`[pair] ${relBase} + ${enRel} → EN docs + DE i18n`);
continue;
}
ensureDir(dirname(deTarget));
writeFileSync(deTarget, german, 'utf8');
writeFileSync(enTarget, english, 'utf8');
rmSync(pathEn);
console.log(`[pair] ${relBase}`);
}
// English-only sibling (Home-en.md without Home.md) — rare
for (const rel of allRel) {
if (!rel.endsWith('-en.md')) continue;
const baseRel = rel.replace(/-en\.md$/, '.md');
if (pairBases.has(baseRel)) continue;
const pathEn = join(docsWikiImport, rel);
const pathBase = join(docsWikiImport, baseRel);
const english = readFileSync(pathEn, 'utf8');
if (dryRun) {
console.log(`[en-only] ${rel}${baseRel}`);
continue;
}
ensureDir(dirname(pathBase));
writeFileSync(pathBase, english, 'utf8');
rmSync(pathEn);
console.log(`[en-only] ${rel}${baseRel}`);
}
// German-only: no Base-en.md (pair bases are excluded from germanOnly)
for (const rel of germanOnly) {
const pathBase = join(docsWikiImport, rel);
const german = readFileSync(pathBase, 'utf8');
const deTarget = join(deWikiImport, rel);
const titleMatch = german.match(/^title:\s*(.+)$/m);
const title = titleMatch ? titleMatch[1].trim().replace(/"/g, '\\"') : basename(rel, '.md');
if (dryRun) {
console.log(`[de-only] ${rel} → i18n/de + EN stub`);
continue;
}
ensureDir(dirname(deTarget));
writeFileSync(deTarget, german, 'utf8');
writeFileSync(pathBase, englishStub(title), 'utf8');
console.log(`[de-only] ${rel}`);
}
console.log(dryRun ? 'Dry run complete.' : 'Done. Next: npm run build');
}
main();

View File

@@ -0,0 +1,50 @@
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
import { join, resolve } from 'node:path';
const projectRoot = resolve(process.cwd());
const gregFrameworkRoot = resolve(projectRoot, '..');
const wikiDir = join(gregFrameworkRoot, '.wiki');
const outDir = join(projectRoot, 'docs', 'wiki-import');
if (!existsSync(wikiDir)) {
console.error(
`Missing ${wikiDir}. Clone or restore the GitHub Wiki working tree there, then re-run this script.\n` +
'Existing files under docs/wiki-import/ are left unchanged.',
);
process.exit(1);
}
mkdirSync(outDir, { recursive: true });
function collectMarkdownFiles(rootDir, prefix = '') {
const entries = readdirSync(join(rootDir, prefix), { withFileTypes: true });
const results = [];
for (const entry of entries) {
const relativePath = prefix ? join(prefix, entry.name) : entry.name;
if (entry.isDirectory()) {
results.push(...collectMarkdownFiles(rootDir, relativePath));
continue;
}
if (entry.isFile() && entry.name.toLowerCase().endsWith('.md')) {
results.push(relativePath);
}
}
return results;
}
const files = collectMarkdownFiles(wikiDir);
for (const file of files) {
const source = join(wikiDir, file);
const sanitizedRelative = file.replace(/\s+/g, '-');
const target = join(outDir, sanitizedRelative);
const targetDir = resolve(target, '..');
mkdirSync(targetDir, { recursive: true });
const raw = readFileSync(source, 'utf8');
writeFileSync(target, raw, 'utf8');
}
console.log(`Synced ${files.length} wiki files to ${outDir}`);

View File

@@ -0,0 +1,38 @@
/** Idempotent: add unique Docusaurus sidebar keys for wiki-import subfolders. */
import fs from 'node:fs';
import path from 'node:path';
const pairs = [
['Contributors/Guides', 'wiki-import-contributors-guides'],
['Contributors/Reference', 'wiki-import-contributors-reference'],
['Contributors/Troubleshooting', 'wiki-import-contributors-troubleshooting'],
['EndUser/Guides', 'wiki-import-enduser-guides'],
['EndUser/Reference', 'wiki-import-enduser-reference'],
['EndUser/Troubleshooting', 'wiki-import-enduser-troubleshooting'],
['ModDevs/Guides', 'wiki-import-moddevs-guides'],
['ModDevs/Reference', 'wiki-import-moddevs-reference'],
['ModDevs/Troubleshooting', 'wiki-import-moddevs-troubleshooting'],
['TechnicalReference/Guides', 'wiki-import-techref-guides'],
['TechnicalReference/Reference', 'wiki-import-techref-reference'],
['TechnicalReference/Troubleshooting', 'wiki-import-techref-troubleshooting'],
];
const bases = [
path.resolve(import.meta.dirname, '../docs/wiki-import'),
path.resolve(
import.meta.dirname,
'../i18n/de/docusaurus-plugin-content-docs/current/wiki-import',
),
];
for (const base of bases) {
if (!fs.existsSync(base)) continue;
for (const [rel, key] of pairs) {
const dir = path.join(base, rel);
if (!fs.existsSync(dir)) continue;
const target = path.join(dir, '_category_.json');
const body = JSON.stringify({ key }, null, 2) + '\n';
fs.writeFileSync(target, body);
console.log('wrote', target);
}
}