diff --git a/component.json b/component.json index e842a254377..3aa245a2072 100644 --- a/component.json +++ b/component.json @@ -18,6 +18,7 @@ "src/observer.js", "src/directive.js", "src/exp-parser.js", + "src/template-parser.js", "src/text-parser.js", "src/deps-parser.js", "src/filters.js", @@ -34,4 +35,4 @@ "src/directives/partial.js", "src/directives/view.js" ] -} \ No newline at end of file +} diff --git a/src/fragment.js b/src/fragment.js index 7b9790a5535..eba460ee664 100644 --- a/src/fragment.js +++ b/src/fragment.js @@ -30,29 +30,12 @@ map.rect = [1, '' var TAG_RE = /<([\w:]+)/ -module.exports = function (template) { - - if (typeof template !== 'string') { - return template - } - - // template by ID - if (template.charAt(0) === '#') { - var templateNode = document.getElementById(template.slice(1)) - if (!templateNode) return - // if its a template tag and the browser supports it, - // its content is already a document fragment! - if (templateNode.tagName === 'TEMPLATE' && templateNode.content) { - return templateNode.content - } - template = templateNode.innerHTML - } - +module.exports = function (templateString) { var frag = document.createDocumentFragment(), - m = TAG_RE.exec(template) + m = TAG_RE.exec(templateString) // text only if (!m) { - frag.appendChild(document.createTextNode(template)) + frag.appendChild(document.createTextNode(templateString)) return frag } @@ -63,7 +46,7 @@ module.exports = function (template) { suffix = wrap[2], node = document.createElement('div') - node.innerHTML = prefix + template.trim() + suffix + node.innerHTML = prefix + templateString.trim() + suffix while (depth--) node = node.lastChild // one element diff --git a/src/main.js b/src/main.js index 449a3bc3b1a..f011ea06f68 100644 --- a/src/main.js +++ b/src/main.js @@ -28,7 +28,7 @@ assetTypes.forEach(function (type) { } if (!value) return hash[id] if (type === 'partial') { - value = utils.toFragment(value) + value = utils.parseTemplateOption(value) } else if (type === 'component') { value = utils.toConstructor(value) } else if (type === 'filter') { diff --git a/src/template-parser.js b/src/template-parser.js new file mode 100644 index 00000000000..09b1d83e5ce --- /dev/null +++ b/src/template-parser.js @@ -0,0 +1,46 @@ +var toFragment = require('./fragment'); + +/** + * Parses a template string or node and normalizes it into a + * a node that can be used as a partial of a template option + * + * Possible values include + * id selector: '#some-template-id' + * template string: '
ha
', frag = utils.toFragment(template) assert.ok(frag instanceof window.DocumentFragment) @@ -223,20 +224,6 @@ describe('Utils', function () { assert.equal(frag.querySelector('p').textContent, 'ha') }) - it('should also work if the string is an ID selector', function () { - var id = 'utils-template-to-fragment', - template = 'ha
', - el = document.createElement('template') - el.id = id - el.innerHTML = template - document.getElementById('test').appendChild(el) - - var frag = utils.toFragment('#' + id) - assert.ok(frag instanceof window.DocumentFragment) - assert.equal(frag.querySelector('.a').textContent, 'hi') - assert.equal(frag.querySelector('p').textContent, 'ha') - }) - it('should work with table elements', function () { var frag = utils.toFragment('ha
', + frag = utils.parseTemplateOption(template) + assert.ok(frag instanceof window.DocumentFragment) + assert.equal(frag.querySelector('.a').textContent, 'hi') + assert.equal(frag.querySelector('p').textContent, 'ha') + }) + + describe('id selector', function() { + it('should work with a TEMPLATE tag', function() { + var id = 'utils-template-parse-template-option-template-tag', + template = 'ha
', + el = document.createElement('template') + el.id = id + el.innerHTML = template + appendMock(el) + + var frag = utils.parseTemplateOption('#' + id) + assert.ok(frag instanceof window.DocumentFragment) + assert.equal(frag.querySelector('.a').textContent, 'hi') + assert.equal(frag.querySelector('p').textContent, 'ha') + }) + + it('should work with a DIV tag', function() { + var id = 'utils-template-parse-template-option-div-tag', + template = 'ha
', + el = document.createElement('div') + el.id = id + el.innerHTML = template + appendMock(el) + + var frag = utils.parseTemplateOption('#' + id) + assert.ok(frag instanceof window.DocumentFragment) + assert.equal(frag.querySelector('.a').textContent, 'hi') + assert.equal(frag.querySelector('p').textContent, 'ha') + }) + }) + + describe('when passed a Node', function() { + it('should work with a TEMPLATE tag', function() { + var el = document.createElement('template') + el.innerHTML = 'ha
' + + var frag = utils.parseTemplateOption(el) + assert.ok(frag instanceof window.DocumentFragment) + assert.equal(frag.querySelector('.a').textContent, 'hi') + assert.equal(frag.querySelector('p').textContent, 'ha') + }) + + it('should work with a DIV tag', function() { + var el = document.createElement('div') + el.innerHTML = 'hiha
' + + var frag = utils.parseTemplateOption(el) + assert.ok(frag instanceof window.DocumentFragment) + + assert.equal(frag.firstChild.outerHTML, el.outerHTML) + assert.equal(frag.querySelector('.a').textContent, 'hi') + assert.equal(frag.querySelector('p').textContent, 'ha') + }) + }) + + + }) + describe('toConstructor', function () { it('should convert an non-VM object to a VM constructor', function () { @@ -270,6 +326,17 @@ describe('Utils', function () { describe('processOptions', function () { + beforeEach(function() { + var id = 'utils-template-to-fragment', + template = 'ha
', + el = document.createElement('template') + el.id = id + el.innerHTML = template + appendMock(el) + }) + + afterEach(cleanupMocks) + var options = { partials: { a: '#utils-template-to-fragment', diff --git a/test/unit/utils/prepare.js b/test/unit/utils/prepare.js index 5aafad2e7f7..5304449aa49 100644 --- a/test/unit/utils/prepare.js +++ b/test/unit/utils/prepare.js @@ -7,10 +7,18 @@ function mock (id, html, attrs) { el.setAttribute(attr, attrs[attr]) } } - document.getElementById('test').appendChild(el) + appendMock(el) return el } +function appendMock(el) { + document.getElementById('test').appendChild(el) +} + +function cleanupMocks() { + document.getElementById('test').innerHTML = '' +} + function mockHTMLEvent (type) { var e = document.createEvent('HTMLEvents') e.initEvent(type, true, true)