使用正则内部的逻辑短路匹配之一举多得
用多分支来排除,像if-else那样不用写出完全的条件。
小而广的条件有时不仅能匹配到最终目标,而且还能锦上添花(一举多得):
regexp = /str|regexp|lineannotaion|blockannotation|tampstring/g
let tmp='', str = `
${tmp+'\`'+"${}"+
`${tmp}`+ /*A*/
(tmp={'a':/(?<!x`)/g}["a"]) //B
}'c' \" <d> & // e /*f*/`, // g
reg = /(?<!\\)\/(?![^\/\*])[\s\S]+?(?<!\\)\//g;
//*/ h
str; reg = /c/g, str = ``
/*/ j
k //KK
//*/
str = "\"http://'xxxx'\/\"";
str = `.replace(/&/g, '&').replace(/</g, '<').replace(/\u00a0/g, ' ')${`l`+str}`
str = '\
\' //n"`\
' /* // */
匹配任意字符
/[\s\S]/g
/[^]/g
匹配单行注释
/\/\/.*/g
匹配多行注释
/\/\*[^]*?\*\//g
匹配字符串
/('|"|`)[^]*?(?<!\\)\1/g
/''|``|""|('|"|`)[^]*?[^\\]\1/g
/''|""|('|")[^]*?[^\\]\1|`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/g
字符串模板${}内部可能还会出现字符串模板和正则表达式内存在未转义的\`
书写简单的字符串模板时使用第二个正则表达式应该是没大问题的
匹配正则表达式
/\/.*?[^\\]\//g
替换需要转义的字符
.replace(/&|<|\u00a0/g,m=>
m =='&' ? "&"
: m=='<' ? "<"
: /\u00a0/.test(m)
? ' ' : m
)
基本实现
CODE_JAVASCRIPT
.replace(/&|<|\u00a0/g,m=> // 匹配需要转义的HTML符号
m =='&' ? "&" : m=='<' ? "<" : /\u00a0/.test(m) ? ' ' : m
)
.replace(
// /\/\/.*|\/\*[^]*?\*\/|''|``|""|('|"|`)[^]*?[^\\]\1|\/.*?[^\\]\//g, // ${}内部不能再嵌套模板字符串,内部使用正则时要转义`,像这样 ${"helo".match(/\`/)[0]}
/\/\/.*|\/\*[^]*?\*\/|\/.*?[^\\]\/|''|""|('|")[^]*?[^\\]\1|`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/g,
(m,a,b,c,d,e,f,g)=>{
// return /\/\*|\/\//.test(m.slice(0, 2))
return m.slice(0,2) == "//" || m.slice(0,2) == "/*"
// ? (!b || /\r|\n/.test(c[b-1]) ? "<span class=\"annotation\">"+m+"</span>" : "<span class=\"annotation-sub\">"+m+"</span>")
? "<span class=\"annotation\">"+m+"</span>"
: m
})
测试版
<link rel="icon" href="data:base64">
<title>CL Testy</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<body>
<textarea style="white-space:pre;width:100%;height:400px"></textarea>
<pre style="padding:0.5em;background:rgba(0,0,0,0.05);overflow:scroll;scrollbar-width:none"></pre>
<article></article>
<script>"use strict";
let PXHR=(e,t=!0)=>{return new Promise((n,s)=>{let a=new XMLHttpRequest;a.onreadystatechange=(()=>{4==a.readyState&&(200==a.status||304==a.status?n(a):s(a))}),a.open("GET",e,t),a.send()})},
$ = s => document.querySelector(s),
_ = s => s.replace(/\/\/.*|\/\*[^]*?\*\/|\/.*?[^\\]\/|''|""|('|")[^]*?[^\\]\1|`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/g, (m,a,b,c)=>{
return /\/\*|\/\//.test(m.slice(0, 2)) ?
( !b || /\r|\n/.test(c[b-1])
? "<span class=\"annotation\">"+m+"</span>"
: "<span class=\"annotation-sub\">"+m+"</span>"
)
:a={
'\'':"<span class=char>"+m+"</span>",
'\"':"<span class=string>"+m+"</span>",
'/' :"<span class='regexp'>"+m+"</span>",
'\`':"<span class='blockstr'>"+m+"</span>"
}[m[0]] || m
}),
__= s => s.replace(/&|<|\u00a0/g,m=> m=='&' ? "&" : m=='<' ? "<" : /\u00a0/.test(m) ? ' ' : m);
PXHR(location.origin+"/testy.js").then( res =>{
document.querySelector("pre").innerHTML
= $("textarea").value
= _(__(res.responseText))
})
PXHR(location.origin+"/testy.md").then( res =>{
document.querySelector("article").innerHTML
= marked(res.responseText);
document.querySelector(".language-js").innerHTML
= _(__(document.querySelector(".language-js").textContent))
})
</script>
</body></html>
<style>
.annotation{background:#62a562}
.annotation-sub{background:#ccc}
.char{background:skyblue}
.string{background:rgb(172, 134, 172)}
.blockstr{background:orange}
.regexp{background:pink}
</style>
测试的js和md文件
let tmp='', str = `
${tmp+'\`'+"${}"+
`${tmp}`+ /*A*/
(tmp={'a':/(?<!x`)/g}["a"]) //B
}'c' \" <d> & // e /*f*/`, // g
reg = /(?<!\\)\/(?![^\/\*])[\s\S]+?(?<!\\)\//g;
//*/ h
str; reg = /c/g, str = ``
/*/ j
k //KK
//*/
str = "\"https://'crawly.top'\/\"";
str = `.replace(/&/g, '&').replace(/</g, '<').replace(/\u00a0/g, ' ')${`l`+str}`
str = '\
\' //n"`\
' /* // */
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。