Skip to content

Commit 7c13372

Browse files
committed
fix(TemplateParser): match element and attributes regardless the namespace
1 parent 778677b commit 7c13372

5 files changed

Lines changed: 37 additions & 15 deletions

File tree

‎modules/angular2/src/compiler/html_parser.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {HtmlAst, HtmlAttrAst, HtmlTextAst, HtmlElementAst} from './html_ast';
1616
import {Injectable} from 'angular2/src/core/di';
1717
import {HtmlToken, HtmlTokenType, tokenizeHtml} from './html_lexer';
1818
import {ParseError, ParseLocation, ParseSourceSpan} from './parse_util';
19-
import {HtmlTagDefinition, getHtmlTagDefinition, getHtmlTagNamespacePrefix} from './html_tags';
19+
import {HtmlTagDefinition, getHtmlTagDefinition, getNsPrefix} from './html_tags';
2020

2121
export class HtmlTreeError extends ParseError {
2222
static create(elementName: string, location: ParseLocation, msg: string): HtmlTreeError {
@@ -144,7 +144,7 @@ class TreeBuilder {
144144
if (this.peek.type === HtmlTokenType.TAG_OPEN_END_VOID) {
145145
this._advance();
146146
selfClosing = true;
147-
if (getHtmlTagNamespacePrefix(fullName) == null && !getHtmlTagDefinition(fullName).isVoid) {
147+
if (getNsPrefix(fullName) == null && !getHtmlTagDefinition(fullName).isVoid) {
148148
this.errors.push(HtmlTreeError.create(
149149
fullName, startTagToken.sourceSpan.start,
150150
`Only void and foreign elements can be self closed "${startTagToken.parts[1]}"`));
@@ -247,7 +247,7 @@ function getElementFullName(prefix: string, localName: string,
247247
if (isBlank(prefix)) {
248248
prefix = getHtmlTagDefinition(localName).implicitNamespacePrefix;
249249
if (isBlank(prefix) && isPresent(parentElement)) {
250-
prefix = getHtmlTagNamespacePrefix(parentElement.name);
250+
prefix = getNsPrefix(parentElement.name);
251251
}
252252
}
253253

‎modules/angular2/src/compiler/html_tags.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,14 +409,14 @@ export function getHtmlTagDefinition(tagName: string): HtmlTagDefinition {
409409

410410
var NS_PREFIX_RE = /^@([^:]+):(.+)/g;
411411

412-
export function splitHtmlTagNamespace(elementName: string): string[] {
412+
export function splitNsName(elementName: string): string[] {
413413
if (elementName[0] != '@') {
414414
return [null, elementName];
415415
}
416416
let match = RegExpWrapper.firstMatch(NS_PREFIX_RE, elementName);
417417
return [match[1], match[2]];
418418
}
419419

420-
export function getHtmlTagNamespacePrefix(elementName: string): string {
421-
return splitHtmlTagNamespace(elementName)[0];
420+
export function getNsPrefix(elementName: string): string {
421+
return splitNsName(elementName)[0];
422422
}

‎modules/angular2/src/compiler/schema/dom_element_schema_registry.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Injectable} from 'angular2/src/core/di';
22
import {isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
33
import {StringMapWrapper} from 'angular2/src/facade/collection';
44
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
5-
import {splitHtmlTagNamespace} from 'angular2/src/compiler/html_tags';
5+
import {splitNsName} from 'angular2/src/compiler/html_tags';
66

77
import {ElementSchemaRegistry} from './element_schema_registry';
88

@@ -16,7 +16,7 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry {
1616
private _getProtoElement(tagName: string): Element {
1717
var element = this._protoElements.get(tagName);
1818
if (isBlank(element)) {
19-
var nsAndName = splitHtmlTagNamespace(tagName);
19+
var nsAndName = splitNsName(tagName);
2020
element = isPresent(nsAndName[0]) ?
2121
DOM.createElementNS(NAMESPACE_URIS[nsAndName[0]], nsAndName[1]) :
2222
DOM.createElement(nsAndName[1]);

‎modules/angular2/src/compiler/template_parser.ts‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {Parser, AST, ASTWithSource} from 'angular2/src/core/change_detection/cha
77
import {TemplateBinding} from 'angular2/src/core/change_detection/parser/ast';
88
import {CompileDirectiveMetadata} from './directive_metadata';
99
import {HtmlParser} from './html_parser';
10-
import {splitHtmlTagNamespace} from './html_tags';
10+
import {splitNsName} from './html_tags';
1111
import {ParseSourceSpan, ParseError, ParseLocation} from './parse_util';
1212

1313

@@ -216,7 +216,7 @@ class TemplateParseVisitor implements HtmlAstVisitor {
216216
}
217217
});
218218

219-
var lcElName = splitHtmlTagNamespace(nodeName.toLowerCase())[1];
219+
var lcElName = splitNsName(nodeName.toLowerCase())[1];
220220
var isTemplateElement = lcElName == TEMPLATE_ELEMENT;
221221
var elementCssSelector = createElementCssSelector(nodeName, matchableAttrs);
222222
var directives = this._createDirectiveAsts(
@@ -687,13 +687,17 @@ class Component {
687687

688688
function createElementCssSelector(elementName: string, matchableAttrs: string[][]): CssSelector {
689689
var cssSelector = new CssSelector();
690+
let elNameNoNs = splitNsName(elementName)[1];
691+
692+
cssSelector.setElement(elNameNoNs);
690693

691-
cssSelector.setElement(elementName);
692694
for (var i = 0; i < matchableAttrs.length; i++) {
693-
var attrName = matchableAttrs[i][0];
694-
var attrValue = matchableAttrs[i][1];
695-
cssSelector.addAttribute(attrName, attrValue);
696-
if (attrName == CLASS_ATTR) {
695+
let attrName = matchableAttrs[i][0];
696+
let attrNameNoNs = splitNsName(attrName)[1];
697+
let attrValue = matchableAttrs[i][1];
698+
699+
cssSelector.addAttribute(attrNameNoNs, attrValue);
700+
if (attrName.toLowerCase() == CLASS_ATTR) {
697701
var classes = splitClasses(attrValue);
698702
classes.forEach(className => cssSelector.addClassName(className));
699703
}

‎modules/angular2/test/compiler/template_parser_spec.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,24 @@ Property binding a not used by any directive on an embedded template ("[ERROR ->
908908
]);
909909
});
910910

911+
it('should support directive in namespace', () => {
912+
var tagSel = CompileDirectiveMetadata.create(
913+
{selector: 'circle', type: new CompileTypeMetadata({name: 'elDir'})});
914+
var attrSel = CompileDirectiveMetadata.create(
915+
{selector: '[href]', type: new CompileTypeMetadata({name: 'attrDir'})});
916+
917+
expect(humanizeTplAstSourceSpans(
918+
parse('<svg><circle /><use xlink:href="Port" /></svg>', [tagSel, attrSel])))
919+
.toEqual([
920+
[ElementAst, '@svg:svg', '<svg>'],
921+
[ElementAst, '@svg:circle', '<circle />'],
922+
[DirectiveAst, tagSel, '<circle />'],
923+
[ElementAst, '@svg:use', '<use xlink:href="Port" />'],
924+
[AttrAst, '@xlink:href', 'Port', 'xlink:href="Port"'],
925+
[DirectiveAst, attrSel, '<use xlink:href="Port" />'],
926+
]);
927+
});
928+
911929
it('should support directive property', () => {
912930
var dirA = CompileDirectiveMetadata.create(
913931
{selector: 'div', type: new CompileTypeMetadata({name: 'DirA'}), inputs: ['aProp']});

0 commit comments

Comments
 (0)