eslint-plugin-yml 0.12.0 → 0.15.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/README.md +14 -1
- package/lib/rules/indent.js +6 -0
- package/lib/rules/sort-keys.js +185 -118
- package/lib/rules/sort-sequence-values.d.ts +2 -0
- package/lib/rules/sort-sequence-values.js +512 -0
- package/lib/utils/index.js +5 -1
- package/lib/utils/rules.js +2 -0
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -146,6 +146,18 @@ Example **.vscode/settings.json**:
|
|
|
146
146
|
}
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
+
### JetBrains WebStorm IDEs
|
|
150
|
+
|
|
151
|
+
In any of the JetBrains IDEs you can [configure the linting scope](https://www.jetbrains.com/help/webstorm/eslint.html#ws_eslint_configure_scope).
|
|
152
|
+
Following the steps in their help document, you can add YAML files to the scope like so:
|
|
153
|
+
|
|
154
|
+
1. Open the **Settings/Preferences** dialog, go to **Languages and Frameworks** | **JavaScript** | **Code Quality Tools** | **ESLint**, and select **Automatic ESLint configuration** or **Manual ESLint configuration**.
|
|
155
|
+
2. In the **Run for files** field, update the pattern that defines the set of files to be linted to include YAML files as well:
|
|
156
|
+
```
|
|
157
|
+
{**/*,*}.{js,ts,jsx,tsx,html,vue,yaml,yml}
|
|
158
|
+
^^^^ ^^^
|
|
159
|
+
```
|
|
160
|
+
|
|
149
161
|
<!--USAGE_GUIDE_END-->
|
|
150
162
|
<!--USAGE_SECTION_END-->
|
|
151
163
|
|
|
@@ -176,6 +188,8 @@ The rules with the following star :star: are included in the config.
|
|
|
176
188
|
| [yml/plain-scalar](https://ota-meshi.github.io/eslint-plugin-yml/rules/plain-scalar.html) | require or disallow plain style scalar. | :wrench: | | :star: |
|
|
177
189
|
| [yml/quotes](https://ota-meshi.github.io/eslint-plugin-yml/rules/quotes.html) | enforce the consistent use of either double, or single quotes | :wrench: | | :star: |
|
|
178
190
|
| [yml/require-string-key](https://ota-meshi.github.io/eslint-plugin-yml/rules/require-string-key.html) | disallow mapping keys other than strings | | | |
|
|
191
|
+
| [yml/sort-keys](https://ota-meshi.github.io/eslint-plugin-yml/rules/sort-keys.html) | require mapping keys to be sorted | :wrench: | | |
|
|
192
|
+
| [yml/sort-sequence-values](https://ota-meshi.github.io/eslint-plugin-yml/rules/sort-sequence-values.html) | require sequence values to be sorted | :wrench: | | |
|
|
179
193
|
| [yml/vue-custom-block/no-parsing-error](https://ota-meshi.github.io/eslint-plugin-yml/rules/vue-custom-block/no-parsing-error.html) | disallow parsing errors in Vue custom blocks | | :star: | :star: |
|
|
180
194
|
|
|
181
195
|
### Extension Rules
|
|
@@ -189,7 +203,6 @@ The rules with the following star :star: are included in the config.
|
|
|
189
203
|
| [yml/key-spacing](https://ota-meshi.github.io/eslint-plugin-yml/rules/key-spacing.html) | enforce consistent spacing between keys and values in mapping pairs | :wrench: | | :star: |
|
|
190
204
|
| [yml/no-irregular-whitespace](https://ota-meshi.github.io/eslint-plugin-yml/rules/no-irregular-whitespace.html) | disallow irregular whitespace | | :star: | :star: |
|
|
191
205
|
| [yml/no-multiple-empty-lines](https://ota-meshi.github.io/eslint-plugin-yml/rules/no-multiple-empty-lines.html) | disallow multiple empty lines | :wrench: | | |
|
|
192
|
-
| [yml/sort-keys](https://ota-meshi.github.io/eslint-plugin-yml/rules/sort-keys.html) | require mapping keys to be sorted | :wrench: | | |
|
|
193
206
|
| [yml/spaced-comment](https://ota-meshi.github.io/eslint-plugin-yml/rules/spaced-comment.html) | enforce consistent spacing after the `#` in a comment | :wrench: | | :star: |
|
|
194
207
|
|
|
195
208
|
<!--RULES_TABLE_END-->
|
package/lib/rules/indent.js
CHANGED
|
@@ -37,6 +37,7 @@ exports.default = (0, utils_1.createRule)("indent", {
|
|
|
37
37
|
const sourceCode = context.getSourceCode();
|
|
38
38
|
const offsets = new Map();
|
|
39
39
|
const marks = new Set();
|
|
40
|
+
const blockLiteralMarks = new Set();
|
|
40
41
|
const scalars = new Map();
|
|
41
42
|
function setOffset(token, offset, baseToken, options) {
|
|
42
43
|
var _a;
|
|
@@ -224,6 +225,7 @@ exports.default = (0, utils_1.createRule)("indent", {
|
|
|
224
225
|
const literal = sourceCode.getLastToken(node);
|
|
225
226
|
setOffset(literal, 1, mark);
|
|
226
227
|
scalars.set(literal, node);
|
|
228
|
+
blockLiteralMarks.add(mark);
|
|
227
229
|
}
|
|
228
230
|
else {
|
|
229
231
|
scalars.set(sourceCode.getFirstToken(node), node);
|
|
@@ -283,6 +285,10 @@ exports.default = (0, utils_1.createRule)("indent", {
|
|
|
283
285
|
1,
|
|
284
286
|
actualOffset: nextToken.range[0] - token.range[1],
|
|
285
287
|
});
|
|
288
|
+
if (blockLiteralMarks.has(nextToken)) {
|
|
289
|
+
lineTokens.unshift(nextToken);
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
286
292
|
token = nextToken;
|
|
287
293
|
expectedIndent = nextExpectedIndent;
|
|
288
294
|
cacheExpectedIndent = expectedIndent;
|
package/lib/rules/sort-keys.js
CHANGED
|
@@ -23,6 +23,35 @@ function getPropertyName(node, sourceCode) {
|
|
|
23
23
|
}
|
|
24
24
|
return sourceCode.text.slice(...target.range);
|
|
25
25
|
}
|
|
26
|
+
class YAMLPairData {
|
|
27
|
+
constructor(mapping, node, index, anchorAlias) {
|
|
28
|
+
this.cachedName = null;
|
|
29
|
+
this.mapping = mapping;
|
|
30
|
+
this.node = node;
|
|
31
|
+
this.index = index;
|
|
32
|
+
this.anchorAlias = anchorAlias;
|
|
33
|
+
}
|
|
34
|
+
get reportLoc() {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
return (_b = (_a = this.node.key) === null || _a === void 0 ? void 0 : _a.loc) !== null && _b !== void 0 ? _b : this.node.loc;
|
|
37
|
+
}
|
|
38
|
+
get name() {
|
|
39
|
+
var _a;
|
|
40
|
+
return ((_a = this.cachedName) !== null && _a !== void 0 ? _a : (this.cachedName = getPropertyName(this.node, this.mapping.sourceCode)));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
class YAMLMappingData {
|
|
44
|
+
constructor(node, sourceCode, anchorAliasMap) {
|
|
45
|
+
this.cachedProperties = null;
|
|
46
|
+
this.node = node;
|
|
47
|
+
this.sourceCode = sourceCode;
|
|
48
|
+
this.anchorAliasMap = anchorAliasMap;
|
|
49
|
+
}
|
|
50
|
+
get pairs() {
|
|
51
|
+
var _a;
|
|
52
|
+
return ((_a = this.cachedProperties) !== null && _a !== void 0 ? _a : (this.cachedProperties = this.node.pairs.map((e, index) => new YAMLPairData(this, e, index, this.anchorAliasMap.get(e)))));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
26
55
|
function isCompatibleWithESLintOptions(options) {
|
|
27
56
|
if (options.length === 0) {
|
|
28
57
|
return true;
|
|
@@ -44,7 +73,7 @@ function buildValidatorFromType(order, insensitive, natural) {
|
|
|
44
73
|
const baseCompare = compare;
|
|
45
74
|
compare = (args) => baseCompare(args.reverse());
|
|
46
75
|
}
|
|
47
|
-
return (a, b) => compare([a, b]);
|
|
76
|
+
return (a, b) => compare([a.name, b.name]);
|
|
48
77
|
}
|
|
49
78
|
function parseOptions(options, sourceCode) {
|
|
50
79
|
var _a, _b, _c;
|
|
@@ -56,16 +85,15 @@ function parseOptions(options, sourceCode) {
|
|
|
56
85
|
const minKeys = (_c = obj.minKeys) !== null && _c !== void 0 ? _c : 2;
|
|
57
86
|
return [
|
|
58
87
|
{
|
|
59
|
-
isTargetMapping: () =>
|
|
88
|
+
isTargetMapping: (data) => data.node.pairs.length >= minKeys,
|
|
60
89
|
ignore: () => false,
|
|
61
90
|
isValidOrder: buildValidatorFromType(type, insensitive, natural),
|
|
62
|
-
minKeys,
|
|
63
91
|
orderText: `${natural ? "natural " : ""}${insensitive ? "insensitive " : ""}${type}ending`,
|
|
64
92
|
},
|
|
65
93
|
];
|
|
66
94
|
}
|
|
67
95
|
return options.map((opt) => {
|
|
68
|
-
var _a, _b, _c;
|
|
96
|
+
var _a, _b, _c, _d, _e;
|
|
69
97
|
const order = opt.order;
|
|
70
98
|
const pathPattern = new RegExp(opt.pathPattern);
|
|
71
99
|
const hasProperties = (_a = opt.hasProperties) !== null && _a !== void 0 ? _a : [];
|
|
@@ -78,30 +106,65 @@ function parseOptions(options, sourceCode) {
|
|
|
78
106
|
isTargetMapping,
|
|
79
107
|
ignore: () => false,
|
|
80
108
|
isValidOrder: buildValidatorFromType(type, insensitive, natural),
|
|
81
|
-
minKeys,
|
|
82
109
|
orderText: `${natural ? "natural " : ""}${insensitive ? "insensitive " : ""}${type}ending`,
|
|
83
110
|
};
|
|
84
111
|
}
|
|
112
|
+
const parsedOrder = [];
|
|
113
|
+
for (const o of order) {
|
|
114
|
+
if (typeof o === "string") {
|
|
115
|
+
parsedOrder.push({
|
|
116
|
+
test: (data) => data.name === o,
|
|
117
|
+
isValidNestOrder: () => true,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const keyPattern = o.keyPattern
|
|
122
|
+
? new RegExp(o.keyPattern)
|
|
123
|
+
: null;
|
|
124
|
+
const nestOrder = (_d = o.order) !== null && _d !== void 0 ? _d : {};
|
|
125
|
+
const type = (_e = nestOrder.type) !== null && _e !== void 0 ? _e : "asc";
|
|
126
|
+
const insensitive = nestOrder.caseSensitive === false;
|
|
127
|
+
const natural = Boolean(nestOrder.natural);
|
|
128
|
+
parsedOrder.push({
|
|
129
|
+
test: (data) => keyPattern ? keyPattern.test(data.name) : true,
|
|
130
|
+
isValidNestOrder: buildValidatorFromType(type, insensitive, natural),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
85
134
|
return {
|
|
86
135
|
isTargetMapping,
|
|
87
|
-
ignore: (
|
|
136
|
+
ignore: (data) => parsedOrder.every((p) => !p.test(data)),
|
|
88
137
|
isValidOrder(a, b) {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
138
|
+
for (const p of parsedOrder) {
|
|
139
|
+
const matchA = p.test(a);
|
|
140
|
+
const matchB = p.test(b);
|
|
141
|
+
if (!matchA || !matchB) {
|
|
142
|
+
if (matchA) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
if (matchB) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
return p.isValidNestOrder(a, b);
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
92
153
|
},
|
|
93
|
-
minKeys,
|
|
94
154
|
orderText: "specified",
|
|
95
155
|
};
|
|
96
|
-
function isTargetMapping(
|
|
156
|
+
function isTargetMapping(data) {
|
|
157
|
+
if (data.node.pairs.length < minKeys) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
97
160
|
if (hasProperties.length > 0) {
|
|
98
|
-
const names = new Set(
|
|
161
|
+
const names = new Set(data.pairs.map((p) => p.name));
|
|
99
162
|
if (!hasProperties.every((name) => names.has(name))) {
|
|
100
163
|
return false;
|
|
101
164
|
}
|
|
102
165
|
}
|
|
103
166
|
let path = "";
|
|
104
|
-
let curr = node;
|
|
167
|
+
let curr = data.node;
|
|
105
168
|
let p = curr.parent;
|
|
106
169
|
while (p) {
|
|
107
170
|
if (p.type === "YAMLPair") {
|
|
@@ -127,13 +190,28 @@ function parseOptions(options, sourceCode) {
|
|
|
127
190
|
}
|
|
128
191
|
});
|
|
129
192
|
}
|
|
130
|
-
const
|
|
193
|
+
const ALLOW_ORDER_TYPES = ["asc", "desc"];
|
|
194
|
+
const ORDER_OBJECT_SCHEMA = {
|
|
195
|
+
type: "object",
|
|
196
|
+
properties: {
|
|
197
|
+
type: {
|
|
198
|
+
enum: ALLOW_ORDER_TYPES,
|
|
199
|
+
},
|
|
200
|
+
caseSensitive: {
|
|
201
|
+
type: "boolean",
|
|
202
|
+
},
|
|
203
|
+
natural: {
|
|
204
|
+
type: "boolean",
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
additionalProperties: false,
|
|
208
|
+
};
|
|
131
209
|
exports.default = (0, utils_1.createRule)("sort-keys", {
|
|
132
210
|
meta: {
|
|
133
211
|
docs: {
|
|
134
212
|
description: "require mapping keys to be sorted",
|
|
135
213
|
categories: null,
|
|
136
|
-
extensionRule:
|
|
214
|
+
extensionRule: false,
|
|
137
215
|
layout: false,
|
|
138
216
|
},
|
|
139
217
|
fixable: "code",
|
|
@@ -153,24 +231,24 @@ exports.default = (0, utils_1.createRule)("sort-keys", {
|
|
|
153
231
|
oneOf: [
|
|
154
232
|
{
|
|
155
233
|
type: "array",
|
|
156
|
-
items: {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
},
|
|
234
|
+
items: {
|
|
235
|
+
anyOf: [
|
|
236
|
+
{ type: "string" },
|
|
237
|
+
{
|
|
238
|
+
type: "object",
|
|
239
|
+
properties: {
|
|
240
|
+
keyPattern: {
|
|
241
|
+
type: "string",
|
|
242
|
+
},
|
|
243
|
+
order: ORDER_OBJECT_SCHEMA,
|
|
244
|
+
},
|
|
245
|
+
additionalProperties: false,
|
|
246
|
+
},
|
|
247
|
+
],
|
|
171
248
|
},
|
|
172
|
-
|
|
249
|
+
uniqueItems: true,
|
|
173
250
|
},
|
|
251
|
+
ORDER_OBJECT_SCHEMA,
|
|
174
252
|
],
|
|
175
253
|
},
|
|
176
254
|
minKeys: {
|
|
@@ -187,7 +265,7 @@ exports.default = (0, utils_1.createRule)("sort-keys", {
|
|
|
187
265
|
type: "array",
|
|
188
266
|
items: [
|
|
189
267
|
{
|
|
190
|
-
enum:
|
|
268
|
+
enum: ALLOW_ORDER_TYPES,
|
|
191
269
|
},
|
|
192
270
|
{
|
|
193
271
|
type: "object",
|
|
@@ -216,51 +294,81 @@ exports.default = (0, utils_1.createRule)("sort-keys", {
|
|
|
216
294
|
type: "suggestion",
|
|
217
295
|
},
|
|
218
296
|
create(context) {
|
|
219
|
-
const sourceCode = context.getSourceCode();
|
|
220
297
|
if (!context.parserServices.isYAML) {
|
|
221
298
|
return {};
|
|
222
299
|
}
|
|
300
|
+
const sourceCode = context.getSourceCode();
|
|
223
301
|
const parsedOptions = parseOptions(context.options, sourceCode);
|
|
224
|
-
let mappingStack = {
|
|
225
|
-
upper: null,
|
|
226
|
-
prevList: [],
|
|
227
|
-
numKeys: 0,
|
|
228
|
-
option: null,
|
|
229
|
-
};
|
|
230
|
-
let pairStack = {
|
|
231
|
-
upper: null,
|
|
232
|
-
anchors: new Set(),
|
|
233
|
-
aliases: new Set(),
|
|
234
|
-
};
|
|
235
302
|
function isValidOrder(prevData, thisData, option) {
|
|
236
|
-
if (option.isValidOrder(prevData
|
|
303
|
+
if (option.isValidOrder(prevData, thisData)) {
|
|
237
304
|
return true;
|
|
238
305
|
}
|
|
239
|
-
for (const aliasName of thisData.aliases) {
|
|
240
|
-
if (prevData.anchors.has(aliasName)) {
|
|
306
|
+
for (const aliasName of thisData.anchorAlias.aliases) {
|
|
307
|
+
if (prevData.anchorAlias.anchors.has(aliasName)) {
|
|
241
308
|
return true;
|
|
242
309
|
}
|
|
243
310
|
}
|
|
244
|
-
for (const anchorName of thisData.anchors) {
|
|
245
|
-
if (prevData.aliases.has(anchorName)) {
|
|
311
|
+
for (const anchorName of thisData.anchorAlias.anchors) {
|
|
312
|
+
if (prevData.anchorAlias.aliases.has(anchorName)) {
|
|
246
313
|
return true;
|
|
247
314
|
}
|
|
248
315
|
}
|
|
249
316
|
return false;
|
|
250
317
|
}
|
|
318
|
+
function ignore(data, option) {
|
|
319
|
+
if (!data.node.key && !data.node.value) {
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
return option.ignore(data);
|
|
323
|
+
}
|
|
324
|
+
function verifyPair(data, option) {
|
|
325
|
+
if (ignore(data, option)) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const prevList = data.mapping.pairs
|
|
329
|
+
.slice(0, data.index)
|
|
330
|
+
.reverse()
|
|
331
|
+
.filter((d) => !ignore(d, option));
|
|
332
|
+
if (prevList.length === 0) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const prev = prevList[0];
|
|
336
|
+
if (!isValidOrder(prev, data, option)) {
|
|
337
|
+
context.report({
|
|
338
|
+
loc: data.reportLoc,
|
|
339
|
+
messageId: "sortKeys",
|
|
340
|
+
data: {
|
|
341
|
+
thisName: data.name,
|
|
342
|
+
prevName: prev.name,
|
|
343
|
+
orderText: option.orderText,
|
|
344
|
+
},
|
|
345
|
+
*fix(fixer) {
|
|
346
|
+
let moveTarget = prevList[0];
|
|
347
|
+
for (const prev of prevList) {
|
|
348
|
+
if (isValidOrder(prev, data, option)) {
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
moveTarget = prev;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (data.mapping.node.style === "flow") {
|
|
356
|
+
yield* fixForFlow(fixer, data, moveTarget);
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
yield* fixForBlock(fixer, data, moveTarget);
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
let pairStack = {
|
|
366
|
+
upper: null,
|
|
367
|
+
anchors: new Set(),
|
|
368
|
+
aliases: new Set(),
|
|
369
|
+
};
|
|
370
|
+
const anchorAliasMap = new Map();
|
|
251
371
|
return {
|
|
252
|
-
YAMLMapping(node) {
|
|
253
|
-
mappingStack = {
|
|
254
|
-
upper: mappingStack,
|
|
255
|
-
prevList: [],
|
|
256
|
-
numKeys: node.pairs.length,
|
|
257
|
-
option: parsedOptions.find((o) => o.isTargetMapping(node)) ||
|
|
258
|
-
null,
|
|
259
|
-
};
|
|
260
|
-
},
|
|
261
|
-
"YAMLMapping:exit"() {
|
|
262
|
-
mappingStack = mappingStack.upper;
|
|
263
|
-
},
|
|
264
372
|
YAMLPair() {
|
|
265
373
|
pairStack = {
|
|
266
374
|
upper: pairStack,
|
|
@@ -279,69 +387,28 @@ exports.default = (0, utils_1.createRule)("sort-keys", {
|
|
|
279
387
|
}
|
|
280
388
|
},
|
|
281
389
|
"YAMLPair:exit"(node) {
|
|
282
|
-
|
|
390
|
+
anchorAliasMap.set(node, pairStack);
|
|
283
391
|
const { anchors, aliases } = pairStack;
|
|
284
392
|
pairStack = pairStack.upper;
|
|
285
393
|
pairStack.anchors = new Set([...pairStack.anchors, ...anchors]);
|
|
286
394
|
pairStack.aliases = new Set([...pairStack.aliases, ...aliases]);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const option =
|
|
395
|
+
},
|
|
396
|
+
"YAMLMapping:exit"(node) {
|
|
397
|
+
const data = new YAMLMappingData(node, sourceCode, anchorAliasMap);
|
|
398
|
+
const option = parsedOptions.find((o) => o.isTargetMapping(data));
|
|
291
399
|
if (!option) {
|
|
292
400
|
return;
|
|
293
401
|
}
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
const prevList = mappingStack.prevList;
|
|
299
|
-
const numKeys = mappingStack.numKeys;
|
|
300
|
-
const thisData = {
|
|
301
|
-
name: thisName,
|
|
302
|
-
node,
|
|
303
|
-
anchors,
|
|
304
|
-
aliases,
|
|
305
|
-
};
|
|
306
|
-
mappingStack.prevList = [thisData, ...prevList];
|
|
307
|
-
if (prevList.length === 0 || numKeys < option.minKeys) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
if (!isValidOrder(prevList[0], thisData, option)) {
|
|
311
|
-
context.report({
|
|
312
|
-
loc: (_b = (_a = node.key) === null || _a === void 0 ? void 0 : _a.loc) !== null && _b !== void 0 ? _b : node.loc,
|
|
313
|
-
messageId: "sortKeys",
|
|
314
|
-
data: {
|
|
315
|
-
thisName,
|
|
316
|
-
prevName: prevList[0].name,
|
|
317
|
-
orderText: option.orderText,
|
|
318
|
-
},
|
|
319
|
-
*fix(fixer) {
|
|
320
|
-
let moveTarget = prevList[0].node;
|
|
321
|
-
for (const prev of prevList) {
|
|
322
|
-
if (isValidOrder(prev, thisData, option)) {
|
|
323
|
-
break;
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
326
|
-
moveTarget = prev.node;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
if (node.parent.style === "flow") {
|
|
330
|
-
yield* fixForFlow(fixer, node, moveTarget);
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
yield* fixForBlock(fixer, node, moveTarget);
|
|
334
|
-
}
|
|
335
|
-
},
|
|
336
|
-
});
|
|
402
|
+
for (const pair of data.pairs) {
|
|
403
|
+
verifyPair(pair, option);
|
|
337
404
|
}
|
|
338
405
|
},
|
|
339
406
|
};
|
|
340
|
-
function* fixForFlow(fixer,
|
|
341
|
-
const beforeCommaToken = sourceCode.getTokenBefore(node);
|
|
407
|
+
function* fixForFlow(fixer, data, moveTarget) {
|
|
408
|
+
const beforeCommaToken = sourceCode.getTokenBefore(data.node);
|
|
342
409
|
let insertCode, removeRange, insertTargetToken;
|
|
343
|
-
const afterCommaToken = sourceCode.getTokenAfter(node);
|
|
344
|
-
const moveTargetBeforeToken = sourceCode.getTokenBefore(moveTarget);
|
|
410
|
+
const afterCommaToken = sourceCode.getTokenAfter(data.node);
|
|
411
|
+
const moveTargetBeforeToken = sourceCode.getTokenBefore(moveTarget.node);
|
|
345
412
|
if ((0, ast_utils_1.isComma)(afterCommaToken)) {
|
|
346
413
|
removeRange = [
|
|
347
414
|
beforeCommaToken.range[1],
|
|
@@ -351,22 +418,22 @@ exports.default = (0, utils_1.createRule)("sort-keys", {
|
|
|
351
418
|
insertTargetToken = moveTargetBeforeToken;
|
|
352
419
|
}
|
|
353
420
|
else {
|
|
354
|
-
removeRange = [beforeCommaToken.range[0], node.range[1]];
|
|
421
|
+
removeRange = [beforeCommaToken.range[0], data.node.range[1]];
|
|
355
422
|
if ((0, ast_utils_1.isComma)(moveTargetBeforeToken)) {
|
|
356
423
|
insertCode = sourceCode.text.slice(...removeRange);
|
|
357
424
|
insertTargetToken = sourceCode.getTokenBefore(moveTargetBeforeToken);
|
|
358
425
|
}
|
|
359
426
|
else {
|
|
360
|
-
insertCode = `${sourceCode.text.slice(beforeCommaToken.range[1], node.range[1])},`;
|
|
427
|
+
insertCode = `${sourceCode.text.slice(beforeCommaToken.range[1], data.node.range[1])},`;
|
|
361
428
|
insertTargetToken = moveTargetBeforeToken;
|
|
362
429
|
}
|
|
363
430
|
}
|
|
364
431
|
yield fixer.insertTextAfterRange(insertTargetToken.range, insertCode);
|
|
365
432
|
yield fixer.removeRange(removeRange);
|
|
366
433
|
}
|
|
367
|
-
function* fixForBlock(fixer,
|
|
368
|
-
const nodeLocs = getPairRangeForBlock(node);
|
|
369
|
-
const moveTargetLocs = getPairRangeForBlock(moveTarget);
|
|
434
|
+
function* fixForBlock(fixer, data, moveTarget) {
|
|
435
|
+
const nodeLocs = getPairRangeForBlock(data.node);
|
|
436
|
+
const moveTargetLocs = getPairRangeForBlock(moveTarget.node);
|
|
370
437
|
if (moveTargetLocs.loc.start.column === 0) {
|
|
371
438
|
const removeRange = [
|
|
372
439
|
getNewlineStartIndex(nodeLocs.range[0]),
|
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const natural_compare_1 = __importDefault(require("natural-compare"));
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
const ast_utils_1 = require("../utils/ast-utils");
|
|
9
|
+
const yaml_eslint_parser_1 = require("yaml-eslint-parser");
|
|
10
|
+
class YAMLEntryData {
|
|
11
|
+
constructor(sequence, node, index, anchorAlias) {
|
|
12
|
+
this.cached = null;
|
|
13
|
+
this.cachedRange = null;
|
|
14
|
+
this.cachedAroundTokens = null;
|
|
15
|
+
this.sequence = sequence;
|
|
16
|
+
this.node = node;
|
|
17
|
+
this.index = index;
|
|
18
|
+
this.anchorAlias = anchorAlias;
|
|
19
|
+
}
|
|
20
|
+
get reportLoc() {
|
|
21
|
+
if (this.node) {
|
|
22
|
+
return this.node.loc;
|
|
23
|
+
}
|
|
24
|
+
const aroundTokens = this.aroundTokens;
|
|
25
|
+
return {
|
|
26
|
+
start: aroundTokens.before.loc.end,
|
|
27
|
+
end: aroundTokens.after.loc.start,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
get range() {
|
|
31
|
+
if (this.node) {
|
|
32
|
+
return this.node.range;
|
|
33
|
+
}
|
|
34
|
+
if (this.cachedRange) {
|
|
35
|
+
return this.cachedRange;
|
|
36
|
+
}
|
|
37
|
+
const aroundTokens = this.aroundTokens;
|
|
38
|
+
return (this.cachedRange = [
|
|
39
|
+
aroundTokens.before.range[1],
|
|
40
|
+
aroundTokens.after.range[0],
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
43
|
+
get aroundTokens() {
|
|
44
|
+
if (this.cachedAroundTokens) {
|
|
45
|
+
return this.cachedAroundTokens;
|
|
46
|
+
}
|
|
47
|
+
const sourceCode = this.sequence.sourceCode;
|
|
48
|
+
if (this.node) {
|
|
49
|
+
return (this.cachedAroundTokens = {
|
|
50
|
+
before: sourceCode.getTokenBefore(this.node),
|
|
51
|
+
after: sourceCode.getTokenAfter(this.node),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const before = this.index > 0
|
|
55
|
+
? this.sequence.entries[this.index - 1].aroundTokens.after
|
|
56
|
+
: sourceCode.getFirstToken(this.sequence.node);
|
|
57
|
+
const after = sourceCode.getTokenAfter(before);
|
|
58
|
+
return (this.cachedAroundTokens = { before, after });
|
|
59
|
+
}
|
|
60
|
+
get value() {
|
|
61
|
+
var _a;
|
|
62
|
+
return ((_a = this.cached) !== null && _a !== void 0 ? _a : (this.cached = {
|
|
63
|
+
value: this.node == null ? null : (0, yaml_eslint_parser_1.getStaticYAMLValue)(this.node),
|
|
64
|
+
})).value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
class YAMLSequenceData {
|
|
68
|
+
constructor(node, sourceCode, anchorAliasMap) {
|
|
69
|
+
this.cachedEntries = null;
|
|
70
|
+
this.node = node;
|
|
71
|
+
this.sourceCode = sourceCode;
|
|
72
|
+
this.anchorAliasMap = anchorAliasMap;
|
|
73
|
+
}
|
|
74
|
+
get entries() {
|
|
75
|
+
var _a;
|
|
76
|
+
return ((_a = this.cachedEntries) !== null && _a !== void 0 ? _a : (this.cachedEntries = this.node.entries.map((e, index) => new YAMLEntryData(this, e, index, this.anchorAliasMap.get(e)))));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function buildValidatorFromType(order, insensitive, natural) {
|
|
80
|
+
let compareValue = ([a, b]) => a <= b;
|
|
81
|
+
let compareText = compareValue;
|
|
82
|
+
if (natural) {
|
|
83
|
+
compareText = ([a, b]) => (0, natural_compare_1.default)(a, b) <= 0;
|
|
84
|
+
}
|
|
85
|
+
if (insensitive) {
|
|
86
|
+
const baseCompareText = compareText;
|
|
87
|
+
compareText = ([a, b]) => baseCompareText([a.toLowerCase(), b.toLowerCase()]);
|
|
88
|
+
}
|
|
89
|
+
if (order === "desc") {
|
|
90
|
+
const baseCompareText = compareText;
|
|
91
|
+
compareText = (args) => baseCompareText(args.reverse());
|
|
92
|
+
const baseCompareValue = compareValue;
|
|
93
|
+
compareValue = (args) => baseCompareValue(args.reverse());
|
|
94
|
+
}
|
|
95
|
+
return (a, b) => {
|
|
96
|
+
if (typeof a.value === "string" && typeof b.value === "string") {
|
|
97
|
+
return compareText([a.value, b.value]);
|
|
98
|
+
}
|
|
99
|
+
const type = getYAMLPrimitiveType(a.value);
|
|
100
|
+
if (type && type === getYAMLPrimitiveType(b.value)) {
|
|
101
|
+
return compareValue([a.value, b.value]);
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function parseOptions(options, sourceCode) {
|
|
107
|
+
return options.map((opt) => {
|
|
108
|
+
var _a, _b, _c, _d;
|
|
109
|
+
const order = opt.order;
|
|
110
|
+
const pathPattern = new RegExp(opt.pathPattern);
|
|
111
|
+
const minValues = (_a = opt.minValues) !== null && _a !== void 0 ? _a : 2;
|
|
112
|
+
if (!Array.isArray(order)) {
|
|
113
|
+
const type = (_b = order.type) !== null && _b !== void 0 ? _b : "asc";
|
|
114
|
+
const insensitive = order.caseSensitive === false;
|
|
115
|
+
const natural = Boolean(order.natural);
|
|
116
|
+
return {
|
|
117
|
+
isTargetArray,
|
|
118
|
+
ignore: () => false,
|
|
119
|
+
isValidOrder: buildValidatorFromType(type, insensitive, natural),
|
|
120
|
+
orderText(data) {
|
|
121
|
+
if (typeof data.value === "string") {
|
|
122
|
+
return `${natural ? "natural " : ""}${insensitive ? "insensitive " : ""}${type}ending`;
|
|
123
|
+
}
|
|
124
|
+
return `${type}ending`;
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const parsedOrder = [];
|
|
129
|
+
for (const o of order) {
|
|
130
|
+
if (typeof o === "string") {
|
|
131
|
+
parsedOrder.push({
|
|
132
|
+
test: (v) => v.value === o,
|
|
133
|
+
isValidNestOrder: () => true,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const valuePattern = o.valuePattern
|
|
138
|
+
? new RegExp(o.valuePattern)
|
|
139
|
+
: null;
|
|
140
|
+
const nestOrder = (_c = o.order) !== null && _c !== void 0 ? _c : {};
|
|
141
|
+
const type = (_d = nestOrder.type) !== null && _d !== void 0 ? _d : "asc";
|
|
142
|
+
const insensitive = nestOrder.caseSensitive === false;
|
|
143
|
+
const natural = Boolean(nestOrder.natural);
|
|
144
|
+
parsedOrder.push({
|
|
145
|
+
test: (v) => valuePattern
|
|
146
|
+
? Boolean(getYAMLPrimitiveType(v.value)) &&
|
|
147
|
+
valuePattern.test(String(v.value))
|
|
148
|
+
: true,
|
|
149
|
+
isValidNestOrder: buildValidatorFromType(type, insensitive, natural),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
isTargetArray,
|
|
155
|
+
ignore: (v) => parsedOrder.every((p) => !p.test(v)),
|
|
156
|
+
isValidOrder(a, b) {
|
|
157
|
+
for (const p of parsedOrder) {
|
|
158
|
+
const matchA = p.test(a);
|
|
159
|
+
const matchB = p.test(b);
|
|
160
|
+
if (!matchA || !matchB) {
|
|
161
|
+
if (matchA) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
if (matchB) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
return p.isValidNestOrder(a, b);
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
},
|
|
173
|
+
orderText: () => "specified",
|
|
174
|
+
};
|
|
175
|
+
function isTargetArray(data) {
|
|
176
|
+
if (data.node.entries.length < minValues) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
let path = "";
|
|
180
|
+
let curr = data.node;
|
|
181
|
+
let p = curr.parent;
|
|
182
|
+
while (p) {
|
|
183
|
+
if (p.type === "YAMLPair") {
|
|
184
|
+
const name = getPropertyName(p);
|
|
185
|
+
if (/^[$_a-z][\w$]*$/iu.test(name)) {
|
|
186
|
+
path = `.${name}${path}`;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
path = `[${JSON.stringify(name)}]${path}`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else if (p.type === "YAMLSequence") {
|
|
193
|
+
const index = p.entries.indexOf(curr);
|
|
194
|
+
path = `[${index}]${path}`;
|
|
195
|
+
}
|
|
196
|
+
curr = p;
|
|
197
|
+
p = curr.parent;
|
|
198
|
+
}
|
|
199
|
+
if (path.startsWith(".")) {
|
|
200
|
+
path = path.slice(1);
|
|
201
|
+
}
|
|
202
|
+
return pathPattern.test(path);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
function getPropertyName(node) {
|
|
206
|
+
const prop = node.key;
|
|
207
|
+
if (prop == null) {
|
|
208
|
+
return "";
|
|
209
|
+
}
|
|
210
|
+
const target = prop.type === "YAMLWithMeta" ? prop.value : prop;
|
|
211
|
+
if (target == null) {
|
|
212
|
+
return "";
|
|
213
|
+
}
|
|
214
|
+
if (target.type === "YAMLScalar" && typeof target.value === "string") {
|
|
215
|
+
return target.value;
|
|
216
|
+
}
|
|
217
|
+
return sourceCode.text.slice(...target.range);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function getYAMLPrimitiveType(val) {
|
|
221
|
+
const t = typeof val;
|
|
222
|
+
if (t === "string" || t === "number" || t === "boolean" || t === "bigint") {
|
|
223
|
+
return t;
|
|
224
|
+
}
|
|
225
|
+
if (val === null) {
|
|
226
|
+
return "null";
|
|
227
|
+
}
|
|
228
|
+
if (val === undefined) {
|
|
229
|
+
return "undefined";
|
|
230
|
+
}
|
|
231
|
+
if (val instanceof RegExp) {
|
|
232
|
+
return "regexp";
|
|
233
|
+
}
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
const ALLOW_ORDER_TYPES = ["asc", "desc"];
|
|
237
|
+
const ORDER_OBJECT_SCHEMA = {
|
|
238
|
+
type: "object",
|
|
239
|
+
properties: {
|
|
240
|
+
type: {
|
|
241
|
+
enum: ALLOW_ORDER_TYPES,
|
|
242
|
+
},
|
|
243
|
+
caseSensitive: {
|
|
244
|
+
type: "boolean",
|
|
245
|
+
},
|
|
246
|
+
natural: {
|
|
247
|
+
type: "boolean",
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
additionalProperties: false,
|
|
251
|
+
};
|
|
252
|
+
exports.default = (0, utils_1.createRule)("sort-sequence-values", {
|
|
253
|
+
meta: {
|
|
254
|
+
docs: {
|
|
255
|
+
description: "require sequence values to be sorted",
|
|
256
|
+
categories: null,
|
|
257
|
+
extensionRule: false,
|
|
258
|
+
layout: false,
|
|
259
|
+
},
|
|
260
|
+
fixable: "code",
|
|
261
|
+
schema: {
|
|
262
|
+
type: "array",
|
|
263
|
+
items: {
|
|
264
|
+
type: "object",
|
|
265
|
+
properties: {
|
|
266
|
+
pathPattern: { type: "string" },
|
|
267
|
+
order: {
|
|
268
|
+
oneOf: [
|
|
269
|
+
{
|
|
270
|
+
type: "array",
|
|
271
|
+
items: {
|
|
272
|
+
anyOf: [
|
|
273
|
+
{ type: "string" },
|
|
274
|
+
{
|
|
275
|
+
type: "object",
|
|
276
|
+
properties: {
|
|
277
|
+
valuePattern: {
|
|
278
|
+
type: "string",
|
|
279
|
+
},
|
|
280
|
+
order: ORDER_OBJECT_SCHEMA,
|
|
281
|
+
},
|
|
282
|
+
additionalProperties: false,
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
uniqueItems: true,
|
|
287
|
+
},
|
|
288
|
+
ORDER_OBJECT_SCHEMA,
|
|
289
|
+
],
|
|
290
|
+
},
|
|
291
|
+
minValues: {
|
|
292
|
+
type: "integer",
|
|
293
|
+
minimum: 2,
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
required: ["pathPattern", "order"],
|
|
297
|
+
additionalProperties: false,
|
|
298
|
+
},
|
|
299
|
+
minItems: 1,
|
|
300
|
+
},
|
|
301
|
+
messages: {
|
|
302
|
+
sortValues: "Expected sequence values to be in {{orderText}} order. '{{thisValue}}' should be before '{{prevValue}}'.",
|
|
303
|
+
},
|
|
304
|
+
type: "suggestion",
|
|
305
|
+
},
|
|
306
|
+
create(context) {
|
|
307
|
+
if (!context.parserServices.isYAML) {
|
|
308
|
+
return {};
|
|
309
|
+
}
|
|
310
|
+
const sourceCode = context.getSourceCode();
|
|
311
|
+
const parsedOptions = parseOptions(context.options, sourceCode);
|
|
312
|
+
function isValidOrder(prevData, thisData, option) {
|
|
313
|
+
if (option.isValidOrder(prevData, thisData)) {
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
for (const aliasName of thisData.anchorAlias.aliases) {
|
|
317
|
+
if (prevData.anchorAlias.anchors.has(aliasName)) {
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
for (const anchorName of thisData.anchorAlias.anchors) {
|
|
322
|
+
if (prevData.anchorAlias.aliases.has(anchorName)) {
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
function verifyArrayElement(data, option) {
|
|
329
|
+
if (option.ignore(data)) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const prevList = data.sequence.entries
|
|
333
|
+
.slice(0, data.index)
|
|
334
|
+
.reverse()
|
|
335
|
+
.filter((d) => !option.ignore(d));
|
|
336
|
+
if (prevList.length === 0) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
const prev = prevList[0];
|
|
340
|
+
if (!isValidOrder(prev, data, option)) {
|
|
341
|
+
const reportLoc = data.reportLoc;
|
|
342
|
+
context.report({
|
|
343
|
+
loc: reportLoc,
|
|
344
|
+
messageId: "sortValues",
|
|
345
|
+
data: {
|
|
346
|
+
thisValue: toText(data),
|
|
347
|
+
prevValue: toText(prev),
|
|
348
|
+
orderText: option.orderText(data),
|
|
349
|
+
},
|
|
350
|
+
*fix(fixer) {
|
|
351
|
+
let moveTarget = prevList[0];
|
|
352
|
+
for (const prev of prevList) {
|
|
353
|
+
if (isValidOrder(prev, data, option)) {
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
moveTarget = prev;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (data.sequence.node.style === "flow") {
|
|
361
|
+
yield* fixForFlow(fixer, data, moveTarget);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
yield* fixForBlock(fixer, data, moveTarget);
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function toText(data) {
|
|
371
|
+
if (getYAMLPrimitiveType(data.value)) {
|
|
372
|
+
return String(data.value);
|
|
373
|
+
}
|
|
374
|
+
return sourceCode.getText(data.node);
|
|
375
|
+
}
|
|
376
|
+
let entryStack = {
|
|
377
|
+
upper: null,
|
|
378
|
+
anchors: new Set(),
|
|
379
|
+
aliases: new Set(),
|
|
380
|
+
};
|
|
381
|
+
const anchorAliasMap = new Map();
|
|
382
|
+
return {
|
|
383
|
+
"YAMLSequence > *"(node) {
|
|
384
|
+
if (!node.parent.entries.includes(node)) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
entryStack = {
|
|
388
|
+
upper: entryStack,
|
|
389
|
+
anchors: new Set(),
|
|
390
|
+
aliases: new Set(),
|
|
391
|
+
};
|
|
392
|
+
if (node.type === "YAMLAlias") {
|
|
393
|
+
entryStack.aliases.add(node.name);
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
YAMLAnchor(node) {
|
|
397
|
+
if (entryStack) {
|
|
398
|
+
entryStack.anchors.add(node.name);
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
YAMLAlias(node) {
|
|
402
|
+
if (entryStack) {
|
|
403
|
+
entryStack.aliases.add(node.name);
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
"YAMLSequence > *:exit"(node) {
|
|
407
|
+
if (!node.parent.entries.includes(node)) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
anchorAliasMap.set(node, entryStack);
|
|
411
|
+
const { anchors, aliases } = entryStack;
|
|
412
|
+
entryStack = entryStack.upper;
|
|
413
|
+
entryStack.anchors = new Set([
|
|
414
|
+
...entryStack.anchors,
|
|
415
|
+
...anchors,
|
|
416
|
+
]);
|
|
417
|
+
entryStack.aliases = new Set([
|
|
418
|
+
...entryStack.aliases,
|
|
419
|
+
...aliases,
|
|
420
|
+
]);
|
|
421
|
+
},
|
|
422
|
+
"YAMLSequence:exit"(node) {
|
|
423
|
+
const data = new YAMLSequenceData(node, sourceCode, anchorAliasMap);
|
|
424
|
+
const option = parsedOptions.find((o) => o.isTargetArray(data));
|
|
425
|
+
if (!option) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
for (const element of data.entries) {
|
|
429
|
+
verifyArrayElement(element, option);
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
};
|
|
433
|
+
function* fixForFlow(fixer, data, moveTarget) {
|
|
434
|
+
const beforeToken = data.aroundTokens.before;
|
|
435
|
+
const afterToken = data.aroundTokens.after;
|
|
436
|
+
let insertCode, removeRange, insertTargetToken;
|
|
437
|
+
if ((0, ast_utils_1.isComma)(afterToken)) {
|
|
438
|
+
removeRange = [beforeToken.range[1], afterToken.range[1]];
|
|
439
|
+
insertCode = sourceCode.text.slice(...removeRange);
|
|
440
|
+
insertTargetToken = moveTarget.aroundTokens.before;
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
removeRange = [beforeToken.range[0], data.range[1]];
|
|
444
|
+
if ((0, ast_utils_1.isComma)(moveTarget.aroundTokens.before)) {
|
|
445
|
+
insertCode = sourceCode.text.slice(...removeRange);
|
|
446
|
+
insertTargetToken = sourceCode.getTokenBefore(moveTarget.aroundTokens.before);
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
insertCode = `${sourceCode.text.slice(beforeToken.range[1], data.range[1])},`;
|
|
450
|
+
insertTargetToken = moveTarget.aroundTokens.before;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
yield fixer.insertTextAfterRange(insertTargetToken.range, insertCode);
|
|
454
|
+
yield fixer.removeRange(removeRange);
|
|
455
|
+
}
|
|
456
|
+
function* fixForBlock(fixer, data, moveTarget) {
|
|
457
|
+
const moveDataList = data.sequence.entries.slice(moveTarget.index, data.index + 1);
|
|
458
|
+
let replacementCodeRange = getBlockEntryRange(data);
|
|
459
|
+
for (const target of moveDataList) {
|
|
460
|
+
const range = getBlockEntryRange(target);
|
|
461
|
+
yield fixer.replaceTextRange(range, sourceCode.text.slice(...replacementCodeRange));
|
|
462
|
+
replacementCodeRange = range;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
function getBlockEntryRange(data) {
|
|
466
|
+
return [
|
|
467
|
+
getBlockEntryStartOffset(data),
|
|
468
|
+
getBlockEntryEndOffset(data),
|
|
469
|
+
];
|
|
470
|
+
}
|
|
471
|
+
function getBlockEntryStartOffset(data) {
|
|
472
|
+
const beforeHyphenToken = sourceCode.getTokenBefore(data.aroundTokens.before);
|
|
473
|
+
if (!beforeHyphenToken) {
|
|
474
|
+
const comment = sourceCode.getTokenBefore(data.aroundTokens.before, {
|
|
475
|
+
includeComments: true,
|
|
476
|
+
});
|
|
477
|
+
if (comment &&
|
|
478
|
+
data.aroundTokens.before.loc.start.column <=
|
|
479
|
+
comment.loc.start.column) {
|
|
480
|
+
return comment.range[0];
|
|
481
|
+
}
|
|
482
|
+
return data.aroundTokens.before.range[0];
|
|
483
|
+
}
|
|
484
|
+
let next = sourceCode.getTokenAfter(beforeHyphenToken, {
|
|
485
|
+
includeComments: true,
|
|
486
|
+
});
|
|
487
|
+
while (beforeHyphenToken.loc.end.line === next.loc.start.line &&
|
|
488
|
+
next.range[1] < data.aroundTokens.before.range[0]) {
|
|
489
|
+
next = sourceCode.getTokenAfter(next, {
|
|
490
|
+
includeComments: true,
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
return next.range[0];
|
|
494
|
+
}
|
|
495
|
+
function getBlockEntryEndOffset(data) {
|
|
496
|
+
var _a;
|
|
497
|
+
const valueEndToken = (_a = data.node) !== null && _a !== void 0 ? _a : data.aroundTokens.before;
|
|
498
|
+
let last = valueEndToken;
|
|
499
|
+
let afterToken = sourceCode.getTokenAfter(last, {
|
|
500
|
+
includeComments: true,
|
|
501
|
+
});
|
|
502
|
+
while (afterToken &&
|
|
503
|
+
valueEndToken.loc.end.line === afterToken.loc.start.line) {
|
|
504
|
+
last = afterToken;
|
|
505
|
+
afterToken = sourceCode.getTokenAfter(last, {
|
|
506
|
+
includeComments: true,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
return last.range[1];
|
|
510
|
+
}
|
|
511
|
+
},
|
|
512
|
+
});
|
package/lib/utils/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
package/lib/utils/rules.js
CHANGED
|
@@ -26,6 +26,7 @@ const plain_scalar_1 = __importDefault(require("../rules/plain-scalar"));
|
|
|
26
26
|
const quotes_1 = __importDefault(require("../rules/quotes"));
|
|
27
27
|
const require_string_key_1 = __importDefault(require("../rules/require-string-key"));
|
|
28
28
|
const sort_keys_1 = __importDefault(require("../rules/sort-keys"));
|
|
29
|
+
const sort_sequence_values_1 = __importDefault(require("../rules/sort-sequence-values"));
|
|
29
30
|
const spaced_comment_1 = __importDefault(require("../rules/spaced-comment"));
|
|
30
31
|
const no_parsing_error_1 = __importDefault(require("../rules/vue-custom-block/no-parsing-error"));
|
|
31
32
|
exports.rules = [
|
|
@@ -51,6 +52,7 @@ exports.rules = [
|
|
|
51
52
|
quotes_1.default,
|
|
52
53
|
require_string_key_1.default,
|
|
53
54
|
sort_keys_1.default,
|
|
55
|
+
sort_sequence_values_1.default,
|
|
54
56
|
spaced_comment_1.default,
|
|
55
57
|
no_parsing_error_1.default,
|
|
56
58
|
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-yml",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "This ESLint plugin provides linting rules for YAML.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"yml"
|
|
43
43
|
],
|
|
44
44
|
"author": "Yosuke Ota",
|
|
45
|
+
"funding": "https://github.com/sponsors/ota-meshi",
|
|
45
46
|
"license": "MIT",
|
|
46
47
|
"bugs": {
|
|
47
48
|
"url": "https://github.com/ota-meshi/eslint-plugin-yml/issues"
|
|
@@ -62,7 +63,7 @@
|
|
|
62
63
|
"@types/eslint": "^8.0.0",
|
|
63
64
|
"@types/eslint-scope": "^3.7.0",
|
|
64
65
|
"@types/eslint-visitor-keys": "^1.0.0",
|
|
65
|
-
"@types/estree": "^0.0.
|
|
66
|
+
"@types/estree": "^0.0.51",
|
|
66
67
|
"@types/lodash": "^4.14.158",
|
|
67
68
|
"@types/mocha": "^9.0.0",
|
|
68
69
|
"@types/natural-compare": "^1.4.0",
|
|
@@ -80,27 +81,27 @@
|
|
|
80
81
|
"eslint-plugin-jsonc": "^2.0.0",
|
|
81
82
|
"eslint-plugin-markdown": "^2.0.0-0",
|
|
82
83
|
"eslint-plugin-node": "^11.1.0",
|
|
83
|
-
"eslint-plugin-node-dependencies": "^0.
|
|
84
|
+
"eslint-plugin-node-dependencies": "^0.8.0",
|
|
84
85
|
"eslint-plugin-prettier": "^4.0.0",
|
|
85
86
|
"eslint-plugin-regexp": "^1.0.0",
|
|
86
87
|
"eslint-plugin-vue": "^8.0.0",
|
|
87
|
-
"eslint-plugin-yml": "^0.
|
|
88
|
+
"eslint-plugin-yml": "^0.14.0",
|
|
88
89
|
"eslint4b": "^7.3.1",
|
|
89
90
|
"espree": "^9.0.0",
|
|
90
|
-
"mocha": "^
|
|
91
|
-
"monaco-editor": "^0.
|
|
91
|
+
"mocha": "^10.0.0",
|
|
92
|
+
"monaco-editor": "^0.33.0",
|
|
92
93
|
"nyc": "^15.1.0",
|
|
93
94
|
"prettier": "^2.2.1",
|
|
94
95
|
"raw-loader": "^4.0.1",
|
|
95
96
|
"semver": "^7.3.2",
|
|
96
97
|
"stylelint": "^14.0.0",
|
|
97
98
|
"stylelint-config-recommended-vue": "^1.0.0",
|
|
98
|
-
"stylelint-config-standard": "^
|
|
99
|
+
"stylelint-config-standard": "^25.0.0",
|
|
99
100
|
"stylelint-plugin-stylus": "^0.13.0",
|
|
100
101
|
"ts-node": "^10.0.0",
|
|
101
|
-
"typescript": "~4.
|
|
102
|
+
"typescript": "~4.6.0",
|
|
102
103
|
"vue-eslint-editor": "^1.1.0",
|
|
103
|
-
"vue-eslint-parser": "^
|
|
104
|
+
"vue-eslint-parser": "^9.0.0",
|
|
104
105
|
"vuepress": "^1.5.2"
|
|
105
106
|
}
|
|
106
107
|
}
|