Skip to content

Commit

Permalink
feat: add overrides option to yml/plain-scalar (#374)
Browse files Browse the repository at this point in the history
* feat: add `overrides` option to `yml/plain-scalar`

* Create chilled-emus-tap.md
  • Loading branch information
ota-meshi authored Oct 31, 2024
1 parent d10b977 commit 4790eaf
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilled-emus-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-yml": minor
---

feat: add `overrides` option to `yml/plain-scalar`
4 changes: 4 additions & 0 deletions docs/rules/plain-scalar.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,16 @@ yml/plain-scalar:
- always # or "never"
- ignorePatterns:
- "[\\v\\f\\u0085\\u00a0\\u1680\\u180e\\u2000-\\u200b\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]"
overrides:
mappingKey: null # or "always" or "never"
```
- `"always"` ... Enforce the use of plain style scalars.
- `"never"` ... Disallow the use of plain style scalars.
- `ignorePatterns` ... Specify the pattern to be excluded from the check as an array.
If `"always"`, the default is `[ "[\\v\\f\\u0085\\u00a0\\u1680\\u180e\\u2000-\\u200b\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]" ]`. It to ignores irregular whitespace.
- `overrides` ... Overrides any setting to a specific value.
- `mappingKey` ... Specify the style to use for the mapping key.

## :couple: Related rules

Expand Down
71 changes: 59 additions & 12 deletions src/rules/plain-scalar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ export default createRule("plain-scalar", {
type: "array",
items: { type: "string" },
},
overrides: {
type: "object",
properties: {
mappingKey: { enum: ["always", "never", null] },
},
additionalProperties: false,
},
},
additionalProperties: false,
},
Expand All @@ -83,16 +90,39 @@ export default createRule("plain-scalar", {
if (!sourceCode.parserServices.isYAML) {
return {};
}
const option: "always" | "never" = context.options[0] || "always";
const ignorePatterns: RegExp[] = toRegExps(
context.options[1]?.ignorePatterns ??
(option === "always"
? [
// Irregular white spaces
String.raw`[\v\f\u0085\u00a0\u1680\u180e\u2000-\u200b\u2028\u2029\u202f\u205f\u3000\ufeff]`,
]
: []),
);
type Option = {
prefer: "always" | "never";
ignorePatterns: RegExp[];
};
const valueOption: Option = {
prefer: context.options[0] || "always",
ignorePatterns: [],
};
const overridesMappingKey = context.options[1]?.overrides?.mappingKey;
const keyOption: Option = overridesMappingKey
? {
prefer: overridesMappingKey,
ignorePatterns: [],
}
: valueOption;
if (context.options[1]?.ignorePatterns) {
valueOption.ignorePatterns = toRegExps(
context.options[1]?.ignorePatterns,
);
} else {
if (valueOption.prefer === "always") {
valueOption.ignorePatterns = toRegExps([
// Irregular white spaces
String.raw`[\v\f\u0085\u00a0\u1680\u180e\u2000-\u200b\u2028\u2029\u202f\u205f\u3000\ufeff]`,
]);
}
if (overridesMappingKey && keyOption.prefer === "always") {
keyOption.ignorePatterns = toRegExps([
// Irregular white spaces
String.raw`[\v\f\u0085\u00a0\u1680\u180e\u2000-\u200b\u2028\u2029\u202f\u205f\u3000\ufeff]`,
]);
}
}

let currentDocument: AST.YAMLDocument | undefined;

Expand Down Expand Up @@ -202,6 +232,21 @@ export default createRule("plain-scalar", {
});
}

/**
* Checks whether the given node is within key
*/
function withinKey(node: AST.YAMLScalar | AST.YAMLWithMeta) {
const parent = node.parent;
if (parent.type === "YAMLPair" && parent.key === node) {
return true;
}
const grandParent = parent.parent;
if (grandParent.type === "YAMLWithMeta") {
return withinKey(grandParent);
}
return false;
}

return {
YAMLDocument(node) {
currentDocument = node;
Expand All @@ -210,10 +255,12 @@ export default createRule("plain-scalar", {
if (!isStringScalar(node)) {
return;
}
if (ignorePatterns.some((p) => p.test(node.value))) {
const option = withinKey(node) ? keyOption : valueOption;

if (option.ignorePatterns.some((p) => p.test(node.value))) {
return;
}
if (option === "always") {
if (option.prefer === "always") {
verifyAlways(node);
} else {
verifyNever(node);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"options": ["never", { "overrides": { "mappingKey": "always" } }]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"message": "Must use quoted style scalar.",
"line": 2,
"column": 6
},
{
"message": "Must use plain style scalar.",
"line": 3,
"column": 3
},
{
"message": "Must use quoted style scalar.",
"line": 4,
"column": 8
},
{
"message": "Must use plain style scalar.",
"line": 5,
"column": 5
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- a: b
- "a": "b"
- { a: b }
- { "a": "b" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# plain-scalar/invalid/override-mapping-key/map-test-input.yml
- a: "b"
- a: "b"
- { a: "b" }
- { a: "b" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"message": "Must use quoted style scalar.",
"line": 2,
"column": 3
},
{
"message": "Must use quoted style scalar.",
"line": 4,
"column": 4
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- a
- "b"
- [a, "b"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# plain-scalar/invalid/override-mapping-key/seq-test-input.yml
- "a"
- "b"
- ["a", "b"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"options": ["never", { "overrides": { "mappingKey": "always" } }]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- a: "b"
- { a: "b" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- "a"
- "b"
- ["a", "b"]
3 changes: 2 additions & 1 deletion tests/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ function writeFixtures(
const result = linter.verify(
config.code,
{
files: ["**/*.*"],
plugins: {
yml: plugin,
},
Expand All @@ -321,7 +322,7 @@ function writeFixtures(
yml: ymlSettings,
},
},
config.filename,
inputFile,
);
if (force || !fs.existsSync(errorFile)) {
fs.writeFileSync(
Expand Down

0 comments on commit 4790eaf

Please sign in to comment.