From 13613d4acbd3eb55a8747ee47d2f0853eb6997ba Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Mon, 25 Sep 2017 13:33:31 -0700 Subject: [PATCH] fix(compiler): skip   when trimming / removing whitespaces (#19310) Fixes #19304 --- packages/compiler/src/ml_parser/html_whitespaces.ts | 13 ++++++++++--- .../test/ml_parser/html_whitespaces_spec.ts | 10 ++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/packages/compiler/src/ml_parser/html_whitespaces.ts b/packages/compiler/src/ml_parser/html_whitespaces.ts index 73e5b48665..c9302a7288 100644 --- a/packages/compiler/src/ml_parser/html_whitespaces.ts +++ b/packages/compiler/src/ml_parser/html_whitespaces.ts @@ -14,6 +14,12 @@ export const PRESERVE_WS_ATTR_NAME = 'ngPreserveWhitespaces'; const SKIP_WS_TRIM_TAGS = new Set(['pre', 'template', 'textarea', 'script', 'style']); +// Equivalent to \s with \u00a0 (non-breaking space) excluded. +// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp +const WS_CHARS = ' \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff'; +const NO_WS_REGEXP = new RegExp(`[^${WS_CHARS}]`); +const WS_REPLACE_REGEXP = new RegExp(`[${WS_CHARS}]{2,}`, 'g'); + function hasPreserveWhitespacesAttr(attrs: html.Attribute[]): boolean { return attrs.some((attr: html.Attribute) => attr.name === PRESERVE_WS_ATTR_NAME); } @@ -63,10 +69,11 @@ class WhitespaceVisitor implements html.Visitor { } visitText(text: html.Text, context: any): any { - const isBlank = text.value.trim().length === 0; + const isNotBlank = text.value.match(NO_WS_REGEXP); - if (!isBlank) { - return new html.Text(replaceNgsp(text.value).replace(/\s\s+/g, ' '), text.sourceSpan); + if (isNotBlank) { + return new html.Text( + replaceNgsp(text.value).replace(WS_REPLACE_REGEXP, ' '), text.sourceSpan); } return null; diff --git a/packages/compiler/test/ml_parser/html_whitespaces_spec.ts b/packages/compiler/test/ml_parser/html_whitespaces_spec.ts index 7f9f6fa898..bb7c9a8470 100644 --- a/packages/compiler/test/ml_parser/html_whitespaces_spec.ts +++ b/packages/compiler/test/ml_parser/html_whitespaces_spec.ts @@ -64,6 +64,16 @@ export function main() { expect(parseAndRemoveWS(' \n foo \t ')).toEqual([[html.Text, ' foo ', 0]]); }); + it('should not replace  ', () => { + expect(parseAndRemoveWS(' ')).toEqual([[html.Text, '\u00a0', 0]]); + }); + + it('should not replace sequences of  ', () => { + expect(parseAndRemoveWS('  foo  ')).toEqual([ + [html.Text, '\u00a0\u00a0foo\u00a0\u00a0', 0] + ]); + }); + it('should not replace single tab and newline with spaces', () => { expect(parseAndRemoveWS('\nfoo')).toEqual([[html.Text, '\nfoo', 0]]); expect(parseAndRemoveWS('\tfoo')).toEqual([[html.Text, '\tfoo', 0]]);