@acdvs/eslint-plugin-amd 1.0.0
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/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/define-B8C8F-jq.cjs +118 -0
- package/dist/define-DldfQ_w6.mjs +89 -0
- package/dist/index.cjs +343 -0
- package/dist/index.d.cts +23 -0
- package/dist/index.d.mts +23 -0
- package/dist/index.mjs +319 -0
- package/dist/types-OWk_tv7p.d.cts +475 -0
- package/dist/types-OWk_tv7p.d.mts +475 -0
- package/dist/utils/index.cjs +7 -0
- package/dist/utils/index.d.cts +20 -0
- package/dist/utils/index.d.mts +20 -0
- package/dist/utils/index.mjs +2 -0
- package/package.json +77 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { a as DependencyPair, i as DependencyAnalysis, n as DefineCall, r as DefineFactory, t as DefineArgs } from "./types-OWk_tv7p.mjs";
|
|
2
|
+
import { Linter, Rule } from "eslint";
|
|
3
|
+
|
|
4
|
+
//#region lib/index.d.ts
|
|
5
|
+
declare const plugin: {
|
|
6
|
+
meta: {
|
|
7
|
+
name: string;
|
|
8
|
+
version: string;
|
|
9
|
+
};
|
|
10
|
+
rules: {
|
|
11
|
+
'define-indicator': Rule.RuleModule;
|
|
12
|
+
'no-dynamic-require': Rule.RuleModule;
|
|
13
|
+
'no-extra-deps': Rule.RuleModule;
|
|
14
|
+
'no-extra-params': Rule.RuleModule;
|
|
15
|
+
'no-invalid-define': Rule.RuleModule;
|
|
16
|
+
'no-module-extensions': Rule.RuleModule;
|
|
17
|
+
'no-name': Rule.RuleModule;
|
|
18
|
+
'sorted-deps': Rule.RuleModule;
|
|
19
|
+
};
|
|
20
|
+
configs: Record<string, Linter.Config[]>;
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
export { DefineArgs, DefineCall, DefineFactory, DependencyAnalysis, DependencyPair, plugin as default };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { a as hasAMDIndicator, i as isRequireCall, n as getDefineCall } from "./define-DldfQ_w6.mjs";
|
|
2
|
+
import globals from "globals";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
//#region package.json
|
|
5
|
+
var name = "@acdvs/eslint-plugin-amd";
|
|
6
|
+
var version = "1.0.0";
|
|
7
|
+
var homepage = "https://github.com/acdvs/eslint-plugin-amd";
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region lib/rules/index.ts
|
|
10
|
+
var rules_default = {
|
|
11
|
+
"define-indicator": {
|
|
12
|
+
meta: {
|
|
13
|
+
type: "suggestion",
|
|
14
|
+
docs: {
|
|
15
|
+
description: "Enforce the presence of the AMD module `define()` indicator.",
|
|
16
|
+
url: `${homepage}/blob/main/docs/rules/${path.basename(import.meta.filename, ".ts")}.md`
|
|
17
|
+
},
|
|
18
|
+
fixable: "code",
|
|
19
|
+
schema: [],
|
|
20
|
+
messages: {
|
|
21
|
+
defineCallWithoutIndicator: "Missing AMD module `define` indicator: `define.amd = {}`",
|
|
22
|
+
indicatorWithoutDefineCall: "AMD module `define` indicator present without a `define()` call."
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
create: (context) => {
|
|
26
|
+
let hasDefineCall = false;
|
|
27
|
+
return {
|
|
28
|
+
"CallExpression[callee.name=define]": () => {
|
|
29
|
+
hasDefineCall = true;
|
|
30
|
+
},
|
|
31
|
+
"Program:exit": (program) => {
|
|
32
|
+
const hasIndicator = hasAMDIndicator(context.sourceCode);
|
|
33
|
+
if (hasDefineCall && !hasIndicator) {
|
|
34
|
+
context.report({
|
|
35
|
+
node: program,
|
|
36
|
+
messageId: "defineCallWithoutIndicator",
|
|
37
|
+
fix: (fixer) => {
|
|
38
|
+
return fixer.insertTextAfter(program, "\n\ndefine.amd = {};");
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!hasDefineCall && hasIndicator) context.report({
|
|
44
|
+
node: program,
|
|
45
|
+
messageId: "indicatorWithoutDefineCall"
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"no-dynamic-require": {
|
|
52
|
+
meta: {
|
|
53
|
+
type: "suggestion",
|
|
54
|
+
docs: {
|
|
55
|
+
description: "Disallow dynamic (non-literal) expressions in `require()` calls.",
|
|
56
|
+
url: `${homepage}/blob/main/docs/rules/${path.basename(import.meta.filename, ".ts")}.md`
|
|
57
|
+
},
|
|
58
|
+
schema: [],
|
|
59
|
+
messages: {
|
|
60
|
+
dynamicRequire: "`require()` argument must be a string literal or an array of string literals.",
|
|
61
|
+
dynamicRequireElement: "All elements of a `require()` dependency array must be string literals."
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
create: (context) => {
|
|
65
|
+
return { CallExpression: (node) => {
|
|
66
|
+
if (!isRequireCall(node) || node.arguments.length === 0) return;
|
|
67
|
+
const firstArg = node.arguments[0];
|
|
68
|
+
if (firstArg.type === "Literal") return;
|
|
69
|
+
if (firstArg.type === "ArrayExpression") {
|
|
70
|
+
for (const el of firstArg.elements) if (el === null || el.type !== "Literal") context.report({
|
|
71
|
+
node: el ?? firstArg,
|
|
72
|
+
messageId: "dynamicRequireElement"
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
context.report({
|
|
77
|
+
node: firstArg,
|
|
78
|
+
messageId: "dynamicRequire"
|
|
79
|
+
});
|
|
80
|
+
} };
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"no-extra-deps": {
|
|
84
|
+
meta: {
|
|
85
|
+
type: "suggestion",
|
|
86
|
+
docs: {
|
|
87
|
+
description: "Disallow more dependency literals than factory parameters.",
|
|
88
|
+
recommended: true,
|
|
89
|
+
url: `${homepage}/blob/main/docs/rules/${path.basename(import.meta.filename, ".ts")}.md`
|
|
90
|
+
},
|
|
91
|
+
schema: [{
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: { ignoreValueFactory: {
|
|
94
|
+
type: "boolean",
|
|
95
|
+
default: true
|
|
96
|
+
} },
|
|
97
|
+
additionalProperties: false
|
|
98
|
+
}],
|
|
99
|
+
defaultOptions: [{ ignoreValueFactory: true }],
|
|
100
|
+
messages: { extraDep: "Dependency '{{dep}}' has no corresponding factory parameter. Add a parameter or remove the dependency." }
|
|
101
|
+
},
|
|
102
|
+
create: (context) => {
|
|
103
|
+
const { ignoreValueFactory } = context.options[0] ?? {};
|
|
104
|
+
return { "CallExpression[callee.name=define]": (node) => {
|
|
105
|
+
const def = getDefineCall(node);
|
|
106
|
+
const hasValueFactory = def?.args.factory.type === "ObjectExpression";
|
|
107
|
+
if (!def?.depAnalysis || hasValueFactory && ignoreValueFactory) return;
|
|
108
|
+
for (const name of def.depAnalysis.extraNames) context.report({
|
|
109
|
+
node: name,
|
|
110
|
+
messageId: "extraDep",
|
|
111
|
+
data: { dep: String(name.value) }
|
|
112
|
+
});
|
|
113
|
+
} };
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"no-extra-params": {
|
|
117
|
+
meta: {
|
|
118
|
+
type: "problem",
|
|
119
|
+
docs: {
|
|
120
|
+
description: "Disallow more factory parameters than dependency literals.",
|
|
121
|
+
recommended: true,
|
|
122
|
+
url: `${homepage}/blob/main/docs/rules/${path.basename(import.meta.filename, ".ts")}.md`
|
|
123
|
+
},
|
|
124
|
+
schema: [],
|
|
125
|
+
messages: {
|
|
126
|
+
extraIdentParam: "Factory parameter '{{param}}' has no corresponding dependency literal. Add a dependency or remove the parameter.",
|
|
127
|
+
extraNonIdentParam: "Factory parameter has no corresponding dependency literal. Add a dependency or remove the parameter."
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
create: (context) => {
|
|
131
|
+
return { "CallExpression[callee.name=define]": (node) => {
|
|
132
|
+
const def = getDefineCall(node);
|
|
133
|
+
if (!def?.depAnalysis) return;
|
|
134
|
+
for (const param of def.depAnalysis.extraParams) if (param.type === "Identifier") context.report({
|
|
135
|
+
node: param,
|
|
136
|
+
messageId: "extraIdentParam",
|
|
137
|
+
data: { param: param.name }
|
|
138
|
+
});
|
|
139
|
+
else context.report({
|
|
140
|
+
node: param,
|
|
141
|
+
messageId: "extraNonIdentParam"
|
|
142
|
+
});
|
|
143
|
+
} };
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"no-invalid-define": {
|
|
147
|
+
meta: {
|
|
148
|
+
type: "problem",
|
|
149
|
+
docs: {
|
|
150
|
+
description: "Disallow `define()` calls that do not match a valid AMD module signature.",
|
|
151
|
+
recommended: true,
|
|
152
|
+
url: `${homepage}/blob/main/docs/rules/${path.basename(import.meta.filename, ".ts")}.md`
|
|
153
|
+
},
|
|
154
|
+
schema: [],
|
|
155
|
+
messages: { invalidDefine: "`define()` call does not match a valid signature." }
|
|
156
|
+
},
|
|
157
|
+
create: (context) => {
|
|
158
|
+
return { "CallExpression[callee.name=define]": (node) => {
|
|
159
|
+
if (!getDefineCall(node)) context.report({
|
|
160
|
+
node,
|
|
161
|
+
messageId: "invalidDefine"
|
|
162
|
+
});
|
|
163
|
+
} };
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
"no-module-extensions": {
|
|
167
|
+
meta: {
|
|
168
|
+
type: "suggestion",
|
|
169
|
+
docs: {
|
|
170
|
+
description: "Disallow file extensions in AMD dependency paths.",
|
|
171
|
+
recommended: true,
|
|
172
|
+
url: `${homepage}/blob/main/docs/rules/${path.basename(import.meta.filename, ".ts")}.md`
|
|
173
|
+
},
|
|
174
|
+
schema: [{ oneOf: [{
|
|
175
|
+
type: "object",
|
|
176
|
+
properties: {
|
|
177
|
+
blacklist: {
|
|
178
|
+
type: "array",
|
|
179
|
+
items: { type: "string" },
|
|
180
|
+
minItems: 1,
|
|
181
|
+
uniqueItems: true,
|
|
182
|
+
description: "Extensions disallowed in dependency paths. If set, all other extensions are allowed."
|
|
183
|
+
},
|
|
184
|
+
whitelist: {
|
|
185
|
+
type: "array",
|
|
186
|
+
items: { type: "string" },
|
|
187
|
+
minItems: 1,
|
|
188
|
+
uniqueItems: true,
|
|
189
|
+
description: "Extensions allowed in dependency paths. If set, all other extensions are disallowed and any `blacklist` is ignored."
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
additionalProperties: false
|
|
193
|
+
}] }],
|
|
194
|
+
messages: {
|
|
195
|
+
blacklistedDefault: "Dependency '{{dep}}' should not include a file extension.",
|
|
196
|
+
blacklisted: "Dependency '{{dep}}' should not include a blacklisted file extension.",
|
|
197
|
+
notWhitelisted: "Dependency '{{dep}}' includes a non-whitelisted file extension."
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
create: (context) => {
|
|
201
|
+
const { blacklist, whitelist } = context.options[0] ?? {};
|
|
202
|
+
return { "CallExpression[callee.name=define]": (node) => {
|
|
203
|
+
const def = getDefineCall(node);
|
|
204
|
+
if (!def?.args.dependencies) return;
|
|
205
|
+
for (const el of def.args.dependencies.elements) {
|
|
206
|
+
const literal = el;
|
|
207
|
+
const dep = literal.value;
|
|
208
|
+
if (!/(\.\w+)+$/.test(dep)) continue;
|
|
209
|
+
if (whitelist && whitelist.length > 0) {
|
|
210
|
+
if (!whitelist.some((ext) => dep.endsWith(ext))) context.report({
|
|
211
|
+
node: literal,
|
|
212
|
+
messageId: "notWhitelisted",
|
|
213
|
+
data: { dep }
|
|
214
|
+
});
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const isDefaultBlacklist = !blacklist;
|
|
218
|
+
if (isDefaultBlacklist || blacklist.some((ext) => dep.endsWith(ext))) context.report({
|
|
219
|
+
node: literal,
|
|
220
|
+
messageId: isDefaultBlacklist ? "blacklistedDefault" : "blacklisted",
|
|
221
|
+
data: { dep }
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
} };
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
"no-name": {
|
|
228
|
+
meta: {
|
|
229
|
+
type: "suggestion",
|
|
230
|
+
docs: {
|
|
231
|
+
description: "Disallow named AMD modules.",
|
|
232
|
+
recommended: true,
|
|
233
|
+
url: `${homepage}/blob/main/docs/rules/${path.basename(import.meta.filename, ".ts")}.md`
|
|
234
|
+
},
|
|
235
|
+
schema: [],
|
|
236
|
+
messages: { noAmdName: "AMD module should be anonymous. Remove the name argument '{{name}}' from the `define()` call." }
|
|
237
|
+
},
|
|
238
|
+
create: (context) => {
|
|
239
|
+
return { "CallExpression[callee.name=define]": (node) => {
|
|
240
|
+
const def = getDefineCall(node);
|
|
241
|
+
if (!def) return;
|
|
242
|
+
if (def.args.name) context.report({
|
|
243
|
+
node: def.args.name,
|
|
244
|
+
messageId: "noAmdName",
|
|
245
|
+
data: { name: def.args.name.value }
|
|
246
|
+
});
|
|
247
|
+
} };
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
"sorted-deps": {
|
|
251
|
+
meta: {
|
|
252
|
+
type: "suggestion",
|
|
253
|
+
docs: {
|
|
254
|
+
description: "Enforce alphabetical ordering of `define()` dependency literals.",
|
|
255
|
+
url: `${homepage}/blob/main/docs/rules/${path.basename(import.meta.filename, ".ts")}.md`
|
|
256
|
+
},
|
|
257
|
+
schema: [{
|
|
258
|
+
type: "object",
|
|
259
|
+
properties: { order: {
|
|
260
|
+
type: "string",
|
|
261
|
+
enum: ["asc", "desc"],
|
|
262
|
+
default: "asc"
|
|
263
|
+
} },
|
|
264
|
+
additionalProperties: false
|
|
265
|
+
}],
|
|
266
|
+
defaultOptions: [{ order: "asc" }],
|
|
267
|
+
messages: { wrongOrder: "Dependencies should be sorted in {{order}} order." }
|
|
268
|
+
},
|
|
269
|
+
create: (context) => {
|
|
270
|
+
const { order } = context.options[0] ?? {};
|
|
271
|
+
return { "CallExpression[callee.name=define]": (node) => {
|
|
272
|
+
const deps = getDefineCall(node)?.args.dependencies;
|
|
273
|
+
const els = deps?.elements;
|
|
274
|
+
if (!deps || !els) return;
|
|
275
|
+
for (let i = 1; i < els.length; i++) {
|
|
276
|
+
const prevEl = els[i - 1];
|
|
277
|
+
const currEl = els[i];
|
|
278
|
+
const prevDep = prevEl.value;
|
|
279
|
+
const currDep = currEl.value;
|
|
280
|
+
if (order === "asc" ? currDep < prevDep : currDep > prevDep) context.report({
|
|
281
|
+
node: deps,
|
|
282
|
+
messageId: "wrongOrder",
|
|
283
|
+
data: { order: order === "asc" ? "alphabetical" : `reverse alphabetical` }
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
} };
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
//#endregion
|
|
291
|
+
//#region lib/index.ts
|
|
292
|
+
const plugin = {
|
|
293
|
+
meta: {
|
|
294
|
+
name,
|
|
295
|
+
version
|
|
296
|
+
},
|
|
297
|
+
rules: rules_default,
|
|
298
|
+
configs: {}
|
|
299
|
+
};
|
|
300
|
+
const defaults = {
|
|
301
|
+
plugins: { amd: plugin },
|
|
302
|
+
languageOptions: {
|
|
303
|
+
sourceType: "commonjs",
|
|
304
|
+
globals: { ...globals.amd }
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
plugin.configs.all = [{
|
|
308
|
+
...defaults,
|
|
309
|
+
rules: Object.fromEntries(Object.entries(rules_default).map(entryToConfigArray))
|
|
310
|
+
}];
|
|
311
|
+
plugin.configs.recommended = [{
|
|
312
|
+
...defaults,
|
|
313
|
+
rules: Object.fromEntries(Object.entries(rules_default).filter(([, rule]) => rule.meta?.docs?.recommended).map(entryToConfigArray))
|
|
314
|
+
}];
|
|
315
|
+
function entryToConfigArray([name, rule]) {
|
|
316
|
+
return [`amd/${name}`, rule.meta?.type === "problem" ? "error" : "warn"];
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
319
|
+
export { plugin as default };
|