diff --git a/.changeset/spotty-baboons-train.md b/.changeset/spotty-baboons-train.md new file mode 100644 index 0000000000..870126130d --- /dev/null +++ b/.changeset/spotty-baboons-train.md @@ -0,0 +1,5 @@ +--- +"stylelint": patch +--- + +Fixed: `keyframe-selector-notation` false positives for named timeline ranges diff --git a/lib/rules/keyframe-selector-notation/__tests__/index.js b/lib/rules/keyframe-selector-notation/__tests__/index.js index 7b5e73a2c3..1066dd5fbc 100644 --- a/lib/rules/keyframe-selector-notation/__tests__/index.js +++ b/lib/rules/keyframe-selector-notation/__tests__/index.js @@ -2,6 +2,29 @@ const { messages, ruleName } = require('..'); +const ACCEPT_TIMELINE_RANGE_NAME_TEST_CASES = [ + { + code: '@keyframes foo { cover 0% {} cover 100% {} }', + description: 'timeline-range-name cover', + }, + { + code: '@keyframes foo { contain 0% {} contain 100% {} }', + description: 'timeline-range-name contain', + }, + { + code: '@keyframes foo { entry 0% {} entry 100% {} }', + description: 'timeline-range-name entry', + }, + { + code: '@keyframes foo { enter 0% {} enter 100% {} }', + description: 'timeline-range-name enter', + }, + { + code: '@keyframes foo { exit 0% {} exit 100% {} }', + description: 'timeline-range-name exit', + }, +]; + testRule({ ruleName, config: ['keyword'], @@ -29,6 +52,7 @@ testRule({ code: '@keyframes foo { from, to {} }', description: 'selector lists', }, + ...ACCEPT_TIMELINE_RANGE_NAME_TEST_CASES, ], reject: [ @@ -166,6 +190,7 @@ testRule({ code: '@keyframes foo { 0%, 100% {} }', description: 'selector lists', }, + ...ACCEPT_TIMELINE_RANGE_NAME_TEST_CASES, ], reject: [ @@ -301,6 +326,7 @@ testRule({ { code: '@keyframes foo { from,to {} }', }, + ...ACCEPT_TIMELINE_RANGE_NAME_TEST_CASES, ], reject: [ diff --git a/lib/rules/keyframe-selector-notation/index.js b/lib/rules/keyframe-selector-notation/index.js index b83301935c..9854e40eec 100644 --- a/lib/rules/keyframe-selector-notation/index.js +++ b/lib/rules/keyframe-selector-notation/index.js @@ -19,6 +19,7 @@ const meta = { const PERCENTAGE_SELECTORS = new Set(['0%', '100%']); const KEYWORD_SELECTORS = new Set(['from', 'to']); +const NAMED_TIMELINE_RANGE_SELECTORS = new Set(['cover', 'contain', 'entry', 'enter', 'exit']); const PERCENTAGE_TO_KEYWORD = new Map([ ['0%', 'from'], ['100%', 'to'], @@ -73,7 +74,15 @@ const rule = (primary, _, context) => { atRuleKeyframes.walkRules((keyframeRule) => { transformSelector(result, keyframeRule, (selectors) => { + let first = true; + selectors.walkTags((selectorTag) => { + if (first && NAMED_TIMELINE_RANGE_SELECTORS.has(selectorTag.value)) { + return false; + } + + first = false; + checkSelector( selectorTag.value, optionFuncs[primary],