diff --git a/src/.jshintrc b/src/.jshintrc
index b32113555d7b..1202b64447a3 100644
--- a/src/.jshintrc
+++ b/src/.jshintrc
@@ -138,6 +138,7 @@
"JQLitePrototype": false,
"addEventListenerFn": false,
"removeEventListenerFn": false,
+ "jqLiteIsTextNode": false,
/* apis.js */
"hashKey": false,
diff --git a/src/jqLite.js b/src/jqLite.js
index 738f47a9b167..a471d3742bc0 100644
--- a/src/jqLite.js
+++ b/src/jqLite.js
@@ -179,6 +179,75 @@ function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArgu
}
}
+var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
+var HTML_REGEXP = /<|?\w+;/;
+var TAG_NAME_REGEXP = /<([\w:]+)/;
+var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
+
+var wrapMap = {
+ 'option': [1, ''],
+
+ 'thead': [1, '
'],
+ 'col': [2, ''],
+ 'tr': [2, ''],
+ 'td': [3, ''],
+ '_default': [0, "", ""]
+};
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+function jqLiteIsTextNode(html) {
+ return !HTML_REGEXP.test(html);
+}
+
+function jqLiteBuildFragment(html, context) {
+ var elem, tmp, tag, wrap,
+ fragment = context.createDocumentFragment(),
+ nodes = [], i, j, jj;
+
+ if (jqLiteIsTextNode(html)) {
+ // Convert non-html into a text node
+ nodes.push(context.createTextNode(html));
+ } else {
+ tmp = fragment.appendChild(context.createElement('div'));
+ // Convert html into DOM nodes
+ tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
+ wrap = wrapMap[tag] || wrapMap._default;
+ tmp.innerHTML = '
' +
+ wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1>$2>") + wrap[2];
+ tmp.removeChild(tmp.firstChild);
+
+ // Descend through wrappers to the right content
+ i = wrap[0];
+ while (i--) {
+ tmp = tmp.lastChild;
+ }
+
+ for (j=0, jj=tmp.childNodes.length; j]*)?>/i;
+ CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/;
// Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
// The assumption is that future DOM event attribute names will begin with
@@ -1259,7 +1258,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (directive.replace) {
replaceDirective = directive;
- $template = directiveTemplateContents(directiveValue);
+ if (jqLiteIsTextNode(directiveValue)) {
+ $template = [];
+ } else {
+ $template = jqLite(directiveValue);
+ }
compileNode = $template[0];
if ($template.length != 1 || compileNode.nodeType !== 1) {
@@ -1658,27 +1661,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
- function directiveTemplateContents(template) {
- var type;
- template = trim(template);
- if ((type = TABLE_CONTENT_REGEXP.exec(template))) {
- type = type[1].toLowerCase();
- var table = jqLite('');
- if (/(thead|tbody|tfoot)/.test(type)) {
- return table.children(type);
- }
- table = table.children('tbody');
- if (type === 'tr') {
- return table.children('tr');
- }
- return table.children('tr').contents();
- }
- return jqLite('' +
- template +
- '
').contents();
- }
-
-
function compileTemplateUrl(directives, $compileNode, tAttrs,
$rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
var linkQueue = [],
@@ -1703,7 +1685,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
content = denormalizeTemplate(content);
if (origAsyncDirective.replace) {
- $template = directiveTemplateContents(content);
+ if (jqLiteIsTextNode(content)) {
+ $template = [];
+ } else {
+ $template = jqLite(content);
+ }
compileNode = $template[0];
if ($template.length != 1 || compileNode.nodeType !== 1) {
diff --git a/test/jqLiteSpec.js b/test/jqLiteSpec.js
index faf1c98cbb8c..f9c6f3a2b55f 100644
--- a/test/jqLiteSpec.js
+++ b/test/jqLiteSpec.js
@@ -95,6 +95,36 @@ describe('jqLite', function() {
expect(fragment.length).toBe(1);
expect(fragment[0].nodeType).toBe(11);
});
+
+
+ it('should allow construction of '
+ }));
+ directive('replaceWithOptgroup', valueFn({
+ replace: true,
+ template: ''
+ }));
}));
@@ -746,6 +754,20 @@ describe('$compile', function() {
}).not.toThrow();
expect(nodeName_(element)).toMatch(/tfoot/i);
}));
+
+ it('should support templates with root