sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.21k stars 4.09k forks source link

Feature request: Option to trim whitespace between tags #3080

Closed trbrc closed 5 months ago

trbrc commented 5 years ago

Problem

Svelte's handling of whitespace in templates is supposed to be consistent with HTML. However, the way HTML handles whitespace makes styling of inline blocks notoriously difficult in some cases, with no satisfactory workaround. There are basically two types of workarounds, each with their own frustrating problems:

1) Either you change your styling so it removes the spaces. This is often requires complicated, unintuitive and fragile workarounds in your CSS. Most of the strategies I'm aware of can have unintended consequences in some situations. 2) Or you change the markup to remove all the spacing. This is possible, but now you are severely impacting the readability of your component to achieve a certain styling.

Strategy 2 is arguably even trickier in a Svelte template, where spaces may or may not appear inside other components or slots, or around {#if} or {#each} blocks. Blocks appear to already have some heuristics to avoid unnecessary spaces, but that also makes it harder to predict where spaces will need to be avoided or not.

I'm used to JSX, where whitespace is automatically trimmed, and you have to insert it manually with {" "} when you want it. While this can cause its own occasional oddities, it's always much easier to add spaces explicitly than to remove them, and it allows the formatting of a template to be optimised for readability.

Suggestion

It would be very helpful if there was a way to opt in to similar behaviour for a Svelte component. I think the natural way to do it would be by using <svelte:options>:

<svelte:options trimWhitespace={true} />

I don't understand the details of how whitespace is handled in the compiler, but I think the compiler would just need to remove any calls to space() from svelte/internal.

stalkerg commented 5 years ago

I suppose it's duplicate of #189

neuronetio commented 4 years ago

I think that {#each} and {#if} blocks should not add any empty text node too (because of performance). If you have a lot of DOM nodes and in between each node there is a text node inserted (even empty) - it will drastically affect rendering speed (DOM nodes are really slow of course).

neuronetio commented 4 years ago

sometimes those text nodes are out of control https://svelte.dev/repl/902d4ccfcc5745d0b927b6db6be4f441?version=3

neuronetio commented 4 years ago

I've created an issue for empty text nodes here #3586

stalkerg commented 4 years ago

Ok, who can implement this proposal? Personal for me I want to add a feature when you can control space trimming per nodes, like <div :trim></div>. But global config for a component also need.

elron commented 2 years ago

Anything new on this?

tmarsik42 commented 1 year ago

It's possible to work around this by creating a html comment tag wherever unneeded whitespace appears. Although that's a very ugly hack and I'd be more than happy to remove those comments from my codebase.

stalkerg commented 1 year ago

I tried to fix it but, it was too complicated. Need a new attempt.

AlbertMarashi commented 1 year ago

Also need this for building markdown renderers that might affect whitespace.

Having a :trim to toggle inclusion of whitespace in svelte would be useful

Its nice to be able to indent svelte instead of having to put everything on one line because of whitespace

stalkerg commented 1 year ago

Yeah, now we have a better codebase, maybe it will be simpler, but the team is probably focused on Svelte5 now.

Rich-Harris commented 5 months ago

I'm going to close this, as Svelte 5 has much more sensible whitespace handling — whitespace is preserved between siblings, but collapsed at the edges of nodes. In practice, this is what you want 99% of the time, and there are escape hatches ({' '} etc) for the remaining 1%.