Subscribe on changes!

Whitespace is incorrectly stripped between tags in string templates

avatar
Oct 19th 2020

Version

3.0.1

Reproduction link

https://codepen.io/stowball/pen/VwjjQmr

Steps to reproduce

  1. Create a new app whose template is a tagged template literal with multiple tags with whitespace in-between

What is expected?

For the whitespace to be maintained, like in Vue 2 https://codepen.io/stowball/pen/ExyyQmN

What is actually happening?

All whitespace between tags is removed

avatar
Oct 19th 2020

Oh wow. Any template does it!

Here's an SFC: https://codepen.io/stowball/pen/MWeeQXK Here's a UMD build using the app's innerHTML: https://codepen.io/stowball/pen/LYZZQmO

avatar
Oct 19th 2020

This is an intended change. v3 uses the equivalent of v2's whitespace: 'condense' in all cases, so whitespace between tags are only preserved if it contains no newlines:

<div>
  <span>{{ foo }}</span> <span>{{ baz }}</span>
</div>

See https://github.com/vuejs/vue/tree/dev/packages/vue-template-compiler#options

I believe in v2 CLI scaffolded apps already use this behavior by default. In v3 this applies to runtime-compiled templates too.

avatar
Oct 19th 2020

I would have to say that this is a bad change. Many teams, mine included, use new lines exclusively between tags, including those in "sentences".

This change basically breaks many of our layouts where, for example, we intentionally bold words besides hyperlinks.

It is reasonable to expect that the compiled template behave exactly like the raw HTML provided, just with interpolations replaced, especially when the template was provided by said HTML file. HTML smartly handles all whitespace between tags, providing inline superpowers, and so should Vue imo.

avatar
Oct 19th 2020

Looks like the same problem I’m having. https://stackoverflow.com/questions/64432182/vue-3-removes-white-space-between-inline-block-elements.

This is a breaking change from version 2 that I haven’t seen documented. I also agree it shouldn’t change what the user intended (raw HTML). There’s other solutions to this problem (e.g. using comments between the tags) which should be down to the user and not the compiler.

avatar
Oct 21st 2020

I've realized also inline v-if/v-else is not work a migrated code from Vue2 in Vue3.

<div>
  <div v-if="1">ccc</div> <div v-else>ddd</div>
</div>

Then I get,

[Vue warn]: Template compilation error: v-else/v-else-if has no adjacent v-if.
13 |  
14 |  		<div>
15 |  			<div v-if="1">ccc</div>	<div v-else>ddd</div>
   |                               ^^^^^^^^^^^^^^^^^^^^^
16 |  		</div>
17 |   
  at <App>

But, when I use new line is only fine, not space(s) or tab(s).

<div>
  <div v-if="1">ccc</div>
  <div v-else>ddd</div>
</div>

with no errors.

My develop environments minify newline to space automatically like,

from

<div v-if="1">ccc</div>
<div v-else>ddd</div>

to

<div v-if="1">ccc</div> <div v-else>ddd</div>

So I'm getting tons of Vue warning when I try using Vue3... My temporary solutions are,

Solution 01

<div v-if="1">
  ccc
</div><div v-else>
  ddd
</div>

Solution 02

<div v-if="1">ccc</div><!--
--><div v-else>ddd</div>

Is there anyone who has a better idea for is issue? I'm thinking if I have to give up migration from Vue2 to Vue3.

avatar
Dec 10th 2020

This is an intended change. v3 uses the equivalent of v2's whitespace: 'condense' in all cases, so whitespace between tags are only preserved if it contains no newlines

@yyx990803 I'd like to also weigh in on this not being an ideal behavior, especially as a default.

This ended up causing a lot of unfortunate behavior for us in trying to migrate to vue 3 (and ultimately stopped us altogether). We had many places where text that used tags for things like highlighting or in-line formatting which ended up jumbled because vue 3 decided to ignore normal HTML whitespace rules.

Fundamentally, I feel like the issue is a lack of consistency between vue and HTML. Consider that in plain HTML, this: <i>a</i> <i>b</i>\n<i>c</i> renders as "a b c". In vue-2, this renders as "a b c". In vue-3, this renders as "a bc". Having a paragraph or even a single sentence broken up across multiple lines in HTML is not exactly a strange behavior, and the fact that Vue-3 diverges from expectation was problematic.

As a user of pre-built, CDN-supplied Vue libraries in various websites, I am still looking for a way to modify the compiler behavior to the vue-2 default in vue-3. I asked around in the vue discord, and while there were people who both agreed and disagreed with what vue-3 should do, none of us could find a means to get the HTML behavior out of a CDN-hosted Vue.