Parser adds <br> tag to every paragraph

When I supply supply a content div which contains a paragraph with trailing line breaks, then I parse that div according to the demo schema, then I use the resulting content to create an EditorView, the HTML produced by the EditorView contains an extra line break

  1. Start with this content
<div id="content">
  <p>
    hello
    <br>
    <br>
  </p>
</div>
  1. Parse the content let startDoc = DOMParser.fromSchema(demoSchema).parse(content)

  2. Create a new EditorView let view = new EditorView(document.querySelector("#editor"), { …

  3. Editor has a third line break that wasn’t in the original HTML

<div contenteditable="true" class="ProseMirror ProseMirror-example-setup-style">
  <p>
    hello
    <br>
    <br>
    <br>
  </p>
</div>

Anyone have this issue before? Any idea the best way to fix it? Thank you!

The third break is just there in the editor view to make the second break visible. It isn’t part of the document and you probably shouldn’t worry about it.

@marijn thank you for your quick reply! okeydokey, i understand.

however! the reason this was causing me trouble is that, for my application, i’ve been saving the HTML contents of my editor to my database, then parsing them back in when I want to continue working on my document. this causes the document to slowly accumulate line breaks as I save and refresh.

is it not conventional to save the HTML of my document and read it back in? should I be exclusively saving JSON and reading JSON?

I made this change to addTextBlockHacks() which seems to solve my problem.

Hopefully this is not a bad idea!

addTextblockHacks() {
    let lastChild = this.top.children[this.index - 1]
    while (lastChild instanceof MarkViewDesc) lastChild = lastChild.children[lastChild.children.length - 1]

    if(!lastChild || // Empty textblock
      lastChild.node.type.name !== "hard_break") { // Don't double up on line breaks
      if (!(lastChild instanceof TextViewDesc) ||
          /\n$/.test(lastChild.node.text)) {
        if (this.index < this.top.children.length && this.top.children[this.index].matchesHack()) {
          this.index++
        } else {
          let dom = document.createElement("br")
          this.top.children.splice(this.index++, 0, new BRHackViewDesc(this.top, nothing, dom, null))
          this.changed = true
        }
      }
    }
  }
1 Like

Definitely a bad idea.

And so is taking the innerHTML from the editor. Run the document through a DOMSerializer instead and save that HTML—that’ll be the actual document representation, rather than whatever the editor needs to display to make browsers behave.

In case you need it: This is my function to get HTML from prosemirror:

getHTML() {
	const div = document.createElement('div')
	const fragment = DOMSerializer
		.fromSchema(this.schema)
		.serializeFragment(this.state.doc.content)

	div.appendChild(fragment)

	return div.innerHTML
}
3 Likes

Excellent, thank you!

@philippkuehn I’ll give your function a shot

Your code has helped me a lot. Great job!!!

Hi @marijn, I don’t understand why it needs to add a third break. The 2 first breaks are already visible. Adding a third break adds a visual third break which is not what I want (I only want to see 2 breaks).

I wan not able to fix this on my side. The editor keeps adding breaks that are visible.

我也采用了你的方法

由于修改了 addTextblockHacks 方法,可能造成了编辑出现错乱,因此将修改方法改为 setContent 时候进行,代码如下

      Array.prototype.forEach.call(pList, (child: HTMLParagraphElement) => {
    console.log('child', child);
    if (child.children.length === 1) {
      let lastChild = child.children[0];

      while (lastChild.children.length === 1) {
        lastChild = lastChild.children[0];
      }

      if (lastChild.nodeName === 'BR' && /^\n+$/.test(child.textContent || '')) {
        child.setAttribute('style', '');
        child.innerHTML = '';
      }
    }
  });