From d0b26a4dcebda882b195b0699a065dc59f9278c2 Mon Sep 17 00:00:00 2001 From: KumJungMin <37934668+KumJungMin@users.noreply.github.com> Date: Sat, 19 Sep 2026 22:43:48 +0900 Subject: [PATCH 1/2] feat: preserve keyframe selector casing in error messages --- src/rules/no-duplicate-keyframe-selectors.js | 8 ++++++-- tests/rules/no-duplicate-keyframe-selectors.test.js | 12 ++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/rules/no-duplicate-keyframe-selectors.js b/src/rules/no-duplicate-keyframe-selectors.js index a51ff808..778dee03 100644 --- a/src/rules/no-duplicate-keyframe-selectors.js +++ b/src/rules/no-duplicate-keyframe-selectors.js @@ -66,16 +66,20 @@ export default /** @satisfies {DuplicateKeyframeSelectorRuleDefinition} */ ({ // @ts-ignore - children is a valid property for prelude node.prelude.children.forEach(selector => { const value = []; + const rawValue = []; selector.children.forEach(component => { if (component.type === "Percentage") { - value.push(`${component.value}%`); + const percentage = `${component.value}%`; + value.push(percentage); + rawValue.push(percentage); } else if (component.type === "TypeSelector") { value.push(component.name.toLowerCase()); + rawValue.push(component.name); } }); - const selectorValue = value.join(" "); + const selectorValue = rawValue.join(" "); const key = value .map( selectorPart => diff --git a/tests/rules/no-duplicate-keyframe-selectors.test.js b/tests/rules/no-duplicate-keyframe-selectors.test.js index 272b1a6e..1dcd93e1 100644 --- a/tests/rules/no-duplicate-keyframe-selectors.test.js +++ b/tests/rules/no-duplicate-keyframe-selectors.test.js @@ -215,7 +215,7 @@ ruleTester.run("no-duplicate-keyframe-selectors", rule, { errors: [ { messageId: "duplicateKeyframeSelector", - data: { selector: "from" }, + data: { selector: "From" }, line: 3, column: 5, endLine: 3, @@ -231,7 +231,7 @@ ruleTester.run("no-duplicate-keyframe-selectors", rule, { errors: [ { messageId: "duplicateKeyframeSelector", - data: { selector: "from" }, + data: { selector: "FROM" }, line: 3, column: 5, endLine: 3, @@ -265,7 +265,7 @@ ruleTester.run("no-duplicate-keyframe-selectors", rule, { errors: [ { messageId: "duplicateKeyframeSelector", - data: { selector: "to" }, + data: { selector: "TO" }, line: 4, column: 5, endLine: 4, @@ -624,7 +624,7 @@ ruleTester.run("no-duplicate-keyframe-selectors", rule, { errors: [ { messageId: "duplicateKeyframeSelector", - data: { selector: "entry 0%" }, + data: { selector: "Entry 0%" }, line: 2, column: 15, endLine: 2, @@ -742,7 +742,7 @@ ruleTester.run("no-duplicate-keyframe-selectors", rule, { errors: [ { messageId: "duplicateKeyframeSelector", - data: { selector: "from" }, + data: { selector: "From" }, line: 3, column: 5, endLine: 3, @@ -750,7 +750,7 @@ ruleTester.run("no-duplicate-keyframe-selectors", rule, { }, { messageId: "duplicateKeyframeSelector", - data: { selector: "to" }, + data: { selector: "TO" }, line: 5, column: 5, endLine: 5, From 963d3dcbe0d87cbcd7a7cdbb773a77aeb9bf0f11 Mon Sep 17 00:00:00 2001 From: KumJungMin <37934668+KumJungMin@users.noreply.github.com> Date: Mon, 21 Sep 2026 08:14:08 +0900 Subject: [PATCH 2/2] refactor: lowercase keyframe selectors when computing comparison keys --- src/rules/no-duplicate-keyframe-selectors.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/rules/no-duplicate-keyframe-selectors.js b/src/rules/no-duplicate-keyframe-selectors.js index 778dee03..fd0ba11e 100644 --- a/src/rules/no-duplicate-keyframe-selectors.js +++ b/src/rules/no-duplicate-keyframe-selectors.js @@ -66,26 +66,21 @@ export default /** @satisfies {DuplicateKeyframeSelectorRuleDefinition} */ ({ // @ts-ignore - children is a valid property for prelude node.prelude.children.forEach(selector => { const value = []; - const rawValue = []; selector.children.forEach(component => { if (component.type === "Percentage") { - const percentage = `${component.value}%`; - value.push(percentage); - rawValue.push(percentage); + value.push(`${component.value}%`); } else if (component.type === "TypeSelector") { - value.push(component.name.toLowerCase()); - rawValue.push(component.name); + value.push(component.name); } }); - const selectorValue = rawValue.join(" "); + const selectorValue = value.join(" "); const key = value - .map( - selectorPart => - keyframeSelectorAliases.get(selectorPart) ?? - selectorPart, - ) + .map(selectorPart => { + const part = selectorPart.toLowerCase(); + return keyframeSelectorAliases.get(part) ?? part; + }) .join(" "); if (seen.has(key)) {