diff --git a/.changeset/tricky-radios-vanish.md b/.changeset/tricky-radios-vanish.md new file mode 100644 index 0000000000..0935148fba --- /dev/null +++ b/.changeset/tricky-radios-vanish.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: remove leading newline from `
` contents diff --git a/packages/svelte/src/compiler/phases/3-transform/utils.js b/packages/svelte/src/compiler/phases/3-transform/utils.js index b53a3110bd..62a635de35 100644 --- a/packages/svelte/src/compiler/phases/3-transform/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/utils.js @@ -5,6 +5,7 @@ import { regex_ends_with_whitespaces, regex_not_whitespace, + regex_starts_with_newline, regex_starts_with_whitespaces } from '../patterns.js'; import * as b from '../../utils/builders.js'; @@ -270,6 +271,22 @@ export function clean_nodes( var first = trimmed[0]; + // initial newline inside a `` is disregarded, if not followed by another newline + if (parent.type === 'RegularElement' && parent.name === 'pre' && first.type === 'Text') { + const text = first.data.replace(regex_starts_with_newline, ''); + if (text !== first.data) { + const tmp = text.replace(regex_starts_with_newline, ''); + if (text === tmp) { + first.data = text; + first.raw = first.raw.replace(regex_starts_with_newline, ''); + if (first.data === '') { + trimmed.shift(); + first = trimmed[0]; + } + } + } + } + // Special case: Add a comment if this is a lone script tag. This ensures that our run_scripts logic in template.js // will always be able to call node.replaceWith() on the script tag in order to make it run. If we don't add this // and would still call node.replaceWith() on the script tag, it would be a no-op because the script tag has no parent. diff --git a/packages/svelte/tests/hydration/samples/pre-first-node-newline/_config.js b/packages/svelte/tests/hydration/samples/pre-first-node-newline/_config.js new file mode 100644 index 0000000000..c838aab749 --- /dev/null +++ b/packages/svelte/tests/hydration/samples/pre-first-node-newline/_config.js @@ -0,0 +1,5 @@ +import { test } from '../../test'; + +// A note about _expected.html: It is different from body.html because we're +// testing against target.innerHTML which already removed the redundant first newline +export default test({}); diff --git a/packages/svelte/tests/hydration/samples/pre-first-node-newline/_expected.html b/packages/svelte/tests/hydration/samples/pre-first-node-newline/_expected.html new file mode 100644 index 0000000000..26de34d1ed --- /dev/null +++ b/packages/svelte/tests/hydration/samples/pre-first-node-newline/_expected.html @@ -0,0 +1,7 @@ +static content no linestatic content ignored line ++ static content relevant line +++diff --git a/packages/svelte/tests/hydration/samples/pre-first-node-newline/main.svelte b/packages/svelte/tests/hydration/samples/pre-first-node-newline/main.svelte new file mode 100644 index 0000000000..9764b49e99 --- /dev/null +++ b/packages/svelte/tests/hydration/samples/pre-first-node-newline/main.svelte @@ -0,0 +1,23 @@ + + ++static content no line+ ++ static content ignored line ++ ++ + static content relevant line ++ +++ +{name}++ +diff --git a/packages/svelte/tests/runtime-legacy/samples/pre-tag/_config.js b/packages/svelte/tests/runtime-legacy/samples/pre-tag/_config.js index f1a42e996a..d7e1fe9d43 100644 --- a/packages/svelte/tests/runtime-legacy/samples/pre-tag/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/pre-tag/_config.js @@ -2,17 +2,9 @@ import { test } from '../../test'; export default test({ mode: ['client', 'server'], // output is correct, but test suite chokes on the extra ssr comment which is harmless - withoutNormalizeHtml: true, - html: get_html(false), - ssrHtml: get_html(true) -}); - -/** @param {boolean} ssr */ -function get_html(ssr) { - // ssr rendered HTML has an extra newline prefixed within `{name}+` tag, - // if thetag starts with `\n` - // because when browser parses the SSR rendered HTML, it will ignore the 1st '\n' character - return `${ssr ? '' : ''}A + withoutNormalizeHtml: 'only-strip-comments', // because whitespace inside pre tags is significant + // Note how we're testing against target.innerHTML which already removed the redundant first newline + html: `` +});A B C @@ -35,5 +27,5 @@ function get_html(ssr) { leading newlines
without spaceswith spaces${' '} newline after leading space-multiple leading newlines${ssr ? '' : ''}`; -} +multiple leading newlines