From 3ed9db4ba78f61792b875b7651755a9c0a018037 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 12 Aug 2026 17:40:28 +0200 Subject: [PATCH] fix: don't duplicate comments in attributes (#18636) An attribute with a comment would be printed again atop the following attribute because we didn't take that case into account. --- .changeset/modern-otters-pick.md | 5 +++++ packages/svelte/src/compiler/print/index.js | 18 ++++++++++++------ .../comment-inside-attribute/input.svelte | 7 +++++++ .../comment-inside-attribute/output.svelte | 7 +++++++ 4 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 .changeset/modern-otters-pick.md create mode 100644 packages/svelte/tests/print/samples/comment-inside-attribute/input.svelte create mode 100644 packages/svelte/tests/print/samples/comment-inside-attribute/output.svelte diff --git a/.changeset/modern-otters-pick.md b/.changeset/modern-otters-pick.md new file mode 100644 index 0000000000..de5803e19f --- /dev/null +++ b/.changeset/modern-otters-pick.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: don't duplicate comments in attributes diff --git a/packages/svelte/src/compiler/print/index.js b/packages/svelte/src/compiler/print/index.js index a5fbc96fc8..fe76f31ad3 100644 --- a/packages/svelte/src/compiler/print/index.js +++ b/packages/svelte/src/compiler/print/index.js @@ -82,6 +82,7 @@ function attributes(node, attributes, context, comments) { } const separator = context.new(); + let previous_attribute_end = node.start; const children = attributes.map((attribute) => { const child_context = context.new(); @@ -90,12 +91,16 @@ function attributes(node, attributes, context, comments) { const comment = comments[comment_index]; if (comment.start < attribute.start) { - if (comment.type === 'Line') { - child_context.write('//' + comment.value); - child_context.newline(); - } else { - child_context.write('/*' + comment.value + '*/'); // TODO match indentation? - child_context.append(separator); + // Inside a previous attribute's value can be comments which don't + // advance comment_index, therefore this additional check + if (comment.start >= previous_attribute_end) { + if (comment.type === 'Line') { + child_context.write('//' + comment.value); + child_context.newline(); + } else { + child_context.write('/*' + comment.value + '*/'); // TODO match indentation? + child_context.append(separator); + } } comment_index += 1; @@ -105,6 +110,7 @@ function attributes(node, attributes, context, comments) { } child_context.visit(attribute); + previous_attribute_end = attribute.end; length += child_context.measure() + 1; diff --git a/packages/svelte/tests/print/samples/comment-inside-attribute/input.svelte b/packages/svelte/tests/print/samples/comment-inside-attribute/input.svelte new file mode 100644 index 0000000000..4575abf75a --- /dev/null +++ b/packages/svelte/tests/print/samples/comment-inside-attribute/input.svelte @@ -0,0 +1,7 @@ +