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 5b40867aab70..ce682edd528d 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -196,12 +196,13 @@ const visitors = { SelectorList(node, { state, next, path }) { // 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)) { + const children = node.children; let pruning = false; - let prune_start = node.children[0].start; + let prune_start = children[0].start; let last = prune_start; - for (let i = 0; i < node.children.length; i += 1) { - const selector = node.children[i]; + for (let i = 0; i < children.length; i += 1) { + const selector = children[i]; if (selector.metadata.used === pruning) { if (pruning) { @@ -221,10 +222,17 @@ 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) { + while (state.code.original[prune_start - 1] !== ',') prune_start++; + state.code.update(last, prune_start, separator); + } } else { - state.code.overwrite(last, selector.start, ' /* (unused) '); + 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 @@ +
p
+ + 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 @@ -