Skip to content

Commit 20f0aaa

Browse files
author
Evan You
committed
Merge branch '335-allow-using-node-as-template' of https://github.com/jordangarcia/vue into template
2 parents 2b34485 + 66f4708 commit 20f0aaa

File tree

7 files changed

+151
-41
lines changed

7 files changed

+151
-41
lines changed

component.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"src/observer.js",
1919
"src/directive.js",
2020
"src/exp-parser.js",
21+
"src/template-parser.js",
2122
"src/text-parser.js",
2223
"src/deps-parser.js",
2324
"src/filters.js",
@@ -34,4 +35,4 @@
3435
"src/directives/partial.js",
3536
"src/directives/view.js"
3637
]
37-
}
38+
}

src/fragment.js

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,29 +30,12 @@ map.rect = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'
3030

3131
var TAG_RE = /<([\w:]+)/
3232

33-
module.exports = function (template) {
34-
35-
if (typeof template !== 'string') {
36-
return template
37-
}
38-
39-
// template by ID
40-
if (template.charAt(0) === '#') {
41-
var templateNode = document.getElementById(template.slice(1))
42-
if (!templateNode) return
43-
// if its a template tag and the browser supports it,
44-
// its content is already a document fragment!
45-
if (templateNode.tagName === 'TEMPLATE' && templateNode.content) {
46-
return templateNode.content
47-
}
48-
template = templateNode.innerHTML
49-
}
50-
33+
module.exports = function (templateString) {
5134
var frag = document.createDocumentFragment(),
52-
m = TAG_RE.exec(template)
35+
m = TAG_RE.exec(templateString)
5336
// text only
5437
if (!m) {
55-
frag.appendChild(document.createTextNode(template))
38+
frag.appendChild(document.createTextNode(templateString))
5639
return frag
5740
}
5841

@@ -63,7 +46,7 @@ module.exports = function (template) {
6346
suffix = wrap[2],
6447
node = document.createElement('div')
6548

66-
node.innerHTML = prefix + template.trim() + suffix
49+
node.innerHTML = prefix + templateString.trim() + suffix
6750
while (depth--) node = node.lastChild
6851

6952
// one element

src/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ assetTypes.forEach(function (type) {
3030
}
3131
if (!value) return hash[id]
3232
if (type === 'partial') {
33-
value = utils.toFragment(value)
33+
value = utils.parseTemplateOption(value)
3434
} else if (type === 'component') {
3535
value = utils.toConstructor(value)
3636
} else if (type === 'filter') {

src/template-parser.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
var toFragment = require('./fragment');
2+
3+
/**
4+
* Parses a template string or node and normalizes it into a
5+
* a node that can be used as a partial of a template option
6+
*
7+
* Possible values include
8+
* id selector: '#some-template-id'
9+
* template string: '<div><span>my template</span></div>'
10+
* DocumentFragment object
11+
* Node object of type Template
12+
*/
13+
module.exports = function(template) {
14+
var templateNode;
15+
16+
if (template instanceof window.DocumentFragment) {
17+
// if the template is already a document fragment -- do nothing
18+
return template
19+
}
20+
21+
if (typeof template === 'string') {
22+
// template by ID
23+
if (template.charAt(0) === '#') {
24+
templateNode = document.getElementById(template.slice(1))
25+
if (!templateNode) return
26+
} else {
27+
return toFragment(template)
28+
}
29+
} else if (template.nodeType) {
30+
templateNode = template
31+
} else {
32+
return
33+
}
34+
35+
// if its a template tag and the browser supports it,
36+
// its content is already a document fragment!
37+
if (templateNode.tagName === 'TEMPLATE' && templateNode.content) {
38+
return templateNode.content
39+
}
40+
41+
if (templateNode.tagName === 'SCRIPT') {
42+
return toFragment(templateNode.innerHTML)
43+
}
44+
45+
return toFragment(templateNode.outerHTML);
46+
}

src/utils.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ var utils = module.exports = {
3232
*/
3333
toFragment: require('./fragment'),
3434

35+
/**
36+
* Parse the various types of template options
37+
*/
38+
parseTemplateOption: require('./template-parser.js'),
39+
3540
/**
3641
* get a value from an object keypath
3742
*/
@@ -226,7 +231,7 @@ var utils = module.exports = {
226231
}
227232
if (partials) {
228233
for (key in partials) {
229-
partials[key] = utils.toFragment(partials[key])
234+
partials[key] = utils.parseTemplateOption(partials[key])
230235
}
231236
}
232237
if (filters) {
@@ -235,7 +240,7 @@ var utils = module.exports = {
235240
}
236241
}
237242
if (template) {
238-
options.template = utils.toFragment(template)
243+
options.template = utils.parseTemplateOption(template)
239244
}
240245
},
241246

test/unit/specs/utils.js

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
describe('Utils', function () {
2+
afterEach(cleanupMocks)
23

34
var utils = require('vue/src/utils'),
45
config = require('vue/src/config')
@@ -215,28 +216,14 @@ describe('Utils', function () {
215216

216217
describe('toFragment', function () {
217218

218-
it('should convert a string tempalte to a documentFragment', function () {
219+
it('should convert a string template to a documentFragment', function () {
219220
var template = '<div class="a">hi</div><p>ha</p>',
220221
frag = utils.toFragment(template)
221222
assert.ok(frag instanceof window.DocumentFragment)
222223
assert.equal(frag.querySelector('.a').textContent, 'hi')
223224
assert.equal(frag.querySelector('p').textContent, 'ha')
224225
})
225226

226-
it('should also work if the string is an ID selector', function () {
227-
var id = 'utils-template-to-fragment',
228-
template = '<div class="a">hi</div><p>ha</p>',
229-
el = document.createElement('template')
230-
el.id = id
231-
el.innerHTML = template
232-
document.getElementById('test').appendChild(el)
233-
234-
var frag = utils.toFragment('#' + id)
235-
assert.ok(frag instanceof window.DocumentFragment)
236-
assert.equal(frag.querySelector('.a').textContent, 'hi')
237-
assert.equal(frag.querySelector('p').textContent, 'ha')
238-
})
239-
240227
it('should work with table elements', function () {
241228
var frag = utils.toFragment('<td></td>')
242229
assert.ok(frag instanceof window.DocumentFragment)
@@ -252,6 +239,75 @@ describe('Utils', function () {
252239

253240
})
254241

242+
describe('parseTemplateOption', function () {
243+
244+
afterEach(cleanupMocks)
245+
246+
it('should convert a string template to a documentFragment', function () {
247+
var template = '<div class="a">hi</div><p>ha</p>',
248+
frag = utils.parseTemplateOption(template)
249+
assert.ok(frag instanceof window.DocumentFragment)
250+
assert.equal(frag.querySelector('.a').textContent, 'hi')
251+
assert.equal(frag.querySelector('p').textContent, 'ha')
252+
})
253+
254+
describe('id selector', function() {
255+
it('should work with a TEMPLATE tag', function() {
256+
var id = 'utils-template-parse-template-option-template-tag',
257+
template = '<div class="a">hi</div><p>ha</p>',
258+
el = document.createElement('template')
259+
el.id = id
260+
el.innerHTML = template
261+
appendMock(el)
262+
263+
var frag = utils.parseTemplateOption('#' + id)
264+
assert.ok(frag instanceof window.DocumentFragment)
265+
assert.equal(frag.querySelector('.a').textContent, 'hi')
266+
assert.equal(frag.querySelector('p').textContent, 'ha')
267+
})
268+
269+
it('should work with a DIV tag', function() {
270+
var id = 'utils-template-parse-template-option-div-tag',
271+
template = '<div class="a">hi</div><p>ha</p>',
272+
el = document.createElement('div')
273+
el.id = id
274+
el.innerHTML = template
275+
appendMock(el)
276+
277+
var frag = utils.parseTemplateOption('#' + id)
278+
assert.ok(frag instanceof window.DocumentFragment)
279+
assert.equal(frag.querySelector('.a').textContent, 'hi')
280+
assert.equal(frag.querySelector('p').textContent, 'ha')
281+
})
282+
})
283+
284+
describe('when passed a Node', function() {
285+
it('should work with a TEMPLATE tag', function() {
286+
var el = document.createElement('template')
287+
el.innerHTML = '<div class="a">hi</div><p>ha</p>'
288+
289+
var frag = utils.parseTemplateOption(el)
290+
assert.ok(frag instanceof window.DocumentFragment)
291+
assert.equal(frag.querySelector('.a').textContent, 'hi')
292+
assert.equal(frag.querySelector('p').textContent, 'ha')
293+
})
294+
295+
it('should work with a DIV tag', function() {
296+
var el = document.createElement('div')
297+
el.innerHTML = '<span class="a">hi</span><p>ha</p>'
298+
299+
var frag = utils.parseTemplateOption(el)
300+
assert.ok(frag instanceof window.DocumentFragment)
301+
302+
assert.equal(frag.firstChild.outerHTML, el.outerHTML)
303+
assert.equal(frag.querySelector('.a').textContent, 'hi')
304+
assert.equal(frag.querySelector('p').textContent, 'ha')
305+
})
306+
})
307+
308+
309+
})
310+
255311
describe('toConstructor', function () {
256312

257313
it('should convert an non-VM object to a VM constructor', function () {
@@ -270,6 +326,17 @@ describe('Utils', function () {
270326

271327
describe('processOptions', function () {
272328

329+
beforeEach(function() {
330+
var id = 'utils-template-to-fragment',
331+
template = '<div class="a">hi</div><p>ha</p>',
332+
el = document.createElement('template')
333+
el.id = id
334+
el.innerHTML = template
335+
appendMock(el)
336+
})
337+
338+
afterEach(cleanupMocks)
339+
273340
var options = {
274341
partials: {
275342
a: '#utils-template-to-fragment',

test/unit/utils/prepare.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,18 @@ function mock (id, html, attrs) {
77
el.setAttribute(attr, attrs[attr])
88
}
99
}
10-
document.getElementById('test').appendChild(el)
10+
appendMock(el)
1111
return el
1212
}
1313

14+
function appendMock(el) {
15+
document.getElementById('test').appendChild(el)
16+
}
17+
18+
function cleanupMocks() {
19+
document.getElementById('test').innerHTML = ''
20+
}
21+
1422
function mockHTMLEvent (type) {
1523
var e = document.createEvent('HTMLEvents')
1624
e.initEvent(type, true, true)

0 commit comments

Comments
 (0)