| | |
| | | 'use strict' |
| | | |
| | | /**
|
| | | * @fileoverview html 解析器
|
| | | /** |
| | | * @fileoverview html 解析器 |
| | | */ |
| | | // 配置 |
| | | const config = { |
| | |
| | | config.ignoreTags.source = void 0 |
| | | config.ignoreTags.style = void 0 // #endif |
| | | |
| | | /**
|
| | | * @description 创建 map
|
| | | * @param {String} str 逗号分隔
|
| | | /** |
| | | * @description 创建 map |
| | | * @param {String} str 逗号分隔 |
| | | */ |
| | | |
| | | function makeMap(str) { |
| | |
| | | |
| | | return map |
| | | } |
| | | /**
|
| | | * @description 解码 html 实体
|
| | | * @param {String} str 要解码的字符串
|
| | | * @param {Boolean} amp 要不要解码 &
|
| | | * @returns {String} 解码后的字符串
|
| | | /** |
| | | * @description 解码 html 实体 |
| | | * @param {String} str 要解码的字符串 |
| | | * @param {Boolean} amp 要不要解码 & |
| | | * @returns {String} 解码后的字符串 |
| | | */ |
| | | |
| | | function decodeEntity(str, amp) { |
| | |
| | | |
| | | return str |
| | | } |
| | | /**
|
| | | * @description html 解析器
|
| | | * @param {Object} vm 组件实例
|
| | | /** |
| | | * @description html 解析器 |
| | | * @param {Object} vm 组件实例 |
| | | */ |
| | | |
| | | function parser(vm) { |
| | |
| | | this.stack = [] |
| | | this.nodes = [] |
| | | } |
| | | /**
|
| | | * @description 执行解析
|
| | | * @param {String} content 要解析的文本
|
| | | /** |
| | | * @description 执行解析 |
| | | * @param {String} content 要解析的文本 |
| | | */ |
| | | |
| | | parser.prototype.parse = function (content) { |
| | |
| | | |
| | | return this.nodes |
| | | } |
| | | /**
|
| | | * @description 将标签暴露出来(不被 rich-text 包含)
|
| | | /** |
| | | * @description 将标签暴露出来(不被 rich-text 包含) |
| | | */ |
| | | |
| | | parser.prototype.expose = function () { |
| | |
| | | item.c = 1 |
| | | } // #endif |
| | | } |
| | | /**
|
| | | * @description 处理插件
|
| | | * @param {Object} node 要处理的标签
|
| | | * @returns {Boolean} 是否要移除此标签
|
| | | /** |
| | | * @description 处理插件 |
| | | * @param {Object} node 要处理的标签 |
| | | * @returns {Boolean} 是否要移除此标签 |
| | | */ |
| | | |
| | | parser.prototype.hook = function (node) { |
| | |
| | | |
| | | return true |
| | | } |
| | | /**
|
| | | * @description 将链接拼接上主域名
|
| | | * @param {String} url 需要拼接的链接
|
| | | * @returns {String} 拼接后的链接
|
| | | /** |
| | | * @description 将链接拼接上主域名 |
| | | * @param {String} url 需要拼接的链接 |
| | | * @returns {String} 拼接后的链接 |
| | | */ |
| | | |
| | | parser.prototype.getUrl = function (url) { |
| | |
| | | |
| | | return url |
| | | } |
| | | /**
|
| | | * @description 解析样式表
|
| | | * @param {Object} node 标签
|
| | | * @returns {Object}
|
| | | /** |
| | | * @description 解析样式表 |
| | | * @param {Object} node 标签 |
| | | * @returns {Object} |
| | | */ |
| | | |
| | | parser.prototype.parseStyle = function (node) { |
| | |
| | | node.attrs.style = tmp |
| | | return styleObj |
| | | } |
| | | /**
|
| | | * @description 解析到标签名
|
| | | * @param {String} name 标签名
|
| | | * @private
|
| | | /** |
| | | * @description 解析到标签名 |
| | | * @param {String} name 标签名 |
| | | * @private |
| | | */ |
| | | |
| | | parser.prototype.onTagName = function (name) { |
| | | this.tagName = this.xml ? name : name.toLowerCase() |
| | | if (this.tagName == 'svg') this.xml = true // svg 标签内大小写敏感 |
| | | } |
| | | /**
|
| | | * @description 解析到属性名
|
| | | * @param {String} name 属性名
|
| | | * @private
|
| | | /** |
| | | * @description 解析到属性名 |
| | | * @param {String} name 属性名 |
| | | * @private |
| | | */ |
| | | |
| | | parser.prototype.onAttrName = function (name) { |
| | |
| | | this.attrs[name] = 'T' // boolean 型属性缺省设置 |
| | | } |
| | | } |
| | | /**
|
| | | * @description 解析到属性值
|
| | | * @param {String} val 属性值
|
| | | * @private
|
| | | /** |
| | | * @description 解析到属性值 |
| | | * @param {String} val 属性值 |
| | | * @private |
| | | */ |
| | | |
| | | parser.prototype.onAttrVal = function (val) { |
| | |
| | | if (name == 'style' || name == 'href') this.attrs[name] = decodeEntity(val, true) // 拼接主域名 |
| | | else if (name.includes('src')) this.attrs[name] = this.getUrl(decodeEntity(val, true)); else if (name) this.attrs[name] = val |
| | | } |
| | | /**
|
| | | * @description 解析到标签开始
|
| | | * @param {Boolean} selfClose 是否有自闭合标识 />
|
| | | * @private
|
| | | /** |
| | | * @description 解析到标签开始 |
| | | * @param {Boolean} selfClose 是否有自闭合标识 /> |
| | | * @private |
| | | */ |
| | | |
| | | parser.prototype.onOpenTag = function (selfClose) { |
| | |
| | | |
| | | siblings.push(node) |
| | | } |
| | | /**
|
| | | * @description 解析到标签结束
|
| | | * @param {String} name 标签名
|
| | | * @private
|
| | | /** |
| | | * @description 解析到标签结束 |
| | | * @param {String} name 标签名 |
| | | * @private |
| | | */ |
| | | |
| | | parser.prototype.onCloseTag = function (name) { |
| | |
| | | }) |
| | | } |
| | | } |
| | | /**
|
| | | * @description 处理标签出栈
|
| | | * @private
|
| | | /** |
| | | * @description 处理标签出栈 |
| | | * @private |
| | | */ |
| | | |
| | | parser.prototype.popNode = function () { |
| | |
| | | |
| | | attrs.style = attrs.style.substr(1) || void 0 |
| | | } |
| | | /**
|
| | | * @description 解析到文本
|
| | | * @param {String} text 文本内容
|
| | | /** |
| | | * @description 解析到文本 |
| | | * @param {String} text 文本内容 |
| | | */ |
| | | |
| | | parser.prototype.onText = function (text) { |
| | |
| | | siblings.push(node) |
| | | } |
| | | } |
| | | /**
|
| | | * @description html 词法分析器
|
| | | * @param {Object} handler 高层处理器
|
| | | /** |
| | | * @description html 词法分析器 |
| | | * @param {Object} handler 高层处理器 |
| | | */ |
| | | |
| | | function lexer(handler) { |
| | | this.handler = handler |
| | | } |
| | | /**
|
| | | * @description 执行解析
|
| | | * @param {String} content 要解析的文本
|
| | | /** |
| | | * @description 执行解析 |
| | | * @param {String} content 要解析的文本 |
| | | */ |
| | | |
| | | lexer.prototype.parse = function (content) { |
| | |
| | | this.state() |
| | | } |
| | | } |
| | | /**
|
| | | * @description 检查标签是否闭合
|
| | | * @param {String} method 如果闭合要进行的操作
|
| | | * @returns {Boolean} 是否闭合
|
| | | * @private
|
| | | /** |
| | | * @description 检查标签是否闭合 |
| | | * @param {String} method 如果闭合要进行的操作 |
| | | * @returns {Boolean} 是否闭合 |
| | | * @private |
| | | */ |
| | | |
| | | lexer.prototype.checkClose = function (method) { |
| | |
| | | |
| | | return false |
| | | } |
| | | /**
|
| | | * @description 文本状态
|
| | | * @private
|
| | | /** |
| | | * @description 文本状态 |
| | | * @private |
| | | */ |
| | | |
| | | lexer.prototype.text = function () { |
| | |
| | | } |
| | | } else this.i++ |
| | | } |
| | | /**
|
| | | * @description 标签名状态
|
| | | * @private
|
| | | /** |
| | | * @description 标签名状态 |
| | | * @private |
| | | */ |
| | | |
| | | lexer.prototype.tagName = function () { |
| | |
| | | } |
| | | } else if (!this.checkClose('onTagName')) this.i++ |
| | | } |
| | | /**
|
| | | * @description 属性名状态
|
| | | * @private
|
| | | /** |
| | | * @description 属性名状态 |
| | | * @private |
| | | */ |
| | | |
| | | lexer.prototype.attrName = function () { |
| | |
| | | } |
| | | } else if (!this.checkClose('onAttrName')) this.i++ |
| | | } |
| | | /**
|
| | | * @description 属性值状态
|
| | | * @private
|
| | | /** |
| | | * @description 属性值状态 |
| | | * @private |
| | | */ |
| | | |
| | | lexer.prototype.attrVal = function () { |
| | |
| | | this.state = this.attrName |
| | | } |
| | | } |
| | | /**
|
| | | * @description 结束标签状态
|
| | | * @returns {String} 结束的标签名
|
| | | * @private
|
| | | /** |
| | | * @description 结束标签状态 |
| | | * @returns {String} 结束的标签名 |
| | | * @private |
| | | */ |
| | | |
| | | lexer.prototype.endTag = function () { |