diff --git a/src/platforms/weex/runtime/components/richtext.js b/src/platforms/weex/runtime/components/richtext.js index 5ad6259750..ddfa3340ba 100644 --- a/src/platforms/weex/runtime/components/richtext.js +++ b/src/platforms/weex/runtime/components/richtext.js @@ -11,7 +11,28 @@ function isSimpleSpan (vnode) { } function trimCSSUnit (prop) { - return Number(prop.replace(/px$/i, '')) || prop + return Number(String(prop).replace(/px$/i, '')) || prop +} + +function parseStyle (vnode) { + const { staticStyle, staticClass } = vnode.data + if (vnode.data.style || vnode.data.class || staticStyle || staticClass) { + const styles = Object.assign({}, staticStyle, vnode.data.style) + + // TODO: more reliable + const cssMap = vnode.context.$options.style + const classList = [].concat(staticClass, vnode.data.class) + classList.forEach(name => { + if (name && cssMap[name]) { + Object.assign(styles, cssMap[name]) + } + }) + + for (const key in styles) { + styles[key] = trimCSSUnit(styles[key]) + } + return styles + } } function convertVNodeChildren (children) { @@ -31,15 +52,8 @@ function convertVNodeChildren (children) { } if (vnode.data) { - props.style = vnode.data.staticStyle + props.style = parseStyle(vnode) 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)) { diff --git a/test/weex/runtime/component/richtext.spec.js b/test/weex/runtime/component/richtext.spec.js index 41bbcefda4..20bc8be2a4 100644 --- a/test/weex/runtime/component/richtext.spec.js +++ b/test/weex/runtime/component/richtext.spec.js @@ -5,17 +5,17 @@ import { createInstance } from '../../helpers/index' -function compileSnippet (runtime, snippet) { +function compileSnippet (runtime, snippet, additional) { const { render, staticRenderFns } = compileAndStringify(`
${snippet}
`) const instance = createInstance(runtime, ` new Vue({ + el: 'body', render: ${render}, staticRenderFns: ${staticRenderFns}, - el: 'body' + ${additional} }) `) - const result = instance.getRealRoot().children[0] - return result + return instance.getRealRoot().children[0] } describe('richtext component', () => { @@ -57,6 +57,7 @@ describe('richtext component', () => { }) describe('span', () => { + // pending('work in progress') it('single node', () => { expect(compileSnippet(runtime, ` @@ -124,6 +125,7 @@ describe('richtext component', () => { }) describe('a', () => { + // pending('work in progress') it('single node', () => { expect(compileSnippet(runtime, ` @@ -162,6 +164,7 @@ describe('richtext component', () => { }) describe('image', () => { + // pending('work in progress') it('single node', () => { expect(compileSnippet(runtime, ` @@ -220,6 +223,7 @@ describe('richtext component', () => { }) describe('nested', () => { + // pending('work in progress') it('span', () => { expect(compileSnippet(runtime, ` @@ -296,6 +300,7 @@ describe('richtext component', () => { describe('with styles', () => { // pending('work in progress') it('inline', () => { + // pending('work in progress') expect(compileSnippet(runtime, ` ABCD @@ -316,5 +321,290 @@ describe('richtext component', () => { } }) }) + + it('class list', () => { + // pending('work in progress') + expect(compileSnippet(runtime, ` + + + ABCD + + `, ` + style: { + title: { color: '#FF6600' }, + large: { fontSize: 24 }, + icon: { width: 40, height: 60 } + } + `)).toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'image', + style: { width: 40, height: 60 }, + attr: { src: 'path/to/A.png' } + }, { + type: 'span', + style: { fontSize: 24, color: '#FF6600' }, + attr: { value: 'ABCD' } + }] + } + }) + }) + }) + + describe('data binding', () => { + // pending('work in progress') + it('simple', () => { + expect(compileSnippet(runtime, ` + + {{name}} + + `, `data: { name: 'ABCDEFG' }`)).toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'span', + attr: { value: 'ABCDEFG' } + }] + } + }) + }) + + it('nested', () => { + expect(compileSnippet(runtime, ` + + {{a}} + {{b}}{{c.d}} + {{e}} + + `, `data: { a: 'A', b: 'B', c: { d: 'CD' }, e: 'E' }`)) + .toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'span', + attr: { value: 'A' } + }, { + type: 'span', + children: [{ + type: 'span', + attr: { value: 'B' } + }, { + type: 'span', + attr: { value: 'CD' } + }] + }, { + type: 'span', + attr: { value: 'E' } + }] + } + }) + }) + + it('update', () => { + expect(compileSnippet(runtime, ` + + {{name}} + + `, ` + data: { name: 'default' }, + created: function () { + this.name = 'updated' + } + `)).toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'span', + attr: { value: 'updated' } + }] + } + }) + }) + + it('attribute', () => { + expect(compileSnippet(runtime, ` + + {{name}} + + `, ` + data: { + label: 'uid', + name: '10100' + } + `)).toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'span', + attr: { + label: 'uid', + value: '10100' + } + }] + } + }) + }) + + it('update attribute', () => { + expect(compileSnippet(runtime, ` + + {{name}} + + `, ` + data: { + label: 'name', + name: 'Hanks' + }, + created: function () { + this.label = 'uid'; + this.name = '10100'; + } + `)).toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'span', + attr: { + label: 'uid', + value: '10100' + } + }] + } + }) + }) + + it('inline style', () => { + expect(compileSnippet(runtime, ` + + ABCD + EFGH + + `, ` + data: { + styleObject: { fontSize: '32px', color: '#F6F660' }, + align: 'center' + } + `)).toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'span', + style: { fontSize: 32, color: '#F6F660' }, + attr: { value: 'ABCD' } + }, { + type: 'span', + style: { textAlign: 'center', color: 'red' }, + attr: { value: 'EFGH' } + }] + } + }) + }) + + it('class list', () => { + // pending('work in progress') + expect(compileSnippet(runtime, ` + + + ABCD + EFGH + + `, ` + style: { + title: { color: '#FF6600' }, + large: { fontSize: 24 }, + icon: { width: 40, height: 60 } + }, + data: { + classList: ['unknown'], + size: 'small' + }, + created: function () { + this.classList = ['icon']; + this.size = 'large'; + } + `)).toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'image', + style: { width: 40, height: 60 }, + attr: { src: 'path/to/A.png' } + }, { + type: 'span', + style: { fontSize: 24, color: '#FF6600' }, + attr: { value: 'ABCD' } + }, { + type: 'span', + style: { fontSize: 24, color: '#F6F0F4' }, + attr: { value: 'EFGH' } + }] + } + }) + }) + + it('update inline style', () => { + expect(compileSnippet(runtime, ` + + ABCD + EFGH + + `, ` + data: { + styleObject: { fontSize: '32px', color: '#F6F660' } + }, + created: function () { + this.styleObject = { fontSize: '24px', color: 'blue' } + this.styleObject.color = '#ABCDEF' + this.align = 'left' + } + `)).toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'span', + style: { fontSize: 24, color: '#ABCDEF' }, + attr: { value: 'ABCD' } + }, { + type: 'span', + style: { textAlign: 'left', color: 'red' }, + attr: { value: 'EFGH' } + }] + } + }) + }) + }) + + describe('bind events', () => { + pending('work in progress') + it('inline', () => { + const { render, staticRenderFns } = compileAndStringify(` +
+ + Button + +
+ `) + const instance = createInstance(runtime, ` + new Vue({ + el: 'body', + render: ${render}, + staticRenderFns: ${staticRenderFns}, + methods: { + handler: function () {} + } + }) + `) + expect(instance.getRealRoot().children[0]).toEqual({ + type: 'richtext', + attr: { + value: [{ + type: 'span', + events: { click: 'handler' }, + attr: { value: 'Button' } + }] + } + }) + }) }) })