diff --git a/packages/compiler/src/i18n/i18n_ast.ts b/packages/compiler/src/i18n/i18n_ast.ts index 0a7159bbc185c..0f7c412205bb0 100644 --- a/packages/compiler/src/i18n/i18n_ast.ts +++ b/packages/compiler/src/i18n/i18n_ast.ts @@ -87,7 +87,7 @@ export class TagPlaceholder implements Node { constructor( public tag: string, public attrs: {[k: string]: string}, public startName: string, public closeName: string, public children: Node[], public isVoid: boolean, - public sourceSpan: ParseSourceSpan) {} + public sourceSpan: ParseSourceSpan, public closeSourceSpan: ParseSourceSpan|null) {} visit(visitor: Visitor, context?: any): any { return visitor.visitTagPlaceholder(this, context); @@ -151,7 +151,8 @@ export class CloneVisitor implements Visitor { visitTagPlaceholder(ph: TagPlaceholder, context?: any): TagPlaceholder { const children = ph.children.map(n => n.visit(this, context)); return new TagPlaceholder( - ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan); + ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan, + ph.closeSourceSpan); } visitPlaceholder(ph: Placeholder, context?: any): Placeholder { diff --git a/packages/compiler/src/i18n/i18n_parser.ts b/packages/compiler/src/i18n/i18n_parser.ts index 1a1f7f35bd179..923a9d8dff628 100644 --- a/packages/compiler/src/i18n/i18n_parser.ts +++ b/packages/compiler/src/i18n/i18n_parser.ts @@ -93,7 +93,8 @@ class _I18nVisitor implements html.Visitor { } const node = new i18n.TagPlaceholder( - el.name, attrs, startPhName, closePhName, children, isVoid, el.sourceSpan!); + el.name, attrs, startPhName, closePhName, children, isVoid, el.startSourceSpan!, + el.endSourceSpan); return context.visitNodeFn(el, node); } @@ -167,22 +168,32 @@ class _I18nVisitor implements html.Visitor { if (splitInterpolation.strings[i].length) { // No need to add empty strings - nodes.push(new i18n.Text(splitInterpolation.strings[i], sourceSpan)); + const stringSpan = getOffsetSourceSpan(sourceSpan, splitInterpolation.stringSpans[i]); + nodes.push(new i18n.Text(splitInterpolation.strings[i], stringSpan)); } - nodes.push(new i18n.Placeholder(expression, phName, sourceSpan)); + const expressionSpan = + getOffsetSourceSpan(sourceSpan, splitInterpolation.expressionsSpans[i]); + nodes.push(new i18n.Placeholder(expression, phName, expressionSpan)); context.placeholderToContent[phName] = sDelimiter + expression + eDelimiter; } // The last index contains no expression const lastStringIdx = splitInterpolation.strings.length - 1; if (splitInterpolation.strings[lastStringIdx].length) { - nodes.push(new i18n.Text(splitInterpolation.strings[lastStringIdx], sourceSpan)); + const stringSpan = + getOffsetSourceSpan(sourceSpan, splitInterpolation.stringSpans[lastStringIdx]); + nodes.push(new i18n.Text(splitInterpolation.strings[lastStringIdx], stringSpan)); } return container; } } +function getOffsetSourceSpan( + sourceSpan: ParseSourceSpan, {start, end}: {start: number, end: number}): ParseSourceSpan { + return new ParseSourceSpan(sourceSpan.start.moveBy(start), sourceSpan.start.moveBy(end)); +} + const _CUSTOM_PH_EXP = /\/\/[\s\S]*i18n[\s\S]*\([\s\S]*ph[\s\S]*=[\s\S]*("|')([\s\S]*?)\1[\s\S]*\)/g; diff --git a/packages/compiler/src/i18n/message_bundle.ts b/packages/compiler/src/i18n/message_bundle.ts index 37fb284604d53..036b6d45fb175 100644 --- a/packages/compiler/src/i18n/message_bundle.ts +++ b/packages/compiler/src/i18n/message_bundle.ts @@ -94,7 +94,8 @@ class MapPlaceholderNames extends i18n.CloneVisitor { const closeName = ph.closeName ? mapper.toPublicName(ph.closeName)! : ph.closeName; const children = ph.children.map(n => n.visit(this, mapper)); return new i18n.TagPlaceholder( - ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan); + ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan, + ph.closeSourceSpan); } visitPlaceholder(ph: i18n.Placeholder, mapper: PlaceholderMapper): i18n.Placeholder { diff --git a/packages/compiler/test/i18n/serializers/i18n_ast_spec.ts b/packages/compiler/test/i18n/serializers/i18n_ast_spec.ts index 3ee5872d416f7..910bb735334f2 100644 --- a/packages/compiler/test/i18n/serializers/i18n_ast_spec.ts +++ b/packages/compiler/test/i18n/serializers/i18n_ast_spec.ts @@ -41,7 +41,7 @@ import {_extractMessages} from '../i18n_parser_spec'; new i18n.IcuPlaceholder(null!, '', null!), ], null!); - const tag = new i18n.TagPlaceholder('', {}, '', '', [container], false, null!); + const tag = new i18n.TagPlaceholder('', {}, '', '', [container], false, null!, null); const icu = new i18n.Icu('', '', {tag}, null!); icu.visit(visitor);