fix(document): 统一编辑器与文书纸的排版和字体口径
This commit is contained in:
@@ -8,6 +8,10 @@
|
||||
*
|
||||
* 本模块只解除这些「布局锁定」,表格结构(行列、合并、边框、加粗、对齐)全部保留,
|
||||
* 宽度改由各渲染端的 CSS 统一控制,避免同一份文书在不同容器里表现不一致。
|
||||
*
|
||||
* 解除动作本身是 `unlockTableLayout`,粘贴近来要用,**渲染出去也要用**:
|
||||
* 编辑器序列化出来的表格自带 `style="width: auto"` 这类内联锁,只堵粘贴这一个口
|
||||
* 挡不住它(详见该函数的注释)。
|
||||
*/
|
||||
|
||||
const COMMENTS = /<!--[\s\S]*?-->/g
|
||||
@@ -49,6 +53,43 @@ function sanitizeStyleAttribute(style: string): string {
|
||||
.join('; ')
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除表格上的「布局锁定」:绝对宽度、固定行高、固定布局、不换行、内容裁剪。
|
||||
* 宽度交回渲染端 CSS(`.doc-paper table { width: 100% }` 那一套)。
|
||||
*
|
||||
* **两个边界都要做,少一个就会出现"编辑器里与渲染出来不一样"**:
|
||||
*
|
||||
* - **粘贴时**(本模块的 normalizePastedHtml):Word / WPS 的表格带 pt/px 绝对宽度、
|
||||
* `nowrap` 与 `overflow: hidden`;
|
||||
* - **渲染时**(utils/signing-document 的 buildSigningDocumentHtml):WangEditor 的表格
|
||||
* 序列化会把宽度写成**内联样式** —— 它导出的每张表都是
|
||||
* `<table style="width: auto;">`(见 @wangeditor/editor 的 table elemToHtml)。
|
||||
* 而内联样式优先级高于 `.doc-paper table { width: 100% }`,于是同一张表
|
||||
* 在编辑器里撑满版心(编辑器 DOM 上那个 width 是**属性**、值为 `auto` 时浏览器直接忽略),
|
||||
* 到预览 / 签署就变成"按内容收缩",宽度两边对不上。渲染端统一按 CSS 排版才是唯一口径。
|
||||
*
|
||||
* 就地修改传入的文档片段,无返回值。
|
||||
*/
|
||||
export function unlockTableLayout(root: ParentNode): void {
|
||||
root.querySelectorAll('table, col, colgroup, td, th').forEach((element) => {
|
||||
LAYOUT_LOCK_ATTRIBUTES.forEach((name) => element.removeAttribute(name))
|
||||
|
||||
const style = element.getAttribute('style')
|
||||
|
||||
if (!style) {
|
||||
return
|
||||
}
|
||||
|
||||
const sanitized = sanitizeStyleAttribute(style)
|
||||
|
||||
if (sanitized) {
|
||||
element.setAttribute('style', sanitized)
|
||||
} else {
|
||||
element.removeAttribute('style')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 归一化 Word / WPS 粘贴的富文本 HTML。
|
||||
* 入参为空或解析失败时原样返回,不会抛错。
|
||||
@@ -77,23 +118,7 @@ export function normalizePastedHtml(html: string): string {
|
||||
})
|
||||
|
||||
// 表格、列定义与单元格:解除绝对尺寸与不换行约束,宽度交由渲染端 CSS 决定
|
||||
root.querySelectorAll('table, col, colgroup, td, th').forEach((element) => {
|
||||
LAYOUT_LOCK_ATTRIBUTES.forEach((name) => element.removeAttribute(name))
|
||||
|
||||
const style = element.getAttribute('style')
|
||||
|
||||
if (!style) {
|
||||
return
|
||||
}
|
||||
|
||||
const sanitized = sanitizeStyleAttribute(style)
|
||||
|
||||
if (sanitized) {
|
||||
element.setAttribute('style', sanitized)
|
||||
} else {
|
||||
element.removeAttribute('style')
|
||||
}
|
||||
})
|
||||
unlockTableLayout(root)
|
||||
|
||||
return root.innerHTML
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user