@arcgis/eslint-config 5.0.0-next.98 → 5.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.md +9 -5
- package/README.md +2 -3
- package/dist/config/index.js +51 -1
- package/dist/estree-Can6TC4w.js +159 -0
- package/dist/plugins/lumina/index.js +7 -105
- package/dist/plugins/lumina/utils/estree.d.ts +8 -0
- package/dist/plugins/webgis/index.js +70 -15
- package/dist/plugins/webgis/rules/no-unsafe-hash-links.d.ts +2 -0
- package/package.json +6 -3
- package/dist/makePlugin-DvrrzfxD.js +0 -41
package/LICENSE.md
CHANGED
|
@@ -4,10 +4,14 @@ COPYRIGHT © Esri
|
|
|
4
4
|
|
|
5
5
|
All rights reserved under the copyright laws of the United States and applicable international laws, treaties, and conventions.
|
|
6
6
|
|
|
7
|
-
This material is licensed for use under the Esri Master License Agreement (MLA), and is bound by the terms of that agreement.
|
|
7
|
+
This material is licensed for use under the [Esri Master License Agreement (MLA)](https://www.esri.com/content/dam/esrisites/en-us/media/legal/ma-full/ma-full.pdf), and is bound by the terms of that agreement.
|
|
8
|
+
You may redistribute and use this code without modification, provided you adhere to the terms of the MLA and include this copyright notice.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
For additional information, contact:
|
|
11
|
+
Environmental Systems Research Institute, Inc.
|
|
12
|
+
Attn: Contracts and Legal Services Department
|
|
13
|
+
380 New York Street
|
|
14
|
+
Redlands, California, USA 92373
|
|
15
|
+
USA
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
email: contracts@esri.com
|
|
17
|
+
email: legal@esri.com
|
package/README.md
CHANGED
|
@@ -8,6 +8,5 @@ It is not intended to be used directly, but rather used as a dependency by other
|
|
|
8
8
|
|
|
9
9
|
## License
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
This package is licensed under the terms described in the `LICENSE.md` file, located in the root of the package.
|
|
11
|
+
This package is licensed under the terms described in the `LICENSE.md` file, located in the root of the package, and at https://js.arcgis.com/5.0/LICENSE.txt.
|
|
12
|
+
For third party notices, see https://js.arcgis.com/5.0/third-party-notices.txt.
|
package/dist/config/index.js
CHANGED
|
@@ -5,6 +5,10 @@ import globals from "globals";
|
|
|
5
5
|
import { webgisPlugin } from "../plugins/webgis/index.js";
|
|
6
6
|
import { globalIgnores } from "eslint/config";
|
|
7
7
|
import markdown from "@eslint/markdown";
|
|
8
|
+
import packageJson from "eslint-plugin-package-json";
|
|
9
|
+
const packageJsonSortableCollections = packageJson.rules["sort-collections"].meta.defaultOptions[0].filter(
|
|
10
|
+
(collection) => !["scripts", "exports"].includes(collection)
|
|
11
|
+
) ?? [];
|
|
8
12
|
const defaultConfig = [
|
|
9
13
|
globalIgnores(["**/www", "**/dist", "**/assets", "**/coverage", "**/.docs"]),
|
|
10
14
|
{
|
|
@@ -280,7 +284,7 @@ const defaultConfig = [
|
|
|
280
284
|
"no-loss-of-precision": "error",
|
|
281
285
|
"@typescript-eslint/switch-exhaustiveness-check": "error",
|
|
282
286
|
"default-case-last": "error",
|
|
283
|
-
"func-style": ["error", "declaration", { allowArrowFunctions: true }],
|
|
287
|
+
"func-style": ["error", "declaration", { allowArrowFunctions: true, allowTypeAnnotation: true }],
|
|
284
288
|
"no-new-func": "error",
|
|
285
289
|
"no-new-wrappers": "error",
|
|
286
290
|
"@typescript-eslint/no-misused-promises": [
|
|
@@ -570,6 +574,52 @@ const defaultConfig = [
|
|
|
570
574
|
// Don't do type-aware linting for untyped files
|
|
571
575
|
files: ["**/*.js"],
|
|
572
576
|
...tsEslint.configs.disableTypeChecked
|
|
577
|
+
},
|
|
578
|
+
packageJson.configs.recommended,
|
|
579
|
+
{
|
|
580
|
+
files: ["**/package.json"],
|
|
581
|
+
rules: {
|
|
582
|
+
// We don't want to sort scripts and exports
|
|
583
|
+
"package-json/sort-collections": ["warn", packageJsonSortableCollections],
|
|
584
|
+
// Making a warning for now to avoid disrupting current work but we should go to error later
|
|
585
|
+
"package-json/require-description": "warn",
|
|
586
|
+
"package-json/bin-name-casing": "warn",
|
|
587
|
+
// Allow empty "files" field to explicitly indicate that no files
|
|
588
|
+
// should be included in the package
|
|
589
|
+
"package-json/no-empty-fields": ["error", { ignoreProperties: ["files"] }],
|
|
590
|
+
// Enforce a specific property order for better readability and consistency
|
|
591
|
+
"package-json/order-properties": [
|
|
592
|
+
"warn",
|
|
593
|
+
{
|
|
594
|
+
order: [
|
|
595
|
+
"name",
|
|
596
|
+
"version",
|
|
597
|
+
"description",
|
|
598
|
+
"keywords",
|
|
599
|
+
"homepage",
|
|
600
|
+
"private",
|
|
601
|
+
"sideEffects",
|
|
602
|
+
"workspaces",
|
|
603
|
+
"type",
|
|
604
|
+
"main",
|
|
605
|
+
"module",
|
|
606
|
+
"types",
|
|
607
|
+
"exports",
|
|
608
|
+
"files",
|
|
609
|
+
"bin",
|
|
610
|
+
"publishConfig",
|
|
611
|
+
"license",
|
|
612
|
+
"scripts",
|
|
613
|
+
"acme:scripts",
|
|
614
|
+
"dependencies",
|
|
615
|
+
"devDependencies",
|
|
616
|
+
"peerDependencies",
|
|
617
|
+
"peerDependenciesMeta",
|
|
618
|
+
"packageManager"
|
|
619
|
+
]
|
|
620
|
+
}
|
|
621
|
+
]
|
|
622
|
+
}
|
|
573
623
|
}
|
|
574
624
|
];
|
|
575
625
|
export {
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
const version = "5.0.0";
|
|
3
|
+
const packageJson = {
|
|
4
|
+
version
|
|
5
|
+
};
|
|
6
|
+
function makeEslintPlugin(pluginName, urlCreator) {
|
|
7
|
+
const rules = [];
|
|
8
|
+
const creator = ESLintUtils.RuleCreator(urlCreator);
|
|
9
|
+
return {
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
11
|
+
createRule(rule) {
|
|
12
|
+
const { meta, name, ...rest } = rule;
|
|
13
|
+
const docs = { ...meta.docs, name };
|
|
14
|
+
const ruleModule = creator({ ...rest, meta: { ...meta, docs }, name });
|
|
15
|
+
rules.push(ruleModule);
|
|
16
|
+
return ruleModule;
|
|
17
|
+
},
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
19
|
+
finalize() {
|
|
20
|
+
const config = {
|
|
21
|
+
rules: Object.fromEntries(
|
|
22
|
+
rules.map((rule) => [`${pluginName}/${rule.meta.docs.name}`, rule.meta.docs.defaultLevel])
|
|
23
|
+
)
|
|
24
|
+
};
|
|
25
|
+
const plugin = {
|
|
26
|
+
meta: { name: `@arcgis/eslint-plugin-${pluginName}`, version: packageJson.version },
|
|
27
|
+
configs: {
|
|
28
|
+
recommended: config
|
|
29
|
+
},
|
|
30
|
+
rules: Object.fromEntries(rules.map((rule) => [rule.meta.docs.name, rule]))
|
|
31
|
+
};
|
|
32
|
+
config.plugins = {
|
|
33
|
+
[pluginName]: plugin
|
|
34
|
+
};
|
|
35
|
+
return plugin;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const unwrapExpression = (expression) => expression.type === AST_NODE_TYPES.TSAsExpression || expression.type === AST_NODE_TYPES.TSNonNullExpression || expression.type === AST_NODE_TYPES.TSSatisfiesExpression ? unwrapExpression(expression.expression) : expression;
|
|
40
|
+
const luminaEntrypointName = "@arcgis/lumina";
|
|
41
|
+
const luminaTestEntrypointName = "@arcgis/lumina-compiler/testing";
|
|
42
|
+
const luminaJsxExportName = "h";
|
|
43
|
+
function checkForLuminaJsx() {
|
|
44
|
+
const ImportDeclaration = (node) => {
|
|
45
|
+
if (node.source.value !== luminaEntrypointName) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
for (const specifier of node.specifiers) {
|
|
49
|
+
if (specifier.type === AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES.Identifier && specifier.imported.name === luminaJsxExportName || specifier.imported.type === AST_NODE_TYPES.Literal && specifier.imported.value === luminaJsxExportName)) {
|
|
50
|
+
withProperty.isLuminaJsx = true;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const withProperty = ImportDeclaration;
|
|
56
|
+
return withProperty;
|
|
57
|
+
}
|
|
58
|
+
function hasDecorator(node, decoratorName) {
|
|
59
|
+
return node.decorators.some(
|
|
60
|
+
(decorator) => decorator.expression.type === AST_NODE_TYPES.CallExpression && decorator.expression.callee.type === AST_NODE_TYPES.Identifier && decorator.expression.callee.name === decoratorName
|
|
61
|
+
) ?? false;
|
|
62
|
+
}
|
|
63
|
+
function extractDeclareElementsInterface(node) {
|
|
64
|
+
return node.kind === "global" ? node.body.body.find(
|
|
65
|
+
(node2) => node2.type === AST_NODE_TYPES.TSInterfaceDeclaration && node2.id.name === "DeclareElements"
|
|
66
|
+
) : void 0;
|
|
67
|
+
}
|
|
68
|
+
function getComponentDeclaration(node) {
|
|
69
|
+
for (const member of node.body.body) {
|
|
70
|
+
if (member.type !== AST_NODE_TYPES.TSPropertySignature) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const type = member.typeAnnotation?.typeAnnotation;
|
|
74
|
+
if (type?.type !== AST_NODE_TYPES.TSTypeReference || type.typeName.type !== AST_NODE_TYPES.Identifier) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (member.key.type !== AST_NODE_TYPES.Literal) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
return member;
|
|
81
|
+
}
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
function isCreateEvent(node) {
|
|
85
|
+
return node.value?.type === AST_NODE_TYPES.CallExpression && node.value.callee.type === AST_NODE_TYPES.Identifier && node.value.callee.name === "createEvent" && !node.static;
|
|
86
|
+
}
|
|
87
|
+
const getProperty = (properties, name) => properties?.find(
|
|
88
|
+
(option) => option.type === AST_NODE_TYPES.Property && option.key.type === AST_NODE_TYPES.Identifier && option.key.name === name
|
|
89
|
+
)?.value;
|
|
90
|
+
function isGetterWithoutSetter(node) {
|
|
91
|
+
const isGetter = node.type === AST_NODE_TYPES.MethodDefinition && node.kind === "get";
|
|
92
|
+
if (!isGetter) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const index = node.parent.body.indexOf(node);
|
|
96
|
+
const previousNode = node.parent.body.at(index - 1);
|
|
97
|
+
const nextNode = node.parent.body.at(index + 1);
|
|
98
|
+
const name = getName(node);
|
|
99
|
+
if (name === void 0) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
const previousIsSetter = previousNode?.type === AST_NODE_TYPES.MethodDefinition && previousNode.kind === "set" && getName(previousNode) === name;
|
|
103
|
+
if (previousIsSetter) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
const nextIsSetter = nextNode?.type === AST_NODE_TYPES.MethodDefinition && nextNode.kind === "set" && getName(nextNode) === name;
|
|
107
|
+
return !nextIsSetter;
|
|
108
|
+
}
|
|
109
|
+
function getName(node) {
|
|
110
|
+
if (node.key.type === AST_NODE_TYPES.Identifier) {
|
|
111
|
+
return node.key.name;
|
|
112
|
+
} else if (node.key.type === AST_NODE_TYPES.Literal && typeof node.key.value === "string") {
|
|
113
|
+
return node.key.value;
|
|
114
|
+
} else {
|
|
115
|
+
return void 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function parsePropertyDecorator(decorator) {
|
|
119
|
+
const isPropertyDecorator = decorator.expression.type === AST_NODE_TYPES.CallExpression && decorator.expression.callee.type === AST_NODE_TYPES.Identifier && decorator.expression.callee.name === "property";
|
|
120
|
+
if (!isPropertyDecorator) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const callExpression = decorator?.expression.type === AST_NODE_TYPES.CallExpression ? decorator.expression : void 0;
|
|
124
|
+
if (callExpression === void 0) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const options = callExpression.arguments[0]?.type === AST_NODE_TYPES.ObjectExpression ? callExpression.arguments[0] : void 0;
|
|
128
|
+
const properties = options?.properties;
|
|
129
|
+
return {
|
|
130
|
+
callExpression,
|
|
131
|
+
options,
|
|
132
|
+
properties
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function isBindThisCallee(callee) {
|
|
136
|
+
return callee.type === AST_NODE_TYPES.MemberExpression && // expression.identifier(this)
|
|
137
|
+
callee.property.type === AST_NODE_TYPES.Identifier && // expression.bind(this)
|
|
138
|
+
callee.property.name === "bind" && // expression.expression.bind(this)
|
|
139
|
+
callee.object.type === AST_NODE_TYPES.MemberExpression && // expression.identifier.bind(this)
|
|
140
|
+
callee.object.property.type === AST_NODE_TYPES.Identifier && // this.identifier.bind(this)
|
|
141
|
+
callee.object.object.type === AST_NODE_TYPES.ThisExpression;
|
|
142
|
+
}
|
|
143
|
+
export {
|
|
144
|
+
luminaEntrypointName as a,
|
|
145
|
+
luminaTestEntrypointName as b,
|
|
146
|
+
getProperty as c,
|
|
147
|
+
checkForLuminaJsx as d,
|
|
148
|
+
extractDeclareElementsInterface as e,
|
|
149
|
+
isCreateEvent as f,
|
|
150
|
+
getComponentDeclaration as g,
|
|
151
|
+
hasDecorator as h,
|
|
152
|
+
isGetterWithoutSetter as i,
|
|
153
|
+
getName as j,
|
|
154
|
+
isBindThisCallee as k,
|
|
155
|
+
luminaJsxExportName as l,
|
|
156
|
+
makeEslintPlugin as m,
|
|
157
|
+
parsePropertyDecorator as p,
|
|
158
|
+
unwrapExpression as u
|
|
159
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as makeEslintPlugin } from "../../
|
|
1
|
+
import { m as makeEslintPlugin, l as luminaJsxExportName, a as luminaEntrypointName, b as luminaTestEntrypointName, p as parsePropertyDecorator, c as getProperty, i as isGetterWithoutSetter, d as checkForLuminaJsx, e as extractDeclareElementsInterface, f as isCreateEvent, h as hasDecorator, j as getName, k as isBindThisCallee, g as getComponentDeclaration, u as unwrapExpression } from "../../estree-Can6TC4w.js";
|
|
2
2
|
import { AST_NODE_TYPES, ESLintUtils, AST_TOKEN_TYPES } from "@typescript-eslint/utils";
|
|
3
3
|
import ts from "typescript";
|
|
4
4
|
import { camelToKebab } from "@arcgis/toolkit/string";
|
|
@@ -6,94 +6,6 @@ const plugin = makeEslintPlugin(
|
|
|
6
6
|
"lumina",
|
|
7
7
|
(rule) => `https://devtopia.esri.com/WebGIS/arcgis-web-components/tree/main/packages/support-packages/eslint-config/src/plugins/lumina/rules/${rule}.ts`
|
|
8
8
|
);
|
|
9
|
-
const unwrapExpression = (expression) => expression.type === AST_NODE_TYPES.TSAsExpression || expression.type === AST_NODE_TYPES.TSNonNullExpression || expression.type === AST_NODE_TYPES.TSSatisfiesExpression ? unwrapExpression(expression.expression) : expression;
|
|
10
|
-
const luminaEntrypointName = "@arcgis/lumina";
|
|
11
|
-
const luminaTestEntrypointName = "@arcgis/lumina-compiler/testing";
|
|
12
|
-
const luminaJsxExportName = "h";
|
|
13
|
-
function checkForLuminaJsx() {
|
|
14
|
-
const ImportDeclaration = (node) => {
|
|
15
|
-
if (node.source.value !== luminaEntrypointName) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
for (const specifier of node.specifiers) {
|
|
19
|
-
if (specifier.type === AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES.Identifier && specifier.imported.name === luminaJsxExportName || specifier.imported.type === AST_NODE_TYPES.Literal && specifier.imported.value === luminaJsxExportName)) {
|
|
20
|
-
withProperty.isLuminaJsx = true;
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
const withProperty = ImportDeclaration;
|
|
26
|
-
return withProperty;
|
|
27
|
-
}
|
|
28
|
-
function hasDecorator(node, decoratorName) {
|
|
29
|
-
return node.decorators.some(
|
|
30
|
-
(decorator) => decorator.expression.type === AST_NODE_TYPES.CallExpression && decorator.expression.callee.type === AST_NODE_TYPES.Identifier && decorator.expression.callee.name === decoratorName
|
|
31
|
-
) ?? false;
|
|
32
|
-
}
|
|
33
|
-
function extractDeclareElementsInterface(node) {
|
|
34
|
-
return node.kind === "global" ? node.body.body.find(
|
|
35
|
-
(node2) => node2.type === AST_NODE_TYPES.TSInterfaceDeclaration && node2.id.name === "DeclareElements"
|
|
36
|
-
) : void 0;
|
|
37
|
-
}
|
|
38
|
-
function isCreateEvent(node) {
|
|
39
|
-
return node.value?.type === AST_NODE_TYPES.CallExpression && node.value.callee.type === AST_NODE_TYPES.Identifier && node.value.callee.name === "createEvent" && !node.static;
|
|
40
|
-
}
|
|
41
|
-
const getProperty = (properties, name) => properties?.find(
|
|
42
|
-
(option) => option.type === AST_NODE_TYPES.Property && option.key.type === AST_NODE_TYPES.Identifier && option.key.name === name
|
|
43
|
-
)?.value;
|
|
44
|
-
function isGetterWithoutSetter(node) {
|
|
45
|
-
const isGetter = node.type === AST_NODE_TYPES.MethodDefinition && node.kind === "get";
|
|
46
|
-
if (!isGetter) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
const index = node.parent.body.indexOf(node);
|
|
50
|
-
const previousNode = node.parent.body.at(index - 1);
|
|
51
|
-
const nextNode = node.parent.body.at(index + 1);
|
|
52
|
-
const name = getName(node);
|
|
53
|
-
if (name === void 0) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
const previousIsSetter = previousNode?.type === AST_NODE_TYPES.MethodDefinition && previousNode.kind === "set" && getName(previousNode) === name;
|
|
57
|
-
if (previousIsSetter) {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
const nextIsSetter = nextNode?.type === AST_NODE_TYPES.MethodDefinition && nextNode.kind === "set" && getName(nextNode) === name;
|
|
61
|
-
return !nextIsSetter;
|
|
62
|
-
}
|
|
63
|
-
function getName(node) {
|
|
64
|
-
if (node.key.type === AST_NODE_TYPES.Identifier) {
|
|
65
|
-
return node.key.name;
|
|
66
|
-
} else if (node.key.type === AST_NODE_TYPES.Literal && typeof node.key.value === "string") {
|
|
67
|
-
return node.key.value;
|
|
68
|
-
} else {
|
|
69
|
-
return void 0;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
function parsePropertyDecorator(decorator) {
|
|
73
|
-
const isPropertyDecorator = decorator.expression.type === AST_NODE_TYPES.CallExpression && decorator.expression.callee.type === AST_NODE_TYPES.Identifier && decorator.expression.callee.name === "property";
|
|
74
|
-
if (!isPropertyDecorator) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const callExpression = decorator?.expression.type === AST_NODE_TYPES.CallExpression ? decorator.expression : void 0;
|
|
78
|
-
if (callExpression === void 0) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const options = callExpression.arguments[0]?.type === AST_NODE_TYPES.ObjectExpression ? callExpression.arguments[0] : void 0;
|
|
82
|
-
const properties = options?.properties;
|
|
83
|
-
return {
|
|
84
|
-
callExpression,
|
|
85
|
-
options,
|
|
86
|
-
properties
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
function isBindThisCallee(callee) {
|
|
90
|
-
return callee.type === AST_NODE_TYPES.MemberExpression && // expression.identifier(this)
|
|
91
|
-
callee.property.type === AST_NODE_TYPES.Identifier && // expression.bind(this)
|
|
92
|
-
callee.property.name === "bind" && // expression.expression.bind(this)
|
|
93
|
-
callee.object.type === AST_NODE_TYPES.MemberExpression && // expression.identifier.bind(this)
|
|
94
|
-
callee.object.property.type === AST_NODE_TYPES.Identifier && // this.identifier.bind(this)
|
|
95
|
-
callee.object.object.type === AST_NODE_TYPES.ThisExpression;
|
|
96
|
-
}
|
|
97
9
|
const importDeclaration = `import { ${luminaJsxExportName} } from "${luminaEntrypointName}";`;
|
|
98
10
|
const description$k = `To use Lumina's JSX, you need to ${importDeclaration}`;
|
|
99
11
|
plugin.createRule({
|
|
@@ -1575,7 +1487,7 @@ plugin.createRule({
|
|
|
1575
1487
|
},
|
|
1576
1488
|
defaultOptions: [],
|
|
1577
1489
|
create(context) {
|
|
1578
|
-
|
|
1490
|
+
let className;
|
|
1579
1491
|
const hasLuminaDeclarations = context.sourceCode.text.includes("interface DeclareElements");
|
|
1580
1492
|
return {
|
|
1581
1493
|
TSModuleDeclaration(node) {
|
|
@@ -1583,20 +1495,10 @@ plugin.createRule({
|
|
|
1583
1495
|
if (luminaDeclarationInterface === void 0) {
|
|
1584
1496
|
return;
|
|
1585
1497
|
}
|
|
1586
|
-
luminaDeclarationInterface.
|
|
1587
|
-
if (member.type !== AST_NODE_TYPES.TSPropertySignature || member.computed) {
|
|
1588
|
-
return;
|
|
1589
|
-
}
|
|
1590
|
-
const type = member.typeAnnotation?.typeAnnotation;
|
|
1591
|
-
if (type?.type !== AST_NODE_TYPES.TSTypeReference || type.typeName.type !== AST_NODE_TYPES.Identifier) {
|
|
1592
|
-
return;
|
|
1593
|
-
}
|
|
1594
|
-
const className = type.typeName.name;
|
|
1595
|
-
declaredComponents.add(className);
|
|
1596
|
-
});
|
|
1498
|
+
className = getComponentDeclaration(luminaDeclarationInterface)?.typeAnnotation?.typeAnnotation.typeName.name;
|
|
1597
1499
|
},
|
|
1598
1500
|
ExportNamedDeclaration(node) {
|
|
1599
|
-
if (!hasLuminaDeclarations &&
|
|
1501
|
+
if (!hasLuminaDeclarations && className === void 0) {
|
|
1600
1502
|
return;
|
|
1601
1503
|
}
|
|
1602
1504
|
if (node.exportKind === "type") {
|
|
@@ -1620,7 +1522,7 @@ plugin.createRule({
|
|
|
1620
1522
|
) {
|
|
1621
1523
|
return;
|
|
1622
1524
|
} else if (node.declaration?.type === AST_NODE_TYPES.ClassDeclaration) {
|
|
1623
|
-
const isComponent =
|
|
1525
|
+
const isComponent = node.declaration.id?.name === className;
|
|
1624
1526
|
if (isComponent) {
|
|
1625
1527
|
return;
|
|
1626
1528
|
}
|
|
@@ -1631,7 +1533,7 @@ plugin.createRule({
|
|
|
1631
1533
|
});
|
|
1632
1534
|
},
|
|
1633
1535
|
ExportDefaultDeclaration(node) {
|
|
1634
|
-
if (!hasLuminaDeclarations &&
|
|
1536
|
+
if (!hasLuminaDeclarations && className === void 0) {
|
|
1635
1537
|
return;
|
|
1636
1538
|
}
|
|
1637
1539
|
context.report({
|
|
@@ -1640,7 +1542,7 @@ plugin.createRule({
|
|
|
1640
1542
|
});
|
|
1641
1543
|
},
|
|
1642
1544
|
ExportAllDeclaration(node) {
|
|
1643
|
-
if (!hasLuminaDeclarations &&
|
|
1545
|
+
if (!hasLuminaDeclarations && className === void 0) {
|
|
1644
1546
|
return;
|
|
1645
1547
|
}
|
|
1646
1548
|
if (node.exportKind === "type") {
|
|
@@ -9,6 +9,14 @@ export declare function checkForLuminaJsx(): LuminaJsxCheck & {
|
|
|
9
9
|
};
|
|
10
10
|
export declare function hasDecorator(node: Pick<TSESTree.PropertyDefinitionNonComputedName, "decorators">, decoratorName: string): boolean;
|
|
11
11
|
export declare function extractDeclareElementsInterface(node: TSESTree.TSModuleDeclaration): TSESTree.TSInterfaceDeclaration | undefined;
|
|
12
|
+
export declare function getComponentDeclaration(node: TSESTree.TSInterfaceDeclaration): {
|
|
13
|
+
key: TSESTree.Literal;
|
|
14
|
+
typeAnnotation: {
|
|
15
|
+
typeAnnotation: {
|
|
16
|
+
typeName: TSESTree.Identifier;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
} | undefined;
|
|
12
20
|
export declare function isCreateEvent(node: TSESTree.PropertyDefinition): boolean;
|
|
13
21
|
export declare const getProperty: (properties: TSESTree.ObjectLiteralElement[] | undefined, name: string) => TSESTree.Property["value"] | undefined;
|
|
14
22
|
export declare function isGetterWithoutSetter(node: TSESTree.MethodDefinition | TSESTree.PropertyDefinition): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as makeEslintPlugin } from "../../
|
|
1
|
+
import { m as makeEslintPlugin, e as extractDeclareElementsInterface, g as getComponentDeclaration } from "../../estree-Can6TC4w.js";
|
|
2
2
|
import { resolve } from "path/posix";
|
|
3
3
|
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
4
4
|
const plugin = makeEslintPlugin(
|
|
@@ -7,16 +7,16 @@ const plugin = makeEslintPlugin(
|
|
|
7
7
|
);
|
|
8
8
|
const isTestFile = (filePath) => filePath.includes("/test") || filePath.includes(".test") || filePath.includes(".spec") || filePath.includes("e2e") || filePath.includes("__") || filePath.includes("/.");
|
|
9
9
|
const isStorybookFile = (filePath) => filePath.includes(".stories");
|
|
10
|
-
const description$
|
|
10
|
+
const description$5 = `Imports of files outside the src/ folder are not-portable and likely to break for consumers of this package.`;
|
|
11
11
|
plugin.createRule({
|
|
12
12
|
name: "no-import-outside-src",
|
|
13
13
|
meta: {
|
|
14
14
|
docs: {
|
|
15
|
-
description: description$
|
|
15
|
+
description: description$5,
|
|
16
16
|
defaultLevel: "error"
|
|
17
17
|
},
|
|
18
18
|
messages: {
|
|
19
|
-
noImportOutsideSrc: description$
|
|
19
|
+
noImportOutsideSrc: description$5
|
|
20
20
|
},
|
|
21
21
|
type: "problem",
|
|
22
22
|
schema: []
|
|
@@ -50,16 +50,16 @@ plugin.createRule({
|
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
});
|
|
53
|
-
const description$
|
|
53
|
+
const description$4 = `Having two JSDoc comments next to each other is most likely a mistake - consider combining them into one, or separating them for clarity.`;
|
|
54
54
|
plugin.createRule({
|
|
55
55
|
name: "no-touching-jsdoc",
|
|
56
56
|
meta: {
|
|
57
57
|
docs: {
|
|
58
|
-
description: description$
|
|
58
|
+
description: description$4,
|
|
59
59
|
defaultLevel: "warn"
|
|
60
60
|
},
|
|
61
61
|
messages: {
|
|
62
|
-
noTouchingJsDoc: description$
|
|
62
|
+
noTouchingJsDoc: description$4
|
|
63
63
|
},
|
|
64
64
|
type: "problem",
|
|
65
65
|
schema: []
|
|
@@ -95,17 +95,17 @@ plugin.createRule({
|
|
|
95
95
|
}
|
|
96
96
|
});
|
|
97
97
|
const reTouchingJsDoc = /\*\/\s+\/\*\*/gu;
|
|
98
|
-
const description$
|
|
98
|
+
const description$3 = `@arcgis/core imports need to end with .js for better compatibility with ESM CDN builds for @arcgis/core and other packages.`;
|
|
99
99
|
const packagesToEnforce = ["@arcgis/core/", "@amcharts/amcharts4/", "@amcharts/amcharts5/"];
|
|
100
100
|
plugin.createRule({
|
|
101
101
|
name: "require-js-in-imports",
|
|
102
102
|
meta: {
|
|
103
103
|
docs: {
|
|
104
|
-
description: description$
|
|
104
|
+
description: description$3,
|
|
105
105
|
defaultLevel: "warn"
|
|
106
106
|
},
|
|
107
107
|
messages: {
|
|
108
|
-
requireJsInCoreImport: description$
|
|
108
|
+
requireJsInCoreImport: description$3
|
|
109
109
|
},
|
|
110
110
|
type: "problem",
|
|
111
111
|
fixable: "code",
|
|
@@ -139,17 +139,17 @@ plugin.createRule({
|
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
141
|
});
|
|
142
|
-
const description$
|
|
142
|
+
const description$2 = "Using .d.ts files is discouraged. Prefer .ts files instead, as they are type-checked and not in global scope.";
|
|
143
143
|
const allowedNames = /* @__PURE__ */ new Set(["vite-env.d.ts", "components.d.ts"]);
|
|
144
144
|
plugin.createRule({
|
|
145
145
|
name: "no-dts-files",
|
|
146
146
|
meta: {
|
|
147
147
|
docs: {
|
|
148
|
-
description: description$
|
|
148
|
+
description: description$2,
|
|
149
149
|
defaultLevel: "warn"
|
|
150
150
|
},
|
|
151
151
|
messages: {
|
|
152
|
-
avoidDtsFiles: description$
|
|
152
|
+
avoidDtsFiles: description$2
|
|
153
153
|
},
|
|
154
154
|
type: "suggestion",
|
|
155
155
|
schema: []
|
|
@@ -179,12 +179,12 @@ plugin.createRule({
|
|
|
179
179
|
};
|
|
180
180
|
}
|
|
181
181
|
});
|
|
182
|
-
const description = `Enforce consistent logging so that ArcGIS developers can easily debug errors or warnings logged by our web components, which may lack a meaningful context in compiled code. See [our documentation on @arcgis/toolkit/log](https://webgis.esri.com/references/toolkit/log).`;
|
|
182
|
+
const description$1 = `Enforce consistent logging so that ArcGIS developers can easily debug errors or warnings logged by our web components, which may lack a meaningful context in compiled code. See [our documentation on @arcgis/toolkit/log](https://webgis.esri.com/references/toolkit/log).`;
|
|
183
183
|
plugin.createRule({
|
|
184
184
|
name: "consistent-logging",
|
|
185
185
|
meta: {
|
|
186
186
|
docs: {
|
|
187
|
-
description,
|
|
187
|
+
description: description$1,
|
|
188
188
|
defaultLevel: "off"
|
|
189
189
|
// NOTE: this is turned on conditionally in root eslint config
|
|
190
190
|
},
|
|
@@ -217,6 +217,61 @@ plugin.createRule({
|
|
|
217
217
|
};
|
|
218
218
|
}
|
|
219
219
|
});
|
|
220
|
+
const description = `Do not use links like [](#something) as they are not portable across .d.ts, and are not validated at build time. Use {@link } syntax, or absolute links. See https://webgis.esri.com/webgis/core/core/documenting-api#link`;
|
|
221
|
+
plugin.createRule({
|
|
222
|
+
name: "no-unsafe-hash-links",
|
|
223
|
+
meta: {
|
|
224
|
+
docs: {
|
|
225
|
+
description,
|
|
226
|
+
defaultLevel: "warn"
|
|
227
|
+
},
|
|
228
|
+
messages: {
|
|
229
|
+
error: description
|
|
230
|
+
},
|
|
231
|
+
type: "problem",
|
|
232
|
+
schema: [],
|
|
233
|
+
fixable: "code"
|
|
234
|
+
},
|
|
235
|
+
defaultOptions: [],
|
|
236
|
+
create(context) {
|
|
237
|
+
let declareElementsInterface;
|
|
238
|
+
return {
|
|
239
|
+
"TSModuleDeclaration"(node) {
|
|
240
|
+
declareElementsInterface = extractDeclareElementsInterface(node);
|
|
241
|
+
},
|
|
242
|
+
"Program:exit"() {
|
|
243
|
+
if (declareElementsInterface === void 0 && !context.sourceCode.text.includes("@public") && !context.sourceCode.text.includes("@internal")) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
for (const match of context.sourceCode.text.matchAll(reHashLink)) {
|
|
247
|
+
const fullMatch = match[0];
|
|
248
|
+
const anchor = match[2];
|
|
249
|
+
const replacement = computeReplacement(declareElementsInterface, anchor);
|
|
250
|
+
context.report({
|
|
251
|
+
messageId: "error",
|
|
252
|
+
loc: {
|
|
253
|
+
start: context.sourceCode.getLocFromIndex(match.index),
|
|
254
|
+
end: context.sourceCode.getLocFromIndex(match.index + fullMatch.length)
|
|
255
|
+
},
|
|
256
|
+
fix: replacement === void 0 ? void 0 : (fixer) => fixer.replaceTextRange([match.index, match.index + fullMatch.length], `{@link ${replacement}}`)
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
const reHashLink = /\[([^\]\n]+)\]\(#([^)]+)\)/gu;
|
|
264
|
+
function computeReplacement(declareElementsInterface, anchor) {
|
|
265
|
+
if (declareElementsInterface === void 0) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const declaration = getComponentDeclaration(declareElementsInterface);
|
|
269
|
+
if (declaration === void 0) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const tagName = declaration.key.value;
|
|
273
|
+
return `components/${tagName}#${anchor}`;
|
|
274
|
+
}
|
|
220
275
|
const webgisPlugin = plugin.finalize();
|
|
221
276
|
export {
|
|
222
277
|
webgisPlugin
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcgis/eslint-config",
|
|
3
|
-
"version": "5.0.0
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "ESLint configuration for arcgis-web-components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -20,16 +20,19 @@
|
|
|
20
20
|
],
|
|
21
21
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@arcgis/toolkit": "5.0.0-next.98",
|
|
24
23
|
"@eslint/js": "^9.39.1",
|
|
25
24
|
"@eslint/markdown": "^7.5.1",
|
|
26
25
|
"@types/confusing-browser-globals": "^1.0.3",
|
|
26
|
+
"@typescript-eslint/utils": "^8.46.4",
|
|
27
27
|
"confusing-browser-globals": "^1.0.11",
|
|
28
|
+
"eslint-plugin-package-json": "^0.88.1",
|
|
28
29
|
"eslint-plugin-storybook": "^0.12.0",
|
|
29
30
|
"globals": "^16.5.0",
|
|
31
|
+
"jsonc-eslint-parser": "^2.0.0",
|
|
30
32
|
"tslib": "^2.8.1",
|
|
31
33
|
"typescript": "~5.9.3",
|
|
32
|
-
"typescript-eslint": "^8.46.3"
|
|
34
|
+
"typescript-eslint": "^8.46.3",
|
|
35
|
+
"@arcgis/toolkit": "5.0.0"
|
|
33
36
|
},
|
|
34
37
|
"peerDependencies": {
|
|
35
38
|
"eslint": "^9.39.1"
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
2
|
-
const version = "5.0.0-next.98";
|
|
3
|
-
const packageJson = {
|
|
4
|
-
version
|
|
5
|
-
};
|
|
6
|
-
function makeEslintPlugin(pluginName, urlCreator) {
|
|
7
|
-
const rules = [];
|
|
8
|
-
const creator = ESLintUtils.RuleCreator(urlCreator);
|
|
9
|
-
return {
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
11
|
-
createRule(rule) {
|
|
12
|
-
const { meta, name, ...rest } = rule;
|
|
13
|
-
const docs = { ...meta.docs, name };
|
|
14
|
-
const ruleModule = creator({ ...rest, meta: { ...meta, docs }, name });
|
|
15
|
-
rules.push(ruleModule);
|
|
16
|
-
return ruleModule;
|
|
17
|
-
},
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
19
|
-
finalize() {
|
|
20
|
-
const config = {
|
|
21
|
-
rules: Object.fromEntries(
|
|
22
|
-
rules.map((rule) => [`${pluginName}/${rule.meta.docs.name}`, rule.meta.docs.defaultLevel])
|
|
23
|
-
)
|
|
24
|
-
};
|
|
25
|
-
const plugin = {
|
|
26
|
-
meta: { name: `@arcgis/eslint-plugin-${pluginName}`, version: packageJson.version },
|
|
27
|
-
configs: {
|
|
28
|
-
recommended: config
|
|
29
|
-
},
|
|
30
|
-
rules: Object.fromEntries(rules.map((rule) => [rule.meta.docs.name, rule]))
|
|
31
|
-
};
|
|
32
|
-
config.plugins = {
|
|
33
|
-
[pluginName]: plugin
|
|
34
|
-
};
|
|
35
|
-
return plugin;
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
export {
|
|
40
|
-
makeEslintPlugin as m
|
|
41
|
-
};
|