From 95baabdd1c88dc68602edafa71f3a8c0083cc85e Mon Sep 17 00:00:00 2001 From: Tanuj Kanti Date: Thu, 7 May 2026 21:23:59 +0530 Subject: [PATCH 1/3] feat: replace fix with suggestion --- src/rules/no-duplicate-imports.js | 110 +++++++++++++++++++---- tests/rules/no-duplicate-imports.test.js | 48 ++++++++++ 2 files changed, 142 insertions(+), 16 deletions(-) diff --git a/src/rules/no-duplicate-imports.js b/src/rules/no-duplicate-imports.js index 0e1749a1..d7f8891b 100644 --- a/src/rules/no-duplicate-imports.js +++ b/src/rules/no-duplicate-imports.js @@ -9,10 +9,58 @@ /** * @import { CSSRuleDefinition } from "../types.js" - * @typedef {"duplicateImport"} NoDuplicateKeysMessageIds + * @typedef {"duplicateImport" | "removeDuplicateImportWithConditions" | "removeDuplicateImportWithoutConditions"} NoDuplicateKeysMessageIds * @typedef {CSSRuleDefinition<{ RuleOptions: [], MessageIds: NoDuplicateKeysMessageIds }>} NoDuplicateImportsRuleDefinition */ +//----------------------------------------------------------------------------- +// Helpers +//----------------------------------------------------------------------------- + +/** + * Get the end index of import statement including a following newline if present. + * @param {string} text The full text of the source code. + * @param {number} end The end index of the import statement. + * @returns {number} The end index of the import statement including a following newline. + */ +function getImportEnd(text, end) { + let removeEnd = end; + + // Remove the node, and also remove a following newline if present + if (text[removeEnd] === "\r") { + removeEnd += + text[removeEnd + 1] === "\n" ? 2 : 1; + } else if ( + text[removeEnd] === "\n" || + text[removeEnd] === "\f" + ) { + removeEnd += 1; + } + + return removeEnd; +} + +/** + * Get the conditions of an import statement. + * @param {Object} importNode The import node to get conditions from. + * @param {Object} sourceCode The source code object. + * @returns {string[]} An array of conditions for the import statement. + */ +function getImportConditions(importNode, sourceCode) { + const importConditions = []; + + const importHasConditions = importNode.prelude.children.length > 1; + + if (importHasConditions) { + importNode.prelude.children.slice(1).forEach(condition => { + const conditionText = sourceCode.getText(condition).trim(); + importConditions.push(conditionText); + }); + } + + return importConditions; +} + //----------------------------------------------------------------------------- // Rule //----------------------------------------------------------------------------- @@ -25,6 +73,7 @@ export default { type: "problem", fixable: "code", + hasSuggestions: true, docs: { description: "Disallow duplicate @import rules", @@ -34,6 +83,8 @@ export default { messages: { duplicateImport: "Unexpected duplicate @import rule for '{{url}}'.", + removeDuplicateImportWithConditions: "Remove duplicate @import rule with condition(s) - {{conditions}}.", + removeDuplicateImportWithoutConditions: "Remove duplicate @import rule without conditions.", }, }, @@ -44,32 +95,59 @@ export default { return { "Atrule[name=/^import$/i]"(node) { const url = node.prelude.children[0].value; + const hasImport = [...imports].some(importNode => importNode.prelude.children[0].value === url); + + if (hasImport) { + const firstImportNode = [...imports].find(importNode => importNode.prelude.children[0].value === url); + const [firstImportStart, firstImportEnd] = sourceCode.getRange(firstImportNode); + + const [start, end] = sourceCode.getRange(node); + const text = sourceCode.text; - if (imports.has(url)) { context.report({ loc: node.loc, messageId: "duplicateImport", data: { url }, fix(fixer) { - const [start, end] = sourceCode.getRange(node); - const text = sourceCode.text; - // Remove the node, and also remove a following newline if present - let removeEnd = end; - if (text[removeEnd] === "\r") { - removeEnd += - text[removeEnd + 1] === "\n" ? 2 : 1; - } else if ( - text[removeEnd] === "\n" || - text[removeEnd] === "\f" - ) { - removeEnd += 1; + const removeEnd = getImportEnd(text, end); + + if ((firstImportNode && firstImportNode.prelude.children.length === 1) && node.prelude.children.length === 1) { + return fixer.removeRange([start, removeEnd]); } - return fixer.removeRange([start, removeEnd]); + return null; }, + suggest: [ + { + messageId: getImportConditions(firstImportNode, sourceCode).length > 0 ? "removeDuplicateImportWithConditions" : "removeDuplicateImportWithoutConditions", + data: { conditions: getImportConditions(firstImportNode, sourceCode).join(", ") }, + fix(fixer) { + const removeEnd = getImportEnd(text, firstImportEnd); + + if ((firstImportNode && firstImportNode.prelude.children.length > 1) || node.prelude.children.length > 1) { + return fixer.removeRange([firstImportStart, removeEnd]); + } + + return null; + } + }, + { + messageId: getImportConditions(node, sourceCode).length > 0 ? "removeDuplicateImportWithConditions" : "removeDuplicateImportWithoutConditions", + data: { conditions: getImportConditions(node, sourceCode).join(", ") }, + fix(fixer) { + const removeEnd = getImportEnd(text, end); + + if ((firstImportNode && firstImportNode.prelude.children.length > 1) || node.prelude.children.length > 1) { + return fixer.removeRange([start, removeEnd]); + } + + return null; + } + }, + ], }); } else { - imports.add(url); + imports.add(node); } }, }; diff --git a/tests/rules/no-duplicate-imports.test.js b/tests/rules/no-duplicate-imports.test.js index 6b2bb3ce..91c9cee2 100644 --- a/tests/rules/no-duplicate-imports.test.js +++ b/tests/rules/no-duplicate-imports.test.js @@ -280,5 +280,53 @@ ruleTester.run("no-duplicate-imports", rule, { }, ], }, + { + code: "@import url('a.css') print;\n@import url('a.css');\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 22, + suggestions: [ + { + messageId: "removeDuplicateImportWithConditions", + data: { conditions: "print" }, + output: "@import url('a.css');\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithoutConditions", + output: "@import url('a.css') print;\n@import url('b.css');", + }, + ], + }, + ], + }, + { + code: "@import url('a.css');\n@import url('a.css') print;\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 28, + suggestions: [ + { + messageId: "removeDuplicateImportWithoutConditions", + output: "@import url('a.css') print;\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithConditions", + data: { conditions: "print" }, + output: "@import url('a.css');\n@import url('b.css');", + }, + ], + }, + ], + }, ], }); From 612e252fc337c33d8528e82a565535526a7c7012 Mon Sep 17 00:00:00 2001 From: Tanuj Kanti Date: Fri, 8 May 2026 18:44:59 +0530 Subject: [PATCH 2/3] update code and add more tests --- docs/rules/no-duplicate-imports.md | 16 +++- src/rules/no-duplicate-imports.js | 104 +++++++++++++++++------ tests/rules/no-duplicate-imports.test.js | 89 +++++++++++++++++++ 3 files changed, 182 insertions(+), 27 deletions(-) diff --git a/docs/rules/no-duplicate-imports.md b/docs/rules/no-duplicate-imports.md index 60b4174d..6ac14127 100644 --- a/docs/rules/no-duplicate-imports.md +++ b/docs/rules/no-duplicate-imports.md @@ -25,13 +25,23 @@ Examples of **incorrect** code: /* eslint css/no-duplicate-imports: "error" */ @import url(a.css); -@import "b.css"; -@import url("c.css"); +@import "b.css" print; +@import url("c.css") print, screen; /* duplicates */ @import "a.css"; @import url(b.css); -@import "c.css"; +@import "c.css" print; +``` + +Examples of **correct** code: + +```css +/* eslint css/no-duplicate-imports: "error" */ + +@import url(a.css); +@import "b.css"; +@import url("c.css") print; ``` ## When Not to Use It diff --git a/src/rules/no-duplicate-imports.js b/src/rules/no-duplicate-imports.js index d7f8891b..01611af4 100644 --- a/src/rules/no-duplicate-imports.js +++ b/src/rules/no-duplicate-imports.js @@ -28,12 +28,8 @@ function getImportEnd(text, end) { // Remove the node, and also remove a following newline if present if (text[removeEnd] === "\r") { - removeEnd += - text[removeEnd + 1] === "\n" ? 2 : 1; - } else if ( - text[removeEnd] === "\n" || - text[removeEnd] === "\f" - ) { + removeEnd += text[removeEnd + 1] === "\n" ? 2 : 1; + } else if (text[removeEnd] === "\n" || text[removeEnd] === "\f") { removeEnd += 1; } @@ -83,8 +79,10 @@ export default { messages: { duplicateImport: "Unexpected duplicate @import rule for '{{url}}'.", - removeDuplicateImportWithConditions: "Remove duplicate @import rule with condition(s) - {{conditions}}.", - removeDuplicateImportWithoutConditions: "Remove duplicate @import rule without conditions.", + removeDuplicateImportWithConditions: + "Remove duplicate @import rule with condition(s) - {{conditions}}.", + removeDuplicateImportWithoutConditions: + "Remove duplicate @import rule without conditions.", }, }, @@ -95,15 +93,42 @@ export default { return { "Atrule[name=/^import$/i]"(node) { const url = node.prelude.children[0].value; - const hasImport = [...imports].some(importNode => importNode.prelude.children[0].value === url); + const hasImport = [...imports].some( + importNode => importNode.prelude.children[0].value === url, + ); if (hasImport) { - const firstImportNode = [...imports].find(importNode => importNode.prelude.children[0].value === url); - const [firstImportStart, firstImportEnd] = sourceCode.getRange(firstImportNode); + const firstImportNode = [...imports].find( + importNode => + importNode.prelude.children[0].value === url, + ); + const [firstImportStart, firstImportEnd] = + sourceCode.getRange(firstImportNode); + + const firstImporthHasConditions = + firstImportNode.prelude.children.length > 1; + const nodeHasConditions = node.prelude.children.length > 1; const [start, end] = sourceCode.getRange(node); const text = sourceCode.text; + const firstImportConditions = getImportConditions( + firstImportNode, + sourceCode, + ); + const duplicateImportConditions = getImportConditions( + node, + sourceCode, + ); + + const hasSameConditions = + firstImportConditions.length === + duplicateImportConditions.length && + firstImportConditions.every( + (condition, index) => + condition === duplicateImportConditions[index], + ); + context.report({ loc: node.loc, messageId: "duplicateImport", @@ -111,7 +136,11 @@ export default { fix(fixer) { const removeEnd = getImportEnd(text, end); - if ((firstImportNode && firstImportNode.prelude.children.length === 1) && node.prelude.children.length === 1) { + if ( + (!firstImporthHasConditions && + !nodeHasConditions) || + hasSameConditions + ) { return fixer.removeRange([start, removeEnd]); } @@ -119,30 +148,57 @@ export default { }, suggest: [ { - messageId: getImportConditions(firstImportNode, sourceCode).length > 0 ? "removeDuplicateImportWithConditions" : "removeDuplicateImportWithoutConditions", - data: { conditions: getImportConditions(firstImportNode, sourceCode).join(", ") }, + messageId: firstImporthHasConditions + ? "removeDuplicateImportWithConditions" + : "removeDuplicateImportWithoutConditions", + data: { + conditions: + firstImportConditions.join(", "), + }, fix(fixer) { - const removeEnd = getImportEnd(text, firstImportEnd); - - if ((firstImportNode && firstImportNode.prelude.children.length > 1) || node.prelude.children.length > 1) { - return fixer.removeRange([firstImportStart, removeEnd]); + const removeEnd = getImportEnd( + text, + firstImportEnd, + ); + + if ( + (firstImporthHasConditions || + nodeHasConditions) && + !hasSameConditions + ) { + return fixer.removeRange([ + firstImportStart, + removeEnd, + ]); } return null; - } + }, }, { - messageId: getImportConditions(node, sourceCode).length > 0 ? "removeDuplicateImportWithConditions" : "removeDuplicateImportWithoutConditions", - data: { conditions: getImportConditions(node, sourceCode).join(", ") }, + messageId: nodeHasConditions + ? "removeDuplicateImportWithConditions" + : "removeDuplicateImportWithoutConditions", + data: { + conditions: + duplicateImportConditions.join(", "), + }, fix(fixer) { const removeEnd = getImportEnd(text, end); - if ((firstImportNode && firstImportNode.prelude.children.length > 1) || node.prelude.children.length > 1) { - return fixer.removeRange([start, removeEnd]); + if ( + (firstImporthHasConditions || + nodeHasConditions) && + !hasSameConditions + ) { + return fixer.removeRange([ + start, + removeEnd, + ]); } return null; - } + }, }, ], }); diff --git a/tests/rules/no-duplicate-imports.test.js b/tests/rules/no-duplicate-imports.test.js index 91c9cee2..d8c4b175 100644 --- a/tests/rules/no-duplicate-imports.test.js +++ b/tests/rules/no-duplicate-imports.test.js @@ -280,6 +280,20 @@ ruleTester.run("no-duplicate-imports", rule, { }, ], }, + { + code: "@import url('a.css') print;\n@import url('a.css') print;\n@import url('b.css');", + output: "@import url('a.css') print;\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 28, + }, + ], + }, { code: "@import url('a.css') print;\n@import url('a.css');\n@import url('b.css');", errors: [ @@ -328,5 +342,80 @@ ruleTester.run("no-duplicate-imports", rule, { }, ], }, + { + code: "@import url('a.css') print, screen;\n@import url('a.css');\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 22, + suggestions: [ + { + messageId: "removeDuplicateImportWithConditions", + data: { conditions: "print, screen" }, + output: "@import url('a.css');\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithoutConditions", + output: "@import url('a.css') print, screen;\n@import url('b.css');", + }, + ], + }, + ], + }, + { + code: "@import url('a.css');\n@import url('a.css') print, screen;\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 36, + suggestions: [ + { + messageId: "removeDuplicateImportWithoutConditions", + output: "@import url('a.css') print, screen;\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithConditions", + data: { conditions: "print, screen" }, + output: "@import url('a.css');\n@import url('b.css');", + }, + ], + }, + ], + }, + { + code: "@import url('a.css') print, screen;\n@import url('a.css') print, screen and (width > 800px);\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 56, + suggestions: [ + { + messageId: "removeDuplicateImportWithConditions", + data: { conditions: "print, screen" }, + output: "@import url('a.css') print, screen and (width > 800px);\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: "print, screen and (width > 800px)", + }, + output: "@import url('a.css') print, screen;\n@import url('b.css');", + }, + ], + }, + ], + }, ], }); From bed2a9065b521714702e38900e556feb15ad106b Mon Sep 17 00:00:00 2001 From: Tanuj Kanti Date: Thu, 14 May 2026 13:48:18 +0530 Subject: [PATCH 3/3] address suggestions add tests --- src/rules/no-duplicate-imports.js | 96 +++++---- tests/rules/no-duplicate-imports.test.js | 236 +++++++++++++++++++++++ 2 files changed, 290 insertions(+), 42 deletions(-) diff --git a/src/rules/no-duplicate-imports.js b/src/rules/no-duplicate-imports.js index 01611af4..095bf4e9 100644 --- a/src/rules/no-duplicate-imports.js +++ b/src/rules/no-duplicate-imports.js @@ -57,6 +57,25 @@ function getImportConditions(importNode, sourceCode) { return importConditions; } +/** + * Get the fix for a duplicate import statement. + * @param {Object} fixer The fixer object. + * @param {string} text The full text of the source code. + * @param {number} start The start index of the import statement to fix. + * @param {number} end The end index of the import statement to fix. + * @param {boolean} condition A boolean indicating whether the import statement has conditions that differ from the original import. + * @returns {Object|null} A fix object if a fix is applicable, or null if no fix should be applied. + */ +function getFixForImport(fixer, text, start, end, condition) { + const removeEnd = getImportEnd(text, end); + + if (condition) { + return fixer.removeRange([start, removeEnd]); + } + + return null; +} + //----------------------------------------------------------------------------- // Rule //----------------------------------------------------------------------------- @@ -88,17 +107,17 @@ export default { create(context) { const { sourceCode } = context; - const imports = new Set(); + const imports = []; return { "Atrule[name=/^import$/i]"(node) { const url = node.prelude.children[0].value; - const hasImport = [...imports].some( + const hasImport = imports.some( importNode => importNode.prelude.children[0].value === url, ); if (hasImport) { - const firstImportNode = [...imports].find( + const firstImportNode = imports.find( importNode => importNode.prelude.children[0].value === url, ); @@ -134,17 +153,18 @@ export default { messageId: "duplicateImport", data: { url }, fix(fixer) { - const removeEnd = getImportEnd(text, end); - - if ( + const condition = (!firstImporthHasConditions && !nodeHasConditions) || - hasSameConditions - ) { - return fixer.removeRange([start, removeEnd]); - } - - return null; + hasSameConditions; + + return getFixForImport( + fixer, + text, + start, + end, + condition, + ); }, suggest: [ { @@ -152,27 +172,21 @@ export default { ? "removeDuplicateImportWithConditions" : "removeDuplicateImportWithoutConditions", data: { - conditions: - firstImportConditions.join(", "), + conditions: firstImportConditions.join(" "), }, fix(fixer) { - const removeEnd = getImportEnd( + const condition = + (firstImporthHasConditions || + nodeHasConditions) && + !hasSameConditions; + + return getFixForImport( + fixer, text, + firstImportStart, firstImportEnd, + condition, ); - - if ( - (firstImporthHasConditions || - nodeHasConditions) && - !hasSameConditions - ) { - return fixer.removeRange([ - firstImportStart, - removeEnd, - ]); - } - - return null; }, }, { @@ -181,29 +195,27 @@ export default { : "removeDuplicateImportWithoutConditions", data: { conditions: - duplicateImportConditions.join(", "), + duplicateImportConditions.join(" "), }, fix(fixer) { - const removeEnd = getImportEnd(text, end); - - if ( + const condition = (firstImporthHasConditions || nodeHasConditions) && - !hasSameConditions - ) { - return fixer.removeRange([ - start, - removeEnd, - ]); - } - - return null; + !hasSameConditions; + + return getFixForImport( + fixer, + text, + start, + end, + condition, + ); }, }, ], }); } else { - imports.add(node); + imports.push(node); } }, }; diff --git a/tests/rules/no-duplicate-imports.test.js b/tests/rules/no-duplicate-imports.test.js index d8c4b175..df26d74f 100644 --- a/tests/rules/no-duplicate-imports.test.js +++ b/tests/rules/no-duplicate-imports.test.js @@ -294,6 +294,20 @@ ruleTester.run("no-duplicate-imports", rule, { }, ], }, + { + code: "@import 'a.css' print;\n@import url('a.css') print;\n@import url('b.css');", + output: "@import 'a.css' print;\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 28, + }, + ], + }, { code: "@import url('a.css') print;\n@import url('a.css');\n@import url('b.css');", errors: [ @@ -417,5 +431,227 @@ ruleTester.run("no-duplicate-imports", rule, { }, ], }, + { + code: "@import url('a.css') layer(foo);\n@import url('a.css') layer(foo);\n@import url('b.css');", + output: "@import url('a.css') layer(foo);\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 33, + }, + ], + }, + { + code: "@import url('a.css');\n@import url('a.css') layer(foo);\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 33, + suggestions: [ + { + messageId: "removeDuplicateImportWithoutConditions", + output: "@import url('a.css') layer(foo);\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: "layer(foo)", + }, + output: "@import url('a.css');\n@import url('b.css');", + }, + ], + }, + ], + }, + { + code: "@import url('a.css') layer(foo);\n@import url('a.css');\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 22, + suggestions: [ + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: "layer(foo)", + }, + output: "@import url('a.css');\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithoutConditions", + output: "@import url('a.css') layer(foo);\n@import url('b.css');", + }, + ], + }, + ], + }, + { + code: "@import url('a.css') layer;\n@import url('a.css') layer(foo);\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 33, + suggestions: [ + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: "layer", + }, + output: "@import url('a.css') layer(foo);\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: "layer(foo)", + }, + output: "@import url('a.css') layer;\n@import url('b.css');", + }, + ], + }, + ], + }, + { + code: "@import url('a.css') supports(display: grid);\n@import url('a.css') supports(display: grid);\n@import url('b.css');", + output: "@import url('a.css') supports(display: grid);\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 46, + }, + ], + }, + { + code: "@import url('a.css');\n@import url('a.css') supports(display: grid);\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 46, + suggestions: [ + { + messageId: "removeDuplicateImportWithoutConditions", + output: "@import url('a.css') supports(display: grid);\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: "supports(display: grid)", + }, + output: "@import url('a.css');\n@import url('b.css');", + }, + ], + }, + ], + }, + { + code: "@import url('a.css') supports(display: grid);\n@import url('a.css');\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 22, + suggestions: [ + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: "supports(display: grid)", + }, + output: "@import url('a.css');\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithoutConditions", + output: "@import url('a.css') supports(display: grid);\n@import url('b.css');", + }, + ], + }, + ], + }, + { + code: "@import url('a.css') layer(foo) supports(display: grid);\n@import url('a.css') layer(foo);\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 33, + suggestions: [ + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: + "layer(foo) supports(display: grid)", + }, + output: "@import url('a.css') layer(foo);\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: "layer(foo)", + }, + output: "@import url('a.css') layer(foo) supports(display: grid);\n@import url('b.css');", + }, + ], + }, + ], + }, + { + code: "@import url('a.css') layer(foo) supports(display: grid) screen and (width > 600px);\n@import url('a.css') layer(foo) supports(display: grid);\n@import url('b.css');", + errors: [ + { + messageId: "duplicateImport", + data: { url: "a.css" }, + line: 2, + column: 1, + endLine: 2, + endColumn: 57, + suggestions: [ + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: + "layer(foo) supports(display: grid) screen and (width > 600px)", + }, + output: "@import url('a.css') layer(foo) supports(display: grid);\n@import url('b.css');", + }, + { + messageId: "removeDuplicateImportWithConditions", + data: { + conditions: + "layer(foo) supports(display: grid)", + }, + output: "@import url('a.css') layer(foo) supports(display: grid) screen and (width > 600px);\n@import url('b.css');", + }, + ], + }, + ], + }, ], });