源码索引 / CURRENT IMPLEMENTATION
site/scripts/verify.mjs
41 行 · 点击行号可定位;函数链接随声明位置更新,不手填行号。
/* Public view: redacted lines; not a complete executable copy. */ import fs from 'node:fs';
import path from 'node:path';
function files(dir) { return fs.readdirSync(dir,{withFileTypes:true}).flatMap(e=>e.isDirectory()?files(path.join(dir,e.name)):[path.join(dir,e.name)]); }
const all=files('dist');
const html=all.filter(f=>f.endsWith('.html'));
/* [REDACTED: private operational rule] */
for(const f of all){
if(/\.(wasm|log|jsonl|map|env|md)$/.test(f))throw new Error(`Unexpected published file: ${f}`);
const text=fs.readFileSync(f,'utf8');
for(const re of denied)if(re.test(text))throw new Error(`Private detail: ${f} (${re})`);
}
if(all.some(f=>/sitemap/i.test(f)))throw new Error('Do not publish a sitemap');
for(const f of html){
const text=fs.readFileSync(f,'utf8');
if(!/<meta\s+name="robots"\s+content="noindex, nofollow, noarchive, nosnippet"/.test(text))throw new Error(`Missing noindex: ${f}`);
for(const [,link] of text.matchAll(/href="([^"\s]+)"/g)){
if(!link.startsWith('/')&&!link.startsWith('#'))continue;
const [url,hash]=link.split('#');
const target=url ? path.join('dist',url.replace(/^\//,''),url.endsWith('/')?'index.html':'') : f;
if(!fs.existsSync(target))throw new Error(`Broken local link: ${f} -> ${link}`);
if(hash&&target.endsWith('.html')){
const body=fs.readFileSync(target,'utf8');
if(!body.includes(`id="${decodeURIComponent(hash)}"`))throw new Error(`Missing fragment: ${f} -> ${link}`);
}
}
}
const headers=fs.readFileSync('dist/_headers','utf8');
if(!headers.startsWith('/*\n')||!headers.includes('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet'))throw new Error('Missing global X-Robots-Tag');
const robots=fs.readFileSync('dist/robots.txt','utf8');
if(!robots.includes('User-agent: *\nAllow: /')||/^Disallow:\s*\//m.test(robots))throw new Error('Crawlers must be able to see noindex');
const sources=JSON.parse(fs.readFileSync('.generated/sources.json','utf8'));
const entity=(_match,name)=>({amp:'&',lt:'<',gt:'>',quot:'"',apos:"'"}[name] ?? String.fromCodePoint(parseInt(name.replace(/^#x?/i,''),name.startsWith('#x')?16:10)));
for(const source of sources){
const body=fs.readFileSync(`dist/code/${source.id}/index.html`,'utf8');
const code=source.code.replace(/\n$/,'');
for(let line=1;line<=code.split('\n').length;line++) if(!body.includes(`id="L${line}"`))throw new Error(`Missing line ${source.name}:${line}`);
for(const symbol of source.symbols) if(!body.includes(`id="${symbol.id}"`))throw new Error(`Missing symbol ${source.name}:${symbol.label}`);
const rendered=body.match(/<code[^>]*>([\s\S]*?)<\/code>/)?.[1].replace(/<[^>]*>/g,'').replace(/&(amp|lt|gt|quot|apos|#x[0-9a-f]+|#[0-9]+);/gi,entity);
if(rendered!==code)throw new Error(`Source text altered by navigation markup: ${source.name}`);
}
console.log(`Verified ${html.length} HTML pages: noindex, internal links/fragments, privacy allowlist; ${all.length} static files.`);