diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/component.ts b/packages/compiler-cli/src/ngtsc/annotations/src/component.ts
index f68f4bc21d..9f1805088c 100644
--- a/packages/compiler-cli/src/ngtsc/annotations/src/component.ts
+++ b/packages/compiler-cli/src/ngtsc/annotations/src/component.ts
@@ -879,6 +879,9 @@ export class ComponentDecoratorHandler implements
//
// In order to guarantee the correctness of diagnostics, templates are parsed a second time
// with the above options set to preserve source mappings.
+ //
+ // Note: template parse options should be aligned with `template_target_spec.ts` and
+ // `TemplateTypeCheckerImpl.overrideComponentTemplate`.
const {nodes: diagNodes} = parseTemplate(templateStr, template.sourceMapUrl, {
preserveWhitespaces: true,
diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts
index 68ff907a02..6a63764c81 100644
--- a/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts
+++ b/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts
@@ -154,6 +154,11 @@ export class TemplateTypeCheckerImpl implements TemplateTypeChecker {
overrideComponentTemplate(component: ts.ClassDeclaration, template: string):
{nodes: TmplAstNode[], errors: ParseError[]|null} {
const {nodes, errors} = parseTemplate(template, 'override.html', {
+ // Set `leadingTriviaChars` and `preserveWhitespaces` such that whitespace is not stripped
+ // and fully accounted for in source spans. Without these flags the source spans can be
+ // inaccurate.
+ // Note: template parse options should be aligned with `template_target_spec.ts` and the
+ // `diagNodes` in `ComponentDecoratorHandler._parseTemplate`.
preserveWhitespaces: true,
leadingTriviaChars: [],
});
diff --git a/packages/compiler-cli/test/compliance/test_cases/source_mapping/external_templates/escaped_chars.js b/packages/compiler-cli/test/compliance/test_cases/source_mapping/external_templates/escaped_chars.js
index 51a98de501..0ecf510659 100644
--- a/packages/compiler-cli/test/compliance/test_cases/source_mapping/external_templates/escaped_chars.js
+++ b/packages/compiler-cli/test/compliance/test_cases/source_mapping/external_templates/escaped_chars.js
@@ -1,4 +1,4 @@
-i0.ɵɵelementStart(0, "div") // SOURCE: "/escaped_chars.html"
…
// NOTE: the `\\r\\n` at the end of the next line will be unescaped to `\r\n`. If it was just `\r\n` it would get unescaped to the actual characters.
i0.ɵɵtext(1, " Some Message Encoded character: \uD83D\uDE80\\n") // SOURCE: "/escaped_chars.html" Some Message\r\n Encoded character: 🚀\\r\\n
diff --git a/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/i18n_message_element_whitespace.js b/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/i18n_message_element_whitespace.js
index d72da22f8c..f0be5ea453 100644
--- a/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/i18n_message_element_whitespace.js
+++ b/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/i18n_message_element_whitespace.js
@@ -9,9 +9,9 @@
}:CLOSE_PARAGRAPH: post-p\n` // SOURCE: "/i18n_message_element_whitespace.ts" post-p\\n
…
-i0.ɵɵelementStart(0, "div") // SOURCE: "/i18n_message_element_whitespace.ts"