source: imaps-frontend/node_modules/css-what/lib/commonjs/parse.js@ 79a0317

main
Last change on this file since 79a0317 was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 16.5 KB
RevLine 
[79a0317]1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.parse = exports.isTraversal = void 0;
4var types_1 = require("./types");
5var reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
6var reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
7var actionTypes = new Map([
8 [126 /* Tilde */, types_1.AttributeAction.Element],
9 [94 /* Circumflex */, types_1.AttributeAction.Start],
10 [36 /* Dollar */, types_1.AttributeAction.End],
11 [42 /* Asterisk */, types_1.AttributeAction.Any],
12 [33 /* ExclamationMark */, types_1.AttributeAction.Not],
13 [124 /* Pipe */, types_1.AttributeAction.Hyphen],
14]);
15// Pseudos, whose data property is parsed as well.
16var unpackPseudos = new Set([
17 "has",
18 "not",
19 "matches",
20 "is",
21 "where",
22 "host",
23 "host-context",
24]);
25/**
26 * Checks whether a specific selector is a traversal.
27 * This is useful eg. in swapping the order of elements that
28 * are not traversals.
29 *
30 * @param selector Selector to check.
31 */
32function isTraversal(selector) {
33 switch (selector.type) {
34 case types_1.SelectorType.Adjacent:
35 case types_1.SelectorType.Child:
36 case types_1.SelectorType.Descendant:
37 case types_1.SelectorType.Parent:
38 case types_1.SelectorType.Sibling:
39 case types_1.SelectorType.ColumnCombinator:
40 return true;
41 default:
42 return false;
43 }
44}
45exports.isTraversal = isTraversal;
46var stripQuotesFromPseudos = new Set(["contains", "icontains"]);
47// Unescape function taken from https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L152
48function funescape(_, escaped, escapedWhitespace) {
49 var high = parseInt(escaped, 16) - 0x10000;
50 // NaN means non-codepoint
51 return high !== high || escapedWhitespace
52 ? escaped
53 : high < 0
54 ? // BMP codepoint
55 String.fromCharCode(high + 0x10000)
56 : // Supplemental Plane codepoint (surrogate pair)
57 String.fromCharCode((high >> 10) | 0xd800, (high & 0x3ff) | 0xdc00);
58}
59function unescapeCSS(str) {
60 return str.replace(reEscape, funescape);
61}
62function isQuote(c) {
63 return c === 39 /* SingleQuote */ || c === 34 /* DoubleQuote */;
64}
65function isWhitespace(c) {
66 return (c === 32 /* Space */ ||
67 c === 9 /* Tab */ ||
68 c === 10 /* NewLine */ ||
69 c === 12 /* FormFeed */ ||
70 c === 13 /* CarriageReturn */);
71}
72/**
73 * Parses `selector`, optionally with the passed `options`.
74 *
75 * @param selector Selector to parse.
76 * @param options Options for parsing.
77 * @returns Returns a two-dimensional array.
78 * The first dimension represents selectors separated by commas (eg. `sub1, sub2`),
79 * the second contains the relevant tokens for that selector.
80 */
81function parse(selector) {
82 var subselects = [];
83 var endIndex = parseSelector(subselects, "".concat(selector), 0);
84 if (endIndex < selector.length) {
85 throw new Error("Unmatched selector: ".concat(selector.slice(endIndex)));
86 }
87 return subselects;
88}
89exports.parse = parse;
90function parseSelector(subselects, selector, selectorIndex) {
91 var tokens = [];
92 function getName(offset) {
93 var match = selector.slice(selectorIndex + offset).match(reName);
94 if (!match) {
95 throw new Error("Expected name, found ".concat(selector.slice(selectorIndex)));
96 }
97 var name = match[0];
98 selectorIndex += offset + name.length;
99 return unescapeCSS(name);
100 }
101 function stripWhitespace(offset) {
102 selectorIndex += offset;
103 while (selectorIndex < selector.length &&
104 isWhitespace(selector.charCodeAt(selectorIndex))) {
105 selectorIndex++;
106 }
107 }
108 function readValueWithParenthesis() {
109 selectorIndex += 1;
110 var start = selectorIndex;
111 var counter = 1;
112 for (; counter > 0 && selectorIndex < selector.length; selectorIndex++) {
113 if (selector.charCodeAt(selectorIndex) ===
114 40 /* LeftParenthesis */ &&
115 !isEscaped(selectorIndex)) {
116 counter++;
117 }
118 else if (selector.charCodeAt(selectorIndex) ===
119 41 /* RightParenthesis */ &&
120 !isEscaped(selectorIndex)) {
121 counter--;
122 }
123 }
124 if (counter) {
125 throw new Error("Parenthesis not matched");
126 }
127 return unescapeCSS(selector.slice(start, selectorIndex - 1));
128 }
129 function isEscaped(pos) {
130 var slashCount = 0;
131 while (selector.charCodeAt(--pos) === 92 /* BackSlash */)
132 slashCount++;
133 return (slashCount & 1) === 1;
134 }
135 function ensureNotTraversal() {
136 if (tokens.length > 0 && isTraversal(tokens[tokens.length - 1])) {
137 throw new Error("Did not expect successive traversals.");
138 }
139 }
140 function addTraversal(type) {
141 if (tokens.length > 0 &&
142 tokens[tokens.length - 1].type === types_1.SelectorType.Descendant) {
143 tokens[tokens.length - 1].type = type;
144 return;
145 }
146 ensureNotTraversal();
147 tokens.push({ type: type });
148 }
149 function addSpecialAttribute(name, action) {
150 tokens.push({
151 type: types_1.SelectorType.Attribute,
152 name: name,
153 action: action,
154 value: getName(1),
155 namespace: null,
156 ignoreCase: "quirks",
157 });
158 }
159 /**
160 * We have finished parsing the current part of the selector.
161 *
162 * Remove descendant tokens at the end if they exist,
163 * and return the last index, so that parsing can be
164 * picked up from here.
165 */
166 function finalizeSubselector() {
167 if (tokens.length &&
168 tokens[tokens.length - 1].type === types_1.SelectorType.Descendant) {
169 tokens.pop();
170 }
171 if (tokens.length === 0) {
172 throw new Error("Empty sub-selector");
173 }
174 subselects.push(tokens);
175 }
176 stripWhitespace(0);
177 if (selector.length === selectorIndex) {
178 return selectorIndex;
179 }
180 loop: while (selectorIndex < selector.length) {
181 var firstChar = selector.charCodeAt(selectorIndex);
182 switch (firstChar) {
183 // Whitespace
184 case 32 /* Space */:
185 case 9 /* Tab */:
186 case 10 /* NewLine */:
187 case 12 /* FormFeed */:
188 case 13 /* CarriageReturn */: {
189 if (tokens.length === 0 ||
190 tokens[0].type !== types_1.SelectorType.Descendant) {
191 ensureNotTraversal();
192 tokens.push({ type: types_1.SelectorType.Descendant });
193 }
194 stripWhitespace(1);
195 break;
196 }
197 // Traversals
198 case 62 /* GreaterThan */: {
199 addTraversal(types_1.SelectorType.Child);
200 stripWhitespace(1);
201 break;
202 }
203 case 60 /* LessThan */: {
204 addTraversal(types_1.SelectorType.Parent);
205 stripWhitespace(1);
206 break;
207 }
208 case 126 /* Tilde */: {
209 addTraversal(types_1.SelectorType.Sibling);
210 stripWhitespace(1);
211 break;
212 }
213 case 43 /* Plus */: {
214 addTraversal(types_1.SelectorType.Adjacent);
215 stripWhitespace(1);
216 break;
217 }
218 // Special attribute selectors: .class, #id
219 case 46 /* Period */: {
220 addSpecialAttribute("class", types_1.AttributeAction.Element);
221 break;
222 }
223 case 35 /* Hash */: {
224 addSpecialAttribute("id", types_1.AttributeAction.Equals);
225 break;
226 }
227 case 91 /* LeftSquareBracket */: {
228 stripWhitespace(1);
229 // Determine attribute name and namespace
230 var name_1 = void 0;
231 var namespace = null;
232 if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */) {
233 // Equivalent to no namespace
234 name_1 = getName(1);
235 }
236 else if (selector.startsWith("*|", selectorIndex)) {
237 namespace = "*";
238 name_1 = getName(2);
239 }
240 else {
241 name_1 = getName(0);
242 if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */ &&
243 selector.charCodeAt(selectorIndex + 1) !==
244 61 /* Equal */) {
245 namespace = name_1;
246 name_1 = getName(1);
247 }
248 }
249 stripWhitespace(0);
250 // Determine comparison operation
251 var action = types_1.AttributeAction.Exists;
252 var possibleAction = actionTypes.get(selector.charCodeAt(selectorIndex));
253 if (possibleAction) {
254 action = possibleAction;
255 if (selector.charCodeAt(selectorIndex + 1) !==
256 61 /* Equal */) {
257 throw new Error("Expected `=`");
258 }
259 stripWhitespace(2);
260 }
261 else if (selector.charCodeAt(selectorIndex) === 61 /* Equal */) {
262 action = types_1.AttributeAction.Equals;
263 stripWhitespace(1);
264 }
265 // Determine value
266 var value = "";
267 var ignoreCase = null;
268 if (action !== "exists") {
269 if (isQuote(selector.charCodeAt(selectorIndex))) {
270 var quote = selector.charCodeAt(selectorIndex);
271 var sectionEnd = selectorIndex + 1;
272 while (sectionEnd < selector.length &&
273 (selector.charCodeAt(sectionEnd) !== quote ||
274 isEscaped(sectionEnd))) {
275 sectionEnd += 1;
276 }
277 if (selector.charCodeAt(sectionEnd) !== quote) {
278 throw new Error("Attribute value didn't end");
279 }
280 value = unescapeCSS(selector.slice(selectorIndex + 1, sectionEnd));
281 selectorIndex = sectionEnd + 1;
282 }
283 else {
284 var valueStart = selectorIndex;
285 while (selectorIndex < selector.length &&
286 ((!isWhitespace(selector.charCodeAt(selectorIndex)) &&
287 selector.charCodeAt(selectorIndex) !==
288 93 /* RightSquareBracket */) ||
289 isEscaped(selectorIndex))) {
290 selectorIndex += 1;
291 }
292 value = unescapeCSS(selector.slice(valueStart, selectorIndex));
293 }
294 stripWhitespace(0);
295 // See if we have a force ignore flag
296 var forceIgnore = selector.charCodeAt(selectorIndex) | 0x20;
297 // If the forceIgnore flag is set (either `i` or `s`), use that value
298 if (forceIgnore === 115 /* LowerS */) {
299 ignoreCase = false;
300 stripWhitespace(1);
301 }
302 else if (forceIgnore === 105 /* LowerI */) {
303 ignoreCase = true;
304 stripWhitespace(1);
305 }
306 }
307 if (selector.charCodeAt(selectorIndex) !==
308 93 /* RightSquareBracket */) {
309 throw new Error("Attribute selector didn't terminate");
310 }
311 selectorIndex += 1;
312 var attributeSelector = {
313 type: types_1.SelectorType.Attribute,
314 name: name_1,
315 action: action,
316 value: value,
317 namespace: namespace,
318 ignoreCase: ignoreCase,
319 };
320 tokens.push(attributeSelector);
321 break;
322 }
323 case 58 /* Colon */: {
324 if (selector.charCodeAt(selectorIndex + 1) === 58 /* Colon */) {
325 tokens.push({
326 type: types_1.SelectorType.PseudoElement,
327 name: getName(2).toLowerCase(),
328 data: selector.charCodeAt(selectorIndex) ===
329 40 /* LeftParenthesis */
330 ? readValueWithParenthesis()
331 : null,
332 });
333 continue;
334 }
335 var name_2 = getName(1).toLowerCase();
336 var data = null;
337 if (selector.charCodeAt(selectorIndex) ===
338 40 /* LeftParenthesis */) {
339 if (unpackPseudos.has(name_2)) {
340 if (isQuote(selector.charCodeAt(selectorIndex + 1))) {
341 throw new Error("Pseudo-selector ".concat(name_2, " cannot be quoted"));
342 }
343 data = [];
344 selectorIndex = parseSelector(data, selector, selectorIndex + 1);
345 if (selector.charCodeAt(selectorIndex) !==
346 41 /* RightParenthesis */) {
347 throw new Error("Missing closing parenthesis in :".concat(name_2, " (").concat(selector, ")"));
348 }
349 selectorIndex += 1;
350 }
351 else {
352 data = readValueWithParenthesis();
353 if (stripQuotesFromPseudos.has(name_2)) {
354 var quot = data.charCodeAt(0);
355 if (quot === data.charCodeAt(data.length - 1) &&
356 isQuote(quot)) {
357 data = data.slice(1, -1);
358 }
359 }
360 data = unescapeCSS(data);
361 }
362 }
363 tokens.push({ type: types_1.SelectorType.Pseudo, name: name_2, data: data });
364 break;
365 }
366 case 44 /* Comma */: {
367 finalizeSubselector();
368 tokens = [];
369 stripWhitespace(1);
370 break;
371 }
372 default: {
373 if (selector.startsWith("/*", selectorIndex)) {
374 var endIndex = selector.indexOf("*/", selectorIndex + 2);
375 if (endIndex < 0) {
376 throw new Error("Comment was not terminated");
377 }
378 selectorIndex = endIndex + 2;
379 // Remove leading whitespace
380 if (tokens.length === 0) {
381 stripWhitespace(0);
382 }
383 break;
384 }
385 var namespace = null;
386 var name_3 = void 0;
387 if (firstChar === 42 /* Asterisk */) {
388 selectorIndex += 1;
389 name_3 = "*";
390 }
391 else if (firstChar === 124 /* Pipe */) {
392 name_3 = "";
393 if (selector.charCodeAt(selectorIndex + 1) === 124 /* Pipe */) {
394 addTraversal(types_1.SelectorType.ColumnCombinator);
395 stripWhitespace(2);
396 break;
397 }
398 }
399 else if (reName.test(selector.slice(selectorIndex))) {
400 name_3 = getName(0);
401 }
402 else {
403 break loop;
404 }
405 if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */ &&
406 selector.charCodeAt(selectorIndex + 1) !== 124 /* Pipe */) {
407 namespace = name_3;
408 if (selector.charCodeAt(selectorIndex + 1) ===
409 42 /* Asterisk */) {
410 name_3 = "*";
411 selectorIndex += 2;
412 }
413 else {
414 name_3 = getName(1);
415 }
416 }
417 tokens.push(name_3 === "*"
418 ? { type: types_1.SelectorType.Universal, namespace: namespace }
419 : { type: types_1.SelectorType.Tag, name: name_3, namespace: namespace });
420 }
421 }
422 }
423 finalizeSubselector();
424 return selectorIndex;
425}
Note: See TracBrowser for help on using the repository browser.