Files
UI/apps/demo/build.mjs
T
2026-10-23 16:52:28 +08:00

85 lines
4.0 KiB
JavaScript

/**
* 演示站打包:esbuild 从 TS 源码打包(alias 直连各包 src),
* 连同 tokens.css / ui.css 内嵌进单文件 apps/demo/dist/demo.html。
*/
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { createRequire } from 'node:module';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const root = path.resolve(__dirname, '..', '..'); // apps/demo 上两级 = 仓库根
// esbuild 装在托管 node workspace,用 createRequire 指过去
const require = createRequire('C:/Users/shawn/.workbuddy/binaries/node/workspace/index.js');
const esbuild = require('esbuild');
const read = (p) => fs.readFileSync(path.join(root, p), 'utf8');
const result = await esbuild.build({
entryPoints: [path.join(root, 'apps/demo/main.ts')],
bundle: true,
format: 'iife',
target: 'es2020',
charset: 'utf8', // 中文保留原文,不转义为 \uXXXX
write: false,
legalComments: 'none',
alias: {
'@ui-arch/frame': path.join(root, 'packages/core/frame/src/index.ts'),
'@ui-arch/ui': path.join(root, 'packages/skin/ui/src/index.ts'),
'@ui-arch/table-core': path.join(root, 'packages/core/table-core/src/index.ts'),
},
});
const js = result.outputFiles[0].text.replace(/<\/script>/gi, '<\\/script>'); // 防提前闭合
const css = [read('packages/design/tokens/tokens.css'), read('packages/skin/ui/ui.css')].join('\n');
const html = `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@ui-arch 组件库 · 现场演示</title>
<style>
${css}
:root{--page-bg:#ffffff;--page-text:#1c1e21;--page-muted:#6b7280;--page-border:rgba(0,0,0,.14)}
@media (prefers-color-scheme:dark){:root{--page-bg:#101216;--page-text:#e7e9ec;--page-muted:#888780;--page-border:rgba(255,255,255,.15)}}
*{box-sizing:border-box}
body{margin:0;background:var(--page-bg);color:var(--page-text);font:14px/1.7 -apple-system,"Segoe UI","Microsoft YaHei",sans-serif}
.shell{max-width:1160px;margin:0 auto;padding:36px 20px 80px;display:grid;grid-template-columns:190px minmax(0,1fr);gap:36px}
.page{max-width:900px;margin:0;padding:0}
.toc{position:sticky;top:24px;align-self:start;max-height:calc(100vh - 48px);overflow:auto;font-size:13px}
.toc-title{color:var(--page-muted);font-size:11px;letter-spacing:.08em;margin-bottom:8px}
.toc-link{display:block;padding:3px 8px;border-left:2px solid transparent;border-radius:0 4px 4px 0;color:var(--page-muted);text-decoration:none;transition:color .15s,background .15s,border-color .15s}
.toc-link:hover{color:var(--page-text);background:rgba(127,127,127,.08)}
.toc-link.is-active{color:var(--ua-color-accent);border-left-color:var(--ua-color-accent);background:color-mix(in srgb,var(--ua-color-accent) 10%,transparent)}
@media (max-width:820px){.shell{grid-template-columns:1fr;gap:0}.toc{display:none}}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
header{margin-bottom:30px}
h1{font-size:20px;font-weight:500;margin:0}
.sub{color:var(--page-muted);font-size:13px;margin:8px 0 0}
.sec{margin-bottom:40px}
h2{font-size:16px;font-weight:500;margin:0 0 4px}
.desc{color:var(--page-muted);font-size:13px;margin:0 0 14px}
.stage{display:flex;flex-wrap:wrap;gap:12px;align-items:center;border:1px dashed var(--page-border);border-radius:12px;padding:18px 20px}
.row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.stage .ua-table,.stage .ua-card{width:100%}
.out{color:var(--ua-color-accent,#185fa5);font-size:13px}
footer{color:var(--page-muted);font-size:12px;text-align:center;margin-top:50px}
</style>
</head>
<body>
<div id="app"></div>
<footer>由 @ui-arch/frame + @ui-arch/ui 驱动 · 构建产物单文件,无运行时依赖</footer>
<script>
${js}
</script>
</body>
</html>
`;
const outDir = path.join(root, 'apps/demo/dist');
fs.mkdirSync(outDir, { recursive: true });
fs.writeFileSync(path.join(outDir, 'demo.html'), html);
console.log(`demo built -> apps/demo/dist/demo.html (${Math.round(html.length / 1024)} KB)`);