@linkdesk/plugin-sdk 0.1.0 → 0.1.2
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/README.md +21 -0
- package/dist/bin.js +12 -0
- package/dist/bin.js.map +1 -1
- package/dist/eslint/checks/css-hardcode.d.ts +14 -0
- package/dist/eslint/checks/css-hardcode.d.ts.map +1 -0
- package/dist/eslint/checks/css-hardcode.js +87 -0
- package/dist/eslint/checks/css-hardcode.js.map +1 -0
- package/dist/eslint/checks/disable.d.ts +29 -0
- package/dist/eslint/checks/disable.d.ts.map +1 -0
- package/dist/eslint/checks/disable.js +151 -0
- package/dist/eslint/checks/disable.js.map +1 -0
- package/dist/eslint/checks/font-scale.d.ts +19 -0
- package/dist/eslint/checks/font-scale.d.ts.map +1 -0
- package/dist/eslint/checks/font-scale.js +127 -0
- package/dist/eslint/checks/font-scale.js.map +1 -0
- package/dist/eslint/checks/scan.d.ts +20 -0
- package/dist/eslint/checks/scan.d.ts.map +1 -0
- package/dist/eslint/checks/scan.js +63 -0
- package/dist/eslint/checks/scan.js.map +1 -0
- package/dist/eslint/checks/spacing-grid.d.ts +14 -0
- package/dist/eslint/checks/spacing-grid.d.ts.map +1 -0
- package/dist/eslint/checks/spacing-grid.js +54 -0
- package/dist/eslint/checks/spacing-grid.js.map +1 -0
- package/dist/eslint/index.d.ts +15 -0
- package/dist/eslint/index.d.ts.map +1 -0
- package/dist/eslint/index.js +13 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/lint.d.ts +26 -0
- package/dist/eslint/lint.d.ts.map +1 -0
- package/dist/eslint/lint.js +112 -0
- package/dist/eslint/lint.js.map +1 -0
- package/dist/eslint/preset.d.ts +11 -0
- package/dist/eslint/preset.d.ts.map +1 -0
- package/dist/eslint/preset.js +88 -0
- package/dist/eslint/preset.js.map +1 -0
- package/dist/eslint/rules.d.ts +28 -0
- package/dist/eslint/rules.d.ts.map +1 -0
- package/dist/eslint/rules.js +441 -0
- package/dist/eslint/rules.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/validate.d.ts +9 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +88 -24
- package/dist/validate.js.map +1 -1
- package/dist/vite-config.d.ts +29 -8
- package/dist/vite-config.d.ts.map +1 -1
- package/dist/vite-config.js +377 -67
- package/dist/vite-config.js.map +1 -1
- package/package.json +20 -3
- package/schemas/icon-theme.schema.json +97 -0
- package/schemas/plugin.schema.json +696 -687
- package/schemas/theme.schema.json +109 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════
|
|
2
|
+
// 1. async 初始化函数 _initialized guard 必须配 _loadingPromise
|
|
3
|
+
// (壳 #59c 教训:StrictMode 双重 effect 竞态)
|
|
4
|
+
// ═══════════════════════════════════════════════════════════
|
|
5
|
+
export const noAsyncInitGuardOnly = {
|
|
6
|
+
meta: {
|
|
7
|
+
type: "problem",
|
|
8
|
+
docs: {
|
|
9
|
+
description: "async 初始化函数只设 _initialized guard 不够——必须配 _loadingPromise 防 StrictMode 双重 effect 竞态(第二次调用须返回进行中的 Promise)",
|
|
10
|
+
recommended: true,
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
noLoadingPromise: "async init 函数 {{name}} 在 await 前设 _initialized=true,未返回 _loadingPromise。" +
|
|
14
|
+
" StrictMode 双重 effect 第二次调用会跳过加载,但后续初始化操作可能尚未就绪(隐形竞态)。" +
|
|
15
|
+
" 修复:if (_initialized) return _loadingPromise ?? Promise.resolve(); return (_loadingPromise = (async () => { ... })());",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
create(context) {
|
|
19
|
+
let initializedSet = false;
|
|
20
|
+
let hasAwaitAfter = false;
|
|
21
|
+
let hasLoadingPromise = false;
|
|
22
|
+
let functionName = "";
|
|
23
|
+
return {
|
|
24
|
+
":matches(FunctionDeclaration, FunctionExpression, ArrowFunctionExpression)[async=true]"(node) {
|
|
25
|
+
initializedSet = false;
|
|
26
|
+
hasAwaitAfter = false;
|
|
27
|
+
hasLoadingPromise = false;
|
|
28
|
+
functionName = (node.id && node.id.name) || "";
|
|
29
|
+
},
|
|
30
|
+
"AssignmentExpression[left.type='Identifier'][left.name='_initialized']"(node) {
|
|
31
|
+
if (node.right && node.right.value === true) {
|
|
32
|
+
initializedSet = true;
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"Identifier[name='_loadingPromise']"() {
|
|
36
|
+
hasLoadingPromise = true;
|
|
37
|
+
},
|
|
38
|
+
AwaitExpression() {
|
|
39
|
+
if (initializedSet) {
|
|
40
|
+
hasAwaitAfter = true;
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
":matches(FunctionDeclaration, FunctionExpression, ArrowFunctionExpression)[async=true]:exit"(node) {
|
|
44
|
+
if (initializedSet && hasAwaitAfter && !hasLoadingPromise) {
|
|
45
|
+
context.report({
|
|
46
|
+
node,
|
|
47
|
+
messageId: "noLoadingPromise",
|
|
48
|
+
data: { name: functionName || "(anonymous)" },
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
initializedSet = false;
|
|
52
|
+
hasAwaitAfter = false;
|
|
53
|
+
hasLoadingPromise = false;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
// ═══════════════════════════════════════════════════════════
|
|
59
|
+
// 2. useEffect 依赖回调 prop 但缺活跃守卫(壳 #59c 教训)
|
|
60
|
+
// 组件 return null 不代表 effect 不跑——React effect 只看挂载不看 DOM。
|
|
61
|
+
// ═══════════════════════════════════════════════════════════
|
|
62
|
+
export const noEffectCallbackWithoutActiveGuard = {
|
|
63
|
+
meta: {
|
|
64
|
+
type: "problem",
|
|
65
|
+
docs: {
|
|
66
|
+
description: "useEffect 依赖回调 prop(onChange/onHighlight/onSelect/onApply)但缺 if (!open)/if (!isActive) 活跃守卫——组件 return null 时 effect 照跑",
|
|
67
|
+
recommended: true,
|
|
68
|
+
},
|
|
69
|
+
messages: {
|
|
70
|
+
missingGuard: "useEffect 依赖了回调 prop (onChange/onHighlight/onSelect/onApply),但没有 if (!open) 或 if (!isActive) 活跃守卫。" +
|
|
71
|
+
" 组件 return null 时 React effect 照跑——回调可能意外触发全局副作用。" +
|
|
72
|
+
" 修复:effect 顶部加 if (!open) return; 并把 open/isActive 纳入依赖数组。",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
create(context) {
|
|
76
|
+
const CALLBACK_PROP_PATTERN = /^on(Change|Highlight|Select|Apply|Close|Toggle|Submit)$/;
|
|
77
|
+
return {
|
|
78
|
+
CallExpression(node) {
|
|
79
|
+
if (node.callee?.type !== "Identifier" || node.callee.name !== "useEffect")
|
|
80
|
+
return;
|
|
81
|
+
const args = node.arguments;
|
|
82
|
+
if (args.length < 2)
|
|
83
|
+
return;
|
|
84
|
+
const depsArg = args[1];
|
|
85
|
+
if (!depsArg || depsArg.type !== "ArrayExpression")
|
|
86
|
+
return;
|
|
87
|
+
const body = args[0];
|
|
88
|
+
if (!body || (body.type !== "ArrowFunctionExpression" && body.type !== "FunctionExpression"))
|
|
89
|
+
return;
|
|
90
|
+
const callbackDeps = depsArg.elements.filter((el) => {
|
|
91
|
+
if (!el || el.type !== "Identifier")
|
|
92
|
+
return false;
|
|
93
|
+
return CALLBACK_PROP_PATTERN.test(el.name);
|
|
94
|
+
});
|
|
95
|
+
if (callbackDeps.length === 0)
|
|
96
|
+
return;
|
|
97
|
+
const bodyText = context.getSourceCode().getText(body);
|
|
98
|
+
const hasActiveGuard = /\bif\s*\(\s*!\s*(?:open|isActive|active|visible|enabled)\s*\)/.test(bodyText);
|
|
99
|
+
if (hasActiveGuard)
|
|
100
|
+
return;
|
|
101
|
+
context.report({ node, messageId: "missingGuard" });
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
// ═══════════════════════════════════════════════════════════
|
|
107
|
+
// 3. useEffect/useCallback cleanup 禁止动态 import()(壳 #36k2 教训)
|
|
108
|
+
// import() 异步在 StrictMode 重挂载后 resolve → 误删新注册数据
|
|
109
|
+
// ═══════════════════════════════════════════════════════════
|
|
110
|
+
const AST_CHILD_KEYS = new Set([
|
|
111
|
+
"body", "expression", "argument", "callee", "alternate", "consequent",
|
|
112
|
+
"test", "init", "left", "right", "object", "property", "elements",
|
|
113
|
+
"declarations", "params", "id", "handler", "finalizer",
|
|
114
|
+
]);
|
|
115
|
+
function hasDynamicImport(node, context, depth = 0) {
|
|
116
|
+
if (!node || depth > 20)
|
|
117
|
+
return false;
|
|
118
|
+
if (node.type === "CallExpression" && node.callee?.type === "Import") {
|
|
119
|
+
context.report({ node, messageId: "dynamicImport" });
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
for (const key of AST_CHILD_KEYS) {
|
|
123
|
+
const child = node[key];
|
|
124
|
+
if (!child)
|
|
125
|
+
continue;
|
|
126
|
+
if (Array.isArray(child)) {
|
|
127
|
+
for (const item of child) {
|
|
128
|
+
if (item && typeof item.type === "string" && hasDynamicImport(item, context, depth + 1))
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else if (typeof child.type === "string" && hasDynamicImport(child, context, depth + 1)) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
export const noDynamicImportInEffectCleanup = {
|
|
139
|
+
meta: {
|
|
140
|
+
type: "problem",
|
|
141
|
+
docs: {
|
|
142
|
+
description: "useEffect/useCallback cleanup 禁止动态 import()——异步执行在 StrictMode 重挂载后误删新数据",
|
|
143
|
+
recommended: true,
|
|
144
|
+
},
|
|
145
|
+
messages: {
|
|
146
|
+
dynamicImport: "useEffect/useCallback cleanup 中禁止动态 import()。" +
|
|
147
|
+
" import() 异步执行——React StrictMode 会先 unmount(触发此 cleanup)再 mount(重新注册)," +
|
|
148
|
+
" 异步 import 在 mount 之后才 resolve → 把新注册的数据也删了。" +
|
|
149
|
+
" 修复:改成文件顶部静态 import。",
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
create(context) {
|
|
153
|
+
return {
|
|
154
|
+
CallExpression(node) {
|
|
155
|
+
if (node.callee?.type !== "Identifier")
|
|
156
|
+
return;
|
|
157
|
+
if (node.callee.name !== "useEffect" && node.callee.name !== "useCallback")
|
|
158
|
+
return;
|
|
159
|
+
const args = node.arguments;
|
|
160
|
+
if (args.length === 0)
|
|
161
|
+
return;
|
|
162
|
+
const body = args[0];
|
|
163
|
+
if (!body || (body.type !== "ArrowFunctionExpression" && body.type !== "FunctionExpression"))
|
|
164
|
+
return;
|
|
165
|
+
const bodyNode = body.body;
|
|
166
|
+
if (!bodyNode)
|
|
167
|
+
return;
|
|
168
|
+
if (bodyNode.type === "CallExpression") {
|
|
169
|
+
if (bodyNode.callee?.type === "Import")
|
|
170
|
+
context.report({ node: bodyNode, messageId: "dynamicImport" });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (bodyNode.type !== "BlockStatement")
|
|
174
|
+
return;
|
|
175
|
+
for (const stmt of bodyNode.body) {
|
|
176
|
+
if (stmt.type !== "ReturnStatement" || !stmt.argument)
|
|
177
|
+
continue;
|
|
178
|
+
hasDynamicImport(stmt.argument, context);
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
// ═══════════════════════════════════════════════════════════
|
|
185
|
+
// 4. JSX 中禁止 ref.current 参与渲染(壳 #58e 教训)
|
|
186
|
+
// ref 更新不触发重渲染 → UI 与实际状态脱节。渲染决策走 useState。
|
|
187
|
+
// ═══════════════════════════════════════════════════════════
|
|
188
|
+
export const noRefCurrentInJsx = {
|
|
189
|
+
meta: {
|
|
190
|
+
type: "problem",
|
|
191
|
+
docs: {
|
|
192
|
+
description: "JSX 中禁止 ref.current 直接参与渲染——ref 更新不触发 React 重渲染",
|
|
193
|
+
recommended: true,
|
|
194
|
+
},
|
|
195
|
+
messages: {
|
|
196
|
+
noRefCurrent: "JSX 中禁止 {{name}}.current——ref 更新不触发 React 重渲染。" +
|
|
197
|
+
" 异步拿到数据 → ref 更新 → 组件不知道 → 下次任何事件触发重渲染时突然切状态 → UI 跳变/空白。" +
|
|
198
|
+
" 修复:改用 useState。ref 仅用于 DOM 引用/前值对比/generation counter。",
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
create(context) {
|
|
202
|
+
return {
|
|
203
|
+
"JSXExpressionContainer > MemberExpression[property.name='current']"(node) {
|
|
204
|
+
const objectName = node.object?.type === "Identifier" ? node.object.name : "?";
|
|
205
|
+
context.report({ node, messageId: "noRefCurrent", data: { name: objectName } });
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
// ═══════════════════════════════════════════════════════════
|
|
211
|
+
// 5. JSX/UI 中文字面量必须走 t()(壳 no-hardcoded-chinese 同逻辑;门禁名 = no-hardcoded-zh)
|
|
212
|
+
// UI 文案硬编码中文 → i18n 遗漏。注释/console/测试文件不拦。
|
|
213
|
+
// ═══════════════════════════════════════════════════════════
|
|
214
|
+
const CHINESE_RE = /[㐀-鿿]/;
|
|
215
|
+
function hasChinese(text) {
|
|
216
|
+
return CHINESE_RE.test(text);
|
|
217
|
+
}
|
|
218
|
+
function isInsideTranslationCall(node) {
|
|
219
|
+
let cur = node.parent;
|
|
220
|
+
while (cur) {
|
|
221
|
+
if (cur.type === "CallExpression") {
|
|
222
|
+
const callee = cur.callee;
|
|
223
|
+
if (callee.type === "Identifier" && (callee.name === "t" || callee.name === "i18n"))
|
|
224
|
+
return true;
|
|
225
|
+
if (callee.type === "MemberExpression" &&
|
|
226
|
+
callee.object?.type === "Identifier" &&
|
|
227
|
+
callee.object.name === "i18n" &&
|
|
228
|
+
callee.property?.type === "Identifier" &&
|
|
229
|
+
callee.property.name === "t")
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
if (cur.type === "JSXExpressionContainer" || cur.type === "JSXAttribute")
|
|
233
|
+
break;
|
|
234
|
+
cur = cur.parent;
|
|
235
|
+
}
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
/** 字面量是否落在 JSX 表达式上下文——向上穿透三元/逻辑链(盲区:placeholder={cond ? "中文" : "…"}) */
|
|
239
|
+
function isInJsxContext(node) {
|
|
240
|
+
let cur = node.parent;
|
|
241
|
+
while (cur) {
|
|
242
|
+
if (cur.type === "JSXExpressionContainer" || cur.type === "JSXAttribute")
|
|
243
|
+
return true;
|
|
244
|
+
if (cur.type === "ConditionalExpression" || cur.type === "LogicalExpression") {
|
|
245
|
+
cur = cur.parent;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
export const noHardcodedZh = {
|
|
253
|
+
meta: {
|
|
254
|
+
type: "suggestion",
|
|
255
|
+
docs: {
|
|
256
|
+
description: "JSX/UI 中的中文字面量必须走 t() 包裹——防 i18n 遗漏(UI 文字全走 t() 硬约束)",
|
|
257
|
+
recommended: true,
|
|
258
|
+
},
|
|
259
|
+
messages: {
|
|
260
|
+
noZh: "UI 文案中文字面量 \"{{text}}\" 未用 t() 包裹。" +
|
|
261
|
+
" 修复:<span>{t(\"中文\")}</span> 或 placeholder={t(\"中文\")},文案进 i18n 资源。" +
|
|
262
|
+
" 注释/console/测试文件可忽略。",
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
create(context) {
|
|
266
|
+
return {
|
|
267
|
+
JSXText(node) {
|
|
268
|
+
const text = node.value.trim();
|
|
269
|
+
if (!text || !hasChinese(text))
|
|
270
|
+
return;
|
|
271
|
+
context.report({ node, messageId: "noZh", data: { text: text.slice(0, 20) } });
|
|
272
|
+
},
|
|
273
|
+
Literal(node) {
|
|
274
|
+
if (typeof node.value !== "string" || !hasChinese(node.value))
|
|
275
|
+
return;
|
|
276
|
+
if (isInsideTranslationCall(node))
|
|
277
|
+
return;
|
|
278
|
+
if (isInJsxContext(node)) {
|
|
279
|
+
context.report({ node, messageId: "noZh", data: { text: node.value.slice(0, 20) } });
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
TemplateLiteral(node) {
|
|
283
|
+
if (node.quasis.length === 1 && hasChinese(node.quasis[0].value.raw)) {
|
|
284
|
+
if (isInsideTranslationCall(node))
|
|
285
|
+
return;
|
|
286
|
+
if (isInJsxContext(node)) {
|
|
287
|
+
context.report({ node, messageId: "noZh", data: { text: node.quasis[0].value.raw.slice(0, 20) } });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
// ═══════════════════════════════════════════════════════════
|
|
295
|
+
// 6. 颜色禁止硬编码 hex——走 CSS 变量 var(--xxx)(壳 no-hardcoded-hex 同逻辑)
|
|
296
|
+
// var(--x, #hex) 回退值合规;取色器色板/canvas/测试/i18n 数据豁免;
|
|
297
|
+
// 内容画布(游戏/数据可视化主区)走文件级 /* eslint-disable linkdesk/no-hardcoded-hex -- 内容画布 */
|
|
298
|
+
// ——标准注释即批量知情绕行(07 §七·2)。
|
|
299
|
+
// ═══════════════════════════════════════════════════════════
|
|
300
|
+
const HEX_RE = /#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/;
|
|
301
|
+
const CSS_VAR_FALLBACK_RE = /var\(/;
|
|
302
|
+
export const noHardcodedHex = {
|
|
303
|
+
meta: {
|
|
304
|
+
type: "problem",
|
|
305
|
+
docs: {
|
|
306
|
+
description: "颜色禁止硬编码 hex——走 CSS 变量 var(--xxx)(var(--*)/t() 零警告,主题/玻璃自动跟随)",
|
|
307
|
+
recommended: true,
|
|
308
|
+
},
|
|
309
|
+
messages: {
|
|
310
|
+
noHex: "颜色硬编码 hex \"{{text}}\" 未走 CSS 变量。" +
|
|
311
|
+
" 修复:color/background 用 var(--text-*/--bg-*/--accent-*/--surface-*) → 自动跟随主题+玻璃。" +
|
|
312
|
+
" 若是默认色数据/取色器色板/canvas 绘图,加 `// eslint-disable-next-line linkdesk/no-hardcoded-hex -- 理由` 并注明豁免类别。" +
|
|
313
|
+
" 内容画布(游戏/数据可视化主区)用文件级 `/* eslint-disable linkdesk/no-hardcoded-hex -- 内容画布 */`。",
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
create(context) {
|
|
317
|
+
const filename = (context.getFilename?.() ?? "").replace(/\\/g, "/");
|
|
318
|
+
const isExemptFile = /\.(test|spec)\.(ts|tsx)$/.test(filename) ||
|
|
319
|
+
/mock/i.test(filename) ||
|
|
320
|
+
/\/themes?\//.test(filename) ||
|
|
321
|
+
/\/i18n\//.test(filename) ||
|
|
322
|
+
/\/color-picker\//.test(filename) ||
|
|
323
|
+
/canvas/i.test(filename);
|
|
324
|
+
return {
|
|
325
|
+
Literal(node) {
|
|
326
|
+
if (typeof node.value !== "string")
|
|
327
|
+
return;
|
|
328
|
+
if (isExemptFile)
|
|
329
|
+
return;
|
|
330
|
+
if (!HEX_RE.test(node.value))
|
|
331
|
+
return;
|
|
332
|
+
if (CSS_VAR_FALLBACK_RE.test(node.value))
|
|
333
|
+
return;
|
|
334
|
+
context.report({ node, messageId: "noHex", data: { text: node.value.slice(0, 20) } });
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
// ═══════════════════════════════════════════════════════════
|
|
340
|
+
// 7. 禁止裸 px 圆角(新写)——border-radius 走 var(--radius-*) / var(--surface-radius)
|
|
341
|
+
// React style={{ borderRadius: 8 }}(数字=px)或 borderRadius: "8px" → 用 var() 字符串。
|
|
342
|
+
// 内容画布豁免同上(文件级 disable)。CSS 文件里的 border-radius 由 token 契约文档引导
|
|
343
|
+
// (eslint 不扫 .css——契约域,07 §六「不设门禁的域」同精神)。
|
|
344
|
+
// ═══════════════════════════════════════════════════════════
|
|
345
|
+
const PX_STRING_RE = /^(\d+(?:\.\d+)?)px$/;
|
|
346
|
+
export const noHardcodedRadius = {
|
|
347
|
+
meta: {
|
|
348
|
+
type: "problem",
|
|
349
|
+
docs: {
|
|
350
|
+
description: "禁止裸 px 圆角——border-radius 走 var(--radius-*) / var(--surface-radius) 跟随圆角滑杆",
|
|
351
|
+
recommended: true,
|
|
352
|
+
},
|
|
353
|
+
messages: {
|
|
354
|
+
noRadius: "borderRadius 硬编码 {{value}} 未走 CSS 变量。" +
|
|
355
|
+
" 修复:border-radius: var(--radius-md) 或 var(--surface-radius) → 自动跟随全局圆角滑杆。" +
|
|
356
|
+
" 内容画布(游戏/数据可视化)用文件级 `/* eslint-disable linkdesk/no-hardcoded-radius -- 内容画布 */`。",
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
create(context) {
|
|
360
|
+
const filename = (context.getFilename?.() ?? "").replace(/\\/g, "/");
|
|
361
|
+
const isExemptFile = /\.(test|spec)\.(ts|tsx)$/.test(filename) || /canvas/i.test(filename);
|
|
362
|
+
return {
|
|
363
|
+
JSXAttribute(node) {
|
|
364
|
+
if (isExemptFile)
|
|
365
|
+
return;
|
|
366
|
+
// 只查 style={{ ... }} 的 JSX 表达式对象
|
|
367
|
+
if (node.name?.type !== "JSXIdentifier" || node.name.name !== "style")
|
|
368
|
+
return;
|
|
369
|
+
const val = node.value;
|
|
370
|
+
if (!val || val.type !== "JSXExpressionContainer" || !val.expression)
|
|
371
|
+
return;
|
|
372
|
+
const expr = val.expression;
|
|
373
|
+
if (expr.type !== "ObjectExpression")
|
|
374
|
+
return;
|
|
375
|
+
for (const prop of expr.properties) {
|
|
376
|
+
if (prop.type !== "Property")
|
|
377
|
+
continue;
|
|
378
|
+
const key = prop.key;
|
|
379
|
+
if (!key || (key.type !== "Identifier" && key.type !== "Literal"))
|
|
380
|
+
continue;
|
|
381
|
+
const keyName = key.type === "Identifier" ? key.name : String(key.value);
|
|
382
|
+
if (keyName !== "borderRadius")
|
|
383
|
+
continue;
|
|
384
|
+
const v = prop.value;
|
|
385
|
+
if (v && v.type === "Literal") {
|
|
386
|
+
if (typeof v.value === "number" || (typeof v.value === "string" && PX_STRING_RE.test(v.value))) {
|
|
387
|
+
context.report({ node: v, messageId: "noRadius", data: { value: String(v.value) } });
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
// ═══════════════════════════════════════════════════════════
|
|
396
|
+
// 8. QuickPick 禁止 renderItem(壳同规则)——@linkdesk/ui 控件用 slot props 保视觉统一
|
|
397
|
+
// ═══════════════════════════════════════════════════════════
|
|
398
|
+
export const noQuickpickRenderItem = {
|
|
399
|
+
meta: {
|
|
400
|
+
type: "problem",
|
|
401
|
+
docs: {
|
|
402
|
+
description: "QuickPick 禁止 renderItem——用 structured slot props 保面板视觉统一",
|
|
403
|
+
recommended: true,
|
|
404
|
+
},
|
|
405
|
+
messages: {
|
|
406
|
+
noRenderItem: "QuickPick renderItem 已废弃——自由度过高导致面板视觉不统一。" +
|
|
407
|
+
" 改用 slot props:renderLabel / renderCategory / renderDetail / renderDetailRight。",
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
create(context) {
|
|
411
|
+
return {
|
|
412
|
+
JSXElement(node) {
|
|
413
|
+
const tagName = node.openingElement?.name;
|
|
414
|
+
if (!tagName || tagName.type !== "Identifier" || tagName.name !== "QuickPick")
|
|
415
|
+
return;
|
|
416
|
+
for (const attr of node.openingElement.attributes || []) {
|
|
417
|
+
if (attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier" && attr.name.name === "renderItem") {
|
|
418
|
+
context.report({ node: attr, messageId: "noRenderItem" });
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
};
|
|
424
|
+
},
|
|
425
|
+
};
|
|
426
|
+
// ═══════════════════════════════════════════════════════════
|
|
427
|
+
// 注册映射——kebab 键 = 配置规则 id 的 ruleName 部分。
|
|
428
|
+
// eslint 按原样名查 plugin.rules(config.js parseRuleId 后直查,无 camel 转换),
|
|
429
|
+
// 故键必须与 preset 里 `linkdesk/<rule>` 的破折号名一致(壳 export default 同款)。
|
|
430
|
+
// ═══════════════════════════════════════════════════════════
|
|
431
|
+
export const linkdeskRuleMap = {
|
|
432
|
+
"no-async-init-guard-only": noAsyncInitGuardOnly,
|
|
433
|
+
"no-effect-callback-without-active-guard": noEffectCallbackWithoutActiveGuard,
|
|
434
|
+
"no-dynamic-import-in-effect-cleanup": noDynamicImportInEffectCleanup,
|
|
435
|
+
"no-ref-current-in-jsx": noRefCurrentInJsx,
|
|
436
|
+
"no-hardcoded-zh": noHardcodedZh,
|
|
437
|
+
"no-hardcoded-hex": noHardcodedHex,
|
|
438
|
+
"no-hardcoded-radius": noHardcodedRadius,
|
|
439
|
+
"no-quickpick-render-item": noQuickpickRenderItem,
|
|
440
|
+
};
|
|
441
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/eslint/rules.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @linkdesk/plugin-sdk 公共出口(barrel)。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 运行面:`defineLinkdeskPluginConfig()`(构建)+ validate 家族(plugin.json / 主题数据 / 图标主题数据;
|
|
5
|
+
* E6#60 起主题/图标作者也走 npm 通道——validateThemeJson / validateIconThemeJson);
|
|
5
6
|
* 类型面经 types.js 全量转发 @linkdesk/contracts(window.linkdesk.* 全局声明随契约进 program,E6#2b)。
|
|
6
7
|
* validate 的内部 helper(collectI18nDecls/derivePluginId/SAFE_PLUGIN_ID 等)供 vite-config/packager
|
|
7
8
|
* 跨模块复用,但**不进 barrel**——公共 API 面保持最小(对标 @types/vscode 只给类型+工具)。
|
|
@@ -9,6 +10,7 @@
|
|
|
9
10
|
export { defineLinkdeskPluginConfig } from "./vite-config.js";
|
|
10
11
|
export type { LinkdeskPluginOptions } from "./vite-config.js";
|
|
11
12
|
export { validatePluginJson } from "./validate.js";
|
|
13
|
+
export { validateThemeJson, validateIconThemeJson } from "./validate.js";
|
|
12
14
|
export type { ValidationResult } from "./validate.js";
|
|
13
15
|
export type * from "./types.js";
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACzE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,mBAAmB,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @linkdesk/plugin-sdk 公共出口(barrel)。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 运行面:`defineLinkdeskPluginConfig()`(构建)+ validate 家族(plugin.json / 主题数据 / 图标主题数据;
|
|
5
|
+
* E6#60 起主题/图标作者也走 npm 通道——validateThemeJson / validateIconThemeJson);
|
|
5
6
|
* 类型面经 types.js 全量转发 @linkdesk/contracts(window.linkdesk.* 全局声明随契约进 program,E6#2b)。
|
|
6
7
|
* validate 的内部 helper(collectI18nDecls/derivePluginId/SAFE_PLUGIN_ID 等)供 vite-config/packager
|
|
7
8
|
* 跨模块复用,但**不进 barrel**——公共 API 面保持最小(对标 @types/vscode 只给类型+工具)。
|
|
8
9
|
*/
|
|
9
10
|
export { defineLinkdeskPluginConfig } from "./vite-config.js";
|
|
10
11
|
export { validatePluginJson } from "./validate.js";
|
|
12
|
+
export { validateThemeJson, validateIconThemeJson } from "./validate.js";
|
|
11
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/validate.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* 作者面 schema 验证工具(E6#5 立 plugin.json;E6#60 扩 theme/icon 数据文件)。
|
|
3
|
+
* - validatePluginJson(plugin.schema.json,2020-12)——jsonc 解析 + JSON Schema + i18n 文件存在性。
|
|
4
|
+
* - validateThemeJson / validateIconThemeJson(theme.schema.json draft-07 / icon-theme.schema.json 2020-12)——
|
|
5
|
+
* E6#60 主题/图标作者数据文件校验,镜像 scripts/check-theme-schema.mjs 同规则(同一 schema 文件编译,永不漂移)。
|
|
6
|
+
* 纯逻辑、无 vite import——validatePluginJson 与 bin / defineLinkdeskPluginConfig 三方共用。
|
|
4
7
|
*
|
|
5
8
|
* 设计裁决:
|
|
6
9
|
* - **解析走 jsonc-parser**(对齐壳 E6#55)——作者 plugin.json 可写注释/尾逗号(对标 VS Code
|
|
@@ -50,4 +53,8 @@ export declare function isWithinRoot(root: string, target: string): boolean;
|
|
|
50
53
|
* 顺序:读文件 → jsonc 语法 → schema 全量 → i18n 文件存在性(schema 干净才查第二类,防噪音)。
|
|
51
54
|
*/
|
|
52
55
|
export declare function validatePluginJson(path: string): ValidationResult;
|
|
56
|
+
/** 校验主题数据 JSON 文件(对照 theme.schema.json draft-07——E5.8#129,引擎 parseThemeRecipe 消费格式) */
|
|
57
|
+
export declare function validateThemeJson(path: string): ValidationResult;
|
|
58
|
+
/** 校验图标主题 mappings JSON 文件(对照 icon-theme.schema.json 2020-12——E5.8#133 / E6#60 实收格式,引擎 normalizeIconThemeMappings 消费) */
|
|
59
|
+
export declare function validateIconThemeJson(path: string): ValidationResult;
|
|
53
60
|
//# sourceMappingURL=validate.d.ts.map
|
package/dist/validate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAiBH;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAiC,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,+DAA+D;AAC/D,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,EAAE,CAc9D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAkB/E;AAED,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWxD;AA+FD,oDAAoD;AACpD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAiCjE;AA8BD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAEhE;AAED,yHAAyH;AACzH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAEpE"}
|