From 7dc4d54865ec652abdffebcb9ef2fd88f75bc631 Mon Sep 17 00:00:00 2001 From: liguanpingdev <53906298+liguanpingdev@users.noreply.github.com> Date: Thu, 8 Aug 2019 22:56:25 +0800 Subject: [PATCH] Create rich-text.js --- .../runtime/components/rich-text.js | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 src/platforms/app-plus-nvue/runtime/components/rich-text.js diff --git a/src/platforms/app-plus-nvue/runtime/components/rich-text.js b/src/platforms/app-plus-nvue/runtime/components/rich-text.js new file mode 100644 index 000000000..043a150cb --- /dev/null +++ b/src/platforms/app-plus-nvue/runtime/components/rich-text.js @@ -0,0 +1,180 @@ +import { + cached, + normalizeUnit +} from '../helpers/index' + +const parseStyleText = cached(function (cssText) { + const res = {} + const listDelimiter = /;(?![^(]*\))/g + const propertyDelimiter = /:(.+)/ + cssText.split(listDelimiter).forEach(function (item) { + if (item) { + const tmp = item.split(propertyDelimiter) + tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim()) + } + }) + return res +}) + +function parseStyle (node, ctx) { + const styles = Object.create(null) + + if (!node.attrs) { + return styles + } + + const classList = (node.attrs.class || '').split(' ') + + const cssMap = ctx.$options.style || {} + + classList.forEach(name => { + if (name && cssMap[name]) { + Object.assign(styles, cssMap[name]) + } + }) + + Object.assign(styles, parseStyleText(node.attrs.style || '')) + + return styles +} + +const TAGS = ['span', 'a', 'image', 'img'] + +function block (node) { + node.attr.value = (node.attr.value || '') + '\n' + return node +} + +function heading (node, em, options) { + !node.style.fontSize && (node.style.fontSize = options.defaultFontSize * em) + return block(bold(node)) +} + +function createHeading (em) { + return function (node, options) { + return heading(node, em, options) + } +} + +function bold (node) { + !node.style.fontWeight && (node.style.fontWeight = 'bold') + return node +} + +const strategies = { + 'blockquote': block, + 'br': block, + 'div': block, + 'dl': block, + 'h1': createHeading(2), + 'h2': createHeading(1.5), + 'h3': createHeading(1.17), + 'h4': createHeading(1), + 'h5': createHeading(0.83), + 'h6': createHeading(0.67), + 'hr': block, + 'ol': block, + 'p': block, + 'strong': bold, + 'table': block, + 'tbody': block, + 'tfoot': block, + 'thead': block, + 'ul': block +} + +const HTML_RE = /&(amp|gt|lt|nbsp|quot|apos);/g + +const CHARS = { + 'amp': '&', + 'gt': '>', + 'lt': '<', + 'nbsp': ' ', + 'quot': '"', + 'apos': "'" +} + +function normalizeText (str) { + return str.replace(HTML_RE, function (match, entity) { + return CHARS[entity] + }) +} + +function normalizeNode (node, ctx, options) { + let type = (node.name || '').toLowerCase() + + const strategy = strategies[type] + + if (TAGS.indexOf(type) === -1) { + type = 'span' + } + if (type === 'img') { + type = 'image' + } + const nvueNode = { + type, + attr: Object.create(null) + } + + if (node.type === 'text' || node.text) { + nvueNode.attr.value = normalizeText((node.text || '').trim()) + } + + if (node.attrs) { + Object.keys(node.attrs).forEach(name => { + if (name !== 'class' && name !== 'style') { + nvueNode.attr[name] = node.attrs[name] + } + }) + } + + nvueNode.style = normalizeUnit(parseStyle(node, ctx)) + + if (strategy) { + strategy(nvueNode, options) + } + + nvueNode.children = normalizeNodes(node.children, ctx, options) + + return nvueNode +} + +function normalizeNodes (nodes, ctx, options) { + if (Array.isArray(nodes)) { + return nodes.map(node => normalizeNode(node, ctx, options)) + } + return [] +} + +function getRichText (weex) { + const { + scale, + deviceWidth + } = weex.config.env + const defaultFontSize = deviceWidth / scale / 20 + return { + props: { + nodes: { + type: [Array, String], + default: function () { + return [] + } + } + }, + render (createElement) { + // TODO 待处理 String 类型 + const nodes = normalizeNodes(this.nodes || [], this.$vnode.context, { + defaultFontSize + }) + return createElement('u-rich-text', this._g({ + attrs: { + value: nodes + } + }, this.$listeners)) + } + } +} + +export default function init (Vue, weex) { + Vue.component('rich-text', getRichText(weex)) +} -- GitLab