weex-templater
Version:
Weex <template> transformer
570 lines (540 loc) • 20.1 kB
JavaScript
var chai = require('chai')
var sinon = require('sinon')
var sinonChai = require('sinon-chai')
var expect = chai.expect
chai.use(sinonChai)
var templater = require('../')
function stringify(json) {
return JSON.stringify(json, function replacer(key, value) {
if (typeof value === 'function') {
return value.toString()
}
return value;
}, 2)
}
describe('parse', function () {
it('parse normal template code', function (done) {
var code = '<container><text>Hello</text><img class="a {{x}} c" src="{{y}}" /><image style="opacity: {{z}}"></image></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', attr: {value: 'Hello'}},
{type: 'image', classList: function () {return ['a', this.x, 'c']}, attr: {src: function () {return this.y}}},
{type: 'image', style: {opacity: function () {return this.z}}}
]
},
deps: ['container', 'text', 'image'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse root with space around', function (done) {
var code = ' <container></container> '
var expected = {
jsonTemplate: {
type: 'container'
},
deps: ['container'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse multiple root', function (done) {
var code = '<container></container><container></container>'
var expected = {
jsonTemplate: {},
deps: [],
log: [{reason: 'ERROR: only one root element required', line: 1, column: 1}]
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse root attributes', function (done) {
var code = '<container id="main" style="x: a; y: b" class="a b c" x="a" if="a" onclick="a"><text>abc</text></container>'
var expected = {
jsonTemplate: {
type: 'container',
id: 'main',
style: {x: 'a', y: 'b'},
classList: ['a', 'b', 'c'],
attr: {x: 'a'},
shown: function () {return this.a},
events: {click: 'a'},
children: [
{type: 'text', attr: {value: 'abc'}}
]
},
deps: ['container', 'text'],
log: [
{line: 1, column: 1, reason: 'WARNING: `x` is not a standard property name (may not be supported)'},
{line: 1, column: 1, reason: 'WARNING: `y` is not a standard property name (may not be supported)'}
]
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse and ignore space text value', function (done) {
var code = '<container>\n <text>abc</text>\t</container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', attr: {value: 'abc'}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse text space around data', function (done) {
var code = '<container><text> a {{c}} </text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', attr: {value: function () {return 'a ' + (this.c)}}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse child text content', function (done) {
var code = '<container><text>abc</text><h1>{{abc}}</h1></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', attr: {value: 'abc'}},
{type: 'h1', attr: {value: function () {return this.abc}}},
]
},
deps: ['container', 'text', 'h1'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse id', function (done) {
var code = '<container><text></text><text id="abc"></text><text id="{{abc}}"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text'},
{type: 'text', id: 'abc'},
{type: 'text', id: function () {return this.abc}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse class', function (done) {
var code = '<container><text></text><text class="a b c"></text><text class="a {{b}} c"></text><text class="a b{{b}} c"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text'},
{type: 'text', classList: ['a', 'b', 'c']},
{type: 'text', classList: function () {return ['a', this.b, 'c']}},
{type: 'text', classList: function () {return ['a', 'b' + (this.b), 'c']}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse complex class', function (done) {
var code = '<container><text class="a b{{b ? \'d\' : \'f\' }} c"></text><text class=" b{{b ? \'d\' : \'f\' }} a {{c + d}}"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', classList: function () {return ['a', 'b' + (this.b?'d':'f'), 'c']}},
{type: 'text', classList: function () {return ['b' + (this.b?'d':'f'), 'a', this.c+this.d]}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse style', function (done) {
var code = '<container><text></text><text style="color: #FF0000; background-color: rgba(2,2,2,2); padding: 8px;"></text><text style="x: a; y: b; z: {{c}}"></text><text style="background-color: {{active ? \'#ff0000\' : \'#00ff00\'}};"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text'},
{type: 'text', style: {color: '#FF0000', padding: 8}},
{type: 'text', style: {x: 'a', y: 'b', z: function () {return this.c}}},
{type: 'text', style: {backgroundColor: function () {return this.active?'#ff0000':'#00ff00'}}}
]
},
deps: ['container', 'text'],
log: [
{line: 1, column: 25, reason: 'ERROR: property value `rgba(2,2,2,2)` is not valid for `background-color`'},
{line: 1, column: 25, reason: 'NOTE: unit `px` is not supported and property value `8px` is autofixed to `8`'},
{line: 1, column: 109, reason: 'WARNING: `x` is not a standard property name (may not be supported)'},
{line: 1, column: 109, reason: 'WARNING: `y` is not a standard property name (may not be supported)'},
{line: 1, column: 109, reason: 'WARNING: `z` is not a standard property name (may not be supported)'}
]
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse if', function (done) {
var code = '<container><text if="a"></text><text if="{{a}}"></text><text if="{{a()}}"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', shown: function () {return this.a}},
{type: 'text', shown: function () {return this.a}},
{type: 'text', shown: function () {return this.a()}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse repeat', function (done) {
var code = '<container><text repeat="a"></text><text repeat="{{a}}"></text><text repeat="{{a()}}"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', repeat: function () {return this.a}},
{type: 'text', repeat: function () {return this.a}},
{type: 'text', repeat: function () {return this.a()}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse repeat key/value', function (done) {
var code = '<container><text repeat="v in listOrMap"></text><text repeat="{{v in listOrMap}}"></text><text repeat="(k, v) in listOrMap"></text><text repeat="{{(k, v) in listOrMap}}"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', repeat: {expression: function () {return this.listOrMap}, value: 'v'}},
{type: 'text', repeat: {expression: function () {return this.listOrMap}, value: 'v'}},
{type: 'text', repeat: {expression: function () {return this.listOrMap}, key: 'k', value: 'v'}},
{type: 'text', repeat: {expression: function () {return this.listOrMap}, key: 'k', value: 'v'}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse else with if', function (done) {
var code = '<container><text if="a && b"></text><text else></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', shown: function () {return this.a&&this.b}},
{type: 'text', shown: function () {return !(this.a&&this.b)}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse else without if', function (done) {
var code = '<container><container><text></text><text else></text></container><container><text else></text></container></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'container', children: [{type: 'text'}, {type: 'text'}]},
{type: 'container', children: [{type: 'text'}]}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse append', function (done) {
var code = '<container append="tree"><container append="{{mode}}"></container></container>'
var expected = {
jsonTemplate: {
type: 'container',
append: 'tree',
children: [
{type: 'container', append: function () {return this.mode}}
]
},
deps: ['container'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse events', function (done) {
var code = '<container><text onclick="a" onappear="{{a()}}"></text><text onclick="{{a}}" onappear="{{a(x, 1, \'2\', $event)}}"></text><text onappear="{{a(x, $event, 1, \'2\')}}"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', events: {click: 'a', appear: function ($event) {this.a($event)}}},
{type: 'text', events: {click: 'a', appear: function ($event) {this.a(this.x,1,'2',$event)}}},
{type: 'text', events: {appear: function ($event) {this.a(this.x,$event,1,'2')}}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse attributes', function (done) {
var code = '<container><text x="a" y="b"></text><text x="{{a}}" y="b"></text><text x="a" y="{{b()}}"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', attr: {x: 'a', y: 'b'}},
{type: 'text', attr: {x: function () {return this.a}, y: 'b'}},
{type: 'text', attr: {x: 'a', y: function () {return this.b()}}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse default attributes', function (done) {
var code = '<container><cell></cell></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'cell', append: 'tree'}
]
},
deps: ['container', 'cell'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse value', function (done) {
var code = '<container><text value="a"></text><text value="a{{b}}c"></text><text>a</text><text>a{{b}}c</text><text value="a{{b}}c">d{{e}}f</text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', attr: {value: 'a'}},
{type: 'text', attr: {value: function () {return 'a' + (this.b) + 'c'}}},
{type: 'text', attr: {value: 'a'}},
{type: 'text', attr: {value: function () {return 'a' + (this.b) + 'c'}}},
{type: 'text', attr: {value: function () {return 'd' + (this.e) + 'f'}}}
]
},
deps: ['container', 'text'],
log: [
{line: 1, column: 12, reason: 'NOTE: `value` could be written as text content in <text>'},
{line: 1, column: 35, reason: 'NOTE: `value` could be written as text content in <text>'},
{line: 1, column: 98, reason: 'NOTE: `value` could be written as text content in <text>'}
]
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse complex value', function (done) {
var code = '<container><text>{{data.items[0].title[0].valueDesc}}</text><text>{{ a }} and {{ b[c.d][0] ? \'a\' : "b" }} hhh {{parseInt("65")}}</text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', attr: {value: function () {return this.data.items[0].title[0].valueDesc}}},
{type: 'text', attr: {value: function () {return (this.a) + ' and ' + (this.b[this.c.d][0]?'a':'b') + ' hhh ' + (parseInt('65'))}}}
]
},
deps: ['container', 'text'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse hyphenated attr name', function (done) {
var code = '<container><text aaa-bbb-ccc ddd-eee-fff="ggg-hhh-iii" style="padding-left: 3; -webkit-transform: none;"></text></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'text', attr: {aaaBbbCcc: '', dddEeeFff: 'ggg-hhh-iii'}, style: {paddingLeft: 3, WebkitTransform: 'none'}}
]
},
deps: ['container', 'text'],
log: [{line: 1, column: 12, reason: 'WARNING: `-webkit-transform` is not a standard property name (may not be supported)'}]
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse empty attr value', function (done) {
var code = '<container><input value="" placeholder=""></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'input', attr: {value: '', placeholder: ''}}
]
},
deps: ['container', 'input'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse node which has no children', function (done) {
var code = ' <container><tabheader><text>aaa</text></tabheader></container> '
var expected = {
jsonTemplate: {
type: 'container',
children: [
{
type: 'tabheader',
children: [{type: 'text', attr: {value: 'aaa'}}]
}
]
},
deps: ['container', 'tabheader', 'text'],
log: [{line: 1, column: 13, reason: 'ERROR: tag `tabheader` should not have children'}]
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse component', function (done) {
var code = '<container><component></component><component is="foo"></component><component is="{{foo}}"></component></container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [
{type: 'container'},
{type: 'foo'},
{type: function () {return this.foo}}
]
},
deps: ['container', 'foo'],
log: [{line: 1, column: 12, reason: 'WARNING: tag `component` should have an `is` attribute, otherwise it will be regarded as a `container`'}]
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
it('parse richtext', function (done) {
var code = '<container> <richtext> <text style="padding: 8; color: {{active ? \'#ff0000\' : \'#00ff00\'}};"> {{xxx}} </text> </richtext> <richtext> <text if="a" repeat="list" class="a {{b}}"> {{xxx}} </text> <image class="a {{b}}" style="padding: 8; color: {{active ? \'#ff0000\' : \'#00ff00\'}};"></image> </richtext> <container> <text if="a" repeat="list">{{xxx}}</text> <image id="{{x}}" class="a {{x}} c" src="{{y}}" style="opacity: {{z}}"></image> </container> </container>'
var expected = {
jsonTemplate: {
type: 'container',
children: [{
type: 'richtext',
append: 'once',
attr: {
value: function () {return [{type: 'text', style: {padding: 8, color: this.active?'#ff0000':'#00ff00'}, attr: {value: this.xxx}}]}
}
},
{
type: 'richtext',
append: 'once',
attr: {
value: function () {return [{type: 'text', shown: this.a, repeat: this.list, style: (function () { var _s = this._css; return Object.assign({}, _s['a'], _s[this.b]); }).call(this), attr: {value: this.xxx}}, {type: 'image', style: (function () { var _s = this._css; return Object.assign({padding: 8, color: this.active?'#ff0000':'#00ff00'}, _s['a'], _s[this.b]); }).call(this)}]}
}
},
{
type: 'container',
children: [
{type: 'text', shown: function () {return this.a}, repeat: function () {return this.list}, attr: {value: function () {return this.xxx}}},
{type: 'image', id: function () {return this.x}, classList: function () {return ['a', this.x, 'c']}, attr: {src: function () {return this.y}}, style: {opacity: function () {return this.z}}}
]
}]
},
deps: ['container', 'richtext', 'text', 'image'],
log: []
}
templater.parse(code, function (err, result) {
expect(stringify(result)).eql(stringify(expected))
done()
})
})
})