From f49ece46d482ed1732f2ca34cbd975dbaf447e24 Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Fri, 23 Jun 2023 17:52:53 +0200 Subject: [PATCH 1/6] Add `media-query-no-invalid` --- docs/user-guide/rules.md | 1 + lib/rules/index.js | 1 + .../__tests__/index.js | 11 + .../index.js | 3 + lib/rules/media-feature-no-invalid/README.md | 57 ++++ .../__tests__/index.js | 251 ++++++++++++++++++ lib/rules/media-feature-no-invalid/index.js | 158 +++++++++++ package-lock.json | 16 +- package.json | 2 +- 9 files changed, 491 insertions(+), 9 deletions(-) create mode 100644 lib/rules/media-feature-no-invalid/README.md create mode 100644 lib/rules/media-feature-no-invalid/__tests__/index.js create mode 100644 lib/rules/media-feature-no-invalid/index.js diff --git a/docs/user-guide/rules.md b/docs/user-guide/rules.md index 1dd541d7d0..8c2506f9f0 100644 --- a/docs/user-guide/rules.md +++ b/docs/user-guide/rules.md @@ -62,6 +62,7 @@ Disallow invalid syntax with these (sometimes implicit) `no-invalid` rules. | [`no-invalid-double-slash-comments`](../../lib/rules/no-invalid-double-slash-comments/README.md)
Disallow invalid double-slash comments. | ✅ | | | [`no-invalid-position-at-import-rule`](../../lib/rules/no-invalid-position-at-import-rule/README.md)
Disallow invalid position `@import` rules. | ✅ | | | [`string-no-newline`](../../lib/rules/string-no-newline/README.md)
Disallow invalid newlines within strings. | ✅ | | +| [`media-feature-no-invalid`](../../lib/rules/media-feature-no-invalid/README.md)
Disallow invalid media queries. | | | ### Irregular diff --git a/lib/rules/index.js b/lib/rules/index.js index 68f5fd871e..baa04c4fa1 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -203,6 +203,7 @@ const rules = { 'media-feature-name-value-no-unknown': importLazy(() => require('./media-feature-name-value-no-unknown'), )(), + 'media-feature-no-invalid': importLazy(() => require('./media-feature-no-invalid'))(), 'media-feature-parentheses-space-inside': importLazy(() => require('./media-feature-parentheses-space-inside'), )(), diff --git a/lib/rules/media-feature-name-no-unknown/__tests__/index.js b/lib/rules/media-feature-name-no-unknown/__tests__/index.js index 691b5f264a..d95c25b52b 100644 --- a/lib/rules/media-feature-name-no-unknown/__tests__/index.js +++ b/lib/rules/media-feature-name-no-unknown/__tests__/index.js @@ -62,6 +62,9 @@ testRule({ { code: '@media () { }', }, + { + code: '@media (grid: 1) {}', + }, ], reject: [ @@ -153,6 +156,14 @@ testRule({ endLine: 1, endColumn: 49, }, + { + code: '@media (min-grid: 1) { }', + message: messages.rejected('min-grid'), + line: 1, + column: 9, + endLine: 1, + endColumn: 17, + }, ], }); diff --git a/lib/rules/media-feature-name-value-no-unknown/index.js b/lib/rules/media-feature-name-value-no-unknown/index.js index 235e482820..62950526ce 100644 --- a/lib/rules/media-feature-name-value-no-unknown/index.js +++ b/lib/rules/media-feature-name-value-no-unknown/index.js @@ -6,6 +6,7 @@ const { isMediaFeature, isMediaFeatureValue, matchesRatioExactly, + isMediaQueryInvalid, } = require('@csstools/media-query-list-parser'); const atRuleParamIndex = require('../../utils/atRuleParamIndex'); @@ -239,6 +240,8 @@ const rule = (primary) => { }; parseMediaQuery(atRule).forEach((mediaQuery) => { + if (isMediaQueryInvalid(mediaQuery)) return; + mediaQuery.walk((entry) => { if (!entry.state) return; diff --git a/lib/rules/media-feature-no-invalid/README.md b/lib/rules/media-feature-no-invalid/README.md new file mode 100644 index 0000000000..750a4398ab --- /dev/null +++ b/lib/rules/media-feature-no-invalid/README.md @@ -0,0 +1,57 @@ +# media-feature-no-invalid + +Disallow invalid media queries. + + +```css +@media not(min-width: 300px) {} +/** ↑ + * This media query */ +``` + +Media queries must be grammatically valid according to the [Media Queries Level 5](https://www.w3.org/TR/mediaqueries-5/) specification. + +The [`message` secondary option](../../../docs/user-guide/configure.md#message) can accept the arguments of this rule. + +## Options + +### `true` + +The following patterns are considered problems: + + +```css +@media not(min-width: 300px) {} +``` + + +```css +@media (width == 100px) {} +``` + + +```css +@media (color) and (hover) or (width) {} +``` + +The following patterns are _not_ considered problems: + + +```css +@media not (min-width: 300px) {} +``` + + +```css +@media (width = 100px) {} +``` + + +```css +@media ((color) and (hover)) or (width) {} +``` + + +```css +@media (color) and ((hover) or (width)) {} +``` diff --git a/lib/rules/media-feature-no-invalid/__tests__/index.js b/lib/rules/media-feature-no-invalid/__tests__/index.js new file mode 100644 index 0000000000..6ada83741c --- /dev/null +++ b/lib/rules/media-feature-no-invalid/__tests__/index.js @@ -0,0 +1,251 @@ +'use strict'; + +const { messages, ruleName } = require('..'); + +testRule({ + ruleName, + config: [true], + + accept: [ + { + code: '@media screen {}', + }, + { + code: '@media print {}', + }, + { + code: '@media all {}', + }, + { + code: '@media {}', + }, + { + code: '@media screen and (color) {}', + }, + { + code: '@media only screen and (color) {}', + }, + { + code: '@media speech and (device-aspect-ratio: 16/9) {}', + }, + { + code: '@media (width >= 600px) {}', + }, + { + code: '@media (width: 600px) {}', + }, + { + code: '@media not (width <= -100px) {}', + }, + { + code: '@media not (resolution: -300dpi) {}', + }, + { + code: '@media (min-width: 320.01px) {}', + }, + { + code: '@media not (color) {}', + }, + { + code: '@media (width < 600px) and (height < 600px) {}', + }, + { + code: '@media (width < 600px) and (height < 600px) {}', + }, + { + code: '@media (not (color)) or (hover) {}', + }, + { + code: '@media (not (color)) and (not (hover)) {}', + }, + { + code: '@media (not (color)) and (not (hover)) {}', + }, + { + code: '@media screen and (max-weight: 3kg) and (color), (color) {}', + }, + { + code: '@media not unknown {}', + }, + ], + + reject: [ + { + code: '@media @foo {}', + message: messages.rejected('@foo'), + line: 1, + column: 8, + endLine: 1, + endColumn: 12, + }, + { + code: '@media screen or (min-width > 500px) {}', + message: messages.rejected('screen or (min-width > 500px)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 37, + }, + { + code: '@media ((min-width: 300px) and (hover: hover) or (aspect-ratio: 1 / 1)) {}', + message: messages.rejected( + '((min-width: 300px) and (hover: hover) or (aspect-ratio: 1 / 1))', + ), + line: 1, + column: 8, + endLine: 1, + endColumn: 72, + }, + { + code: '@media (min-width: var(--foo)) {}', + message: messages.rejected('(min-width: var(--foo))'), + line: 1, + column: 8, + endLine: 1, + endColumn: 31, + }, + { + code: '@media (min-width: 50%) {}', + message: messages.rejected('(min-width: 50%)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 24, + }, + { + code: '@media ((color: 2) and (min-width: 50%)) {}', + message: messages.rejected('(min-width: 50%)'), + line: 1, + column: 24, + endLine: 1, + endColumn: 40, + }, + { + code: '@media ((color: foo(--bar)) and (min-width: 50%)) {}', + warnings: [ + { + message: messages.rejected('(color: foo(--bar))'), + line: 1, + column: 9, + endLine: 1, + endColumn: 28, + }, + { + message: messages.rejected('(min-width: 50%)'), + line: 1, + column: 33, + endLine: 1, + endColumn: 49, + }, + ], + }, + { + code: '@media (color: foo(--bar)), (min-width: 50%) {}', + warnings: [ + { + message: messages.rejected('(color: foo(--bar))'), + line: 1, + column: 8, + endLine: 1, + endColumn: 27, + }, + { + message: messages.rejected('(min-width: 50%)'), + line: 1, + column: 29, + endLine: 1, + endColumn: 45, + }, + ], + }, + { + code: '@media (--foo: 2) {}', + message: messages.rejected('(--foo: 2)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 18, + }, + { + code: '@media (min-width < 500px) {}', + message: messages.rejected('(min-width < 500px)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 27, + }, + { + code: '@media (min-width) {}', + message: messages.rejected('(min-width)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 19, + }, + { + code: '@media (grid < 0) {}', + message: messages.rejected('(grid < 0)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 18, + }, + { + code: '@media (not (color) and (hover)) {}', + message: messages.rejected('(not (color) and (hover))'), + line: 1, + column: 8, + endLine: 1, + endColumn: 33, + }, + + { + code: '@media (color) and (hover) or (width) {}', + message: messages.rejected('(color) and (hover) or (width)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 38, + }, + { + code: '@media (width => 100px) {}', + message: messages.rejected('(width => 100px)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 24, + }, + { + code: '@media (width == 100px) {}', + message: messages.rejected('(width == 100px)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 24, + }, + { + code: '@media not(min-width: 100px) {}', + message: messages.rejected('not(min-width: 100px)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 29, + }, + { + code: '@media foo screen {}', + message: messages.rejected('foo screen'), + line: 1, + column: 8, + endLine: 1, + endColumn: 18, + }, + { + code: '@media not screen foo (min-width: 300px) {}', + message: messages.rejected('not screen foo (min-width: 300px)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 41, + }, + ], +}); diff --git a/lib/rules/media-feature-no-invalid/index.js b/lib/rules/media-feature-no-invalid/index.js new file mode 100644 index 0000000000..b4d5f84d83 --- /dev/null +++ b/lib/rules/media-feature-no-invalid/index.js @@ -0,0 +1,158 @@ +'use strict'; + +const { + isMediaQueryInvalid, + isGeneralEnclosed, + isMediaFeaturePlain, + isMediaFeatureRange, + isMediaFeatureBoolean, +} = require('@csstools/media-query-list-parser'); + +const atRuleParamIndex = require('../../utils/atRuleParamIndex'); +const parseMediaQuery = require('../../utils/parseMediaQuery'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); +const isCustomMediaQuery = require('../../utils/isCustomMediaQuery'); +const { rangeTypeMediaFeatureNames } = require('../../reference/mediaFeatures'); + +const ruleName = 'media-feature-no-invalid'; + +const messages = ruleMessages(ruleName, { + rejected: (query) => `Unexpected invalid media query "${query}"`, +}); + +const HAS_MIN_MAX_PREFIX = /^(?:min|max)-/i; + +const meta = { + url: 'https://stylelint.io/user-guide/rules/media-feature-no-invalid', +}; + +/** @type {import('stylelint').Rule} */ +const rule = (primary) => { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { actual: primary }); + + if (!validOptions) { + return; + } + + root.walkAtRules(/^media$/i, (atRule) => { + /** @type {Array<{tokens(): Array}>} */ + let invalidNodes = []; + + parseMediaQuery(atRule).forEach((mediaQuery) => { + if (isMediaQueryInvalid(mediaQuery)) { + // Queries that fail to parse are invalid. + invalidNodes.push(mediaQuery); + + return; + } + + mediaQuery.walk((entry) => { + // All general enclosured nodes are invalid. + if (isGeneralEnclosed(entry.node)) { + invalidNodes.push(entry.node); + + return; + } + + // Invalid plain media features. + if (isMediaFeaturePlain(entry.node)) { + const name = entry.node.getName(); + + if (isCustomMediaQuery(name)) { + // In a plain context, custom media queries are invalid. + invalidNodes.push(entry.parent); + + return; + } + + return; + } + + // Invalid range media features. + if (isMediaFeatureRange(entry.node)) { + const name = entry.node.getName().toLowerCase(); + + if (isCustomMediaQuery(name)) { + // In a range context, custom media queries are invalid. + invalidNodes.push(entry.parent); + + return; + } + + if (HAS_MIN_MAX_PREFIX.test(name)) { + // In a range context, min- and max- prefixed feature names are invalid. + invalidNodes.push(entry.parent); + + return; + } + + if (!rangeTypeMediaFeatureNames.has(name)) { + // In a range context, non-range typed features are invalid. + invalidNodes.push(entry.parent); + + return; + } + + return; + } + + // Invalid boolean media features. + if (isMediaFeatureBoolean(entry.node)) { + const name = entry.node.getName().toLowerCase(); + + if (HAS_MIN_MAX_PREFIX.test(name)) { + // In a range context, min- and max- prefixed feature names are invalid + invalidNodes.push(entry.parent); + } + } + }); + }); + + if (invalidNodes.length === 0) return; + + const atRuleParamIndexValue = atRuleParamIndex(atRule); + + invalidNodes.forEach((invalidNode) => { + const [start, end] = startAndEndIndex(invalidNode); + + report({ + message: messages.rejected, + messageArgs: [invalidNode.toString()], + index: atRuleParamIndexValue + start, + endIndex: atRuleParamIndexValue + end + 1, + node: atRule, + ruleName, + result, + }); + }); + }); + }; +}; + +/** + * A function that returns the start and end boundaries of a node. + * + * @param {{ tokens(): Array }} node + * @returns {[number, number]} + */ +function startAndEndIndex(node) { + const tokens = node.tokens(); + + const firstToken = tokens[0]; + const lastToken = tokens[tokens.length - 1]; + + if (!firstToken || !lastToken) return [0, 0]; + + const start = firstToken[2]; + const end = lastToken[3]; + + return [start, end]; +} + +rule.ruleName = ruleName; +rule.messages = messages; +rule.meta = meta; +module.exports = rule; diff --git a/package-lock.json b/package-lock.json index 9ae1e7a3e4..2881de2379 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@csstools/css-parser-algorithms": "^2.2.0", "@csstools/css-tokenizer": "^2.1.1", - "@csstools/media-query-list-parser": "^2.1.0", + "@csstools/media-query-list-parser": "^2.1.1", "@csstools/selector-specificity": "^2.2.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", @@ -1512,9 +1512,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.0.tgz", - "integrity": "sha512-MXkR+TeaS2q9IkpyO6jVCdtA/bfpABJxIrfkLswThFN8EZZgI2RfAHhm6sDNDuYV25d5+b8Lj1fpTccIcSLPsQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.1.tgz", + "integrity": "sha512-pUjtFbaKbiFNjJo8pprrIaXLvQvWIlwPiFnRI4sEnc4F0NIGTOsw8kaJSR3CmZAKEvV8QYckovgAnWQC0bgLLQ==", "funding": [ { "type": "github", @@ -1529,7 +1529,7 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.1.1", + "@csstools/css-parser-algorithms": "^2.2.0", "@csstools/css-tokenizer": "^2.1.1" } }, @@ -17142,9 +17142,9 @@ "integrity": "sha512-GbrTj2Z8MCTUv+52GE0RbFGM527xuXZ0Xa5g0Z+YN573uveS4G0qi6WNOMyz3yrFM/jaILTTwJ0+umx81EzqfA==" }, "@csstools/media-query-list-parser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.0.tgz", - "integrity": "sha512-MXkR+TeaS2q9IkpyO6jVCdtA/bfpABJxIrfkLswThFN8EZZgI2RfAHhm6sDNDuYV25d5+b8Lj1fpTccIcSLPsQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.1.tgz", + "integrity": "sha512-pUjtFbaKbiFNjJo8pprrIaXLvQvWIlwPiFnRI4sEnc4F0NIGTOsw8kaJSR3CmZAKEvV8QYckovgAnWQC0bgLLQ==", "requires": {} }, "@csstools/selector-specificity": { diff --git a/package.json b/package.json index 10e11cf45e..d364f413c0 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "dependencies": { "@csstools/css-parser-algorithms": "^2.2.0", "@csstools/css-tokenizer": "^2.1.1", - "@csstools/media-query-list-parser": "^2.1.0", + "@csstools/media-query-list-parser": "^2.1.1", "@csstools/selector-specificity": "^2.2.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", From a86927372777f730be256c55bc239559ebcb64b9 Mon Sep 17 00:00:00 2001 From: Romain Menke <11521496+romainmenke@users.noreply.github.com> Date: Fri, 23 Jun 2023 17:56:50 +0200 Subject: [PATCH 2/6] Create early-jobs-hunt.md --- .changeset/early-jobs-hunt.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/early-jobs-hunt.md diff --git a/.changeset/early-jobs-hunt.md b/.changeset/early-jobs-hunt.md new file mode 100644 index 0000000000..5620cd66a5 --- /dev/null +++ b/.changeset/early-jobs-hunt.md @@ -0,0 +1,5 @@ +--- +"stylelint": minor +--- + +Added: `media-query-no-invalid` From bd0a51e74ecbd6b498b3ea66cbba7b5513156aef Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Fri, 23 Jun 2023 18:17:11 +0200 Subject: [PATCH 3/6] fix rule name --- docs/user-guide/rules.md | 2 +- lib/rules/index.js | 2 +- .../README.md | 2 +- .../__tests__/index.js | 0 .../index.js | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename lib/rules/{media-feature-no-invalid => media-query-no-invalid}/README.md (97%) rename lib/rules/{media-feature-no-invalid => media-query-no-invalid}/__tests__/index.js (100%) rename lib/rules/{media-feature-no-invalid => media-query-no-invalid}/index.js (98%) diff --git a/docs/user-guide/rules.md b/docs/user-guide/rules.md index 8c2506f9f0..6a0ac130f4 100644 --- a/docs/user-guide/rules.md +++ b/docs/user-guide/rules.md @@ -62,7 +62,7 @@ Disallow invalid syntax with these (sometimes implicit) `no-invalid` rules. | [`no-invalid-double-slash-comments`](../../lib/rules/no-invalid-double-slash-comments/README.md)
Disallow invalid double-slash comments. | ✅ | | | [`no-invalid-position-at-import-rule`](../../lib/rules/no-invalid-position-at-import-rule/README.md)
Disallow invalid position `@import` rules. | ✅ | | | [`string-no-newline`](../../lib/rules/string-no-newline/README.md)
Disallow invalid newlines within strings. | ✅ | | -| [`media-feature-no-invalid`](../../lib/rules/media-feature-no-invalid/README.md)
Disallow invalid media queries. | | | +| [`media-query-no-invalid`](../../lib/rules/media-query-no-invalid/README.md)
Disallow invalid media queries. | | | ### Irregular diff --git a/lib/rules/index.js b/lib/rules/index.js index baa04c4fa1..4c71d0e055 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -203,7 +203,7 @@ const rules = { 'media-feature-name-value-no-unknown': importLazy(() => require('./media-feature-name-value-no-unknown'), )(), - 'media-feature-no-invalid': importLazy(() => require('./media-feature-no-invalid'))(), + 'media-query-no-invalid': importLazy(() => require('./media-query-no-invalid'))(), 'media-feature-parentheses-space-inside': importLazy(() => require('./media-feature-parentheses-space-inside'), )(), diff --git a/lib/rules/media-feature-no-invalid/README.md b/lib/rules/media-query-no-invalid/README.md similarity index 97% rename from lib/rules/media-feature-no-invalid/README.md rename to lib/rules/media-query-no-invalid/README.md index 750a4398ab..b679778fab 100644 --- a/lib/rules/media-feature-no-invalid/README.md +++ b/lib/rules/media-query-no-invalid/README.md @@ -1,4 +1,4 @@ -# media-feature-no-invalid +# media-query-no-invalid Disallow invalid media queries. diff --git a/lib/rules/media-feature-no-invalid/__tests__/index.js b/lib/rules/media-query-no-invalid/__tests__/index.js similarity index 100% rename from lib/rules/media-feature-no-invalid/__tests__/index.js rename to lib/rules/media-query-no-invalid/__tests__/index.js diff --git a/lib/rules/media-feature-no-invalid/index.js b/lib/rules/media-query-no-invalid/index.js similarity index 98% rename from lib/rules/media-feature-no-invalid/index.js rename to lib/rules/media-query-no-invalid/index.js index b4d5f84d83..df8c09e4b6 100644 --- a/lib/rules/media-feature-no-invalid/index.js +++ b/lib/rules/media-query-no-invalid/index.js @@ -16,7 +16,7 @@ const validateOptions = require('../../utils/validateOptions'); const isCustomMediaQuery = require('../../utils/isCustomMediaQuery'); const { rangeTypeMediaFeatureNames } = require('../../reference/mediaFeatures'); -const ruleName = 'media-feature-no-invalid'; +const ruleName = 'media-query-no-invalid'; const messages = ruleMessages(ruleName, { rejected: (query) => `Unexpected invalid media query "${query}"`, From 67dbfc23c7e10bac3c6aa6fe7e0f89ad7c2e2fce Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Fri, 23 Jun 2023 18:19:43 +0200 Subject: [PATCH 4/6] increase test coverage --- .../media-query-no-invalid/__tests__/index.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/rules/media-query-no-invalid/__tests__/index.js b/lib/rules/media-query-no-invalid/__tests__/index.js index 6ada83741c..1582375c40 100644 --- a/lib/rules/media-query-no-invalid/__tests__/index.js +++ b/lib/rules/media-query-no-invalid/__tests__/index.js @@ -247,5 +247,21 @@ testRule({ endLine: 1, endColumn: 41, }, + { + code: '@media (--foo: 300px) {}', + message: messages.rejected('(--foo: 300px)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 22, + }, + { + code: '@media (--foo < 300px) {}', + message: messages.rejected('(--foo < 300px)'), + line: 1, + column: 8, + endLine: 1, + endColumn: 23, + }, ], }); From a8be46224fa99a24368cef8afb818f6955b79433 Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Sat, 24 Jun 2023 10:26:22 +0200 Subject: [PATCH 5/6] apply suggestions from code review --- docs/user-guide/rules.md | 2 +- lib/rules/index.js | 2 +- lib/rules/media-query-no-invalid/index.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/user-guide/rules.md b/docs/user-guide/rules.md index 6a0ac130f4..59faba2cd4 100644 --- a/docs/user-guide/rules.md +++ b/docs/user-guide/rules.md @@ -58,11 +58,11 @@ Disallow invalid syntax with these (sometimes implicit) `no-invalid` rules. | [`color-no-invalid-hex`](../../lib/rules/color-no-invalid-hex/README.md)
Disallow invalid hex colors. | ✅ | | | [`function-calc-no-unspaced-operator`](../../lib/rules/function-calc-no-unspaced-operator/README.md)
Disallow invalid unspaced operator within `calc` functions. | ✅ | 🔧 | | [`keyframe-declaration-no-important`](../../lib/rules/keyframe-declaration-no-important/README.md)
Disallow invalid `!important` within keyframe declarations. | ✅ | | +| [`media-query-no-invalid`](../../lib/rules/media-query-no-invalid/README.md)
Disallow invalid media queries. | | | | [`named-grid-areas-no-invalid`](../../lib/rules/named-grid-areas-no-invalid/README.md)
Disallow invalid named grid areas. | ✅ | | | [`no-invalid-double-slash-comments`](../../lib/rules/no-invalid-double-slash-comments/README.md)
Disallow invalid double-slash comments. | ✅ | | | [`no-invalid-position-at-import-rule`](../../lib/rules/no-invalid-position-at-import-rule/README.md)
Disallow invalid position `@import` rules. | ✅ | | | [`string-no-newline`](../../lib/rules/string-no-newline/README.md)
Disallow invalid newlines within strings. | ✅ | | -| [`media-query-no-invalid`](../../lib/rules/media-query-no-invalid/README.md)
Disallow invalid media queries. | | | ### Irregular diff --git a/lib/rules/index.js b/lib/rules/index.js index 4c71d0e055..6693e5f47b 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -203,7 +203,6 @@ const rules = { 'media-feature-name-value-no-unknown': importLazy(() => require('./media-feature-name-value-no-unknown'), )(), - 'media-query-no-invalid': importLazy(() => require('./media-query-no-invalid'))(), 'media-feature-parentheses-space-inside': importLazy(() => require('./media-feature-parentheses-space-inside'), )(), @@ -226,6 +225,7 @@ const rules = { 'media-query-list-comma-space-before': importLazy(() => require('./media-query-list-comma-space-before'), )(), + 'media-query-no-invalid': importLazy(() => require('./media-query-no-invalid'))(), 'named-grid-areas-no-invalid': importLazy(() => require('./named-grid-areas-no-invalid'))(), 'no-descending-specificity': importLazy(() => require('./no-descending-specificity'))(), 'no-duplicate-at-import-rules': importLazy(() => require('./no-duplicate-at-import-rules'))(), diff --git a/lib/rules/media-query-no-invalid/index.js b/lib/rules/media-query-no-invalid/index.js index df8c09e4b6..47a8f4c2ea 100644 --- a/lib/rules/media-query-no-invalid/index.js +++ b/lib/rules/media-query-no-invalid/index.js @@ -25,7 +25,7 @@ const messages = ruleMessages(ruleName, { const HAS_MIN_MAX_PREFIX = /^(?:min|max)-/i; const meta = { - url: 'https://stylelint.io/user-guide/rules/media-feature-no-invalid', + url: 'https://stylelint.io/user-guide/rules/media-query-no-invalid', }; /** @type {import('stylelint').Rule} */ From 64dc211f616bcbd352f5de1934b15bf151cda18f Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Sat, 24 Jun 2023 17:00:22 +0200 Subject: [PATCH 6/6] add more docs --- lib/rules/media-query-no-invalid/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/rules/media-query-no-invalid/README.md b/lib/rules/media-query-no-invalid/README.md index b679778fab..7e462c55c8 100644 --- a/lib/rules/media-query-no-invalid/README.md +++ b/lib/rules/media-query-no-invalid/README.md @@ -11,6 +11,13 @@ Disallow invalid media queries. Media queries must be grammatically valid according to the [Media Queries Level 5](https://www.w3.org/TR/mediaqueries-5/) specification. +This rule is only appropriate for CSS. You should not turn it on for CSS-like languages, such as Sass or Less, as they have their own syntaxes. + +It works well with other rules that validate feature names and values: + +- [`media-feature-name-no-unknown`](../media-feature-name-no-unknown/README.md) +- [`media-feature-name-value-no-unknown`](../media-feature-name-value-no-unknown/README.md) + The [`message` secondary option](../../../docs/user-guide/configure.md#message) can accept the arguments of this rule. ## Options