如何用HTML包裹字符串局部内容实现代码自定义着色?
问题
我想在<code>元素中渲染按钮的HTML标记,同时用不同的<span>元素给代码的特定部分加颜色(比如尖括号设为蓝色,引号设为绿色)。
用正则表达式和HTML字符编码处理后,现在能包裹目标内容,但遇到了瓶颈:生成的<span>被浏览器解析成了真实的HTML元素,而我需要这些<span>作为代码字符串的高亮容器——准确来说,是让<span>实现语法高亮,同时里面的代码内容能正确显示成HTML标记。
当前生成的错误输出如下:
<span class="chev"><<span>button id=<span class="quote">"">"<<span>btn<span class="quote">"">"<<span> class=<span class="quote">"">"<<span>btn btn-primary tru-btn<span class="quote">"">"<<span> data-value=<span class="quote">"">"<<span>btn-primary<span class="quote">"">"<<span> type=<span class="quote">"">"<<span>button<span class="quote">"">"<<span><span class="chev">><<span>Button<span class="chev"><<span>/button<span class="chev">><<span>
当前代码
JavaScript
generateHTMLBlock = () => { let someButton = document.querySelector('div').innerHTML, modBtnCode = someButton.replace(/^.\s+|\s+$/gm, ''), btnMarkup = modBtnCode.replace(/(.{100})/g, "$1\r"); encodeElement = (output) => { return output.replace(/</g, '<span class="chev">&#60;<span>') .replace(/>/g, '<span class="chev">&#62;<span>') .replace(/"/g, '<span class="quote">&#34;</span>'); let code = encodeElement(btnMarkup); document.getElementsByTagName('code').appendChild(code); };
CSS
.btn-primary:not(disabled):not(.disabled), .btn-secondary:not(disabled):not(.disabled) { box-sizing: border-box; display: flex; align-items: center; max-width: fit-content; padding: 0.338rem 1.5rem; margin: 0; overflow: hidden; background: black; border-radius: .625rem; border-width: .125rem; border: 1px solid transparent; border-color: black; box-shadow: none; font-family: arial; color: white; font-size: 16px; font-weight: 400; text-align: center; vertical-align: middle; text-transform: none; user-select: none; line-height: 2.2rem; letter-spacing: .25px; text-decoration: none !important; cursor: pointer; transition: all .3s ease-in-out; } pre { padding: 1rem; margin-bottom: 0; width: 100%; height: 6em; } code { display: block; color: black; width: 100%; height: 100%; border: 1px solid red; } .quote { color: green; } .chev { color: blue; }
HTML
<div> <button id="btn" class="btn btn-primary" data-value="btn-primary" type="button">Button</button> </div> <pre> <code></code> </pre>
解决方案
问题出在编码逻辑搞反了:你需要先把原始HTML转成实体,再用真实的<span>包裹这些实体,而不是把<span>也转成实体。正确步骤如下:
- 转义原始HTML:先把按钮的HTML代码转成HTML实体,确保浏览器把它们当作文本显示,而非真实标签。
- 添加高亮容器:对转义后的实体(比如
<、>、")进行替换,用真实的<span>标签包裹,让浏览器解析这些span来应用颜色样式。 - 插入到code元素:把处理后的HTML字符串作为
innerHTML插入,而非创建文本节点。
修改后的JavaScript代码:
generateHTMLBlock = () => { // 获取按钮的HTML代码 let someButton = document.querySelector('div').innerHTML; // 去除首尾空白 let modBtnCode = someButton.replace(/^\s+|\s+$/gm, ''); // 第一步:转义原始HTML为实体 let escapedMarkup = modBtnCode .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"'); // 第二步:用span包裹需要高亮的实体 let highlightedCode = escapedMarkup .replace(/</g, '<span class="chev"><</span>') .replace(/>/g, '<span class="chev">></span>') .replace(/"/g, '<span class="quote">"</span>'); // 第三步:插入到code元素中 document.querySelector('code').innerHTML = highlightedCode; }; // 调用函数 generateHTMLBlock();
说明
- 先转义:把
<>和"转成对应的HTML实体,确保原始代码以文本形式展示。 - 再包裹:用带样式类的span包裹这些实体,让浏览器解析span并应用颜色。
- 用
innerHTML插入:既保留span的样式效果,又能正确显示HTML代码内容。
这样处理后,<code>元素里会正确显示按钮的HTML代码,同时尖括号为蓝色、引号为绿色,完全符合需求。
内容的提问来源于stack exchange,提问作者Eric Guest
相关产品推荐
相关产品推荐

