@acemir/cssom 0.9.2 → 0.9.3
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/build/CSSOM.js +31 -20
- package/lib/parse.js +31 -20
- package/package.json +1 -1
package/build/CSSOM.js
CHANGED
|
@@ -1816,7 +1816,7 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
1816
1816
|
*
|
|
1817
1817
|
* @type {RegExp}
|
|
1818
1818
|
*/
|
|
1819
|
-
var basicSelectorRegExp = /^([a-zA-Z][a-zA-Z0-9_-]*|\*|#[a-zA-Z0-9_-]+|\.[a-zA-Z0-9_-]+|\[[^\[\]]
|
|
1819
|
+
var basicSelectorRegExp = /^([a-zA-Z][a-zA-Z0-9_-]*|\*|#[a-zA-Z0-9_-]+|\.[a-zA-Z0-9_-]+|\[[^\[\]]*(?:\s+[iI])?\]|::?[a-zA-Z0-9_-]+(?:\([^\(\)]*\))?|&|\s*[>+~]\s*|\s+)+$/;
|
|
1820
1820
|
|
|
1821
1821
|
/**
|
|
1822
1822
|
* Regular expression to match CSS pseudo-classes with arguments.
|
|
@@ -1834,7 +1834,7 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
1834
1834
|
* - Group 2: "2n+1"
|
|
1835
1835
|
* @type {RegExp}
|
|
1836
1836
|
*/
|
|
1837
|
-
var globalPseudoClassRegExp = /:([a-zA-Z-]+)\(([^)]
|
|
1837
|
+
var globalPseudoClassRegExp = /:([a-zA-Z-]+)\(([^)]*?(?:\s+[iI])?)\)/g;
|
|
1838
1838
|
|
|
1839
1839
|
/**
|
|
1840
1840
|
* Parses a CSS selector string and splits it into parts, handling nested parentheses.
|
|
@@ -1846,30 +1846,42 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
1846
1846
|
* @param {string} selector - The CSS selector string to parse.
|
|
1847
1847
|
* @returns {string[]} An array of selector parts, split by top-level commas, with whitespace trimmed.
|
|
1848
1848
|
*/
|
|
1849
|
-
function
|
|
1849
|
+
function parseAndSplitNestedSelectors(selector) {
|
|
1850
1850
|
var depth = 0;
|
|
1851
1851
|
var buffer = "";
|
|
1852
1852
|
var parts = [];
|
|
1853
|
+
var inSingleQuote = false;
|
|
1854
|
+
var inDoubleQuote = false;
|
|
1853
1855
|
var i, char;
|
|
1854
1856
|
|
|
1855
1857
|
for (i = 0; i < selector.length; i++) {
|
|
1856
1858
|
char = selector.charAt(i);
|
|
1857
1859
|
|
|
1858
|
-
if (char === '
|
|
1859
|
-
|
|
1860
|
+
if (char === "'" && !inDoubleQuote) {
|
|
1861
|
+
inSingleQuote = !inSingleQuote;
|
|
1860
1862
|
buffer += char;
|
|
1861
|
-
} else if (char === '
|
|
1862
|
-
|
|
1863
|
+
} else if (char === '"' && !inSingleQuote) {
|
|
1864
|
+
inDoubleQuote = !inDoubleQuote;
|
|
1863
1865
|
buffer += char;
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
+
} else if (!inSingleQuote && !inDoubleQuote) {
|
|
1867
|
+
if (char === '(') {
|
|
1868
|
+
depth++;
|
|
1869
|
+
buffer += char;
|
|
1870
|
+
} else if (char === ')') {
|
|
1871
|
+
depth--;
|
|
1872
|
+
buffer += char;
|
|
1873
|
+
if (depth === 0) {
|
|
1874
|
+
parts.push(buffer.replace(/^\s+|\s+$/g, ""));
|
|
1875
|
+
buffer = "";
|
|
1876
|
+
}
|
|
1877
|
+
} else if (char === ',' && depth === 0) {
|
|
1878
|
+
if (buffer.replace(/^\s+|\s+$/g, "")) {
|
|
1879
|
+
parts.push(buffer.replace(/^\s+|\s+$/g, ""));
|
|
1880
|
+
}
|
|
1866
1881
|
buffer = "";
|
|
1882
|
+
} else {
|
|
1883
|
+
buffer += char;
|
|
1867
1884
|
}
|
|
1868
|
-
} else if (char === ',' && depth === 0) {
|
|
1869
|
-
if (buffer.replace(/^\s+|\s+$/g, "")) {
|
|
1870
|
-
parts.push(buffer.replace(/^\s+|\s+$/g, ""));
|
|
1871
|
-
}
|
|
1872
|
-
buffer = "";
|
|
1873
1885
|
} else {
|
|
1874
1886
|
buffer += char;
|
|
1875
1887
|
}
|
|
@@ -1908,7 +1920,7 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
1908
1920
|
while ((match = pseudoClassRegExp.exec(selector)) !== null) {
|
|
1909
1921
|
var pseudoClass = match[1];
|
|
1910
1922
|
if (selectorListPseudoClasses.hasOwnProperty(pseudoClass)) {
|
|
1911
|
-
nestedSelectors =
|
|
1923
|
+
nestedSelectors = parseAndSplitNestedSelectors(match[2]);
|
|
1912
1924
|
// Validate each nested selector
|
|
1913
1925
|
for (i = 0; i < nestedSelectors.length; i++) {
|
|
1914
1926
|
if (!validateSelector(nestedSelectors[i])) {
|
|
@@ -1931,9 +1943,10 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
1931
1943
|
*/
|
|
1932
1944
|
function isValidSelectorText(selectorText) {
|
|
1933
1945
|
// Split selectorText by commas and validate each part
|
|
1934
|
-
var selectors = selectorText
|
|
1946
|
+
var selectors = parseAndSplitNestedSelectors(selectorText);
|
|
1935
1947
|
for (var i = 0; i < selectors.length; i++) {
|
|
1936
|
-
|
|
1948
|
+
var processedSelectors = selectors[i].replace(/^\s+|\s+$/g, "");
|
|
1949
|
+
if (!validateSelector(processedSelectors)) {
|
|
1937
1950
|
return false;
|
|
1938
1951
|
}
|
|
1939
1952
|
}
|
|
@@ -2159,7 +2172,6 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
2159
2172
|
}
|
|
2160
2173
|
|
|
2161
2174
|
currentScope = parentRule = styleRule;
|
|
2162
|
-
console.log('sel out', buffer);
|
|
2163
2175
|
styleRule.selectorText = buffer.trim();
|
|
2164
2176
|
styleRule.style.__starts = i;
|
|
2165
2177
|
styleRule.parentStyleSheet = styleSheet;
|
|
@@ -2289,9 +2301,8 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
2289
2301
|
}
|
|
2290
2302
|
|
|
2291
2303
|
styleRule = new CSSOM.CSSStyleRule();
|
|
2292
|
-
console.log('sel in', buffer);
|
|
2293
2304
|
// In a nested selector, ensure each selector contains '&' at the beginning, except for selectors that already have '&' somewhere
|
|
2294
|
-
styleRule.selectorText =
|
|
2305
|
+
styleRule.selectorText = parseAndSplitNestedSelectors(buffer.trim()).map(function(sel) {
|
|
2295
2306
|
return sel.indexOf('&') === -1 ? '& ' + sel : sel;
|
|
2296
2307
|
}).join(', ');
|
|
2297
2308
|
styleRule.style.__starts = i - buffer.length;
|
package/lib/parse.js
CHANGED
|
@@ -249,7 +249,7 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
249
249
|
*
|
|
250
250
|
* @type {RegExp}
|
|
251
251
|
*/
|
|
252
|
-
var basicSelectorRegExp = /^([a-zA-Z][a-zA-Z0-9_-]*|\*|#[a-zA-Z0-9_-]+|\.[a-zA-Z0-9_-]+|\[[^\[\]]
|
|
252
|
+
var basicSelectorRegExp = /^([a-zA-Z][a-zA-Z0-9_-]*|\*|#[a-zA-Z0-9_-]+|\.[a-zA-Z0-9_-]+|\[[^\[\]]*(?:\s+[iI])?\]|::?[a-zA-Z0-9_-]+(?:\([^\(\)]*\))?|&|\s*[>+~]\s*|\s+)+$/;
|
|
253
253
|
|
|
254
254
|
/**
|
|
255
255
|
* Regular expression to match CSS pseudo-classes with arguments.
|
|
@@ -267,7 +267,7 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
267
267
|
* - Group 2: "2n+1"
|
|
268
268
|
* @type {RegExp}
|
|
269
269
|
*/
|
|
270
|
-
var globalPseudoClassRegExp = /:([a-zA-Z-]+)\(([^)]
|
|
270
|
+
var globalPseudoClassRegExp = /:([a-zA-Z-]+)\(([^)]*?(?:\s+[iI])?)\)/g;
|
|
271
271
|
|
|
272
272
|
/**
|
|
273
273
|
* Parses a CSS selector string and splits it into parts, handling nested parentheses.
|
|
@@ -279,30 +279,42 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
279
279
|
* @param {string} selector - The CSS selector string to parse.
|
|
280
280
|
* @returns {string[]} An array of selector parts, split by top-level commas, with whitespace trimmed.
|
|
281
281
|
*/
|
|
282
|
-
function
|
|
282
|
+
function parseAndSplitNestedSelectors(selector) {
|
|
283
283
|
var depth = 0;
|
|
284
284
|
var buffer = "";
|
|
285
285
|
var parts = [];
|
|
286
|
+
var inSingleQuote = false;
|
|
287
|
+
var inDoubleQuote = false;
|
|
286
288
|
var i, char;
|
|
287
289
|
|
|
288
290
|
for (i = 0; i < selector.length; i++) {
|
|
289
291
|
char = selector.charAt(i);
|
|
290
292
|
|
|
291
|
-
if (char === '
|
|
292
|
-
|
|
293
|
+
if (char === "'" && !inDoubleQuote) {
|
|
294
|
+
inSingleQuote = !inSingleQuote;
|
|
293
295
|
buffer += char;
|
|
294
|
-
} else if (char === '
|
|
295
|
-
|
|
296
|
+
} else if (char === '"' && !inSingleQuote) {
|
|
297
|
+
inDoubleQuote = !inDoubleQuote;
|
|
296
298
|
buffer += char;
|
|
297
|
-
|
|
298
|
-
|
|
299
|
+
} else if (!inSingleQuote && !inDoubleQuote) {
|
|
300
|
+
if (char === '(') {
|
|
301
|
+
depth++;
|
|
302
|
+
buffer += char;
|
|
303
|
+
} else if (char === ')') {
|
|
304
|
+
depth--;
|
|
305
|
+
buffer += char;
|
|
306
|
+
if (depth === 0) {
|
|
307
|
+
parts.push(buffer.replace(/^\s+|\s+$/g, ""));
|
|
308
|
+
buffer = "";
|
|
309
|
+
}
|
|
310
|
+
} else if (char === ',' && depth === 0) {
|
|
311
|
+
if (buffer.replace(/^\s+|\s+$/g, "")) {
|
|
312
|
+
parts.push(buffer.replace(/^\s+|\s+$/g, ""));
|
|
313
|
+
}
|
|
299
314
|
buffer = "";
|
|
315
|
+
} else {
|
|
316
|
+
buffer += char;
|
|
300
317
|
}
|
|
301
|
-
} else if (char === ',' && depth === 0) {
|
|
302
|
-
if (buffer.replace(/^\s+|\s+$/g, "")) {
|
|
303
|
-
parts.push(buffer.replace(/^\s+|\s+$/g, ""));
|
|
304
|
-
}
|
|
305
|
-
buffer = "";
|
|
306
318
|
} else {
|
|
307
319
|
buffer += char;
|
|
308
320
|
}
|
|
@@ -341,7 +353,7 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
341
353
|
while ((match = pseudoClassRegExp.exec(selector)) !== null) {
|
|
342
354
|
var pseudoClass = match[1];
|
|
343
355
|
if (selectorListPseudoClasses.hasOwnProperty(pseudoClass)) {
|
|
344
|
-
nestedSelectors =
|
|
356
|
+
nestedSelectors = parseAndSplitNestedSelectors(match[2]);
|
|
345
357
|
// Validate each nested selector
|
|
346
358
|
for (i = 0; i < nestedSelectors.length; i++) {
|
|
347
359
|
if (!validateSelector(nestedSelectors[i])) {
|
|
@@ -364,9 +376,10 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
364
376
|
*/
|
|
365
377
|
function isValidSelectorText(selectorText) {
|
|
366
378
|
// Split selectorText by commas and validate each part
|
|
367
|
-
var selectors = selectorText
|
|
379
|
+
var selectors = parseAndSplitNestedSelectors(selectorText);
|
|
368
380
|
for (var i = 0; i < selectors.length; i++) {
|
|
369
|
-
|
|
381
|
+
var processedSelectors = selectors[i].replace(/^\s+|\s+$/g, "");
|
|
382
|
+
if (!validateSelector(processedSelectors)) {
|
|
370
383
|
return false;
|
|
371
384
|
}
|
|
372
385
|
}
|
|
@@ -592,7 +605,6 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
592
605
|
}
|
|
593
606
|
|
|
594
607
|
currentScope = parentRule = styleRule;
|
|
595
|
-
console.log('sel out', buffer);
|
|
596
608
|
styleRule.selectorText = buffer.trim();
|
|
597
609
|
styleRule.style.__starts = i;
|
|
598
610
|
styleRule.parentStyleSheet = styleSheet;
|
|
@@ -722,9 +734,8 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
722
734
|
}
|
|
723
735
|
|
|
724
736
|
styleRule = new CSSOM.CSSStyleRule();
|
|
725
|
-
console.log('sel in', buffer);
|
|
726
737
|
// In a nested selector, ensure each selector contains '&' at the beginning, except for selectors that already have '&' somewhere
|
|
727
|
-
styleRule.selectorText =
|
|
738
|
+
styleRule.selectorText = parseAndSplitNestedSelectors(buffer.trim()).map(function(sel) {
|
|
728
739
|
return sel.indexOf('&') === -1 ? '& ' + sel : sel;
|
|
729
740
|
}).join(', ');
|
|
730
741
|
styleRule.style.__starts = i - buffer.length;
|