eslint-soml 0.0.5 → 0.0.6
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/index.d.ts +13 -0
- package/package.json +6 -6
- package/readme.md +4 -4
- package/rules/no-duplicate-array-items.js +11 -10
- package/rules/no-quoted-values-in-arrays.js +1 -0
package/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
FloatNode,
|
|
19
19
|
BooleanNode,
|
|
20
20
|
NullNode,
|
|
21
|
+
DateNode,
|
|
21
22
|
InstantNode,
|
|
22
23
|
DurationNode,
|
|
23
24
|
Token,
|
|
@@ -37,6 +38,7 @@ export type {
|
|
|
37
38
|
FloatNode,
|
|
38
39
|
BooleanNode,
|
|
39
40
|
NullNode,
|
|
41
|
+
DateNode,
|
|
40
42
|
InstantNode,
|
|
41
43
|
DurationNode,
|
|
42
44
|
DurationPart,
|
|
@@ -178,6 +180,17 @@ export interface SomlRuleVisitor extends RuleVisitor, CustomRuleVisitorWithExit<
|
|
|
178
180
|
Float?(node: FloatNode, parent: ValueParent): void;
|
|
179
181
|
Boolean?(node: BooleanNode, parent: ValueParent): void;
|
|
180
182
|
Null?(node: NullNode, parent: ValueParent): void;
|
|
183
|
+
/**
|
|
184
|
+
Visits a calendar date without needing Temporal to read its components.
|
|
185
|
+
|
|
186
|
+
@example
|
|
187
|
+
```
|
|
188
|
+
Date(node) {
|
|
189
|
+
const year: number = node.year;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
*/
|
|
193
|
+
Date?(node: DateNode, parent: ValueParent): void;
|
|
181
194
|
Instant?(node: InstantNode, parent: ValueParent): void;
|
|
182
195
|
Duration?(node: DurationNode, parent: ValueParent): void;
|
|
183
196
|
}> {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-soml",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "ESLint plugin for SOML, a config format for humans",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "github:soml-lang/eslint-soml",
|
|
@@ -53,23 +53,23 @@
|
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@eslint/core": "^1.2.1",
|
|
55
55
|
"@eslint/plugin-kit": "^0.7.3",
|
|
56
|
-
"soml-lang": "^0.0.
|
|
56
|
+
"soml-lang": "^0.0.8"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@babel/code-frame": "^8.0.6",
|
|
60
60
|
"@eslint-community/eslint-utils": "^4.10.1",
|
|
61
|
-
"@typescript-eslint/types": "^8.
|
|
61
|
+
"@typescript-eslint/types": "^8.72.1",
|
|
62
62
|
"enquirer": "^2.4.1",
|
|
63
|
-
"eslint": "^10.
|
|
63
|
+
"eslint": "^10.14.0",
|
|
64
64
|
"eslint-config-xo": "^7.0.0",
|
|
65
65
|
"eslint-doc-generator": "^3.7.1",
|
|
66
66
|
"eslint-plugin-eslint-plugin": "^7.6.2",
|
|
67
|
-
"eslint-plugin-jsdoc": "^65.
|
|
67
|
+
"eslint-plugin-jsdoc": "^65.4.2",
|
|
68
68
|
"indent-string": "^5.0.0",
|
|
69
69
|
"markdownlint-cli": "^0.50.0",
|
|
70
70
|
"nano-spawn": "^2.1.0",
|
|
71
71
|
"node-style-text": "^2.1.2",
|
|
72
|
-
"npm-run-all2": "^9.0.
|
|
72
|
+
"npm-run-all2": "^9.0.4",
|
|
73
73
|
"open-editor": "^6.0.0",
|
|
74
74
|
"outdent": "^0.8.0",
|
|
75
75
|
"typescript": "^6.0.3",
|
package/readme.md
CHANGED
|
@@ -16,7 +16,7 @@ npm install --save-dev eslint eslint-soml
|
|
|
16
16
|
|
|
17
17
|
**Requires Node.js 22.13 or later, ESLint `>=10.4`, [flat config](https://eslint.org/docs/latest/use/configure/configuration-files), and [ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#how-can-i-make-my-typescript-project-output-esm).**
|
|
18
18
|
|
|
19
|
-
The rules of this plugin do not need `Temporal`, so they work on every supported Node.js version, also for files with instants and durations. Only reading the `value` of
|
|
19
|
+
The rules of this plugin do not need `Temporal`, so they work on every supported Node.js version, also for files with dates, instants, and durations. Only reading the `value` of a `Date`, `Instant`, or `Duration` node needs it, as in your own rule or in a `no-restricted-syntax` selector that matches on `value`, such as `[value=1]`. Node.js 26 and later have `Temporal` built in. On older versions, load a [`Temporal` polyfill](https://github.com/fullcalendar/temporal-polyfill) first: make `import 'temporal-polyfill/global';` the first import in `eslint.config.js`, before `eslint-soml`.
|
|
20
20
|
|
|
21
21
|
## Usage
|
|
22
22
|
|
|
@@ -137,8 +137,8 @@ A selector can also say what the program that reads a file does not support. SOM
|
|
|
137
137
|
message: 'This program does not support the key `__proto__`.',
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
|
-
selector: ':matches(Instant, Duration)',
|
|
141
|
-
message: 'This program does not support instants and durations.',
|
|
140
|
+
selector: ':matches(Date, Instant, Duration)',
|
|
141
|
+
message: 'This program does not support dates, instants, and durations.',
|
|
142
142
|
},
|
|
143
143
|
],
|
|
144
144
|
```
|
|
@@ -187,7 +187,7 @@ A block that shows a mistake on purpose can be skipped with `<!-- eslint-skip --
|
|
|
187
187
|
| [no-decimal-file-modes](docs/rules/no-decimal-file-modes.md) | Disallow file modes written as decimal numbers. | ✅ ☑️ | | 💡 |
|
|
188
188
|
| [no-dotted-key-collisions](docs/rules/no-dotted-key-collisions.md) | Disallow quoted keys with a `.` that read as a path into an object next to them. | ✅ | | |
|
|
189
189
|
| [no-doubled-backslashes-in-literal-strings](docs/rules/no-doubled-backslashes-in-literal-strings.md) | Disallow doubled backslashes in literal strings, such as `'^\\d+$'`. | ✅ | | 💡 |
|
|
190
|
-
| [no-duplicate-array-items](docs/rules/no-duplicate-array-items.md) | Disallow
|
|
190
|
+
| [no-duplicate-array-items](docs/rules/no-duplicate-array-items.md) | Disallow duplicate strings and dates in an array. | | | 💡 |
|
|
191
191
|
| [no-empty-keys](docs/rules/no-empty-keys.md) | Disallow empty and whitespace-only keys. | ✅ ☑️ | | |
|
|
192
192
|
| [no-escapes-in-literal-strings](docs/rules/no-escapes-in-literal-strings.md) | Disallow escapes in literal strings, such as `'Line one\nLine two'`. | ✅ | | 💡 |
|
|
193
193
|
| [no-escapes-in-paths](docs/rules/no-escapes-in-paths.md) | Disallow `\n` and `\t` escapes in Windows paths. | ✅ ☑️ | | 💡 |
|
|
@@ -4,7 +4,6 @@ import {escapeInvisibleCharacters, hasAdjacentComment, isPunctuator} from './uti
|
|
|
4
4
|
/**
|
|
5
5
|
@import {SomlContext} from './rule/soml-context.js';
|
|
6
6
|
@import {SomlRule} from './rule/to-eslint-rule.js';
|
|
7
|
-
@import {StringNode} from 'soml-lang';
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
const MESSAGE_ID_ERROR = 'no-duplicate-array-items/error';
|
|
@@ -48,20 +47,22 @@ const create = context => {
|
|
|
48
47
|
|
|
49
48
|
context.on('Array', function * (node) {
|
|
50
49
|
/**
|
|
51
|
-
@type {Map<string,
|
|
50
|
+
@type {Map<string, number>}
|
|
52
51
|
*/
|
|
53
52
|
const seen = new Map();
|
|
54
53
|
|
|
55
54
|
for (const item of node.elements) {
|
|
56
|
-
// Only strings, because numbers and the like repeat in data, as in `[0, 0, 1]`.
|
|
57
|
-
if (item.type !== 'String') {
|
|
55
|
+
// Only strings and dates, because numbers and the like repeat in data, as in `[0, 0, 1]`.
|
|
56
|
+
if (item.type !== 'String' && item.type !== 'Date') {
|
|
58
57
|
continue;
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
const
|
|
60
|
+
const value = item.type === 'Date' ? `${item.year}-${item.month}-${item.day}` : item.value;
|
|
61
|
+
const key = `${item.type}:${value}`;
|
|
62
|
+
const firstLine = seen.get(key);
|
|
62
63
|
|
|
63
|
-
if (
|
|
64
|
-
seen.set(
|
|
64
|
+
if (firstLine === undefined) {
|
|
65
|
+
seen.set(key, sourceCode.getLoc(item).start.line);
|
|
65
66
|
continue;
|
|
66
67
|
}
|
|
67
68
|
|
|
@@ -73,8 +74,8 @@ const create = context => {
|
|
|
73
74
|
messageId: MESSAGE_ID_ERROR,
|
|
74
75
|
data: {
|
|
75
76
|
// A block string spans lines, so it is shown as a one-line string with the same value. A bidirectional control is escaped, or it could reorder the message, whichever spelling the string uses.
|
|
76
|
-
item: escapeInvisibleCharacters(item.block ? stringifyValue(item.value) : sourceCode.getText(item)),
|
|
77
|
-
line:
|
|
77
|
+
item: escapeInvisibleCharacters(item.type === 'String' && item.block ? stringifyValue(item.value) : sourceCode.getText(item)),
|
|
78
|
+
line: firstLine,
|
|
78
79
|
},
|
|
79
80
|
// Removing an item changes the value, so it is a suggestion. It is left out when it would remove a comment.
|
|
80
81
|
suggest: hasComment
|
|
@@ -98,7 +99,7 @@ const config = {
|
|
|
98
99
|
meta: {
|
|
99
100
|
type: 'problem',
|
|
100
101
|
docs: {
|
|
101
|
-
description: 'Disallow
|
|
102
|
+
description: 'Disallow duplicate strings and dates in an array.',
|
|
102
103
|
recommended: false,
|
|
103
104
|
},
|
|
104
105
|
hasSuggestions: true,
|