活力39282
在线时间13640 小时
阅读权限200
管理员
自由的灵魂
- 积分
- 107434
- 主题
- 5630
- 回帖
- 26661
- 注册时间
- 2003-4-10
- 最后登录
- 2026-10-2
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、问题缘起
使用中发现,后台设置“帖子内容字号”为14px后,在论坛发帖使用所见即所得(WYSIWYG)编辑器时,粘贴内容会自动被包裹 [ size=14px ] 标签,导致:
- 代码冗余:每段文字都被[ size=14px ] ... [ /size ] 包裹,增加不必要的 BBcode
- 影响阅读:部分用户使用的 14px 字号与论坛默认显示不一致,导致排版混乱
- 编辑困难:切换到纯文本模式时,大量 [size] 标签干扰内容编辑
- 影响美观:帖子源码充斥着无意义的标签,不专业
- 浏览器差异:问题仅在 Microsoft Edge 浏览器中出现,Firefox 正常
探讨过程中提出的独立问题汇总:
| 序号 | 问题 | 结论 | | 1 | 标签由谁生成? | 所见即所得编辑器在粘贴内容时自动添加 | | 2 | 为什么编辑器会认为 14px 需要添加 [size] 标签? | 编辑器 iframe 的 <body> 没有设置 font-size,浏览器使用默认字号(通常 12px 或 16px),粘贴内容中的 14px 被视为“差异样式”,被自动转换为 [size] 标签 | | 3 | 修改 editor.css 为何无效? | editor.css 控制的是纯文本模式(textarea)下的编辑框字号,而所见即所得模式是一个独立的 iframe,其样式由 editor.js 初始化时决定,两者互不关联 | | 4 | 为什么只有 Edge 浏览器有此问题? | Edge(及 Chrome)在粘贴纯文本时,会将其“包裹”一层默认样式以保持视觉一致性,从而触发 [size] 标签生成;Firefox 则直接作为纯文本插入,不添加额外样式 | | 5 | 为什么只有从记事本复制的无格式文本会触发? | 有格式的文本(如从网页复制)自带样式信息,编辑器能正确处理;无格式文本会被浏览器赋予默认样式,从而触发 [size] 标签的生成 | | 6 | 后台 {MSGFONTSIZE} 与编辑器字号是什么关系? | 后台设置仅控制前台帖子显示,编辑器初始化时并不读取该值 |
二、解决方案
(1)简要技术分析
采用三重策略:① 在编辑器 iframe 初始化时,给 <body> 标签添加 style="font-size:14px",消除样式差异;② 在粘贴事件中拦截纯文本,强制使用 insertText 或直接操作 textarea.value 插入,阻止浏览器自动添加样式;③ 根据编辑模式(可视化/纯文本)选择不同的插入方式,避免 execCommand 在纯文本模式下报错。
(2)修改文件列表(完整路径)
| 文件 | 修改位置 | 控制对象 | | /static/js/editor.js | writeEditorContents 函数 | 可视化模式(iframe body 字号) | | /static/js/editor.js | setEditorEvents 函数 | 粘贴事件拦截(纯文本处理,含模式判断) | | /template/default/common/editor.css | .edt .pt 规则 | 纯文本模式(textarea 字号) |
(3)关键作用代码段
文件 1:/static/js/editor.js(writeEditorContents 函数)
修改前:
- '</head><body>' + text + '</body></html>';
复制代码
修改后:
- '</head><body style="font-size:14px">' + text + '</body></html>';
复制代码
文件 2:/static/js/editor.js(setEditorEvents 函数)
修改后完整代码:
- function setEditorEvents() {
- if(BROWSER.firefox || BROWSER.opera) {
- editdoc.addEventListener('mouseup', function(e) {mouseUp(e)}, true);
- editdoc.addEventListener('keyup', function(e) {keyUp(e)}, true);
- editwin.addEventListener('keydown', function(e) {keyDown(e)}, true);
- // ----- 新增:paste 事件监听(纯文本粘贴拦截) -----
- editdoc.addEventListener('paste', function(e) {
- var clipboardData = e.clipboardData || window.clipboardData;
- if (!clipboardData) return;
- var text = clipboardData.getData('text/plain');
- if (text) {
- e.preventDefault();
- if (wysiwyg) {
- editdoc.execCommand('insertText', false, text);
- } else {
- var start = editdoc.selectionStart;
- var end = editdoc.selectionEnd;
- var value = editdoc.value;
- editdoc.value = value.substring(0, start) + text + value.substring(end);
- editdoc.selectionStart = editdoc.selectionEnd = start + text.length;
- }
- }
- }, true);
- // -------------------------------------------------
- } else if(editdoc.attachEvent) {
- try{
- editdoc.attachEvent('onmouseup', mouseUp);
- editdoc.attachEvent('onkeyup', keyUp);
- editdoc.attachEvent('onkeydown', keyDown);
- // ----- 新增:paste 事件监听(IE 兼容写法) -----
- editdoc.attachEvent('onpaste', function(e) {
- e = e || window.event;
- var clipboardData = e.clipboardData || window.clipboardData;
- if (!clipboardData) return;
- var text = clipboardData.getData('text');
- if (text) {
- e.returnValue = false;
- if (wysiwyg) {
- var range = editdoc.selection.createRange();
- range.text = text;
- } else {
- var start = editdoc.selectionStart;
- var end = editdoc.selectionEnd;
- var value = editdoc.value;
- editdoc.value = value.substring(0, start) + text + value.substring(end);
- editdoc.selectionStart = editdoc.selectionEnd = start + text.length;
- }
- }
- });
- // ------------------------------------------------
- } catch(e) {}
- }
- }
复制代码
文件 3:/template/default/common/editor.css
修改前:
- .edt .pt { padding: 0 !important; width: 100%; height: 400px; border: none; background: {WRAPBG} none; font-size: {MSGFONTSIZE}; }
复制代码
修改后:
- .edt .pt { padding: 0 !important; width: 100%; height: 400px; border: none; background: {WRAPBG} none; font-size: 14px; }
复制代码
三、最终实现效果
| 测试场景 | 修改前 | 修改后 | | 所见即所得模式粘贴内容(任意来源) | 自动添加 标签 | 不再生成任何 [size] 标签 | | Edge 浏览器粘贴纯文本 | 被添加 | 正常插入,无标签 | | Firefox 浏览器粘贴纯文本 | 正常 | 正常(不受影响) | | 粘贴富文本(带格式) | 正常保留格式 | 正常保留格式(不受影响) | | 纯文本模式粘贴 | 报错 execCommand is not a function | 正常插入 | | 编辑器显示 | 闪烁或不一致 | 稳定 14px | | 纯文本模式编辑框 | 字号由 {MSGFONTSIZE} 控制 | 固定 14px | | 用户手动选择字号 | 正常生成 等标签 | 正常生成(不受影响) | | 后台 {MSGFONTSIZE} 设置 | 被编辑器间接借用 | 仅控制前台帖子显示 |
四、重要技术沉淀
- iframe 独立文档环境的隔离性:iframe 内部是一个完全独立的文档,主页面的 CSS 无法控制其内部样式。调试时需注意区分“主页面样式”和“iframe 内部样式”两个不同的上下文
- 编辑器字号问题的根源:[size] 标签的自动生成,源于 iframe body 缺少字号定义导致的“样式差异”。给 body 设置明确的 font-size 即可消除此行为
- editor.css 的作用范围:该文件控制的是纯文本模式(textarea)下的编辑框字号,对可视化模式(iframe)无效,两者互不关联
- 浏览器粘贴行为差异:Edge/Chrome 在粘贴纯文本时会自动包裹默认样式,Firefox 则直接插入纯文本。需通过 paste 事件拦截来统一行为
- execCommand 的适用场景:document.execCommand('insertText') 仅在可视化模式(iframe document)下可用,纯文本模式(textarea)下需直接操作 value 属性,否则会报错
- {MSGFONTSIZE} 的正确职责:该变量应仅用于控制前台帖子显示,不应被编辑器借用为生成 [size] 标签的依据
是否需要更新固化摘要:✅ 是。建议在 env-base 固化摘要的“编辑器”章节补充:所见即所得编辑器已通过修改 editor.js 固定 body 字号并拦截 paste 事件,解决自动生成 [size] 标签的问题,同时兼容可视化与纯文本两种模式。
五、进一步优化的可能性
编辑器核心升级:Discuz! 编辑器版本较老,可考虑升级至更现代的编辑器(如 Quill、TinyMCE)从根本上解决此类问题,但涉及全站改造成本较高,暂不实施。 |
|