@qilitt-mickey/vue3-temp-skill 1.1.72 → 1.1.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +1 -1
- package/dist/theme-vars.js +1 -1
- package/dist/theme.css +1 -1
- package/mapping/layout/shell-geometry.json +26 -26
- package/mapping/scenes/admin/content.json +3 -0
- package/mapping/scenes/admin/layout.json +4 -1
- package/package.json +1 -1
- package/parser/fixtures/changeset-fullpage-restore.json +259 -138
- package/parser/fixtures/changeset-gap-block.json +24 -0
- package/parser/fixtures/changeset-neg4-g8.json +15 -15
- package/parser/fixtures/changeset-neg6-g9-identity.json +39 -39
- package/parser/fixtures/changeset-neg8-g11-oracle.json +57 -57
- package/parser/fixtures/changeset-neg9-g6-token-chain.json +34 -0
- package/parser/fixtures/changeset-pos-g6-token-chain.json +35 -0
- package/parser/fixtures/changeset-pos-theme-neutral.json +264 -264
- package/parser/fixtures/changeset-pos.json +50 -43
- package/parser/fixtures/changeset-v32-fields.json +71 -63
- package/parser/fixtures/registry-g6-token-chain.json +10 -0
- package/parser/fixtures/registry-sample.json +15 -15
- package/parser/fixtures/verify/mockup-baseline-admin-list.html +27 -0
- package/parser/fixtures/verify/mockup-g6-content.html +12 -0
- package/parser/fixtures/verify/oracle.json +37 -37
- package/parser/generator.js +178 -178
- package/parser/index.js +2706 -2648
- package/parser/override.js +119 -119
- package/parser/regression.js +301 -293
- package/parser/watch.js +103 -103
- package/references/layout-theme.md +2 -0
- package/references/steps/maintenance.md +31 -31
- package/references/steps/regression.md +49 -49
- package/references/steps/step1-match.md +65 -64
- package/references/steps/step1b-audit.md +23 -23
- package/references/steps/step1c-registry.md +29 -29
- package/references/steps/step2-structure.md +73 -73
- package/references/steps/step3-style.md +5 -0
- package/references/steps/step3b-shell.md +63 -61
- package/references/steps/step5-gates.md +1 -0
- package/scripts/apply-final-gate.mjs +170 -170
- package/scripts/check.mjs +24 -0
- package/scripts/design-audit.mjs +1575 -1502
package/parser/override.js
CHANGED
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* override.js — 业务级映射覆写 API
|
|
3
|
-
*
|
|
4
|
-
* 用途:业务项目存在少量自定义映射需求时,通过本 API 在运行时覆写
|
|
5
|
-
* 指定字段,无需在业务侧维护完整 mapping/ 目录。
|
|
6
|
-
*
|
|
7
|
-
* 设计约束(严格按方案):
|
|
8
|
-
* 1. 浅覆写 + 深合并:覆写只落在传入的 key 上,未提及的映射原样保留。
|
|
9
|
-
* 2. 不可变:返回新对象,不修改传入的 themeVars / 映射数据集。
|
|
10
|
-
* 3. 白名单校验:只允许覆写词典中已存在的 key——防止业务侧拼错字段名
|
|
11
|
-
* 造成静默失效(与 parser「守门员」职责一致:错误数据进不了链路)。
|
|
12
|
-
* 需要放开时传 { strict: false },未知 key 将产生告警但不阻断。
|
|
13
|
-
* 4. 本 API 属链路 A(基线注入)配套能力:服务于「空白新项目从零接入
|
|
14
|
-
* Skill 主题体系」的场景;成熟模板项目(如 vue3-web-temp)不引入。
|
|
15
|
-
*
|
|
16
|
-
* 用法:
|
|
17
|
-
* import { themeVars, overrideMapping } from "@qilitt-mickey/vue3-temp-skill/dist/theme-vars.js";
|
|
18
|
-
* const custom = overrideMapping(themeVars, { color: { brandPrimary: "#ff6600" } });
|
|
19
|
-
*
|
|
20
|
-
* 或对语义 ID 映射条目覆写(parser 内部使用):
|
|
21
|
-
* const entry = overrideMapping(baseEntry, { css_vars: { menu_bg: "--custom-var" } }, { id: "admin.layout.sidebar.menu" });
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/** 递归合并覆写:override 中的值覆盖 base,对象做深合并,其余类型直接替换 */
|
|
25
|
-
function deepMerge(base, override) {
|
|
26
|
-
const out = Array.isArray(base) ? [...base] : { ...base };
|
|
27
|
-
for (const [k, v] of Object.entries(override ?? {})) {
|
|
28
|
-
if (v !== null && typeof v === "object" && !Array.isArray(v)
|
|
29
|
-
&& out[k] !== null && typeof out[k] === "object" && !Array.isArray(out[k])) {
|
|
30
|
-
out[k] = deepMerge(out[k], v);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
out[k] = v;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return out;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* 覆写映射对象。
|
|
41
|
-
* @param {object} base 基础映射(themeVars / 单个映射条目 / 整个 dataset)
|
|
42
|
-
* @param {object} override 覆写片段,结构与 base 对应部分同构
|
|
43
|
-
* @param {{ id?: string, strict?: boolean }} [opts]
|
|
44
|
-
* - id:被覆写对象的标识(用于错误提示,如语义 ID 名)
|
|
45
|
-
* - strict:默认 true——override 中出现 base 不存在的 key 时抛错
|
|
46
|
-
* @returns {object} 新对象(base 不被修改)
|
|
47
|
-
*/
|
|
48
|
-
export function overrideMapping(base, override, opts = {}) {
|
|
49
|
-
const { id = "mapping", strict = true } = opts;
|
|
50
|
-
if (base === null || typeof base !== "object")
|
|
51
|
-
throw new TypeError(`overrideMapping: base 必须为对象(${id})`);
|
|
52
|
-
if (override === null || override === undefined)
|
|
53
|
-
return base;
|
|
54
|
-
if (typeof override !== "object")
|
|
55
|
-
throw new TypeError(`overrideMapping: override 必须为对象(${id})`);
|
|
56
|
-
|
|
57
|
-
// 白名单校验:只允许覆写已存在的 key(拼错字段名直接暴露)
|
|
58
|
-
for (const k of Object.keys(override)) {
|
|
59
|
-
if (!(k in base)) {
|
|
60
|
-
const msg = `overrideMapping: 「${k}」在 ${id} 中不存在,无法覆写${strict ? "(strict 模式,疑似字段名拼写错误)" : "(已忽略)"}`;
|
|
61
|
-
if (strict)
|
|
62
|
-
throw new Error(msg);
|
|
63
|
-
console.warn(` ⚠ ${msg}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return deepMerge(base, override);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* 便捷封装:批量覆写多个语义 ID 条目。
|
|
72
|
-
* @param {Record<string, object>} index 合并索引(id → 条目),如 buildMergedIndex 结果
|
|
73
|
-
* @param {Record<string, object>} overrides { 语义ID: 覆写片段 }
|
|
74
|
-
* @param {{ strict?: boolean }} [opts]
|
|
75
|
-
* @returns {Record<string, object>} 新索引
|
|
76
|
-
*/
|
|
77
|
-
export function overrideMappings(index, overrides, opts = {}) {
|
|
78
|
-
const out = { ...index };
|
|
79
|
-
for (const [id, patch] of Object.entries(overrides)) {
|
|
80
|
-
if (!out[id]) {
|
|
81
|
-
const msg = `overrideMappings: 语义 ID「${id}」不在词典中,无法覆写`;
|
|
82
|
-
if (opts.strict !== false)
|
|
83
|
-
throw new Error(msg);
|
|
84
|
-
console.warn(` ⚠ ${msg}`);
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
out[id] = overrideMapping(out[id], patch, { id, strict: opts.strict !== false });
|
|
88
|
-
}
|
|
89
|
-
return out;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// ---- CLI 独立执行:对一份 changeset 计算覆写结果(调试用)----
|
|
93
|
-
// 用法:node parser/override.js <overrides.json>
|
|
94
|
-
// overrides.json 形如 { "admin.layout.sidebar.menu": { "css_vars": { "menu_bg": "--x" } } }
|
|
95
|
-
if (process.argv[1] && process.argv[1].endsWith("override.js")) {
|
|
96
|
-
const { readFileSync } = await import("node:fs");
|
|
97
|
-
const { buildMappingDataset } = await import("./loader.js");
|
|
98
|
-
const { buildMergedIndex } = await import("./validator.js");
|
|
99
|
-
const file = process.argv[2];
|
|
100
|
-
if (!file) {
|
|
101
|
-
console.error("用法:node parser/override.js <overrides.json>");
|
|
102
|
-
process.exit(1);
|
|
103
|
-
}
|
|
104
|
-
try {
|
|
105
|
-
const overrides = JSON.parse(readFileSync(file, "utf-8"));
|
|
106
|
-
const dataset = buildMappingDataset();
|
|
107
|
-
const index = buildMergedIndex(dataset);
|
|
108
|
-
const merged = overrideMappings(index, overrides);
|
|
109
|
-
const changed = Object.keys(overrides).filter(id => merged[id]);
|
|
110
|
-
console.log(`✔ 覆写成功 ${changed.length} 条:`);
|
|
111
|
-
for (const id of changed)
|
|
112
|
-
console.log(` - ${id}`);
|
|
113
|
-
console.log(JSON.stringify(Object.fromEntries(changed.map(id => [id, merged[id]])), null, 2));
|
|
114
|
-
}
|
|
115
|
-
catch (e) {
|
|
116
|
-
console.error(`✖ 覆写失败:${e.message}`);
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* override.js — 业务级映射覆写 API(可选扩展)
|
|
3
|
+
*
|
|
4
|
+
* 用途:业务项目存在少量自定义映射需求时,通过本 API 在运行时覆写
|
|
5
|
+
* 指定字段,无需在业务侧维护完整 mapping/ 目录。
|
|
6
|
+
*
|
|
7
|
+
* 设计约束(严格按方案):
|
|
8
|
+
* 1. 浅覆写 + 深合并:覆写只落在传入的 key 上,未提及的映射原样保留。
|
|
9
|
+
* 2. 不可变:返回新对象,不修改传入的 themeVars / 映射数据集。
|
|
10
|
+
* 3. 白名单校验:只允许覆写词典中已存在的 key——防止业务侧拼错字段名
|
|
11
|
+
* 造成静默失效(与 parser「守门员」职责一致:错误数据进不了链路)。
|
|
12
|
+
* 需要放开时传 { strict: false },未知 key 将产生告警但不阻断。
|
|
13
|
+
* 4. 本 API 属链路 A(基线注入)配套能力:服务于「空白新项目从零接入
|
|
14
|
+
* Skill 主题体系」的场景;成熟模板项目(如 vue3-web-temp)不引入。
|
|
15
|
+
*
|
|
16
|
+
* 用法:
|
|
17
|
+
* import { themeVars, overrideMapping } from "@qilitt-mickey/vue3-temp-skill/dist/theme-vars.js";
|
|
18
|
+
* const custom = overrideMapping(themeVars, { color: { brandPrimary: "#ff6600" } });
|
|
19
|
+
*
|
|
20
|
+
* 或对语义 ID 映射条目覆写(parser 内部使用):
|
|
21
|
+
* const entry = overrideMapping(baseEntry, { css_vars: { menu_bg: "--custom-var" } }, { id: "admin.layout.sidebar.menu" });
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** 递归合并覆写:override 中的值覆盖 base,对象做深合并,其余类型直接替换 */
|
|
25
|
+
function deepMerge(base, override) {
|
|
26
|
+
const out = Array.isArray(base) ? [...base] : { ...base };
|
|
27
|
+
for (const [k, v] of Object.entries(override ?? {})) {
|
|
28
|
+
if (v !== null && typeof v === "object" && !Array.isArray(v)
|
|
29
|
+
&& out[k] !== null && typeof out[k] === "object" && !Array.isArray(out[k])) {
|
|
30
|
+
out[k] = deepMerge(out[k], v);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
out[k] = v;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 覆写映射对象。
|
|
41
|
+
* @param {object} base 基础映射(themeVars / 单个映射条目 / 整个 dataset)
|
|
42
|
+
* @param {object} override 覆写片段,结构与 base 对应部分同构
|
|
43
|
+
* @param {{ id?: string, strict?: boolean }} [opts]
|
|
44
|
+
* - id:被覆写对象的标识(用于错误提示,如语义 ID 名)
|
|
45
|
+
* - strict:默认 true——override 中出现 base 不存在的 key 时抛错
|
|
46
|
+
* @returns {object} 新对象(base 不被修改)
|
|
47
|
+
*/
|
|
48
|
+
export function overrideMapping(base, override, opts = {}) {
|
|
49
|
+
const { id = "mapping", strict = true } = opts;
|
|
50
|
+
if (base === null || typeof base !== "object")
|
|
51
|
+
throw new TypeError(`overrideMapping: base 必须为对象(${id})`);
|
|
52
|
+
if (override === null || override === undefined)
|
|
53
|
+
return base;
|
|
54
|
+
if (typeof override !== "object")
|
|
55
|
+
throw new TypeError(`overrideMapping: override 必须为对象(${id})`);
|
|
56
|
+
|
|
57
|
+
// 白名单校验:只允许覆写已存在的 key(拼错字段名直接暴露)
|
|
58
|
+
for (const k of Object.keys(override)) {
|
|
59
|
+
if (!(k in base)) {
|
|
60
|
+
const msg = `overrideMapping: 「${k}」在 ${id} 中不存在,无法覆写${strict ? "(strict 模式,疑似字段名拼写错误)" : "(已忽略)"}`;
|
|
61
|
+
if (strict)
|
|
62
|
+
throw new Error(msg);
|
|
63
|
+
console.warn(` ⚠ ${msg}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return deepMerge(base, override);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 便捷封装:批量覆写多个语义 ID 条目。
|
|
72
|
+
* @param {Record<string, object>} index 合并索引(id → 条目),如 buildMergedIndex 结果
|
|
73
|
+
* @param {Record<string, object>} overrides { 语义ID: 覆写片段 }
|
|
74
|
+
* @param {{ strict?: boolean }} [opts]
|
|
75
|
+
* @returns {Record<string, object>} 新索引
|
|
76
|
+
*/
|
|
77
|
+
export function overrideMappings(index, overrides, opts = {}) {
|
|
78
|
+
const out = { ...index };
|
|
79
|
+
for (const [id, patch] of Object.entries(overrides)) {
|
|
80
|
+
if (!out[id]) {
|
|
81
|
+
const msg = `overrideMappings: 语义 ID「${id}」不在词典中,无法覆写`;
|
|
82
|
+
if (opts.strict !== false)
|
|
83
|
+
throw new Error(msg);
|
|
84
|
+
console.warn(` ⚠ ${msg}`);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
out[id] = overrideMapping(out[id], patch, { id, strict: opts.strict !== false });
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ---- CLI 独立执行:对一份 changeset 计算覆写结果(调试用)----
|
|
93
|
+
// 用法:node parser/override.js <overrides.json>
|
|
94
|
+
// overrides.json 形如 { "admin.layout.sidebar.menu": { "css_vars": { "menu_bg": "--x" } } }
|
|
95
|
+
if (process.argv[1] && process.argv[1].endsWith("override.js")) {
|
|
96
|
+
const { readFileSync } = await import("node:fs");
|
|
97
|
+
const { buildMappingDataset } = await import("./loader.js");
|
|
98
|
+
const { buildMergedIndex } = await import("./validator.js");
|
|
99
|
+
const file = process.argv[2];
|
|
100
|
+
if (!file) {
|
|
101
|
+
console.error("用法:node parser/override.js <overrides.json>");
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const overrides = JSON.parse(readFileSync(file, "utf-8"));
|
|
106
|
+
const dataset = buildMappingDataset();
|
|
107
|
+
const index = buildMergedIndex(dataset);
|
|
108
|
+
const merged = overrideMappings(index, overrides);
|
|
109
|
+
const changed = Object.keys(overrides).filter(id => merged[id]);
|
|
110
|
+
console.log(`✔ 覆写成功 ${changed.length} 条:`);
|
|
111
|
+
for (const id of changed)
|
|
112
|
+
console.log(` - ${id}`);
|
|
113
|
+
console.log(JSON.stringify(Object.fromEntries(changed.map(id => [id, merged[id]])), null, 2));
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
console.error(`✖ 覆写失败:${e.message}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
}
|