From 9f32e587af8e88612218a090b4b30af206185605 Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Tue, 23 Aug 2022 09:28:51 +0900 Subject: [PATCH] Fix `at-rule-no-unknown` end positions This change also adds a test helper function to make testing multiline strings easier. --- jest-setup.js | 7 + package.json | 1 + .../at-rule-no-unknown/__tests__/index.js | 132 +++++++++--------- src/rules/at-rule-no-unknown/index.js | 22 +-- 4 files changed, 83 insertions(+), 79 deletions(-) diff --git a/jest-setup.js b/jest-setup.js index a0fb03a6..83970fdd 100644 --- a/jest-setup.js +++ b/jest-setup.js @@ -1,3 +1,10 @@ const getTestRule = require("jest-preset-stylelint/getTestRule"); global.testRule = getTestRule({ plugins: ["./src"] }); + +// Inspired by https://www.npmjs.com/package/dedent-tag +global.dedent = function dedent(strings) { + return strings[0] + .replace(/^[ \t]+/gm, "") // remove indentation + .replace(/^\s*\n/gm, ""); // remove empty lines +}; diff --git a/package.json b/package.json index 09b2682d..bc96452b 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "lodash" ], "globals": { + "dedent": true, "testRule": true }, "rules": { diff --git a/src/rules/at-rule-no-unknown/__tests__/index.js b/src/rules/at-rule-no-unknown/__tests__/index.js index c854ba94..b732ab20 100644 --- a/src/rules/at-rule-no-unknown/__tests__/index.js +++ b/src/rules/at-rule-no-unknown/__tests__/index.js @@ -7,115 +7,111 @@ testRule({ accept: [ { - code: "@charset 'UTF-8';" + code: "@charset 'UTF-8';", }, { - code: "@CHARSET 'UTF-8';" + code: "@CHARSET 'UTF-8';", }, { - code: "@charset 'iso-8859-15'" + code: "@charset 'iso-8859-15'", }, { - code: '@import url("fineprint.css") print;' + code: '@import url("fineprint.css") print;', }, { - code: "@import 'custom.css'" + code: "@import 'custom.css'", }, { - code: "@import url('landscape.css') screen and (orientation:landscape);" + code: "@import url('landscape.css') screen and (orientation:landscape);", }, { - code: "@namespace url(http://www.w3.org/1999/xhtml);" + code: "@namespace url(http://www.w3.org/1999/xhtml);", }, { - code: "@namespace prefix url(XML-namespace-URL);" + code: "@namespace prefix url(XML-namespace-URL);", }, { - code: "@media print { body { font-size: 10pt } }" + code: "@media print { body { font-size: 10pt } }", }, { - code: "@media (max-width: 960px) { body { font-size: 13px } }" + code: "@media (max-width: 960px) { body { font-size: 13px } }", }, { - code: "@media screen, print { body { line-height: 1.2 } }" + code: "@media screen, print { body { line-height: 1.2 } }", }, { - code: "@supports (--foo: green) { body { color: green; } }" + code: "@supports (--foo: green) { body { color: green; } }", }, { - code: - "@supports ( (perspective: 10px) or (-webkit-perspective: 10px) ) { font-size: 10pt }" + code: "@supports ( (perspective: 10px) or (-webkit-perspective: 10px) ) { font-size: 10pt }", }, { - code: - "@counter-style win-list { system: fixed; symbols: url(gold-medal.svg); suffix: ' ';}" + code: "@counter-style win-list { system: fixed; symbols: url(gold-medal.svg); suffix: ' ';}", }, { - code: - "@document url(http://www.w3.org/), url-prefix(http://www.w3.org/Style/), domain(mozilla.org), regexp('https:.*')" + code: "@document url(http://www.w3.org/), url-prefix(http://www.w3.org/Style/), domain(mozilla.org), regexp('https:.*')", }, { - code: "@page :left { margin-left: 4cm; }" + code: "@page :left { margin-left: 4cm; }", }, { - code: - '@font-face { font-family: MyHelvetica; src: local("Helvetica"), url(MgOpenModern.ttf); }' + code: '@font-face { font-family: MyHelvetica; src: local("Helvetica"), url(MgOpenModern.ttf); }', }, { - code: - "@keyframes identifier { 0% { top: 0; left: 0; } 30% { top: 50px; } 68%, 100% { top: 100px; left: 100%; } }" + code: "@keyframes identifier { 0% { top: 0; left: 0; } 30% { top: 50px; } 68%, 100% { top: 100px; left: 100%; } }", }, { - code: - "@-webkit-keyframes identifier { 0% { top: 0; left: 0; } 30% { top: 50px; } 68%, 100% { top: 100px; left: 100%; } }" + code: "@-webkit-keyframes identifier { 0% { top: 0; left: 0; } 30% { top: 50px; } 68%, 100% { top: 100px; left: 100%; } }", }, { - code: "@viewport { min-width: 640px; max-width: 800px; }" + code: "@viewport { min-width: 640px; max-width: 800px; }", }, { - code: "@viewport { orientation: landscape; }" + code: "@viewport { orientation: landscape; }", }, { - code: - '@counter-style winners-list { system: fixed; symbols: url(gold-medal.svg); suffix: " "; }' + code: '@counter-style winners-list { system: fixed; symbols: url(gold-medal.svg); suffix: " "; }', }, { - code: "@font-feature-values Font One { @styleset { nice-style: 12; } }" + code: "@font-feature-values Font One { @styleset { nice-style: 12; } }", }, { - code: ".foo { color: red; @nest .parent & { color: blue; } }" + code: ".foo { color: red; @nest .parent & { color: blue; } }", }, { - code: '@forward "functions";' + code: '@forward "functions";', }, { - code: "@function foo () {}" + code: "@function foo () {}", }, { - code: "@extend %p" + code: "@extend %p", }, { - code: "@if ($i) {}" + code: "@if ($i) {}", }, { - code: "@if ($i) {} @else {}" + code: "@if ($i) {} @else {}", }, { - code: "@if ($i) {} @else if {} @else {}" + code: "@if ($i) {} @else if {} @else {}", }, { - code: '@use "bootstrap";' - } + code: '@use "bootstrap";', + }, ], reject: [ { - code: ` - @funciton floo ($n) {} - `, - line: 2, + code: dedent` + @funciton floo ($n) {} + `, + line: 1, + column: 1, + endLine: 1, + endColumn: 10, description: "", - message: messages.rejected("@funciton") + message: messages.rejected("@funciton"), }, { code: ` @@ -123,7 +119,7 @@ testRule({ `, line: 2, description: "", - message: messages.rejected("@Function") + message: messages.rejected("@Function"), }, { code: ` @@ -131,9 +127,9 @@ testRule({ `, line: 2, description: "", - message: messages.rejected("@While") - } - ] + message: messages.rejected("@While"), + }, + ], }); testRule({ @@ -141,21 +137,21 @@ testRule({ config: [ true, { - ignoreAtRules: ["unknown", "/^my-/i"] - } + ignoreAtRules: ["unknown", "/^my-/i"], + }, ], skipBasicChecks: true, accept: [ { - code: "@unknown { }" + code: "@unknown { }", }, { - code: "@my-at-rule { }" + code: "@my-at-rule { }", }, { - code: "@MY-other-at-rule { }" - } + code: "@MY-other-at-rule { }", + }, ], reject: [ @@ -163,39 +159,39 @@ testRule({ code: "@unknown-at-rule { }", line: 1, column: 1, - message: messages.rejected("@unknown-at-rule") + message: messages.rejected("@unknown-at-rule"), }, { code: "@unknown { @unknown-at-rule { font-size: 14px; } }", line: 1, column: 12, - message: messages.rejected("@unknown-at-rule") + message: messages.rejected("@unknown-at-rule"), }, { code: "@not-my-at-rule {}", line: 1, column: 1, - message: messages.rejected("@not-my-at-rule") + message: messages.rejected("@not-my-at-rule"), }, { code: "@Unknown { }", line: 1, column: 1, - message: messages.rejected("@Unknown") + message: messages.rejected("@Unknown"), }, { code: "@uNkNoWn { }", line: 1, column: 1, - message: messages.rejected("@uNkNoWn") + message: messages.rejected("@uNkNoWn"), }, { code: "@UNKNOWN { }", line: 1, column: 1, - message: messages.rejected("@UNKNOWN") - } - ] + message: messages.rejected("@UNKNOWN"), + }, + ], }); testRule({ @@ -211,14 +207,14 @@ testRule({ { line: 1, column: 1, - message: messages.rejected("@foo") + message: messages.rejected("@foo"), }, { line: 1, column: 10, - message: messages.rejected("@bar") - } - ] - } - ] + message: messages.rejected("@bar"), + }, + ], + }, + ], }); diff --git a/src/rules/at-rule-no-unknown/index.js b/src/rules/at-rule-no-unknown/index.js index ef0634c0..dd25019d 100644 --- a/src/rules/at-rule-no-unknown/index.js +++ b/src/rules/at-rule-no-unknown/index.js @@ -22,7 +22,7 @@ const sassAtRules = [ "return", "use", "warn", - "while" + "while", ]; const ruleToCheckAgainst = "at-rule-no-unknown"; @@ -34,11 +34,11 @@ export const messages = utils.ruleMessages(ruleName, { return rules[ruleToCheckAgainst].messages .rejected(...args) .replace(` (${ruleToCheckAgainst})`, ""); - } + }, }); export const meta = { - url: ruleUrl(ruleName) + url: ruleUrl(ruleName), }; export default function rule(primaryOption, secondaryOptions) { @@ -47,14 +47,14 @@ export default function rule(primaryOption, secondaryOptions) { result, ruleName, { - actual: primaryOption + actual: primaryOption, }, { actual: secondaryOptions, possible: { - ignoreAtRules: [isRegExp, isString] + ignoreAtRules: [isRegExp, isString], }, - optional: true + optional: true, } ); @@ -65,16 +65,16 @@ export default function rule(primaryOption, secondaryOptions) { const optionsAtRules = secondaryOptions && secondaryOptions.ignoreAtRules; const ignoreAtRules = sassAtRules.concat(optionsAtRules || []); const defaultedOptions = Object.assign({}, secondaryOptions, { - ignoreAtRules + ignoreAtRules, }); utils.checkAgainstRule( { ruleName: ruleToCheckAgainst, ruleSettings: [primaryOption, defaultedOptions], - root + root, }, - warning => { + (warning) => { const name = warning.node.name; if (!ignoreAtRules.includes(name)) { @@ -83,8 +83,8 @@ export default function rule(primaryOption, secondaryOptions) { ruleName, result, node: warning.node, - line: warning.line, - column: warning.column + start: { line: warning.line, column: warning.column }, + end: { line: warning.endLine, column: warning.endColumn }, }); } }