fix(HtmlParser): ng-content is not a void element
fixes #5563 Closes #5586
This commit is contained in:
parent
0614797d84
commit
e67e1952d0
|
@ -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}),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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'
|
||||
]
|
||||
]);
|
||||
});
|
||||
|
|
|
@ -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`);
|
||||
|
|
Loading…
Reference in New Issue