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 ? `` : ``; const tags = deck.tags.map(tag => `
  • ${escapeHtml(tag)}
  • `).join(''); return `
    ${cover}

    ${escapeHtml(deck.date || 'Undated')}${deck.author ? ` · ${escapeHtml(deck.author)}` : ''}

    ${escapeHtml(deck.title)}

    ${deck.description ? `

    ${escapeHtml(deck.description)}

    ` : ''} ${tags ? `` : ''}
    `; }).join('\n'); return ` ${escapeHtml(config.title)}

    MARKDOWN PRESENTATIONS

    ${escapeHtml(config.title)}

    ${escapeHtml(config.description)}

    ${cards || '

    暂无公开演示。

    '}
    `; } function landingStyles() { return `:root{font-family:Inter,"Noto Sans SC","PingFang SC","Microsoft YaHei",sans-serif;color:#222;background:#f6f5f2}*{box-sizing:border-box}body{margin:0}main{width:min(1120px,calc(100% - 40px));margin:auto;padding:72px 0 96px}header{border-bottom:2px solid #1d4ed8;padding-bottom:28px;margin-bottom:36px}.eyebrow{font-size:12px;font-weight:700;letter-spacing:.18em;color:#1d4ed8}h1{font-size:clamp(48px,8vw,82px);line-height:1;margin:14px 0}.lede{font-size:clamp(19px,2.2vw,26px);color:#555;margin:0}.deck-list{display:grid;gap:28px}.deck-card{display:grid;grid-template-columns:minmax(220px,36%) 1fr;background:#fff;border:1px solid #d9d7d2;border-radius:10px;overflow:hidden;box-shadow:0 12px 36px rgba(30,64,175,.08)}.cover{display:block;min-height:230px;background:#eae7e2}.cover img{display:block;width:100%;height:100%;min-height:230px;object-fit:cover}.cover-fallback{height:100%;min-height:230px;display:grid;place-items:center;background:linear-gradient(135deg,#eff6ff,#dbeafe);color:#1d4ed8;font-size:92px;font-weight:700}.deck-copy{padding:32px}.meta{font-size:13px;color:#777;margin:0 0 10px}h2{font-size:clamp(26px,3vw,38px);line-height:1.15;margin:0}h2 a{color:inherit;text-decoration:none}h2 a:hover{color:#1d4ed8}.description{font-size:17px;line-height:1.7;color:#555}.tags{display:flex;gap:8px;flex-wrap:wrap;list-style:none;padding:0;margin:24px 0 0}.tags li{font-size:12px;background:#eff6ff;color:#1d4ed8;padding:5px 9px;border-radius:999px}@media(max-width:680px){main{padding-top:44px}.deck-card{grid-template-columns:1fr}.cover,.cover img,.cover-fallback{min-height:190px}.deck-copy{padding:24px}}`; } function renderHeaders() { return `/*.html\n Cache-Control: public, max-age=0, must-revalidate\n\n/*/assets/*\n Cache-Control: public, max-age=31536000, immutable\n`; } function renderRedirects(decks) { return decks.map(deck => `${joinBase(siteBase, deck.slug)}* ${joinBase(siteBase, deck.slug)}index.html 200`).join('\n'); } function escapeHtml(value) { return value.replace(/[&<>"']/g, character => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[character]); } function escapeAttribute(value) { return escapeHtml(value); } await main().catch((error) => { console.error(error instanceof Error ? error.message : error); process.exitCode = 1; }); //# sourceMappingURL=build.js.map