diff --git a/packages/svelte/src/compiler/phases/3-transform/utils.js b/packages/svelte/src/compiler/phases/3-transform/utils.js index 9360b5122fcd..62a635de3536 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,19 +271,19 @@ export function clean_nodes( var first = trimmed[0]; - // initial newline inside a `
` is disregarded
-	if (
-		parent.type === 'RegularElement' &&
-		parent.name === 'pre' &&
-		first.type === 'Text' &&
-		first.data[0] === '\n'
-	) {
-		first.data = first.data.slice(1);
-		first.raw = first.raw.slice(1);
-
-		if (first.data === '') {
-			trimmed.shift();
-			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];
+				}
+			}
 		}
 	}
 
diff --git a/packages/svelte/tests/hydration/samples/pre-first-node-backslash-n/_config.js b/packages/svelte/tests/hydration/samples/pre-first-node-backslash-n/_config.js
deleted file mode 100644
index f47bee71df87..000000000000
--- a/packages/svelte/tests/hydration/samples/pre-first-node-backslash-n/_config.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import { test } from '../../test';
-
-export default test({});
diff --git a/packages/svelte/tests/hydration/samples/pre-first-node-backslash-n/_expected.html b/packages/svelte/tests/hydration/samples/pre-first-node-backslash-n/_expected.html
deleted file mode 100644
index b2e80650314e..000000000000
--- a/packages/svelte/tests/hydration/samples/pre-first-node-backslash-n/_expected.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file diff --git a/packages/svelte/tests/hydration/samples/pre-first-node-backslash-n/main.svelte b/packages/svelte/tests/hydration/samples/pre-first-node-backslash-n/main.svelte deleted file mode 100644 index abd29eed72d9..000000000000 --- a/packages/svelte/tests/hydration/samples/pre-first-node-backslash-n/main.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - -
-
{name}
-
\ No newline at end of file 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 000000000000..c838aab749cd --- /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 000000000000..26de34d1ed27 --- /dev/null +++ b/packages/svelte/tests/hydration/samples/pre-first-node-newline/_expected.html @@ -0,0 +1,7 @@ +
static content no line
	static 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 000000000000..9764b49e99d1 --- /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}
+
+ +
+
+
{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 194499bd5be8..d7e1fe9d43a3 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 `
` tag,
-	// if the 
 tag 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
@@ -31,7 +23,9 @@ function get_html(ssr) {
     
     E
     F
-  
leading newline
  leading newline and spaces
leading newlines
without spaces
  with spaces  
${' '}
+  
leading newline
  leading newline and spaces
+leading newlines
without spaces
  with spaces  
${' '}
 newline after leading space
-multiple leading newlines
${ssr ? '' : ''}`; -} + +multiple leading newlines
` +});