const NodeType= {
Empty : 'Empty',
Text : 'Text',
PlainText : 'PlainText',
Bold : 'Bold',
View :'View',
Image : 'Image',
Touch : 'Touch',
OldTouch : 'OldTouch',
Custom : 'Custom',
}
const NodeAliasMap = {
font: NodeType.Text,
b: NodeType.Bold,
view: NodeType.View,
div: NodeType.View,
i: NodeType.Image,
touch: NodeType.Touch,
a: NodeType.OldTouch,
c: NodeType.OldTouch,
custom: NodeType.Custom,
}
function newNode (type= NodeType.Empty, props = {}, children=[]) {
return {
type,
props,
children,
}
}
const parseOpenTag = (input) => {
input = input.trim()
let res = /^(\w+)\s*/.exec(input)
if (res) {
const tagName = res[1]
const tagType = NodeAliasMap[tagName] || NodeType[tagName] || NodeType.Empty
const props = {}
input = input.slice(res[0].length)
while (input) {
res = /^(\w+)\s+/.exec(input)
if (res) {
const key = res[1]
props[key] = true
input = input.slice(res[0].length)
continue
}
res = /^(\w+)$/.exec(input)
if (res) {
const key = res[1]
props[key] = true
break
}
res = /^(\w+)=([^'"`\s]+)\s*/.exec(input)
if (res) {
const key = res[1]
let value = res[2]
try {
value = JSON.parse(value)
} catch (error) {}
props[key] = value
input = input.slice(res[0].length)
continue
}
res = /^(\w+)='(\{.*?\})'\s*/.exec(input)
if (res) {
const key = res[1]
const value = res[2]
props[key] = value
input = input.slice(res[0].length)
continue
}
res = /^(\w+)='([^']*)'\s*/.exec(input)
if (res) {
const key = res[1]
const value = res[2]
props[key] = value
input = input.slice(res[0].length)
continue
}
res = /^(\w+)="(\{.*?\})"\s*/.exec(input)
if (res) {
const key = res[1]
const value = res[2]
props[key] = value
input = input.slice(res[0].length)
continue
}
res = /^(\w+)="([^"]*)"\s*/.exec(input)
if (res) {
const key = res[1]
const value = res[2]
props[key] = value
input = input.slice(res[0].length)
continue
}
res = /^(\w+)=`([^`]*)`\s*/.exec(input)
if (res) {
const key = res[1]
let value = res[2]
try {
value = JSON.parse(value)
} catch (error) {}
props[key] = value
input = input.slice(res[0].length)
continue
}
break
}
return newNode(tagType, props)
}
return newNode()
}
function _parse (
input,
parentNode,
isFirstRecursion // 是否是第一次递归
) {
let startIndex = 0
let index = 0
while (index < input.length) {
const char = input.charAt(index)
if (char === '<') {
let node
let subIndex = index + 1
while (subIndex < input.length) {
const subChar = input.charAt(subIndex)
if (subChar === '>') {
const str = input.slice(startIndex, index)
if (str) {
node = newNode(NodeType.PlainText, {
text: str,
})
parentNode.children.push(node)
}
const tagStr = input.slice(index + 1, subIndex)
if (input.charAt(index + 1) === '/') {
if (!isFirstRecursion) {
return {
node: parentNode,
parsedInput: input.slice(0, subIndex + 1),
}
}
node = null
startIndex = subIndex + 1
} else if (tagStr[tagStr.length - 1] === '/') {
node = parseOpenTag(tagStr.slice(0, tagStr.length - 1))
startIndex = subIndex + 1
} else {
node = parseOpenTag(tagStr)
const { parsedInput } = _parse(input.slice(subIndex + 1), node, false)
subIndex += parsedInput.length
startIndex = subIndex + 1
}
break
} else if (subChar === '<') {
node = newNode(NodeType.PlainText, {
text: input.slice(startIndex, subIndex),
})
startIndex = subIndex
subIndex--
break
}
subIndex++
}
if (node) {
parentNode.children.push(node)
index = subIndex
}
}
index++
}
const str = input.slice(startIndex, index)
if (str) {
const node = newNode(NodeType.PlainText, {
text: str,
})
parentNode.children.push(node)
}
return {
node: parentNode,
parsedInput: input.slice(0, index),
}
}
function parse (input) {
if (!input) return null
input = input.replace(/<br\s*\/?>/gi, '\n')
const node = _parse(input, newNode(NodeType.Empty), true).node
if (node.type === NodeType.Empty && node.children.length === 1) {
return node.children[0]
}
return node
}
let stra='<view style=`{"display": "flex","flexDirection": "row"}`><font color=#999999 size=13 numberOfLines=1>货主接通成功后扣</font><i uri="https://imagecdn.ymm56.com/ymmfile/static/resource/b4b2de00-f30c-4e5e-8b3f-aa8621680643.png" defaultSize=`{"width": 20,"height": 20}` style=`{"width": 19,"height": 19}` resizeStyle="fix-height" /><font color=#FA871E size=13 style=`{ "marginLeft" : -2 }`>{{ copyData }}</font><font color=#999999 size=13 numberOfLines=1>,抢单不重复扣豆</font></view>'
let ss= '<font color=#999999 size=13 numberOfLines=1>货主接通成功后扣</font><i uri="https://imagecdn.ymm56.com/ymmfile/static/resource/b4b2de00-f30c-4e5e-8b3f-aa8621680643.png" defaultSize=`{"width": 20,"height": 20}` style=`{"width": 19,"height": 19}` resizeStyle="fix-height" /><font color=#FA871E size=13 style=`{ "marginLeft" : -2 }`>{{ copyData }}</font><font color=#999999 size=13 numberOfLines=1>,抢单不重复扣豆</font>'
let res=parse(ss)
console.log(ss)
console.log(JSON.stringify(ss))
console