我正在构建的应用程序中有一个奇怪的问题:
我有一个显示文本的部分,并且某些单词被标记为
span
,其类别为 annotation
。这个注释有一个text-decoration: underline
风格,没什么花哨的。
如果我现在将此文本粘贴到带有
div
的 content-editable=true
或 MS Office Word 等程序中,则具有 annotation
类的文本实际上会被转换为类似于完整下划线的内容。
我在 Firefox 中尝试了相同的操作,但它的行为并不相同 - 尽管所有 Chromium 浏览器都是如此。
示例:
粘贴到富文本字段(在内部再次突出显示该单词):
与Word相同:
我查看了 Chrome 放入剪贴板的内容,这是添加的内容
text/html
:
<span style="color: rgb(68, 64, 60); font-family: InterVariable, Inter, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">were once<span> </span></span><span class="annotation " style="box-sizing: border-box; border: 0px solid rgb(228, 228, 231); --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-pan-x: ; --tw-pan-y: ; --tw-pinch-zoom: ; --tw-scroll-snap-strictness: proximity; --tw-gradient-from-position: ; --tw-gradient-via-position: ; --tw-gradient-to-position: ; --tw-ordinal: ; --tw-slashed-zero: ; --tw-numeric-figure: ; --tw-numeric-spacing: ; --tw-numeric-fraction: ; --tw-ring-inset: ; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: #fde04766; --tw-ring-offset-shadow: var(--tw-ring-inset)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color); --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; --tw-blur: ; --tw-brightness: ; --tw-contrast: ; --tw-grayscale: ; --tw-hue-rotate: ; --tw-invert: ; --tw-saturate: ; --tw-sepia: ; --tw-drop-shadow: ; --tw-backdrop-blur: ; --tw-backdrop-brightness: ; --tw-backdrop-contrast: ; --tw-backdrop-grayscale: ; --tw-backdrop-hue-rotate: ; --tw-backdrop-invert: ; --tw-backdrop-opacity: ; --tw-backdrop-saturate: ; --tw-backdrop-sepia: ; --tw-contain-size: ; --tw-contain-layout: ; --tw-contain-paint: ; --tw-contain-style: ; cursor: pointer; text-underline-offset: 3px; border-radius: 0.25rem; text-decoration: underline; background-color: rgba(253, 224, 71, 0.4); box-shadow: var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000); color: rgb(68, 64, 60); font-family: InterVariable, Inter, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal;">Olympic swimming</span><span style="color: rgb(68, 64, 60); font-family: InterVariable, Inter, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;"><span> </span>rivals,</span>
这是 Firefox 放入剪贴板的内容:
were once <span class="annotation">Olympic swimming</span> rivals
这几乎就是原始 HTML 的样子。
有没有办法不将样式复制到剪贴板中?或者至少更改它以便不选择下划线样式?
我注意到 Chrome 在将 html 复制到剪贴板时添加了额外的样式可能是一个相关的问题
我已经尝试将
text-decoration
更改为使用 border-bottom
的内容,但这会破坏我的应用程序中的其他样式并且无法使用,与使用 ::after
标签的组合相同。
每当将某些文本复制到剪贴板时,我们可以防止默认行为并自己实现复制功能。例如,我们可以获取选定的文本,将其克隆到某个地方,根据需要更新样式,然后使用这个问题中的基本方法将该 HTML 复制到剪贴板。
document.addEventListener("copy", (event) => {
const selection = document.getSelection().getRangeAt(0).cloneContents();
recursivelyUpdateStyles(selection);
const result = document.createElement("div");
result.append(selection);
event.preventDefault();
event.clipboardData.setData("text/html", result.innerHTML);
});
function recursivelyUpdateStyles(node) {
for (const child of node.childNodes) {
if (child.nodeType !== Node.ELEMENT_NODE) continue;
child.style.textDecoration = "none";
recursivelyUpdateStyles(child);
}
}
.underline {
text-decoration: underline;
}
.red {
color: #f00;
}
Some text <span class="underline">with underline</span> and <span class="red">formatting</span> to copy.
<br><br>
<div contenteditable="true">Try pasting here</div>