update:翻译备份
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
// 回归截图中的小程序循环作用域问题:执行真实 render,再按 WXML 作用域取文本。
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const vm = require('node:vm');
|
||||
const {baseParse} = require('@vue/compiler-dom');
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const read = file => fs.readFileSync(path.join(root, file), 'utf8');
|
||||
const en = JSON.parse(read('src/locales/en.json'));
|
||||
const sourceKeys = JSON.parse(read('src/locales/source-keys.json'));
|
||||
const localeCode = read('src/locales/index.js').replace(/^import .*;\r?\n/gm, '').replace(/export /g, '');
|
||||
const locale = new Function('createI18n','en','sourceKeys',localeCode+'\nreturn {t,formatBattleTip};')(
|
||||
() => ({global: {t: key => key}}), en, sourceKeys);
|
||||
const computed = getter => ({get value() {return getter();}});
|
||||
const vendor = {
|
||||
computed, unref: value => value,
|
||||
e: (...parts) => Object.assign({}, ...parts),
|
||||
f: (items, render) => (typeof items === 'number' ? Array.from({length: items}, (_,i) => i+1) : items)
|
||||
.map((item,index) => render(item,index,index)),
|
||||
t: value => value == null ? '' : String(value),
|
||||
_export_sfc: component => component,
|
||||
};
|
||||
function loadComponent(file, dependencies) {
|
||||
let component;
|
||||
vm.runInNewContext(read(file), {
|
||||
exports: {}, wx: {createComponent: value => {component = value;}},
|
||||
require: id => {
|
||||
for (const [suffix,value] of Object.entries(dependencies)) if (id.endsWith(suffix)) return value;
|
||||
throw Error('Unexpected component dependency: '+id);
|
||||
},
|
||||
}, {filename: file});
|
||||
assert(component, 'No compiled component: '+file);
|
||||
return component;
|
||||
}
|
||||
const prefix = 'dist/build/mp-weixin/pages/team-battle/components/';
|
||||
const footer = loadComponent(prefix+'BattleFooter.js', {
|
||||
'common/vendor.js': vendor,
|
||||
'locales/index.js': locale,
|
||||
'constants.js': {RoundImages: {round1:'round1',round2:'round2',round3:'round3',gold1:'gold1'}},
|
||||
});
|
||||
const wxml = baseParse(read(prefix+'BattleFooter.wxml'));
|
||||
function evaluate(expression, scope) {
|
||||
return new Function('scope', 'with(scope){return ('+expression+');}')(scope);
|
||||
}
|
||||
function renderedTexts(node,scope) {
|
||||
const attr = name => (node.props || []).find(p => p.name === name)?.value?.content;
|
||||
const forValue = attr('wx:for');
|
||||
if (forValue) {
|
||||
const rows = evaluate(forValue.slice(2,-2),scope);
|
||||
return rows.flatMap((item,index) => renderedTexts({...node,props:node.props.filter(p=>p.name!=='wx:for')},
|
||||
{...scope,[attr('wx:for-item') || 'item']:item,[attr('wx:for-index') || 'index']:index}));
|
||||
}
|
||||
const ifValue = attr('wx:if');
|
||||
if (ifValue && !evaluate(ifValue.slice(2,-2),scope)) return [];
|
||||
if (node.tag === 'text') {
|
||||
return [(node.children || []).map(child => {
|
||||
const value = child.type === 5 ? evaluate(child.content.content,scope) : child.content || '';
|
||||
assert(value === null || typeof value !== 'object', 'WXML rendered a loop object in a text node');
|
||||
return value == null ? '' : String(value);
|
||||
}).join('')];
|
||||
}
|
||||
return (node.children || []).flatMap(child => renderedTexts(child,scope));
|
||||
}
|
||||
for (const count of [0,1,2,3,4]) {
|
||||
const roundResults = Array.from({length:count},(_,index)=>({
|
||||
ifGold:index===3, goldRound:index===3 ? 1 : 0,
|
||||
shoots:{1:[{ring:index===0 ? 10 : 0}],2:[{ring:8}]},
|
||||
}));
|
||||
const props = {roundResults,bluePoints:0,redPoints:0,goldenRound:count===4 ? 1 : 0};
|
||||
const data = footer.setup(props)(props,{});
|
||||
const texts = renderedTexts(wxml,data);
|
||||
assert.equal(texts.filter(text=>text===en.pts).length, Math.max(3,count)*2);
|
||||
assert(!texts.join('').includes('[object Object]'));
|
||||
if (count) assert(texts.includes('10'), 'Completed round score lost');
|
||||
if (count>1) assert(texts.includes('0'), 'Zero score lost');
|
||||
}
|
||||
// 顶部只转换显示值,监听器仍接收原始中文提示,语音控制不增加播放调用。
|
||||
for (const tip of ['请蓝队射箭','请红队射箭你重回']) {
|
||||
const store = {game:{currentShot:1,totalShot:3,tips:tip}};
|
||||
const header = loadComponent(prefix+'HeaderProgress.js', {
|
||||
'common/vendor.js': {...vendor,
|
||||
ref:value=>({value}), watch:(source,callback)=>callback(source()),
|
||||
onMounted:()=>{},onBeforeUnmount:()=>{},o:handler=>handler,
|
||||
},
|
||||
'locales/index.js':locale,
|
||||
'store.js':{useStore:()=>store},
|
||||
'audioManager.js':{audioManager:{setMuted:()=>{}}},
|
||||
});
|
||||
const data = header.setup({})({},{});
|
||||
assert.equal(data.a,locale.formatBattleTip(tip));
|
||||
assert(!/[\u3400-\u9fff]/.test(data.a));
|
||||
assert.equal(store.game.tips,tip);
|
||||
assert.equal(data.c,'1');
|
||||
assert.equal(data.d,'3');
|
||||
}
|
||||
console.log('Battle display checks passed: compiled JS + WXML, 0–3 rounds and golden round, blank/zero scores, English tips and original Chinese state preserved.');
|
||||
Reference in New Issue
Block a user