如何开发支持符号高亮的语法高亮器,现有转义问题求解决
所需学习的核心技术
- 正则表达式进阶:贪婪/非贪婪匹配、零宽断言、分组捕获、特殊字符转义规则
- HTML基础:实体编码/解码规则、
textContent/innerHTML/innerText的属性差异 - 基础词法分析逻辑:语法单元优先级处理规则(长匹配优先、高优先级语法单元(字符串、注释)先处理)
现有问题的解决方法
1. HTML实体转义异常问题
你用innerHTML读取内容时,拿到的是已经被浏览器转义后的编码内容,比如<会被转成<,后续匹配时就会把&、;当成独立符号处理,自然出现异常。
解决办法:读取内容时用textContent属性,直接拿到未经过转义的原始纯文本,处理完成后再赋值给innerHTML渲染即可。
2. 高亮逻辑冲突问题
你当前的替换顺序完全颠倒了优先级:先替换短字符的符号,后续再添加字符串高亮逻辑时,字符串首尾的引号已经被<span>标签包裹,正则无法匹配到完整的字符串区间,必然出现异常。
正确的替换顺序需要遵循「长匹配优先、高优先级单元优先」的规则:
- 先处理长语法单元:字符串、注释
- 再处理中等长度单元:关键字、数字
- 最后处理短单元:独立符号
另外还要注意添加匹配限制,避免正则匹配到你插入的<span>标签内部的字符,破坏标签结构。
修正后的可用示例代码
function syntaxue(){ const codes = document.getElementsByClassName("syntaxue"); for (let i = 0; i < codes.length; i++){ // 读取原始未转义的文本 let raw = codes[i].textContent; // 1. 先高亮双引号、单引号字符串,支持转义引号 raw = raw.replace(/("(?:\\.|[^"\\])*")/g, '<span class="str">$1</span>'); raw = raw.replace(/('(?:\\.|[^'\\])*')/g, '<span class="str">$1</span>'); // 2. 高亮数字 raw = raw.replace(/(\d+\.?\d*)/g, '<span class="num">$1</span>'); // 3. 高亮指定符号,零宽断言避免匹配span标签内的字符 raw = raw.replace(/(?![^<]*>)([{(<\/!&|>\])};.,:=+*\-@$~_^?%'"])/g, '<span class="sym">$1</span>'); // 渲染结果 codes[i].innerHTML = raw; } }
拓展提示
如果后续需要支持更复杂的语法(比如HTML标签、多行注释、模板字符串),不建议继续用正则堆叠实现,正则仅适合简单场景的高亮需求。复杂场景可以自己实现简易词法分析器,把原始文本拆分为类型明确的token(字符串、数字、符号、关键字等),再逐个渲染对应样式,逻辑会更清晰,也不会出现匹配冲突问题。
内容的提问来源于stack exchange,提问作者Front Cutted
相关产品推荐
相关产品推荐

