feat(config-editor): add RecordValue serializer with tests
This commit is contained in:
1
extensions/pixelhero-config-editor/__tests__/.gitignore
vendored
Normal file
1
extensions/pixelhero-config-editor/__tests__/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.tmp/
|
||||
@@ -0,0 +1,44 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { serializeValue, serializeEntry } from '../src/io/serializer';
|
||||
import { RecordValue } from '../src/io/recordValue';
|
||||
|
||||
test('serializeValue: num/str/bool', () => {
|
||||
assert.equal(serializeValue({ kind: 'num', value: 400 }), '400');
|
||||
assert.equal(serializeValue({ kind: 'str', value: '小铁卫' }), '"小铁卫"');
|
||||
assert.equal(serializeValue({ kind: 'bool', value: true }), 'true');
|
||||
});
|
||||
test('serializeValue: enumRef', () => {
|
||||
const v: RecordValue = { kind: 'enumRef', qualifier: 'FacSet', member: 'HERO' };
|
||||
assert.equal(serializeValue(v), 'FacSet.HERO');
|
||||
});
|
||||
test('serializeValue: speed', () => {
|
||||
const v: RecordValue = { kind: 'speed', level: 'Slow3' };
|
||||
assert.equal(serializeValue(v), 'AtkSpeedSet[AtkSpeedLv.Slow3].cd');
|
||||
});
|
||||
test('serializeValue: arr', () => {
|
||||
const v: RecordValue = { kind: 'arr', items: [{ kind: 'num', value: 1 }, { kind: 'num', value: 2 }] };
|
||||
assert.equal(serializeValue(v), '[1,2]');
|
||||
});
|
||||
test('serializeValue: obj', () => {
|
||||
const v: RecordValue = { kind: 'obj', props: { a: { kind: 'num', value: 1 }, b: { kind: 'str', value: 'x' } } };
|
||||
assert.equal(serializeValue(v), '{a:1,b:"x"}');
|
||||
});
|
||||
test('serializeValue: raw passthrough', () => {
|
||||
const v: RecordValue = { kind: 'raw', text: 'a + b' };
|
||||
assert.equal(serializeValue(v), 'a + b');
|
||||
});
|
||||
test('serializeEntry: all-scalar one line with trailing comma', () => {
|
||||
const v: RecordValue = { kind: 'obj', props: { uuid: { kind: 'num', value: 1 }, name: { kind: 'str', value: 'x' } } };
|
||||
assert.equal(serializeEntry('1', v), '1:{uuid:1,name:"x"},');
|
||||
});
|
||||
test('serializeEntry: nested on continuation lines', () => {
|
||||
const v: RecordValue = { kind: 'obj', props: {
|
||||
uuid: { kind: 'num', value: 5011 },
|
||||
skills: { kind: 'obj', props: { 6001: { kind: 'obj', props: { uuid: { kind: 'num', value: 6001 } } } } },
|
||||
} };
|
||||
const out = serializeEntry('5011', v);
|
||||
assert.match(out, /^5011:\{uuid:5011,$/m); // 首行:键 + 标量
|
||||
assert.match(out, / skills:\{6001:\{uuid:6001\}\},$/m); // 续行 8 空格
|
||||
assert.match(out, /^ \},$/m); // 闭合 4 空格
|
||||
});
|
||||
32
extensions/pixelhero-config-editor/src/io/serializer.ts
Normal file
32
extensions/pixelhero-config-editor/src/io/serializer.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { RecordValue, isScalar } from './recordValue';
|
||||
|
||||
export function serializeValue(v: RecordValue): string {
|
||||
switch (v.kind) {
|
||||
case 'num': return String(v.value);
|
||||
case 'str': return JSON.stringify(v.value);
|
||||
case 'bool': return String(v.value);
|
||||
case 'enumRef': return `${v.qualifier}.${v.member}`;
|
||||
case 'speed': return `AtkSpeedSet[AtkSpeedLv.${v.level}].cd`;
|
||||
case 'arr': return `[${v.items.map(serializeValue).join(',')}]`;
|
||||
case 'obj': {
|
||||
const body = Object.entries(v.props).map(([k, val]) => `${k}:${serializeValue(val)}`).join(',');
|
||||
return `{${body}}`;
|
||||
}
|
||||
case 'raw': return v.text;
|
||||
}
|
||||
}
|
||||
|
||||
/** 序列化一条顶层记录。首行无缩进(缩进由调用处保留的 trivia 提供);嵌套字段 8 空格续行;闭合 4 空格。 */
|
||||
export function serializeEntry(key: string, obj: RecordValue): string {
|
||||
if (obj.kind !== 'obj') return `${key}:${serializeValue(obj)},`;
|
||||
const props = obj.props;
|
||||
const keys = Object.keys(props);
|
||||
const scalars = keys.filter(k => isScalar(props[k]));
|
||||
const nested = keys.filter(k => !isScalar(props[k]));
|
||||
const scalarTxt = scalars.map(k => `${k}:${serializeValue(props[k])}`).join(',');
|
||||
if (nested.length === 0) return `${key}:{${scalarTxt}},`;
|
||||
const lines = [`${key}:{${scalarTxt},`];
|
||||
for (const k of nested) lines.push(` ${k}:${serializeValue(props[k])},`);
|
||||
lines.push(' },');
|
||||
return lines.join('\n');
|
||||
}
|
||||
Reference in New Issue
Block a user