From d4ec697cb95dfc71bd16f98289536b5134649720 Mon Sep 17 00:00:00 2001 From: Roman Dvornov Date: Fri, 9 Apr 2021 16:40:13 +0200 Subject: [PATCH] Initial work on ident encode/decode --- lib/syntax/node/ClassSelector.js | 5 +++-- lib/syntax/node/Dimension.js | 5 +++-- lib/syntax/node/IdSelector.js | 5 +++-- lib/syntax/node/Identifier.js | 5 +++-- lib/utils/ident.js | 4 ++-- test/fixture/ast/mediaQuery/MediaQuery.json | 3 ++- test/fixture/ast/selector/ClassSelector.json | 11 ++++++----- test/fixture/ast/selector/Selector.json | 2 +- test/fixture/ast/value/Dimension.json | 3 ++- test/fixture/ast/value/Value.json | 6 ++++-- test/fixture/stringify.ast | 2 +- test/fixture/stringify.css | 2 +- 12 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/syntax/node/ClassSelector.js b/lib/syntax/node/ClassSelector.js index 8a899d6b..0dc02635 100644 --- a/lib/syntax/node/ClassSelector.js +++ b/lib/syntax/node/ClassSelector.js @@ -1,4 +1,5 @@ const { Delim, Ident } = require('../../tokenizer/types'); +const { decode, encode } = require('../../utils/ident'); const FULLSTOP = 0x002E; // U+002E FULL STOP (.) @@ -14,11 +15,11 @@ module.exports = { return { type: 'ClassSelector', loc: this.getLocation(this.tokenStart - 1, this.tokenEnd), - name: this.consume(Ident) + name: decode(this.consume(Ident)) }; }, generate: function(node) { this.token(Delim, '.'); - this.token(Ident, node.name); + this.token(Ident, encode(node.name)); } }; diff --git a/lib/syntax/node/Dimension.js b/lib/syntax/node/Dimension.js index f5bc7279..a6dcef2c 100644 --- a/lib/syntax/node/Dimension.js +++ b/lib/syntax/node/Dimension.js @@ -1,4 +1,5 @@ const { Dimension } = require('../../tokenizer/types'); +const { decode, encode } = require('../../utils/ident'); module.exports = { name: 'Dimension', @@ -14,10 +15,10 @@ module.exports = { type: 'Dimension', loc: this.getLocation(start, this.tokenStart), value, - unit: this.substring(start + value.length, this.tokenStart) + unit: decode(this.substrToCursor(start + value.length)) }; }, generate: function(node) { - this.token(Dimension, node.value + node.unit); + this.token(Dimension, node.value + encode(node.unit)); } }; diff --git a/lib/syntax/node/IdSelector.js b/lib/syntax/node/IdSelector.js index 9b8011ac..841f6003 100644 --- a/lib/syntax/node/IdSelector.js +++ b/lib/syntax/node/IdSelector.js @@ -1,4 +1,5 @@ const { Hash } = require('../../tokenizer/types'); +const { decode, encode } = require('../../utils/ident'); // module.exports = { @@ -15,10 +16,10 @@ module.exports = { return { type: 'IdSelector', loc: this.getLocation(start, this.tokenStart), - name: this.substrToCursor(start + 1) + name: decode(this.substrToCursor(start + 1)) }; }, generate: function(node) { - this.token(Hash, '#' + node.name); + this.token(Hash, '#' + encode(node.name)); } }; diff --git a/lib/syntax/node/Identifier.js b/lib/syntax/node/Identifier.js index e495d3d8..17ea27d8 100644 --- a/lib/syntax/node/Identifier.js +++ b/lib/syntax/node/Identifier.js @@ -1,4 +1,5 @@ const { Ident } = require('../../tokenizer/types'); +const { decode, encode } = require('../../utils/ident'); module.exports = { name: 'Identifier', @@ -9,10 +10,10 @@ module.exports = { return { type: 'Identifier', loc: this.getLocation(this.tokenStart, this.tokenEnd), - name: this.consume(Ident) + name: decode(this.consume(Ident)) }; }, generate: function(node) { - this.token(Ident, node.name); + this.token(Ident, encode(node.name)); } }; diff --git a/lib/utils/ident.js b/lib/utils/ident.js index 9f05d224..d2931fc0 100644 --- a/lib/utils/ident.js +++ b/lib/utils/ident.js @@ -89,10 +89,10 @@ function encode(str) { // of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to U+005A), // or \[a-z] (U+0061 to U+007A), then the character itself. if (isName(code)) { - encoded += str.charAt(i); + encoded += str[i]; } else { // Otherwise, the escaped character. - encoded += '\\' + str.charAt(i); + encoded += '\\' + str[i]; } } diff --git a/test/fixture/ast/mediaQuery/MediaQuery.json b/test/fixture/ast/mediaQuery/MediaQuery.json index 699ef495..b52b6399 100644 --- a/test/fixture/ast/mediaQuery/MediaQuery.json +++ b/test/fixture/ast/mediaQuery/MediaQuery.json @@ -152,6 +152,7 @@ }, "number with \\0 hack": { "source": "(min-width:0\\0)", + "generate": "(min-width:0\uFFFD)", "ast": { "type": "MediaQuery", "children": [ @@ -161,7 +162,7 @@ "value": { "type": "Dimension", "value": "0", - "unit": "\\0" + "unit": "\uFFFD" } } ] diff --git a/test/fixture/ast/selector/ClassSelector.json b/test/fixture/ast/selector/ClassSelector.json index b618e5c6..ffea89e5 100644 --- a/test/fixture/ast/selector/ClassSelector.json +++ b/test/fixture/ast/selector/ClassSelector.json @@ -17,35 +17,36 @@ "source": ".\\31 0\\+", "ast": { "type": "ClassSelector", - "name": "\\31 0\\+" + "name": "10+" } }, "escaped class selector #2": { "source": ".\\31 b", "ast": { "type": "ClassSelector", - "name": "\\31 b" + "name": "1b" } }, "escaped class selector #3": { "source": ".\\31 \\ b", "ast": { "type": "ClassSelector", - "name": "\\31 \\ b" + "name": "1 b" } }, "escaped class selector #4": { "source": ".\\30 \\30\r\\30\r\n\\30\n\\30\f", + "generate": ".\\30 0000", "ast": { "type": "ClassSelector", - "name": "\\30 \\30\r\\30\r\n\\30\n\\30\f" + "name": "00000" } }, "escaped class selector #5": { "source": ".test\\(1\\)", "ast": { "type": "ClassSelector", - "name": "test\\(1\\)" + "name": "test(1)" } } } diff --git a/test/fixture/ast/selector/Selector.json b/test/fixture/ast/selector/Selector.json index 0bd1a034..50d1ffa0 100644 --- a/test/fixture/ast/selector/Selector.json +++ b/test/fixture/ast/selector/Selector.json @@ -97,7 +97,7 @@ "children": [ { "type": "ClassSelector", - "name": "\\31 " + "name": "1" }, { "type": "Combinator", diff --git a/test/fixture/ast/value/Dimension.json b/test/fixture/ast/value/Dimension.json index 24c66577..e12d2615 100644 --- a/test/fixture/ast/value/Dimension.json +++ b/test/fixture/ast/value/Dimension.json @@ -33,10 +33,11 @@ }, "IE hack": { "source": "1px\\9", + "generate": "1px\\9 ", "ast": { "type": "Dimension", "value": "1", - "unit": "px\\9" + "unit": "px\t" } } } diff --git a/test/fixture/ast/value/Value.json b/test/fixture/ast/value/Value.json index 241b014d..ebd46550 100644 --- a/test/fixture/ast/value/Value.json +++ b/test/fixture/ast/value/Value.json @@ -147,26 +147,28 @@ "should parse number with following \\0 or \\9 hack as Dimension": [ { "source": "1\\0", + "generate": "1\uFFFD", "ast": { "type": "Value", "children": [ { "type": "Dimension", "value": "1", - "unit": "\\0" + "unit": "\uFFFD" } ] } }, { "source": "1\\9", + "generate": "1\\9 ", "ast": { "type": "Value", "children": [ { "type": "Dimension", "value": "1", - "unit": "\\9" + "unit": "\t" } ] } diff --git a/test/fixture/stringify.ast b/test/fixture/stringify.ast index 947e950b..ba1d8cd9 100644 --- a/test/fixture/stringify.ast +++ b/test/fixture/stringify.ast @@ -4214,7 +4214,7 @@ "column": 16 } }, - "name": "c\\61ases" + "name": "cases" } ] } diff --git a/test/fixture/stringify.css b/test/fixture/stringify.css index ea8f81cb..32f836bd 100644 --- a/test/fixture/stringify.css +++ b/test/fixture/stringify.css @@ -48,7 +48,7 @@ svg|*:matches(a)::slotted(c) > :nth-child(odd of a, :b):nth-child(2n + 1 of [a]) 100% { ;color: blue;; } } -edge\ .c\61ases { +edge\ .c\61 ses { --empty-var: ; --bad-var:; number: 0.1.2.3;