fix: `print()` multiline behaviour (#17319)

* way cleaner new line handling for base_elements

* fix

* more fixes

* use esrap preview

* changeset

* bump `esrap`

* update snapshot

* update more snapshots

* Update .changeset/rich-zoos-walk.md

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/17588/head
Manuel 6 months ago committed by GitHub
parent 9d1dd2e199
commit 82fde88780
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: properly separate multiline html blocks from each other in `print()`

@ -176,7 +176,7 @@
"clsx": "^2.1.1",
"devalue": "^5.6.2",
"esm-env": "^1.2.1",
"esrap": "^2.2.1",
"esrap": "^2.2.2",
"is-reference": "^3.0.3",
"locate-character": "^3.0.0",
"magic-string": "^0.30.11",

@ -115,57 +115,17 @@ function base_element(node, context) {
const is_doctype_node = node.name.toLowerCase() === '!doctype';
const is_self_closing =
is_void(node.name) || (node.type === 'Component' && node.fragment.nodes.length === 0);
let multiline_content = false;
if (is_doctype_node) child_context.write(`>`);
else if (is_self_closing) {
child_context.write(`${multiline_attributes ? '' : ' '}/>`);
} else {
child_context.write('>');
// Process the element's content in a separate context for measurement
const content_context = child_context.new();
const allow_inline_content = child_context.measure() < LINE_BREAK_THRESHOLD;
block(content_context, node.fragment, allow_inline_content);
// Determine if content should be formatted on multiple lines
multiline_content = content_context.measure() > LINE_BREAK_THRESHOLD;
if (multiline_content) {
child_context.newline();
// Only indent if attributes are inline and content itself isn't already multiline
const should_indent = !multiline_attributes && !content_context.multiline;
if (should_indent) {
child_context.indent();
}
child_context.append(content_context);
if (should_indent) {
child_context.dedent();
}
child_context.newline();
} else {
child_context.append(content_context);
}
block(child_context, node.fragment, true);
child_context.write(`</${node.name}>`);
}
const break_line_after = child_context.measure() > LINE_BREAK_THRESHOLD;
if ((multiline_content || multiline_attributes) && !context.empty()) {
context.newline();
}
context.append(child_context);
if (is_self_closing) return;
if (multiline_content || multiline_attributes || break_line_after) {
context.newline();
}
}
/** @type {Visitors<AST.SvelteNode>} */
@ -412,6 +372,8 @@ const svelte_visitors = {
}
} else {
sequence.push(child_node);
if (child_node.type === 'RegularElement') flush();
}
}
@ -420,18 +382,20 @@ const svelte_visitors = {
let multiline = false;
let width = 0;
const child_contexts = items.map((sequence) => {
const child_context = context.new();
const child_contexts = items
.filter((x) => x.length > 0)
.map((sequence) => {
const child_context = context.new();
for (const node of sequence) {
child_context.visit(node);
multiline ||= child_context.multiline;
}
for (const node of sequence) {
child_context.visit(node);
multiline ||= child_context.multiline;
}
width += child_context.measure();
width += child_context.measure();
return child_context;
});
return child_context;
});
multiline ||= width > LINE_BREAK_THRESHOLD;

@ -4,4 +4,4 @@
</script>
<Component>
<slot name="derived" slot="derived" />
</Component>
</Component>

@ -3,4 +3,4 @@
let body;
</script>
<slot name="body"></slot>
<slot name="body"></slot>

@ -1,2 +1,2 @@
<!-- @migration-task Error while migrating Svelte code: This migration would change the name of a slot (dashed-name to dashed_name) making the component unusable -->
<slot name="dashed-name"></slot>
<slot name="dashed-name"></slot>

@ -1 +1,8 @@
<script>import { setLocale } from '$lib/paraglide/runtime';import { m } from '$lib/paraglide/messages.js';</script><h1>{m.hello_world({ name: 'SvelteKit User' })}</h1><div><button onclick={() => setLocale('en')}>en</button><button onclick={() => setLocale('es')}>es</button></div><p>If you use VSCode, install the <a href="https://marketplace.visualstudio.com/items?itemName=inlang.vs-code-extension" target="_blank">Sherlock i18n extension</a>for a better i18n experience.</p>
<script>import { setLocale } from '$lib/paraglide/runtime';import { m } from '$lib/paraglide/messages.js';</script>
<h1>{m.hello_world({ name: 'SvelteKit User' })}</h1><div><button onclick={() => setLocale('en')}>en</button><button onclick={() => setLocale('es')}>es</button></div><p>If you use VSCode, install the <a href="https://marketplace.visualstudio.com/items?itemName=inlang.vs-code-extension" target="_blank">Sherlock i18n extension</a>for a better i18n experience.</p>
<Component><div><button>Hello, this is a test</button><button>Hello, this is a test</button></div></Component>
<Component><button>Hello, this is a test</button><button>Hello, this is a test</button></Component>
<button class="foo bar" aria-label="click" onclick={() => console.log("clicked")}>Click me!</button>
<button class="foo bar" aria-label="click" onclick={() => console.log("clicked")}><span>some fancy looking</span><span>really long button text</span></button>

@ -4,18 +4,46 @@
</script>
<h1>{m.hello_world({ name: 'SvelteKit User' })}</h1>
<div>
<button onclick={() => setLocale('en')}>en</button>
<button onclick={() => setLocale('es')}>es</button>
</div>
<p>
If you use VSCode, install the
<a
href="https://marketplace.visualstudio.com/items?itemName=inlang.vs-code-extension"
target="_blank"
>
Sherlock i18n extension
</a>
>Sherlock i18n extension</a>
for a better i18n experience.
</p>
<Component>
<div>
<button>Hello, this is a test</button>
<button>Hello, this is a test</button>
</div>
</Component>
<Component>
<button>Hello, this is a test</button>
<button>Hello, this is a test</button>
</Component>
<button
class="foo bar"
aria-label="click"
onclick={() => console.log("clicked")}
>Click me!</button>
<button
class="foo bar"
aria-label="click"
onclick={() => console.log("clicked")}
>
<span>some fancy looking</span>
<span>really long button text</span>
</button>

@ -1,12 +1,16 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>Svelte App</title>
</head>
<body><div>Hello World</div></body>
</html>

@ -1,8 +1,7 @@
<div style:color="red">...</div>
<div
style:color
style:width="12rem"
style:background-color={darkMode ? 'black' : 'white'}
>
...
</div>
>...</div>

@ -4,6 +4,7 @@
<Widget>
<h1 slot="header">Hello</h1>
<svelte:fragment slot="footer">
<p>All rights reserved.</p>
<p>Copyright (c) 2019 Svelte Industries</p>

@ -1,5 +1,6 @@
<svelte:head>
<title>Hello world!</title>
<meta
name="description"
content="This is where the description goes for SEO"

@ -10,7 +10,6 @@ export default function Async_in_derived($$anchor, $$props) {
var $$promises = $.run([
async () => yes1 = await $.async_derived(() => 1),
async () => yes2 = await $.async_derived(async () => foo(await 1)),
() => no1 = $.derived(async () => {
return await 1;
}),
@ -33,7 +32,6 @@ export default function Async_in_derived($$anchor, $$props) {
var promises = $.run([
async () => yes1 = (await $.save($.async_derived(async () => (await $.save(1))())))(),
async () => yes2 = (await $.save($.async_derived(async () => foo((await $.save(1))()))))(),
() => no1 = $.derived(() => (async () => {
return await 1;
})()),

@ -8,7 +8,6 @@ export default function Async_in_derived($$renderer, $$props) {
var $$promises = $$renderer.run([
async () => yes1 = await 1,
async () => yes2 = foo(await 1),
() => no1 = (async () => {
return await 1;
})(),

@ -14,7 +14,6 @@ export default function Function_prop_no_getter($$anchor) {
onmousedown: () => $.set(count, $.get(count) + 1),
onmouseup,
onmouseenter: () => $.set(count, plusOne($.get(count)), true),
children: ($$anchor, $$slotProps) => {
$.next();
@ -23,7 +22,6 @@ export default function Function_prop_no_getter($$anchor) {
$.template_effect(() => $.set_text(text, `clicks: ${$.get(count) ?? ''}`));
$.append($$anchor, text);
},
$$slots: { default: true }
});
}

@ -13,11 +13,9 @@ export default function Function_prop_no_getter($$renderer) {
onmousedown: () => count += 1,
onmouseup,
onmouseenter: () => count = plusOne(count),
children: ($$renderer) => {
$$renderer.push(`<!---->clicks: ${$.escape(count)}`);
},
$$slots: { default: true }
});
}

@ -6,7 +6,6 @@ var root = $.from_tree(
[
['h1', null, 'hello'],
' ',
[
'div',
{ class: 'potato' },

@ -96,8 +96,8 @@ importers:
specifier: ^1.2.1
version: 1.2.1
esrap:
specifier: ^2.2.1
version: 2.2.1
specifier: ^2.2.2
version: 2.2.2
is-reference:
specifier: ^3.0.3
version: 3.0.3
@ -1356,8 +1356,8 @@ packages:
resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
engines: {node: '>=0.10'}
esrap@2.2.1:
resolution: {integrity: sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==}
esrap@2.2.2:
resolution: {integrity: sha512-zA6497ha+qKvoWIK+WM9NAh5ni17sKZKhbS5B3PoYbBvaYHZWoS33zmFybmyqpn07RLUxSmn+RCls2/XF+d0oQ==}
esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
@ -3720,7 +3720,7 @@ snapshots:
dependencies:
estraverse: 5.3.0
esrap@2.2.1:
esrap@2.2.2:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0

Loading…
Cancel
Save