${escapeHtml(deck.title)}
${deck.description ? `${escapeHtml(deck.description)}
` : ''} ${tags ? `` : ''}import 'dotenv/config';
import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { checkProject, printIssues } from "./check.js";
import { joinBase, normalizeSiteBase } from "./lib/site-base.js";
import { auditBuiltDecks } from "./lib/overflow-audit.js";
import { formatOverflowAuditResult } from "./lib/overflow-report.js";
import { runSlidev } from "./lib/run-slidev.js";
import { resolveTheme } from "./lib/theme.js";
const cwd = process.cwd();
const siteBase = normalizeSiteBase(process.env.SITE_BASE);
let config;
let dist;
async function main() {
const result = await checkProject(cwd);
config = result.config;
dist = path.join(cwd, config.outDir);
const { decks, issues } = result;
printIssues(issues, cwd);
if (issues.some(issue => issue.level === 'error'))
throw new Error('内容检查失败,已停止构建');
const published = decks.filter(deck => !deck.draft);
await rm(dist, { recursive: true, force: true });
await mkdir(dist, { recursive: true });
for (const deck of published)
await buildDeck(deck);
await reportSlideOverflow(published);
await writeFile(path.join(dist, 'index.html'), renderIndex(published), 'utf8');
await writeFile(path.join(dist, '_headers'), renderHeaders(), 'utf8');
await writeFile(path.join(dist, '_redirects'), renderRedirects(published), 'utf8');
console.log(`\n构建完成:${published.length} 套演示 → ${path.relative(cwd, dist)}`);
}
async function buildDeck(deck) {
const output = path.join(dist, deck.slug);
const base = joinBase(siteBase, deck.slug);
console.log(`\nBuilding ${deck.slug} (${base})`);
await runSlidev([
'build',
deck.entry,
'--theme',
resolveTheme(config.theme),
'--out',
output,
'--base',
base,
'--router-mode',
'hash',
]);
const assets = path.join(deck.directory, 'assets');
await cp(assets, path.join(output, 'assets'), { recursive: true, force: true }).catch(() => undefined);
await copySpaEntry(output, 'presenter');
await copySpaEntry(output, 'overview');
await copySpaEntry(output, 'notes-edit');
}
async function copySpaEntry(output, route) {
const html = await readFile(path.join(output, 'index.html'), 'utf8');
const routeBootstrap = ``;
const routedHtml = html.replace('', `${routeBootstrap}`);
const directory = path.join(output, route);
await mkdir(directory, { recursive: true });
await writeFile(path.join(directory, 'index.html'), routedHtml, 'utf8');
}
async function reportSlideOverflow(decks) {
if (!decks.length)
return;
console.log('\n检查编译后的幻灯片内容边界...');
const result = await auditBuiltDecks({ root: dist, decks, siteBase });
formatOverflowAuditResult(result, cwd).forEach(line => console.log(line));
}
function renderIndex(decks) {
const cards = decks.map((deck) => {
const href = joinBase(siteBase, deck.slug);
const cover = deck.cover
? ``
: `
${escapeHtml(deck.description)}
` : ''} ${tags ? `` : ''}MARKDOWN PRESENTATIONS
${escapeHtml(config.description)}
暂无公开演示。
'}