解析HTML字符串成AST树
网友投稿
897
2022-10-28
解析HTML字符串成AST树
1. 如何将一个字符传转换成一个AST树结构。
直接上代码:
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`const qnameCapture = `((?:${ncname}\\:)?${ncname})`// 匹配 />const startTagClose = /^\s*(\/?)>/// 匹配
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)const doctype = /^]+>/i//注意树形的html 只能有一个根节点function parseHtmlToAst(html){ let text,root,currentParent,stack=[]; while(html){ let textEnd=html.indexOf("<"); if(textEnd===0){ //查找开始tag const startTagMatch=parseStartTag(); if(startTagMatch){ //生成AST树 start(startTagMatch.tagName,startTagMatch.attrs); continue; } //查找结束标签 const endTagMatch=html.match(endTag); if(endTagMatch){ advance(endTagMatch[0].length); //构造ast树 end(endTagMatch[1]); continue; } } //文本节点 if(textEnd>0){ text=html.substring(0,textEnd); } if(text){ //截取字符串 advance(text.length); chars(text); } } //截些开始标记 function parseStartTag(){ const start=html.match(startTagOpen); let end,attr; //找到开始标记 if(start){ const match={ tagName:start[1], attrs:[] } advance(start[0].length) //配置属性 while(!(end=html.match(startTagClose)) && (attr=html.match(attribute))){ match.attrs.push({ name:attr[1], value: attr[3] || attr[4] || attr[5] }) advance(attr[0].length); } //匹配结束字符 > 或 /> if(end){ advance(end[0].length); return match; } } } //截取字符串 function advance (n) { html = html.substring(n) } //构造AST树形 function start(tagName,attrs){ const element=createAstElement(tagName,attrs); if(!root){ root=element; } currentParent=element; stack.push(element); } //结束钩爪树形 function end(tagName){ const element=stack.pop(); currentParent=stack[stack.length-1]; if(currentParent){ element.parent=currentParent; currentParent.children.push(element); } } //处理文本节点 function chars(text){ text=text.trim(); if(text.length>0){ currentParent.children.push({ type:3, text }) } } function createAstElement(tagName,attrs){ return { tag: tagName, type: 1, children:[], attrs, parent } } return root;}let html=`
你好:{{name}} {{age}}
`;let root=parseHtmlToAst(html);console.info(root)
代码的逻辑是:
对字符串的处理,从头开始处理,先找 < 开头的字符,如果找到则用 正则表达式查找
或 />字符为止,找到让后截取后面的字符串。
中间用到了堆栈作为树节点作为串联。
2.构造结果
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~