Make the docs renderer name match its purpose, add CMS_DOCS_SITE_PATH with ASTRO_SITE_PATH compatibility, and update docs publishing paths. --- Build: pass | Tests: pass — 2372 passed (704 files)
161 lines
5.6 KiB
JavaScript
161 lines
5.6 KiB
JavaScript
/**
|
|
* Strapi export script — snapshots Strapi content into the repo as committed .md files.
|
|
*
|
|
* Git is the source of record. Strapi is an optional content service.
|
|
* Run this script when Strapi content has changed and you want to snapshot it:
|
|
*
|
|
* npm run export-strapi
|
|
*
|
|
* Then review the diff and commit. The build never requires Strapi to be running —
|
|
* it uses whatever .md files are committed in src/content/docs/.
|
|
*
|
|
* Directories this script fully owns (cleared + rewritten on each run):
|
|
* guides/ ← sl guides (English slug, Slovenian content)
|
|
* en/guides/ ← en guides
|
|
*
|
|
* Strapi-generated pages are tracked in .strapi-manifest.json so stale files
|
|
* are cleaned up across runs. The manifest itself is committed.
|
|
*/
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const DOCS_DIR = path.join(__dirname, '..', 'src', 'content', 'docs');
|
|
const MANIFEST = path.join(DOCS_DIR, '.strapi-manifest.json');
|
|
const TENANT_SITE_DIR = path.join(__dirname, '..', 'src', 'content', 'tenant-sites');
|
|
|
|
const STRAPI_URL = process.env.STRAPI_URL ?? 'http://localhost:1337';
|
|
const TOKEN = process.env.STRAPI_API_TOKEN ?? '';
|
|
|
|
if (!TOKEN) {
|
|
console.error('ERROR: STRAPI_API_TOKEN is not set. Run with --env-file=.env or export the variable.');
|
|
process.exit(1);
|
|
}
|
|
|
|
async function fetchStrapi(endpoint) {
|
|
const res = await fetch(`${STRAPI_URL}/api/${endpoint}`, {
|
|
headers: { Authorization: `Bearer ${TOKEN}` },
|
|
});
|
|
if (!res.ok) throw new Error(`Strapi ${res.status}: ${endpoint}`);
|
|
return res.json();
|
|
}
|
|
|
|
function htmlToMarkdown(html) {
|
|
if (!html) return '';
|
|
return html
|
|
.replace(/<p>(.*?)<\/p>/gs, '$1\n\n')
|
|
.replace(/<strong>(.*?)<\/strong>/g, '**$1**')
|
|
.replace(/<em>(.*?)<\/em>/g, '_$1_')
|
|
.replace(/<code>(.*?)<\/code>/g, '`$1`')
|
|
.replace(/<[^>]+>/g, '')
|
|
.trim();
|
|
}
|
|
|
|
function writeDoc(filePath, frontmatter, body) {
|
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
const fm = Object.entries(frontmatter)
|
|
.filter(([, v]) => v !== null && v !== undefined && v !== '')
|
|
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
|
|
.join('\n');
|
|
fs.writeFileSync(filePath, `---\n${fm}\n---\n\n${body}\n`);
|
|
console.log(' wrote', path.relative(DOCS_DIR, filePath));
|
|
}
|
|
|
|
function writeJson(filePath, value) {
|
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\n');
|
|
console.log(' wrote', path.relative(path.join(__dirname, '..', 'src', 'content'), filePath));
|
|
}
|
|
|
|
// Remove stale page files from previous export
|
|
const prevManifest = fs.existsSync(MANIFEST)
|
|
? JSON.parse(fs.readFileSync(MANIFEST, 'utf8'))
|
|
: { pages: [], tenantSiteSnapshots: [] };
|
|
for (const f of prevManifest.pages ?? []) {
|
|
if (fs.existsSync(f)) {
|
|
fs.rmSync(f);
|
|
console.log(' removed stale', path.relative(DOCS_DIR, f));
|
|
}
|
|
}
|
|
for (const f of prevManifest.tenantSiteSnapshots ?? []) {
|
|
if (fs.existsSync(f)) {
|
|
fs.rmSync(f);
|
|
console.log(' removed stale', path.relative(TENANT_SITE_DIR, f));
|
|
}
|
|
}
|
|
|
|
const manifest = { pages: [], guideDirs: [], tenantSiteSnapshots: [] };
|
|
|
|
async function exportLocale(locale) {
|
|
const prefix = locale === 'sl' ? '' : `${locale}/`;
|
|
const guidesDir = path.join(DOCS_DIR, prefix, 'guides');
|
|
|
|
const [guidesRes, pagesRes] = await Promise.all([
|
|
fetchStrapi(`guides?locale=${locale}&pagination[pageSize]=100&sort=order:asc`),
|
|
fetchStrapi(`pages?locale=${locale}&pagination[pageSize]=100&sort=order:asc`),
|
|
]);
|
|
|
|
// Fully clear + recreate guides directory (this script owns it)
|
|
if (fs.existsSync(guidesDir)) fs.rmSync(guidesDir, { recursive: true });
|
|
fs.mkdirSync(guidesDir, { recursive: true });
|
|
manifest.guideDirs.push(guidesDir);
|
|
|
|
console.log(`\n[${locale}] guides:`);
|
|
for (const guide of guidesRes.data ?? []) {
|
|
writeDoc(
|
|
path.join(guidesDir, `${guide.slug}.md`),
|
|
{ title: guide.title, description: guide.summary ?? '' },
|
|
htmlToMarkdown(guide.content)
|
|
);
|
|
}
|
|
|
|
console.log(`[${locale}] pages:`);
|
|
for (const page of pagesRes.data ?? []) {
|
|
// Skip homepage — handled by committed index.md
|
|
if (page.slug === 'home') continue;
|
|
const filePath = path.join(DOCS_DIR, prefix, `${page.slug}.gen.md`);
|
|
writeDoc(filePath, { title: page.title, description: page.summary ?? '' }, htmlToMarkdown(page.content));
|
|
manifest.pages.push(filePath);
|
|
}
|
|
}
|
|
|
|
async function exportTenantSites() {
|
|
const tenantSitePagesRes = await fetchStrapi(
|
|
'tenant-site-pages?pagination[pageSize]=200&sort=tenant_id:asc&sort=site_id:asc&sort=locale:asc&sort=order:asc'
|
|
);
|
|
const grouped = new Map();
|
|
|
|
for (const page of tenantSitePagesRes.data ?? []) {
|
|
const key = `${page.tenant_id}/${page.site_id}`;
|
|
const bucket = grouped.get(key) || {
|
|
tenantId: page.tenant_id,
|
|
siteId: page.site_id,
|
|
title: page.title,
|
|
pages: [],
|
|
};
|
|
bucket.pages.push({
|
|
slug: page.slug,
|
|
locale: page.locale,
|
|
title: page.title,
|
|
summary: page.summary ?? '',
|
|
content: htmlToMarkdown(page.content),
|
|
order: page.order ?? 0,
|
|
});
|
|
grouped.set(key, bucket);
|
|
}
|
|
|
|
console.log('\n[tenant-sites] pages:');
|
|
for (const snapshot of grouped.values()) {
|
|
const filePath = path.join(TENANT_SITE_DIR, snapshot.tenantId, `${snapshot.siteId}.json`);
|
|
writeJson(filePath, snapshot);
|
|
manifest.tenantSiteSnapshots.push(filePath);
|
|
}
|
|
}
|
|
|
|
await exportLocale('sl');
|
|
await exportLocale('en');
|
|
await exportTenantSites();
|
|
|
|
fs.writeFileSync(MANIFEST, JSON.stringify(manifest, null, 2));
|
|
console.log('\nStrapi export complete. Review the diff and commit if the content looks right.');
|