@weapp-vite/eslint 0.2.2 → 0.2.3
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 +20 -1
- package/dist/index.d.mts +40 -1
- package/dist/index.mjs +237 -14
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @weapp-vite/eslint
|
|
2
2
|
|
|
3
|
-
`@weapp-vite/eslint` 提供 Wevu
|
|
3
|
+
`@weapp-vite/eslint` 提供 Wevu 兼容性和小程序 AppService 宿主 API 静态检查规则。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -12,12 +12,14 @@ pnpm add -D @weapp-vite/eslint eslint
|
|
|
12
12
|
|
|
13
13
|
```js
|
|
14
14
|
import {
|
|
15
|
+
miniProgramRuntimeRecommended,
|
|
15
16
|
wevuCompatibilityPlugin,
|
|
16
17
|
wevuCompatibilityRecommended,
|
|
17
18
|
} from '@weapp-vite/eslint'
|
|
18
19
|
import { defineConfig } from 'eslint/config'
|
|
19
20
|
|
|
20
21
|
export default defineConfig([
|
|
22
|
+
miniProgramRuntimeRecommended,
|
|
21
23
|
wevuCompatibilityRecommended,
|
|
22
24
|
{
|
|
23
25
|
plugins: {
|
|
@@ -33,6 +35,23 @@ export default defineConfig([
|
|
|
33
35
|
- `wevu/no-risky-api`:警告同名但参数、时序或宿主语义不同的 API。
|
|
34
36
|
- `wevu/no-unsupported-template-feature`:只对能追溯到 `vue-router` 导入的 `RouterLink` 模板能力报错。
|
|
35
37
|
|
|
38
|
+
`miniProgramRuntimeRecommended` 另外提供:
|
|
39
|
+
|
|
40
|
+
- `mini-program/no-unsupported-runtime-api`:禁止 DOM/Node 全局和超出 ES2018 小程序兼容基线的现代内建。
|
|
41
|
+
- `mini-program/no-implicit-runtime-polyfill`:警告 `queueMicrotask`、`fetch`、`URL`、`AbortController` 等不能依赖宿主隐式提供的能力,并指向 `weapp.appPrelude.webRuntime` 或显式兼容层。
|
|
42
|
+
|
|
43
|
+
默认只匹配 `src/**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx,vue}`,排除 config、测试、脚本、Web-only、`dist` 和生成目录。需要自定义源码范围时使用:
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
import { createMiniProgramRuntimeConfig } from '@weapp-vite/eslint'
|
|
47
|
+
|
|
48
|
+
export default defineConfig([
|
|
49
|
+
createMiniProgramRuntimeConfig({ files: ['app/**/*.ts'] }),
|
|
50
|
+
])
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
局部变量、参数、import、类型位置和单纯的 `typeof` 能力探测不会报错。静态规则不能代替目标真机/IDE 验证;尤其不能假定所有微信基础库都提供 `queueMicrotask`。
|
|
54
|
+
|
|
36
55
|
规则只检查项目源码,不扫描 `node_modules`、构建产物或 `.weapp-vite` 生成文件。动态属性访问、第三方依赖内部代码和宿主运行时能力不在静态判定范围内。
|
|
37
56
|
|
|
38
57
|
兼容矩阵也从根入口导出:
|
package/dist/index.d.mts
CHANGED
|
@@ -27,6 +27,45 @@ interface WevuCompatibilityEntry {
|
|
|
27
27
|
declare const wevuCompatibilityCatalog: readonly WevuCompatibilityEntry[];
|
|
28
28
|
declare function findWevuCompatibilityEntry(upstream: WevuCompatibilityUpstream, api: string, surface?: WevuCompatibilitySurface): WevuCompatibilityEntry | undefined;
|
|
29
29
|
//#endregion
|
|
30
|
+
//#region src/miniProgramRuntime.d.ts
|
|
31
|
+
type MiniProgramRuntimeApiDiagnostic = 'off' | 'warn' | 'error';
|
|
32
|
+
type MiniProgramRuntimeApiKind = 'global' | 'static-method' | 'instance-method';
|
|
33
|
+
type MiniProgramRuntimeApiSupport = 'baseline' | 'polyfill-required' | 'unsupported';
|
|
34
|
+
interface MiniProgramRuntimeApiEntry {
|
|
35
|
+
api: string;
|
|
36
|
+
kind: MiniProgramRuntimeApiKind;
|
|
37
|
+
support: MiniProgramRuntimeApiSupport;
|
|
38
|
+
diagnostic: MiniProgramRuntimeApiDiagnostic;
|
|
39
|
+
platform: 'wechat';
|
|
40
|
+
replacement?: string;
|
|
41
|
+
summary: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 微信小程序 AppService 运行时能力清单。
|
|
45
|
+
*
|
|
46
|
+
* baseline 表示兼容基线可直接使用;polyfill-required 表示必须显式启用或调用
|
|
47
|
+
* weapp-vite 兼容层;unsupported 表示业务运行时代码不应依赖该能力。
|
|
48
|
+
*/
|
|
49
|
+
declare const miniProgramRuntimeApiCatalog: readonly MiniProgramRuntimeApiEntry[];
|
|
50
|
+
declare const miniProgramRuntimePlugin: {
|
|
51
|
+
meta: {
|
|
52
|
+
name: string;
|
|
53
|
+
version: string;
|
|
54
|
+
};
|
|
55
|
+
rules: {
|
|
56
|
+
'no-unsupported-runtime-api': Rule.RuleModule;
|
|
57
|
+
'no-implicit-runtime-polyfill': Rule.RuleModule;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
interface MiniProgramRuntimeConfigOptions {
|
|
61
|
+
files?: string[];
|
|
62
|
+
ignores?: string[];
|
|
63
|
+
}
|
|
64
|
+
declare const MINI_PROGRAM_RUNTIME_DEFAULT_FILES: string[];
|
|
65
|
+
declare const MINI_PROGRAM_RUNTIME_DEFAULT_IGNORES: string[];
|
|
66
|
+
declare function createMiniProgramRuntimeConfig(options?: MiniProgramRuntimeConfigOptions): Linter.Config;
|
|
67
|
+
declare const miniProgramRuntimeRecommended: Linter.Config;
|
|
68
|
+
//#endregion
|
|
30
69
|
//#region src/index.d.ts
|
|
31
70
|
declare const wevuCompatibilityPlugin: {
|
|
32
71
|
meta: {
|
|
@@ -41,4 +80,4 @@ declare const wevuCompatibilityPlugin: {
|
|
|
41
80
|
};
|
|
42
81
|
declare const wevuCompatibilityRecommended: Linter.Config;
|
|
43
82
|
//#endregion
|
|
44
|
-
export { type WevuCompatibilityDiagnostic, type WevuCompatibilityEntry, type WevuCompatibilityLevel, type WevuCompatibilitySurface, type WevuCompatibilityUpstream, findWevuCompatibilityEntry, wevuCompatibilityCatalog, wevuCompatibilityPlugin, wevuCompatibilityRecommended };
|
|
83
|
+
export { MINI_PROGRAM_RUNTIME_DEFAULT_FILES, MINI_PROGRAM_RUNTIME_DEFAULT_IGNORES, type MiniProgramRuntimeApiDiagnostic, type MiniProgramRuntimeApiEntry, type MiniProgramRuntimeApiKind, type MiniProgramRuntimeApiSupport, type MiniProgramRuntimeConfigOptions, type WevuCompatibilityDiagnostic, type WevuCompatibilityEntry, type WevuCompatibilityLevel, type WevuCompatibilitySurface, type WevuCompatibilityUpstream, createMiniProgramRuntimeConfig, findWevuCompatibilityEntry, miniProgramRuntimeApiCatalog, miniProgramRuntimePlugin, miniProgramRuntimeRecommended, wevuCompatibilityCatalog, wevuCompatibilityPlugin, wevuCompatibilityRecommended };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/compatibility.ts
|
|
2
|
-
const entry = (value) => value;
|
|
2
|
+
const entry$1 = (value) => value;
|
|
3
3
|
/**
|
|
4
4
|
* Wevu 与 Vue 生态的公开兼容真值。
|
|
5
5
|
*
|
|
@@ -57,7 +57,7 @@ const wevuCompatibilityCatalog = [
|
|
|
57
57
|
"createWebHashHistory",
|
|
58
58
|
"createRouter()"
|
|
59
59
|
]
|
|
60
|
-
].map(([upstream, api, replacement]) => entry({
|
|
60
|
+
].map(([upstream, api, replacement]) => entry$1({
|
|
61
61
|
upstream,
|
|
62
62
|
api,
|
|
63
63
|
wevuEntry: upstream === "vue-router" ? "wevu/router" : "wevu",
|
|
@@ -68,7 +68,7 @@ const wevuCompatibilityCatalog = [
|
|
|
68
68
|
docs: "/wevu/compatibility",
|
|
69
69
|
surfaces: ["runtime"]
|
|
70
70
|
})),
|
|
71
|
-
entry({
|
|
71
|
+
entry$1({
|
|
72
72
|
upstream: "vue",
|
|
73
73
|
api: "hasInjectionContext",
|
|
74
74
|
wevuEntry: "wevu",
|
|
@@ -78,7 +78,7 @@ const wevuCompatibilityCatalog = [
|
|
|
78
78
|
docs: "/wevu/api/setup-context#hasinjectioncontext",
|
|
79
79
|
surfaces: ["runtime"]
|
|
80
80
|
}),
|
|
81
|
-
entry({
|
|
81
|
+
entry$1({
|
|
82
82
|
upstream: "pinia",
|
|
83
83
|
api: "createPinia",
|
|
84
84
|
wevuEntry: "wevu/store",
|
|
@@ -89,7 +89,7 @@ const wevuCompatibilityCatalog = [
|
|
|
89
89
|
docs: "/wevu/api/store#createpinia",
|
|
90
90
|
surfaces: ["runtime"]
|
|
91
91
|
}),
|
|
92
|
-
entry({
|
|
92
|
+
entry$1({
|
|
93
93
|
upstream: "vue-router",
|
|
94
94
|
api: "RouterLink",
|
|
95
95
|
wevuEntry: "wevu/router",
|
|
@@ -100,7 +100,7 @@ const wevuCompatibilityCatalog = [
|
|
|
100
100
|
docs: "/wevu/api/router#routerlink",
|
|
101
101
|
surfaces: ["runtime", "template"]
|
|
102
102
|
}),
|
|
103
|
-
entry({
|
|
103
|
+
entry$1({
|
|
104
104
|
upstream: "vue-router",
|
|
105
105
|
api: "<router-link>",
|
|
106
106
|
wevuEntry: "wevu/router",
|
|
@@ -122,7 +122,7 @@ const wevuCompatibilityCatalog = [
|
|
|
122
122
|
["replace", "映射宿主 redirect/reLaunch/switchTab,而非 Web history replace。"],
|
|
123
123
|
["go", "仅支持负数回退;正数历史导航不可用。"],
|
|
124
124
|
["forward", "小程序没有正向历史栈。"]
|
|
125
|
-
].map(([api, summary]) => entry({
|
|
125
|
+
].map(([api, summary]) => entry$1({
|
|
126
126
|
upstream: "vue-router",
|
|
127
127
|
api,
|
|
128
128
|
wevuEntry: "wevu/router",
|
|
@@ -140,7 +140,7 @@ const wevuCompatibilityCatalog = [
|
|
|
140
140
|
["$onAction", "插件和 action 错误处理不提供完整 Pinia 上下文。"],
|
|
141
141
|
["install", "Store manager 的 install() 是 no-op。"],
|
|
142
142
|
["use", "插件上下文是 Wevu Store manager 契约,不等同 PiniaPluginContext。"]
|
|
143
|
-
].map(([api, summary]) => entry({
|
|
143
|
+
].map(([api, summary]) => entry$1({
|
|
144
144
|
upstream: "pinia",
|
|
145
145
|
api,
|
|
146
146
|
wevuEntry: "wevu/store",
|
|
@@ -158,7 +158,7 @@ const wevuCompatibilityCatalog = [
|
|
|
158
158
|
[":slotted()", "为 slot 投影节点生成独立 slotted scope 属性。"],
|
|
159
159
|
["CSS Modules", "支持默认 $style 和命名 module。"],
|
|
160
160
|
["useCssModule()", "只能在同步 setup 中读取当前 SFC 的 module 映射。"]
|
|
161
|
-
].map(([api, summary]) => entry({
|
|
161
|
+
].map(([api, summary]) => entry$1({
|
|
162
162
|
upstream: "vue",
|
|
163
163
|
api,
|
|
164
164
|
wevuEntry: api === "useCssModule()" ? "wevu" : "weapp-vite",
|
|
@@ -181,7 +181,7 @@ const wevuCompatibilityCatalog = [
|
|
|
181
181
|
["ObjectDirective", "只覆盖 Wevu 可编译或可桥接的指令钩子。"],
|
|
182
182
|
["ExtractPropTypes", "推导结果包含小程序 properties 归一化规则。"],
|
|
183
183
|
["ExtractPublicPropTypes", "公开 props 推导遵循 Wevu 组件构造类型。"]
|
|
184
|
-
].map(([api, summary]) => entry({
|
|
184
|
+
].map(([api, summary]) => entry$1({
|
|
185
185
|
upstream: "vue",
|
|
186
186
|
api,
|
|
187
187
|
wevuEntry: "wevu",
|
|
@@ -204,7 +204,7 @@ const wevuCompatibilityCatalog = [
|
|
|
204
204
|
"ToRefs",
|
|
205
205
|
"WritableComputedOptions",
|
|
206
206
|
"WritableComputedRef"
|
|
207
|
-
].map((api) => entry({
|
|
207
|
+
].map((api) => entry$1({
|
|
208
208
|
upstream: "vue",
|
|
209
209
|
api,
|
|
210
210
|
wevuEntry: "wevu",
|
|
@@ -231,7 +231,7 @@ const wevuCompatibilityCatalog = [
|
|
|
231
231
|
"ShallowUnwrapRef",
|
|
232
232
|
"TemplateRef",
|
|
233
233
|
"VNodeProps"
|
|
234
|
-
].map((api) => entry({
|
|
234
|
+
].map((api) => entry$1({
|
|
235
235
|
upstream: "vue",
|
|
236
236
|
api,
|
|
237
237
|
wevuEntry: "wevu",
|
|
@@ -249,7 +249,7 @@ const wevuCompatibilityCatalog = [
|
|
|
249
249
|
"WatchOptions",
|
|
250
250
|
"WatchSource",
|
|
251
251
|
"WatchStopHandle"
|
|
252
|
-
].map((api) => entry({
|
|
252
|
+
].map((api) => entry$1({
|
|
253
253
|
upstream: "vue",
|
|
254
254
|
api,
|
|
255
255
|
wevuEntry: "wevu",
|
|
@@ -264,6 +264,229 @@ function findWevuCompatibilityEntry(upstream, api, surface) {
|
|
|
264
264
|
return wevuCompatibilityCatalog.find((item) => item.upstream === upstream && item.api === api && (!surface || item.surfaces.includes(surface)));
|
|
265
265
|
}
|
|
266
266
|
//#endregion
|
|
267
|
+
//#region src/miniProgramRuntime.ts
|
|
268
|
+
const entry = (value) => value;
|
|
269
|
+
/**
|
|
270
|
+
* 微信小程序 AppService 运行时能力清单。
|
|
271
|
+
*
|
|
272
|
+
* baseline 表示兼容基线可直接使用;polyfill-required 表示必须显式启用或调用
|
|
273
|
+
* weapp-vite 兼容层;unsupported 表示业务运行时代码不应依赖该能力。
|
|
274
|
+
*/
|
|
275
|
+
const miniProgramRuntimeApiCatalog = [
|
|
276
|
+
...[
|
|
277
|
+
"fetch",
|
|
278
|
+
"Headers",
|
|
279
|
+
"Request",
|
|
280
|
+
"Response",
|
|
281
|
+
"AbortController",
|
|
282
|
+
"AbortSignal",
|
|
283
|
+
"XMLHttpRequest",
|
|
284
|
+
"WebSocket",
|
|
285
|
+
"URL",
|
|
286
|
+
"URLSearchParams",
|
|
287
|
+
"Blob",
|
|
288
|
+
"File",
|
|
289
|
+
"FormData",
|
|
290
|
+
"TextEncoder",
|
|
291
|
+
"TextDecoder",
|
|
292
|
+
"atob",
|
|
293
|
+
"btoa",
|
|
294
|
+
"performance",
|
|
295
|
+
"crypto",
|
|
296
|
+
"Event",
|
|
297
|
+
"CustomEvent",
|
|
298
|
+
"queueMicrotask"
|
|
299
|
+
].map((api) => entry({
|
|
300
|
+
api,
|
|
301
|
+
kind: "global",
|
|
302
|
+
support: "polyfill-required",
|
|
303
|
+
diagnostic: "warn",
|
|
304
|
+
platform: "wechat",
|
|
305
|
+
replacement: "启用 weapp.appPrelude.webRuntime,或从 @wevu/web-apis 使用显式兼容实现",
|
|
306
|
+
summary: "不同基础库、真机和 DevTools 版本的宿主能力不一致,不能依赖隐式全局。"
|
|
307
|
+
})),
|
|
308
|
+
...[
|
|
309
|
+
"window",
|
|
310
|
+
"document",
|
|
311
|
+
"navigator",
|
|
312
|
+
"self",
|
|
313
|
+
"global",
|
|
314
|
+
"location",
|
|
315
|
+
"process",
|
|
316
|
+
"Buffer",
|
|
317
|
+
"localStorage",
|
|
318
|
+
"sessionStorage",
|
|
319
|
+
"setImmediate",
|
|
320
|
+
"structuredClone"
|
|
321
|
+
].map((api) => entry({
|
|
322
|
+
api,
|
|
323
|
+
kind: "global",
|
|
324
|
+
support: "unsupported",
|
|
325
|
+
diagnostic: "error",
|
|
326
|
+
platform: "wechat",
|
|
327
|
+
summary: "微信小程序 AppService 不提供可移植的浏览器或 Node.js 全局能力。"
|
|
328
|
+
})),
|
|
329
|
+
...[
|
|
330
|
+
["Object.fromEntries", "使用 for...of 构造对象"],
|
|
331
|
+
["Object.hasOwn", "使用 Object.prototype.hasOwnProperty.call(...)"],
|
|
332
|
+
["Promise.any", "使用兼容实现或调整并发策略"],
|
|
333
|
+
["Promise.allSettled", "使用 Promise.all 包装每个任务结果"]
|
|
334
|
+
].map(([api, replacement]) => entry({
|
|
335
|
+
api,
|
|
336
|
+
kind: "static-method",
|
|
337
|
+
support: "unsupported",
|
|
338
|
+
diagnostic: "error",
|
|
339
|
+
platform: "wechat",
|
|
340
|
+
replacement,
|
|
341
|
+
summary: "该现代内建超出项目的小程序 ES2018 运行时兼容基线。"
|
|
342
|
+
})),
|
|
343
|
+
...[
|
|
344
|
+
["Array.prototype.at", "使用下标访问"],
|
|
345
|
+
["String.prototype.at", "使用 charAt() 或下标访问"],
|
|
346
|
+
["Array.prototype.flat", "使用循环展开数组"],
|
|
347
|
+
["Array.prototype.flatMap", "使用循环或 reduce 展开数组"],
|
|
348
|
+
["String.prototype.replaceAll", "使用带全局标志的正则 replace()"]
|
|
349
|
+
].map(([api, replacement]) => entry({
|
|
350
|
+
api,
|
|
351
|
+
kind: "instance-method",
|
|
352
|
+
support: "unsupported",
|
|
353
|
+
diagnostic: "error",
|
|
354
|
+
platform: "wechat",
|
|
355
|
+
replacement,
|
|
356
|
+
summary: "该现代内建超出项目的小程序 ES2018 运行时兼容基线。"
|
|
357
|
+
}))
|
|
358
|
+
];
|
|
359
|
+
const unsupportedEntries = miniProgramRuntimeApiCatalog.filter((item) => item.support === "unsupported");
|
|
360
|
+
const polyfillEntries = miniProgramRuntimeApiCatalog.filter((item) => item.support === "polyfill-required");
|
|
361
|
+
function staticPropertyName(node) {
|
|
362
|
+
if (!node.computed && node.property?.type === "Identifier") return node.property.name;
|
|
363
|
+
if (node.computed && node.property?.type === "Literal" && typeof node.property.value === "string") return node.property.value;
|
|
364
|
+
}
|
|
365
|
+
function isTypePosition(node) {
|
|
366
|
+
let current = node.parent;
|
|
367
|
+
while (current) {
|
|
368
|
+
if (String(current.type).startsWith("TS")) return true;
|
|
369
|
+
if (/Expression$|Statement$|Declaration$/.test(current.type)) return false;
|
|
370
|
+
current = current.parent;
|
|
371
|
+
}
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
function isLocallyBound(context, node, name) {
|
|
375
|
+
let scope = context.sourceCode.getScope(node);
|
|
376
|
+
while (scope) {
|
|
377
|
+
if ((scope.set?.get(name))?.defs?.length) return true;
|
|
378
|
+
scope = scope.upper;
|
|
379
|
+
}
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
function isScopeReference(context, node) {
|
|
383
|
+
let scope = context.sourceCode.getScope(node);
|
|
384
|
+
while (scope) {
|
|
385
|
+
if (scope.references?.some((reference) => reference.identifier === node) || scope.through?.some((reference) => reference.identifier === node)) return true;
|
|
386
|
+
scope = scope.upper;
|
|
387
|
+
}
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
function isInspectionOnlyReference(node) {
|
|
391
|
+
return isTypePosition(node) || node.parent?.type === "UnaryExpression" && node.parent.operator === "typeof";
|
|
392
|
+
}
|
|
393
|
+
function isRuntimeReference(context, node) {
|
|
394
|
+
if (isInspectionOnlyReference(node)) return false;
|
|
395
|
+
return isScopeReference(context, node) && !isLocallyBound(context, node, node.name);
|
|
396
|
+
}
|
|
397
|
+
function staticRuntimeObjectName(context, node) {
|
|
398
|
+
if (node?.type === "Identifier" && !isLocallyBound(context, node, node.name)) return node.name;
|
|
399
|
+
if (node?.type === "MemberExpression" && node.object?.type === "Identifier" && node.object.name === "globalThis" && !isLocallyBound(context, node.object, "globalThis")) return staticPropertyName(node);
|
|
400
|
+
}
|
|
401
|
+
function report(context, node, entry) {
|
|
402
|
+
context.report({
|
|
403
|
+
node,
|
|
404
|
+
message: entry.replacement ? `{{api}} 不能作为隐式小程序运行时能力使用;{{replacement}}。` : `{{api}} 不是受支持的小程序运行时能力。`,
|
|
405
|
+
data: {
|
|
406
|
+
api: entry.api,
|
|
407
|
+
replacement: entry.replacement
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
function createRuntimeApiRule(entries) {
|
|
412
|
+
const globals = new Map(entries.filter((item) => item.kind === "global").map((item) => [item.api, item]));
|
|
413
|
+
const staticMethods = new Map(entries.filter((item) => item.kind === "static-method").map((item) => [item.api, item]));
|
|
414
|
+
const instanceMethods = /* @__PURE__ */ new Map();
|
|
415
|
+
for (const item of entries.filter((item) => item.kind === "instance-method")) instanceMethods.set(item.api.slice(item.api.lastIndexOf(".") + 1), item);
|
|
416
|
+
return {
|
|
417
|
+
meta: {
|
|
418
|
+
type: "problem",
|
|
419
|
+
docs: { description: "限制小程序 AppService 不可移植的运行时 API" },
|
|
420
|
+
schema: [],
|
|
421
|
+
messages: {}
|
|
422
|
+
},
|
|
423
|
+
create(context) {
|
|
424
|
+
return {
|
|
425
|
+
Identifier(node) {
|
|
426
|
+
const entry = globals.get(node.name);
|
|
427
|
+
if (!entry || !isRuntimeReference(context, node)) return;
|
|
428
|
+
if (node.parent?.type === "MemberExpression" && node.parent.property === node && !node.parent.computed) return;
|
|
429
|
+
report(context, node, entry);
|
|
430
|
+
},
|
|
431
|
+
MemberExpression(node) {
|
|
432
|
+
if (isInspectionOnlyReference(node)) return;
|
|
433
|
+
const property = staticPropertyName(node);
|
|
434
|
+
if (!property) return;
|
|
435
|
+
if (node.object?.type === "Identifier" && node.object.name === "globalThis" && !isLocallyBound(context, node.object, "globalThis")) {
|
|
436
|
+
const globalEntry = globals.get(property);
|
|
437
|
+
if (globalEntry) report(context, node, globalEntry);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const runtimeObjectName = staticRuntimeObjectName(context, node.object);
|
|
441
|
+
if (runtimeObjectName) {
|
|
442
|
+
const staticEntry = staticMethods.get(`${runtimeObjectName}.${property}`);
|
|
443
|
+
if (staticEntry) {
|
|
444
|
+
report(context, node, staticEntry);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const instanceEntry = instanceMethods.get(property);
|
|
449
|
+
if (instanceEntry && node.parent?.type === "CallExpression" && node.parent.callee === node) report(context, node, instanceEntry);
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
const miniProgramRuntimePlugin = {
|
|
456
|
+
meta: {
|
|
457
|
+
name: "weapp-vite-mini-program-runtime",
|
|
458
|
+
version: "1.0.0"
|
|
459
|
+
},
|
|
460
|
+
rules: {
|
|
461
|
+
"no-unsupported-runtime-api": createRuntimeApiRule(unsupportedEntries),
|
|
462
|
+
"no-implicit-runtime-polyfill": createRuntimeApiRule(polyfillEntries)
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
const MINI_PROGRAM_RUNTIME_DEFAULT_FILES = ["src/**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx,vue}"];
|
|
466
|
+
const MINI_PROGRAM_RUNTIME_DEFAULT_IGNORES = [
|
|
467
|
+
"**/node_modules/**",
|
|
468
|
+
"**/dist/**",
|
|
469
|
+
"**/dist-*/**",
|
|
470
|
+
"**/.weapp-vite/**",
|
|
471
|
+
"**/generated/**",
|
|
472
|
+
"**/scripts/**",
|
|
473
|
+
"**/src/**/node.{js,mjs,cjs,jsx,ts,mts,cts,tsx}",
|
|
474
|
+
"**/src/**/*.web.*",
|
|
475
|
+
"**/*.{test,spec}.{js,mjs,cjs,jsx,ts,mts,cts,tsx}"
|
|
476
|
+
];
|
|
477
|
+
function createMiniProgramRuntimeConfig(options = {}) {
|
|
478
|
+
return {
|
|
479
|
+
files: options.files ?? MINI_PROGRAM_RUNTIME_DEFAULT_FILES,
|
|
480
|
+
ignores: options.ignores ?? MINI_PROGRAM_RUNTIME_DEFAULT_IGNORES,
|
|
481
|
+
plugins: { "mini-program": miniProgramRuntimePlugin },
|
|
482
|
+
rules: {
|
|
483
|
+
"mini-program/no-unsupported-runtime-api": "error",
|
|
484
|
+
"mini-program/no-implicit-runtime-polyfill": "warn"
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
const miniProgramRuntimeRecommended = createMiniProgramRuntimeConfig();
|
|
489
|
+
//#endregion
|
|
267
490
|
//#region src/index.ts
|
|
268
491
|
const SOURCE_TO_UPSTREAM = {
|
|
269
492
|
"vue": "vue",
|
|
@@ -379,4 +602,4 @@ const wevuCompatibilityRecommended = {
|
|
|
379
602
|
}
|
|
380
603
|
};
|
|
381
604
|
//#endregion
|
|
382
|
-
export { findWevuCompatibilityEntry, wevuCompatibilityCatalog, wevuCompatibilityPlugin, wevuCompatibilityRecommended };
|
|
605
|
+
export { MINI_PROGRAM_RUNTIME_DEFAULT_FILES, MINI_PROGRAM_RUNTIME_DEFAULT_IGNORES, createMiniProgramRuntimeConfig, findWevuCompatibilityEntry, miniProgramRuntimeApiCatalog, miniProgramRuntimePlugin, miniProgramRuntimeRecommended, wevuCompatibilityCatalog, wevuCompatibilityPlugin, wevuCompatibilityRecommended };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weapp-vite/eslint",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"description": "Wevu compatibility ESLint plugin and recommended configuration",
|
|
6
6
|
"author": "ice breaker <1324318532@qq.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@typescript-eslint/parser": "^8.
|
|
55
|
+
"@typescript-eslint/parser": "^8.69.0",
|
|
56
56
|
"eslint": "^10.9.1",
|
|
57
57
|
"typescript": "^6.0.3",
|
|
58
58
|
"vitest": "^4.1.11",
|