Files
shanhe-puzzle/scripts/build.mjs
T
codex-bot 4845826deb
Shanhe source and offline package checks / verify (pull_request) Failing after 5s
feat: sync Shanhe 2.2 source and add remote package verification
2026-11-01 17:13:46 +08:00

27 lines
3.3 KiB
JavaScript

import fs from 'node:fs';
import path from 'node:path';
import vm from 'node:vm';
import packCountyMaps from './pack-county-maps.cjs';
import {transform,build} from 'esbuild';
import {execFileSync} from 'node:child_process';
fs.rmSync('dist',{force:true,recursive:true});fs.mkdirSync('dist/vendor',{recursive:true});
for(const name of ['index.html','style.css','maps.js'])fs.copyFileSync('src/'+name,'dist/'+name);
for(const name of ['core.js','atlas.js','game.js','result.js','app.js']){const result=await transform(fs.readFileSync('src/'+name,'utf8'),{target:['chrome61'],minify:true,legalComments:'inline'});fs.writeFileSync('dist/'+name,result.code);}
await build({entryPoints:['src/video.js'],outfile:'dist/video.js',bundle:true,format:'iife',target:['es2017','chrome61'],minify:true,legalComments:'inline'});
const countyContext={window:{}};vm.runInNewContext(fs.readFileSync('src/county-index.js','utf8'),countyContext);
const countyPackage=packCountyMaps(countyContext.window.COUNTY_INDEX,id=>fs.readFileSync('src/county/'+id+'.js','utf8'));
fs.writeFileSync('dist/county-index.js','window.COUNTY_INDEX='+JSON.stringify(countyPackage.index)+';\n');
fs.mkdirSync('dist/county',{recursive:true});for(const [file,text] of countyPackage.files)fs.writeFileSync('dist/'+file,text);
for(const name of ['matter.min.js','decomp.min.js'])fs.copyFileSync('src/vendor/'+name,'dist/vendor/'+name);
// Include third-party notices in an allowed local asset, outside game UI.
fs.writeFileSync('dist/licenses.json',JSON.stringify({matter:{version:'0.20.0',license:fs.readFileSync('node_modules/matter-js/LICENSE','utf8')},decomp:{version:'0.3.0',license:fs.readFileSync('node_modules/poly-decomp/LICENSE','utf8')},mp4Muxer:{version:'5.2.2',license:fs.readFileSync('node_modules/mp4-muxer/LICENSE','utf8')},taiwanCounty:{source:'NLSC',snapshot:'COUNTY_MOI_1090820',url:'https://data.gov.tw/dataset/7442',license:'政府資料開放授權條款第1版',licenseURL:'https://data.gov.tw/license',downloaded:'2026-10-17',note:'County/city outlines simplified for gameplay; remote island clusters use a labelled translated inset. Kinmen and Lienchiang belong to Fujian and are not duplicated in the Taiwan level.'},maps:{source:'DataV.GeoAtlas',url:'https://datav.aliyun.com/portal/school/atlas/area_selector',downloaded:'2026-10-16',note:'Public data; geographic outlines simplified for a game. Original provider terms apply.'}},null,2));
execFileSync(process.execPath,['scripts/check.mjs'],{stdio:'inherit'});
execFileSync(process.execPath,['scripts/audit-maps.cjs'],{stdio:'inherit'});
execFileSync(process.execPath,['scripts/audit-county-maps.cjs'],{stdio:'inherit'});
fs.mkdirSync('artifacts',{recursive:true});const audit='.codex/skills/minitool-zip-builder/scripts/audit_artifact.py';
if(!fs.existsSync(audit))throw Error('缺少用户指定官方 Skill,请先安装 1.8.0。');
const dirAudit=execFileSync('python3',[audit,'dist'],{encoding:'utf8'});console.log('官方目录审计:'+dirAudit.trim());
execFileSync('python3',['scripts/package.py'],{stdio:'inherit'});
const zipAudit=execFileSync('python3',[audit,'artifacts/shanhe-puzzle-xhs.zip'],{encoding:'utf8'});console.log('官方 ZIP 审计:'+zipAudit.trim());
fs.writeFileSync('artifacts/official-audit.txt','Skill version: 1.8.0\nDirectory: '+dirAudit+'ZIP: '+zipAudit);