fix(compiler): allow WS as `<ng-content>` content (#12225)

This commit is contained in:
Victor Berchet 2016-10-12 07:58:06 -07:00 committed by Tobias Bosch
parent 17e3410d98
commit df1718d624
2 changed files with 17 additions and 9 deletions

View File

@ -428,10 +428,8 @@ class TemplateParseVisitor implements html.Visitor {
let parsedElement: TemplateAst; let parsedElement: TemplateAst;
if (preparsedElement.type === PreparsedElementType.NG_CONTENT) { if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
if (isPresent(element.children) && element.children.length > 0) { if (element.children && !element.children.every(_isEmptyTextNode)) {
this._reportError( this._reportError(`<ng-content> element cannot have content.`, element.sourceSpan);
`<ng-content> element cannot have content. <ng-content> must be immediately followed by </ng-content>`,
element.sourceSpan);
} }
parsedElement = new NgContentAst( parsedElement = new NgContentAst(
@ -1201,3 +1199,7 @@ export class PipeCollector extends RecursiveAstVisitor {
function _isAnimationLabel(name: string): boolean { function _isAnimationLabel(name: string): boolean {
return name[0] == '@'; return name[0] == '@';
} }
function _isEmptyTextNode(node: html.Node): boolean {
return node instanceof html.Text && node.value.trim().length == 0;
}

View File

@ -274,12 +274,17 @@ export function main() {
}); });
it('should parse ngContent', () => { it('should parse ngContent', () => {
var parsed = parse('<ng-content select="a">', []); const parsed = parse('<ng-content select="a"></ng-content>', []);
expect(humanizeTplAst(parsed)).toEqual([[NgContentAst]]);
});
it('should parse ngContent when it contains WS only', () => {
const parsed = parse('<ng-content select="a"> \n </ng-content>', []);
expect(humanizeTplAst(parsed)).toEqual([[NgContentAst]]); expect(humanizeTplAst(parsed)).toEqual([[NgContentAst]]);
}); });
it('should parse ngContent regardless the namespace', () => { it('should parse ngContent regardless the namespace', () => {
var parsed = parse('<svg><ng-content></ng-content></svg>', []); const parsed = parse('<svg><ng-content></ng-content></svg>', []);
expect(humanizeTplAst(parsed)).toEqual([ expect(humanizeTplAst(parsed)).toEqual([
[ElementAst, ':svg:svg'], [ElementAst, ':svg:svg'],
[NgContentAst], [NgContentAst],
@ -1418,10 +1423,11 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
}); });
describe('error cases', () => { describe('error cases', () => {
it('should report when ng-content has content', () => { it('should report when ng-content has non WS content', () => {
expect(() => parse('<ng-content>content</ng-content>', [])) expect(() => parse('<ng-content>content</ng-content>', []))
.toThrowError(`Template parse errors: .toThrowError(
<ng-content> element cannot have content. <ng-content> must be immediately followed by </ng-content> ("[ERROR ->]<ng-content>content</ng-content>"): TestComp@0:0`); `Template parse errors:\n` +
`<ng-content> element cannot have content. ("[ERROR ->]<ng-content>content</ng-content>"): TestComp@0:0`);
}); });
it('should treat *attr on a template element as valid', it('should treat *attr on a template element as valid',