eslint-plugin-yml 3.2.2 → 3.3.1

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/lib/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import { AST } from "yaml-eslint-parser";
2
2
  import { IDirective, TextSourceCodeBase, TraversalStep } from "@eslint/plugin-kit";
3
3
  import { CursorWithCountOptionsWithComment, CursorWithCountOptionsWithFilter, CursorWithCountOptionsWithoutFilter, CursorWithSkipOptionsWithComment, CursorWithSkipOptionsWithFilter, CursorWithSkipOptionsWithoutFilter } from "@ota-meshi/ast-token-store";
4
4
  import * as _eslint_core0 from "@eslint/core";
5
- import { File, FileProblem, Language, OkParseResult, RuleDefinition, RulesConfig } from "@eslint/core";
5
+ import { File, FileProblem, Language, OkParseResult, ParseResult, RuleDefinition, RulesConfig } from "@eslint/core";
6
6
  import { Linter, Scope } from "eslint";
7
7
 
8
8
  //#region src/meta.d.ts
@@ -262,6 +262,7 @@ declare class YAMLSourceCode extends TextSourceCodeBase<{
262
262
  getCommentsInside(nodeOrToken: YAMLSyntaxElement): AST.Comment[];
263
263
  getCommentsBefore(nodeOrToken: YAMLSyntaxElement): AST.Comment[];
264
264
  getCommentsAfter(nodeOrToken: YAMLSyntaxElement): AST.Comment[];
265
+ commentsExistBetween(first: YAMLSyntaxElement, second: YAMLSyntaxElement): boolean;
265
266
  isSpaceBetween(first: AST.Token | AST.Comment, second: AST.Token | AST.Comment): boolean;
266
267
  /**
267
268
  * Compatibility for ESLint's SourceCode API
@@ -282,13 +283,6 @@ declare class YAMLSourceCode extends TextSourceCodeBase<{
282
283
  }
283
284
  //#endregion
284
285
  //#region src/language/yaml-language.d.ts
285
- /**
286
- * Parse result
287
- */
288
- interface YAMLParseResult {
289
- ok: true;
290
- ast: AST.YAMLProgram;
291
- }
292
286
  /**
293
287
  * Language options for YAML
294
288
  */
@@ -332,11 +326,11 @@ declare class YAMLLanguage implements Language<{
332
326
  */
333
327
  parse(file: File, context: {
334
328
  languageOptions?: YAMLLanguageOptions;
335
- }): OkParseResult<AST.YAMLProgram> | YAMLParseResult;
329
+ }): ParseResult<AST.YAMLProgram>;
336
330
  /**
337
331
  * Creates a new SourceCode object for the given file and parse result.
338
332
  */
339
- createSourceCode(file: File, parseResult: OkParseResult<AST.YAMLProgram> | YAMLParseResult): YAMLSourceCode;
333
+ createSourceCode(file: File, parseResult: OkParseResult<AST.YAMLProgram>): YAMLSourceCode;
340
334
  }
341
335
  //#endregion
342
336
  //#region src/index.d.ts
package/lib/index.mjs CHANGED
@@ -478,7 +478,7 @@ const OPTIONS_ENUM$1 = [
478
478
  /**
479
479
  * Parse options
480
480
  */
481
- function parseOptions$4(option) {
481
+ function parseOptions$5(option) {
482
482
  const opt = {
483
483
  singleline: "ignore",
484
484
  multiline: "always"
@@ -517,7 +517,7 @@ var block_mapping_default = createRule("block-mapping", {
517
517
  },
518
518
  create(context) {
519
519
  if (!context.sourceCode.parserServices?.isYAML) return {};
520
- const options = parseOptions$4(context.options[0]);
520
+ const options = parseOptions$5(context.options[0]);
521
521
  let styleStack = null;
522
522
  /**
523
523
  * Moves the stack down.
@@ -750,7 +750,7 @@ const OPTIONS_ENUM = [
750
750
  /**
751
751
  * Parse options
752
752
  */
753
- function parseOptions$3(option) {
753
+ function parseOptions$4(option) {
754
754
  const opt = {
755
755
  singleline: "ignore",
756
756
  multiline: "always"
@@ -790,7 +790,7 @@ var block_sequence_default = createRule("block-sequence", {
790
790
  create(context) {
791
791
  const sourceCode = context.sourceCode;
792
792
  if (!sourceCode.parserServices?.isYAML) return {};
793
- const options = parseOptions$3(context.options[0]);
793
+ const options = parseOptions$4(context.options[0]);
794
794
  let styleStack = null;
795
795
  /**
796
796
  * Moves the stack down.
@@ -1169,6 +1169,50 @@ var flow_mapping_curly_newline_default = createRule("flow-mapping-curly-newline"
1169
1169
 
1170
1170
  //#endregion
1171
1171
  //#region src/rules/flow-mapping-curly-spacing.ts
1172
+ /**
1173
+ * Parse rule options and return helpers for spacing checks.
1174
+ * @param options The options tuple from the rule configuration.
1175
+ * @param sourceCode The sourceCode object for node lookup.
1176
+ */
1177
+ function parseOptions$3(options, sourceCode) {
1178
+ const spaced = options[0] ?? "never";
1179
+ /**
1180
+ * Determines whether an exception option is set relative to the base spacing.
1181
+ * @param option The option to check.
1182
+ */
1183
+ function isOptionSet(option) {
1184
+ return options[1] ? options[1][option] === (spaced === "never") : false;
1185
+ }
1186
+ const arraysInObjectsException = isOptionSet("arraysInObjects");
1187
+ const objectsInObjectsException = isOptionSet("objectsInObjects");
1188
+ const emptyObjects = options[1]?.emptyObjects ?? "ignore";
1189
+ /**
1190
+ * Whether the opening brace must be spaced, considering exceptions.
1191
+ * @param spaced The primary spaced option string.
1192
+ * @param second The token after the opening brace.
1193
+ */
1194
+ function isOpeningCurlyBraceMustBeSpaced(spaced, second) {
1195
+ const targetPenultimateType = arraysInObjectsException && isOpeningBracketToken(second) ? "YAMLSequence" : objectsInObjectsException && isOpeningBraceToken(second) ? "YAMLMapping" : null;
1196
+ const node = sourceCode.getNodeByRangeIndex(second.range[0]);
1197
+ return targetPenultimateType && node?.type === targetPenultimateType ? spaced === "never" : spaced === "always";
1198
+ }
1199
+ /**
1200
+ * Whether the closing brace must be spaced, considering exceptions.
1201
+ * @param spaced The primary spaced option string.
1202
+ * @param penultimate The token before the closing brace.
1203
+ */
1204
+ function isClosingCurlyBraceMustBeSpaced(spaced, penultimate) {
1205
+ const targetPenultimateType = arraysInObjectsException && isClosingBracketToken(penultimate) ? "YAMLSequence" : objectsInObjectsException && isClosingBraceToken(penultimate) ? "YAMLMapping" : null;
1206
+ const node = sourceCode.getNodeByRangeIndex(penultimate.range[0]);
1207
+ return targetPenultimateType && node?.type === targetPenultimateType ? spaced === "never" : spaced === "always";
1208
+ }
1209
+ return {
1210
+ spaced,
1211
+ emptyObjects,
1212
+ isOpeningCurlyBraceMustBeSpaced,
1213
+ isClosingCurlyBraceMustBeSpaced
1214
+ };
1215
+ }
1172
1216
  var flow_mapping_curly_spacing_default = createRule("flow-mapping-curly-spacing", {
1173
1217
  meta: {
1174
1218
  docs: {
@@ -1186,7 +1230,15 @@ var flow_mapping_curly_spacing_default = createRule("flow-mapping-curly-spacing"
1186
1230
  type: "object",
1187
1231
  properties: {
1188
1232
  arraysInObjects: { type: "boolean" },
1189
- objectsInObjects: { type: "boolean" }
1233
+ objectsInObjects: { type: "boolean" },
1234
+ emptyObjects: {
1235
+ type: "string",
1236
+ enum: [
1237
+ "ignore",
1238
+ "always",
1239
+ "never"
1240
+ ]
1241
+ }
1190
1242
  },
1191
1243
  additionalProperties: false
1192
1244
  }],
@@ -1194,36 +1246,15 @@ var flow_mapping_curly_spacing_default = createRule("flow-mapping-curly-spacing"
1194
1246
  requireSpaceBefore: "A space is required before '{{token}}'.",
1195
1247
  requireSpaceAfter: "A space is required after '{{token}}'.",
1196
1248
  unexpectedSpaceBefore: "There should be no space before '{{token}}'.",
1197
- unexpectedSpaceAfter: "There should be no space after '{{token}}'."
1249
+ unexpectedSpaceAfter: "There should be no space after '{{token}}'.",
1250
+ requiredSpaceInEmptyObject: "A space is required in empty flow mapping.",
1251
+ unexpectedSpaceInEmptyObject: "There should be no space in empty flow mapping."
1198
1252
  }
1199
1253
  },
1200
1254
  create(context) {
1201
1255
  const sourceCode = context.sourceCode;
1202
1256
  if (!sourceCode.parserServices?.isYAML) return {};
1203
- const spaced = context.options[0] === "always";
1204
- /**
1205
- * Determines whether an option is set, relative to the spacing option.
1206
- * If spaced is "always", then check whether option is set to false.
1207
- * If spaced is "never", then check whether option is set to true.
1208
- * @param option The option to exclude.
1209
- * @returns Whether or not the property is excluded.
1210
- */
1211
- function isOptionSet(option) {
1212
- return context.options[1] ? context.options[1][option] === !spaced : false;
1213
- }
1214
- const options = {
1215
- spaced,
1216
- arraysInObjectsException: isOptionSet("arraysInObjects"),
1217
- objectsInObjectsException: isOptionSet("objectsInObjects"),
1218
- isOpeningCurlyBraceMustBeSpaced(second) {
1219
- const targetPenultimateType = options.arraysInObjectsException && isOpeningBracketToken(second) ? "YAMLSequence" : options.objectsInObjectsException && isOpeningBraceToken(second) ? "YAMLMapping" : null;
1220
- return targetPenultimateType && sourceCode.getNodeByRangeIndex(second.range[0])?.type === targetPenultimateType ? !options.spaced : options.spaced;
1221
- },
1222
- isClosingCurlyBraceMustBeSpaced(penultimate) {
1223
- const targetPenultimateType = options.arraysInObjectsException && isClosingBracketToken(penultimate) ? "YAMLSequence" : options.objectsInObjectsException && isClosingBraceToken(penultimate) ? "YAMLMapping" : null;
1224
- return targetPenultimateType && sourceCode.getNodeByRangeIndex(penultimate.range[0])?.type === targetPenultimateType ? !options.spaced : options.spaced;
1225
- }
1226
- };
1257
+ const options = parseOptions$3(context.options, sourceCode);
1227
1258
  /**
1228
1259
  * Reports that there shouldn't be a space after the first token
1229
1260
  * @param node The node to report in the event of an error.
@@ -1304,18 +1335,18 @@ var flow_mapping_curly_spacing_default = createRule("flow-mapping-curly-spacing"
1304
1335
  * @param penultimate The penultimate token to check (should be last before closing brace)
1305
1336
  * @param last The last token to check (should be closing brace)
1306
1337
  */
1307
- function validateBraceSpacing(node, first, second, penultimate, last) {
1308
- if (isTokenOnSameLine(first, second)) {
1309
- const firstSpaced = sourceCode.isSpaceBetween(first, second);
1310
- if (options.isOpeningCurlyBraceMustBeSpaced(second)) {
1311
- if (!firstSpaced) reportRequiredBeginningSpace(node, first);
1312
- } else if (firstSpaced && second.type !== "Line") reportNoBeginningSpace(node, first);
1338
+ function validateBraceSpacing(node, spaced, openingToken, second, penultimate, closingToken) {
1339
+ if (isTokenOnSameLine(openingToken, second)) {
1340
+ const firstSpaced = sourceCode.isSpaceBetween(openingToken, second);
1341
+ if (options.isOpeningCurlyBraceMustBeSpaced(spaced, second)) {
1342
+ if (!firstSpaced) reportRequiredBeginningSpace(node, openingToken);
1343
+ } else if (firstSpaced && second.type !== "Line") reportNoBeginningSpace(node, openingToken);
1313
1344
  }
1314
- if (isTokenOnSameLine(penultimate, last)) {
1315
- const lastSpaced = sourceCode.isSpaceBetween(penultimate, last);
1316
- if (options.isClosingCurlyBraceMustBeSpaced(penultimate)) {
1317
- if (!lastSpaced) reportRequiredEndingSpace(node, last);
1318
- } else if (lastSpaced) reportNoEndingSpace(node, last);
1345
+ if (isTokenOnSameLine(penultimate, closingToken)) {
1346
+ const lastSpaced = sourceCode.isSpaceBetween(penultimate, closingToken);
1347
+ if (options.isClosingCurlyBraceMustBeSpaced(spaced, penultimate)) {
1348
+ if (!lastSpaced) reportRequiredEndingSpace(node, closingToken);
1349
+ } else if (lastSpaced) reportNoEndingSpace(node, closingToken);
1319
1350
  }
1320
1351
  }
1321
1352
  /**
@@ -1337,11 +1368,61 @@ var flow_mapping_curly_spacing_default = createRule("flow-mapping-curly-spacing"
1337
1368
  * Reports a given object node if spacing in curly braces is invalid.
1338
1369
  * @param node An ObjectExpression or ObjectPattern node to check.
1339
1370
  */
1371
+ function checkSpaceInEmptyObject(node) {
1372
+ if (options.emptyObjects === "ignore") return;
1373
+ const openingToken = sourceCode.getFirstToken(node);
1374
+ const closingToken = sourceCode.getLastToken(node);
1375
+ const second = sourceCode.getTokenAfter(openingToken, { includeComments: true });
1376
+ if (second !== closingToken && isCommentToken(second)) {
1377
+ const penultimate = sourceCode.getTokenBefore(closingToken, { includeComments: true });
1378
+ validateBraceSpacing(node, options.emptyObjects, openingToken, second, penultimate, closingToken);
1379
+ return;
1380
+ }
1381
+ if (!isTokenOnSameLine(openingToken, closingToken)) return;
1382
+ const sourceBetween = sourceCode.text.slice(openingToken.range[1], closingToken.range[0]);
1383
+ if (sourceBetween.trim() !== "") return;
1384
+ if (options.emptyObjects === "always") {
1385
+ if (sourceBetween) return;
1386
+ context.report({
1387
+ node,
1388
+ loc: {
1389
+ start: openingToken.loc.end,
1390
+ end: closingToken.loc.start
1391
+ },
1392
+ messageId: "requiredSpaceInEmptyObject",
1393
+ fix(fixer) {
1394
+ return fixer.replaceTextRange([openingToken.range[1], closingToken.range[0]], " ");
1395
+ }
1396
+ });
1397
+ } else if (options.emptyObjects === "never") {
1398
+ if (!sourceBetween) return;
1399
+ context.report({
1400
+ node,
1401
+ loc: {
1402
+ start: openingToken.loc.end,
1403
+ end: closingToken.loc.start
1404
+ },
1405
+ messageId: "unexpectedSpaceInEmptyObject",
1406
+ fix(fixer) {
1407
+ return fixer.removeRange([openingToken.range[1], closingToken.range[0]]);
1408
+ }
1409
+ });
1410
+ }
1411
+ }
1412
+ /**
1413
+ * Reports a given mapping node if spacing in curly braces is invalid.
1414
+ * @param node A YAMLMapping node to check.
1415
+ */
1340
1416
  function checkForObject(node) {
1341
- if (node.pairs.length === 0) return;
1342
- const first = sourceCode.getFirstToken(node);
1343
- const last = getClosingBraceOfObject(node);
1344
- validateBraceSpacing(node, first, sourceCode.getTokenAfter(first, { includeComments: true }), sourceCode.getTokenBefore(last, { includeComments: true }), last);
1417
+ if (node.pairs.length === 0) {
1418
+ checkSpaceInEmptyObject(node);
1419
+ return;
1420
+ }
1421
+ const openingToken = sourceCode.getFirstToken(node);
1422
+ const closingToken = getClosingBraceOfObject(node);
1423
+ const second = sourceCode.getTokenAfter(openingToken, { includeComments: true });
1424
+ const penultimate = sourceCode.getTokenBefore(closingToken, { includeComments: true });
1425
+ validateBraceSpacing(node, options.spaced, openingToken, second, penultimate, closingToken);
1345
1426
  }
1346
1427
  return { YAMLMapping(node) {
1347
1428
  if (node.style === "flow") checkForObject(node);
@@ -5255,7 +5336,7 @@ var prettier_default = [...base_default, { rules: {
5255
5336
  //#endregion
5256
5337
  //#region package.json
5257
5338
  var name$1 = "eslint-plugin-yml";
5258
- var version$1 = "3.2.2";
5339
+ var version$1 = "3.3.1";
5259
5340
 
5260
5341
  //#endregion
5261
5342
  //#region src/meta.ts
@@ -5493,6 +5574,9 @@ var YAMLSourceCode = class extends TextSourceCodeBase {
5493
5574
  getCommentsAfter(nodeOrToken) {
5494
5575
  return this.tokenStore.getCommentsAfter(nodeOrToken);
5495
5576
  }
5577
+ commentsExistBetween(first, second) {
5578
+ return this.tokenStore.commentsExistBetween(first, second);
5579
+ }
5496
5580
  isSpaceBetween(first, second) {
5497
5581
  const [left, right] = first.range[1] <= second.range[0] ? [first, second] : [second, first];
5498
5582
  return this.tokenStore.isSpaceBetween(left, right);
@@ -5610,13 +5694,26 @@ var YAMLLanguage = class {
5610
5694
  */
5611
5695
  parse(file, context) {
5612
5696
  const text = file.body;
5613
- return {
5614
- ok: true,
5615
- ast: parseYAML(text, {
5616
- filePath: file.path,
5617
- defaultYAMLVersion: context.languageOptions?.parserOptions?.defaultYAMLVersion
5618
- })
5619
- };
5697
+ try {
5698
+ return {
5699
+ ok: true,
5700
+ ast: parseYAML(text, {
5701
+ filePath: file.path,
5702
+ defaultYAMLVersion: context.languageOptions?.parserOptions?.defaultYAMLVersion
5703
+ })
5704
+ };
5705
+ } catch (error) {
5706
+ const message = error instanceof Error ? error.message : String(error);
5707
+ const parseError = error;
5708
+ return {
5709
+ ok: false,
5710
+ errors: [{
5711
+ message,
5712
+ line: parseError.lineNumber ?? 1,
5713
+ column: parseError.column ?? 1
5714
+ }]
5715
+ };
5716
+ }
5620
5717
  }
5621
5718
  /**
5622
5719
  * Creates a new SourceCode object for the given file and parse result.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-yml",
3
- "version": "3.2.2",
3
+ "version": "3.3.1",
4
4
  "description": "This ESLint plugin provides linting rules for YAML.",
5
5
  "type": "module",
6
6
  "main": "lib/index.mjs",
@@ -77,7 +77,7 @@
77
77
  "eslint": ">=9.38.0"
78
78
  },
79
79
  "devDependencies": {
80
- "@changesets/changelog-github": "^0.5.0",
80
+ "@changesets/changelog-github": "^0.6.0",
81
81
  "@changesets/cli": "^2.24.2",
82
82
  "@eslint-community/eslint-plugin-eslint-comments": "^4.3.0",
83
83
  "@eslint/eslintrc": "^3.1.0",
@@ -112,7 +112,7 @@
112
112
  "events": "^3.3.0",
113
113
  "mocha": "^11.0.0",
114
114
  "monaco-editor": "^0.55.0",
115
- "nyc": "^17.0.0",
115
+ "nyc": "^18.0.0",
116
116
  "pako": "^2.1.0",
117
117
  "prettier": "^3.0.3",
118
118
  "semver": "^7.3.2",
@@ -125,7 +125,7 @@
125
125
  "tsx": "^4.21.0",
126
126
  "typescript": "~5.9.0",
127
127
  "typescript-eslint": "^8.0.0",
128
- "vite-plugin-eslint4b": "^0.6.0",
128
+ "vite-plugin-eslint4b": "^0.7.0",
129
129
  "vitepress": "^1.0.0-rc.17",
130
130
  "vue-eslint-parser": "^10.0.0",
131
131
  "yaml": "^2.1.1"