diff --git a/modules/angular2/src/compiler/html_parser.ts b/modules/angular2/src/compiler/html_parser.ts index fc9c9a234d..579cbc37cd 100644 --- a/modules/angular2/src/compiler/html_parser.ts +++ b/modules/angular2/src/compiler/html_parser.ts @@ -106,7 +106,18 @@ class TreeBuilder { } private _consumeText(token: HtmlToken) { - this._addToParent(new HtmlTextAst(token.parts[0], token.sourceSpan)); + let text = token.parts[0]; + if (text.length > 0 && text[0] == '\n') { + let parent = this._getParentElement(); + if (isPresent(parent) && parent.children.length == 0 && + getHtmlTagDefinition(parent.name).ignoreFirstLf) { + text = text.substring(1); + } + } + + if (text.length > 0) { + this._addToParent(new HtmlTextAst(text, token.sourceSpan)); + } } private _closeVoidElement(): void { diff --git a/modules/angular2/src/compiler/html_tags.ts b/modules/angular2/src/compiler/html_tags.ts index e45ff34d16..6fc4f23fe5 100644 --- a/modules/angular2/src/compiler/html_tags.ts +++ b/modules/angular2/src/compiler/html_tags.ts @@ -279,15 +279,17 @@ export class HtmlTagDefinition { public implicitNamespacePrefix: string; public contentType: HtmlTagContentType; public isVoid: boolean; + public ignoreFirstLf: boolean; constructor({closedByChildren, requiredParents, implicitNamespacePrefix, contentType, - closedByParent, isVoid}: { + closedByParent, isVoid, ignoreFirstLf}: { closedByChildren?: string[], closedByParent?: boolean, requiredParents?: string[], implicitNamespacePrefix?: string, contentType?: HtmlTagContentType, - isVoid?: boolean + isVoid?: boolean, + ignoreFirstLf?: boolean } = {}) { if (isPresent(closedByChildren) && closedByChildren.length > 0) { closedByChildren.forEach(tagName => this.closedByChildren[tagName] = true); @@ -301,6 +303,7 @@ export class HtmlTagDefinition { } this.implicitNamespacePrefix = implicitNamespacePrefix; this.contentType = isPresent(contentType) ? contentType : HtmlTagContentType.PARSABLE_DATA; + this.ignoreFirstLf = normalizeBool(ignoreFirstLf); } requireExtraParent(currentParent: string): boolean { @@ -388,10 +391,13 @@ var TAG_DEFINITIONS: {[key: string]: HtmlTagDefinition} = { 'rp': new HtmlTagDefinition({closedByChildren: ['rb', 'rt', 'rtc', 'rp'], closedByParent: true}), 'optgroup': new HtmlTagDefinition({closedByChildren: ['optgroup'], closedByParent: true}), 'option': new HtmlTagDefinition({closedByChildren: ['option', 'optgroup'], closedByParent: true}), + 'pre': new HtmlTagDefinition({ignoreFirstLf: true}), + 'listing': new HtmlTagDefinition({ignoreFirstLf: true}), 'style': new HtmlTagDefinition({contentType: HtmlTagContentType.RAW_TEXT}), 'script': new HtmlTagDefinition({contentType: HtmlTagContentType.RAW_TEXT}), 'title': new HtmlTagDefinition({contentType: HtmlTagContentType.ESCAPABLE_RAW_TEXT}), - 'textarea': new HtmlTagDefinition({contentType: HtmlTagContentType.ESCAPABLE_RAW_TEXT}), + 'textarea': new HtmlTagDefinition( + {contentType: HtmlTagContentType.ESCAPABLE_RAW_TEXT, ignoreFirstLf: true}), }; var DEFAULT_TAG_DEFINITION = new HtmlTagDefinition(); diff --git a/modules/angular2/test/compiler/html_parser_spec.ts b/modules/angular2/test/compiler/html_parser_spec.ts index a9217414f8..5094eb3a8d 100644 --- a/modules/angular2/test/compiler/html_parser_spec.ts +++ b/modules/angular2/test/compiler/html_parser_spec.ts @@ -178,6 +178,22 @@ export function main() { expect(humanizeDom(parser.parse('', 'TestComp'))) .toEqual([[HtmlElementAst, '@math:math', 0]]); }); + + it('should ignore LF immediately after textarea, pre and listing', () => { + expect(humanizeDom(parser.parse( + '

\n

\n\n
\n\n', + 'TestComp'))) + .toEqual([ + [HtmlElementAst, 'p', 0], + [HtmlTextAst, '\n', 1], + [HtmlElementAst, 'textarea', 0], + [HtmlElementAst, 'pre', 0], + [HtmlTextAst, '\n', 1], + [HtmlElementAst, 'listing', 0], + [HtmlTextAst, '\n', 1], + ]); + }); + }); describe('attributes', () => {