为什么富文本无法渲染多个连续空格

1,692 阅读4分钟

事情的起因

添加空格之后,上传给后台之后,回显的时候,没有正确的处理空格,不管多少个空格都只显示一个空格。

输入空格之前:

输入之后:

问题盘查

将显现和问题输入chatGPT,它给了答案。辅以谷歌百度。得到下面的解释:

浏览器会识别标签之间的空格,但会将连续的空格合并为一个空格。这是因为HTML规范规定,连续的空白字符(包括空格、制表符和换行符)在渲染时会被合并为一个空格,这样可以保证页面的呈现一致性。所以在HTML标签内部的连续空格会被视为一个空格,而不会影响页面的布局。但需要注意的是,标签开始和结束之间的空格不会被合并,它们会被保留。

也就是说,当我们在html中输入下面的代码:

<p>
  This is a paragraph with
  multiple lines of text.
</p>

它在页面上面最终渲染的还是一行。只是在with和multiple之间有一个空格。

解决过程

让浏览器能够识别出空格就好了。所以浏览器识别什么空格呢?实体' '。所以说只要将空格都替换成实体的' '就可以让浏览器正确的渲染。

代码实现:

const saveEditorValue = () => {
  const value = editorValue?.replace (/\s\s/g, ' &nbsp;') || ''
  localStorage. setItem('gasEditorValue', value) 
  console.log('The data storage server succeeds. Procedure')
}

但是这样有一个明显的问题。对字符串进行处理不是浏览器的长处。当要处理的文本超过100KB的时候,浏览器会有明显的卡顿。所以我们最后能够让浏览器可以对标签内的空格进行识别。

所以说最好是能够直接渲染出标签内的空格。经过一分钟的搜索,得到出了结论,可以使用css的属性white-space。翻阅mdn文档之后知道了它的四个属性:

.my-element {
	white-space: normal;   /* 默认值 */
}
.preformatted {
	white-space: pre;      /* 保留所有空白字符的可见性 */
}
.nowrap-text {
	white-space: nowrap;   /* 不换行,文本在一行上显示 */
}
.wrap-text {
	white-space: pre-wrap; /* 保留所有空白字符的可见性,并且超出容器宽度换行 */
}

所以我们使用使用pre或者 pre-wrap即可。

问题来了,我们使用该css属性是可以让v-html渲染的节点可以实现多空格的渲染的。但是想要拿到富文本的class来直接穿透属性进行的方式却行不通。如下图:

看来是富文本对输入进去的内容进行了处理。所以打开tiptap的文档,果然找到了对应配置的属性。

new Editor({
  parseOptions: {
    preserveWhitespace: 'full',
  },
})

代码中有该属性的注释,如下:

    /**
    By default, whitespace is collapsed as per HTML's rules. Pass
    `true` to preserve whitespace, but normalize newlines to
    spaces, and `"full"` to preserve whitespace entirely.
    */
    preserveWhitespace?: boolean | "full";

翻译的结果就是效果和white-space是一样的。

配置上去之后,数据初始话的时候,果然渲染出了多个空格,但是当我们使用editor.value?.commands.setContent('xx xxx', false)给富文本赋值的时候,空格又全部只有一个。官网站不到问题。

属性已经给了,但是配置上去了依旧不行,那是不是tiptap自身的BUG呢?所以只能去tiptap的github代码仓库的issue上面找寻答案。

换了多个关键字搜索:'space'、'entity'、'content' 垃圾英语表述能力只能通过这样的方式来搜索了,看Open的,看closed。 这是一个漫长的过程!

还好最终在closed中找到了答案,链接如下github.com/ueberdosis/…

原来配置好初始之后还不够,还需要我们在setContent方法里面也添加上preserveWhitespace属性。

editor.commands.setContent(xxxxx, false, {
  preserveWhitespace: "full",
})

问题得到解决。

总结

ChatGTP + 官方文档 + 代码仓库的issue = 问题解决路径

扩展

  • 标签内的空格在ASCII码中用32来表示。

  • 一些常用的实体如下:

    &lt;:小于号 <
    &gt;:大于号 >
    &amp;:和号 &
    &quot;:引号 "
    &apos;:单引号 '
    &nbsp;:空格
    &copy;:版权符号 ©
    &reg;:注册商标符号 ®
    &trade;:商标符号 ™