飞流 发表于 2025-10-5 21:19:04

Discuz编辑器换行时,出现多余<br>标签问题的解决思路

这个问题是discuz历年版本来一直存在的问题了,最近研究了一下,没有最终解决,但是我似乎发现了重要线索,记录一下吧。关键性文件static/js/bbcode.js,现在我们来分析一下。在 Discuz! 3.5 的bbcode.js中,涉及文字换行与<br>标签转换的核心代码主要集中在 bbcode2html(BBcode 转 HTML) 和 html2bbcode(HTML 转 BBcode) 两个核心函数中,同时包含一处针对 Chrome 浏览器的换行兼容性修复。以下是具体代码及功能说明:一、核心场景 1:BBcode 转 HTML(将文本换行符转为<br>)bbcode2html函数的作用是将用户输入的 BBcode 语法转换为浏览器可识别的 HTML。其中,文本中的换行符(\r\n/\n/\r)会被替换为<br />标签,确保换行在页面上正常显示。相关代码片段(位于bbcode2html函数末尾):if(!allowhtml || !fetchCheckbox('htmlon')) {
    str = str.replace(/(^|>)([^<]+)(?=<|$)/ig, function($1, $2, $3) {
      // 替换制表符、空格,并将所有换行符(\r\n|\n|\r)转为<br />
      return $2 + preg_replace(
            ['\t', '   ', '', '(\r\n|\n|\r)'],// 匹配目标:制表符、多空格、换行符
            ['&nbsp; &nbsp; &nbsp; &nbsp; ', '&nbsp; &nbsp;', '&nbsp;&nbsp;', '<br />'],// 替换结果:空格占位符、<br>换行
            $3
      );
    });
}功能说明:
[*]触发条件:当页面不允许 HTML 输入(!allowhtml)或用户未勾选 “允许 HTML”(!fetchCheckbox('htmlon'))时生效。
[*]核心逻辑:通过正则匹配文本中 “非 HTML 标签包裹的内容”,将其中的:

[*]制表符(\t)→ 4 个空格占位符( );
[*]3 个空格 → 2 个空格占位符;
[*]2 个空格 → 2 个空格占位符;
[*]所有换行符(\r\n Windows 换行、\n Unix/Linux 换行、\r 旧 Mac 换行)→ <br />标签,实现文本换行的 HTML 渲染。
二、核心场景 2:HTML 转 BBcode(将<br>标签转为文本换行符)
该函数负责将 HTML 中的<br>标签反向转换为文本换行符(\n),确保编辑时换行符正常保留。
1. 修复 “首个回车无法换行” 的<br>插入(位置:html2bbcode函数开头)
// fix first enter cannot start new line
var divPos = strpos(str,"<div>");
if(divPos > 0 ){
    if(divPos > 4 && str.substr(divPos - 4,4) == '</p>'){}
    else{
      // 在<div>前插入<br>,确保首个换行生效
      str = str.substr(0,divPos) + '<br>'+ str.substr(divPos);
    }
}
// end功能:修复编辑器中 “首个回车无法生成换行” 的问题 —— 当 HTML 中<div>标签前无<br>时,手动插入<br>,确保换行逻辑正常。
另外html2bbcode函数的作用是将 HTML 内容反向转换为 BBcode(例如编辑器切换 “源码模式” 时)。其中,HTML 中的<br>标签会被替换为文本换行符(\n),确保换行逻辑在 BBcode 中保留。
相关代码片段(位于html2bbcode函数中部):
// 1. 先清除带“clear: both”样式的<br>(通常用于浮动元素换行,无需保留)
str = str.replace(/<br\s+?style=(["']?)clear: both;?(\1)[^\>]*>/ig, '');
// 2. 将所有剩余的<br>标签(含变体,如<br/>、<br >)转为文本换行符(\n)
str = str.replace(/<br[^\>]*>/ig, "\n");相关代码片段(位于html2bbcode函数前部):
功能说明:
第一步:过滤掉用于 “清除浮动” 的特殊<br>(如<br style="clear: both;">),这类<br>是布局用,不代表用户输入的换行,因此直接删除。
第二步:通过正则/<br[^\>]*>/ig匹配所有标准<br>标签(包括<br>、<br/>、<br class="xxx">等变体),统一替换为文本换行符\n,确保换行逻辑在 BBcode 中正常保留。
三、兼容性修复:Chrome 浏览器中<div>与<br>的换行处理由于 Chrome 浏览器对<div>标签的默认渲染逻辑特殊,html2bbcode中专门增加了针对 Chrome 的换行兼容性修复,避免换行丢失或重复。
相关代码片段(位于html2bbcode函数前部):
if(navigator.userAgent.indexOf('Chrome') > -1){
    // 1. 将空<div><br></div>(Chrome中换行的默认生成结构)转为单个<br>
    str = str.replace(/<div><br><\/div>/ig, '<br>');
    // 2. 在<div>开头添加<br>,确保Chrome中<div>的换行被识别
    str = str.replace(/<div>/ig, '<br><div>');
    // 3. 合并<div>之间的多个<br>,避免重复换行
    str = str.replace(/<\/div>((<br[^>]*>){1,})<div>/ig, '$1');
}功能说明:
[*]Chrome 浏览器在富文本编辑时,会将用户的 “换行” 自动生成<div><br></div>或<div></div>结构,而非标准<br>。
[*]这段代码通过正则调整该结构:

[*]空的<div><br></div> → 简化为<br>,避免冗余标签;
[*]普通<div>开头添加<br>,确保换行被后续 “<br>转\n” 逻辑识别;
[*]合并<div>之间的多个<br>,避免转换后出现重复换行。
页: [1]
查看完整版本: Discuz编辑器换行时,出现多余<br>标签问题的解决思路