Skip to content

Commit b609642

Browse files
Hanks10100yyx990803
authored andcommitted
feat(weex richtext): support to parse styles and classList
1 parent 0ea2bb4 commit b609642

File tree

2 files changed

+317
-13
lines changed

2 files changed

+317
-13
lines changed

src/platforms/weex/runtime/components/richtext.js

+23-9
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,28 @@ function isSimpleSpan (vnode) {
1111
}
1212

1313
function trimCSSUnit (prop) {
14-
return Number(prop.replace(/px$/i, '')) || prop
14+
return Number(String(prop).replace(/px$/i, '')) || prop
15+
}
16+
17+
function parseStyle (vnode) {
18+
const { staticStyle, staticClass } = vnode.data
19+
if (vnode.data.style || vnode.data.class || staticStyle || staticClass) {
20+
const styles = Object.assign({}, staticStyle, vnode.data.style)
21+
22+
// TODO: more reliable
23+
const cssMap = vnode.context.$options.style
24+
const classList = [].concat(staticClass, vnode.data.class)
25+
classList.forEach(name => {
26+
if (name && cssMap[name]) {
27+
Object.assign(styles, cssMap[name])
28+
}
29+
})
30+
31+
for (const key in styles) {
32+
styles[key] = trimCSSUnit(styles[key])
33+
}
34+
return styles
35+
}
1536
}
1637

1738
function convertVNodeChildren (children) {
@@ -31,15 +52,8 @@ function convertVNodeChildren (children) {
3152
}
3253

3354
if (vnode.data) {
34-
props.style = vnode.data.staticStyle
55+
props.style = parseStyle(vnode)
3556
props.attr = vnode.data.attrs
36-
37-
// TODO: convert inline styles
38-
if (props.style) {
39-
for (const key in props.style) {
40-
props.style[key] = trimCSSUnit(props.style[key])
41-
}
42-
}
4357
}
4458

4559
if (type === 'span' && isSimpleSpan(vnode)) {

test/weex/runtime/component/richtext.spec.js

+294-4
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ import {
55
createInstance
66
} from '../../helpers/index'
77

8-
function compileSnippet (runtime, snippet) {
8+
function compileSnippet (runtime, snippet, additional) {
99
const { render, staticRenderFns } = compileAndStringify(`<div>${snippet}</div>`)
1010
const instance = createInstance(runtime, `
1111
new Vue({
12+
el: 'body',
1213
render: ${render},
1314
staticRenderFns: ${staticRenderFns},
14-
el: 'body'
15+
${additional}
1516
})
1617
`)
17-
const result = instance.getRealRoot().children[0]
18-
return result
18+
return instance.getRealRoot().children[0]
1919
}
2020

2121
describe('richtext component', () => {
@@ -57,6 +57,7 @@ describe('richtext component', () => {
5757
})
5858

5959
describe('span', () => {
60+
// pending('work in progress')
6061
it('single node', () => {
6162
expect(compileSnippet(runtime, `
6263
<richtext>
@@ -124,6 +125,7 @@ describe('richtext component', () => {
124125
})
125126

126127
describe('a', () => {
128+
// pending('work in progress')
127129
it('single node', () => {
128130
expect(compileSnippet(runtime, `
129131
<richtext>
@@ -162,6 +164,7 @@ describe('richtext component', () => {
162164
})
163165

164166
describe('image', () => {
167+
// pending('work in progress')
165168
it('single node', () => {
166169
expect(compileSnippet(runtime, `
167170
<richtext>
@@ -220,6 +223,7 @@ describe('richtext component', () => {
220223
})
221224

222225
describe('nested', () => {
226+
// pending('work in progress')
223227
it('span', () => {
224228
expect(compileSnippet(runtime, `
225229
<richtext>
@@ -296,6 +300,7 @@ describe('richtext component', () => {
296300
describe('with styles', () => {
297301
// pending('work in progress')
298302
it('inline', () => {
303+
// pending('work in progress')
299304
expect(compileSnippet(runtime, `
300305
<richtext>
301306
<span style="font-size:16px;color:#FF6600;">ABCD</span>
@@ -316,5 +321,290 @@ describe('richtext component', () => {
316321
}
317322
})
318323
})
324+
325+
it('class list', () => {
326+
// pending('work in progress')
327+
expect(compileSnippet(runtime, `
328+
<richtext>
329+
<image class="icon" src="path/to/A.png"></image>
330+
<span class="title large">ABCD</span>
331+
</richtext>
332+
`, `
333+
style: {
334+
title: { color: '#FF6600' },
335+
large: { fontSize: 24 },
336+
icon: { width: 40, height: 60 }
337+
}
338+
`)).toEqual({
339+
type: 'richtext',
340+
attr: {
341+
value: [{
342+
type: 'image',
343+
style: { width: 40, height: 60 },
344+
attr: { src: 'path/to/A.png' }
345+
}, {
346+
type: 'span',
347+
style: { fontSize: 24, color: '#FF6600' },
348+
attr: { value: 'ABCD' }
349+
}]
350+
}
351+
})
352+
})
353+
})
354+
355+
describe('data binding', () => {
356+
// pending('work in progress')
357+
it('simple', () => {
358+
expect(compileSnippet(runtime, `
359+
<richtext>
360+
<span>{{name}}</span>
361+
</richtext>
362+
`, `data: { name: 'ABCDEFG' }`)).toEqual({
363+
type: 'richtext',
364+
attr: {
365+
value: [{
366+
type: 'span',
367+
attr: { value: 'ABCDEFG' }
368+
}]
369+
}
370+
})
371+
})
372+
373+
it('nested', () => {
374+
expect(compileSnippet(runtime, `
375+
<richtext>
376+
<span>{{a}}</span>
377+
<span>{{b}}<span>{{c.d}}</span></span>
378+
<span>{{e}}</span>
379+
</richtext>
380+
`, `data: { a: 'A', b: 'B', c: { d: 'CD' }, e: 'E' }`))
381+
.toEqual({
382+
type: 'richtext',
383+
attr: {
384+
value: [{
385+
type: 'span',
386+
attr: { value: 'A' }
387+
}, {
388+
type: 'span',
389+
children: [{
390+
type: 'span',
391+
attr: { value: 'B' }
392+
}, {
393+
type: 'span',
394+
attr: { value: 'CD' }
395+
}]
396+
}, {
397+
type: 'span',
398+
attr: { value: 'E' }
399+
}]
400+
}
401+
})
402+
})
403+
404+
it('update', () => {
405+
expect(compileSnippet(runtime, `
406+
<richtext>
407+
<span>{{name}}</span>
408+
</richtext>
409+
`, `
410+
data: { name: 'default' },
411+
created: function () {
412+
this.name = 'updated'
413+
}
414+
`)).toEqual({
415+
type: 'richtext',
416+
attr: {
417+
value: [{
418+
type: 'span',
419+
attr: { value: 'updated' }
420+
}]
421+
}
422+
})
423+
})
424+
425+
it('attribute', () => {
426+
expect(compileSnippet(runtime, `
427+
<richtext>
428+
<span :label="label">{{name}}</span>
429+
</richtext>
430+
`, `
431+
data: {
432+
label: 'uid',
433+
name: '10100'
434+
}
435+
`)).toEqual({
436+
type: 'richtext',
437+
attr: {
438+
value: [{
439+
type: 'span',
440+
attr: {
441+
label: 'uid',
442+
value: '10100'
443+
}
444+
}]
445+
}
446+
})
447+
})
448+
449+
it('update attribute', () => {
450+
expect(compileSnippet(runtime, `
451+
<richtext>
452+
<span :label="label">{{name}}</span>
453+
</richtext>
454+
`, `
455+
data: {
456+
label: 'name',
457+
name: 'Hanks'
458+
},
459+
created: function () {
460+
this.label = 'uid';
461+
this.name = '10100';
462+
}
463+
`)).toEqual({
464+
type: 'richtext',
465+
attr: {
466+
value: [{
467+
type: 'span',
468+
attr: {
469+
label: 'uid',
470+
value: '10100'
471+
}
472+
}]
473+
}
474+
})
475+
})
476+
477+
it('inline style', () => {
478+
expect(compileSnippet(runtime, `
479+
<richtext>
480+
<span :style="styleObject">ABCD</span>
481+
<span :style="{ textAlign: align, color: 'red' }">EFGH</span>
482+
</richtext>
483+
`, `
484+
data: {
485+
styleObject: { fontSize: '32px', color: '#F6F660' },
486+
align: 'center'
487+
}
488+
`)).toEqual({
489+
type: 'richtext',
490+
attr: {
491+
value: [{
492+
type: 'span',
493+
style: { fontSize: 32, color: '#F6F660' },
494+
attr: { value: 'ABCD' }
495+
}, {
496+
type: 'span',
497+
style: { textAlign: 'center', color: 'red' },
498+
attr: { value: 'EFGH' }
499+
}]
500+
}
501+
})
502+
})
503+
504+
it('class list', () => {
505+
// pending('work in progress')
506+
expect(compileSnippet(runtime, `
507+
<richtext>
508+
<image :class="classList" src="path/to/A.png"></image>
509+
<span :class="['title', size]">ABCD</span>
510+
<span class="large" style="color:#F6F0F4">EFGH</span>
511+
</richtext>
512+
`, `
513+
style: {
514+
title: { color: '#FF6600' },
515+
large: { fontSize: 24 },
516+
icon: { width: 40, height: 60 }
517+
},
518+
data: {
519+
classList: ['unknown'],
520+
size: 'small'
521+
},
522+
created: function () {
523+
this.classList = ['icon'];
524+
this.size = 'large';
525+
}
526+
`)).toEqual({
527+
type: 'richtext',
528+
attr: {
529+
value: [{
530+
type: 'image',
531+
style: { width: 40, height: 60 },
532+
attr: { src: 'path/to/A.png' }
533+
}, {
534+
type: 'span',
535+
style: { fontSize: 24, color: '#FF6600' },
536+
attr: { value: 'ABCD' }
537+
}, {
538+
type: 'span',
539+
style: { fontSize: 24, color: '#F6F0F4' },
540+
attr: { value: 'EFGH' }
541+
}]
542+
}
543+
})
544+
})
545+
546+
it('update inline style', () => {
547+
expect(compileSnippet(runtime, `
548+
<richtext>
549+
<span :style="styleObject">ABCD</span>
550+
<span :style="{ textAlign: align, color: 'red' }">EFGH</span>
551+
</richtext>
552+
`, `
553+
data: {
554+
styleObject: { fontSize: '32px', color: '#F6F660' }
555+
},
556+
created: function () {
557+
this.styleObject = { fontSize: '24px', color: 'blue' }
558+
this.styleObject.color = '#ABCDEF'
559+
this.align = 'left'
560+
}
561+
`)).toEqual({
562+
type: 'richtext',
563+
attr: {
564+
value: [{
565+
type: 'span',
566+
style: { fontSize: 24, color: '#ABCDEF' },
567+
attr: { value: 'ABCD' }
568+
}, {
569+
type: 'span',
570+
style: { textAlign: 'left', color: 'red' },
571+
attr: { value: 'EFGH' }
572+
}]
573+
}
574+
})
575+
})
576+
})
577+
578+
describe('bind events', () => {
579+
pending('work in progress')
580+
it('inline', () => {
581+
const { render, staticRenderFns } = compileAndStringify(`
582+
<div>
583+
<richtext>
584+
<span @click="handler">Button</span>
585+
</richtext>
586+
</div>
587+
`)
588+
const instance = createInstance(runtime, `
589+
new Vue({
590+
el: 'body',
591+
render: ${render},
592+
staticRenderFns: ${staticRenderFns},
593+
methods: {
594+
handler: function () {}
595+
}
596+
})
597+
`)
598+
expect(instance.getRealRoot().children[0]).toEqual({
599+
type: 'richtext',
600+
attr: {
601+
value: [{
602+
type: 'span',
603+
events: { click: 'handler' },
604+
attr: { value: 'Button' }
605+
}]
606+
}
607+
})
608+
})
319609
})
320610
})

0 commit comments

Comments
 (0)