// Inspect actual native resources, not merely the source template or H5 output. import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import ts from 'typescript'; const root = fileURLToPath(new URL('../', import.meta.url)); const output = resolve(root, process.argv[2] || 'dist/build/app'); const service = readFileSync(resolve(output, 'app-service.js'), 'utf8'); assert.ok(service.includes('data:image/svg+xml;charset=utf-8,'), 'App bundle is missing embedded icon data'); assert.ok(service.includes('-webkit-mask-image') && service.includes('mask-image'), 'App bundle is missing mask bindings'); const ast = ts.createSourceFile('app-service.js', service, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS); function visit(node) { if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ['resolveComponent', 'createElementVNode', 'createVNode', 'createElementBlock'].includes(node.expression.name.text) && node.arguments.length > 0 && ts.isStringLiteral(node.arguments[0]) && ['svg', 'path'].includes(node.arguments[0].text)) { throw new Error(`Native bundle still contains an unsupported ${node.arguments[0].text} template element`); } ts.forEachChild(node, visit); } visit(ast); for (const page of ['home', 'nearby', 'messages', 'feed', 'profile', 'chat', 'membership']) { const css = readFileSync(resolve(output, `pages/${page}/index.css`), 'utf8'); assert.match(css, /\.app-icon\[/, `${page}: missing shared icon CSS`); for (const declaration of ['background-color:currentColor', '-webkit-mask-size:100% 100%', 'mask-size:100% 100%']) { assert.ok(css.includes(declaration), `${page}: missing ${declaration}`); } if (['home', 'nearby', 'messages', 'feed', 'profile'].includes(page)) { const button = css.match(/\.nav-item\[[^\]]+\]\{([^}]+)\}/)?.[1]; for (const declaration of ['width:100%', 'margin:0', 'overflow:visible', 'line-height:1']) { assert.ok(button?.split(';').includes(declaration), `${page}: bottom tab missing ${declaration}`); } const badge = css.match(/\.badge\[[^\]]+\]\{([^}]+)\}/)?.[1]; for (const declaration of ['display:flex', 'white-space:nowrap', 'pointer-events:none']) { assert.ok(badge?.split(';').includes(declaration), `${page}: unread badge missing ${declaration}`); } } } console.log('App 图标产物检查通过:内置图形、WebKit 兼容样式、消息角标防裁切样式齐全,无原始 SVG 模板组件。');