eslint-plugin-yml 1.4.0 → 1.6.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 CHANGED
@@ -207,6 +207,7 @@ The rules with the following star :star: are included in the config.
207
207
  | [yml/no-empty-mapping-value](https://ota-meshi.github.io/eslint-plugin-yml/rules/no-empty-mapping-value.html) | disallow empty mapping values | | :star: | :star: |
208
208
  | [yml/no-empty-sequence-entry](https://ota-meshi.github.io/eslint-plugin-yml/rules/no-empty-sequence-entry.html) | disallow empty sequence entries | | :star: | :star: |
209
209
  | [yml/no-tab-indent](https://ota-meshi.github.io/eslint-plugin-yml/rules/no-tab-indent.html) | disallow tabs for indentation. | | :star: | :star: |
210
+ | [yml/no-trailing-zeros](https://ota-meshi.github.io/eslint-plugin-yml/rules/no-trailing-zeros.html) | disallow trailing zeros for floats | :wrench: | | |
210
211
  | [yml/plain-scalar](https://ota-meshi.github.io/eslint-plugin-yml/rules/plain-scalar.html) | require or disallow plain style scalar. | :wrench: | | :star: |
211
212
  | [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: |
212
213
  | [yml/require-string-key](https://ota-meshi.github.io/eslint-plugin-yml/rules/require-string-key.html) | disallow mapping keys other than strings | | | |
@@ -11,6 +11,7 @@ declare const _default: {
11
11
  "yml/indent": string;
12
12
  "yml/key-spacing": string;
13
13
  "yml/no-multiple-empty-lines": string;
14
+ "yml/no-trailing-zeros": string;
14
15
  "yml/quotes": string;
15
16
  };
16
17
  };
@@ -18,6 +18,7 @@ module.exports = {
18
18
  "yml/indent": "off",
19
19
  "yml/key-spacing": "off",
20
20
  "yml/no-multiple-empty-lines": "off",
21
+ "yml/no-trailing-zeros": "off",
21
22
  "yml/quotes": "off",
22
23
  },
23
24
  };
package/lib/index.d.ts CHANGED
@@ -63,6 +63,7 @@ declare const _default: {
63
63
  "yml/indent": string;
64
64
  "yml/key-spacing": string;
65
65
  "yml/no-multiple-empty-lines": string;
66
+ "yml/no-trailing-zeros": string;
66
67
  "yml/quotes": string;
67
68
  };
68
69
  };
@@ -10,14 +10,19 @@ function parseOptions(context) {
10
10
  const [indentOption, objectOptions] = context.options;
11
11
  const numOfIndent = (0, yaml_1.getNumOfIndent)(context, indentOption);
12
12
  let indentBlockSequences = true;
13
+ let indicatorValueIndent = numOfIndent;
13
14
  if (objectOptions) {
14
15
  if (objectOptions.indentBlockSequences === false) {
15
16
  indentBlockSequences = false;
16
17
  }
18
+ if (objectOptions.indicatorValueIndent != null) {
19
+ indicatorValueIndent = objectOptions.indicatorValueIndent;
20
+ }
17
21
  }
18
22
  return {
19
23
  numOfIndent,
20
24
  indentBlockSequences,
25
+ indicatorValueIndent,
21
26
  };
22
27
  }
23
28
  exports.default = (0, utils_1.createRule)("indent", {
@@ -38,6 +43,10 @@ exports.default = (0, utils_1.createRule)("indent", {
38
43
  type: "object",
39
44
  properties: {
40
45
  indentBlockSequences: { type: "boolean" },
46
+ indicatorValueIndent: {
47
+ type: "integer",
48
+ minimum: 2,
49
+ },
41
50
  },
42
51
  additionalProperties: false,
43
52
  },
@@ -54,27 +63,33 @@ exports.default = (0, utils_1.createRule)("indent", {
54
63
  if ((0, yaml_1.hasTabIndent)(context)) {
55
64
  return {};
56
65
  }
57
- const { numOfIndent, indentBlockSequences } = parseOptions(context);
66
+ const { numOfIndent, indentBlockSequences, indicatorValueIndent } = parseOptions(context);
58
67
  const sourceCode = context.getSourceCode();
59
- const offsets = new Map();
60
- const marks = new Set();
68
+ const indents = new Map();
69
+ const indicators = new Set();
61
70
  const blockLiteralMarks = new Set();
62
71
  const scalars = new Map();
63
72
  function setOffset(token, offset, baseToken, options) {
73
+ setIndent(token, offset * numOfIndent, baseToken, options && {
74
+ indentWhenBaseIsNotFirst: options.offsetWhenBaseIsNotFirst &&
75
+ options.offsetWhenBaseIsNotFirst * numOfIndent,
76
+ });
77
+ }
78
+ function setIndent(token, indent, baseToken, options) {
64
79
  var _a;
65
80
  if (token == null) {
66
81
  return;
67
82
  }
68
83
  if (Array.isArray(token)) {
69
84
  for (const t of token) {
70
- setOffset(t, offset, baseToken, options);
85
+ setIndent(t, indent, baseToken, options);
71
86
  }
72
87
  }
73
88
  else {
74
- offsets.set(token, {
89
+ indents.set(token, {
75
90
  baseToken,
76
- offset,
77
- offsetWhenBaseIsNotFirst: (_a = options === null || options === void 0 ? void 0 : options.offsetWhenBaseIsNotFirst) !== null && _a !== void 0 ? _a : null,
91
+ indent,
92
+ indentWhenBaseIsNotFirst: (_a = options === null || options === void 0 ? void 0 : options.indentWhenBaseIsNotFirst) !== null && _a !== void 0 ? _a : null,
78
93
  });
79
94
  }
80
95
  }
@@ -110,14 +125,23 @@ exports.default = (0, utils_1.createRule)("indent", {
110
125
  setOffset(right, 0, left);
111
126
  }
112
127
  }
113
- function calcMappingPairValueIndentOffset(node) {
128
+ function calcMappingPairValueIndent(node, indent) {
114
129
  if (indentBlockSequences) {
115
- return 1;
130
+ return indent;
116
131
  }
117
132
  if (node.type === "YAMLSequence" && node.style === "block") {
118
133
  return 0;
119
134
  }
120
- return 1;
135
+ return indent;
136
+ }
137
+ function calcIndicatorValueIndent(token) {
138
+ return isBeginningToken(token) ? indicatorValueIndent : numOfIndent;
139
+ }
140
+ function isBeginningToken(token) {
141
+ const before = sourceCode.getTokenBefore(token, (t) => !indicators.has(t));
142
+ if (!before)
143
+ return true;
144
+ return before.loc.end.line < token.loc.start.line;
121
145
  }
122
146
  const documents = [];
123
147
  return {
@@ -127,10 +151,10 @@ exports.default = (0, utils_1.createRule)("indent", {
127
151
  if (!first) {
128
152
  return;
129
153
  }
130
- offsets.set(first, {
154
+ indents.set(first, {
131
155
  baseToken: null,
132
- offsetWhenBaseIsNotFirst: null,
133
- offset: 0,
156
+ indentWhenBaseIsNotFirst: null,
157
+ indent: 0,
134
158
  expectedIndent: 0,
135
159
  });
136
160
  processNodeList([...node.directives, node.content], first, null, 0);
@@ -160,9 +184,9 @@ exports.default = (0, utils_1.createRule)("indent", {
160
184
  continue;
161
185
  }
162
186
  const hyphen = sourceCode.getTokenBefore(entry, ast_utils_1.isHyphen);
163
- marks.add(hyphen);
187
+ indicators.add(hyphen);
164
188
  const entryToken = sourceCode.getFirstToken(entry);
165
- setOffset(entryToken, 1, hyphen);
189
+ setIndent(entryToken, calcIndicatorValueIndent(hyphen), hyphen);
166
190
  }
167
191
  }
168
192
  },
@@ -172,13 +196,13 @@ exports.default = (0, utils_1.createRule)("indent", {
172
196
  const colonToken = findColonToken();
173
197
  const questionToken = (0, ast_utils_1.isQuestion)(pairFirst) ? pairFirst : null;
174
198
  if (questionToken) {
175
- marks.add(questionToken);
199
+ indicators.add(questionToken);
176
200
  if (node.key) {
177
- setOffset(keyToken, calcMappingPairValueIndentOffset(node.key), questionToken);
201
+ setIndent(keyToken, calcMappingPairValueIndent(node.key, calcIndicatorValueIndent(questionToken)), questionToken);
178
202
  }
179
203
  }
180
204
  if (colonToken) {
181
- marks.add(colonToken);
205
+ indicators.add(colonToken);
182
206
  if (questionToken) {
183
207
  setOffset(colonToken, 0, questionToken, {
184
208
  offsetWhenBaseIsNotFirst: 1,
@@ -191,7 +215,7 @@ exports.default = (0, utils_1.createRule)("indent", {
191
215
  if (node.value) {
192
216
  const valueToken = sourceCode.getFirstToken(node.value);
193
217
  if (colonToken) {
194
- setOffset(valueToken, calcMappingPairValueIndentOffset(node.value), colonToken);
218
+ setIndent(valueToken, calcMappingPairValueIndent(node.value, calcIndicatorValueIndent(colonToken)), colonToken);
195
219
  }
196
220
  else if (keyToken) {
197
221
  setOffset(valueToken, 1, keyToken);
@@ -281,7 +305,7 @@ exports.default = (0, utils_1.createRule)("indent", {
281
305
  const lastToken = lineTokens[lineTokens.length - 1];
282
306
  let lineExpectedIndent = null;
283
307
  let cacheExpectedIndent = null;
284
- const markData = [];
308
+ const indicatorData = [];
285
309
  const firstToken = lineTokens.shift();
286
310
  let token = firstToken;
287
311
  let expectedIndent = getExpectedIndent(token);
@@ -289,7 +313,7 @@ exports.default = (0, utils_1.createRule)("indent", {
289
313
  lineExpectedIndent = expectedIndent;
290
314
  cacheExpectedIndent = expectedIndent;
291
315
  }
292
- while (token && marks.has(token) && expectedIndent != null) {
316
+ while (token && indicators.has(token) && expectedIndent != null) {
293
317
  const nextToken = lineTokens.shift();
294
318
  if (!nextToken) {
295
319
  break;
@@ -300,8 +324,8 @@ exports.default = (0, utils_1.createRule)("indent", {
300
324
  lineTokens.unshift(nextToken);
301
325
  break;
302
326
  }
303
- markData.push({
304
- mark: token,
327
+ indicatorData.push({
328
+ indicator: token,
305
329
  next: nextToken,
306
330
  expectedOffset: nextExpectedIndent - expectedIndent - 1,
307
331
  actualOffset: nextToken.range[0] - token.range[1],
@@ -328,9 +352,9 @@ exports.default = (0, utils_1.createRule)("indent", {
328
352
  }
329
353
  if (cacheExpectedIndent != null) {
330
354
  while ((token = lineTokens.shift()) != null) {
331
- const offset = offsets.get(token);
332
- if (offset) {
333
- offset.expectedIndent = cacheExpectedIndent;
355
+ const indent = indents.get(token);
356
+ if (indent) {
357
+ indent.expectedIndent = cacheExpectedIndent;
334
358
  }
335
359
  }
336
360
  }
@@ -351,7 +375,7 @@ exports.default = (0, utils_1.createRule)("indent", {
351
375
  actualIndent: column,
352
376
  firstToken,
353
377
  line,
354
- markData,
378
+ indicatorData,
355
379
  lastScalar,
356
380
  };
357
381
  }
@@ -359,33 +383,33 @@ exports.default = (0, utils_1.createRule)("indent", {
359
383
  if (token.type === "Marker") {
360
384
  return 0;
361
385
  }
362
- const offset = offsets.get(token);
363
- if (!offset) {
386
+ const indent = indents.get(token);
387
+ if (!indent) {
364
388
  return null;
365
389
  }
366
- if (offset.expectedIndent != null) {
367
- return offset.expectedIndent;
390
+ if (indent.expectedIndent != null) {
391
+ return indent.expectedIndent;
368
392
  }
369
- if (offset.baseToken == null) {
393
+ if (indent.baseToken == null) {
370
394
  return null;
371
395
  }
372
- const baseIndent = getExpectedIndent(offset.baseToken);
396
+ const baseIndent = getExpectedIndent(indent.baseToken);
373
397
  if (baseIndent == null) {
374
398
  return null;
375
399
  }
376
- let offsetIndent = offset.offset;
377
- if (offsetIndent === 0 && offset.offsetWhenBaseIsNotFirst != null) {
378
- let before = offset.baseToken;
400
+ let offsetIndent = indent.indent;
401
+ if (offsetIndent === 0 && indent.indentWhenBaseIsNotFirst != null) {
402
+ let before = indent.baseToken;
379
403
  while ((before = sourceCode.getTokenBefore(before, ITERATION_OPTS)) != null) {
380
- if (!marks.has(before)) {
404
+ if (!indicators.has(before)) {
381
405
  break;
382
406
  }
383
407
  }
384
- if ((before === null || before === void 0 ? void 0 : before.loc.end.line) === offset.baseToken.loc.start.line) {
385
- offsetIndent = offset.offsetWhenBaseIsNotFirst;
408
+ if ((before === null || before === void 0 ? void 0 : before.loc.end.line) === indent.baseToken.loc.start.line) {
409
+ offsetIndent = indent.indentWhenBaseIsNotFirst;
386
410
  }
387
411
  }
388
- return (offset.expectedIndent = baseIndent + numOfIndent * offsetIndent);
412
+ return (indent.expectedIndent = baseIndent + offsetIndent);
389
413
  }
390
414
  function processMissingLines(lineIndents) {
391
415
  const results = [];
@@ -413,7 +437,7 @@ exports.default = (0, utils_1.createRule)("indent", {
413
437
  line,
414
438
  expectedIndent: lineIndent.expectedIndent,
415
439
  actualIndent: lineIndent.actualIndent,
416
- markData: lineIndent.markData,
440
+ indicatorData: lineIndent.indicatorData,
417
441
  };
418
442
  if (!results[line]) {
419
443
  results[line] = indent;
@@ -489,7 +513,7 @@ exports.default = (0, utils_1.createRule)("indent", {
489
513
  line: commentLineIndent.line,
490
514
  expectedIndent,
491
515
  actualIndent: commentLineIndent.actualIndent,
492
- markData: commentLineIndent.markData,
516
+ indicatorData: commentLineIndent.indicatorData,
493
517
  };
494
518
  }
495
519
  }
@@ -538,7 +562,7 @@ exports.default = (0, utils_1.createRule)("indent", {
538
562
  line: scalarLine,
539
563
  expectedIndent,
540
564
  actualIndent: scalarActualIndent,
541
- markData: [],
565
+ indicatorData: [],
542
566
  };
543
567
  }
544
568
  }
@@ -552,7 +576,7 @@ exports.default = (0, utils_1.createRule)("indent", {
552
576
  line: scalarLine,
553
577
  expectedIndent,
554
578
  actualIndent: scalarActualIndent,
555
- markData: [],
579
+ indicatorData: [],
556
580
  };
557
581
  }
558
582
  }
@@ -582,20 +606,20 @@ exports.default = (0, utils_1.createRule)("indent", {
582
606
  fix: buildFix(lineIndent, lineIndents),
583
607
  });
584
608
  }
585
- else if (lineIndent.markData.length) {
586
- for (const markData of lineIndent.markData) {
587
- if (markData.actualOffset !== markData.expectedOffset) {
588
- const markLoc = markData.mark.loc.end;
589
- const loc = markData.next.loc.start;
609
+ else if (lineIndent.indicatorData.length) {
610
+ for (const indicatorData of lineIndent.indicatorData) {
611
+ if (indicatorData.actualOffset !== indicatorData.expectedOffset) {
612
+ const indicatorLoc = indicatorData.indicator.loc.end;
613
+ const loc = indicatorData.next.loc.start;
590
614
  context.report({
591
615
  loc: {
592
- start: markLoc,
616
+ start: indicatorLoc,
593
617
  end: loc,
594
618
  },
595
619
  messageId: "wrongIndentation",
596
620
  data: {
597
- expected: String(markData.expectedOffset),
598
- actual: String(markData.actualOffset),
621
+ expected: String(indicatorData.expectedOffset),
622
+ actual: String(indicatorData.actualOffset),
599
623
  },
600
624
  fix: buildFix(lineIndent, lineIndents),
601
625
  });
@@ -619,8 +643,8 @@ exports.default = (0, utils_1.createRule)("indent", {
619
643
  if (expectedIndent <= li.actualIndent) {
620
644
  return null;
621
645
  }
622
- for (const mark of li.markData) {
623
- if (mark.actualOffset !== mark.expectedOffset) {
646
+ for (const indicator of li.indicatorData) {
647
+ if (indicator.actualOffset !== indicator.expectedOffset) {
624
648
  return null;
625
649
  }
626
650
  }
@@ -684,9 +708,9 @@ exports.default = (0, utils_1.createRule)("indent", {
684
708
  yield* fixLine(fixer, li);
685
709
  }
686
710
  }
687
- if (li.markData) {
688
- for (const markData of li.markData) {
689
- yield fixer.replaceTextRange([markData.mark.range[1], markData.next.range[0]], " ".repeat(markData.expectedOffset));
711
+ if (li.indicatorData) {
712
+ for (const indicatorData of li.indicatorData) {
713
+ yield fixer.replaceTextRange([indicatorData.indicator.range[1], indicatorData.next.range[0]], " ".repeat(indicatorData.expectedOffset));
690
714
  }
691
715
  }
692
716
  }
@@ -0,0 +1,2 @@
1
+ declare const _default: import("../types").RuleModule;
2
+ export default _default;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../utils");
4
+ exports.default = (0, utils_1.createRule)("no-trailing-zeros", {
5
+ meta: {
6
+ docs: {
7
+ description: "disallow trailing zeros for floats",
8
+ categories: null,
9
+ extensionRule: false,
10
+ layout: true,
11
+ },
12
+ fixable: "code",
13
+ schema: [],
14
+ messages: {
15
+ wrongZeros: "Trailing zeros are not allowed, fix to `{{fixed}}`.",
16
+ },
17
+ type: "layout",
18
+ },
19
+ create(context) {
20
+ if (!context.parserServices.isYAML) {
21
+ return {};
22
+ }
23
+ return {
24
+ YAMLScalar(node) {
25
+ if (node.style !== "plain") {
26
+ return;
27
+ }
28
+ else if (typeof node.value !== "number") {
29
+ return;
30
+ }
31
+ const floating = parseFloatingPoint(node.strValue);
32
+ if (!floating) {
33
+ return;
34
+ }
35
+ let { decimalPart } = floating;
36
+ while (decimalPart.endsWith("_")) {
37
+ decimalPart = decimalPart.slice(0, -1);
38
+ }
39
+ if (!decimalPart.endsWith("0")) {
40
+ return;
41
+ }
42
+ while (decimalPart.endsWith("0")) {
43
+ decimalPart = decimalPart.slice(0, -1);
44
+ while (decimalPart.endsWith("_")) {
45
+ decimalPart = decimalPart.slice(0, -1);
46
+ }
47
+ }
48
+ const fixed = decimalPart
49
+ ? `${floating.sign}${floating.intPart}.${decimalPart}${floating.expPart}`
50
+ : `${floating.sign}${floating.intPart || "0"}${floating.expPart}`;
51
+ context.report({
52
+ node,
53
+ messageId: "wrongZeros",
54
+ data: {
55
+ fixed,
56
+ },
57
+ fix(fixer) {
58
+ return fixer.replaceText(node, fixed);
59
+ },
60
+ });
61
+ },
62
+ };
63
+ },
64
+ });
65
+ function parseFloatingPoint(str) {
66
+ const parts = str.split(".");
67
+ if (parts.length !== 2) {
68
+ return null;
69
+ }
70
+ let decimalPart, expPart, intPart, sign;
71
+ const expIndex = parts[1].search(/e/iu);
72
+ if (expIndex >= 0) {
73
+ decimalPart = parts[1].slice(0, expIndex);
74
+ expPart = parts[1].slice(expIndex);
75
+ }
76
+ else {
77
+ decimalPart = parts[1];
78
+ expPart = "";
79
+ }
80
+ if (parts[0].startsWith("-") || parts[0].startsWith("+")) {
81
+ sign = parts[0][0];
82
+ intPart = parts[0].slice(1);
83
+ }
84
+ else {
85
+ sign = "";
86
+ intPart = parts[0];
87
+ }
88
+ return {
89
+ sign,
90
+ intPart,
91
+ decimalPart,
92
+ expPart,
93
+ };
94
+ }
@@ -24,6 +24,7 @@ const no_empty_sequence_entry_1 = __importDefault(require("../rules/no-empty-seq
24
24
  const no_irregular_whitespace_1 = __importDefault(require("../rules/no-irregular-whitespace"));
25
25
  const no_multiple_empty_lines_1 = __importDefault(require("../rules/no-multiple-empty-lines"));
26
26
  const no_tab_indent_1 = __importDefault(require("../rules/no-tab-indent"));
27
+ const no_trailing_zeros_1 = __importDefault(require("../rules/no-trailing-zeros"));
27
28
  const plain_scalar_1 = __importDefault(require("../rules/plain-scalar"));
28
29
  const quotes_1 = __importDefault(require("../rules/quotes"));
29
30
  const require_string_key_1 = __importDefault(require("../rules/require-string-key"));
@@ -52,6 +53,7 @@ exports.rules = [
52
53
  no_irregular_whitespace_1.default,
53
54
  no_multiple_empty_lines_1.default,
54
55
  no_tab_indent_1.default,
56
+ no_trailing_zeros_1.default,
55
57
  plain_scalar_1.default,
56
58
  quotes_1.default,
57
59
  require_string_key_1.default,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-yml",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "This ESLint plugin provides linting rules for YAML.",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -44,7 +44,8 @@
44
44
  "eslintplugin",
45
45
  "eslint-plugin",
46
46
  "yaml",
47
- "yml"
47
+ "yml",
48
+ "lint"
48
49
  ],
49
50
  "author": "Yosuke Ota",
50
51
  "funding": "https://github.com/sponsors/ota-meshi",
@@ -57,7 +58,7 @@
57
58
  "debug": "^4.3.2",
58
59
  "lodash": "^4.17.21",
59
60
  "natural-compare": "^1.4.0",
60
- "yaml-eslint-parser": "^1.1.0"
61
+ "yaml-eslint-parser": "^1.2.1"
61
62
  },
62
63
  "peerDependencies": {
63
64
  "eslint": ">=6.0.0"
@@ -80,7 +81,7 @@
80
81
  "@typescript-eslint/parser": "^5.0.0",
81
82
  "cross-env": "^7.0.2",
82
83
  "env-cmd": "^10.1.0",
83
- "esbuild": "^0.16.0",
84
+ "esbuild": "^0.17.0",
84
85
  "esbuild-register": "^3.2.0",
85
86
  "eslint": "^8.0.0",
86
87
  "eslint-config-prettier": "^8.0.0",
@@ -98,16 +99,16 @@
98
99
  "eslint4b": "^7.3.1",
99
100
  "espree": "^9.0.0",
100
101
  "mocha": "^10.0.0",
101
- "monaco-editor": "^0.34.0",
102
+ "monaco-editor": "^0.38.0",
102
103
  "nyc": "^15.1.0",
103
104
  "prettier": "^2.2.1",
104
105
  "raw-loader": "^4.0.1",
105
106
  "semver": "^7.3.2",
106
- "stylelint": "^14.9.1",
107
+ "stylelint": "^15.0.0",
107
108
  "stylelint-config-recommended-vue": "^1.0.0",
108
- "stylelint-config-standard": "^29.0.0",
109
- "stylelint-stylus": "^0.17.0",
110
- "typescript": "~4.9.0",
109
+ "stylelint-config-standard": "^33.0.0",
110
+ "stylelint-stylus": "^0.18.0",
111
+ "typescript": "~5.0.0",
111
112
  "vue-eslint-editor": "^1.1.0",
112
113
  "vue-eslint-parser": "^9.0.0",
113
114
  "vuepress": "^1.5.2",