Преглед изворни кода

Merge branch '335-allow-using-node-as-template' of https://github.com/jordangarcia/vue into template

Evan You пре 11 година
родитељ
комит
20f0aaa915
7 измењених фајлова са 151 додато и 41 уклоњено
  1. 2 1
      component.json
  2. 4 21
      src/fragment.js
  3. 1 1
      src/main.js
  4. 46 0
      src/template-parser.js
  5. 7 2
      src/utils.js
  6. 82 15
      test/unit/specs/utils.js
  7. 9 1
      test/unit/utils/prepare.js

+ 2 - 1
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"
     ]
-}
+}

+ 4 - 21
src/fragment.js

@@ -30,29 +30,12 @@ map.rect = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'
 
 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

+ 1 - 1
src/main.js

@@ -30,7 +30,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') {

+ 46 - 0
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: '<div><span>my template</span></div>'
+ * DocumentFragment object
+ * Node object of type Template
+ */
+module.exports = function(template) {
+    var templateNode;
+
+    if (template instanceof window.DocumentFragment) {
+        // if the template is already a document fragment -- do nothing
+        return template
+    }
+
+    if (typeof template === 'string') {
+        // template by ID
+        if (template.charAt(0) === '#') {
+            templateNode = document.getElementById(template.slice(1))
+            if (!templateNode) return
+        } else {
+            return toFragment(template)
+        }
+    } else if (template.nodeType) {
+        templateNode = template
+    } else {
+        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
+    }
+
+    if (templateNode.tagName === 'SCRIPT') {
+        return toFragment(templateNode.innerHTML)
+    }
+
+    return toFragment(templateNode.outerHTML);
+}

+ 7 - 2
src/utils.js

@@ -32,6 +32,11 @@ var utils = module.exports = {
      */
     toFragment: require('./fragment'),
 
+    /**
+     *  Parse the various types of template options
+     */
+    parseTemplateOption: require('./template-parser.js'),
+
     /**
      *  get a value from an object keypath
      */
@@ -226,7 +231,7 @@ var utils = module.exports = {
         }
         if (partials) {
             for (key in partials) {
-                partials[key] = utils.toFragment(partials[key])
+                partials[key] = utils.parseTemplateOption(partials[key])
             }
         }
         if (filters) {
@@ -235,7 +240,7 @@ var utils = module.exports = {
             }
         }
         if (template) {
-            options.template = utils.toFragment(template)
+            options.template = utils.parseTemplateOption(template)
         }
     },
 

+ 82 - 15
test/unit/specs/utils.js

@@ -1,4 +1,5 @@
 describe('Utils', function () {
+    afterEach(cleanupMocks)
 
     var utils = require('vue/src/utils'),
         config = require('vue/src/config')
@@ -215,7 +216,7 @@ describe('Utils', function () {
 
     describe('toFragment', function () {
         
-        it('should convert a string tempalte to a documentFragment', function () {
+        it('should convert a string template to a documentFragment', function () {
             var template = '<div class="a">hi</div><p>ha</p>',
                 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 = '<div class="a">hi</div><p>ha</p>',
-                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('<td></td>')
             assert.ok(frag instanceof window.DocumentFragment)
@@ -252,6 +239,75 @@ describe('Utils', function () {
 
     })
 
+    describe('parseTemplateOption', function () {
+        
+        afterEach(cleanupMocks)
+
+        it('should convert a string template to a documentFragment', function () {
+            var template = '<div class="a">hi</div><p>ha</p>',
+                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 = '<div class="a">hi</div><p>ha</p>',
+                    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 = '<div class="a">hi</div><p>ha</p>',
+                    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 = '<div class="a">hi</div><p>ha</p>'
+
+                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 = '<span class="a">hi</span><p>ha</p>'
+
+                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 = '<div class="a">hi</div><p>ha</p>',
+                el = document.createElement('template')
+            el.id = id
+            el.innerHTML = template
+            appendMock(el)
+        })
+
+        afterEach(cleanupMocks)
+
         var options = {
             partials: {
                 a: '#utils-template-to-fragment',

+ 9 - 1
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)