@nativescript/core 7.3.0-rc.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/css-tree-parser.js.map +1 -1
- package/css/parser.js +474 -442
- package/css/parser.js.map +1 -1
- package/package.json +1 -1
- package/ui/bottom-navigation/index.android.js +5 -3
- package/ui/bottom-navigation/index.android.js.map +1 -1
- package/ui/core/properties/index.d.ts +5 -2
- package/ui/core/properties/index.js +85 -20
- package/ui/core/properties/index.js.map +1 -1
- package/ui/dialogs/dialogs-common.d.ts +4 -0
- package/ui/dialogs/dialogs-common.js.map +1 -1
- package/ui/dialogs/index.android.js +2 -2
- package/ui/dialogs/index.android.js.map +1 -1
- package/ui/dialogs/index.d.ts +5 -0
- package/ui/editable-text-base/editable-text-base-common.js +3 -3
- package/ui/editable-text-base/editable-text-base-common.js.map +1 -1
- package/ui/editable-text-base/index.android.js +8 -2
- package/ui/editable-text-base/index.android.js.map +1 -1
- package/ui/frame/fragment.transitions.android.js +17 -17
- package/ui/frame/fragment.transitions.android.js.map +1 -1
- package/ui/text-field/index.android.js +6 -0
- package/ui/text-field/index.android.js.map +1 -1
- package/ui/transition/fade-transition.android.js +5 -5
- package/ui/transition/fade-transition.android.js.map +1 -1
- package/ui/transition/flip-transition.android.js +5 -5
- package/ui/transition/flip-transition.android.js.map +1 -1
- package/ui/transition/index.android.d.ts +6 -6
- package/ui/transition/index.android.js +6 -7
- package/ui/transition/index.android.js.map +1 -1
- package/ui/transition/index.d.ts +2 -8
- package/ui/transition/index.ios.d.ts +1 -0
- package/ui/transition/index.ios.js +1 -0
- package/ui/transition/index.ios.js.map +1 -1
- package/ui/transition/slide-transition.android.d.ts +2 -2
- package/ui/transition/slide-transition.android.js +18 -18
- package/ui/transition/slide-transition.android.js.map +1 -1
- package/xhr/index.js +4 -1
- package/xhr/index.js.map +1 -1
package/css/parser.js
CHANGED
|
@@ -1,30 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var urlRegEx = /\s*url\((?:(['"])([^\1]*)\1|([^)]*))\)\s*/gy;
|
|
5
|
-
function parseURL(text, start) {
|
|
6
|
-
if (start === void 0) { start = 0; }
|
|
1
|
+
import { getKnownColor } from '../color/known-colors';
|
|
2
|
+
const urlRegEx = /\s*url\((?:(['"])([^\1]*)\1|([^)]*))\)\s*/gy;
|
|
3
|
+
export function parseURL(text, start = 0) {
|
|
7
4
|
urlRegEx.lastIndex = start;
|
|
8
|
-
|
|
5
|
+
const result = urlRegEx.exec(text);
|
|
9
6
|
if (!result) {
|
|
10
7
|
return null;
|
|
11
8
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return { start
|
|
9
|
+
const end = urlRegEx.lastIndex;
|
|
10
|
+
const value = result[2] || result[3];
|
|
11
|
+
return { start, end, value };
|
|
15
12
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
function parseHexColor(text, start) {
|
|
19
|
-
if (start === void 0) { start = 0; }
|
|
13
|
+
const hexColorRegEx = /\s*#((?:[0-9A-F]{8})|(?:[0-9A-F]{6})|(?:[0-9A-F]{3}))\s*/giy;
|
|
14
|
+
export function parseHexColor(text, start = 0) {
|
|
20
15
|
hexColorRegEx.lastIndex = start;
|
|
21
|
-
|
|
16
|
+
const result = hexColorRegEx.exec(text);
|
|
22
17
|
if (!result) {
|
|
23
18
|
return null;
|
|
24
19
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
const end = hexColorRegEx.lastIndex;
|
|
21
|
+
const hex = result[1];
|
|
22
|
+
let argb;
|
|
28
23
|
if (hex.length === 8) {
|
|
29
24
|
argb = parseInt('0x' + hex);
|
|
30
25
|
}
|
|
@@ -34,11 +29,9 @@ function parseHexColor(text, start) {
|
|
|
34
29
|
else if (hex.length === 3) {
|
|
35
30
|
argb = parseInt('0xFF' + hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]);
|
|
36
31
|
}
|
|
37
|
-
return { start
|
|
32
|
+
return { start, end, value: argb };
|
|
38
33
|
}
|
|
39
|
-
|
|
40
|
-
function rgbaToArgbNumber(r, g, b, a) {
|
|
41
|
-
if (a === void 0) { a = 1; }
|
|
34
|
+
function rgbaToArgbNumber(r, g, b, a = 1) {
|
|
42
35
|
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 1) {
|
|
43
36
|
return Math.round(a * 0xff) * 0x01000000 + r * 0x010000 + g * 0x000100 + b;
|
|
44
37
|
}
|
|
@@ -46,37 +39,36 @@ function rgbaToArgbNumber(r, g, b, a) {
|
|
|
46
39
|
return null;
|
|
47
40
|
}
|
|
48
41
|
}
|
|
49
|
-
|
|
50
|
-
function parseRGBColor(text, start) {
|
|
51
|
-
if (start === void 0) { start = 0; }
|
|
42
|
+
const rgbColorRegEx = /\s*(rgb\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*\))/gy;
|
|
43
|
+
export function parseRGBColor(text, start = 0) {
|
|
52
44
|
rgbColorRegEx.lastIndex = start;
|
|
53
|
-
|
|
45
|
+
const result = rgbColorRegEx.exec(text);
|
|
54
46
|
if (!result) {
|
|
55
47
|
return null;
|
|
56
48
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return { start
|
|
49
|
+
const end = rgbColorRegEx.lastIndex;
|
|
50
|
+
const value = result[1] && rgbaToArgbNumber(parseInt(result[2]), parseInt(result[3]), parseInt(result[4]));
|
|
51
|
+
return { start, end, value };
|
|
60
52
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
function parseRGBAColor(text, start) {
|
|
64
|
-
if (start === void 0) { start = 0; }
|
|
53
|
+
const rgbaColorRegEx = /\s*(rgba\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*,\s*([01]?\.?\d*)\s*\))/gy;
|
|
54
|
+
export function parseRGBAColor(text, start = 0) {
|
|
65
55
|
rgbaColorRegEx.lastIndex = start;
|
|
66
|
-
|
|
56
|
+
const result = rgbaColorRegEx.exec(text);
|
|
67
57
|
if (!result) {
|
|
68
58
|
return null;
|
|
69
59
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return { start
|
|
60
|
+
const end = rgbaColorRegEx.lastIndex;
|
|
61
|
+
const value = rgbaToArgbNumber(parseInt(result[2]), parseInt(result[3]), parseInt(result[4]), parseFloat(result[5]));
|
|
62
|
+
return { start, end, value };
|
|
73
63
|
}
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
export function convertHSLToRGBColor(hue, saturation, lightness) {
|
|
65
|
+
// Per formula it will be easier if hue is divided to 60° and saturation to 100 beforehand
|
|
66
|
+
// https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB
|
|
76
67
|
hue /= 60;
|
|
77
68
|
lightness /= 100;
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
const chroma = ((1 - Math.abs(2 * lightness - 1)) * saturation) / 100, X = chroma * (1 - Math.abs((hue % 2) - 1));
|
|
70
|
+
// Add lightness match to all RGB components beforehand
|
|
71
|
+
let { m: r, m: g, m: b } = { m: lightness - chroma / 2 };
|
|
80
72
|
if (0 <= hue && hue < 1) {
|
|
81
73
|
r += chroma;
|
|
82
74
|
g += X;
|
|
@@ -107,99 +99,81 @@ function convertHSLToRGBColor(hue, saturation, lightness) {
|
|
|
107
99
|
b: Math.round(b * 0xff),
|
|
108
100
|
};
|
|
109
101
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (a === void 0) { a = 1; }
|
|
113
|
-
var _a = convertHSLToRGBColor(h, s, l), r = _a.r, g = _a.g, b = _a.b;
|
|
102
|
+
function hslaToArgbNumber(h, s, l, a = 1) {
|
|
103
|
+
const { r, g, b } = convertHSLToRGBColor(h, s, l);
|
|
114
104
|
return rgbaToArgbNumber(r, g, b, a);
|
|
115
105
|
}
|
|
116
|
-
|
|
117
|
-
function parseHSLColor(text, start) {
|
|
118
|
-
if (start === void 0) { start = 0; }
|
|
106
|
+
const hslColorRegEx = /\s*(hsl\(\s*([\d.]*)\s*,\s*([\d.]*)%\s*,\s*([\d.]*)%\s*\))/gy;
|
|
107
|
+
export function parseHSLColor(text, start = 0) {
|
|
119
108
|
hslColorRegEx.lastIndex = start;
|
|
120
|
-
|
|
109
|
+
const result = hslColorRegEx.exec(text);
|
|
121
110
|
if (!result) {
|
|
122
111
|
return null;
|
|
123
112
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return { start
|
|
113
|
+
const end = hslColorRegEx.lastIndex;
|
|
114
|
+
const value = result[1] && hslaToArgbNumber(parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]));
|
|
115
|
+
return { start, end, value };
|
|
127
116
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
function parseHSLAColor(text, start) {
|
|
131
|
-
if (start === void 0) { start = 0; }
|
|
117
|
+
const hslaColorRegEx = /\s*(hsla\(\s*([\d.]*)\s*,\s*([\d.]*)%\s*,\s*([\d.]*)%\s*,\s*([01]?\.?\d*)\s*\))/gy;
|
|
118
|
+
export function parseHSLAColor(text, start = 0) {
|
|
132
119
|
hslaColorRegEx.lastIndex = start;
|
|
133
|
-
|
|
120
|
+
const result = hslaColorRegEx.exec(text);
|
|
134
121
|
if (!result) {
|
|
135
122
|
return null;
|
|
136
123
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return { start
|
|
124
|
+
const end = hslaColorRegEx.lastIndex;
|
|
125
|
+
const value = hslaToArgbNumber(parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]), parseFloat(result[5]));
|
|
126
|
+
return { start, end, value };
|
|
140
127
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (keyword === void 0) { keyword = parseKeyword(value, start); }
|
|
144
|
-
var parseColor = keyword && known_colors_1.getKnownColor(keyword.value);
|
|
128
|
+
export function parseColorKeyword(value, start, keyword = parseKeyword(value, start)) {
|
|
129
|
+
const parseColor = keyword && getKnownColor(keyword.value);
|
|
145
130
|
if (parseColor != null) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
return { start
|
|
131
|
+
const end = keyword.end;
|
|
132
|
+
const value = parseColor;
|
|
133
|
+
return { start, end, value };
|
|
149
134
|
}
|
|
150
135
|
return null;
|
|
151
136
|
}
|
|
152
|
-
|
|
153
|
-
function parseColor(value, start, keyword) {
|
|
154
|
-
if (start === void 0) { start = 0; }
|
|
155
|
-
if (keyword === void 0) { keyword = parseKeyword(value, start); }
|
|
137
|
+
export function parseColor(value, start = 0, keyword = parseKeyword(value, start)) {
|
|
156
138
|
return parseHexColor(value, start) || parseColorKeyword(value, start, keyword) || parseRGBColor(value, start) || parseRGBAColor(value, start) || parseHSLColor(value, start) || parseHSLAColor(value, start);
|
|
157
139
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
function parseKeyword(text, start) {
|
|
161
|
-
if (start === void 0) { start = 0; }
|
|
140
|
+
const keywordRegEx = /\s*([a-z][\w\-]*)\s*/giy;
|
|
141
|
+
function parseKeyword(text, start = 0) {
|
|
162
142
|
keywordRegEx.lastIndex = start;
|
|
163
|
-
|
|
143
|
+
const result = keywordRegEx.exec(text);
|
|
164
144
|
if (!result) {
|
|
165
145
|
return null;
|
|
166
146
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
return { start
|
|
147
|
+
const end = keywordRegEx.lastIndex;
|
|
148
|
+
const value = result[1];
|
|
149
|
+
return { start, end, value };
|
|
170
150
|
}
|
|
171
|
-
|
|
172
|
-
function parseRepeat(value, start, keyword) {
|
|
173
|
-
if (start === void 0) { start = 0; }
|
|
174
|
-
if (keyword === void 0) { keyword = parseKeyword(value, start); }
|
|
151
|
+
const backgroundRepeatKeywords = new Set(['repeat', 'repeat-x', 'repeat-y', 'no-repeat']);
|
|
152
|
+
export function parseRepeat(value, start = 0, keyword = parseKeyword(value, start)) {
|
|
175
153
|
if (keyword && backgroundRepeatKeywords.has(keyword.value)) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return { start
|
|
154
|
+
const end = keyword.end;
|
|
155
|
+
const value = keyword.value;
|
|
156
|
+
return { start, end, value };
|
|
179
157
|
}
|
|
180
158
|
return null;
|
|
181
159
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
function parseUnit(text, start) {
|
|
185
|
-
if (start === void 0) { start = 0; }
|
|
160
|
+
const unitRegEx = /\s*([+\-]?(?:\d+\.\d+|\d+|\.\d+)(?:[eE][+\-]?\d+)?)([a-zA-Z]+|%)?\s*/gy;
|
|
161
|
+
export function parseUnit(text, start = 0) {
|
|
186
162
|
unitRegEx.lastIndex = start;
|
|
187
|
-
|
|
163
|
+
const result = unitRegEx.exec(text);
|
|
188
164
|
if (!result) {
|
|
189
165
|
return null;
|
|
190
166
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return { start
|
|
167
|
+
const end = unitRegEx.lastIndex;
|
|
168
|
+
const value = parseFloat(result[1]);
|
|
169
|
+
const unit = result[2] || 'dip';
|
|
170
|
+
return { start, end, value: { value, unit } };
|
|
195
171
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (start === void 0) { start = 0; }
|
|
199
|
-
var unitResult = parseUnit(text, start);
|
|
172
|
+
export function parsePercentageOrLength(text, start = 0) {
|
|
173
|
+
const unitResult = parseUnit(text, start);
|
|
200
174
|
if (unitResult) {
|
|
201
|
-
|
|
202
|
-
|
|
175
|
+
const { start, end } = unitResult;
|
|
176
|
+
const value = unitResult.value;
|
|
203
177
|
if (value.unit === '%') {
|
|
204
178
|
value.value /= 100;
|
|
205
179
|
}
|
|
@@ -207,87 +181,81 @@ function parsePercentageOrLength(text, start) {
|
|
|
207
181
|
value.unit = 'dip';
|
|
208
182
|
}
|
|
209
183
|
else if (value.unit === 'px' || value.unit === 'dip') {
|
|
184
|
+
// same
|
|
210
185
|
}
|
|
211
186
|
else {
|
|
212
187
|
return null;
|
|
213
188
|
}
|
|
214
|
-
return { start
|
|
189
|
+
return { start, end, value };
|
|
215
190
|
}
|
|
216
191
|
return null;
|
|
217
192
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
end: end,
|
|
193
|
+
const angleUnitsToRadMap = {
|
|
194
|
+
deg: (start, end, deg) => ({
|
|
195
|
+
start,
|
|
196
|
+
end,
|
|
223
197
|
value: (deg / 180) * Math.PI,
|
|
224
|
-
})
|
|
225
|
-
rad:
|
|
226
|
-
start
|
|
227
|
-
end
|
|
198
|
+
}),
|
|
199
|
+
rad: (start, end, rad) => ({
|
|
200
|
+
start,
|
|
201
|
+
end,
|
|
228
202
|
value: rad,
|
|
229
|
-
})
|
|
230
|
-
grad:
|
|
231
|
-
start
|
|
232
|
-
end
|
|
203
|
+
}),
|
|
204
|
+
grad: (start, end, grad) => ({
|
|
205
|
+
start,
|
|
206
|
+
end,
|
|
233
207
|
value: (grad / 200) * Math.PI,
|
|
234
|
-
})
|
|
235
|
-
turn:
|
|
236
|
-
start
|
|
237
|
-
end
|
|
208
|
+
}),
|
|
209
|
+
turn: (start, end, turn) => ({
|
|
210
|
+
start,
|
|
211
|
+
end,
|
|
238
212
|
value: turn * Math.PI * 2,
|
|
239
|
-
})
|
|
213
|
+
}),
|
|
240
214
|
};
|
|
241
|
-
function parseAngle(value, start) {
|
|
242
|
-
|
|
243
|
-
var angleResult = parseUnit(value, start);
|
|
215
|
+
export function parseAngle(value, start = 0) {
|
|
216
|
+
const angleResult = parseUnit(value, start);
|
|
244
217
|
if (angleResult) {
|
|
245
|
-
|
|
246
|
-
return (angleUnitsToRadMap[
|
|
218
|
+
const { start, end, value } = angleResult;
|
|
219
|
+
return (angleUnitsToRadMap[value.unit] || ((_, __, ___) => null))(start, end, value.value);
|
|
247
220
|
}
|
|
248
221
|
return null;
|
|
249
222
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if (start === void 0) { start = 0; }
|
|
254
|
-
if (keyword === void 0) { keyword = parseKeyword(value, start); }
|
|
255
|
-
var end = start;
|
|
223
|
+
const backgroundSizeKeywords = new Set(['auto', 'contain', 'cover']);
|
|
224
|
+
export function parseBackgroundSize(value, start = 0, keyword = parseKeyword(value, start)) {
|
|
225
|
+
let end = start;
|
|
256
226
|
if (keyword && backgroundSizeKeywords.has(keyword.value)) {
|
|
257
227
|
end = keyword.end;
|
|
258
|
-
|
|
259
|
-
return { start
|
|
228
|
+
const value = keyword.value;
|
|
229
|
+
return { start, end, value };
|
|
260
230
|
}
|
|
261
|
-
|
|
231
|
+
// Parse one or two lengths... the other will be "auto"
|
|
232
|
+
const firstLength = parsePercentageOrLength(value, end);
|
|
262
233
|
if (firstLength) {
|
|
263
234
|
end = firstLength.end;
|
|
264
|
-
|
|
235
|
+
const secondLength = parsePercentageOrLength(value, firstLength.end);
|
|
265
236
|
if (secondLength) {
|
|
266
237
|
end = secondLength.end;
|
|
267
238
|
return {
|
|
268
|
-
start
|
|
269
|
-
end
|
|
239
|
+
start,
|
|
240
|
+
end,
|
|
270
241
|
value: { x: firstLength.value, y: secondLength.value },
|
|
271
242
|
};
|
|
272
243
|
}
|
|
273
244
|
else {
|
|
274
|
-
return { start
|
|
245
|
+
return { start, end, value: { x: firstLength.value, y: 'auto' } };
|
|
275
246
|
}
|
|
276
247
|
}
|
|
277
248
|
return null;
|
|
278
249
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
var backgroundPositionKeywordsDirection = {
|
|
250
|
+
const backgroundPositionKeywords = Object.freeze(new Set(['left', 'right', 'top', 'bottom', 'center']));
|
|
251
|
+
const backgroundPositionKeywordsDirection = {
|
|
282
252
|
left: 'x',
|
|
283
253
|
right: 'x',
|
|
284
254
|
center: 'center',
|
|
285
255
|
top: 'y',
|
|
286
256
|
bottom: 'y',
|
|
287
257
|
};
|
|
288
|
-
function parseBackgroundPosition(text, start, keyword) {
|
|
289
|
-
if (start === void 0) { start = 0; }
|
|
290
|
-
if (keyword === void 0) { keyword = parseKeyword(text, start); }
|
|
258
|
+
export function parseBackgroundPosition(text, start = 0, keyword = parseKeyword(text, start)) {
|
|
291
259
|
function formatH(align, offset) {
|
|
292
260
|
if (align.value === 'center') {
|
|
293
261
|
return 'center';
|
|
@@ -306,29 +274,29 @@ function parseBackgroundPosition(text, start, keyword) {
|
|
|
306
274
|
}
|
|
307
275
|
return align.value;
|
|
308
276
|
}
|
|
309
|
-
|
|
277
|
+
let end = start;
|
|
310
278
|
if (keyword && backgroundPositionKeywords.has(keyword.value)) {
|
|
311
279
|
end = keyword.end;
|
|
312
|
-
|
|
313
|
-
|
|
280
|
+
const firstDirection = backgroundPositionKeywordsDirection[keyword.value];
|
|
281
|
+
const firstLength = firstDirection !== 'center' && parsePercentageOrLength(text, end);
|
|
314
282
|
if (firstLength) {
|
|
315
283
|
end = firstLength.end;
|
|
316
284
|
}
|
|
317
|
-
|
|
285
|
+
const secondKeyword = parseKeyword(text, end);
|
|
318
286
|
if (secondKeyword && backgroundPositionKeywords.has(secondKeyword.value)) {
|
|
319
287
|
end = secondKeyword.end;
|
|
320
|
-
|
|
288
|
+
const secondDirection = backgroundPositionKeywordsDirection[secondKeyword.end];
|
|
321
289
|
if (firstDirection === secondDirection && firstDirection !== 'center') {
|
|
322
|
-
return null;
|
|
290
|
+
return null; // Reject pair of both horizontal or both vertical alignments.
|
|
323
291
|
}
|
|
324
|
-
|
|
292
|
+
const secondLength = secondDirection !== 'center' && parsePercentageOrLength(text, end);
|
|
325
293
|
if (secondLength) {
|
|
326
294
|
end = secondLength.end;
|
|
327
295
|
}
|
|
328
296
|
if ((firstDirection === secondDirection && secondDirection === 'center') || firstDirection === 'x' || secondDirection === 'y') {
|
|
329
297
|
return {
|
|
330
|
-
start
|
|
331
|
-
end
|
|
298
|
+
start,
|
|
299
|
+
end,
|
|
332
300
|
value: {
|
|
333
301
|
x: formatH(keyword, firstLength),
|
|
334
302
|
y: formatV(secondKeyword, secondLength),
|
|
@@ -337,8 +305,8 @@ function parseBackgroundPosition(text, start, keyword) {
|
|
|
337
305
|
}
|
|
338
306
|
else {
|
|
339
307
|
return {
|
|
340
|
-
start
|
|
341
|
-
end
|
|
308
|
+
start,
|
|
309
|
+
end,
|
|
342
310
|
value: {
|
|
343
311
|
x: formatH(secondKeyword, secondLength),
|
|
344
312
|
y: formatV(keyword, firstLength),
|
|
@@ -348,12 +316,12 @@ function parseBackgroundPosition(text, start, keyword) {
|
|
|
348
316
|
}
|
|
349
317
|
else {
|
|
350
318
|
if (firstDirection === 'center') {
|
|
351
|
-
return { start
|
|
319
|
+
return { start, end, value: { x: 'center', y: 'center' } };
|
|
352
320
|
}
|
|
353
321
|
else if (firstDirection === 'x') {
|
|
354
322
|
return {
|
|
355
|
-
start
|
|
356
|
-
end
|
|
323
|
+
start,
|
|
324
|
+
end,
|
|
357
325
|
value: {
|
|
358
326
|
x: formatH(keyword, firstLength),
|
|
359
327
|
y: 'center',
|
|
@@ -362,8 +330,8 @@ function parseBackgroundPosition(text, start, keyword) {
|
|
|
362
330
|
}
|
|
363
331
|
else {
|
|
364
332
|
return {
|
|
365
|
-
start
|
|
366
|
-
end
|
|
333
|
+
start,
|
|
334
|
+
end,
|
|
367
335
|
value: {
|
|
368
336
|
x: 'center',
|
|
369
337
|
y: formatV(keyword, firstLength),
|
|
@@ -373,15 +341,15 @@ function parseBackgroundPosition(text, start, keyword) {
|
|
|
373
341
|
}
|
|
374
342
|
}
|
|
375
343
|
else {
|
|
376
|
-
|
|
344
|
+
const firstLength = parsePercentageOrLength(text, end);
|
|
377
345
|
if (firstLength) {
|
|
378
346
|
end = firstLength.end;
|
|
379
|
-
|
|
347
|
+
const secondLength = parsePercentageOrLength(text, end);
|
|
380
348
|
if (secondLength) {
|
|
381
349
|
end = secondLength.end;
|
|
382
350
|
return {
|
|
383
|
-
start
|
|
384
|
-
end
|
|
351
|
+
start,
|
|
352
|
+
end,
|
|
385
353
|
value: {
|
|
386
354
|
x: { align: 'left', offset: firstLength.value },
|
|
387
355
|
y: { align: 'top', offset: secondLength.value },
|
|
@@ -390,8 +358,8 @@ function parseBackgroundPosition(text, start, keyword) {
|
|
|
390
358
|
}
|
|
391
359
|
else {
|
|
392
360
|
return {
|
|
393
|
-
start
|
|
394
|
-
end
|
|
361
|
+
start,
|
|
362
|
+
end,
|
|
395
363
|
value: {
|
|
396
364
|
x: { align: 'left', offset: firstLength.value },
|
|
397
365
|
y: 'center',
|
|
@@ -404,15 +372,14 @@ function parseBackgroundPosition(text, start, keyword) {
|
|
|
404
372
|
}
|
|
405
373
|
}
|
|
406
374
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
var sideDirections = {
|
|
375
|
+
const directionRegEx = /\s*to\s*(left|right|top|bottom)\s*(left|right|top|bottom)?\s*/gy;
|
|
376
|
+
const sideDirections = {
|
|
410
377
|
top: (Math.PI * 0) / 2,
|
|
411
378
|
right: (Math.PI * 1) / 2,
|
|
412
379
|
bottom: (Math.PI * 2) / 2,
|
|
413
380
|
left: (Math.PI * 3) / 2,
|
|
414
381
|
};
|
|
415
|
-
|
|
382
|
+
const cornerDirections = {
|
|
416
383
|
top: {
|
|
417
384
|
right: (Math.PI * 1) / 4,
|
|
418
385
|
left: (Math.PI * 7) / 4,
|
|
@@ -430,56 +397,56 @@ var cornerDirections = {
|
|
|
430
397
|
bottom: (Math.PI * 5) / 4,
|
|
431
398
|
},
|
|
432
399
|
};
|
|
433
|
-
function parseDirection(text, start) {
|
|
434
|
-
if (start === void 0) { start = 0; }
|
|
400
|
+
function parseDirection(text, start = 0) {
|
|
435
401
|
directionRegEx.lastIndex = start;
|
|
436
|
-
|
|
402
|
+
const result = directionRegEx.exec(text);
|
|
437
403
|
if (!result) {
|
|
438
404
|
return null;
|
|
439
405
|
}
|
|
440
|
-
|
|
441
|
-
|
|
406
|
+
const end = directionRegEx.lastIndex;
|
|
407
|
+
const firstDirection = result[1];
|
|
442
408
|
if (result[2]) {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
return value === undefined ? null : { start
|
|
409
|
+
const secondDirection = result[2];
|
|
410
|
+
const value = cornerDirections[firstDirection][secondDirection];
|
|
411
|
+
return value === undefined ? null : { start, end, value };
|
|
446
412
|
}
|
|
447
413
|
else {
|
|
448
|
-
return { start
|
|
414
|
+
return { start, end, value: sideDirections[firstDirection] };
|
|
449
415
|
}
|
|
450
416
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
417
|
+
const openingBracketRegEx = /\s*\(\s*/gy;
|
|
418
|
+
const closingBracketRegEx = /\s*\)\s*/gy;
|
|
419
|
+
const closingBracketOrCommaRegEx = /\s*([),])\s*/gy;
|
|
454
420
|
function parseArgumentsList(text, start, argument) {
|
|
455
421
|
openingBracketRegEx.lastIndex = start;
|
|
456
|
-
|
|
422
|
+
const openingBracket = openingBracketRegEx.exec(text);
|
|
457
423
|
if (!openingBracket) {
|
|
458
424
|
return null;
|
|
459
425
|
}
|
|
460
|
-
|
|
461
|
-
|
|
426
|
+
let end = openingBracketRegEx.lastIndex;
|
|
427
|
+
const value = [];
|
|
462
428
|
closingBracketRegEx.lastIndex = end;
|
|
463
|
-
|
|
429
|
+
const closingBracket = closingBracketRegEx.exec(text);
|
|
464
430
|
if (closingBracket) {
|
|
465
|
-
return { start
|
|
431
|
+
return { start, end, value };
|
|
466
432
|
}
|
|
467
|
-
for (
|
|
468
|
-
|
|
433
|
+
for (let index = 0; true; index++) {
|
|
434
|
+
const arg = argument(text, end, index);
|
|
469
435
|
if (!arg) {
|
|
470
436
|
return null;
|
|
471
437
|
}
|
|
472
438
|
end = arg.end;
|
|
473
439
|
value.push(arg);
|
|
474
440
|
closingBracketOrCommaRegEx.lastIndex = end;
|
|
475
|
-
|
|
441
|
+
const closingBracketOrComma = closingBracketOrCommaRegEx.exec(text);
|
|
476
442
|
if (closingBracketOrComma) {
|
|
477
443
|
end = closingBracketOrCommaRegEx.lastIndex;
|
|
478
444
|
if (closingBracketOrComma[1] === ',') {
|
|
445
|
+
// noinspection UnnecessaryContinueJS
|
|
479
446
|
continue;
|
|
480
447
|
}
|
|
481
448
|
else if (closingBracketOrComma[1] === ')') {
|
|
482
|
-
return { start
|
|
449
|
+
return { start, end, value };
|
|
483
450
|
}
|
|
484
451
|
}
|
|
485
452
|
else {
|
|
@@ -487,45 +454,43 @@ function parseArgumentsList(text, start, argument) {
|
|
|
487
454
|
}
|
|
488
455
|
}
|
|
489
456
|
}
|
|
490
|
-
function parseColorStop(text, start) {
|
|
491
|
-
|
|
492
|
-
var color = parseColor(text, start);
|
|
457
|
+
export function parseColorStop(text, start = 0) {
|
|
458
|
+
const color = parseColor(text, start);
|
|
493
459
|
if (!color) {
|
|
494
460
|
return null;
|
|
495
461
|
}
|
|
496
|
-
|
|
497
|
-
|
|
462
|
+
let end = color.end;
|
|
463
|
+
const offset = parsePercentageOrLength(text, end);
|
|
498
464
|
if (offset) {
|
|
499
465
|
end = offset.end;
|
|
500
466
|
return {
|
|
501
|
-
start
|
|
502
|
-
end
|
|
467
|
+
start,
|
|
468
|
+
end,
|
|
503
469
|
value: { argb: color.value, offset: offset.value },
|
|
504
470
|
};
|
|
505
471
|
}
|
|
506
|
-
return { start
|
|
472
|
+
return { start, end, value: { argb: color.value } };
|
|
507
473
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
function parseLinearGradient(text, start) {
|
|
511
|
-
if (start === void 0) { start = 0; }
|
|
474
|
+
const linearGradientStartRegEx = /\s*linear-gradient\s*/gy;
|
|
475
|
+
export function parseLinearGradient(text, start = 0) {
|
|
512
476
|
linearGradientStartRegEx.lastIndex = start;
|
|
513
|
-
|
|
477
|
+
const lgs = linearGradientStartRegEx.exec(text);
|
|
514
478
|
if (!lgs) {
|
|
515
479
|
return null;
|
|
516
480
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
481
|
+
let end = linearGradientStartRegEx.lastIndex;
|
|
482
|
+
let angle = Math.PI;
|
|
483
|
+
const colors = [];
|
|
484
|
+
const parsedArgs = parseArgumentsList(text, end, (text, start, index) => {
|
|
521
485
|
if (index === 0) {
|
|
522
|
-
|
|
486
|
+
// First arg can be gradient direction
|
|
487
|
+
const angleArg = parseAngle(text, start) || parseDirection(text, start);
|
|
523
488
|
if (angleArg) {
|
|
524
489
|
angle = angleArg.value;
|
|
525
490
|
return angleArg;
|
|
526
491
|
}
|
|
527
492
|
}
|
|
528
|
-
|
|
493
|
+
const colorStop = parseColorStop(text, start);
|
|
529
494
|
if (colorStop) {
|
|
530
495
|
colors.push(colorStop.value);
|
|
531
496
|
return colorStop;
|
|
@@ -536,47 +501,46 @@ function parseLinearGradient(text, start) {
|
|
|
536
501
|
return null;
|
|
537
502
|
}
|
|
538
503
|
end = parsedArgs.end;
|
|
539
|
-
return { start
|
|
504
|
+
return { start, end, value: { angle, colors } };
|
|
540
505
|
}
|
|
541
|
-
|
|
542
|
-
var slashRegEx = /\s*(\/)\s*/gy;
|
|
506
|
+
const slashRegEx = /\s*(\/)\s*/gy;
|
|
543
507
|
function parseSlash(text, start) {
|
|
544
508
|
slashRegEx.lastIndex = start;
|
|
545
|
-
|
|
509
|
+
const slash = slashRegEx.exec(text);
|
|
546
510
|
if (!slash) {
|
|
547
511
|
return null;
|
|
548
512
|
}
|
|
549
|
-
|
|
550
|
-
return { start
|
|
513
|
+
const end = slashRegEx.lastIndex;
|
|
514
|
+
return { start, end, value: '/' };
|
|
551
515
|
}
|
|
552
|
-
function parseBackground(text, start) {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
var end = start;
|
|
516
|
+
export function parseBackground(text, start = 0) {
|
|
517
|
+
const value = {};
|
|
518
|
+
let end = start;
|
|
556
519
|
while (end < text.length) {
|
|
557
|
-
|
|
558
|
-
|
|
520
|
+
const keyword = parseKeyword(text, end);
|
|
521
|
+
const color = parseColor(text, end, keyword);
|
|
559
522
|
if (color) {
|
|
560
523
|
value.color = color.value;
|
|
561
524
|
end = color.end;
|
|
562
525
|
continue;
|
|
563
526
|
}
|
|
564
|
-
|
|
527
|
+
const repeat = parseRepeat(text, end, keyword);
|
|
565
528
|
if (repeat) {
|
|
566
529
|
value.repeat = repeat.value;
|
|
567
530
|
end = repeat.end;
|
|
568
531
|
continue;
|
|
569
532
|
}
|
|
570
|
-
|
|
533
|
+
const position = parseBackgroundPosition(text, end, keyword);
|
|
571
534
|
if (position) {
|
|
572
535
|
position.value.text = text.substring(position.start, position.end);
|
|
573
536
|
value.position = position.value;
|
|
574
537
|
end = position.end;
|
|
575
|
-
|
|
538
|
+
const slash = parseSlash(text, end);
|
|
576
539
|
if (slash) {
|
|
577
540
|
end = slash.end;
|
|
578
|
-
|
|
541
|
+
const size = parseBackgroundSize(text, end);
|
|
579
542
|
if (!size) {
|
|
543
|
+
// Found / but no proper size following
|
|
580
544
|
return null;
|
|
581
545
|
}
|
|
582
546
|
value.size = size.value;
|
|
@@ -584,13 +548,13 @@ function parseBackground(text, start) {
|
|
|
584
548
|
}
|
|
585
549
|
continue;
|
|
586
550
|
}
|
|
587
|
-
|
|
551
|
+
const url = parseURL(text, end);
|
|
588
552
|
if (url) {
|
|
589
553
|
value.image = url.value;
|
|
590
554
|
end = url.end;
|
|
591
555
|
continue;
|
|
592
556
|
}
|
|
593
|
-
|
|
557
|
+
const gradient = parseLinearGradient(text, end);
|
|
594
558
|
if (gradient) {
|
|
595
559
|
value.image = gradient.value;
|
|
596
560
|
end = gradient.end;
|
|
@@ -598,102 +562,90 @@ function parseBackground(text, start) {
|
|
|
598
562
|
}
|
|
599
563
|
return null;
|
|
600
564
|
}
|
|
601
|
-
return { start
|
|
565
|
+
return { start, end, value };
|
|
602
566
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
function parseUniversalSelector(text, start) {
|
|
606
|
-
if (start === void 0) { start = 0; }
|
|
567
|
+
const universalSelectorRegEx = /\*/gy;
|
|
568
|
+
export function parseUniversalSelector(text, start = 0) {
|
|
607
569
|
universalSelectorRegEx.lastIndex = start;
|
|
608
|
-
|
|
570
|
+
const result = universalSelectorRegEx.exec(text);
|
|
609
571
|
if (!result) {
|
|
610
572
|
return null;
|
|
611
573
|
}
|
|
612
|
-
|
|
613
|
-
return { start
|
|
574
|
+
const end = universalSelectorRegEx.lastIndex;
|
|
575
|
+
return { start, end, value: { type: '*' } };
|
|
614
576
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
function parseSimpleIdentifierSelector(text, start) {
|
|
619
|
-
if (start === void 0) { start = 0; }
|
|
577
|
+
const simpleIdentifierSelectorRegEx = /(#|\.|:|\b)((?:[\w_-]|\\.)(?:[\w\d_-]|\\.)*)/guy;
|
|
578
|
+
const unicodeEscapeRegEx = /\\([0-9a-fA-F]{1,5}\s|[0-9a-fA-F]{6})/g;
|
|
579
|
+
export function parseSimpleIdentifierSelector(text, start = 0) {
|
|
620
580
|
simpleIdentifierSelectorRegEx.lastIndex = start;
|
|
621
|
-
|
|
581
|
+
const result = simpleIdentifierSelectorRegEx.exec(text.replace(unicodeEscapeRegEx, (_, c) => '\\' + String.fromCodePoint(parseInt(c.trim(), 16))));
|
|
622
582
|
if (!result) {
|
|
623
583
|
return null;
|
|
624
584
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
return { start
|
|
585
|
+
const end = simpleIdentifierSelectorRegEx.lastIndex;
|
|
586
|
+
const type = result[1];
|
|
587
|
+
const identifier = result[2].replace(/\\/g, '');
|
|
588
|
+
const value = { type, identifier };
|
|
589
|
+
return { start, end, value };
|
|
630
590
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
function parseAttributeSelector(text, start) {
|
|
591
|
+
const attributeSelectorRegEx = /\[\s*([_\-\w][_\-\w\d]*)\s*(?:(=|\^=|\$=|\*=|\~=|\|=)\s*(?:([_\-\w][_\-\w\d]*)|"((?:[^\\"]|\\(?:"|n|r|f|\\|0-9a-f))*)"|'((?:[^\\']|\\(?:'|n|r|f|\\|0-9a-f))*)')\s*)?\]/gy;
|
|
592
|
+
export function parseAttributeSelector(text, start) {
|
|
634
593
|
attributeSelectorRegEx.lastIndex = start;
|
|
635
|
-
|
|
594
|
+
const result = attributeSelectorRegEx.exec(text);
|
|
636
595
|
if (!result) {
|
|
637
596
|
return null;
|
|
638
597
|
}
|
|
639
|
-
|
|
640
|
-
|
|
598
|
+
const end = attributeSelectorRegEx.lastIndex;
|
|
599
|
+
const property = result[1];
|
|
641
600
|
if (result[2]) {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
return { start
|
|
601
|
+
const test = result[2];
|
|
602
|
+
const value = result[3] || result[4] || result[5];
|
|
603
|
+
return { start, end, value: { type: '[]', property, test, value } };
|
|
645
604
|
}
|
|
646
|
-
return { start
|
|
605
|
+
return { start, end, value: { type: '[]', property } };
|
|
647
606
|
}
|
|
648
|
-
|
|
649
|
-
function parseSimpleSelector(text, start) {
|
|
650
|
-
if (start === void 0) { start = 0; }
|
|
607
|
+
export function parseSimpleSelector(text, start = 0) {
|
|
651
608
|
return parseUniversalSelector(text, start) || parseSimpleIdentifierSelector(text, start) || parseAttributeSelector(text, start);
|
|
652
609
|
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
var simpleSelector = parseSimpleSelector(text, start);
|
|
610
|
+
export function parseSimpleSelectorSequence(text, start) {
|
|
611
|
+
let simpleSelector = parseSimpleSelector(text, start);
|
|
656
612
|
if (!simpleSelector) {
|
|
657
613
|
return null;
|
|
658
614
|
}
|
|
659
|
-
|
|
660
|
-
|
|
615
|
+
let end = simpleSelector.end;
|
|
616
|
+
const value = [];
|
|
661
617
|
while (simpleSelector) {
|
|
662
618
|
value.push(simpleSelector.value);
|
|
663
619
|
end = simpleSelector.end;
|
|
664
620
|
simpleSelector = parseSimpleSelector(text, end);
|
|
665
621
|
}
|
|
666
|
-
return { start
|
|
622
|
+
return { start, end, value };
|
|
667
623
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
function parseCombinator(text, start) {
|
|
671
|
-
if (start === void 0) { start = 0; }
|
|
624
|
+
const combinatorRegEx = /\s*([+~>])?\s*/gy;
|
|
625
|
+
export function parseCombinator(text, start = 0) {
|
|
672
626
|
combinatorRegEx.lastIndex = start;
|
|
673
|
-
|
|
627
|
+
const result = combinatorRegEx.exec(text);
|
|
674
628
|
if (!result) {
|
|
675
629
|
return null;
|
|
676
630
|
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
return { start
|
|
631
|
+
const end = combinatorRegEx.lastIndex;
|
|
632
|
+
const value = result[1] || ' ';
|
|
633
|
+
return { start, end, value };
|
|
680
634
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
if (start === void 0) { start = 0; }
|
|
685
|
-
var end = start;
|
|
635
|
+
const whiteSpaceRegEx = /\s*/gy;
|
|
636
|
+
export function parseSelector(text, start = 0) {
|
|
637
|
+
let end = start;
|
|
686
638
|
whiteSpaceRegEx.lastIndex = end;
|
|
687
|
-
|
|
639
|
+
const leadingWhiteSpace = whiteSpaceRegEx.exec(text);
|
|
688
640
|
if (leadingWhiteSpace) {
|
|
689
641
|
end = whiteSpaceRegEx.lastIndex;
|
|
690
642
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
643
|
+
const value = [];
|
|
644
|
+
let combinator;
|
|
645
|
+
let expectSimpleSelector = true; // Must have at least one
|
|
646
|
+
let pair;
|
|
695
647
|
do {
|
|
696
|
-
|
|
648
|
+
const simpleSelectorSequence = parseSimpleSelectorSequence(text, end);
|
|
697
649
|
if (!simpleSelectorSequence) {
|
|
698
650
|
if (expectSimpleSelector) {
|
|
699
651
|
return null;
|
|
@@ -704,6 +656,10 @@ function parseSelector(text, start) {
|
|
|
704
656
|
}
|
|
705
657
|
end = simpleSelectorSequence.end;
|
|
706
658
|
if (combinator) {
|
|
659
|
+
// This logic looks weird; this `if` statement would occur on the next LOOP, so it effects the prior `pair`
|
|
660
|
+
// variable which is already pushed into the `value` array is going to have its `undefined` set to this
|
|
661
|
+
// value before the following statement creates a new `pair` memory variable.
|
|
662
|
+
// noinspection JSUnusedAssignment
|
|
707
663
|
pair[1] = combinator.value;
|
|
708
664
|
}
|
|
709
665
|
pair = [simpleSelectorSequence.value, undefined];
|
|
@@ -712,38 +668,51 @@ function parseSelector(text, start) {
|
|
|
712
668
|
if (combinator) {
|
|
713
669
|
end = combinator.end;
|
|
714
670
|
}
|
|
715
|
-
expectSimpleSelector = combinator && combinator.value !== ' ';
|
|
671
|
+
expectSimpleSelector = combinator && combinator.value !== ' '; // Simple selector must follow non trailing white space combinator
|
|
716
672
|
} while (combinator);
|
|
717
|
-
return { start
|
|
673
|
+
return { start, end, value };
|
|
718
674
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
675
|
+
const whitespaceRegEx = /[\s\t\n\r\f]*/gmy;
|
|
676
|
+
const singleQuoteStringRegEx = /'((?:[^\n\r\f\']|\\(?:\$|\n|[0-9a-fA-F]{1,6}\s?))*)(:?'|$)/gmy; // Besides $n, parse escape
|
|
677
|
+
const doubleQuoteStringRegEx = /"((?:[^\n\r\f\"]|\\(?:\$|\n|[0-9a-fA-F]{1,6}\s?))*)(:?"|$)/gmy; // Besides $n, parse escape
|
|
678
|
+
const commentRegEx = /(\/\*(?:[^\*]|\*[^\/])*\*\/)/gmy;
|
|
679
|
+
const numberRegEx = /[\+\-]?(?:\d+\.\d+|\d+|\.\d+)(?:[eE][\+\-]?\d+)?/gmy;
|
|
680
|
+
// eslint-disable-next-line no-control-regex
|
|
681
|
+
const nameRegEx = /-?(?:(?:[a-zA-Z_]|[^\x00-\x7F]|\\(?:\$|\n|[0-9a-fA-F]{1,6}\s?))(?:[a-zA-Z_0-9\-]*|\\(?:\$|\n|[0-9a-fA-F]{1,6}\s?))*)/gmy;
|
|
682
|
+
/**
|
|
683
|
+
* CSS parser following relatively close:
|
|
684
|
+
* CSS Syntax Module Level 3
|
|
685
|
+
* https://www.w3.org/TR/css-syntax-3/
|
|
686
|
+
*/
|
|
687
|
+
export class CSS3Parser {
|
|
688
|
+
constructor(text) {
|
|
728
689
|
this.text = text;
|
|
729
690
|
this.nextInputCodePointIndex = 0;
|
|
730
691
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
692
|
+
/**
|
|
693
|
+
* For testing purposes.
|
|
694
|
+
* This method allows us to run and assert the proper working of the tokenizer.
|
|
695
|
+
*/
|
|
696
|
+
tokenize() {
|
|
697
|
+
const tokens = [];
|
|
698
|
+
let inputToken;
|
|
734
699
|
do {
|
|
735
700
|
inputToken = this.consumeAToken();
|
|
736
701
|
tokens.push(inputToken);
|
|
737
702
|
} while (inputToken);
|
|
738
703
|
return tokens;
|
|
739
|
-
}
|
|
740
|
-
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* 4.3.1. Consume a token
|
|
707
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-token
|
|
708
|
+
*/
|
|
709
|
+
consumeAToken() {
|
|
741
710
|
if (this.reconsumedInputToken) {
|
|
742
|
-
|
|
711
|
+
const result = this.reconsumedInputToken;
|
|
743
712
|
this.reconsumedInputToken = null;
|
|
744
713
|
return result;
|
|
745
714
|
}
|
|
746
|
-
|
|
715
|
+
const char = this.text[this.nextInputCodePointIndex];
|
|
747
716
|
switch (char) {
|
|
748
717
|
case '"':
|
|
749
718
|
return this.consumeAStringToken();
|
|
@@ -770,6 +739,7 @@ var CSS3Parser = (function () {
|
|
|
770
739
|
return this.consumeAWhitespace();
|
|
771
740
|
case '@':
|
|
772
741
|
return this.consumeAtKeyword() || this.consumeADelimToken();
|
|
742
|
+
// TODO: Only if this is valid escape, otherwise it is a parse error
|
|
773
743
|
case '\\':
|
|
774
744
|
return this.consumeAnIdentLikeToken() || this.consumeADelimToken();
|
|
775
745
|
case '0':
|
|
@@ -786,8 +756,9 @@ var CSS3Parser = (function () {
|
|
|
786
756
|
case 'u':
|
|
787
757
|
case 'U':
|
|
788
758
|
if (this.text[this.nextInputCodePointIndex + 1] === '+') {
|
|
789
|
-
|
|
759
|
+
const thirdChar = this.text[this.nextInputCodePointIndex + 2];
|
|
790
760
|
if ((thirdChar >= '0' && thirdChar <= '9') || thirdChar === '?') {
|
|
761
|
+
// TODO: Handle unicode stuff such as U+002B
|
|
791
762
|
throw new Error('Unicode tokens not supported!');
|
|
792
763
|
}
|
|
793
764
|
}
|
|
@@ -812,71 +783,79 @@ var CSS3Parser = (function () {
|
|
|
812
783
|
default:
|
|
813
784
|
return this.consumeAnIdentLikeToken() || this.consumeADelimToken();
|
|
814
785
|
}
|
|
815
|
-
}
|
|
816
|
-
|
|
786
|
+
}
|
|
787
|
+
consumeADelimToken() {
|
|
817
788
|
return {
|
|
818
|
-
type: 2
|
|
789
|
+
type: 2 /* delim */,
|
|
819
790
|
text: this.text[this.nextInputCodePointIndex++],
|
|
820
791
|
};
|
|
821
|
-
}
|
|
822
|
-
|
|
792
|
+
}
|
|
793
|
+
consumeAWhitespace() {
|
|
823
794
|
whitespaceRegEx.lastIndex = this.nextInputCodePointIndex;
|
|
824
795
|
whitespaceRegEx.exec(this.text);
|
|
825
796
|
this.nextInputCodePointIndex = whitespaceRegEx.lastIndex;
|
|
826
797
|
return ' ';
|
|
827
|
-
}
|
|
828
|
-
|
|
798
|
+
}
|
|
799
|
+
consumeAHashToken() {
|
|
829
800
|
this.nextInputCodePointIndex++;
|
|
830
|
-
|
|
801
|
+
const hashName = this.consumeAName();
|
|
831
802
|
if (hashName) {
|
|
832
|
-
return { type: 12
|
|
803
|
+
return { type: 12 /* hash */, text: '#' + hashName.text };
|
|
833
804
|
}
|
|
834
805
|
this.nextInputCodePointIndex--;
|
|
835
806
|
return null;
|
|
836
|
-
}
|
|
837
|
-
|
|
807
|
+
}
|
|
808
|
+
consumeCDO() {
|
|
838
809
|
if (this.text.substr(this.nextInputCodePointIndex, 4) === '<!--') {
|
|
839
810
|
this.nextInputCodePointIndex += 4;
|
|
840
811
|
return '<!--';
|
|
841
812
|
}
|
|
842
813
|
return null;
|
|
843
|
-
}
|
|
844
|
-
|
|
814
|
+
}
|
|
815
|
+
consumeCDC() {
|
|
845
816
|
if (this.text.substr(this.nextInputCodePointIndex, 3) === '-->') {
|
|
846
817
|
this.nextInputCodePointIndex += 3;
|
|
847
818
|
return '-->';
|
|
848
819
|
}
|
|
849
820
|
return null;
|
|
850
|
-
}
|
|
851
|
-
|
|
821
|
+
}
|
|
822
|
+
consumeAMatchToken() {
|
|
852
823
|
if (this.text[this.nextInputCodePointIndex + 1] === '=') {
|
|
853
|
-
|
|
824
|
+
const token = this.text.substr(this.nextInputCodePointIndex, 2);
|
|
854
825
|
this.nextInputCodePointIndex += 2;
|
|
855
826
|
return token;
|
|
856
827
|
}
|
|
857
828
|
return null;
|
|
858
|
-
}
|
|
859
|
-
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* 4.3.2. Consume a numeric token
|
|
832
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-numeric-token
|
|
833
|
+
*/
|
|
834
|
+
consumeANumericToken() {
|
|
860
835
|
numberRegEx.lastIndex = this.nextInputCodePointIndex;
|
|
861
|
-
|
|
836
|
+
const result = numberRegEx.exec(this.text);
|
|
862
837
|
if (!result) {
|
|
863
838
|
return null;
|
|
864
839
|
}
|
|
865
840
|
this.nextInputCodePointIndex = numberRegEx.lastIndex;
|
|
866
841
|
if (this.text[this.nextInputCodePointIndex] === '%') {
|
|
867
|
-
return { type: 4
|
|
842
|
+
return { type: 4 /* percentage */, text: result[0] }; // TODO: Push the actual number and unit here...
|
|
868
843
|
}
|
|
869
|
-
|
|
844
|
+
const name = this.consumeAName();
|
|
870
845
|
if (name) {
|
|
871
846
|
return {
|
|
872
|
-
type: 5
|
|
847
|
+
type: 5 /* dimension */,
|
|
873
848
|
text: result[0] + name.text,
|
|
874
849
|
};
|
|
875
850
|
}
|
|
876
|
-
return { type: 3
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
|
|
851
|
+
return { type: 3 /* number */, text: result[0] };
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* 4.3.3. Consume an ident-like token
|
|
855
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-an-ident-like-token
|
|
856
|
+
*/
|
|
857
|
+
consumeAnIdentLikeToken() {
|
|
858
|
+
const name = this.consumeAName();
|
|
880
859
|
if (!name) {
|
|
881
860
|
return null;
|
|
882
861
|
}
|
|
@@ -886,16 +865,20 @@ var CSS3Parser = (function () {
|
|
|
886
865
|
return this.consumeAURLToken();
|
|
887
866
|
}
|
|
888
867
|
return {
|
|
889
|
-
type: 8
|
|
868
|
+
type: 8 /* functionToken */,
|
|
890
869
|
name: name.text,
|
|
891
870
|
text: name.text + '(',
|
|
892
871
|
};
|
|
893
872
|
}
|
|
894
873
|
return name;
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* 4.3.4. Consume a string token
|
|
877
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-string-token
|
|
878
|
+
*/
|
|
879
|
+
consumeAStringToken() {
|
|
880
|
+
const char = this.text[this.nextInputCodePointIndex];
|
|
881
|
+
let result;
|
|
899
882
|
if (char === "'") {
|
|
900
883
|
singleQuoteStringRegEx.lastIndex = this.nextInputCodePointIndex;
|
|
901
884
|
result = singleQuoteStringRegEx.exec(this.text);
|
|
@@ -912,35 +895,44 @@ var CSS3Parser = (function () {
|
|
|
912
895
|
}
|
|
913
896
|
this.nextInputCodePointIndex = doubleQuoteStringRegEx.lastIndex;
|
|
914
897
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
898
|
+
// TODO: Handle bad-string.
|
|
899
|
+
// TODO: Perform string escaping.
|
|
900
|
+
return { type: 1 /* string */, text: result[0] };
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* 4.3.5. Consume a url token
|
|
904
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-url-token
|
|
905
|
+
*/
|
|
906
|
+
consumeAURLToken() {
|
|
907
|
+
const start = this.nextInputCodePointIndex - 3 /* url */ - 1; /* ( */
|
|
908
|
+
const urlToken = {
|
|
909
|
+
type: 7 /* url */,
|
|
921
910
|
text: undefined,
|
|
922
911
|
};
|
|
923
912
|
this.consumeAWhitespace();
|
|
924
913
|
if (this.nextInputCodePointIndex >= this.text.length) {
|
|
925
914
|
return urlToken;
|
|
926
915
|
}
|
|
927
|
-
|
|
916
|
+
const nextInputCodePoint = this.text[this.nextInputCodePointIndex];
|
|
928
917
|
if (nextInputCodePoint === '"' || nextInputCodePoint === "'") {
|
|
929
|
-
|
|
918
|
+
const stringToken = this.consumeAStringToken();
|
|
919
|
+
// TODO: Handle bad-string.
|
|
920
|
+
// TODO: Set value instead.
|
|
930
921
|
urlToken.text = stringToken.text;
|
|
931
922
|
this.consumeAWhitespace();
|
|
932
923
|
if (this.text[this.nextInputCodePointIndex] === ')' || this.nextInputCodePointIndex >= this.text.length) {
|
|
933
924
|
this.nextInputCodePointIndex++;
|
|
934
|
-
|
|
925
|
+
const end = this.nextInputCodePointIndex;
|
|
935
926
|
urlToken.text = this.text.substring(start, end);
|
|
936
927
|
return urlToken;
|
|
937
928
|
}
|
|
938
929
|
else {
|
|
930
|
+
// TODO: Handle bad-url.
|
|
939
931
|
return null;
|
|
940
932
|
}
|
|
941
933
|
}
|
|
942
934
|
while (this.nextInputCodePointIndex < this.text.length) {
|
|
943
|
-
|
|
935
|
+
const char = this.text[this.nextInputCodePointIndex++];
|
|
944
936
|
switch (char) {
|
|
945
937
|
case ')':
|
|
946
938
|
return urlToken;
|
|
@@ -955,61 +947,79 @@ var CSS3Parser = (function () {
|
|
|
955
947
|
return urlToken;
|
|
956
948
|
}
|
|
957
949
|
else {
|
|
950
|
+
// TODO: Bar url! Consume remnants.
|
|
958
951
|
return null;
|
|
959
952
|
}
|
|
960
953
|
case '"':
|
|
961
954
|
case "'":
|
|
955
|
+
// TODO: Parse error! Bar url! Consume remnants.
|
|
962
956
|
return null;
|
|
963
957
|
case '\\':
|
|
958
|
+
// TODO: Escape!
|
|
964
959
|
throw new Error('Escaping not yet supported!');
|
|
965
960
|
default:
|
|
961
|
+
// TODO: Non-printable chars - error.
|
|
966
962
|
urlToken.text += char;
|
|
967
963
|
}
|
|
968
964
|
}
|
|
969
965
|
return urlToken;
|
|
970
|
-
}
|
|
971
|
-
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* 4.3.11. Consume a name
|
|
969
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-name
|
|
970
|
+
*/
|
|
971
|
+
consumeAName() {
|
|
972
972
|
nameRegEx.lastIndex = this.nextInputCodePointIndex;
|
|
973
|
-
|
|
973
|
+
const result = nameRegEx.exec(this.text);
|
|
974
974
|
if (!result) {
|
|
975
975
|
return null;
|
|
976
976
|
}
|
|
977
977
|
this.nextInputCodePointIndex = nameRegEx.lastIndex;
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
978
|
+
// TODO: Perform string escaping.
|
|
979
|
+
return { type: 6 /* ident */, text: result[0] };
|
|
980
|
+
}
|
|
981
|
+
consumeAtKeyword() {
|
|
981
982
|
this.nextInputCodePointIndex++;
|
|
982
|
-
|
|
983
|
+
const name = this.consumeAName();
|
|
983
984
|
if (name) {
|
|
984
|
-
return { type: 11
|
|
985
|
+
return { type: 11 /* atKeyword */, text: name.text };
|
|
985
986
|
}
|
|
986
987
|
this.nextInputCodePointIndex--;
|
|
987
988
|
return null;
|
|
988
|
-
}
|
|
989
|
-
|
|
989
|
+
}
|
|
990
|
+
consumeAComment() {
|
|
990
991
|
if (this.text[this.nextInputCodePointIndex + 1] === '*') {
|
|
991
992
|
commentRegEx.lastIndex = this.nextInputCodePointIndex;
|
|
992
|
-
|
|
993
|
+
const result = commentRegEx.exec(this.text);
|
|
993
994
|
if (!result) {
|
|
994
|
-
return null;
|
|
995
|
+
return null; // TODO: Handle <bad-comment>
|
|
995
996
|
}
|
|
996
997
|
this.nextInputCodePointIndex = commentRegEx.lastIndex;
|
|
998
|
+
// The CSS spec tokenizer does not emmit comment tokens
|
|
997
999
|
return this.consumeAToken();
|
|
998
1000
|
}
|
|
999
1001
|
return null;
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
+
}
|
|
1003
|
+
reconsumeTheCurrentInputToken(currentInputToken) {
|
|
1002
1004
|
this.reconsumedInputToken = currentInputToken;
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* 5.3.1. Parse a stylesheet
|
|
1008
|
+
* https://www.w3.org/TR/css-syntax-3/#parse-a-stylesheet
|
|
1009
|
+
*/
|
|
1010
|
+
parseAStylesheet() {
|
|
1005
1011
|
this.topLevelFlag = true;
|
|
1006
1012
|
return {
|
|
1007
1013
|
rules: this.consumeAListOfRules(),
|
|
1008
1014
|
};
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* 5.4.1. Consume a list of rules
|
|
1018
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-list-of-rules
|
|
1019
|
+
*/
|
|
1020
|
+
consumeAListOfRules() {
|
|
1021
|
+
const rules = [];
|
|
1022
|
+
let inputToken;
|
|
1013
1023
|
while ((inputToken = this.consumeAToken())) {
|
|
1014
1024
|
switch (inputToken) {
|
|
1015
1025
|
case ' ':
|
|
@@ -1020,32 +1030,36 @@ var CSS3Parser = (function () {
|
|
|
1020
1030
|
continue;
|
|
1021
1031
|
}
|
|
1022
1032
|
this.reconsumeTheCurrentInputToken(inputToken);
|
|
1023
|
-
|
|
1033
|
+
const atRule = this.consumeAnAtRule();
|
|
1024
1034
|
if (atRule) {
|
|
1025
1035
|
rules.push(atRule);
|
|
1026
1036
|
}
|
|
1027
1037
|
continue;
|
|
1028
1038
|
}
|
|
1029
1039
|
}
|
|
1030
|
-
if (inputToken.type === 11) {
|
|
1040
|
+
if (inputToken.type === 11 /* atKeyword */) {
|
|
1031
1041
|
this.reconsumeTheCurrentInputToken(inputToken);
|
|
1032
|
-
|
|
1042
|
+
const atRule = this.consumeAnAtRule();
|
|
1033
1043
|
if (atRule) {
|
|
1034
1044
|
rules.push(atRule);
|
|
1035
1045
|
}
|
|
1036
1046
|
continue;
|
|
1037
1047
|
}
|
|
1038
1048
|
this.reconsumeTheCurrentInputToken(inputToken);
|
|
1039
|
-
|
|
1049
|
+
const qualifiedRule = this.consumeAQualifiedRule();
|
|
1040
1050
|
if (qualifiedRule) {
|
|
1041
1051
|
rules.push(qualifiedRule);
|
|
1042
1052
|
}
|
|
1043
1053
|
}
|
|
1044
1054
|
return rules;
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* 5.4.2. Consume an at-rule
|
|
1058
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-an-at-rule
|
|
1059
|
+
*/
|
|
1060
|
+
consumeAnAtRule() {
|
|
1061
|
+
let inputToken = this.consumeAToken();
|
|
1062
|
+
const atRule = {
|
|
1049
1063
|
type: 'at-rule',
|
|
1050
1064
|
name: inputToken.text,
|
|
1051
1065
|
prelude: [],
|
|
@@ -1059,47 +1073,57 @@ var CSS3Parser = (function () {
|
|
|
1059
1073
|
atRule.block = this.consumeASimpleBlock(inputToken);
|
|
1060
1074
|
return atRule;
|
|
1061
1075
|
}
|
|
1062
|
-
else if (inputToken.type === 9 && inputToken.associatedToken === '{') {
|
|
1076
|
+
else if (inputToken.type === 9 /* simpleBlock */ && inputToken.associatedToken === '{') {
|
|
1063
1077
|
atRule.block = inputToken;
|
|
1064
1078
|
return atRule;
|
|
1065
1079
|
}
|
|
1066
1080
|
this.reconsumeTheCurrentInputToken(inputToken);
|
|
1067
|
-
|
|
1081
|
+
const component = this.consumeAComponentValue();
|
|
1068
1082
|
if (component) {
|
|
1069
1083
|
atRule.prelude.push(component);
|
|
1070
1084
|
}
|
|
1071
1085
|
}
|
|
1072
1086
|
return atRule;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1089
|
+
* 5.4.3. Consume a qualified rule
|
|
1090
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-qualified-rule
|
|
1091
|
+
*/
|
|
1092
|
+
consumeAQualifiedRule() {
|
|
1093
|
+
const qualifiedRule = {
|
|
1076
1094
|
type: 'qualified-rule',
|
|
1077
1095
|
prelude: [],
|
|
1078
1096
|
block: undefined,
|
|
1079
1097
|
};
|
|
1080
|
-
|
|
1098
|
+
let inputToken;
|
|
1081
1099
|
while ((inputToken = this.consumeAToken())) {
|
|
1082
1100
|
if (inputToken === '{') {
|
|
1083
1101
|
qualifiedRule.block = this.consumeASimpleBlock(inputToken);
|
|
1084
1102
|
return qualifiedRule;
|
|
1085
1103
|
}
|
|
1086
|
-
else if (inputToken.type === 9) {
|
|
1087
|
-
|
|
1104
|
+
else if (inputToken.type === 9 /* simpleBlock */) {
|
|
1105
|
+
const simpleBlock = inputToken;
|
|
1088
1106
|
if (simpleBlock.associatedToken === '{') {
|
|
1089
1107
|
qualifiedRule.block = simpleBlock;
|
|
1090
1108
|
return qualifiedRule;
|
|
1091
1109
|
}
|
|
1092
1110
|
}
|
|
1093
1111
|
this.reconsumeTheCurrentInputToken(inputToken);
|
|
1094
|
-
|
|
1112
|
+
const componentValue = this.consumeAComponentValue();
|
|
1095
1113
|
if (componentValue) {
|
|
1096
1114
|
qualifiedRule.prelude.push(componentValue);
|
|
1097
1115
|
}
|
|
1098
1116
|
}
|
|
1117
|
+
// TODO: This is a parse error, log parse errors!
|
|
1099
1118
|
return null;
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1119
|
+
}
|
|
1120
|
+
/**
|
|
1121
|
+
* 5.4.6. Consume a component value
|
|
1122
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-component-value
|
|
1123
|
+
*/
|
|
1124
|
+
consumeAComponentValue() {
|
|
1125
|
+
// const inputToken = this.consumeAToken();
|
|
1126
|
+
const inputToken = this.consumeAToken();
|
|
1103
1127
|
switch (inputToken) {
|
|
1104
1128
|
case '{':
|
|
1105
1129
|
case '[':
|
|
@@ -1107,45 +1131,53 @@ var CSS3Parser = (function () {
|
|
|
1107
1131
|
this.nextInputCodePointIndex++;
|
|
1108
1132
|
return this.consumeASimpleBlock(inputToken);
|
|
1109
1133
|
}
|
|
1110
|
-
if (typeof inputToken === 'object' && inputToken.type === 8) {
|
|
1134
|
+
if (typeof inputToken === 'object' && inputToken.type === 8 /* functionToken */) {
|
|
1111
1135
|
return this.consumeAFunction(inputToken.name);
|
|
1112
1136
|
}
|
|
1113
1137
|
return inputToken;
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* 5.4.7. Consume a simple block
|
|
1141
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-simple-block
|
|
1142
|
+
*/
|
|
1143
|
+
consumeASimpleBlock(associatedToken) {
|
|
1144
|
+
const endianToken = {
|
|
1117
1145
|
'[': ']',
|
|
1118
1146
|
'{': '}',
|
|
1119
1147
|
'(': ')',
|
|
1120
1148
|
}[associatedToken];
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
type: 9
|
|
1149
|
+
const start = this.nextInputCodePointIndex - 1;
|
|
1150
|
+
const block = {
|
|
1151
|
+
type: 9 /* simpleBlock */,
|
|
1124
1152
|
text: undefined,
|
|
1125
|
-
associatedToken
|
|
1153
|
+
associatedToken,
|
|
1126
1154
|
values: [],
|
|
1127
1155
|
};
|
|
1128
|
-
|
|
1156
|
+
let nextInputToken;
|
|
1129
1157
|
while ((nextInputToken = this.text[this.nextInputCodePointIndex])) {
|
|
1130
1158
|
if (nextInputToken === endianToken) {
|
|
1131
1159
|
this.nextInputCodePointIndex++;
|
|
1132
|
-
|
|
1160
|
+
const end = this.nextInputCodePointIndex;
|
|
1133
1161
|
block.text = this.text.substring(start, end);
|
|
1134
1162
|
return block;
|
|
1135
1163
|
}
|
|
1136
|
-
|
|
1164
|
+
const value = this.consumeAComponentValue();
|
|
1137
1165
|
if (value) {
|
|
1138
1166
|
block.values.push(value);
|
|
1139
1167
|
}
|
|
1140
1168
|
}
|
|
1141
1169
|
block.text = this.text.substring(start);
|
|
1142
1170
|
return block;
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1171
|
+
}
|
|
1172
|
+
/**
|
|
1173
|
+
* 5.4.8. Consume a function
|
|
1174
|
+
* https://www.w3.org/TR/css-syntax-3/#consume-a-function
|
|
1175
|
+
*/
|
|
1176
|
+
consumeAFunction(name) {
|
|
1177
|
+
const start = this.nextInputCodePointIndex;
|
|
1178
|
+
const funcToken = {
|
|
1179
|
+
type: 14 /* function */,
|
|
1180
|
+
name,
|
|
1149
1181
|
text: undefined,
|
|
1150
1182
|
components: [],
|
|
1151
1183
|
};
|
|
@@ -1154,75 +1186,77 @@ var CSS3Parser = (function () {
|
|
|
1154
1186
|
funcToken.text = name + '(' + this.text.substring(start);
|
|
1155
1187
|
return funcToken;
|
|
1156
1188
|
}
|
|
1157
|
-
|
|
1189
|
+
const nextInputToken = this.text[this.nextInputCodePointIndex];
|
|
1158
1190
|
switch (nextInputToken) {
|
|
1159
1191
|
case ')': {
|
|
1160
1192
|
this.nextInputCodePointIndex++;
|
|
1161
|
-
|
|
1193
|
+
const end = this.nextInputCodePointIndex;
|
|
1162
1194
|
funcToken.text = name + '(' + this.text.substring(start, end);
|
|
1163
1195
|
return funcToken;
|
|
1164
1196
|
}
|
|
1165
1197
|
default: {
|
|
1166
|
-
|
|
1198
|
+
const component = this.consumeAComponentValue();
|
|
1167
1199
|
if (component) {
|
|
1168
1200
|
funcToken.components.push(component);
|
|
1169
1201
|
}
|
|
1170
1202
|
}
|
|
1203
|
+
// TODO: Else we won't advance
|
|
1171
1204
|
}
|
|
1172
1205
|
} while (true);
|
|
1173
|
-
};
|
|
1174
|
-
return CSS3Parser;
|
|
1175
|
-
}());
|
|
1176
|
-
exports.CSS3Parser = CSS3Parser;
|
|
1177
|
-
var CSSNativeScript = (function () {
|
|
1178
|
-
function CSSNativeScript() {
|
|
1179
1206
|
}
|
|
1180
|
-
|
|
1207
|
+
}
|
|
1208
|
+
/**
|
|
1209
|
+
* Consume a CSS3 parsed stylesheet and convert the rules and selectors to the
|
|
1210
|
+
* NativeScript internal JSON representation.
|
|
1211
|
+
*/
|
|
1212
|
+
export class CSSNativeScript {
|
|
1213
|
+
parseStylesheet(stylesheet) {
|
|
1181
1214
|
return {
|
|
1182
1215
|
type: 'stylesheet',
|
|
1183
1216
|
stylesheet: {
|
|
1184
1217
|
rules: this.parseRules(stylesheet.rules),
|
|
1185
1218
|
},
|
|
1186
1219
|
};
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
CSSNativeScript.prototype.parseRule = function (rule) {
|
|
1220
|
+
}
|
|
1221
|
+
parseRules(rules) {
|
|
1222
|
+
return rules.map((rule) => this.parseRule(rule));
|
|
1223
|
+
}
|
|
1224
|
+
parseRule(rule) {
|
|
1193
1225
|
if (rule.type === 'at-rule') {
|
|
1194
1226
|
return this.parseAtRule(rule);
|
|
1195
1227
|
}
|
|
1196
1228
|
else if (rule.type === 'qualified-rule') {
|
|
1197
1229
|
return this.parseQualifiedRule(rule);
|
|
1198
1230
|
}
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1231
|
+
}
|
|
1232
|
+
parseAtRule(rule) {
|
|
1201
1233
|
if (rule.name === 'import') {
|
|
1234
|
+
// TODO: We have used an "@import { url('path somewhere'); }" at few places.
|
|
1202
1235
|
return {
|
|
1203
1236
|
import: rule.prelude
|
|
1204
|
-
.map(
|
|
1237
|
+
.map((m) => (typeof m === 'string' ? m : m.text))
|
|
1205
1238
|
.join('')
|
|
1206
1239
|
.trim(),
|
|
1207
1240
|
type: 'import',
|
|
1208
1241
|
};
|
|
1209
1242
|
}
|
|
1210
1243
|
return;
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1244
|
+
}
|
|
1245
|
+
parseQualifiedRule(rule) {
|
|
1213
1246
|
return {
|
|
1214
1247
|
type: 'rule',
|
|
1215
1248
|
selectors: this.preludeToSelectorsStringArray(rule.prelude),
|
|
1216
1249
|
declarations: this.ruleBlockToDeclarations(rule.block.values),
|
|
1217
1250
|
};
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1251
|
+
}
|
|
1252
|
+
ruleBlockToDeclarations(declarationsInputTokens) {
|
|
1253
|
+
// return <any>declarationsInputTokens;
|
|
1254
|
+
const declarations = [];
|
|
1255
|
+
let property = '';
|
|
1256
|
+
let value = '';
|
|
1257
|
+
let reading = 'property';
|
|
1258
|
+
for (let i = 0; i < declarationsInputTokens.length; i++) {
|
|
1259
|
+
const inputToken = declarationsInputTokens[i];
|
|
1226
1260
|
if (reading === 'property') {
|
|
1227
1261
|
if (inputToken === ':') {
|
|
1228
1262
|
reading = 'value';
|
|
@@ -1238,7 +1272,7 @@ var CSSNativeScript = (function () {
|
|
|
1238
1272
|
if (inputToken === ';') {
|
|
1239
1273
|
property = property.trim();
|
|
1240
1274
|
value = value.trim();
|
|
1241
|
-
declarations.push({ type: 'declaration', property
|
|
1275
|
+
declarations.push({ type: 'declaration', property, value });
|
|
1242
1276
|
property = '';
|
|
1243
1277
|
value = '';
|
|
1244
1278
|
reading = 'property';
|
|
@@ -1254,14 +1288,14 @@ var CSSNativeScript = (function () {
|
|
|
1254
1288
|
property = property.trim();
|
|
1255
1289
|
value = value.trim();
|
|
1256
1290
|
if (property || value) {
|
|
1257
|
-
declarations.push({ type: 'declaration', property
|
|
1291
|
+
declarations.push({ type: 'declaration', property, value });
|
|
1258
1292
|
}
|
|
1259
1293
|
return declarations;
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
prelude.forEach(
|
|
1294
|
+
}
|
|
1295
|
+
preludeToSelectorsStringArray(prelude) {
|
|
1296
|
+
const selectors = [];
|
|
1297
|
+
let selector = '';
|
|
1298
|
+
prelude.forEach((inputToken) => {
|
|
1265
1299
|
if (typeof inputToken === 'string') {
|
|
1266
1300
|
if (inputToken === ',') {
|
|
1267
1301
|
if (selector) {
|
|
@@ -1281,8 +1315,6 @@ var CSSNativeScript = (function () {
|
|
|
1281
1315
|
selectors.push(selector.trim());
|
|
1282
1316
|
}
|
|
1283
1317
|
return selectors;
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
}());
|
|
1287
|
-
exports.CSSNativeScript = CSSNativeScript;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1288
1320
|
//# sourceMappingURL=parser.js.map
|