diff --git a/modules/angular2/src/compiler/html_parser.ts b/modules/angular2/src/compiler/html_parser.ts index 2f32a6e57e..af1fe27c08 100644 --- a/modules/angular2/src/compiler/html_parser.ts +++ b/modules/angular2/src/compiler/html_parser.ts @@ -16,7 +16,7 @@ import {HtmlAst, HtmlAttrAst, HtmlTextAst, HtmlElementAst} from './html_ast'; import {Injectable} from 'angular2/src/core/di'; import {HtmlToken, HtmlTokenType, tokenizeHtml} from './html_lexer'; import {ParseError, ParseLocation, ParseSourceSpan} from './parse_util'; -import {HtmlTagDefinition, getHtmlTagDefinition, getHtmlTagNamespacePrefix} from './html_tags'; +import {HtmlTagDefinition, getHtmlTagDefinition, getNsPrefix} from './html_tags'; export class HtmlTreeError extends ParseError { static create(elementName: string, location: ParseLocation, msg: string): HtmlTreeError { @@ -144,7 +144,7 @@ class TreeBuilder { if (this.peek.type === HtmlTokenType.TAG_OPEN_END_VOID) { this._advance(); selfClosing = true; - if (getHtmlTagNamespacePrefix(fullName) == null && !getHtmlTagDefinition(fullName).isVoid) { + if (getNsPrefix(fullName) == null && !getHtmlTagDefinition(fullName).isVoid) { this.errors.push(HtmlTreeError.create( fullName, startTagToken.sourceSpan.start, `Only void and foreign elements can be self closed "${startTagToken.parts[1]}"`)); @@ -247,7 +247,7 @@ function getElementFullName(prefix: string, localName: string, if (isBlank(prefix)) { prefix = getHtmlTagDefinition(localName).implicitNamespacePrefix; if (isBlank(prefix) && isPresent(parentElement)) { - prefix = getHtmlTagNamespacePrefix(parentElement.name); + prefix = getNsPrefix(parentElement.name); } } diff --git a/modules/angular2/src/compiler/html_tags.ts b/modules/angular2/src/compiler/html_tags.ts index 6fc4f23fe5..d749cf3844 100644 --- a/modules/angular2/src/compiler/html_tags.ts +++ b/modules/angular2/src/compiler/html_tags.ts @@ -409,7 +409,7 @@ export function getHtmlTagDefinition(tagName: string): HtmlTagDefinition { var NS_PREFIX_RE = /^@([^:]+):(.+)/g; -export function splitHtmlTagNamespace(elementName: string): string[] { +export function splitNsName(elementName: string): string[] { if (elementName[0] != '@') { return [null, elementName]; } @@ -417,6 +417,6 @@ export function splitHtmlTagNamespace(elementName: string): string[] { return [match[1], match[2]]; } -export function getHtmlTagNamespacePrefix(elementName: string): string { - return splitHtmlTagNamespace(elementName)[0]; +export function getNsPrefix(elementName: string): string { + return splitNsName(elementName)[0]; } diff --git a/modules/angular2/src/compiler/schema/dom_element_schema_registry.ts b/modules/angular2/src/compiler/schema/dom_element_schema_registry.ts index 751e420a43..84a9230fe3 100644 --- a/modules/angular2/src/compiler/schema/dom_element_schema_registry.ts +++ b/modules/angular2/src/compiler/schema/dom_element_schema_registry.ts @@ -2,7 +2,7 @@ import {Injectable} from 'angular2/src/core/di'; import {isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang'; import {StringMapWrapper} from 'angular2/src/facade/collection'; import {DOM} from 'angular2/src/platform/dom/dom_adapter'; -import {splitHtmlTagNamespace} from 'angular2/src/compiler/html_tags'; +import {splitNsName} from 'angular2/src/compiler/html_tags'; import {ElementSchemaRegistry} from './element_schema_registry'; @@ -16,7 +16,7 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry { private _getProtoElement(tagName: string): Element { var element = this._protoElements.get(tagName); if (isBlank(element)) { - var nsAndName = splitHtmlTagNamespace(tagName); + var nsAndName = splitNsName(tagName); element = isPresent(nsAndName[0]) ? DOM.createElementNS(NAMESPACE_URIS[nsAndName[0]], nsAndName[1]) : DOM.createElement(nsAndName[1]); diff --git a/modules/angular2/src/compiler/template_parser.ts b/modules/angular2/src/compiler/template_parser.ts index dbb26076c7..32a69f58b1 100644 --- a/modules/angular2/src/compiler/template_parser.ts +++ b/modules/angular2/src/compiler/template_parser.ts @@ -7,7 +7,7 @@ import {Parser, AST, ASTWithSource} from 'angular2/src/core/change_detection/cha import {TemplateBinding} from 'angular2/src/core/change_detection/parser/ast'; import {CompileDirectiveMetadata} from './directive_metadata'; import {HtmlParser} from './html_parser'; -import {splitHtmlTagNamespace} from './html_tags'; +import {splitNsName} from './html_tags'; import {ParseSourceSpan, ParseError, ParseLocation} from './parse_util'; @@ -216,7 +216,7 @@ class TemplateParseVisitor implements HtmlAstVisitor { } }); - var lcElName = splitHtmlTagNamespace(nodeName.toLowerCase())[1]; + var lcElName = splitNsName(nodeName.toLowerCase())[1]; var isTemplateElement = lcElName == TEMPLATE_ELEMENT; var elementCssSelector = createElementCssSelector(nodeName, matchableAttrs); var directives = this._createDirectiveAsts( @@ -687,13 +687,17 @@ class Component { function createElementCssSelector(elementName: string, matchableAttrs: string[][]): CssSelector { var cssSelector = new CssSelector(); + let elNameNoNs = splitNsName(elementName)[1]; + + cssSelector.setElement(elNameNoNs); - cssSelector.setElement(elementName); for (var i = 0; i < matchableAttrs.length; i++) { - var attrName = matchableAttrs[i][0]; - var attrValue = matchableAttrs[i][1]; - cssSelector.addAttribute(attrName, attrValue); - if (attrName == CLASS_ATTR) { + let attrName = matchableAttrs[i][0]; + let attrNameNoNs = splitNsName(attrName)[1]; + let attrValue = matchableAttrs[i][1]; + + cssSelector.addAttribute(attrNameNoNs, attrValue); + if (attrName.toLowerCase() == CLASS_ATTR) { var classes = splitClasses(attrValue); classes.forEach(className => cssSelector.addClassName(className)); } diff --git a/modules/angular2/test/compiler/template_parser_spec.ts b/modules/angular2/test/compiler/template_parser_spec.ts index 2d6b54b434..21916aacc1 100644 --- a/modules/angular2/test/compiler/template_parser_spec.ts +++ b/modules/angular2/test/compiler/template_parser_spec.ts @@ -908,6 +908,24 @@ Property binding a not used by any directive on an embedded template ("[ERROR -> ]); }); + it('should support directive in namespace', () => { + var tagSel = CompileDirectiveMetadata.create( + {selector: 'circle', type: new CompileTypeMetadata({name: 'elDir'})}); + var attrSel = CompileDirectiveMetadata.create( + {selector: '[href]', type: new CompileTypeMetadata({name: 'attrDir'})}); + + expect(humanizeTplAstSourceSpans( + parse('', [tagSel, attrSel]))) + .toEqual([ + [ElementAst, '@svg:svg', ''], + [ElementAst, '@svg:circle', ''], + [DirectiveAst, tagSel, ''], + [ElementAst, '@svg:use', ''], + [AttrAst, '@xlink:href', 'Port', 'xlink:href="Port"'], + [DirectiveAst, attrSel, ''], + ]); + }); + it('should support directive property', () => { var dirA = CompileDirectiveMetadata.create( {selector: 'div', type: new CompileTypeMetadata({name: 'DirA'}), inputs: ['aProp']});