Просмотр исходного кода

feat(weex): support nested components in richtext

Hanks 9 лет назад
Родитель
Сommit
0ea2bb4fb4

+ 32 - 21
src/platforms/weex/runtime/components/richtext.js

@@ -1,17 +1,3 @@
-function parseChildren (h, options) {
-  const children = options._renderChildren
-  if (!children) {
-    return []
-  }
-
-  return children.map(vnode => {
-    if (!vnode.tag && vnode.text) {
-      return h('span', vnode.text)
-    }
-    return vnode
-  })
-}
-
 function getVNodeType (vnode) {
   const tagName = vnode.tag
   if (!tagName) {
@@ -20,6 +6,14 @@ function getVNodeType (vnode) {
   return tagName.replace(/vue\-component\-(\d+\-)?/, '')
 }
 
+function isSimpleSpan (vnode) {
+  return vnode.children && vnode.children.length === 1 && !vnode.children[0].tag
+}
+
+function trimCSSUnit (prop) {
+  return Number(prop.replace(/px$/i, '')) || prop
+}
+
 function convertVNodeChildren (children) {
   if (!children.length) {
     return
@@ -28,15 +22,34 @@ function convertVNodeChildren (children) {
     const type = getVNodeType(vnode)
     const props = { type }
 
-    // TODO: filter
+    // convert raw text node
+    if (!type) {
+      props.type = 'span'
+      props.attr = {
+        value: (vnode.text || '').trim()
+      }
+    }
+
     if (vnode.data) {
       props.style = vnode.data.staticStyle
       props.attr = vnode.data.attrs
+
+      // TODO: convert inline styles
+      if (props.style) {
+        for (const key in props.style) {
+          props.style[key] = trimCSSUnit(props.style[key])
+        }
+      }
+    }
+
+    if (type === 'span' && isSimpleSpan(vnode)) {
+      props.attr = props.attr || {}
+      props.attr.value = vnode.children[0].text.trim()
+      return props
     }
 
-    if (type === 'span') {
-      props.attr = {}
-      props.attr.value = vnode.text || vnode.children.map(c => c.text).join('').trim()
+    if (vnode.children && vnode.children.length) {
+      props.children = convertVNodeChildren(vnode.children)
     }
 
     return props
@@ -47,11 +60,9 @@ export default {
   name: 'richtext',
   abstract: true,
   render (h) {
-    const children = parseChildren(h, this.$options)
-    const values = convertVNodeChildren(children)
     return h('weex:richtext', {
       attrs: {
-        value: values
+        value: convertVNodeChildren(this.$options._renderChildren || [])
       }
     })
   }

+ 28 - 13
test/weex/runtime/component/richtext.spec.js

@@ -57,8 +57,6 @@ describe('richtext component', () => {
   })
 
   describe('span', () => {
-    // pending('work in progress')
-
     it('single node', () => {
       expect(compileSnippet(runtime, `
         <richtext>
@@ -126,8 +124,6 @@ describe('richtext component', () => {
   })
 
   describe('a', () => {
-    // pending('work in progress')
-
     it('single node', () => {
       expect(compileSnippet(runtime, `
         <richtext>
@@ -166,8 +162,6 @@ describe('richtext component', () => {
   })
 
   describe('image', () => {
-    pending('work in progress')
-
     it('single node', () => {
       expect(compileSnippet(runtime, `
         <richtext>
@@ -185,7 +179,6 @@ describe('richtext component', () => {
     })
 
     it('multiple node', () => {
-      // pending('work in progress')
       expect(compileSnippet(runtime, `
         <richtext>
           <image src="path/to/A.png"></image>
@@ -218,7 +211,7 @@ describe('richtext component', () => {
         attr: {
           value: [{
             type: 'image',
-            style: { width: '150px', height: '150px' },
+            style: { width: 150, height: 150 },
             attr: { src: 'path/to/profile.png' }
           }]
         }
@@ -227,8 +220,6 @@ describe('richtext component', () => {
   })
 
   describe('nested', () => {
-    pending('work in progress')
-
     it('span', () => {
       expect(compileSnippet(runtime, `
         <richtext>
@@ -273,7 +264,7 @@ describe('richtext component', () => {
         <richtext>
           <span>title</span>
           <a href="http://remote.com/xx.js">
-            <span>name</span>
+            <span><span>name</span></span>
             <image src="path/to/yy.gif"></image>
           </a>
         </richtext>
@@ -288,7 +279,10 @@ describe('richtext component', () => {
             attr: { href: 'http://remote.com/xx.js' },
             children: [{
               type: 'span',
-              attr: { value: 'name' }
+              children: [{
+                type: 'span',
+                attr: { value: 'name' }
+              }]
             }, {
               type: 'image',
               attr: { src: 'path/to/yy.gif' }
@@ -300,6 +294,27 @@ describe('richtext component', () => {
   })
 
   describe('with styles', () => {
-    pending('work in progress')
+    // pending('work in progress')
+    it('inline', () => {
+      expect(compileSnippet(runtime, `
+        <richtext>
+          <span style="font-size:16px;color:#FF6600;">ABCD</span>
+          <image style="width:40px;height:60px" src="path/to/A.png"></image>
+        </richtext>
+      `)).toEqual({
+        type: 'richtext',
+        attr: {
+          value: [{
+            type: 'span',
+            style: { fontSize: 16, color: '#FF6600' },
+            attr: { value: 'ABCD' }
+          }, {
+            type: 'image',
+            style: { width: 40, height: 60 },
+            attr: { src: 'path/to/A.png' }
+          }]
+        }
+      })
+    })
   })
 })