vue icon indicating copy to clipboard operation
vue copied to clipboard

Trailing whitespaces are trimmed from the end of inline <strong> element when page is being parsed by Vue

Open kfirba opened this issue 5 years ago • 20 comments

Version

2.6.10

Reproduction link

https://jsfiddle.net/kfirba2/us5h04f7/5/

Steps to reproduce

  1. Have a wrapper for Vue
  2. Inside that wrapper, insert an inline element such as <strong> and leave trailing whitespace at the end of it:
<div id="#app">
  This is <strong>BOLD </strong>text
</div>
  1. After the page is parsed with Vue (and Vue has generated a Virtual DOM for the page), the words "BOLD" and "text" will be glued together (the whitespace after the word "BOLD" and before the enclosing tag of <strong> is removed.

What is expected?

It is expected that the whitespace will remain in its place and not trimmed.

What is actually happening?

The trailing whitespace is trimmed.

kfirba avatar Feb 18 '20 10:02 kfirba

I think https://github.com/vuejs/vue/pull/11065 pr will fix this.

despreston avatar Feb 19 '20 15:02 despreston

@despreston I’m not sure it’s going to solve it. The PR focuses on the template compiler if I’m not mistaken. The issue here is the DOM that Vue mounts on and parses into virtual DOM on the fly

kfirba avatar Feb 19 '20 17:02 kfirba

Hi. What's your use case of using

<strong>BOLD </strong>text

instead of this?

<strong>BOLD</strong> text

Justineo avatar Feb 20 '20 03:02 Justineo

@Justineo Hey,

You are absolutely right that it is not natural, however, our website is Vue powered and some of the website's content is UGC. Users are using some sort of a WYSIWYG and never write HTML. Because of that reason, we, nor them, have any good control of the generated HTML. We tried solving that in some ways but it looks like we couldn't achieve a satisfiable solution.

kfirba avatar Feb 20 '20 04:02 kfirba

I assume you won't need Vue to parse and compile the UGC code. You can try put a v-pre directive on the wrapper element around your UGC so that Vue will skip that part.

Justineo avatar Feb 20 '20 04:02 Justineo

@Justineo I wasn't aware of the v-pre directive so thanks for that.

However, it is not entirely true. The way we have it working is that the user (who is not always a "random" user, but may be an editor) has a WYSIWYG where he can also "inject" custom elements which are Vue elements, such as Lead Forms. So the UGC content has Vue elements within it For example:

<div id="#app">
  <p>Text Text Text....</p>
  <lead-form></lead-form>
  <p>...</p>
  <another-element></another-element>
  ...
</div>

kfirba avatar Feb 20 '20 04:02 kfirba

@Justineo Hey, is there anything new with that?

kfirba avatar Feb 24 '20 04:02 kfirba

Correct me if I'm wrong, but isn't skipping whitespaces default behaviour in HTML? You usually have to insert whitespaces manualy as &nbsp;.

s-gbz avatar Mar 06 '20 11:03 s-gbz

Sometimes you will need something like since webpack (if I recall correctly) removes all spaces

Garito avatar Mar 06 '20 12:03 Garito

@s-gbz only subsequent spaces. Multiple spaces are “collapsed” into 1 space visually. In the source code you will find all of the spaces.

This is obviously a bug. Webpack has nothing do to with it as we are talking about Vue mounting on an existing DOM which has never gone any compilation/transpiration step (rendered with PHP)

kfirba avatar Mar 07 '20 17:03 kfirba

Is this something I can look into? @kfirba I agree, this seems like a bug.

abrahamguo avatar Mar 22 '20 05:03 abrahamguo

After investigating this issue, I can see that it is caused by this function:

function trimEndingWhitespace (el) {
	// remove trailing whitespace node
	if (!inPre) {
		var lastNode;
		while (
			(lastNode = el.children[el.children.length - 1]) &&
			lastNode.type === 3 &&
			lastNode.text === ' '
		) {
			el.children.pop();
		}
	}
}

which removes ending whitespace. Does anyone know the reasoning behind this function?

abrahamguo avatar Mar 22 '20 05:03 abrahamguo

@abrahamguo anything new regarding this issue?

kfirba avatar Apr 02 '20 22:04 kfirba

Nope. I found the code for it in the core but I need the advice of people more knowledgeable than me to advise the purpose of this code. Otherwise, you could maybe dig through the history to find why this code was added.

abrahamguo avatar Apr 03 '20 01:04 abrahamguo

@s-gbz only subsequent spaces. Multiple spaces are “collapsed” into 1 space visually. In the source code you will find all of the spaces.

This is obviously a bug. Webpack has nothing do to with it as we are talking about Vue mounting on an existing DOM which has never gone any compilation/transpiration step (rendered with PHP)

Is this something I can look into? @kfirba I agree, this seems like a bug.

Version

2.6.10

Reproduction link

https://jsfiddle.net/kfirba2/us5h04f7/5/

Steps to reproduce

  1. Have a wrapper for Vue
  2. Inside that wrapper, insert an inline element such as <strong> and leave trailing whitespace at the end of it:
<div id="#app">
  This is <strong>BOLD </strong>text
</div>
  1. After the page is parsed with Vue (and Vue has generated a Virtual DOM for the page), the words "BOLD" and "text" will be glued together (the whitespace after the word "BOLD" and before the enclosing tag of <strong> is removed.

What is expected?

It is expected that the whitespace will remain in its place and not trimmed.

What is actually happening?

The trailing whitespace is trimmed.

我认为#11065 pr将解决此问题。

我认为#11065 pr将解决此问题。

cccccccccc

galaxy-s10 avatar Apr 20 '20 02:04 galaxy-s10

Version

2.6.10

Reproduction link

https://jsfiddle.net/kfirba2/us5h04f7/5/

Steps to reproduce

  1. Have a wrapper for Vue
  2. Inside that wrapper, insert an inline element such as <strong> and leave trailing whitespace at the end of it:
<div id="#app">
  This is <strong>BOLD </strong>text
</div>
  1. After the page is parsed with Vue (and Vue has generated a Virtual DOM for the page), the words "BOLD" and "text" will be glued together (the whitespace after the word "BOLD" and before the enclosing tag of <strong> is removed.

What is expected?

It is expected that the whitespace will remain in its place and not trimmed.

What is actually happening?

The trailing whitespace is trimmed.

test

galaxy-s10 avatar Apr 20 '20 02:04 galaxy-s10

@despreston I’m not sure it’s going to solve it. The PR focuses on the template compiler if I’m not mistaken. The issue here is the DOM that Vue mounts on and parses into virtual DOM on the fly

test

galaxy-s10 avatar Apr 20 '20 02:04 galaxy-s10

What is the status of this ticket? I have exactly the same problem with some UGC.

<p>This is a<em> </em>paragraph</p>

will be compiled to

<p>This is a<em></em>paragraph</p>

Not the result I am hoping for. The v-pre directive does nothing and the whitespace compiler option does not have any effect.

weblogjacob avatar Nov 10 '20 14:11 weblogjacob

Going 2021 years... Without changes?

kirya-dev avatar May 21 '21 19:05 kirya-dev

Same issue with vue v3.5.12 using CDN https://unpkg.com/vue@3/dist/vue.esm-browser.js However, it is also removing new lines.

So this:

<div class="modal" :class="{open: open}" @click="open = false">
    <article class="mw-400" @click.stop>
        <p>Modal</p>
        <button @click="open = false">
            Close Modal
        </button>
    </article>
</div>

is becoming:

<div class="modal" :class="{open: open}" @click="open = false"><article class="mw-400" @click.stop><p>Modal</p><button @click="open = false"> Close Modal </button></article></div>

Oddly it is keeping whitespace around the button text, but removing it elsewhere.

I did find that you can do app.config.compilerOptions.whitespace = 'preserve'; but this only works on single nodes and not the entire app container.

The only reason this is an issue for me is that I have a Copy HTML tool that users can copy the html code. But because of this it removes the whitespace before they can copy the code with proper indentation.

Is there a way to disable this. Otherwise, am I stuck with having to add some custom indentation code when they copy the code.

ggedde avatar Nov 09 '24 01:11 ggedde