Files
probably-rendering-one-more…/apps/wiki/scripts/build-reference-layout-demos.ts
T
codex-bot a8515e575a
wiki CI and deployment / verify-and-deploy (push) Successful in 16m40s
Replace approximate recipes with 27 source-matched component layouts
2026-10-26 16:02:03 +08:00

23 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {readFile,writeFile,mkdir} from 'node:fs/promises';
import path from 'node:path';
import layouts from '../src/content/layouts/reference/manifest.json';
const root=path.resolve(import.meta.dirname,'..'),target=path.join(root,'public/layout-reference');
const esc=(s:string)=>s.replaceAll('&','&amp;').replaceAll('<','&lt;').replaceAll('"','&quot;');
async function main(){
await writeFile(path.join(target,'manifest.json'),JSON.stringify(layouts,null,2)+'\n');
const runtime=await readFile(path.join(root,'src/content/layouts/reference/ReferenceLayout.tsx'),'utf8');await writeFile(path.join(target,'ReferenceLayout.tsx'),runtime);
for(const l of layouts){
const layers=l.elements.map(e=>{const[x,y,w,h]=e.box;return `<img data-component="${l.id}/${e.id}" data-kind="${e.kind}" src="${e.asset}" alt="${esc(e.kind==='text'?e.text||e.role+'(未辨识原字形)':'')}" style="left:${x/l.width*100}%;top:${y/l.height*100}%;width:${w/l.width*100}%;height:${h/l.height*100}%">`}).join('\n');
const html=`<!doctype html>\n<html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${l.id} · ${l.name}</title><style>body{margin:0;padding:20px;background:#e8e8e3;color:#222;font:15px/1.7 system-ui}main{display:grid;grid-template-columns:minmax(280px,560px) minmax(280px,1fr);gap:24px;max-width:1250px;margin:auto}.canvas{position:relative;isolation:isolate;aspect-ratio:${l.width}/${l.height};background:#f4f3ee}.canvas img{position:absolute;display:block}.canvas .base{inset:0;width:100%;height:100%}.overlay{position:absolute;z-index:10;pointer-events:none;inset:0;width:100%;height:100%;display:none}label{display:inline-flex;gap:5px;margin-right:16px}button,a{color:#244f9d}table{width:100%;border-collapse:collapse}td,th{padding:7px;border-bottom:1px solid #bbb;text-align:left;font-size:13px}.muted{color:#666}#detail{padding:12px;background:#fff}tr{cursor:pointer}tr:focus,tr:hover{background:#fff}fieldset{border:1px solid #aaa;margin:0 0 16px}.canvas img[data-kind="text"]{z-index:3}.canvas img[data-kind="decoration"]{z-index:2}.canvas img[data-kind="image"]{z-index:1}@media(max-width:800px){main{display:block}.canvas{max-width:560px;margin:auto}aside{margin-top:24px}}</style></head><body><main><section><h1>${l.id} / ${l.name}</h1><div class="canvas" aria-label="按独立图层重建的原版面"><img class="base" src="${l.background}" alt="原图纸底与画框">\n${layers}\n<img class="overlay" src="${l.annotated}" alt="构件标注"></div><p class="muted">原图第 ${l.source.row} 行、第 ${l.source.column} 列;${l.width}×${l.height} 像素。显示为原始构件重组,无新生成图形。放大不增加细节。</p></section><aside><fieldset><legend>按类型检查</legend><label><input type="checkbox" data-toggle="text" checked>文字 T</label><label><input type="checkbox" data-toggle="image" checked>图片/色块 I</label><label><input type="checkbox" data-toggle="decoration" checked>装饰 D</label><label><input id="labels" type="checkbox">显示边界</label></fieldset><p id="detail">点击表格查看对应构件。蓝色 T 为文字、橙色 I 为图片占位/色块、绿色 D 为装饰;原图没有真实照片。</p><table><thead><tr><th>ID</th><th>分类与用途</th><th>文字内容</th></tr></thead><tbody>${l.elements.map(e=>`<tr tabindex="0" data-key="${e.id}"><td>${e.id}</td><td>${e.kind==='text'?'文字':e.kind==='image'?'图片占位/色块':'装饰'} / ${esc(e.role)}</td><td>${esc(e.kind==='text'?e.text??'待核对,保留原字形':'—')}</td></tr>`).join('')}</tbody></table><p><a href="/layout-reference/${l.id}/manifest.json">构件 JSON</a> · <a href="${l.reference}">原裁片</a> · <a href="${l.annotated}">标注图</a> · <a href="/layout-reference/index.html">27 张索引</a></p><p class="muted">修改文字会产生字体差异;替换图片会改变视觉内容。严格原图对应模式保持原字形与原颜色。构件坐标、方向与所属版面固定。</p></aside></main><script>
const manifest=${JSON.stringify(l).replaceAll('<','\\u003c')};
for(const input of document.querySelectorAll('[data-toggle]'))input.addEventListener('change',()=>{for(const el of document.querySelectorAll('[data-kind="'+input.dataset.toggle+'"]'))el.style.visibility=input.checked?'visible':'hidden'});
document.getElementById('labels').addEventListener('change',event=>{document.querySelector('.overlay').style.display=event.target.checked?'block':'none'});
for(const row of document.querySelectorAll('[data-key]')){const select=()=>{const e=manifest.elements.find(e=>e.id===row.dataset.key);for(const el of document.querySelectorAll('[data-component]'))el.style.outline=el.dataset.component.endsWith('/'+e.id)?'2px solid #ed4433':'';document.getElementById('detail').textContent=manifest.id+'/'+e.id+' · '+e.kind+' · '+e.role+' · bbox ['+e.box.join(', ')+']'+(e.kind==='text'?' · '+(e.text||'内容未辨识,保留原字形'):'')};row.addEventListener('click',select);row.addEventListener('keydown',event=>{if(event.key==='Enter'||event.key===' '){event.preventDefault();select()}})}
</script></body></html>\n`;
await writeFile(path.join(target,l.id,'index.html'),html);
}
await writeFile(path.join(target,'index.html'),`<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>27 张原图版面索引</title><style>body{font:16px/1.6 system-ui;background:#eee;padding:24px}nav{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:18px}a{color:#222;text-decoration:none;background:#fff;padding:12px}img{width:100%;aspect-ratio:113/173;object-fit:contain}small{display:block}</style><h1>27 张原图版面 · 一一对应</h1><p>按原图从上到下、每行从左到右编号,排除左侧说明栏。点击每张可分开检查文字、图片占位/色块与装饰。</p><p><a href="/layout-reference/numbered-source.png">查看编号原图</a> · <a href="/layout-reference/index.json">机器索引</a></p><nav>${layouts.map(l=>`<a href="/layout-reference/${l.id}/index.html"><img src="${l.reference}" alt="${l.id} 原裁片"><b>${l.id}</b><small>${esc(l.name)}</small><small>原图 ${l.source.row} 行 ${l.source.column} 列</small></a>`).join('')}</nav></html>\n`);
console.log('Built 27 layer inspectors and the source ID index.');
}
main().catch(e=>{console.error(e);process.exitCode=1});