@acemir/cssom 0.9.17 → 0.9.18
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 +174 -49
- package/lib/CSSFontFaceRule.js +1 -1
- package/lib/CSSGroupingRule.js +43 -5
- package/lib/CSSImportRule.js +5 -5
- package/lib/CSSKeyframeRule.js +1 -1
- package/lib/CSSStyleRule.js +1 -1
- package/lib/CSSStyleSheet.js +99 -11
- package/lib/errorUtils.js +10 -21
- package/lib/parse.js +14 -4
- package/package.json +1 -1
package/build/CSSOM.js
CHANGED
|
@@ -5,27 +5,27 @@ var CSSOM = {};
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Gets the appropriate error constructor from the global object context.
|
|
8
|
-
* Tries to find the error constructor from parentStyleSheet.
|
|
9
|
-
* then from
|
|
8
|
+
* Tries to find the error constructor from parentStyleSheet.__globalObject,
|
|
9
|
+
* then from __globalObject, then falls back to the native constructor.
|
|
10
10
|
*
|
|
11
11
|
* @param {Object} context - The CSSOM object (rule, stylesheet, etc.)
|
|
12
12
|
* @param {string} errorType - The error type ('TypeError', 'RangeError', 'DOMException', etc.)
|
|
13
13
|
* @return {Function} The error constructor
|
|
14
14
|
*/
|
|
15
15
|
function getErrorConstructor(context, errorType) {
|
|
16
|
-
// Try parentStyleSheet.
|
|
17
|
-
if (context.parentStyleSheet && context.parentStyleSheet.
|
|
18
|
-
return context.parentStyleSheet.
|
|
16
|
+
// Try parentStyleSheet.__globalObject first
|
|
17
|
+
if (context.parentStyleSheet && context.parentStyleSheet.__globalObject && context.parentStyleSheet.__globalObject[errorType]) {
|
|
18
|
+
return context.parentStyleSheet.__globalObject[errorType];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// Try __parentStyleSheet (alternative naming)
|
|
22
|
-
if (context.__parentStyleSheet && context.__parentStyleSheet.
|
|
23
|
-
return context.__parentStyleSheet.
|
|
22
|
+
if (context.__parentStyleSheet && context.__parentStyleSheet.__globalObject && context.__parentStyleSheet.__globalObject[errorType]) {
|
|
23
|
+
return context.__parentStyleSheet.__globalObject[errorType];
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// Try
|
|
27
|
-
if (context.
|
|
28
|
-
return context.
|
|
26
|
+
// Try __globalObject on the context itself
|
|
27
|
+
if (context.__globalObject && context.__globalObject[errorType]) {
|
|
28
|
+
return context.__globalObject[errorType];
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// Fall back to native constructor
|
|
@@ -66,16 +66,6 @@ function throwMissingArguments(context, methodName, objectName, required, provid
|
|
|
66
66
|
throwError(context, 'TypeError', message);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
/**
|
|
70
|
-
* Throws a RangeError for index out of bounds.
|
|
71
|
-
*
|
|
72
|
-
* @param {Object} context - The CSSOM object
|
|
73
|
-
* @param {string} [message] - Optional custom message, defaults to 'INDEX_SIZE_ERR'
|
|
74
|
-
*/
|
|
75
|
-
function throwIndexSizeError(context, message) {
|
|
76
|
-
throwError(context, 'RangeError', message || 'INDEX_SIZE_ERR');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
69
|
/**
|
|
80
70
|
* Throws a DOMException for parse errors.
|
|
81
71
|
*
|
|
@@ -111,7 +101,6 @@ var errorUtils = {
|
|
|
111
101
|
getErrorConstructor: getErrorConstructor,
|
|
112
102
|
throwError: throwError,
|
|
113
103
|
throwMissingArguments: throwMissingArguments,
|
|
114
|
-
throwIndexSizeError: throwIndexSizeError,
|
|
115
104
|
throwParseError: throwParseError,
|
|
116
105
|
throwIndexError: throwIndexError
|
|
117
106
|
};
|
|
@@ -422,10 +411,41 @@ CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
|
|
|
422
411
|
* @return {number} The index within the grouping rule's collection of the newly inserted rule.
|
|
423
412
|
*/
|
|
424
413
|
CSSOM.CSSGroupingRule.prototype.insertRule = function insertRule(rule, index) {
|
|
425
|
-
if (
|
|
426
|
-
errorUtils.
|
|
414
|
+
if (rule === undefined && index === undefined) {
|
|
415
|
+
errorUtils.throwMissingArguments(this, 'insertRule', this.constructor.name);
|
|
416
|
+
}
|
|
417
|
+
if (index === void 0) {
|
|
418
|
+
index = 0;
|
|
419
|
+
}
|
|
420
|
+
index = Number(index);
|
|
421
|
+
if (index < 0) {
|
|
422
|
+
index = 4294967296 + index;
|
|
423
|
+
}
|
|
424
|
+
if (index > this.cssRules.length) {
|
|
425
|
+
errorUtils.throwIndexError(this, 'insertRule', this.constructor.name, index, this.cssRules.length);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
var ruleToParse = String(rule);
|
|
429
|
+
var parsedSheet = CSSOM.parse(ruleToParse);
|
|
430
|
+
if (parsedSheet.cssRules.length !== 1) {
|
|
431
|
+
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
|
427
432
|
}
|
|
428
|
-
var cssRule =
|
|
433
|
+
var cssRule = parsedSheet.cssRules[0];
|
|
434
|
+
|
|
435
|
+
// Check for rules that cannot be inserted inside a CSSGroupingRule
|
|
436
|
+
if (cssRule.constructor.name === 'CSSImportRule' || cssRule.constructor.name === 'CSSNamespaceRule') {
|
|
437
|
+
var ruleKeyword = cssRule.constructor.name === 'CSSImportRule' ? '@import' : '@namespace';
|
|
438
|
+
errorUtils.throwError(this, 'DOMException',
|
|
439
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': " +
|
|
440
|
+
"'" + ruleKeyword + "' rules cannot be inserted inside a group rule.",
|
|
441
|
+
'HierarchyRequestError');
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Check for CSSLayerStatementRule (@layer statement rules)
|
|
445
|
+
if (cssRule.constructor.name === 'CSSLayerStatementRule') {
|
|
446
|
+
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
|
447
|
+
}
|
|
448
|
+
|
|
429
449
|
cssRule.__parentRule = this;
|
|
430
450
|
this.cssRules.splice(index, 0, cssRule);
|
|
431
451
|
return index;
|
|
@@ -444,8 +464,15 @@ CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
|
|
|
444
464
|
* @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-deleterule
|
|
445
465
|
*/
|
|
446
466
|
CSSOM.CSSGroupingRule.prototype.deleteRule = function deleteRule(index) {
|
|
447
|
-
if (index
|
|
448
|
-
errorUtils.
|
|
467
|
+
if (index === undefined) {
|
|
468
|
+
errorUtils.throwMissingArguments(this, 'deleteRule', this.constructor.name);
|
|
469
|
+
}
|
|
470
|
+
index = Number(index);
|
|
471
|
+
if (index < 0) {
|
|
472
|
+
index = 4294967296 + index;
|
|
473
|
+
}
|
|
474
|
+
if (index >= this.cssRules.length) {
|
|
475
|
+
errorUtils.throwIndexError(this, 'deleteRule', this.constructor.name, index, this.cssRules.length);
|
|
449
476
|
}
|
|
450
477
|
this.cssRules.splice(index, 1)[0].__parentRule = null;
|
|
451
478
|
};
|
|
@@ -542,7 +569,7 @@ Object.defineProperty(CSSOM.CSSStyleRule.prototype, "cssText", {
|
|
|
542
569
|
valuesArr.push(this.cssRules.map(function(rule){ return rule.cssText }).join("\n "));
|
|
543
570
|
values = valuesArr.join("\n ") + "\n}"
|
|
544
571
|
} else {
|
|
545
|
-
values = " { " + this.style.cssText + " }";
|
|
572
|
+
values = " {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
|
546
573
|
}
|
|
547
574
|
text = this.selectorText + values;
|
|
548
575
|
} else {
|
|
@@ -899,7 +926,7 @@ CSSOM.CSSImportRule.prototype.type = 3;
|
|
|
899
926
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
|
|
900
927
|
get: function() {
|
|
901
928
|
var mediaText = this.media.mediaText;
|
|
902
|
-
return "@import url(" + this.href + ")" + (this.layerName !== null ? " layer" + (this.layerName && "(" + this.layerName + ")") : "" ) + (this.supportsText ? " supports(" + this.supportsText + ")" : "" ) + (mediaText ? " " + mediaText : "") + ";";
|
|
929
|
+
return "@import url(\"" + this.href + "\")" + (this.layerName !== null ? " layer" + (this.layerName && "(" + this.layerName + ")") : "" ) + (this.supportsText ? " supports(" + this.supportsText + ")" : "" ) + (mediaText ? " " + mediaText : "") + ";";
|
|
903
930
|
},
|
|
904
931
|
set: function(cssText) {
|
|
905
932
|
var i = 0;
|
|
@@ -917,7 +944,7 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
|
|
|
917
944
|
var index;
|
|
918
945
|
|
|
919
946
|
var layerRegExp = /layer\(([^)]*)\)/;
|
|
920
|
-
var layerRuleNameRegExp = /^(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)$/;
|
|
947
|
+
var layerRuleNameRegExp = /^(-?[_a-zA-Z]+(\.[_a-zA-Z]+)*[_a-zA-Z0-9-]*)$/;
|
|
921
948
|
var supportsRegExp = /supports\(([^)]+)\)/;
|
|
922
949
|
var doubleOrMoreSpacesRegExp = /\s{2,}/g;
|
|
923
950
|
|
|
@@ -1000,12 +1027,12 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
|
|
|
1000
1027
|
|
|
1001
1028
|
if (layerMatch) {
|
|
1002
1029
|
var layerName = layerMatch[1].trim();
|
|
1003
|
-
bufferTrimmed = bufferTrimmed.replace(layerRegExp, '')
|
|
1004
|
-
.replace(doubleOrMoreSpacesRegExp, ' ') // Replace double or more spaces with single space
|
|
1005
|
-
.trim();
|
|
1006
1030
|
|
|
1007
1031
|
if (layerName.match(layerRuleNameRegExp) !== null) {
|
|
1008
1032
|
this.layerName = layerMatch[1].trim();
|
|
1033
|
+
bufferTrimmed = bufferTrimmed.replace(layerRegExp, '')
|
|
1034
|
+
.replace(doubleOrMoreSpacesRegExp, ' ') // Replace double or more spaces with single space
|
|
1035
|
+
.trim();
|
|
1009
1036
|
} else {
|
|
1010
1037
|
// REVIEW: In the browser, an empty layer() is not processed as a unamed layer
|
|
1011
1038
|
// and treats the rest of the string as mediaText, ignoring the parse of supports()
|
|
@@ -1156,7 +1183,7 @@ Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "style", {
|
|
|
1156
1183
|
// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSFontFaceRule.cpp
|
|
1157
1184
|
Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "cssText", {
|
|
1158
1185
|
get: function() {
|
|
1159
|
-
return "@font-face { " + this.style.cssText + " }";
|
|
1186
|
+
return "@font-face {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
|
1160
1187
|
}
|
|
1161
1188
|
});
|
|
1162
1189
|
|
|
@@ -1279,24 +1306,112 @@ CSSOM.CSSStyleSheet.prototype.constructor = CSSOM.CSSStyleSheet;
|
|
|
1279
1306
|
*/
|
|
1280
1307
|
CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) {
|
|
1281
1308
|
if (rule === undefined && index === undefined) {
|
|
1282
|
-
errorUtils.throwMissingArguments(this, 'insertRule',
|
|
1309
|
+
errorUtils.throwMissingArguments(this, 'insertRule', this.constructor.name);
|
|
1283
1310
|
}
|
|
1284
1311
|
if (index === void 0) {
|
|
1285
1312
|
index = 0;
|
|
1286
1313
|
}
|
|
1287
|
-
|
|
1288
|
-
|
|
1314
|
+
index = Number(index);
|
|
1315
|
+
if (index < 0) {
|
|
1316
|
+
index = 4294967296 + index;
|
|
1317
|
+
}
|
|
1318
|
+
if (index > this.cssRules.length) {
|
|
1319
|
+
errorUtils.throwIndexError(this, 'insertRule', this.constructor.name, index, this.cssRules.length);
|
|
1289
1320
|
}
|
|
1321
|
+
|
|
1290
1322
|
var ruleToParse = String(rule);
|
|
1291
1323
|
var parsedSheet = CSSOM.parse(ruleToParse);
|
|
1292
1324
|
if (parsedSheet.cssRules.length !== 1) {
|
|
1293
|
-
|
|
1294
|
-
if (ruleToParse.trimStart().startsWith('@namespace')) {
|
|
1295
|
-
domExceptionName = "InvalidStateError";
|
|
1296
|
-
}
|
|
1297
|
-
errorUtils.throwParseError(this, 'insertRule', 'CSSStyleSheet', ruleToParse, domExceptionName);
|
|
1325
|
+
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
|
1298
1326
|
}
|
|
1299
1327
|
var cssRule = parsedSheet.cssRules[0];
|
|
1328
|
+
|
|
1329
|
+
// Helper function to find the last index of a specific rule constructor
|
|
1330
|
+
function findLastIndexOfConstructor(rules, constructorName) {
|
|
1331
|
+
for (var i = rules.length - 1; i >= 0; i--) {
|
|
1332
|
+
if (rules[i].constructor.name === constructorName) {
|
|
1333
|
+
return i;
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
return -1;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
// Helper function to find the first index of a rule that's NOT of specified constructors
|
|
1340
|
+
function findFirstNonConstructorIndex(rules, constructorNames) {
|
|
1341
|
+
for (var i = 0; i < rules.length; i++) {
|
|
1342
|
+
if (constructorNames.indexOf(rules[i].constructor.name) === -1) {
|
|
1343
|
+
return i;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
return rules.length;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
// Validate rule ordering based on CSS specification
|
|
1350
|
+
if (cssRule.constructor.name === 'CSSImportRule') {
|
|
1351
|
+
// @import rules cannot be inserted after @layer rules that already exist
|
|
1352
|
+
// They can only be inserted at the beginning or after other @import rules
|
|
1353
|
+
var firstLayerIndex = findFirstNonConstructorIndex(this.cssRules, ['CSSImportRule']);
|
|
1354
|
+
if (firstLayerIndex < this.cssRules.length && this.cssRules[firstLayerIndex].constructor.name === 'CSSLayerStatementRule' && index > firstLayerIndex) {
|
|
1355
|
+
errorUtils.throwError(this, 'DOMException',
|
|
1356
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
1357
|
+
'HierarchyRequestError');
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
// Also cannot insert after @namespace or other rules
|
|
1361
|
+
var firstNonImportIndex = findFirstNonConstructorIndex(this.cssRules, ['CSSImportRule']);
|
|
1362
|
+
if (index > firstNonImportIndex && firstNonImportIndex < this.cssRules.length &&
|
|
1363
|
+
this.cssRules[firstNonImportIndex].constructor.name !== 'CSSLayerStatementRule') {
|
|
1364
|
+
errorUtils.throwError(this, 'DOMException',
|
|
1365
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
1366
|
+
'HierarchyRequestError');
|
|
1367
|
+
}
|
|
1368
|
+
} else if (cssRule.constructor.name === 'CSSNamespaceRule') {
|
|
1369
|
+
// @namespace rules can come after @layer and @import, but before any other rules
|
|
1370
|
+
// They cannot come before @import rules
|
|
1371
|
+
var firstImportIndex = -1;
|
|
1372
|
+
for (var i = 0; i < this.cssRules.length; i++) {
|
|
1373
|
+
if (this.cssRules[i].constructor.name === 'CSSImportRule') {
|
|
1374
|
+
firstImportIndex = i;
|
|
1375
|
+
break;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
var firstNonImportNamespaceIndex = findFirstNonConstructorIndex(this.cssRules, [
|
|
1379
|
+
'CSSLayerStatementRule',
|
|
1380
|
+
'CSSImportRule',
|
|
1381
|
+
'CSSNamespaceRule'
|
|
1382
|
+
]);
|
|
1383
|
+
|
|
1384
|
+
// Cannot insert before @import rules
|
|
1385
|
+
if (firstImportIndex !== -1 && index <= firstImportIndex) {
|
|
1386
|
+
errorUtils.throwError(this, 'DOMException',
|
|
1387
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
1388
|
+
'HierarchyRequestError');
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
// Cannot insert after other types of rules
|
|
1392
|
+
if (index > firstNonImportNamespaceIndex) {
|
|
1393
|
+
errorUtils.throwError(this, 'DOMException',
|
|
1394
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
1395
|
+
'HierarchyRequestError');
|
|
1396
|
+
}
|
|
1397
|
+
} else if (cssRule.constructor.name === 'CSSLayerStatementRule') {
|
|
1398
|
+
// @layer statement rules can be inserted anywhere before @import and @namespace
|
|
1399
|
+
// No additional restrictions beyond what's already handled
|
|
1400
|
+
} else {
|
|
1401
|
+
// Any other rule cannot be inserted before @import and @namespace
|
|
1402
|
+
var firstNonSpecialRuleIndex = findFirstNonConstructorIndex(this.cssRules, [
|
|
1403
|
+
'CSSLayerStatementRule',
|
|
1404
|
+
'CSSImportRule',
|
|
1405
|
+
'CSSNamespaceRule'
|
|
1406
|
+
]);
|
|
1407
|
+
|
|
1408
|
+
if (index < firstNonSpecialRuleIndex) {
|
|
1409
|
+
errorUtils.throwError(this, 'DOMException',
|
|
1410
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
1411
|
+
'HierarchyRequestError');
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1300
1415
|
cssRule.__parentStyleSheet = this;
|
|
1301
1416
|
this.cssRules.splice(index, 0, cssRule);
|
|
1302
1417
|
return index;
|
|
@@ -1318,21 +1433,21 @@ CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) {
|
|
|
1318
1433
|
*/
|
|
1319
1434
|
CSSOM.CSSStyleSheet.prototype.deleteRule = function(index) {
|
|
1320
1435
|
if (index === undefined) {
|
|
1321
|
-
errorUtils.throwMissingArguments(this, 'deleteRule',
|
|
1436
|
+
errorUtils.throwMissingArguments(this, 'deleteRule', this.constructor.name);
|
|
1322
1437
|
}
|
|
1323
1438
|
index = Number(index);
|
|
1324
1439
|
if (index < 0) {
|
|
1325
1440
|
index = 4294967296 + index;
|
|
1326
1441
|
}
|
|
1327
1442
|
if (index >= this.cssRules.length) {
|
|
1328
|
-
errorUtils.throwIndexError(this, 'deleteRule',
|
|
1443
|
+
errorUtils.throwIndexError(this, 'deleteRule', this.constructor.name, index, this.cssRules.length);
|
|
1329
1444
|
}
|
|
1330
1445
|
if (this.cssRules[index] && this.cssRules[index].constructor.name == "CSSNamespaceRule") {
|
|
1331
1446
|
var shouldContinue = this.cssRules.every(function (rule) {
|
|
1332
1447
|
return ['CSSImportRule','CSSLayerStatementRule','CSSNamespaceRule'].indexOf(rule.constructor.name) !== -1
|
|
1333
1448
|
});
|
|
1334
1449
|
if (!shouldContinue) {
|
|
1335
|
-
errorUtils.throwError(this, 'DOMException', "Failed to execute 'deleteRule' on '
|
|
1450
|
+
errorUtils.throwError(this, 'DOMException', "Failed to execute 'deleteRule' on '" + this.constructor.name + "': Failed to delete rule.", "InvalidStateError");
|
|
1336
1451
|
}
|
|
1337
1452
|
}
|
|
1338
1453
|
this.cssRules.splice(index, 1);
|
|
@@ -1616,7 +1731,7 @@ Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "style", {
|
|
|
1616
1731
|
// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframeRule.cpp
|
|
1617
1732
|
Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "cssText", {
|
|
1618
1733
|
get: function() {
|
|
1619
|
-
return this.keyText + " { " + this.style.cssText + " }";
|
|
1734
|
+
return this.keyText + " {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
|
1620
1735
|
}
|
|
1621
1736
|
});
|
|
1622
1737
|
|
|
@@ -2150,10 +2265,16 @@ Object.defineProperties(CSSOM.CSSLayerStatementRule.prototype, {
|
|
|
2150
2265
|
|
|
2151
2266
|
|
|
2152
2267
|
/**
|
|
2153
|
-
*
|
|
2268
|
+
* Parses a CSS string and returns a CSSOM.CSSStyleSheet object representing the parsed stylesheet.
|
|
2269
|
+
*
|
|
2270
|
+
* @param {string} token - The CSS string to parse.
|
|
2271
|
+
* @param {object} [opts] - Optional parsing options.
|
|
2272
|
+
* @param {object} [opts.globalObject] - An optional global object to attach to the stylesheet. Useful on jsdom webplatform tests.
|
|
2273
|
+
* @param {function|boolean} [errorHandler] - Optional error handler function or `true` to use `console.error`.
|
|
2274
|
+
* @returns {CSSOM.CSSStyleSheet} The parsed CSSStyleSheet object.
|
|
2154
2275
|
*/
|
|
2155
|
-
CSSOM.parse = function parse(token, errorHandler) {
|
|
2156
|
-
errorHandler = errorHandler ===
|
|
2276
|
+
CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
2277
|
+
errorHandler = errorHandler === true ? (console && console.error) : errorHandler;
|
|
2157
2278
|
|
|
2158
2279
|
var i = 0;
|
|
2159
2280
|
|
|
@@ -2195,6 +2316,10 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
2195
2316
|
|
|
2196
2317
|
var styleSheet = new CSSOM.CSSStyleSheet();
|
|
2197
2318
|
|
|
2319
|
+
if (opts && opts.globalObject) {
|
|
2320
|
+
styleSheet.__globalObject = opts.globalObject;
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2198
2323
|
// @type CSSStyleSheet|CSSMediaRule|CSSContainerRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule
|
|
2199
2324
|
var currentScope = styleSheet;
|
|
2200
2325
|
|
|
@@ -2892,7 +3017,7 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
2892
3017
|
i += "font-face".length;
|
|
2893
3018
|
fontFaceRule = new CSSOM.CSSFontFaceRule();
|
|
2894
3019
|
fontFaceRule.__starts = i;
|
|
2895
|
-
},
|
|
3020
|
+
}, true);
|
|
2896
3021
|
break;
|
|
2897
3022
|
} else {
|
|
2898
3023
|
atKeyframesRegExp.lastIndex = i;
|
package/lib/CSSFontFaceRule.js
CHANGED
|
@@ -45,7 +45,7 @@ Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "style", {
|
|
|
45
45
|
// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSFontFaceRule.cpp
|
|
46
46
|
Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "cssText", {
|
|
47
47
|
get: function() {
|
|
48
|
-
return "@font-face { " + this.style.cssText + " }";
|
|
48
|
+
return "@font-face {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
|
package/lib/CSSGroupingRule.js
CHANGED
|
@@ -37,10 +37,41 @@ CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
|
|
|
37
37
|
* @return {number} The index within the grouping rule's collection of the newly inserted rule.
|
|
38
38
|
*/
|
|
39
39
|
CSSOM.CSSGroupingRule.prototype.insertRule = function insertRule(rule, index) {
|
|
40
|
-
if (
|
|
41
|
-
errorUtils.
|
|
40
|
+
if (rule === undefined && index === undefined) {
|
|
41
|
+
errorUtils.throwMissingArguments(this, 'insertRule', this.constructor.name);
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
if (index === void 0) {
|
|
44
|
+
index = 0;
|
|
45
|
+
}
|
|
46
|
+
index = Number(index);
|
|
47
|
+
if (index < 0) {
|
|
48
|
+
index = 4294967296 + index;
|
|
49
|
+
}
|
|
50
|
+
if (index > this.cssRules.length) {
|
|
51
|
+
errorUtils.throwIndexError(this, 'insertRule', this.constructor.name, index, this.cssRules.length);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
var ruleToParse = String(rule);
|
|
55
|
+
var parsedSheet = CSSOM.parse(ruleToParse);
|
|
56
|
+
if (parsedSheet.cssRules.length !== 1) {
|
|
57
|
+
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
|
58
|
+
}
|
|
59
|
+
var cssRule = parsedSheet.cssRules[0];
|
|
60
|
+
|
|
61
|
+
// Check for rules that cannot be inserted inside a CSSGroupingRule
|
|
62
|
+
if (cssRule.constructor.name === 'CSSImportRule' || cssRule.constructor.name === 'CSSNamespaceRule') {
|
|
63
|
+
var ruleKeyword = cssRule.constructor.name === 'CSSImportRule' ? '@import' : '@namespace';
|
|
64
|
+
errorUtils.throwError(this, 'DOMException',
|
|
65
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': " +
|
|
66
|
+
"'" + ruleKeyword + "' rules cannot be inserted inside a group rule.",
|
|
67
|
+
'HierarchyRequestError');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check for CSSLayerStatementRule (@layer statement rules)
|
|
71
|
+
if (cssRule.constructor.name === 'CSSLayerStatementRule') {
|
|
72
|
+
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
|
73
|
+
}
|
|
74
|
+
|
|
44
75
|
cssRule.__parentRule = this;
|
|
45
76
|
this.cssRules.splice(index, 0, cssRule);
|
|
46
77
|
return index;
|
|
@@ -59,8 +90,15 @@ CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
|
|
|
59
90
|
* @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-deleterule
|
|
60
91
|
*/
|
|
61
92
|
CSSOM.CSSGroupingRule.prototype.deleteRule = function deleteRule(index) {
|
|
62
|
-
if (index
|
|
63
|
-
errorUtils.
|
|
93
|
+
if (index === undefined) {
|
|
94
|
+
errorUtils.throwMissingArguments(this, 'deleteRule', this.constructor.name);
|
|
95
|
+
}
|
|
96
|
+
index = Number(index);
|
|
97
|
+
if (index < 0) {
|
|
98
|
+
index = 4294967296 + index;
|
|
99
|
+
}
|
|
100
|
+
if (index >= this.cssRules.length) {
|
|
101
|
+
errorUtils.throwIndexError(this, 'deleteRule', this.constructor.name, index, this.cssRules.length);
|
|
64
102
|
}
|
|
65
103
|
this.cssRules.splice(index, 1)[0].__parentRule = null;
|
|
66
104
|
};
|
package/lib/CSSImportRule.js
CHANGED
|
@@ -28,7 +28,7 @@ CSSOM.CSSImportRule.prototype.type = 3;
|
|
|
28
28
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
|
|
29
29
|
get: function() {
|
|
30
30
|
var mediaText = this.media.mediaText;
|
|
31
|
-
return "@import url(" + this.href + ")" + (this.layerName !== null ? " layer" + (this.layerName && "(" + this.layerName + ")") : "" ) + (this.supportsText ? " supports(" + this.supportsText + ")" : "" ) + (mediaText ? " " + mediaText : "") + ";";
|
|
31
|
+
return "@import url(\"" + this.href + "\")" + (this.layerName !== null ? " layer" + (this.layerName && "(" + this.layerName + ")") : "" ) + (this.supportsText ? " supports(" + this.supportsText + ")" : "" ) + (mediaText ? " " + mediaText : "") + ";";
|
|
32
32
|
},
|
|
33
33
|
set: function(cssText) {
|
|
34
34
|
var i = 0;
|
|
@@ -46,7 +46,7 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
|
|
|
46
46
|
var index;
|
|
47
47
|
|
|
48
48
|
var layerRegExp = /layer\(([^)]*)\)/;
|
|
49
|
-
var layerRuleNameRegExp = /^(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)$/;
|
|
49
|
+
var layerRuleNameRegExp = /^(-?[_a-zA-Z]+(\.[_a-zA-Z]+)*[_a-zA-Z0-9-]*)$/;
|
|
50
50
|
var supportsRegExp = /supports\(([^)]+)\)/;
|
|
51
51
|
var doubleOrMoreSpacesRegExp = /\s{2,}/g;
|
|
52
52
|
|
|
@@ -129,12 +129,12 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
|
|
|
129
129
|
|
|
130
130
|
if (layerMatch) {
|
|
131
131
|
var layerName = layerMatch[1].trim();
|
|
132
|
-
bufferTrimmed = bufferTrimmed.replace(layerRegExp, '')
|
|
133
|
-
.replace(doubleOrMoreSpacesRegExp, ' ') // Replace double or more spaces with single space
|
|
134
|
-
.trim();
|
|
135
132
|
|
|
136
133
|
if (layerName.match(layerRuleNameRegExp) !== null) {
|
|
137
134
|
this.layerName = layerMatch[1].trim();
|
|
135
|
+
bufferTrimmed = bufferTrimmed.replace(layerRegExp, '')
|
|
136
|
+
.replace(doubleOrMoreSpacesRegExp, ' ') // Replace double or more spaces with single space
|
|
137
|
+
.trim();
|
|
138
138
|
} else {
|
|
139
139
|
// REVIEW: In the browser, an empty layer() is not processed as a unamed layer
|
|
140
140
|
// and treats the rest of the string as mediaText, ignoring the parse of supports()
|
package/lib/CSSKeyframeRule.js
CHANGED
|
@@ -46,7 +46,7 @@ Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "style", {
|
|
|
46
46
|
// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframeRule.cpp
|
|
47
47
|
Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "cssText", {
|
|
48
48
|
get: function() {
|
|
49
|
-
return this.keyText + " { " + this.style.cssText + " }";
|
|
49
|
+
return this.keyText + " {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
|
50
50
|
}
|
|
51
51
|
});
|
|
52
52
|
|
package/lib/CSSStyleRule.js
CHANGED
|
@@ -66,7 +66,7 @@ Object.defineProperty(CSSOM.CSSStyleRule.prototype, "cssText", {
|
|
|
66
66
|
valuesArr.push(this.cssRules.map(function(rule){ return rule.cssText }).join("\n "));
|
|
67
67
|
values = valuesArr.join("\n ") + "\n}"
|
|
68
68
|
} else {
|
|
69
|
-
values = " { " + this.style.cssText + " }";
|
|
69
|
+
values = " {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
|
70
70
|
}
|
|
71
71
|
text = this.selectorText + values;
|
|
72
72
|
} else {
|
package/lib/CSSStyleSheet.js
CHANGED
|
@@ -39,24 +39,112 @@ CSSOM.CSSStyleSheet.prototype.constructor = CSSOM.CSSStyleSheet;
|
|
|
39
39
|
*/
|
|
40
40
|
CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) {
|
|
41
41
|
if (rule === undefined && index === undefined) {
|
|
42
|
-
errorUtils.throwMissingArguments(this, 'insertRule',
|
|
42
|
+
errorUtils.throwMissingArguments(this, 'insertRule', this.constructor.name);
|
|
43
43
|
}
|
|
44
44
|
if (index === void 0) {
|
|
45
45
|
index = 0;
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
index = Number(index);
|
|
48
|
+
if (index < 0) {
|
|
49
|
+
index = 4294967296 + index;
|
|
50
|
+
}
|
|
51
|
+
if (index > this.cssRules.length) {
|
|
52
|
+
errorUtils.throwIndexError(this, 'insertRule', this.constructor.name, index, this.cssRules.length);
|
|
49
53
|
}
|
|
54
|
+
|
|
50
55
|
var ruleToParse = String(rule);
|
|
51
56
|
var parsedSheet = CSSOM.parse(ruleToParse);
|
|
52
57
|
if (parsedSheet.cssRules.length !== 1) {
|
|
53
|
-
|
|
54
|
-
if (ruleToParse.trimStart().startsWith('@namespace')) {
|
|
55
|
-
domExceptionName = "InvalidStateError";
|
|
56
|
-
}
|
|
57
|
-
errorUtils.throwParseError(this, 'insertRule', 'CSSStyleSheet', ruleToParse, domExceptionName);
|
|
58
|
+
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
|
58
59
|
}
|
|
59
60
|
var cssRule = parsedSheet.cssRules[0];
|
|
61
|
+
|
|
62
|
+
// Helper function to find the last index of a specific rule constructor
|
|
63
|
+
function findLastIndexOfConstructor(rules, constructorName) {
|
|
64
|
+
for (var i = rules.length - 1; i >= 0; i--) {
|
|
65
|
+
if (rules[i].constructor.name === constructorName) {
|
|
66
|
+
return i;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return -1;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Helper function to find the first index of a rule that's NOT of specified constructors
|
|
73
|
+
function findFirstNonConstructorIndex(rules, constructorNames) {
|
|
74
|
+
for (var i = 0; i < rules.length; i++) {
|
|
75
|
+
if (constructorNames.indexOf(rules[i].constructor.name) === -1) {
|
|
76
|
+
return i;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return rules.length;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Validate rule ordering based on CSS specification
|
|
83
|
+
if (cssRule.constructor.name === 'CSSImportRule') {
|
|
84
|
+
// @import rules cannot be inserted after @layer rules that already exist
|
|
85
|
+
// They can only be inserted at the beginning or after other @import rules
|
|
86
|
+
var firstLayerIndex = findFirstNonConstructorIndex(this.cssRules, ['CSSImportRule']);
|
|
87
|
+
if (firstLayerIndex < this.cssRules.length && this.cssRules[firstLayerIndex].constructor.name === 'CSSLayerStatementRule' && index > firstLayerIndex) {
|
|
88
|
+
errorUtils.throwError(this, 'DOMException',
|
|
89
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
90
|
+
'HierarchyRequestError');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Also cannot insert after @namespace or other rules
|
|
94
|
+
var firstNonImportIndex = findFirstNonConstructorIndex(this.cssRules, ['CSSImportRule']);
|
|
95
|
+
if (index > firstNonImportIndex && firstNonImportIndex < this.cssRules.length &&
|
|
96
|
+
this.cssRules[firstNonImportIndex].constructor.name !== 'CSSLayerStatementRule') {
|
|
97
|
+
errorUtils.throwError(this, 'DOMException',
|
|
98
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
99
|
+
'HierarchyRequestError');
|
|
100
|
+
}
|
|
101
|
+
} else if (cssRule.constructor.name === 'CSSNamespaceRule') {
|
|
102
|
+
// @namespace rules can come after @layer and @import, but before any other rules
|
|
103
|
+
// They cannot come before @import rules
|
|
104
|
+
var firstImportIndex = -1;
|
|
105
|
+
for (var i = 0; i < this.cssRules.length; i++) {
|
|
106
|
+
if (this.cssRules[i].constructor.name === 'CSSImportRule') {
|
|
107
|
+
firstImportIndex = i;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
var firstNonImportNamespaceIndex = findFirstNonConstructorIndex(this.cssRules, [
|
|
112
|
+
'CSSLayerStatementRule',
|
|
113
|
+
'CSSImportRule',
|
|
114
|
+
'CSSNamespaceRule'
|
|
115
|
+
]);
|
|
116
|
+
|
|
117
|
+
// Cannot insert before @import rules
|
|
118
|
+
if (firstImportIndex !== -1 && index <= firstImportIndex) {
|
|
119
|
+
errorUtils.throwError(this, 'DOMException',
|
|
120
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
121
|
+
'HierarchyRequestError');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Cannot insert after other types of rules
|
|
125
|
+
if (index > firstNonImportNamespaceIndex) {
|
|
126
|
+
errorUtils.throwError(this, 'DOMException',
|
|
127
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
128
|
+
'HierarchyRequestError');
|
|
129
|
+
}
|
|
130
|
+
} else if (cssRule.constructor.name === 'CSSLayerStatementRule') {
|
|
131
|
+
// @layer statement rules can be inserted anywhere before @import and @namespace
|
|
132
|
+
// No additional restrictions beyond what's already handled
|
|
133
|
+
} else {
|
|
134
|
+
// Any other rule cannot be inserted before @import and @namespace
|
|
135
|
+
var firstNonSpecialRuleIndex = findFirstNonConstructorIndex(this.cssRules, [
|
|
136
|
+
'CSSLayerStatementRule',
|
|
137
|
+
'CSSImportRule',
|
|
138
|
+
'CSSNamespaceRule'
|
|
139
|
+
]);
|
|
140
|
+
|
|
141
|
+
if (index < firstNonSpecialRuleIndex) {
|
|
142
|
+
errorUtils.throwError(this, 'DOMException',
|
|
143
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
|
144
|
+
'HierarchyRequestError');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
60
148
|
cssRule.__parentStyleSheet = this;
|
|
61
149
|
this.cssRules.splice(index, 0, cssRule);
|
|
62
150
|
return index;
|
|
@@ -78,21 +166,21 @@ CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) {
|
|
|
78
166
|
*/
|
|
79
167
|
CSSOM.CSSStyleSheet.prototype.deleteRule = function(index) {
|
|
80
168
|
if (index === undefined) {
|
|
81
|
-
errorUtils.throwMissingArguments(this, 'deleteRule',
|
|
169
|
+
errorUtils.throwMissingArguments(this, 'deleteRule', this.constructor.name);
|
|
82
170
|
}
|
|
83
171
|
index = Number(index);
|
|
84
172
|
if (index < 0) {
|
|
85
173
|
index = 4294967296 + index;
|
|
86
174
|
}
|
|
87
175
|
if (index >= this.cssRules.length) {
|
|
88
|
-
errorUtils.throwIndexError(this, 'deleteRule',
|
|
176
|
+
errorUtils.throwIndexError(this, 'deleteRule', this.constructor.name, index, this.cssRules.length);
|
|
89
177
|
}
|
|
90
178
|
if (this.cssRules[index] && this.cssRules[index].constructor.name == "CSSNamespaceRule") {
|
|
91
179
|
var shouldContinue = this.cssRules.every(function (rule) {
|
|
92
180
|
return ['CSSImportRule','CSSLayerStatementRule','CSSNamespaceRule'].indexOf(rule.constructor.name) !== -1
|
|
93
181
|
});
|
|
94
182
|
if (!shouldContinue) {
|
|
95
|
-
errorUtils.throwError(this, 'DOMException', "Failed to execute 'deleteRule' on '
|
|
183
|
+
errorUtils.throwError(this, 'DOMException', "Failed to execute 'deleteRule' on '" + this.constructor.name + "': Failed to delete rule.", "InvalidStateError");
|
|
96
184
|
}
|
|
97
185
|
}
|
|
98
186
|
this.cssRules.splice(index, 1);
|
package/lib/errorUtils.js
CHANGED
|
@@ -2,27 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Gets the appropriate error constructor from the global object context.
|
|
5
|
-
* Tries to find the error constructor from parentStyleSheet.
|
|
6
|
-
* then from
|
|
5
|
+
* Tries to find the error constructor from parentStyleSheet.__globalObject,
|
|
6
|
+
* then from __globalObject, then falls back to the native constructor.
|
|
7
7
|
*
|
|
8
8
|
* @param {Object} context - The CSSOM object (rule, stylesheet, etc.)
|
|
9
9
|
* @param {string} errorType - The error type ('TypeError', 'RangeError', 'DOMException', etc.)
|
|
10
10
|
* @return {Function} The error constructor
|
|
11
11
|
*/
|
|
12
12
|
function getErrorConstructor(context, errorType) {
|
|
13
|
-
// Try parentStyleSheet.
|
|
14
|
-
if (context.parentStyleSheet && context.parentStyleSheet.
|
|
15
|
-
return context.parentStyleSheet.
|
|
13
|
+
// Try parentStyleSheet.__globalObject first
|
|
14
|
+
if (context.parentStyleSheet && context.parentStyleSheet.__globalObject && context.parentStyleSheet.__globalObject[errorType]) {
|
|
15
|
+
return context.parentStyleSheet.__globalObject[errorType];
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
// Try __parentStyleSheet (alternative naming)
|
|
19
|
-
if (context.__parentStyleSheet && context.__parentStyleSheet.
|
|
20
|
-
return context.__parentStyleSheet.
|
|
19
|
+
if (context.__parentStyleSheet && context.__parentStyleSheet.__globalObject && context.__parentStyleSheet.__globalObject[errorType]) {
|
|
20
|
+
return context.__parentStyleSheet.__globalObject[errorType];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
// Try
|
|
24
|
-
if (context.
|
|
25
|
-
return context.
|
|
23
|
+
// Try __globalObject on the context itself
|
|
24
|
+
if (context.__globalObject && context.__globalObject[errorType]) {
|
|
25
|
+
return context.__globalObject[errorType];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// Fall back to native constructor
|
|
@@ -63,16 +63,6 @@ function throwMissingArguments(context, methodName, objectName, required, provid
|
|
|
63
63
|
throwError(context, 'TypeError', message);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
/**
|
|
67
|
-
* Throws a RangeError for index out of bounds.
|
|
68
|
-
*
|
|
69
|
-
* @param {Object} context - The CSSOM object
|
|
70
|
-
* @param {string} [message] - Optional custom message, defaults to 'INDEX_SIZE_ERR'
|
|
71
|
-
*/
|
|
72
|
-
function throwIndexSizeError(context, message) {
|
|
73
|
-
throwError(context, 'RangeError', message || 'INDEX_SIZE_ERR');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
66
|
/**
|
|
77
67
|
* Throws a DOMException for parse errors.
|
|
78
68
|
*
|
|
@@ -108,7 +98,6 @@ var errorUtils = {
|
|
|
108
98
|
getErrorConstructor: getErrorConstructor,
|
|
109
99
|
throwError: throwError,
|
|
110
100
|
throwMissingArguments: throwMissingArguments,
|
|
111
|
-
throwIndexSizeError: throwIndexSizeError,
|
|
112
101
|
throwParseError: throwParseError,
|
|
113
102
|
throwIndexError: throwIndexError
|
|
114
103
|
};
|
package/lib/parse.js
CHANGED
|
@@ -4,10 +4,16 @@ var CSSOM = {};
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Parses a CSS string and returns a CSSOM.CSSStyleSheet object representing the parsed stylesheet.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} token - The CSS string to parse.
|
|
10
|
+
* @param {object} [opts] - Optional parsing options.
|
|
11
|
+
* @param {object} [opts.globalObject] - An optional global object to attach to the stylesheet. Useful on jsdom webplatform tests.
|
|
12
|
+
* @param {function|boolean} [errorHandler] - Optional error handler function or `true` to use `console.error`.
|
|
13
|
+
* @returns {CSSOM.CSSStyleSheet} The parsed CSSStyleSheet object.
|
|
8
14
|
*/
|
|
9
|
-
CSSOM.parse = function parse(token, errorHandler) {
|
|
10
|
-
errorHandler = errorHandler ===
|
|
15
|
+
CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
16
|
+
errorHandler = errorHandler === true ? (console && console.error) : errorHandler;
|
|
11
17
|
|
|
12
18
|
var i = 0;
|
|
13
19
|
|
|
@@ -49,6 +55,10 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
49
55
|
|
|
50
56
|
var styleSheet = new CSSOM.CSSStyleSheet();
|
|
51
57
|
|
|
58
|
+
if (opts && opts.globalObject) {
|
|
59
|
+
styleSheet.__globalObject = opts.globalObject;
|
|
60
|
+
}
|
|
61
|
+
|
|
52
62
|
// @type CSSStyleSheet|CSSMediaRule|CSSContainerRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule
|
|
53
63
|
var currentScope = styleSheet;
|
|
54
64
|
|
|
@@ -746,7 +756,7 @@ CSSOM.parse = function parse(token, errorHandler) {
|
|
|
746
756
|
i += "font-face".length;
|
|
747
757
|
fontFaceRule = new CSSOM.CSSFontFaceRule();
|
|
748
758
|
fontFaceRule.__starts = i;
|
|
749
|
-
},
|
|
759
|
+
}, true);
|
|
750
760
|
break;
|
|
751
761
|
} else {
|
|
752
762
|
atKeyframesRegExp.lastIndex = i;
|