Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix keyframe-selector-notation false positives for named timeline range #6605

Merged
merged 7 commits into from Feb 4, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/spotty-baboons-train.md
@@ -0,0 +1,5 @@
---
"stylelint": patch
---

Fixed: `keyframe-selector-notation` false positives for named timeline ranges
60 changes: 60 additions & 0 deletions lib/rules/keyframe-selector-notation/__tests__/index.js
Expand Up @@ -29,6 +29,26 @@ testRule({
code: '@keyframes foo { from, to {} }',
description: 'selector lists',
},
{
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',
},
],

reject: [
Expand Down Expand Up @@ -166,6 +186,26 @@ testRule({
code: '@keyframes foo { 0%, 100% {} }',
description: 'selector lists',
},
{
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',
},
],

reject: [
Expand Down Expand Up @@ -301,6 +341,26 @@ testRule({
{
code: '@keyframes foo { from,to {} }',
},
{
Mouvedia marked this conversation as resolved.
Show resolved Hide resolved
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',
},
],

reject: [
Expand Down
22 changes: 22 additions & 0 deletions lib/rules/keyframe-selector-notation/index.js
Expand Up @@ -19,6 +19,7 @@ const meta = {

const PERCENTAGE_SELECTORS = new Set(['0%', '100%']);
const KEYWORD_SELECTORS = new Set(['from', 'to']);
const NAMED_TIMELINE_RABGE_SELECTORS = new Set(['cover', 'contain', 'entry', 'enter', 'exit']);
Mouvedia marked this conversation as resolved.
Show resolved Hide resolved
const PERCENTAGE_TO_KEYWORD = new Map([
['0%', 'from'],
['100%', 'to'],
Expand Down Expand Up @@ -73,6 +74,10 @@ const rule = (primary, _, context) => {

atRuleKeyframes.walkRules((keyframeRule) => {
transformSelector(result, keyframeRule, (selectors) => {
if (isNamedTimelineRange(selectors)) {
return;
}

ybiquitous marked this conversation as resolved.
Show resolved Hide resolved
selectors.walkTags((selectorTag) => {
checkSelector(
selectorTag.value,
Expand Down Expand Up @@ -148,6 +153,23 @@ function getSelectorsInBlock(atRule) {
return selectors;
}

/**
* @param {import('postcss-selector-parser').Root} selectors
* @returns boolean
*/
function isNamedTimelineRange(selectors) {
for (const selectorNode of Array.from(selectors.nodes)) {
const firstTagNode = selectorNode.nodes.filter((node) => node.type === 'tag')[0];
Mouvedia marked this conversation as resolved.
Show resolved Hide resolved
const firstTagValue = firstTagNode && firstTagNode.value ? firstTagNode.value : '';

if (firstTagValue && NAMED_TIMELINE_RABGE_SELECTORS.has(firstTagValue)) {
return true;
}
}

return false;
}

rule.ruleName = ruleName;
rule.messages = messages;
rule.meta = meta;
Expand Down