diff --git a/packages/compiler/src/ml_parser/lexer.ts b/packages/compiler/src/ml_parser/lexer.ts
index 3c8b04ab61b4..013b2eb1505f 100644
--- a/packages/compiler/src/ml_parser/lexer.ts
+++ b/packages/compiler/src/ml_parser/lexer.ts
@@ -1431,7 +1431,12 @@ function isDigitEntityEnd(code: number): boolean {
}
function isNamedEntityEnd(code: number): boolean {
- return code === chars.$SEMICOLON || code === chars.$EOF || !chars.isAsciiLetter(code);
+ // Named entities may contain digits (e.g. ¹, ½, ▓).
+ return (
+ code === chars.$SEMICOLON ||
+ code === chars.$EOF ||
+ !(chars.isAsciiLetter(code) || chars.isDigit(code))
+ );
}
function isExpansionCaseStart(peek: number): boolean {
diff --git a/packages/compiler/test/ml_parser/html_parser_spec.ts b/packages/compiler/test/ml_parser/html_parser_spec.ts
index 47b956aea40e..2ea1422e793d 100644
--- a/packages/compiler/test/ml_parser/html_parser_spec.ts
+++ b/packages/compiler/test/ml_parser/html_parser_spec.ts
@@ -68,6 +68,17 @@ describe('HtmlParser', () => {
]);
});
+ it('should parse named HTML entities containing digits', () => {
+ expect(humanizeDom(parser.parse('
¹
', 'TestComp'))).toEqual([
+ [html.Element, 'div', 0],
+ [html.Text, '\u00B9', 1, [''], ['\u00B9', '¹'], ['']],
+ ]);
+ expect(humanizeDom(parser.parse('½
', 'TestComp'))).toEqual([
+ [html.Element, 'div', 0],
+ [html.Text, '\u00BD', 1, [''], ['\u00BD', '½'], ['']],
+ ]);
+ });
+
it('should normalize line endings within CDATA', () => {
const parsed = parser.parse('', 'TestComp');
expect(humanizeDom(parsed)).toEqual([
diff --git a/packages/compiler/test/ml_parser/lexer_spec.ts b/packages/compiler/test/ml_parser/lexer_spec.ts
index 9d7bbd1c5c74..e3ebac0e8270 100644
--- a/packages/compiler/test/ml_parser/lexer_spec.ts
+++ b/packages/compiler/test/ml_parser/lexer_spec.ts
@@ -2094,6 +2094,27 @@ describe('HtmlLexer', () => {
]);
});
+ it('should parse named entities containing digits', () => {
+ expect(tokenizeAndHumanizeParts('¹')).toEqual([
+ [TokenType.TEXT, ''],
+ [TokenType.ENCODED_ENTITY, '\u00B9', '¹'],
+ [TokenType.TEXT, ''],
+ [TokenType.EOF],
+ ]);
+ expect(tokenizeAndHumanizeParts('½')).toEqual([
+ [TokenType.TEXT, ''],
+ [TokenType.ENCODED_ENTITY, '\u00BD', '½'],
+ [TokenType.TEXT, ''],
+ [TokenType.EOF],
+ ]);
+ expect(tokenizeAndHumanizeParts('▓')).toEqual([
+ [TokenType.TEXT, ''],
+ [TokenType.ENCODED_ENTITY, '\u2593', '▓'],
+ [TokenType.TEXT, ''],
+ [TokenType.EOF],
+ ]);
+ });
+
it('should parse hexadecimal entities', () => {
expect(tokenizeAndHumanizeParts('AA')).toEqual([
[TokenType.TEXT, ''],