@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/generator.js
CHANGED
|
@@ -1,178 +1,178 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* generator.js — 多格式产物生成器
|
|
3
|
-
*
|
|
4
|
-
* 校验通过后,从 mapping/ 数据集生成 dist/ 下四种可交付产物:
|
|
5
|
-
* 1. dist/theme.css CSS 变量全局基线(:root 层,链路 A 空白项目按需引入)
|
|
6
|
-
* 2. dist/theme-vars.ts TypeScript 类型化主题变量对象
|
|
7
|
-
* 3. dist/theme-vars.js ESM 运行时入口(themeVars + overrideMapping,§3.4.4.3)
|
|
8
|
-
* 4. dist/mapping-type.d.ts 映射类型声明
|
|
9
|
-
*
|
|
10
|
-
* 链路 A
|
|
11
|
-
* vue3-web-temp 引入(其自有 design-tokens.scss 为权威令牌源,避免双令牌源冲突)。
|
|
12
|
-
*
|
|
13
|
-
* 用法:node parser/generator.js [--out <dir>] [--dry]
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { mkdirSync, writeFileSync, existsSync } from "node:fs";
|
|
17
|
-
import path from "node:path";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
19
|
-
import { buildMappingDataset } from "./loader.js";
|
|
20
|
-
import { buildMergedIndex } from "./validator.js";
|
|
21
|
-
|
|
22
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
const ROOT = path.resolve(__dirname, "..");
|
|
24
|
-
|
|
25
|
-
// ---- CLI ----
|
|
26
|
-
if (process.argv[1] && process.argv[1].endsWith("generator.js")) {
|
|
27
|
-
const outIdx = process.argv.indexOf("--out");
|
|
28
|
-
const outDir = outIdx > -1 ? path.resolve(process.argv[outIdx + 1]) : path.join(ROOT, "dist");
|
|
29
|
-
const dry = process.argv.includes("--dry");
|
|
30
|
-
const result = generateAll(outDir, dry);
|
|
31
|
-
if (!dry) {
|
|
32
|
-
console.log(`✔ 产物生成完成 → ${outDir}`);
|
|
33
|
-
for (const f of result.written)
|
|
34
|
-
console.log(` · ${f}`);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
console.log(`[dry-run] 将生成 ${result.written.length} 个文件 → ${outDir}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** 汇总所有 tokens(basic/layout 域的令牌定义),返回 { abstractField, token, default } 数组 */
|
|
42
|
-
export function collectTokens(dataset) {
|
|
43
|
-
const rows = [];
|
|
44
|
-
for (const [file, data] of Object.entries(dataset.files)) {
|
|
45
|
-
if (!data.tokens)
|
|
46
|
-
continue;
|
|
47
|
-
for (const [field, def] of Object.entries(data.tokens)) {
|
|
48
|
-
if (field.startsWith("$"))
|
|
49
|
-
continue;
|
|
50
|
-
// token 链("A → B")拆为数组:链上每个实现令牌都要生成
|
|
51
|
-
const tokenChain = typeof def.token === "string" && def.token.includes(" → ")
|
|
52
|
-
? def.token.split(" → ").map(s => s.trim()).filter(Boolean)
|
|
53
|
-
: [def.token || ""];
|
|
54
|
-
rows.push({
|
|
55
|
-
abstract: field,
|
|
56
|
-
token: tokenChain[0],
|
|
57
|
-
tokenChain,
|
|
58
|
-
default: def.default ?? "",
|
|
59
|
-
file,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return rows;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function generateAll(outDir, dry = false) {
|
|
67
|
-
const dataset = buildMappingDataset();
|
|
68
|
-
const tokens = collectTokens(dataset);
|
|
69
|
-
const written = [];
|
|
70
|
-
|
|
71
|
-
// ---- 1. theme.css:链路 A
|
|
72
|
-
// 有出厂值的令牌生成真实 CSS 自定义属性(空白项目引入即得完整基线);
|
|
73
|
-
// 无出厂值的仅生成注释索引(需项目侧自行定值)。
|
|
74
|
-
const cssBody = [];
|
|
75
|
-
for (const t of tokens) {
|
|
76
|
-
if (!t.default) {
|
|
77
|
-
cssBody.push(` /* ${t.abstract} → ${t.token || "(value token)"}(无出厂值,需项目侧定值) */`);
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
for (const token of t.tokenChain) {
|
|
81
|
-
if (!token)
|
|
82
|
-
continue;
|
|
83
|
-
cssBody.push(` ${token}: ${t.default}; /* ← ${t.abstract} */`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const cssLines = [
|
|
87
|
-
"/* AUTO-GENERATED by vue3-temp-skill parser/generator.js — DO NOT EDIT */",
|
|
88
|
-
"/* 链路 A
|
|
89
|
-
" * 仅空白新项目从零接入 Skill 主题体系时在样式入口引入一次;",
|
|
90
|
-
" * 成熟模板项目(自有 design-tokens.scss 权威令牌源)不得引入,避免双令牌源冲突。 */",
|
|
91
|
-
":root {",
|
|
92
|
-
...cssBody,
|
|
93
|
-
"}",
|
|
94
|
-
"",
|
|
95
|
-
];
|
|
96
|
-
|
|
97
|
-
// ---- 2. theme-vars.ts:类型化变量对象 ----
|
|
98
|
-
const tsLines = [
|
|
99
|
-
"// AUTO-GENERATED by vue3-temp-skill parser/generator.js — DO NOT EDIT",
|
|
100
|
-
"export const themeVars = {",
|
|
101
|
-
...tokens.map(t => ` /** ${t.tokenChain.join(" → ") || "value token"}${t.default ? ` 出厂 ${t.default}` : ""} */`),
|
|
102
|
-
...tokens.map(t => ` ${toCamel(t.abstract)}: '${t.default}' as string,`),
|
|
103
|
-
"} as const;",
|
|
104
|
-
"",
|
|
105
|
-
"export type ThemeVarKey = keyof typeof themeVars;",
|
|
106
|
-
"",
|
|
107
|
-
];
|
|
108
|
-
|
|
109
|
-
// ---- 2.5 theme-vars.js:ESM 运行时入口(链路 A 配套,业务级覆写 API 挂载点 §3.4.4.3)----
|
|
110
|
-
const jsLines = [
|
|
111
|
-
"// AUTO-GENERATED by vue3-temp-skill parser/generator.js — DO NOT EDIT",
|
|
112
|
-
"// 链路 A 运行时入口:themeVars + overrideMapping
|
|
113
|
-
"// 用法:import { themeVars, overrideMapping } from '@qilitt-mickey/vue3-temp-skill/dist/theme-vars.js';",
|
|
114
|
-
"// const custom = overrideMapping(themeVars, { color: { brandPrimary: '#ff6600' } });",
|
|
115
|
-
"export const themeVars = {",
|
|
116
|
-
...tokens.map(t => ` ${toCamel(t.abstract)}: '${t.default}',`),
|
|
117
|
-
"};",
|
|
118
|
-
"",
|
|
119
|
-
"export { overrideMapping, overrideMappings } from '../parser/override.js';",
|
|
120
|
-
"",
|
|
121
|
-
];
|
|
122
|
-
|
|
123
|
-
// ---- 3. mapping-type.d.ts:映射条目类型声明 ----
|
|
124
|
-
const dtsLines = [
|
|
125
|
-
"// AUTO-GENERATED by vue3-temp-skill parser/generator.js — DO NOT EDIT",
|
|
126
|
-
"",
|
|
127
|
-
"/** 语义 ID 映射条目(结构与 mapping/scenes/**.json 条目一致) */",
|
|
128
|
-
"export interface SemanticMappingEntry {",
|
|
129
|
-
" type: 'module' | 'component' | 'element' | 'global_component' | 'global_token';",
|
|
130
|
-
" selector?: string;",
|
|
131
|
-
" component?: string;",
|
|
132
|
-
" file?: string;",
|
|
133
|
-
" style_scope: string;",
|
|
134
|
-
" default_props?: Record<string, unknown>;",
|
|
135
|
-
" children?: string[];",
|
|
136
|
-
" forms?: Record<string, string>;",
|
|
137
|
-
" visible_prop?: string;",
|
|
138
|
-
" css_vars?: Record<string, string>;",
|
|
139
|
-
" custom_style_map?: Record<string, string>;",
|
|
140
|
-
" [key: string]: unknown;",
|
|
141
|
-
"}",
|
|
142
|
-
"",
|
|
143
|
-
"/** 设计变更集(design.changeset/1.0 输入,兼容历史值 design-changeset/v1) */",
|
|
144
|
-
"export interface DesignChangeset {",
|
|
145
|
-
" schema: 'design.changeset/1.0' | 'design-changeset/v1';",
|
|
146
|
-
" mapping_version?: string;",
|
|
147
|
-
" scene: string;",
|
|
148
|
-
" layout_type?: string;",
|
|
149
|
-
" global?: Record<string, Record<string, string | number>>;",
|
|
150
|
-
" changes: Array<{",
|
|
151
|
-
" id: string;",
|
|
152
|
-
" visible?: boolean;",
|
|
153
|
-
" position?: Record<string, string>;",
|
|
154
|
-
" form?: string;",
|
|
155
|
-
" style?: Record<string, string | number>;",
|
|
156
|
-
" }>;",
|
|
157
|
-
"}",
|
|
158
|
-
"",
|
|
159
|
-
];
|
|
160
|
-
|
|
161
|
-
if (!dry) {
|
|
162
|
-
mkdirSync(outDir, { recursive: true });
|
|
163
|
-
writeFileSync(path.join(outDir, "theme.css"), cssLines.join("\n"), "utf-8");
|
|
164
|
-
writeFileSync(path.join(outDir, "theme-vars.ts"), tsLines.join("\n"), "utf-8");
|
|
165
|
-
writeFileSync(path.join(outDir, "theme-vars.js"), jsLines.join("\n"), "utf-8");
|
|
166
|
-
writeFileSync(path.join(outDir, "mapping-type.d.ts"), dtsLines.join("\n"), "utf-8");
|
|
167
|
-
written.push("theme.css", "theme-vars.ts", "theme-vars.js", "mapping-type.d.ts");
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
written.push("theme.css", "theme-vars.ts", "theme-vars.js", "mapping-type.d.ts");
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return { written, tokenCount: tokens.length };
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function toCamel(s) {
|
|
177
|
-
return s.replaceAll(/[_-](\w)/g, (_, c) => c.toUpperCase());
|
|
178
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* generator.js — 多格式产物生成器
|
|
3
|
+
*
|
|
4
|
+
* 校验通过后,从 mapping/ 数据集生成 dist/ 下四种可交付产物:
|
|
5
|
+
* 1. dist/theme.css CSS 变量全局基线(:root 层,链路 A 空白项目按需引入)
|
|
6
|
+
* 2. dist/theme-vars.ts TypeScript 类型化主题变量对象
|
|
7
|
+
* 3. dist/theme-vars.js ESM 运行时入口(themeVars + overrideMapping,§3.4.4.3)
|
|
8
|
+
* 4. dist/mapping-type.d.ts 映射类型声明
|
|
9
|
+
*
|
|
10
|
+
* 链路 A(业务项目直接消费产物):产物随 NPM 包发布但不被
|
|
11
|
+
* vue3-web-temp 引入(其自有 design-tokens.scss 为权威令牌源,避免双令牌源冲突)。
|
|
12
|
+
*
|
|
13
|
+
* 用法:node parser/generator.js [--out <dir>] [--dry]
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { mkdirSync, writeFileSync, existsSync } from "node:fs";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
import { buildMappingDataset } from "./loader.js";
|
|
20
|
+
import { buildMergedIndex } from "./validator.js";
|
|
21
|
+
|
|
22
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const ROOT = path.resolve(__dirname, "..");
|
|
24
|
+
|
|
25
|
+
// ---- CLI ----
|
|
26
|
+
if (process.argv[1] && process.argv[1].endsWith("generator.js")) {
|
|
27
|
+
const outIdx = process.argv.indexOf("--out");
|
|
28
|
+
const outDir = outIdx > -1 ? path.resolve(process.argv[outIdx + 1]) : path.join(ROOT, "dist");
|
|
29
|
+
const dry = process.argv.includes("--dry");
|
|
30
|
+
const result = generateAll(outDir, dry);
|
|
31
|
+
if (!dry) {
|
|
32
|
+
console.log(`✔ 产物生成完成 → ${outDir}`);
|
|
33
|
+
for (const f of result.written)
|
|
34
|
+
console.log(` · ${f}`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
console.log(`[dry-run] 将生成 ${result.written.length} 个文件 → ${outDir}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** 汇总所有 tokens(basic/layout 域的令牌定义),返回 { abstractField, token, default } 数组 */
|
|
42
|
+
export function collectTokens(dataset) {
|
|
43
|
+
const rows = [];
|
|
44
|
+
for (const [file, data] of Object.entries(dataset.files)) {
|
|
45
|
+
if (!data.tokens)
|
|
46
|
+
continue;
|
|
47
|
+
for (const [field, def] of Object.entries(data.tokens)) {
|
|
48
|
+
if (field.startsWith("$"))
|
|
49
|
+
continue;
|
|
50
|
+
// token 链("A → B")拆为数组:链上每个实现令牌都要生成
|
|
51
|
+
const tokenChain = typeof def.token === "string" && def.token.includes(" → ")
|
|
52
|
+
? def.token.split(" → ").map(s => s.trim()).filter(Boolean)
|
|
53
|
+
: [def.token || ""];
|
|
54
|
+
rows.push({
|
|
55
|
+
abstract: field,
|
|
56
|
+
token: tokenChain[0],
|
|
57
|
+
tokenChain,
|
|
58
|
+
default: def.default ?? "",
|
|
59
|
+
file,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return rows;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function generateAll(outDir, dry = false) {
|
|
67
|
+
const dataset = buildMappingDataset();
|
|
68
|
+
const tokens = collectTokens(dataset);
|
|
69
|
+
const written = [];
|
|
70
|
+
|
|
71
|
+
// ---- 1. theme.css:链路 A 变量基线 ----
|
|
72
|
+
// 有出厂值的令牌生成真实 CSS 自定义属性(空白项目引入即得完整基线);
|
|
73
|
+
// 无出厂值的仅生成注释索引(需项目侧自行定值)。
|
|
74
|
+
const cssBody = [];
|
|
75
|
+
for (const t of tokens) {
|
|
76
|
+
if (!t.default) {
|
|
77
|
+
cssBody.push(` /* ${t.abstract} → ${t.token || "(value token)"}(无出厂值,需项目侧定值) */`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
for (const token of t.tokenChain) {
|
|
81
|
+
if (!token)
|
|
82
|
+
continue;
|
|
83
|
+
cssBody.push(` ${token}: ${t.default}; /* ← ${t.abstract} */`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const cssLines = [
|
|
87
|
+
"/* AUTO-GENERATED by vue3-temp-skill parser/generator.js — DO NOT EDIT */",
|
|
88
|
+
"/* 链路 A(基线注入)产物:全局令牌变量基线。",
|
|
89
|
+
" * 仅空白新项目从零接入 Skill 主题体系时在样式入口引入一次;",
|
|
90
|
+
" * 成熟模板项目(自有 design-tokens.scss 权威令牌源)不得引入,避免双令牌源冲突。 */",
|
|
91
|
+
":root {",
|
|
92
|
+
...cssBody,
|
|
93
|
+
"}",
|
|
94
|
+
"",
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
// ---- 2. theme-vars.ts:类型化变量对象 ----
|
|
98
|
+
const tsLines = [
|
|
99
|
+
"// AUTO-GENERATED by vue3-temp-skill parser/generator.js — DO NOT EDIT",
|
|
100
|
+
"export const themeVars = {",
|
|
101
|
+
...tokens.map(t => ` /** ${t.tokenChain.join(" → ") || "value token"}${t.default ? ` 出厂 ${t.default}` : ""} */`),
|
|
102
|
+
...tokens.map(t => ` ${toCamel(t.abstract)}: '${t.default}' as string,`),
|
|
103
|
+
"} as const;",
|
|
104
|
+
"",
|
|
105
|
+
"export type ThemeVarKey = keyof typeof themeVars;",
|
|
106
|
+
"",
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
// ---- 2.5 theme-vars.js:ESM 运行时入口(链路 A 配套,业务级覆写 API 挂载点 §3.4.4.3)----
|
|
110
|
+
const jsLines = [
|
|
111
|
+
"// AUTO-GENERATED by vue3-temp-skill parser/generator.js — DO NOT EDIT",
|
|
112
|
+
"// 链路 A 运行时入口:themeVars + overrideMapping(业务级覆写)",
|
|
113
|
+
"// 用法:import { themeVars, overrideMapping } from '@qilitt-mickey/vue3-temp-skill/dist/theme-vars.js';",
|
|
114
|
+
"// const custom = overrideMapping(themeVars, { color: { brandPrimary: '#ff6600' } });",
|
|
115
|
+
"export const themeVars = {",
|
|
116
|
+
...tokens.map(t => ` ${toCamel(t.abstract)}: '${t.default}',`),
|
|
117
|
+
"};",
|
|
118
|
+
"",
|
|
119
|
+
"export { overrideMapping, overrideMappings } from '../parser/override.js';",
|
|
120
|
+
"",
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
// ---- 3. mapping-type.d.ts:映射条目类型声明 ----
|
|
124
|
+
const dtsLines = [
|
|
125
|
+
"// AUTO-GENERATED by vue3-temp-skill parser/generator.js — DO NOT EDIT",
|
|
126
|
+
"",
|
|
127
|
+
"/** 语义 ID 映射条目(结构与 mapping/scenes/**.json 条目一致) */",
|
|
128
|
+
"export interface SemanticMappingEntry {",
|
|
129
|
+
" type: 'module' | 'component' | 'element' | 'global_component' | 'global_token';",
|
|
130
|
+
" selector?: string;",
|
|
131
|
+
" component?: string;",
|
|
132
|
+
" file?: string;",
|
|
133
|
+
" style_scope: string;",
|
|
134
|
+
" default_props?: Record<string, unknown>;",
|
|
135
|
+
" children?: string[];",
|
|
136
|
+
" forms?: Record<string, string>;",
|
|
137
|
+
" visible_prop?: string;",
|
|
138
|
+
" css_vars?: Record<string, string>;",
|
|
139
|
+
" custom_style_map?: Record<string, string>;",
|
|
140
|
+
" [key: string]: unknown;",
|
|
141
|
+
"}",
|
|
142
|
+
"",
|
|
143
|
+
"/** 设计变更集(design.changeset/1.0 输入,兼容历史值 design-changeset/v1) */",
|
|
144
|
+
"export interface DesignChangeset {",
|
|
145
|
+
" schema: 'design.changeset/1.0' | 'design-changeset/v1';",
|
|
146
|
+
" mapping_version?: string;",
|
|
147
|
+
" scene: string;",
|
|
148
|
+
" layout_type?: string;",
|
|
149
|
+
" global?: Record<string, Record<string, string | number>>;",
|
|
150
|
+
" changes: Array<{",
|
|
151
|
+
" id: string;",
|
|
152
|
+
" visible?: boolean;",
|
|
153
|
+
" position?: Record<string, string>;",
|
|
154
|
+
" form?: string;",
|
|
155
|
+
" style?: Record<string, string | number>;",
|
|
156
|
+
" }>;",
|
|
157
|
+
"}",
|
|
158
|
+
"",
|
|
159
|
+
];
|
|
160
|
+
|
|
161
|
+
if (!dry) {
|
|
162
|
+
mkdirSync(outDir, { recursive: true });
|
|
163
|
+
writeFileSync(path.join(outDir, "theme.css"), cssLines.join("\n"), "utf-8");
|
|
164
|
+
writeFileSync(path.join(outDir, "theme-vars.ts"), tsLines.join("\n"), "utf-8");
|
|
165
|
+
writeFileSync(path.join(outDir, "theme-vars.js"), jsLines.join("\n"), "utf-8");
|
|
166
|
+
writeFileSync(path.join(outDir, "mapping-type.d.ts"), dtsLines.join("\n"), "utf-8");
|
|
167
|
+
written.push("theme.css", "theme-vars.ts", "theme-vars.js", "mapping-type.d.ts");
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
written.push("theme.css", "theme-vars.ts", "theme-vars.js", "mapping-type.d.ts");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return { written, tokenCount: tokens.length };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function toCamel(s) {
|
|
177
|
+
return s.replaceAll(/[_-](\w)/g, (_, c) => c.toUpperCase());
|
|
178
|
+
}
|