From 50eb37292970181329162fdc98e9d8f18f917a53 Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Fri, 3 Apr 2020 09:43:52 -0700 Subject: [PATCH] fix(css): parse css selectors with escape sequences (for real) (#8496) * fix(css): CSS escape sequences * Missing semicolon Co-authored-by: Vasil Trifonov --- nativescript-core/css/parser.ts | 10 ++++++-- tests/app/ui/styling/style-tests.ts | 37 +++++++++++++++++------------ 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/nativescript-core/css/parser.ts b/nativescript-core/css/parser.ts index 7782259fe..60eb7ba6e 100644 --- a/nativescript-core/css/parser.ts +++ b/nativescript-core/css/parser.ts @@ -804,10 +804,16 @@ export function parseUniversalSelector(text: string, start: number = 0): Parsed< return { start, end, value: { type: "*" } }; } -const simpleIdentifierSelectorRegEx = /(#|\.|:|\b)([_-\w][_-\w\d\\/]*)/gy; +const simpleIdentifierSelectorRegEx = /(#|\.|:|\b)((?:[\w_-]|\\.)(?:[\w\d_-]|\\.)*)/gyu; +const unicodeEscapeRegEx = /\\([0-9a-fA-F]{1,5}\s|[0-9a-fA-F]{6})/g; export function parseSimpleIdentifierSelector(text: string, start: number = 0): Parsed { simpleIdentifierSelectorRegEx.lastIndex = start; - const result = simpleIdentifierSelectorRegEx.exec(text); + const result = simpleIdentifierSelectorRegEx.exec( + text.replace( + unicodeEscapeRegEx, + (_, c) => "\\" + String.fromCodePoint(parseInt(c.trim(), 16)) + ) + ); if (!result) { return null; } diff --git a/tests/app/ui/styling/style-tests.ts b/tests/app/ui/styling/style-tests.ts index ee4b83443..4d104891a 100644 --- a/tests/app/ui/styling/style-tests.ts +++ b/tests/app/ui/styling/style-tests.ts @@ -200,25 +200,32 @@ export function test_class_selector() { export function test_class_selector_with_escape_characters() { let page = helper.getClearCurrentPage(); - let btnWithClass1: buttonModule.Button; - let btnWithClass2: buttonModule.Button; - - page.css = ".test-1 { color: red; } .test-1\\/2 { color: blue }"; - - //// Will be styled - btnWithClass1 = new buttonModule.Button(); - btnWithClass1.className = "test-1"; - - btnWithClass2 = new buttonModule.Button(); - btnWithClass2.className = "test-1/2"; + page.css = ` + .test-1 { color: red; } + .test-1\\/2, .test-1\\:2, .\\61 f, .\\1F642 { color: blue } + `; const stack = new stackModule.StackLayout(); page.content = stack; - stack.addChild(btnWithClass1); - stack.addChild(btnWithClass2); - helper.assertViewColor(btnWithClass1, "#FF0000"); - helper.assertViewColor(btnWithClass2, "#0000FF"); + let btn: buttonModule.Button = new buttonModule.Button(); + stack.addChild(btn); + + //// Will be styled + btn.className = "test-1"; + helper.assertViewColor(btn, "#FF0000"); + + btn.className = "test-1/2"; + helper.assertViewColor(btn, "#0000FF"); + + btn.className = "test-1:2"; + helper.assertViewColor(btn, "#0000FF"); + + btn.className = "af"; + helper.assertViewColor(btn, "#0000FF"); + + btn.className = "\u{1F642}"; + helper.assertViewColor(btn, "#0000FF"); } export function test_multiple_class_selector() {