From b0dbc8f2c8576d0b1cb559a34a5eb746ea22f584 Mon Sep 17 00:00:00 2001 From: navorite Date: Sat, 26 Oct 2024 17:07:52 +0300 Subject: [PATCH 1/8] fix: preserve the separator between selectors when an unused selector is in between --- .changeset/eighty-icons-fold.md | 5 +++++ .../compiler/phases/3-transform/css/index.js | 14 +++++++++---- .../unused-selector-in-between/_config.js | 20 +++++++++++++++++++ .../unused-selector-in-between/expected.css | 7 +++++++ .../unused-selector-in-between/input.svelte | 14 +++++++++++++ 5 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 .changeset/eighty-icons-fold.md create mode 100644 packages/svelte/tests/css/samples/unused-selector-in-between/_config.js create mode 100644 packages/svelte/tests/css/samples/unused-selector-in-between/expected.css create mode 100644 packages/svelte/tests/css/samples/unused-selector-in-between/input.svelte diff --git a/.changeset/eighty-icons-fold.md b/.changeset/eighty-icons-fold.md new file mode 100644 index 000000000000..2d8f0d57bf53 --- /dev/null +++ b/.changeset/eighty-icons-fold.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: preserve the separator between selectors when an unused selector is in between diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index decdb21ad716..4c865ff96db7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -162,10 +162,13 @@ const visitors = { // Only add comments if we're not inside a complex selector that itself is unused if (!path.find((n) => n.type === 'ComplexSelector' && !n.metadata.used)) { let pruning = false; - let last = node.children[0].start; - for (let i = 0; i < node.children.length; i += 1) { - const selector = node.children[i]; + const children = node.children; + + let last = children.start; + + for (let i = 0; i < children.length; i += 1) { + const selector = children[i]; if (selector.metadata.used === pruning) { if (pruning) { @@ -177,7 +180,10 @@ const visitors = { if (i === 0) { state.code.prependRight(selector.start, '/* (unused) '); } else { - state.code.overwrite(last, selector.start, ' /* (unused) '); + // If this is not the last selector add a separator + const separator = i !== children.length - 1 ? ',' : ''; + + state.code.overwrite(last, selector.start, `${separator} /* (unused) `); } } diff --git a/packages/svelte/tests/css/samples/unused-selector-in-between/_config.js b/packages/svelte/tests/css/samples/unused-selector-in-between/_config.js new file mode 100644 index 000000000000..43747eb0c10f --- /dev/null +++ b/packages/svelte/tests/css/samples/unused-selector-in-between/_config.js @@ -0,0 +1,20 @@ +import { test } from '../../test'; + +export default test({ + warnings: [ + { + code: 'css_unused_selector', + end: { + character: 72, + column: 3, + line: 10 + }, + message: 'Unused CSS selector "h4"', + start: { + character: 70, + column: 1, + line: 10 + } + } + ] +}); diff --git a/packages/svelte/tests/css/samples/unused-selector-in-between/expected.css b/packages/svelte/tests/css/samples/unused-selector-in-between/expected.css new file mode 100644 index 000000000000..5a93aa53b7bc --- /dev/null +++ b/packages/svelte/tests/css/samples/unused-selector-in-between/expected.css @@ -0,0 +1,7 @@ + + h1.svelte-xyz, + h2.svelte-xyz, + h3.svelte-xyz, /* (unused) h4*/ + p.svelte-xyz { + color: red; + } diff --git a/packages/svelte/tests/css/samples/unused-selector-in-between/input.svelte b/packages/svelte/tests/css/samples/unused-selector-in-between/input.svelte new file mode 100644 index 000000000000..c1e149ba76d8 --- /dev/null +++ b/packages/svelte/tests/css/samples/unused-selector-in-between/input.svelte @@ -0,0 +1,14 @@ +

h1

+

h2

+

h3

+

p

+ + From 0074b02daf8524824eab7133f05bed3eca19085a Mon Sep 17 00:00:00 2001 From: navorite Date: Sat, 26 Oct 2024 17:09:08 +0300 Subject: [PATCH 2/8] err --- packages/svelte/src/compiler/phases/3-transform/css/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index 4c865ff96db7..ecec335f4d1b 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -165,7 +165,7 @@ const visitors = { const children = node.children; - let last = children.start; + let last = children[0].start; for (let i = 0; i < children.length; i += 1) { const selector = children[i]; From a4e9d3b24285ad39499055f9847610030193dd18 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:54:52 +0100 Subject: [PATCH 3/8] Update packages/svelte/src/compiler/phases/3-transform/css/index.js --- packages/svelte/src/compiler/phases/3-transform/css/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index a9c71d5c0fc8..57170d6e1b24 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -208,8 +208,8 @@ const visitors = { if (pruning) { let i = selector.start; while (state.code.original[i] !== ',') i--; - // If this is not the last selector keep the separator - if (i !== children.length - 1) i++; + // If this is an in-between pruned selector keep the last separator + if (prune_start !== children[0].start && i !== children.length - 1) i--; if (state.minify) { state.code.remove(prune_start, i + 1); From c10f37d21182319994e1ded4cde0a878d27eb522 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:03:52 +0100 Subject: [PATCH 4/8] Update index.js --- .../src/compiler/phases/3-transform/css/index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index 57170d6e1b24..b2be607a10f0 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -206,15 +206,15 @@ const visitors = { if (selector.metadata.used === pruning) { if (pruning) { - let i = selector.start; - while (state.code.original[i] !== ',') i--; + let end = selector.start; + while (state.code.original[end - 1] !== ',') end--; // If this is an in-between pruned selector keep the last separator - if (prune_start !== children[0].start && i !== children.length - 1) i--; + if (prune_start !== children[0].start && i !== children.length - 1) end--; if (state.minify) { - state.code.remove(prune_start, i + 1); + state.code.remove(prune_start, end); } else { - state.code.overwrite(i, i + 1, '*/'); + state.code.overwrite(i, end, '*/'); } } else { if (i === 0) { From 38ee291dcee5889f51fda29955217990711d3b29 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:05:12 +0100 Subject: [PATCH 5/8] Update packages/svelte/src/compiler/phases/3-transform/css/index.js --- packages/svelte/src/compiler/phases/3-transform/css/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index b2be607a10f0..9fa74ef2b347 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -214,7 +214,7 @@ const visitors = { if (state.minify) { state.code.remove(prune_start, end); } else { - state.code.overwrite(i, end, '*/'); + state.code.overwrite(end - 1, end, '*/'); } } else { if (i === 0) { From 2d031534a817e0fc5d2e38c95c556aaa4aaaabc6 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:18:33 +0100 Subject: [PATCH 6/8] Update index.js --- .../src/compiler/phases/3-transform/css/index.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index 9fa74ef2b347..bb357606bca9 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -206,15 +206,13 @@ const visitors = { if (selector.metadata.used === pruning) { if (pruning) { - let end = selector.start; - while (state.code.original[end - 1] !== ',') end--; - // If this is an in-between pruned selector keep the last separator - if (prune_start !== children[0].start && i !== children.length - 1) end--; + let i = selector.start; + while (state.code.original[i] !== ',') i--; if (state.minify) { - state.code.remove(prune_start, end); + state.code.remove(prune_start, i + 1); } else { - state.code.overwrite(end - 1, end, '*/'); + state.code.overwrite(i, i + 1, '*/'); } } else { if (i === 0) { @@ -224,10 +222,14 @@ const visitors = { state.code.prependRight(selector.start, '/* (unused) '); } } else { + // If this is not the last selector add a separator + const separator = i !== children.length - 1 ? ',' : ''; + if (state.minify) { prune_start = last; + if (separator) state.code.appendLeft(last, separator); } else { - state.code.overwrite(last, selector.start, ' /* (unused) '); + state.code.overwrite(last, selector.start, `${separator} /* (unused) `); } } } From 6a46c262f526ffbae08add3155f773690c736c5f Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:25:30 +0100 Subject: [PATCH 7/8] Update index.js --- packages/svelte/src/compiler/phases/3-transform/css/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index bb357606bca9..ce682edd528d 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -227,7 +227,10 @@ const visitors = { if (state.minify) { prune_start = last; - if (separator) state.code.appendLeft(last, separator); + if (separator) { + while (state.code.original[prune_start - 1] !== ',') prune_start++; + state.code.update(last, prune_start, separator); + } } else { state.code.overwrite(last, selector.start, `${separator} /* (unused) `); } From 392ba82a84c30cc7c14821f888ca858262838e24 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:27:40 +0100 Subject: [PATCH 8/8] add test for minifier --- .../samples/css-injected-options-minify/_expected.html | 2 +- .../samples/css-injected-options-minify/_expected_head.html | 2 +- .../samples/css-injected-options-minify/main.svelte | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/_expected.html b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/_expected.html index caa872be9bd9..60e974bd1af3 100644 --- a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/_expected.html +++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/_expected.html @@ -1 +1 @@ -
foo
\ No newline at end of file +
foo
\ No newline at end of file diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/_expected_head.html b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/_expected_head.html index 8d6e42d979e1..5350e77a49a7 100644 --- a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/_expected_head.html +++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/_expected_head.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/main.svelte b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/main.svelte index 13e01788e25f..6d9ecba8dfb2 100644 --- a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/main.svelte +++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-minify/main.svelte @@ -20,4 +20,10 @@ .foo, .unused { color: green; } + .unused, .foo { + color: green; + } + .foo, .unused, .foo { + color: green; + }