fix(HtmlParser): ng-content is not a void element

fixes #5563
Closes #5586
This commit is contained in:
Victor Berchet 2015-12-03 14:20:00 -08:00
parent 0614797d84
commit e67e1952d0
4 changed files with 21 additions and 11 deletions

View File

@ -311,7 +311,6 @@ export class HtmlTagDefinition {
// This implementation does not fully conform to the HTML5 spec.
var TAG_DEFINITIONS: {[key: string]: HtmlTagDefinition} = {
'link': new HtmlTagDefinition({isVoid: true}),
'ng-content': new HtmlTagDefinition({isVoid: true}),
'img': new HtmlTagDefinition({isVoid: true}),
'input': new HtmlTagDefinition({isVoid: true}),
'hr': new HtmlTagDefinition({isVoid: true}),

View File

@ -228,6 +228,11 @@ class TemplateParseVisitor implements HtmlAstVisitor {
hasInlineTemplates ? null : component.findNgContentIndex(elementCssSelector);
var parsedElement;
if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
if (isPresent(element.children) && element.children.length > 0) {
this._reportError(
`<ng-content> element cannot have content. <ng-content> must be immediately followed by </ng-content>`,
element.sourceSpan);
}
parsedElement =
new NgContentAst(this.ngContentCount++, elementNgContentIndex, element.sourceSpan);
} else if (isTemplateElement) {

View File

@ -86,8 +86,8 @@ export function main() {
});
it('should tolerate end tags for void elements when they have no content', () => {
expect(humanizeDom(parser.parse('<ng-content></ng-content>', 'TestComp')))
.toEqual([[HtmlElementAst, 'ng-content', 0]]);
expect(humanizeDom(parser.parse('<input></input>', 'TestComp')))
.toEqual([[HtmlElementAst, 'input', 0]]);
});
it('should support optional end tags', () => {
@ -215,27 +215,27 @@ export function main() {
});
it('should report text content in void elements', () => {
let errors = parser.parse('<ng-content>content</ng-content>', 'TestComp').errors;
let errors = parser.parse('<input>content</input>', 'TestComp').errors;
expect(errors.length).toEqual(1);
expect(humanizeErrors(errors))
.toEqual([
[
'ng-content',
'Void elements do not have end tags (they can not have content) "ng-content"',
'0:19'
'input',
'Void elements do not have end tags (they can not have content) "input"',
'0:14'
]
]);
});
it('should report html content in void elements', () => {
let errors = parser.parse('<ng-content><p></p></ng-content>', 'TestComp').errors;
let errors = parser.parse('<input><p></p></input>', 'TestComp').errors;
expect(errors.length).toEqual(1);
expect(humanizeErrors(errors))
.toEqual([
[
'ng-content',
'Void elements do not have end tags (they can not have content) "ng-content"',
'0:19'
'input',
'Void elements do not have end tags (they can not have content) "input"',
'0:14'
]
]);
});

View File

@ -689,6 +689,12 @@ There is no directive with "exportAs" set to "dirA" ("<div [ERROR ->]#a="dirA"><
});
describe('error cases', () => {
it('should report when ng-content has content', () => {
expect(() => parse('<ng-content>content</ng-content>', []))
.toThrowError(`Template parse errors:
<ng-content> element cannot have content. <ng-content> must be immediately followed by </ng-content> ("[ERROR ->]<ng-content>content</ng-content>"): TestComp@0:0`);
});
it('should report invalid property names', () => {
expect(() => parse('<div [invalid-prop]></div>', [])).toThrowError(`Template parse errors:
Can't bind to 'invalidProp' since it isn't a known native property ("<div [ERROR ->][invalid-prop]></div>"): TestComp@0:5`);