@acemir/cssom 0.9.24 → 0.9.25
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 +1477 -1236
- package/lib/CSSConditionRule.js +3 -1
- package/lib/CSSContainerRule.js +9 -5
- package/lib/CSSCounterStyleRule.js +36 -2
- package/lib/CSSDocumentRule.js +9 -2
- package/lib/CSSFontFaceRule.js +9 -2
- package/lib/CSSGroupingRule.js +65 -9
- package/lib/CSSHostRule.js +9 -2
- package/lib/CSSImportRule.js +49 -39
- package/lib/CSSKeyframeRule.js +9 -2
- package/lib/CSSKeyframesRule.js +8 -2
- package/lib/CSSLayerBlockRule.js +9 -5
- package/lib/CSSLayerStatementRule.js +9 -5
- package/lib/CSSMediaRule.js +9 -5
- package/lib/CSSNamespaceRule.js +27 -17
- package/lib/CSSNestedDeclarations.js +9 -5
- package/lib/CSSOM.js +16 -1
- package/lib/CSSPageRule.js +3 -152
- package/lib/CSSRule.js +10 -0
- package/lib/CSSScopeRule.js +2 -1
- package/lib/CSSStartingStyleRule.js +9 -2
- package/lib/CSSStyleRule.js +3 -154
- package/lib/CSSStyleSheet.js +40 -8
- package/lib/CSSSupportsRule.js +8 -2
- package/lib/CSSValueExpression.js +3 -1
- package/lib/StyleSheet.js +24 -1
- package/lib/errorUtils.js +8 -13
- package/lib/index.js +2 -0
- package/lib/parse.js +1085 -791
- package/package.json +1 -1
package/build/CSSOM.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
var
|
|
1
|
+
var __globalObject = null;
|
|
2
|
+
|
|
3
|
+
var CSSOM = {
|
|
4
|
+
setup: function(opts) {
|
|
5
|
+
if (opts.globalObject) {
|
|
6
|
+
__globalObject = opts.globalObject;
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
getGlobalObject: function() {
|
|
10
|
+
return __globalObject;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
2
16
|
|
|
3
17
|
|
|
4
18
|
// Utility functions for CSSOM error handling
|
|
@@ -13,19 +27,8 @@ var CSSOM = {};
|
|
|
13
27
|
* @return {Function} The error constructor
|
|
14
28
|
*/
|
|
15
29
|
function getErrorConstructor(context, errorType) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return context.parentStyleSheet.__globalObject[errorType];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Try __parentStyleSheet (alternative naming)
|
|
22
|
-
if (context.__parentStyleSheet && context.__parentStyleSheet.__globalObject && context.__parentStyleSheet.__globalObject[errorType]) {
|
|
23
|
-
return context.__parentStyleSheet.__globalObject[errorType];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Try __globalObject on the context itself
|
|
27
|
-
if (context.__globalObject && context.__globalObject[errorType]) {
|
|
28
|
-
return context.__globalObject[errorType];
|
|
30
|
+
if (CSSOM.getGlobalObject() && CSSOM.getGlobalObject()[errorType]) {
|
|
31
|
+
return CSSOM.getGlobalObject()[errorType];
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
// Fall back to native constructor
|
|
@@ -344,6 +347,16 @@ Object.defineProperties(CSSOM.CSSRule.prototype, {
|
|
|
344
347
|
enumerable: true
|
|
345
348
|
},
|
|
346
349
|
|
|
350
|
+
cssText: {
|
|
351
|
+
get: function() {
|
|
352
|
+
// Default getter: subclasses should override this
|
|
353
|
+
return "";
|
|
354
|
+
},
|
|
355
|
+
set: function(cssText) {
|
|
356
|
+
return cssText;
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
|
|
347
360
|
parentRule: {
|
|
348
361
|
get: function() {
|
|
349
362
|
return this.__parentRule
|
|
@@ -414,9 +427,15 @@ CSSOM.CSSNestedDeclarations = function CSSNestedDeclarations() {
|
|
|
414
427
|
this.__style.parentRule = this;
|
|
415
428
|
};
|
|
416
429
|
|
|
417
|
-
CSSOM.CSSNestedDeclarations.prototype =
|
|
430
|
+
CSSOM.CSSNestedDeclarations.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
418
431
|
CSSOM.CSSNestedDeclarations.prototype.constructor = CSSOM.CSSNestedDeclarations;
|
|
419
|
-
|
|
432
|
+
|
|
433
|
+
Object.setPrototypeOf(CSSOM.CSSNestedDeclarations, CSSOM.CSSRule);
|
|
434
|
+
|
|
435
|
+
Object.defineProperty(CSSOM.CSSNestedDeclarations.prototype, "type", {
|
|
436
|
+
value: 0,
|
|
437
|
+
writable: false
|
|
438
|
+
});
|
|
420
439
|
|
|
421
440
|
Object.defineProperty(CSSOM.CSSNestedDeclarations.prototype, "style", {
|
|
422
441
|
get: function() {
|
|
@@ -434,9 +453,7 @@ Object.defineProperty(CSSOM.CSSNestedDeclarations.prototype, "style", {
|
|
|
434
453
|
Object.defineProperty(CSSOM.CSSNestedDeclarations.prototype, "cssText", {
|
|
435
454
|
get: function () {
|
|
436
455
|
return this.style.cssText;
|
|
437
|
-
}
|
|
438
|
-
configurable: true,
|
|
439
|
-
enumerable: true,
|
|
456
|
+
}
|
|
440
457
|
});
|
|
441
458
|
|
|
442
459
|
|
|
@@ -448,12 +465,19 @@ Object.defineProperty(CSSOM.CSSNestedDeclarations.prototype, "cssText", {
|
|
|
448
465
|
*/
|
|
449
466
|
CSSOM.CSSGroupingRule = function CSSGroupingRule() {
|
|
450
467
|
CSSOM.CSSRule.call(this);
|
|
451
|
-
this.
|
|
468
|
+
this.__cssRules = new CSSOM.CSSRuleList();
|
|
452
469
|
};
|
|
453
470
|
|
|
454
|
-
CSSOM.CSSGroupingRule.prototype
|
|
471
|
+
CSSOM.CSSGroupingRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
455
472
|
CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
|
|
456
473
|
|
|
474
|
+
Object.setPrototypeOf(CSSOM.CSSGroupingRule, CSSOM.CSSRule);
|
|
475
|
+
|
|
476
|
+
Object.defineProperty(CSSOM.CSSGroupingRule.prototype, "cssRules", {
|
|
477
|
+
get: function() {
|
|
478
|
+
return this.__cssRules;
|
|
479
|
+
}
|
|
480
|
+
});
|
|
457
481
|
|
|
458
482
|
/**
|
|
459
483
|
* Used to insert a new CSS rule to a list of CSS rules.
|
|
@@ -485,13 +509,60 @@ CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
|
|
|
485
509
|
if (index > this.cssRules.length) {
|
|
486
510
|
errorUtils.throwIndexError(this, 'insertRule', this.constructor.name, index, this.cssRules.length);
|
|
487
511
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
var
|
|
491
|
-
if (
|
|
492
|
-
|
|
512
|
+
var ruleToParse = processedRuleToParse = String(rule);
|
|
513
|
+
ruleToParse = ruleToParse.trim().replace(/^\/\*[\s\S]*?\*\/\s*/, "");
|
|
514
|
+
var isNestedSelector = this.constructor.name === "CSSStyleRule";
|
|
515
|
+
if (isNestedSelector === false) {
|
|
516
|
+
var currentRule = this;
|
|
517
|
+
while (currentRule.parentRule) {
|
|
518
|
+
currentRule = currentRule.parentRule;
|
|
519
|
+
if (currentRule.constructor.name === "CSSStyleRule") {
|
|
520
|
+
isNestedSelector = true;
|
|
521
|
+
break;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
if (isNestedSelector) {
|
|
526
|
+
processedRuleToParse = 's { n { } ' + ruleToParse + '}';
|
|
527
|
+
}
|
|
528
|
+
var isScopeRule = this.constructor.name === "CSSScopeRule";
|
|
529
|
+
if (isScopeRule) {
|
|
530
|
+
if (isNestedSelector) {
|
|
531
|
+
processedRuleToParse = 's { ' + '@scope {' + ruleToParse + '}}';
|
|
532
|
+
} else {
|
|
533
|
+
processedRuleToParse = '@scope {' + ruleToParse + '}';
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
var parsedRules = new CSSOM.CSSRuleList();
|
|
537
|
+
CSSOM.parse(processedRuleToParse, {
|
|
538
|
+
styleSheet: this.parentStyleSheet,
|
|
539
|
+
cssRules: parsedRules
|
|
540
|
+
});
|
|
541
|
+
if (isScopeRule) {
|
|
542
|
+
if (isNestedSelector) {
|
|
543
|
+
parsedRules = parsedRules[0].cssRules[0].cssRules;
|
|
544
|
+
} else {
|
|
545
|
+
parsedRules = parsedRules[0].cssRules
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (isNestedSelector) {
|
|
549
|
+
parsedRules = parsedRules[0].cssRules.slice(1);
|
|
550
|
+
}
|
|
551
|
+
if (parsedRules.length !== 1) {
|
|
552
|
+
if (isNestedSelector && parsedRules.length === 0 && ruleToParse.indexOf('@font-face') === 0) {
|
|
553
|
+
errorUtils.throwError(this, 'DOMException',
|
|
554
|
+
"Failed to execute 'insertRule' on '" + this.constructor.name + "': " +
|
|
555
|
+
"Only conditional nested group rules, style rules, @scope rules, @apply rules, and nested declaration rules may be nested.",
|
|
556
|
+
'HierarchyRequestError');
|
|
557
|
+
} else {
|
|
558
|
+
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
var cssRule = parsedRules[0];
|
|
562
|
+
|
|
563
|
+
if (cssRule.constructor.name === 'CSSNestedDeclarations' && cssRule.style.length === 0) {
|
|
564
|
+
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
|
493
565
|
}
|
|
494
|
-
var cssRule = parsedSheet.cssRules[0];
|
|
495
566
|
|
|
496
567
|
// Check for rules that cannot be inserted inside a CSSGroupingRule
|
|
497
568
|
if (cssRule.constructor.name === 'CSSImportRule' || cssRule.constructor.name === 'CSSNamespaceRule') {
|
|
@@ -535,7 +606,9 @@ CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
|
|
|
535
606
|
if (index >= this.cssRules.length) {
|
|
536
607
|
errorUtils.throwIndexError(this, 'deleteRule', this.constructor.name, index, this.cssRules.length);
|
|
537
608
|
}
|
|
538
|
-
this.cssRules
|
|
609
|
+
this.cssRules[index].__parentRule = null;
|
|
610
|
+
this.cssRules[index].__parentStyleSheet = null;
|
|
611
|
+
this.cssRules.splice(index, 1);
|
|
539
612
|
};
|
|
540
613
|
|
|
541
614
|
|
|
@@ -549,11 +622,45 @@ CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
|
|
|
549
622
|
CSSOM.CSSCounterStyleRule = function CSSCounterStyleRule() {
|
|
550
623
|
CSSOM.CSSRule.call(this);
|
|
551
624
|
this.name = "";
|
|
625
|
+
this.__props = "";
|
|
552
626
|
};
|
|
553
627
|
|
|
554
|
-
CSSOM.CSSCounterStyleRule.prototype =
|
|
628
|
+
CSSOM.CSSCounterStyleRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
555
629
|
CSSOM.CSSCounterStyleRule.prototype.constructor = CSSOM.CSSCounterStyleRule;
|
|
556
|
-
|
|
630
|
+
|
|
631
|
+
Object.setPrototypeOf(CSSOM.CSSCounterStyleRule, CSSOM.CSSRule);
|
|
632
|
+
|
|
633
|
+
Object.defineProperty(CSSOM.CSSCounterStyleRule.prototype, "type", {
|
|
634
|
+
value: 11,
|
|
635
|
+
writable: false
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
Object.defineProperty(CSSOM.CSSCounterStyleRule.prototype, "cssText", {
|
|
639
|
+
get: function() {
|
|
640
|
+
// FIXME : Implement real cssText generation based on properties
|
|
641
|
+
return "@counter-style " + this.name + " { " + this.__props + " }";
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* NON-STANDARD
|
|
647
|
+
* Rule text parser.
|
|
648
|
+
* @param {string} cssText
|
|
649
|
+
*/
|
|
650
|
+
Object.defineProperty(CSSOM.CSSCounterStyleRule.prototype, "parse", {
|
|
651
|
+
value: function(cssText) {
|
|
652
|
+
// Extract the name from "@counter-style <name> { ... }"
|
|
653
|
+
var match = cssText.match(/@counter-style\s+([^\s{]+)\s*\{([^]*)\}/);
|
|
654
|
+
if (match) {
|
|
655
|
+
this.name = match[1];
|
|
656
|
+
// Get the text inside the brackets and clean it up
|
|
657
|
+
var propsText = match[2];
|
|
658
|
+
this.__props = propsText.trim().replace(/\n/g, " ").replace(/(['"])(?:\\.|[^\\])*?\1|(\s{2,})/g, function (match, quote) {
|
|
659
|
+
return quote ? match : ' ';
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
});
|
|
557
664
|
|
|
558
665
|
|
|
559
666
|
|
|
@@ -568,9 +675,11 @@ CSSOM.CSSConditionRule = function CSSConditionRule() {
|
|
|
568
675
|
this.__conditionText = '';
|
|
569
676
|
};
|
|
570
677
|
|
|
571
|
-
CSSOM.CSSConditionRule.prototype =
|
|
678
|
+
CSSOM.CSSConditionRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
|
572
679
|
CSSOM.CSSConditionRule.prototype.constructor = CSSOM.CSSConditionRule;
|
|
573
680
|
|
|
681
|
+
Object.setPrototypeOf(CSSOM.CSSConditionRule, CSSOM.CSSGroupingRule);
|
|
682
|
+
|
|
574
683
|
Object.defineProperty(CSSOM.CSSConditionRule.prototype, "conditionText", {
|
|
575
684
|
get: function () {
|
|
576
685
|
return this.__conditionText;
|
|
@@ -593,9 +702,11 @@ CSSOM.CSSStyleRule = function CSSStyleRule() {
|
|
|
593
702
|
this.__style.parentRule = this;
|
|
594
703
|
};
|
|
595
704
|
|
|
596
|
-
CSSOM.CSSStyleRule.prototype =
|
|
705
|
+
CSSOM.CSSStyleRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
|
597
706
|
CSSOM.CSSStyleRule.prototype.constructor = CSSOM.CSSStyleRule;
|
|
598
707
|
|
|
708
|
+
Object.setPrototypeOf(CSSOM.CSSStyleRule, CSSOM.CSSGroupingRule);
|
|
709
|
+
|
|
599
710
|
Object.defineProperty(CSSOM.CSSStyleRule.prototype, "type", {
|
|
600
711
|
value: 1,
|
|
601
712
|
writable: false
|
|
@@ -659,163 +770,10 @@ Object.defineProperty(CSSOM.CSSStyleRule.prototype, "cssText", {
|
|
|
659
770
|
text = "";
|
|
660
771
|
}
|
|
661
772
|
return text;
|
|
662
|
-
},
|
|
663
|
-
set: function(cssText) {
|
|
664
|
-
if (typeof cssText === "string") {
|
|
665
|
-
var rule = CSSOM.CSSStyleRule.parse(cssText);
|
|
666
|
-
this.__style = rule.style;
|
|
667
|
-
this.selectorText = rule.selectorText;
|
|
668
|
-
}
|
|
669
773
|
}
|
|
670
774
|
});
|
|
671
775
|
|
|
672
776
|
|
|
673
|
-
/**
|
|
674
|
-
* NON-STANDARD
|
|
675
|
-
* lightweight version of parse.js.
|
|
676
|
-
* @param {string} ruleText
|
|
677
|
-
* @return CSSStyleRule
|
|
678
|
-
*/
|
|
679
|
-
CSSOM.CSSStyleRule.parse = function(ruleText) {
|
|
680
|
-
var i = 0;
|
|
681
|
-
var state = "selector";
|
|
682
|
-
var index;
|
|
683
|
-
var j = i;
|
|
684
|
-
var buffer = "";
|
|
685
|
-
|
|
686
|
-
var SIGNIFICANT_WHITESPACE = {
|
|
687
|
-
"selector": true,
|
|
688
|
-
"value": true
|
|
689
|
-
};
|
|
690
|
-
|
|
691
|
-
var styleRule = new CSSOM.CSSStyleRule();
|
|
692
|
-
var name, priority="";
|
|
693
|
-
|
|
694
|
-
for (var character; (character = ruleText.charAt(i)); i++) {
|
|
695
|
-
|
|
696
|
-
switch (character) {
|
|
697
|
-
|
|
698
|
-
case " ":
|
|
699
|
-
case "\t":
|
|
700
|
-
case "\r":
|
|
701
|
-
case "\n":
|
|
702
|
-
case "\f":
|
|
703
|
-
if (SIGNIFICANT_WHITESPACE[state]) {
|
|
704
|
-
// Squash 2 or more white-spaces in the row into 1
|
|
705
|
-
switch (ruleText.charAt(i - 1)) {
|
|
706
|
-
case " ":
|
|
707
|
-
case "\t":
|
|
708
|
-
case "\r":
|
|
709
|
-
case "\n":
|
|
710
|
-
case "\f":
|
|
711
|
-
break;
|
|
712
|
-
default:
|
|
713
|
-
buffer += " ";
|
|
714
|
-
break;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
break;
|
|
718
|
-
|
|
719
|
-
// String
|
|
720
|
-
case '"':
|
|
721
|
-
j = i + 1;
|
|
722
|
-
index = ruleText.indexOf('"', j) + 1;
|
|
723
|
-
if (!index) {
|
|
724
|
-
throw '" is missing';
|
|
725
|
-
}
|
|
726
|
-
buffer += ruleText.slice(i, index);
|
|
727
|
-
i = index - 1;
|
|
728
|
-
break;
|
|
729
|
-
|
|
730
|
-
case "'":
|
|
731
|
-
j = i + 1;
|
|
732
|
-
index = ruleText.indexOf("'", j) + 1;
|
|
733
|
-
if (!index) {
|
|
734
|
-
throw "' is missing";
|
|
735
|
-
}
|
|
736
|
-
buffer += ruleText.slice(i, index);
|
|
737
|
-
i = index - 1;
|
|
738
|
-
break;
|
|
739
|
-
|
|
740
|
-
// Comment
|
|
741
|
-
case "/":
|
|
742
|
-
if (ruleText.charAt(i + 1) === "*") {
|
|
743
|
-
i += 2;
|
|
744
|
-
index = ruleText.indexOf("*/", i);
|
|
745
|
-
if (index === -1) {
|
|
746
|
-
throw new SyntaxError("Missing */");
|
|
747
|
-
} else {
|
|
748
|
-
i = index + 1;
|
|
749
|
-
}
|
|
750
|
-
} else {
|
|
751
|
-
buffer += character;
|
|
752
|
-
}
|
|
753
|
-
break;
|
|
754
|
-
|
|
755
|
-
case "{":
|
|
756
|
-
if (state === "selector") {
|
|
757
|
-
styleRule.selectorText = buffer.trim();
|
|
758
|
-
buffer = "";
|
|
759
|
-
state = "name";
|
|
760
|
-
}
|
|
761
|
-
break;
|
|
762
|
-
|
|
763
|
-
case ":":
|
|
764
|
-
if (state === "name") {
|
|
765
|
-
name = buffer.trim();
|
|
766
|
-
buffer = "";
|
|
767
|
-
state = "value";
|
|
768
|
-
} else {
|
|
769
|
-
buffer += character;
|
|
770
|
-
}
|
|
771
|
-
break;
|
|
772
|
-
|
|
773
|
-
case "!":
|
|
774
|
-
if (state === "value" && ruleText.indexOf("!important", i) === i) {
|
|
775
|
-
priority = "important";
|
|
776
|
-
i += "important".length;
|
|
777
|
-
} else {
|
|
778
|
-
buffer += character;
|
|
779
|
-
}
|
|
780
|
-
break;
|
|
781
|
-
|
|
782
|
-
case ";":
|
|
783
|
-
if (state === "value") {
|
|
784
|
-
styleRule.style.setProperty(name, buffer.trim(), priority);
|
|
785
|
-
priority = "";
|
|
786
|
-
buffer = "";
|
|
787
|
-
state = "name";
|
|
788
|
-
} else {
|
|
789
|
-
buffer += character;
|
|
790
|
-
}
|
|
791
|
-
break;
|
|
792
|
-
|
|
793
|
-
case "}":
|
|
794
|
-
if (state === "value") {
|
|
795
|
-
styleRule.style.setProperty(name, buffer.trim(), priority);
|
|
796
|
-
priority = "";
|
|
797
|
-
buffer = "";
|
|
798
|
-
} else if (state === "name") {
|
|
799
|
-
break;
|
|
800
|
-
} else {
|
|
801
|
-
buffer += character;
|
|
802
|
-
}
|
|
803
|
-
state = "selector";
|
|
804
|
-
break;
|
|
805
|
-
|
|
806
|
-
default:
|
|
807
|
-
buffer += character;
|
|
808
|
-
break;
|
|
809
|
-
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
return styleRule;
|
|
814
|
-
|
|
815
|
-
};
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
777
|
|
|
820
778
|
|
|
821
779
|
|
|
@@ -888,9 +846,15 @@ CSSOM.CSSMediaRule = function CSSMediaRule() {
|
|
|
888
846
|
this.__media = new CSSOM.MediaList();
|
|
889
847
|
};
|
|
890
848
|
|
|
891
|
-
CSSOM.CSSMediaRule.prototype =
|
|
849
|
+
CSSOM.CSSMediaRule.prototype = Object.create(CSSOM.CSSConditionRule.prototype);
|
|
892
850
|
CSSOM.CSSMediaRule.prototype.constructor = CSSOM.CSSMediaRule;
|
|
893
|
-
|
|
851
|
+
|
|
852
|
+
Object.setPrototypeOf(CSSOM.CSSMediaRule, CSSOM.CSSConditionRule);
|
|
853
|
+
|
|
854
|
+
Object.defineProperty(CSSOM.CSSMediaRule.prototype, "type", {
|
|
855
|
+
value: 4,
|
|
856
|
+
writable: false
|
|
857
|
+
});
|
|
894
858
|
|
|
895
859
|
// https://opensource.apple.com/source/WebCore/WebCore-7611.1.21.161.3/css/CSSMediaRule.cpp
|
|
896
860
|
Object.defineProperties(CSSOM.CSSMediaRule.prototype, {
|
|
@@ -926,9 +890,7 @@ Object.defineProperties(CSSOM.CSSMediaRule.prototype, {
|
|
|
926
890
|
}
|
|
927
891
|
values = valuesArr.join("\n ") + "\n}";
|
|
928
892
|
return "@media " + this.media.mediaText + values;
|
|
929
|
-
}
|
|
930
|
-
configurable: true,
|
|
931
|
-
enumerable: true
|
|
893
|
+
}
|
|
932
894
|
}
|
|
933
895
|
});
|
|
934
896
|
|
|
@@ -946,9 +908,15 @@ CSSOM.CSSContainerRule = function CSSContainerRule() {
|
|
|
946
908
|
CSSOM.CSSConditionRule.call(this);
|
|
947
909
|
};
|
|
948
910
|
|
|
949
|
-
CSSOM.CSSContainerRule.prototype =
|
|
911
|
+
CSSOM.CSSContainerRule.prototype = Object.create(CSSOM.CSSConditionRule.prototype);
|
|
950
912
|
CSSOM.CSSContainerRule.prototype.constructor = CSSOM.CSSContainerRule;
|
|
951
|
-
|
|
913
|
+
|
|
914
|
+
Object.setPrototypeOf(CSSOM.CSSContainerRule, CSSOM.CSSConditionRule);
|
|
915
|
+
|
|
916
|
+
Object.defineProperty(CSSOM.CSSContainerRule.prototype, "type", {
|
|
917
|
+
value: 17,
|
|
918
|
+
writable: false
|
|
919
|
+
});
|
|
952
920
|
|
|
953
921
|
Object.defineProperties(CSSOM.CSSContainerRule.prototype, {
|
|
954
922
|
"cssText": {
|
|
@@ -965,9 +933,7 @@ Object.defineProperties(CSSOM.CSSContainerRule.prototype, {
|
|
|
965
933
|
}
|
|
966
934
|
values = valuesArr.join("\n ") + "\n}";
|
|
967
935
|
return "@container " + this.conditionText + values;
|
|
968
|
-
}
|
|
969
|
-
configurable: true,
|
|
970
|
-
enumerable: true
|
|
936
|
+
}
|
|
971
937
|
},
|
|
972
938
|
"containerName": {
|
|
973
939
|
get: function() {
|
|
@@ -1002,9 +968,15 @@ CSSOM.CSSSupportsRule = function CSSSupportsRule() {
|
|
|
1002
968
|
CSSOM.CSSConditionRule.call(this);
|
|
1003
969
|
};
|
|
1004
970
|
|
|
1005
|
-
CSSOM.CSSSupportsRule.prototype =
|
|
971
|
+
CSSOM.CSSSupportsRule.prototype = Object.create(CSSOM.CSSConditionRule.prototype);
|
|
1006
972
|
CSSOM.CSSSupportsRule.prototype.constructor = CSSOM.CSSSupportsRule;
|
|
1007
|
-
|
|
973
|
+
|
|
974
|
+
Object.setPrototypeOf(CSSOM.CSSSupportsRule, CSSOM.CSSConditionRule);
|
|
975
|
+
|
|
976
|
+
Object.defineProperty(CSSOM.CSSSupportsRule.prototype, "type", {
|
|
977
|
+
value: 12,
|
|
978
|
+
writable: false
|
|
979
|
+
});
|
|
1008
980
|
|
|
1009
981
|
Object.defineProperty(CSSOM.CSSSupportsRule.prototype, "cssText", {
|
|
1010
982
|
get: function() {
|
|
@@ -1041,9 +1013,11 @@ CSSOM.CSSImportRule = function CSSImportRule() {
|
|
|
1041
1013
|
this.__styleSheet = new CSSOM.CSSStyleSheet();
|
|
1042
1014
|
};
|
|
1043
1015
|
|
|
1044
|
-
CSSOM.CSSImportRule.prototype =
|
|
1016
|
+
CSSOM.CSSImportRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
1045
1017
|
CSSOM.CSSImportRule.prototype.constructor = CSSOM.CSSImportRule;
|
|
1046
1018
|
|
|
1019
|
+
Object.setPrototypeOf(CSSOM.CSSImportRule, CSSOM.CSSRule);
|
|
1020
|
+
|
|
1047
1021
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "type", {
|
|
1048
1022
|
value: 3,
|
|
1049
1023
|
writable: false
|
|
@@ -1053,8 +1027,53 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
|
|
|
1053
1027
|
get: function() {
|
|
1054
1028
|
var mediaText = this.media.mediaText;
|
|
1055
1029
|
return "@import url(\"" + this.href.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + "\")" + (this.layerName !== null ? " layer" + (this.layerName && "(" + this.layerName + ")") : "" ) + (this.supportsText ? " supports(" + this.supportsText + ")" : "" ) + (mediaText ? " " + mediaText : "") + ";";
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
Object.defineProperty(CSSOM.CSSImportRule.prototype, "href", {
|
|
1034
|
+
get: function() {
|
|
1035
|
+
return this.__href;
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
Object.defineProperty(CSSOM.CSSImportRule.prototype, "media", {
|
|
1040
|
+
get: function() {
|
|
1041
|
+
return this.__media;
|
|
1056
1042
|
},
|
|
1057
|
-
|
|
1043
|
+
set: function(value) {
|
|
1044
|
+
if (typeof value === "string") {
|
|
1045
|
+
this.__media.mediaText = value;
|
|
1046
|
+
} else {
|
|
1047
|
+
this.__media = value;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
});
|
|
1051
|
+
|
|
1052
|
+
Object.defineProperty(CSSOM.CSSImportRule.prototype, "layerName", {
|
|
1053
|
+
get: function() {
|
|
1054
|
+
return this.__layerName;
|
|
1055
|
+
}
|
|
1056
|
+
});
|
|
1057
|
+
|
|
1058
|
+
Object.defineProperty(CSSOM.CSSImportRule.prototype, "supportsText", {
|
|
1059
|
+
get: function() {
|
|
1060
|
+
return this.__supportsText;
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1064
|
+
Object.defineProperty(CSSOM.CSSImportRule.prototype, "styleSheet", {
|
|
1065
|
+
get: function() {
|
|
1066
|
+
return this.__styleSheet;
|
|
1067
|
+
}
|
|
1068
|
+
});
|
|
1069
|
+
|
|
1070
|
+
/**
|
|
1071
|
+
* NON-STANDARD
|
|
1072
|
+
* Rule text parser.
|
|
1073
|
+
* @param {string} cssText
|
|
1074
|
+
*/
|
|
1075
|
+
Object.defineProperty(CSSOM.CSSImportRule.prototype, "parse", {
|
|
1076
|
+
value: function(cssText) {
|
|
1058
1077
|
var i = 0;
|
|
1059
1078
|
|
|
1060
1079
|
/**
|
|
@@ -1233,43 +1252,6 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
|
|
|
1233
1252
|
}
|
|
1234
1253
|
});
|
|
1235
1254
|
|
|
1236
|
-
Object.defineProperty(CSSOM.CSSImportRule.prototype, "href", {
|
|
1237
|
-
get: function() {
|
|
1238
|
-
return this.__href;
|
|
1239
|
-
}
|
|
1240
|
-
});
|
|
1241
|
-
|
|
1242
|
-
Object.defineProperty(CSSOM.CSSImportRule.prototype, "media", {
|
|
1243
|
-
get: function() {
|
|
1244
|
-
return this.__media;
|
|
1245
|
-
},
|
|
1246
|
-
set: function(value) {
|
|
1247
|
-
if (typeof value === "string") {
|
|
1248
|
-
this.__media.mediaText = value;
|
|
1249
|
-
} else {
|
|
1250
|
-
this.__media = value;
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
});
|
|
1254
|
-
|
|
1255
|
-
Object.defineProperty(CSSOM.CSSImportRule.prototype, "layerName", {
|
|
1256
|
-
get: function() {
|
|
1257
|
-
return this.__layerName;
|
|
1258
|
-
}
|
|
1259
|
-
});
|
|
1260
|
-
|
|
1261
|
-
Object.defineProperty(CSSOM.CSSImportRule.prototype, "supportsText", {
|
|
1262
|
-
get: function() {
|
|
1263
|
-
return this.__supportsText;
|
|
1264
|
-
}
|
|
1265
|
-
});
|
|
1266
|
-
|
|
1267
|
-
Object.defineProperty(CSSOM.CSSImportRule.prototype, "styleSheet", {
|
|
1268
|
-
get: function() {
|
|
1269
|
-
return this.__styleSheet;
|
|
1270
|
-
}
|
|
1271
|
-
});
|
|
1272
|
-
|
|
1273
1255
|
|
|
1274
1256
|
|
|
1275
1257
|
|
|
@@ -1285,29 +1267,52 @@ CSSOM.CSSNamespaceRule = function CSSNamespaceRule() {
|
|
|
1285
1267
|
this.__namespaceURI = "";
|
|
1286
1268
|
};
|
|
1287
1269
|
|
|
1288
|
-
CSSOM.CSSNamespaceRule.prototype =
|
|
1270
|
+
CSSOM.CSSNamespaceRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
1289
1271
|
CSSOM.CSSNamespaceRule.prototype.constructor = CSSOM.CSSNamespaceRule;
|
|
1290
1272
|
|
|
1273
|
+
Object.setPrototypeOf(CSSOM.CSSNamespaceRule, CSSOM.CSSRule);
|
|
1274
|
+
|
|
1291
1275
|
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "type", {
|
|
1292
1276
|
value: 10,
|
|
1293
|
-
|
|
1277
|
+
writable: false
|
|
1294
1278
|
});
|
|
1295
1279
|
|
|
1296
1280
|
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "cssText", {
|
|
1297
1281
|
get: function() {
|
|
1298
1282
|
return "@namespace" + (this.prefix && " " + this.prefix) + " url(\"" + this.namespaceURI + "\");";
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
var newPrefix = "";
|
|
1302
|
-
var newNamespaceURI = "";
|
|
1303
|
-
|
|
1304
|
-
// Remove @namespace and trim
|
|
1305
|
-
var text = cssText.trim();
|
|
1306
|
-
if (text.indexOf('@namespace') === 0) {
|
|
1307
|
-
text = text.slice('@namespace'.length).trim();
|
|
1308
|
-
}
|
|
1283
|
+
}
|
|
1284
|
+
});
|
|
1309
1285
|
|
|
1310
|
-
|
|
1286
|
+
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "prefix", {
|
|
1287
|
+
get: function() {
|
|
1288
|
+
return this.__prefix;
|
|
1289
|
+
}
|
|
1290
|
+
});
|
|
1291
|
+
|
|
1292
|
+
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "namespaceURI", {
|
|
1293
|
+
get: function() {
|
|
1294
|
+
return this.__namespaceURI;
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
/**
|
|
1300
|
+
* NON-STANDARD
|
|
1301
|
+
* Rule text parser.
|
|
1302
|
+
* @param {string} cssText
|
|
1303
|
+
*/
|
|
1304
|
+
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "parse", {
|
|
1305
|
+
value: function(cssText) {
|
|
1306
|
+
var newPrefix = "";
|
|
1307
|
+
var newNamespaceURI = "";
|
|
1308
|
+
|
|
1309
|
+
// Remove @namespace and trim
|
|
1310
|
+
var text = cssText.trim();
|
|
1311
|
+
if (text.indexOf('@namespace') === 0) {
|
|
1312
|
+
text = text.slice('@namespace'.length).trim();
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
// Remove trailing semicolon if present
|
|
1311
1316
|
if (text.charAt(text.length - 1) === ';') {
|
|
1312
1317
|
text = text.slice(0, -1).trim();
|
|
1313
1318
|
}
|
|
@@ -1345,19 +1350,6 @@ Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "cssText", {
|
|
|
1345
1350
|
}
|
|
1346
1351
|
});
|
|
1347
1352
|
|
|
1348
|
-
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "prefix", {
|
|
1349
|
-
get: function() {
|
|
1350
|
-
return this.__prefix;
|
|
1351
|
-
}
|
|
1352
|
-
});
|
|
1353
|
-
|
|
1354
|
-
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "namespaceURI", {
|
|
1355
|
-
get: function() {
|
|
1356
|
-
return this.__namespaceURI;
|
|
1357
|
-
}
|
|
1358
|
-
});
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
1353
|
|
|
1362
1354
|
|
|
1363
1355
|
|
|
@@ -1371,9 +1363,16 @@ CSSOM.CSSFontFaceRule = function CSSFontFaceRule() {
|
|
|
1371
1363
|
this.__style.parentRule = this;
|
|
1372
1364
|
};
|
|
1373
1365
|
|
|
1374
|
-
CSSOM.CSSFontFaceRule.prototype =
|
|
1366
|
+
CSSOM.CSSFontFaceRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
1375
1367
|
CSSOM.CSSFontFaceRule.prototype.constructor = CSSOM.CSSFontFaceRule;
|
|
1376
|
-
|
|
1368
|
+
|
|
1369
|
+
Object.setPrototypeOf(CSSOM.CSSFontFaceRule, CSSOM.CSSRule);
|
|
1370
|
+
|
|
1371
|
+
Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "type", {
|
|
1372
|
+
value: 5,
|
|
1373
|
+
writable: false
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1377
1376
|
//FIXME
|
|
1378
1377
|
//CSSOM.CSSFontFaceRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
|
1379
1378
|
//CSSOM.CSSFontFaceRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
|
@@ -1414,9 +1413,16 @@ CSSOM.CSSHostRule = function CSSHostRule() {
|
|
|
1414
1413
|
this.cssRules = new CSSOM.CSSRuleList();
|
|
1415
1414
|
};
|
|
1416
1415
|
|
|
1417
|
-
CSSOM.CSSHostRule.prototype =
|
|
1416
|
+
CSSOM.CSSHostRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
1418
1417
|
CSSOM.CSSHostRule.prototype.constructor = CSSOM.CSSHostRule;
|
|
1419
|
-
|
|
1418
|
+
|
|
1419
|
+
Object.setPrototypeOf(CSSOM.CSSHostRule, CSSOM.CSSRule);
|
|
1420
|
+
|
|
1421
|
+
Object.defineProperty(CSSOM.CSSHostRule.prototype, "type", {
|
|
1422
|
+
value: 1001,
|
|
1423
|
+
writable: false
|
|
1424
|
+
});
|
|
1425
|
+
|
|
1420
1426
|
//FIXME
|
|
1421
1427
|
//CSSOM.CSSHostRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
|
1422
1428
|
//CSSOM.CSSHostRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
|
@@ -1451,9 +1457,16 @@ CSSOM.CSSStartingStyleRule = function CSSStartingStyleRule() {
|
|
|
1451
1457
|
CSSOM.CSSGroupingRule.call(this);
|
|
1452
1458
|
};
|
|
1453
1459
|
|
|
1454
|
-
CSSOM.CSSStartingStyleRule.prototype =
|
|
1460
|
+
CSSOM.CSSStartingStyleRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
|
1455
1461
|
CSSOM.CSSStartingStyleRule.prototype.constructor = CSSOM.CSSStartingStyleRule;
|
|
1456
|
-
|
|
1462
|
+
|
|
1463
|
+
Object.setPrototypeOf(CSSOM.CSSStartingStyleRule, CSSOM.CSSGroupingRule);
|
|
1464
|
+
|
|
1465
|
+
Object.defineProperty(CSSOM.CSSStartingStyleRule.prototype, "type", {
|
|
1466
|
+
value: 1002,
|
|
1467
|
+
writable: false
|
|
1468
|
+
});
|
|
1469
|
+
|
|
1457
1470
|
//FIXME
|
|
1458
1471
|
//CSSOM.CSSStartingStyleRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
|
1459
1472
|
//CSSOM.CSSStartingStyleRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
|
@@ -1481,15 +1494,38 @@ Object.defineProperty(CSSOM.CSSStartingStyleRule.prototype, "cssText", {
|
|
|
1481
1494
|
|
|
1482
1495
|
|
|
1483
1496
|
/**
|
|
1484
|
-
* @constructor
|
|
1485
1497
|
* @see http://dev.w3.org/csswg/cssom/#the-stylesheet-interface
|
|
1486
1498
|
*/
|
|
1487
1499
|
CSSOM.StyleSheet = function StyleSheet() {
|
|
1500
|
+
this.__href = null;
|
|
1501
|
+
this.__ownerNode = null;
|
|
1502
|
+
this.__title = null;
|
|
1488
1503
|
this.__media = new CSSOM.MediaList();
|
|
1489
1504
|
this.__parentStyleSheet = null;
|
|
1505
|
+
this.disabled = false;
|
|
1490
1506
|
};
|
|
1491
1507
|
|
|
1492
1508
|
Object.defineProperties(CSSOM.StyleSheet.prototype, {
|
|
1509
|
+
type: {
|
|
1510
|
+
get: function() {
|
|
1511
|
+
return "text/css";
|
|
1512
|
+
}
|
|
1513
|
+
},
|
|
1514
|
+
href: {
|
|
1515
|
+
get: function() {
|
|
1516
|
+
return this.__href;
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
ownerNode: {
|
|
1520
|
+
get: function() {
|
|
1521
|
+
return this.__ownerNode;
|
|
1522
|
+
}
|
|
1523
|
+
},
|
|
1524
|
+
title: {
|
|
1525
|
+
get: function() {
|
|
1526
|
+
return this.__title;
|
|
1527
|
+
}
|
|
1528
|
+
},
|
|
1493
1529
|
media: {
|
|
1494
1530
|
get: function() {
|
|
1495
1531
|
return this.__media;
|
|
@@ -1515,21 +1551,52 @@ Object.defineProperties(CSSOM.StyleSheet.prototype, {
|
|
|
1515
1551
|
|
|
1516
1552
|
/**
|
|
1517
1553
|
* @constructor
|
|
1554
|
+
* @param {CSSStyleSheetInit} [opts] - CSSStyleSheetInit options.
|
|
1555
|
+
* @param {string} [opts.baseURL] - The base URL of the stylesheet.
|
|
1556
|
+
* @param {boolean} [opts.disabled] - The disabled attribute of the stylesheet.
|
|
1557
|
+
* @param {MediaList | string} [opts.media] - The media attribute of the stylesheet.
|
|
1518
1558
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet
|
|
1519
1559
|
*/
|
|
1520
|
-
CSSOM.CSSStyleSheet = function CSSStyleSheet() {
|
|
1560
|
+
CSSOM.CSSStyleSheet = function CSSStyleSheet(opts) {
|
|
1521
1561
|
CSSOM.StyleSheet.call(this);
|
|
1522
1562
|
this.__constructed = true;
|
|
1523
|
-
this.
|
|
1563
|
+
this.__cssRules = new CSSOM.CSSRuleList();
|
|
1564
|
+
this.__ownerRule = null;
|
|
1565
|
+
|
|
1566
|
+
if (opts && typeof opts === "object") {
|
|
1567
|
+
if (opts.baseURL && typeof opts.baseURL === "string") {
|
|
1568
|
+
this.__baseURL = opts.baseURL;
|
|
1569
|
+
}
|
|
1570
|
+
if (opts.media && typeof opts.media === "string") {
|
|
1571
|
+
this.media.mediaText = opts.media;
|
|
1572
|
+
}
|
|
1573
|
+
if (typeof opts.disabled === "boolean") {
|
|
1574
|
+
this.disabled = opts.disabled;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1524
1577
|
};
|
|
1525
1578
|
|
|
1526
1579
|
|
|
1527
|
-
CSSOM.CSSStyleSheet.prototype =
|
|
1580
|
+
CSSOM.CSSStyleSheet.prototype = Object.create(CSSOM.StyleSheet.prototype);
|
|
1528
1581
|
CSSOM.CSSStyleSheet.prototype.constructor = CSSOM.CSSStyleSheet;
|
|
1529
1582
|
|
|
1583
|
+
Object.setPrototypeOf(CSSOM.CSSStyleSheet, CSSOM.StyleSheet);
|
|
1584
|
+
|
|
1585
|
+
Object.defineProperty(CSSOM.CSSStyleSheet.prototype, "cssRules", {
|
|
1586
|
+
get: function() {
|
|
1587
|
+
return this.__cssRules;
|
|
1588
|
+
}
|
|
1589
|
+
});
|
|
1590
|
+
|
|
1530
1591
|
Object.defineProperty(CSSOM.CSSStyleSheet.prototype, "rules", {
|
|
1531
1592
|
get: function() {
|
|
1532
|
-
return this.
|
|
1593
|
+
return this.__cssRules;
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1597
|
+
Object.defineProperty(CSSOM.CSSStyleSheet.prototype, "ownerRule", {
|
|
1598
|
+
get: function() {
|
|
1599
|
+
return this.__ownerRule;
|
|
1533
1600
|
}
|
|
1534
1601
|
});
|
|
1535
1602
|
|
|
@@ -1741,8 +1808,8 @@ CSSOM.CSSStyleSheet.prototype.removeRule = function(index) {
|
|
|
1741
1808
|
*/
|
|
1742
1809
|
CSSOM.CSSStyleSheet.prototype.replace = function(text) {
|
|
1743
1810
|
var _Promise;
|
|
1744
|
-
if (
|
|
1745
|
-
_Promise =
|
|
1811
|
+
if (CSSOM.getGlobalObject() && CSSOM.getGlobalObject()['Promise']) {
|
|
1812
|
+
_Promise = CSSOM.getGlobalObject()['Promise'];
|
|
1746
1813
|
} else {
|
|
1747
1814
|
_Promise = Promise;
|
|
1748
1815
|
}
|
|
@@ -1772,7 +1839,7 @@ CSSOM.CSSStyleSheet.prototype.replace = function(text) {
|
|
|
1772
1839
|
}
|
|
1773
1840
|
}
|
|
1774
1841
|
// Set sheet's CSS rules to rules.
|
|
1775
|
-
sheet.
|
|
1842
|
+
sheet.__cssRules = rules;
|
|
1776
1843
|
// Unset sheet’s disallow modification flag.
|
|
1777
1844
|
delete sheet.__disallowModification;
|
|
1778
1845
|
// Resolve promise with sheet.
|
|
@@ -1807,7 +1874,7 @@ CSSOM.CSSStyleSheet.prototype.replaceSync = function(text) {
|
|
|
1807
1874
|
}
|
|
1808
1875
|
}
|
|
1809
1876
|
// Set sheet's CSS rules to rules.
|
|
1810
|
-
sheet.
|
|
1877
|
+
sheet.__cssRules = rules;
|
|
1811
1878
|
}
|
|
1812
1879
|
|
|
1813
1880
|
/**
|
|
@@ -1869,9 +1936,15 @@ CSSOM.CSSKeyframesRule = function CSSKeyframesRule() {
|
|
|
1869
1936
|
});
|
|
1870
1937
|
};
|
|
1871
1938
|
|
|
1872
|
-
CSSOM.CSSKeyframesRule.prototype =
|
|
1939
|
+
CSSOM.CSSKeyframesRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
1873
1940
|
CSSOM.CSSKeyframesRule.prototype.constructor = CSSOM.CSSKeyframesRule;
|
|
1874
|
-
|
|
1941
|
+
|
|
1942
|
+
Object.setPrototypeOf(CSSOM.CSSKeyframesRule, CSSOM.CSSRule);
|
|
1943
|
+
|
|
1944
|
+
Object.defineProperty(CSSOM.CSSKeyframesRule.prototype, "type", {
|
|
1945
|
+
value: 7,
|
|
1946
|
+
writable: false
|
|
1947
|
+
});
|
|
1875
1948
|
|
|
1876
1949
|
// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframesRule.cpp
|
|
1877
1950
|
Object.defineProperty(CSSOM.CSSKeyframesRule.prototype, "cssText", {
|
|
@@ -2071,9 +2144,16 @@ CSSOM.CSSKeyframeRule = function CSSKeyframeRule() {
|
|
|
2071
2144
|
this.__style.parentRule = this;
|
|
2072
2145
|
};
|
|
2073
2146
|
|
|
2074
|
-
CSSOM.CSSKeyframeRule.prototype =
|
|
2147
|
+
CSSOM.CSSKeyframeRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
2075
2148
|
CSSOM.CSSKeyframeRule.prototype.constructor = CSSOM.CSSKeyframeRule;
|
|
2076
|
-
|
|
2149
|
+
|
|
2150
|
+
Object.setPrototypeOf(CSSOM.CSSKeyframeRule, CSSOM.CSSRule);
|
|
2151
|
+
|
|
2152
|
+
Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "type", {
|
|
2153
|
+
value: 8,
|
|
2154
|
+
writable: false
|
|
2155
|
+
});
|
|
2156
|
+
|
|
2077
2157
|
//FIXME
|
|
2078
2158
|
//CSSOM.CSSKeyframeRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
|
2079
2159
|
//CSSOM.CSSKeyframeRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
|
@@ -2172,9 +2252,16 @@ CSSOM.CSSDocumentRule = function CSSDocumentRule() {
|
|
|
2172
2252
|
this.cssRules = new CSSOM.CSSRuleList();
|
|
2173
2253
|
};
|
|
2174
2254
|
|
|
2175
|
-
CSSOM.CSSDocumentRule.prototype =
|
|
2255
|
+
CSSOM.CSSDocumentRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
2176
2256
|
CSSOM.CSSDocumentRule.prototype.constructor = CSSOM.CSSDocumentRule;
|
|
2177
|
-
|
|
2257
|
+
|
|
2258
|
+
Object.setPrototypeOf(CSSOM.CSSDocumentRule, CSSOM.CSSRule);
|
|
2259
|
+
|
|
2260
|
+
Object.defineProperty(CSSOM.CSSDocumentRule.prototype, "type", {
|
|
2261
|
+
value: 10,
|
|
2262
|
+
writable: false
|
|
2263
|
+
});
|
|
2264
|
+
|
|
2178
2265
|
//FIXME
|
|
2179
2266
|
//CSSOM.CSSDocumentRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
|
2180
2267
|
//CSSOM.CSSDocumentRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
|
@@ -2243,9 +2330,11 @@ CSSOM.CSSValueExpression = function CSSValueExpression(token, idx) {
|
|
|
2243
2330
|
this._idx = idx;
|
|
2244
2331
|
};
|
|
2245
2332
|
|
|
2246
|
-
CSSOM.CSSValueExpression.prototype =
|
|
2333
|
+
CSSOM.CSSValueExpression.prototype = Object.create(CSSOM.CSSValue.prototype);
|
|
2247
2334
|
CSSOM.CSSValueExpression.prototype.constructor = CSSOM.CSSValueExpression;
|
|
2248
2335
|
|
|
2336
|
+
Object.setPrototypeOf(CSSOM.CSSValueExpression, CSSOM.CSSValue);
|
|
2337
|
+
|
|
2249
2338
|
/**
|
|
2250
2339
|
* parse css expression() value
|
|
2251
2340
|
*
|
|
@@ -2580,9 +2669,10 @@ CSSOM.CSSScopeRule = function CSSScopeRule() {
|
|
|
2580
2669
|
this.__end = null;
|
|
2581
2670
|
};
|
|
2582
2671
|
|
|
2583
|
-
CSSOM.CSSScopeRule.prototype =
|
|
2672
|
+
CSSOM.CSSScopeRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
|
2584
2673
|
CSSOM.CSSScopeRule.prototype.constructor = CSSOM.CSSScopeRule;
|
|
2585
2674
|
|
|
2675
|
+
Object.setPrototypeOf(CSSOM.CSSScopeRule, CSSOM.CSSGroupingRule);
|
|
2586
2676
|
|
|
2587
2677
|
Object.defineProperties(CSSOM.CSSScopeRule.prototype, {
|
|
2588
2678
|
type: {
|
|
@@ -2631,9 +2721,15 @@ CSSOM.CSSLayerBlockRule = function CSSLayerBlockRule() {
|
|
|
2631
2721
|
this.name = "";
|
|
2632
2722
|
};
|
|
2633
2723
|
|
|
2634
|
-
CSSOM.CSSLayerBlockRule.prototype =
|
|
2724
|
+
CSSOM.CSSLayerBlockRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
|
2635
2725
|
CSSOM.CSSLayerBlockRule.prototype.constructor = CSSOM.CSSLayerBlockRule;
|
|
2636
|
-
|
|
2726
|
+
|
|
2727
|
+
Object.setPrototypeOf(CSSOM.CSSLayerBlockRule, CSSOM.CSSRule);
|
|
2728
|
+
|
|
2729
|
+
Object.defineProperty(CSSOM.CSSLayerBlockRule.prototype, "type", {
|
|
2730
|
+
value: 18,
|
|
2731
|
+
writable: false
|
|
2732
|
+
});
|
|
2637
2733
|
|
|
2638
2734
|
Object.defineProperties(CSSOM.CSSLayerBlockRule.prototype, {
|
|
2639
2735
|
cssText: {
|
|
@@ -2650,9 +2746,7 @@ Object.defineProperties(CSSOM.CSSLayerBlockRule.prototype, {
|
|
|
2650
2746
|
}
|
|
2651
2747
|
values = valuesArr.join("\n ") + "\n}";
|
|
2652
2748
|
return "@layer" + (this.name ? " " + this.name : "") + values;
|
|
2653
|
-
}
|
|
2654
|
-
configurable: true,
|
|
2655
|
-
enumerable: true,
|
|
2749
|
+
}
|
|
2656
2750
|
},
|
|
2657
2751
|
});
|
|
2658
2752
|
|
|
@@ -2668,17 +2762,21 @@ CSSOM.CSSLayerStatementRule = function CSSLayerStatementRule() {
|
|
|
2668
2762
|
this.nameList = [];
|
|
2669
2763
|
};
|
|
2670
2764
|
|
|
2671
|
-
CSSOM.CSSLayerStatementRule.prototype =
|
|
2765
|
+
CSSOM.CSSLayerStatementRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
|
2672
2766
|
CSSOM.CSSLayerStatementRule.prototype.constructor = CSSOM.CSSLayerStatementRule;
|
|
2673
|
-
|
|
2767
|
+
|
|
2768
|
+
Object.setPrototypeOf(CSSOM.CSSLayerStatementRule, CSSOM.CSSRule);
|
|
2769
|
+
|
|
2770
|
+
Object.defineProperty(CSSOM.CSSLayerStatementRule.prototype, "type", {
|
|
2771
|
+
value: 0,
|
|
2772
|
+
writable: false
|
|
2773
|
+
});
|
|
2674
2774
|
|
|
2675
2775
|
Object.defineProperties(CSSOM.CSSLayerStatementRule.prototype, {
|
|
2676
2776
|
cssText: {
|
|
2677
2777
|
get: function () {
|
|
2678
2778
|
return "@layer " + this.nameList.join(", ") + ";";
|
|
2679
|
-
}
|
|
2680
|
-
configurable: true,
|
|
2681
|
-
enumerable: true,
|
|
2779
|
+
}
|
|
2682
2780
|
},
|
|
2683
2781
|
});
|
|
2684
2782
|
|
|
@@ -2696,9 +2794,11 @@ CSSOM.CSSPageRule = function CSSPageRule() {
|
|
|
2696
2794
|
this.__style.parentRule = this;
|
|
2697
2795
|
};
|
|
2698
2796
|
|
|
2699
|
-
CSSOM.CSSPageRule.prototype =
|
|
2797
|
+
CSSOM.CSSPageRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
|
2700
2798
|
CSSOM.CSSPageRule.prototype.constructor = CSSOM.CSSPageRule;
|
|
2701
2799
|
|
|
2800
|
+
Object.setPrototypeOf(CSSOM.CSSPageRule, CSSOM.CSSGroupingRule);
|
|
2801
|
+
|
|
2702
2802
|
Object.defineProperty(CSSOM.CSSPageRule.prototype, "type", {
|
|
2703
2803
|
value: 6,
|
|
2704
2804
|
writable: false
|
|
@@ -2793,161 +2893,9 @@ Object.defineProperty(CSSOM.CSSPageRule.prototype, "cssText", {
|
|
|
2793
2893
|
values = " {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
|
2794
2894
|
}
|
|
2795
2895
|
return "@page" + (this.selectorText ? " " + this.selectorText : "") + values;
|
|
2796
|
-
},
|
|
2797
|
-
set: function(cssText) {
|
|
2798
|
-
if (typeof value === "string") {
|
|
2799
|
-
var rule = CSSOM.CSSPageRule.parse(cssText);
|
|
2800
|
-
this.__style = rule.style;
|
|
2801
|
-
this.selectorText = rule.selectorText;
|
|
2802
|
-
}
|
|
2803
2896
|
}
|
|
2804
2897
|
});
|
|
2805
2898
|
|
|
2806
|
-
/**
|
|
2807
|
-
* NON-STANDARD
|
|
2808
|
-
* lightweight version of parse.js.
|
|
2809
|
-
* @param {string} ruleText
|
|
2810
|
-
* @return CSSPageRule
|
|
2811
|
-
*/
|
|
2812
|
-
CSSOM.CSSPageRule.parse = function(ruleText) {
|
|
2813
|
-
var i = 0;
|
|
2814
|
-
var state = "selector";
|
|
2815
|
-
var index;
|
|
2816
|
-
var j = i;
|
|
2817
|
-
var buffer = "";
|
|
2818
|
-
|
|
2819
|
-
var SIGNIFICANT_WHITESPACE = {
|
|
2820
|
-
"selector": true,
|
|
2821
|
-
"value": true
|
|
2822
|
-
};
|
|
2823
|
-
|
|
2824
|
-
var pageRule = new CSSOM.CSSPageRule();
|
|
2825
|
-
var name, priority="";
|
|
2826
|
-
|
|
2827
|
-
for (var character; (character = ruleText.charAt(i)); i++) {
|
|
2828
|
-
|
|
2829
|
-
switch (character) {
|
|
2830
|
-
|
|
2831
|
-
case " ":
|
|
2832
|
-
case "\t":
|
|
2833
|
-
case "\r":
|
|
2834
|
-
case "\n":
|
|
2835
|
-
case "\f":
|
|
2836
|
-
if (SIGNIFICANT_WHITESPACE[state]) {
|
|
2837
|
-
// Squash 2 or more white-spaces in the row into 1
|
|
2838
|
-
switch (ruleText.charAt(i - 1)) {
|
|
2839
|
-
case " ":
|
|
2840
|
-
case "\t":
|
|
2841
|
-
case "\r":
|
|
2842
|
-
case "\n":
|
|
2843
|
-
case "\f":
|
|
2844
|
-
break;
|
|
2845
|
-
default:
|
|
2846
|
-
buffer += " ";
|
|
2847
|
-
break;
|
|
2848
|
-
}
|
|
2849
|
-
}
|
|
2850
|
-
break;
|
|
2851
|
-
|
|
2852
|
-
// String
|
|
2853
|
-
case '"':
|
|
2854
|
-
j = i + 1;
|
|
2855
|
-
index = ruleText.indexOf('"', j) + 1;
|
|
2856
|
-
if (!index) {
|
|
2857
|
-
throw '" is missing';
|
|
2858
|
-
}
|
|
2859
|
-
buffer += ruleText.slice(i, index);
|
|
2860
|
-
i = index - 1;
|
|
2861
|
-
break;
|
|
2862
|
-
|
|
2863
|
-
case "'":
|
|
2864
|
-
j = i + 1;
|
|
2865
|
-
index = ruleText.indexOf("'", j) + 1;
|
|
2866
|
-
if (!index) {
|
|
2867
|
-
throw "' is missing";
|
|
2868
|
-
}
|
|
2869
|
-
buffer += ruleText.slice(i, index);
|
|
2870
|
-
i = index - 1;
|
|
2871
|
-
break;
|
|
2872
|
-
|
|
2873
|
-
// Comment
|
|
2874
|
-
case "/":
|
|
2875
|
-
if (ruleText.charAt(i + 1) === "*") {
|
|
2876
|
-
i += 2;
|
|
2877
|
-
index = ruleText.indexOf("*/", i);
|
|
2878
|
-
if (index === -1) {
|
|
2879
|
-
throw new SyntaxError("Missing */");
|
|
2880
|
-
} else {
|
|
2881
|
-
i = index + 1;
|
|
2882
|
-
}
|
|
2883
|
-
} else {
|
|
2884
|
-
buffer += character;
|
|
2885
|
-
}
|
|
2886
|
-
break;
|
|
2887
|
-
|
|
2888
|
-
case "{":
|
|
2889
|
-
if (state === "selector") {
|
|
2890
|
-
pageRule.selectorText = buffer.trim();
|
|
2891
|
-
buffer = "";
|
|
2892
|
-
state = "name";
|
|
2893
|
-
}
|
|
2894
|
-
break;
|
|
2895
|
-
|
|
2896
|
-
case ":":
|
|
2897
|
-
if (state === "name") {
|
|
2898
|
-
name = buffer.trim();
|
|
2899
|
-
buffer = "";
|
|
2900
|
-
state = "value";
|
|
2901
|
-
} else {
|
|
2902
|
-
buffer += character;
|
|
2903
|
-
}
|
|
2904
|
-
break;
|
|
2905
|
-
|
|
2906
|
-
case "!":
|
|
2907
|
-
if (state === "value" && ruleText.indexOf("!important", i) === i) {
|
|
2908
|
-
priority = "important";
|
|
2909
|
-
i += "important".length;
|
|
2910
|
-
} else {
|
|
2911
|
-
buffer += character;
|
|
2912
|
-
}
|
|
2913
|
-
break;
|
|
2914
|
-
|
|
2915
|
-
case ";":
|
|
2916
|
-
if (state === "value") {
|
|
2917
|
-
pageRule.style.setProperty(name, buffer.trim(), priority);
|
|
2918
|
-
priority = "";
|
|
2919
|
-
buffer = "";
|
|
2920
|
-
state = "name";
|
|
2921
|
-
} else {
|
|
2922
|
-
buffer += character;
|
|
2923
|
-
}
|
|
2924
|
-
break;
|
|
2925
|
-
|
|
2926
|
-
case "}":
|
|
2927
|
-
if (state === "value") {
|
|
2928
|
-
pageRule.style.setProperty(name, buffer.trim(), priority);
|
|
2929
|
-
priority = "";
|
|
2930
|
-
buffer = "";
|
|
2931
|
-
} else if (state === "name") {
|
|
2932
|
-
break;
|
|
2933
|
-
} else {
|
|
2934
|
-
buffer += character;
|
|
2935
|
-
}
|
|
2936
|
-
state = "selector";
|
|
2937
|
-
break;
|
|
2938
|
-
|
|
2939
|
-
default:
|
|
2940
|
-
buffer += character;
|
|
2941
|
-
break;
|
|
2942
|
-
|
|
2943
|
-
}
|
|
2944
|
-
}
|
|
2945
|
-
|
|
2946
|
-
return pageRule;
|
|
2947
|
-
|
|
2948
|
-
};
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
2899
|
|
|
2952
2900
|
|
|
2953
2901
|
|
|
@@ -2956,7 +2904,9 @@ CSSOM.CSSPageRule.parse = function(ruleText) {
|
|
|
2956
2904
|
*
|
|
2957
2905
|
* @param {string} token - The CSS string to parse.
|
|
2958
2906
|
* @param {object} [opts] - Optional parsing options.
|
|
2959
|
-
* @param {object} [opts.globalObject] - An optional global object to
|
|
2907
|
+
* @param {object} [opts.globalObject] - @deprecated This property will be removed in the next release. Use CSSOM.setup({ globalObject }) instead. - An optional global object to override globals and window. Useful on jsdom webplatform tests.
|
|
2908
|
+
* @param {Element | ProcessingInstruction} [opts.ownerNode] - The owner node of the stylesheet.
|
|
2909
|
+
* @param {CSSRule} [opts.ownerRule] - The owner rule of the stylesheet.
|
|
2960
2910
|
* @param {CSSOM.CSSStyleSheet} [opts.styleSheet] - Reuse a style sheet instead of creating a new one (e.g. as `parentStyleSheet`)
|
|
2961
2911
|
* @param {CSSOM.CSSRuleList} [opts.cssRules] - Prepare all rules in this list instead of mutating the style sheet continually
|
|
2962
2912
|
* @param {function|boolean} [errorHandler] - Optional error handler function or `true` to use `console.error`.
|
|
@@ -3010,6 +2960,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3010
2960
|
styleSheet = opts.styleSheet;
|
|
3011
2961
|
} else {
|
|
3012
2962
|
styleSheet = new CSSOM.CSSStyleSheet()
|
|
2963
|
+
styleSheet.__constructed = false;
|
|
3013
2964
|
}
|
|
3014
2965
|
|
|
3015
2966
|
var topScope;
|
|
@@ -3020,7 +2971,15 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3020
2971
|
}
|
|
3021
2972
|
|
|
3022
2973
|
if (opts && opts.globalObject) {
|
|
3023
|
-
|
|
2974
|
+
CSSOM.setup({ globalObject: opts.globalObject });
|
|
2975
|
+
}
|
|
2976
|
+
|
|
2977
|
+
if (opts && opts.ownerNode) {
|
|
2978
|
+
styleSheet.__ownerNode = opts.ownerNode;
|
|
2979
|
+
}
|
|
2980
|
+
|
|
2981
|
+
if (opts && opts.ownerRule) {
|
|
2982
|
+
styleSheet.__ownerRule = opts.ownerRule;
|
|
3024
2983
|
}
|
|
3025
2984
|
|
|
3026
2985
|
// @type CSSStyleSheet|CSSMediaRule|CSSContainerRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule
|
|
@@ -3032,7 +2991,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3032
2991
|
var ancestorRules = [];
|
|
3033
2992
|
var prevScope;
|
|
3034
2993
|
|
|
3035
|
-
var name, priority="", styleRule, mediaRule, containerRule, counterStyleRule, supportsRule, importRule, fontFaceRule, keyframesRule, documentRule, hostRule, startingStyleRule, scopeRule, pageRule, layerBlockRule, layerStatementRule, nestedSelectorRule, namespaceRule;
|
|
2994
|
+
var name, priority = "", styleRule, mediaRule, containerRule, counterStyleRule, supportsRule, importRule, fontFaceRule, keyframesRule, documentRule, hostRule, startingStyleRule, scopeRule, pageRule, layerBlockRule, layerStatementRule, nestedSelectorRule, namespaceRule;
|
|
3036
2995
|
|
|
3037
2996
|
// Track defined namespace prefixes for validation
|
|
3038
2997
|
var definedNamespacePrefixes = {};
|
|
@@ -3130,14 +3089,14 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3130
3089
|
var ruleClosingMatch = matchBalancedBlock(str, fromIndex);
|
|
3131
3090
|
if (ruleClosingMatch) {
|
|
3132
3091
|
var ignoreRange = ruleClosingMatch.index + ruleClosingMatch[0].length;
|
|
3133
|
-
i+= ignoreRange;
|
|
3092
|
+
i += ignoreRange;
|
|
3134
3093
|
if (token.charAt(i) === '}') {
|
|
3135
3094
|
i -= 1;
|
|
3136
3095
|
}
|
|
3137
3096
|
} else {
|
|
3138
3097
|
i += str.length;
|
|
3139
3098
|
}
|
|
3140
|
-
return i;
|
|
3099
|
+
return i;
|
|
3141
3100
|
}
|
|
3142
3101
|
|
|
3143
3102
|
/**
|
|
@@ -3147,29 +3106,29 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3147
3106
|
*/
|
|
3148
3107
|
function parseScopePrelude(preludeContent) {
|
|
3149
3108
|
var parts = preludeContent.split(/\s*\)\s*to\s+\(/);
|
|
3150
|
-
|
|
3109
|
+
|
|
3151
3110
|
// Restore the parentheses that were consumed by the split
|
|
3152
3111
|
if (parts.length === 2) {
|
|
3153
3112
|
parts[0] = parts[0] + ')';
|
|
3154
3113
|
parts[1] = '(' + parts[1];
|
|
3155
3114
|
}
|
|
3156
|
-
|
|
3115
|
+
|
|
3157
3116
|
var hasStart = parts[0] &&
|
|
3158
3117
|
parts[0].charAt(0) === '(' &&
|
|
3159
3118
|
parts[0].charAt(parts[0].length - 1) === ')';
|
|
3160
3119
|
var hasEnd = parts[1] &&
|
|
3161
3120
|
parts[1].charAt(0) === '(' &&
|
|
3162
3121
|
parts[1].charAt(parts[1].length - 1) === ')';
|
|
3163
|
-
|
|
3122
|
+
|
|
3164
3123
|
// Handle case: @scope to (<end>)
|
|
3165
3124
|
var hasOnlyEnd = !hasStart &&
|
|
3166
3125
|
!hasEnd &&
|
|
3167
3126
|
parts[0].indexOf('to (') === 0 &&
|
|
3168
3127
|
parts[0].charAt(parts[0].length - 1) === ')';
|
|
3169
|
-
|
|
3128
|
+
|
|
3170
3129
|
var startSelector = '';
|
|
3171
3130
|
var endSelector = '';
|
|
3172
|
-
|
|
3131
|
+
|
|
3173
3132
|
if (hasStart) {
|
|
3174
3133
|
startSelector = parts[0].slice(1, -1).trim();
|
|
3175
3134
|
}
|
|
@@ -3179,7 +3138,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3179
3138
|
if (hasOnlyEnd) {
|
|
3180
3139
|
endSelector = parts[0].slice(4, -1).trim();
|
|
3181
3140
|
}
|
|
3182
|
-
|
|
3141
|
+
|
|
3183
3142
|
return {
|
|
3184
3143
|
startSelector: startSelector,
|
|
3185
3144
|
endSelector: endSelector,
|
|
@@ -3217,11 +3176,11 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3217
3176
|
var inDoubleQuote = false;
|
|
3218
3177
|
var inAttr = false;
|
|
3219
3178
|
var stack = useStack ? [] : null;
|
|
3220
|
-
|
|
3179
|
+
|
|
3221
3180
|
for (var i = 0; i < selector.length; i++) {
|
|
3222
3181
|
var char = selector[i];
|
|
3223
3182
|
var prevChar = i > 0 ? selector[i - 1] : '';
|
|
3224
|
-
|
|
3183
|
+
|
|
3225
3184
|
if (inSingleQuote) {
|
|
3226
3185
|
if (char === "'" && prevChar !== "\\") {
|
|
3227
3186
|
inSingleQuote = false;
|
|
@@ -3272,7 +3231,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3272
3231
|
}
|
|
3273
3232
|
}
|
|
3274
3233
|
}
|
|
3275
|
-
|
|
3234
|
+
|
|
3276
3235
|
// Check if everything is balanced
|
|
3277
3236
|
if (useStack) {
|
|
3278
3237
|
return stack.length === 0 && bracketDepth === 0 && !inSingleQuote && !inDoubleQuote && !inAttr;
|
|
@@ -3322,7 +3281,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3322
3281
|
/(?:^|[\s>+~,\[])cue\s*\(/i,
|
|
3323
3282
|
/(?:^|[\s>+~,\[])cue-region\s*\(/i
|
|
3324
3283
|
];
|
|
3325
|
-
|
|
3284
|
+
|
|
3326
3285
|
for (var i = 0; i < invalidPatterns.length; i++) {
|
|
3327
3286
|
if (invalidPatterns[i].test(selector)) {
|
|
3328
3287
|
return true;
|
|
@@ -3368,7 +3327,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3368
3327
|
isValid = true;
|
|
3369
3328
|
}
|
|
3370
3329
|
}
|
|
3371
|
-
|
|
3330
|
+
|
|
3372
3331
|
// Additional validation for @scope rule
|
|
3373
3332
|
if (isValid && atRuleKey === "@scope") {
|
|
3374
3333
|
var openBraceIndex = ruleSlice.indexOf('{');
|
|
@@ -3387,7 +3346,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3387
3346
|
var hasStart = parsedScopePrelude.hasStart;
|
|
3388
3347
|
var hasEnd = parsedScopePrelude.hasEnd;
|
|
3389
3348
|
var hasOnlyEnd = parsedScopePrelude.hasOnlyEnd;
|
|
3390
|
-
|
|
3349
|
+
|
|
3391
3350
|
// Validation rules for @scope:
|
|
3392
3351
|
// 1. Empty selectors in parentheses are invalid: @scope () {} or @scope (.a) to () {}
|
|
3393
3352
|
if ((hasStart && startSelector === '') || (hasEnd && endSelector === '') || (hasOnlyEnd && endSelector === '')) {
|
|
@@ -3423,13 +3382,13 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3423
3382
|
if (openBraceIndex !== -1) {
|
|
3424
3383
|
// Extract the rule prelude (everything between the at-rule and {)
|
|
3425
3384
|
var rulePrelude = ruleSlice.slice(0, openBraceIndex).trim();
|
|
3426
|
-
|
|
3385
|
+
|
|
3427
3386
|
// Skip past at-rule keyword and whitespace
|
|
3428
3387
|
var preludeContent = rulePrelude.slice("@page".length).trim();
|
|
3429
3388
|
|
|
3430
3389
|
if (preludeContent.length > 0) {
|
|
3431
3390
|
var trimmedValue = preludeContent.trim();
|
|
3432
|
-
|
|
3391
|
+
|
|
3433
3392
|
// Empty selector is valid for @page
|
|
3434
3393
|
if (trimmedValue !== '') {
|
|
3435
3394
|
// Parse @page selectorText for page name and pseudo-pages
|
|
@@ -3453,7 +3412,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3453
3412
|
|
|
3454
3413
|
// Validate pseudo-pages if present
|
|
3455
3414
|
if (pseudoPages) {
|
|
3456
|
-
var pseudos = pseudoPages.split(':').filter(function(p) { return p; });
|
|
3415
|
+
var pseudos = pseudoPages.split(':').filter(function (p) { return p; });
|
|
3457
3416
|
var validPseudos = ['left', 'right', 'first', 'blank'];
|
|
3458
3417
|
var allValid = true;
|
|
3459
3418
|
for (var j = 0; j < pseudos.length; j++) {
|
|
@@ -3462,7 +3421,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3462
3421
|
break;
|
|
3463
3422
|
}
|
|
3464
3423
|
}
|
|
3465
|
-
|
|
3424
|
+
|
|
3466
3425
|
if (!allValid) {
|
|
3467
3426
|
isValid = false;
|
|
3468
3427
|
}
|
|
@@ -3471,15 +3430,15 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3471
3430
|
isValid = false;
|
|
3472
3431
|
}
|
|
3473
3432
|
}
|
|
3474
|
-
|
|
3433
|
+
|
|
3475
3434
|
}
|
|
3476
3435
|
}
|
|
3477
3436
|
}
|
|
3478
|
-
|
|
3437
|
+
|
|
3479
3438
|
if (!isValid) {
|
|
3480
3439
|
// If it's invalid the browser will simply ignore the entire invalid block
|
|
3481
3440
|
// Use regex to find the closing brace of the invalid rule
|
|
3482
|
-
|
|
3441
|
+
|
|
3483
3442
|
// Regex used above is not ES5 compliant. Using alternative.
|
|
3484
3443
|
// var ruleStatementMatch = ruleSlice.match(atRulesStatemenRegExp); //
|
|
3485
3444
|
var ruleStatementMatch = atRulesStatemenRegExpES5Alternative(ruleSlice);
|
|
@@ -3494,7 +3453,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3494
3453
|
// Check if there's a semicolon before the invalid at-rule and the first opening brace
|
|
3495
3454
|
if (atRuleKey === "@layer") {
|
|
3496
3455
|
var ruleSemicolonAndOpeningBraceMatch = ruleSlice.match(forwardRuleSemicolonAndOpeningBraceRegExp);
|
|
3497
|
-
if (ruleSemicolonAndOpeningBraceMatch && ruleSemicolonAndOpeningBraceMatch[1] === ";"
|
|
3456
|
+
if (ruleSemicolonAndOpeningBraceMatch && ruleSemicolonAndOpeningBraceMatch[1] === ";") {
|
|
3498
3457
|
// Ignore the rule block until the semicolon
|
|
3499
3458
|
i += ruleSemicolonAndOpeningBraceMatch.index + ruleSemicolonAndOpeningBraceMatch[0].length;
|
|
3500
3459
|
state = "before-selector";
|
|
@@ -3512,7 +3471,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3512
3471
|
|
|
3513
3472
|
// Helper functions for looseSelectorValidator
|
|
3514
3473
|
// Defined outside to avoid recreation on every validation call
|
|
3515
|
-
|
|
3474
|
+
|
|
3516
3475
|
/**
|
|
3517
3476
|
* Check if character is a valid identifier start
|
|
3518
3477
|
* @param {string} c - Character to check
|
|
@@ -3584,19 +3543,19 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3584
3543
|
// Helper: Parse namespace prefix (optional)
|
|
3585
3544
|
function parseNamespace() {
|
|
3586
3545
|
var start = i;
|
|
3587
|
-
|
|
3546
|
+
|
|
3588
3547
|
// Match: *| or identifier| or |
|
|
3589
3548
|
if (i < len && selector[i] === '*') {
|
|
3590
3549
|
i++;
|
|
3591
3550
|
} else if (i < len && (isIdentStart(selector[i]) || selector[i] === '\\')) {
|
|
3592
3551
|
parseIdentifier();
|
|
3593
3552
|
}
|
|
3594
|
-
|
|
3553
|
+
|
|
3595
3554
|
if (i < len && selector[i] === '|') {
|
|
3596
3555
|
i++;
|
|
3597
3556
|
return true;
|
|
3598
3557
|
}
|
|
3599
|
-
|
|
3558
|
+
|
|
3600
3559
|
// Rollback if no pipe found
|
|
3601
3560
|
i = start;
|
|
3602
3561
|
return false;
|
|
@@ -3607,15 +3566,15 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3607
3566
|
if (i >= len || selector[i] !== '(') {
|
|
3608
3567
|
return false;
|
|
3609
3568
|
}
|
|
3610
|
-
|
|
3569
|
+
|
|
3611
3570
|
i++; // Skip opening paren
|
|
3612
3571
|
var depth = 1;
|
|
3613
3572
|
var inString = false;
|
|
3614
3573
|
var stringChar = '';
|
|
3615
|
-
|
|
3574
|
+
|
|
3616
3575
|
while (i < len && depth > 0) {
|
|
3617
3576
|
var c = selector[i];
|
|
3618
|
-
|
|
3577
|
+
|
|
3619
3578
|
if (c === '\\' && i + 1 < len) {
|
|
3620
3579
|
i += 2; // Skip escaped character
|
|
3621
3580
|
} else if (!inString && (c === '"' || c === '\'')) {
|
|
@@ -3635,7 +3594,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3635
3594
|
i++;
|
|
3636
3595
|
}
|
|
3637
3596
|
}
|
|
3638
|
-
|
|
3597
|
+
|
|
3639
3598
|
return depth === 0;
|
|
3640
3599
|
}
|
|
3641
3600
|
|
|
@@ -3737,7 +3696,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3737
3696
|
// Match type selector with optional namespace: [namespace|]identifier
|
|
3738
3697
|
else if (i < len && (isIdentStart(selector[i]) || selector[i] === '\\' || selector[i] === '*' || selector[i] === '|')) {
|
|
3739
3698
|
parseNamespace(); // Optional namespace prefix
|
|
3740
|
-
|
|
3699
|
+
|
|
3741
3700
|
if (i < len && selector[i] === '*') {
|
|
3742
3701
|
i++; // Universal selector
|
|
3743
3702
|
hasMatchedComponent = true;
|
|
@@ -3813,36 +3772,36 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3813
3772
|
// Pseudo-classes like :lang(), :dir(), :nth-*() should not accept quoted strings
|
|
3814
3773
|
// Using iterative parsing instead of regex to avoid exponential backtracking
|
|
3815
3774
|
var noQuotesPseudos = ['lang', 'dir', 'nth-child', 'nth-last-child', 'nth-of-type', 'nth-last-of-type'];
|
|
3816
|
-
|
|
3775
|
+
|
|
3817
3776
|
for (var idx = 0; idx < selector.length; idx++) {
|
|
3818
3777
|
// Look for pseudo-class/element start
|
|
3819
3778
|
if (selector[idx] === ':') {
|
|
3820
3779
|
var pseudoStart = idx;
|
|
3821
3780
|
idx++;
|
|
3822
|
-
|
|
3781
|
+
|
|
3823
3782
|
// Skip second colon for pseudo-elements
|
|
3824
3783
|
if (idx < selector.length && selector[idx] === ':') {
|
|
3825
3784
|
idx++;
|
|
3826
3785
|
}
|
|
3827
|
-
|
|
3786
|
+
|
|
3828
3787
|
// Extract pseudo name
|
|
3829
3788
|
var nameStart = idx;
|
|
3830
3789
|
while (idx < selector.length && /[a-zA-Z0-9\-]/.test(selector[idx])) {
|
|
3831
3790
|
idx++;
|
|
3832
3791
|
}
|
|
3833
|
-
|
|
3792
|
+
|
|
3834
3793
|
if (idx === nameStart) {
|
|
3835
3794
|
continue; // No name found
|
|
3836
3795
|
}
|
|
3837
|
-
|
|
3796
|
+
|
|
3838
3797
|
var pseudoName = selector.substring(nameStart, idx).toLowerCase();
|
|
3839
|
-
|
|
3798
|
+
|
|
3840
3799
|
// Check if this pseudo has arguments
|
|
3841
3800
|
if (idx < selector.length && selector[idx] === '(') {
|
|
3842
3801
|
idx++;
|
|
3843
3802
|
var contentStart = idx;
|
|
3844
3803
|
var depth = 1;
|
|
3845
|
-
|
|
3804
|
+
|
|
3846
3805
|
// Find matching closing paren (handle nesting)
|
|
3847
3806
|
while (idx < selector.length && depth > 0) {
|
|
3848
3807
|
if (selector[idx] === '\\') {
|
|
@@ -3857,10 +3816,10 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3857
3816
|
idx++;
|
|
3858
3817
|
}
|
|
3859
3818
|
}
|
|
3860
|
-
|
|
3819
|
+
|
|
3861
3820
|
if (depth === 0) {
|
|
3862
3821
|
var pseudoContent = selector.substring(contentStart, idx - 1);
|
|
3863
|
-
|
|
3822
|
+
|
|
3864
3823
|
// Check if this pseudo should not have quoted strings
|
|
3865
3824
|
for (var j = 0; j < noQuotesPseudos.length; j++) {
|
|
3866
3825
|
if (pseudoName === noQuotesPseudos[j] && /['"]/.test(pseudoContent)) {
|
|
@@ -3875,7 +3834,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3875
3834
|
// Use the iterative validator to avoid regex backtracking issues
|
|
3876
3835
|
return looseSelectorValidator(selector);
|
|
3877
3836
|
}
|
|
3878
|
-
|
|
3837
|
+
|
|
3879
3838
|
/**
|
|
3880
3839
|
* Regular expression to match CSS pseudo-classes with arguments.
|
|
3881
3840
|
*
|
|
@@ -3894,7 +3853,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3894
3853
|
*
|
|
3895
3854
|
* REPLACED WITH FUNCTION to avoid exponential backtracking.
|
|
3896
3855
|
*/
|
|
3897
|
-
|
|
3856
|
+
|
|
3898
3857
|
/**
|
|
3899
3858
|
* Extract pseudo-classes with arguments from a selector using iterative parsing.
|
|
3900
3859
|
* Replaces the previous globalPseudoClassRegExp to avoid exponential backtracking.
|
|
@@ -3910,30 +3869,30 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3910
3869
|
*/
|
|
3911
3870
|
function extractPseudoClasses(selector) {
|
|
3912
3871
|
var matches = [];
|
|
3913
|
-
|
|
3872
|
+
|
|
3914
3873
|
for (var i = 0; i < selector.length; i++) {
|
|
3915
3874
|
// Look for pseudo-class start (single or double colon)
|
|
3916
3875
|
if (selector[i] === ':') {
|
|
3917
3876
|
var pseudoStart = i;
|
|
3918
3877
|
i++;
|
|
3919
|
-
|
|
3878
|
+
|
|
3920
3879
|
// Skip second colon for pseudo-elements (::)
|
|
3921
3880
|
if (i < selector.length && selector[i] === ':') {
|
|
3922
3881
|
i++;
|
|
3923
3882
|
}
|
|
3924
|
-
|
|
3883
|
+
|
|
3925
3884
|
// Extract pseudo name
|
|
3926
3885
|
var nameStart = i;
|
|
3927
3886
|
while (i < selector.length && /[a-zA-Z\-]/.test(selector[i])) {
|
|
3928
3887
|
i++;
|
|
3929
3888
|
}
|
|
3930
|
-
|
|
3889
|
+
|
|
3931
3890
|
if (i === nameStart) {
|
|
3932
3891
|
continue; // No name found
|
|
3933
3892
|
}
|
|
3934
|
-
|
|
3893
|
+
|
|
3935
3894
|
var pseudoName = selector.substring(nameStart, i);
|
|
3936
|
-
|
|
3895
|
+
|
|
3937
3896
|
// Check if this pseudo has arguments
|
|
3938
3897
|
if (i < selector.length && selector[i] === '(') {
|
|
3939
3898
|
i++;
|
|
@@ -3941,11 +3900,11 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3941
3900
|
var depth = 1;
|
|
3942
3901
|
var inSingleQuote = false;
|
|
3943
3902
|
var inDoubleQuote = false;
|
|
3944
|
-
|
|
3903
|
+
|
|
3945
3904
|
// Find matching closing paren (handle nesting and strings)
|
|
3946
3905
|
while (i < selector.length && depth > 0) {
|
|
3947
3906
|
var ch = selector[i];
|
|
3948
|
-
|
|
3907
|
+
|
|
3949
3908
|
if (ch === '\\') {
|
|
3950
3909
|
i += 2; // Skip escaped character
|
|
3951
3910
|
} else if (ch === "'" && !inDoubleQuote) {
|
|
@@ -3964,21 +3923,21 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
3964
3923
|
i++;
|
|
3965
3924
|
}
|
|
3966
3925
|
}
|
|
3967
|
-
|
|
3926
|
+
|
|
3968
3927
|
if (depth === 0) {
|
|
3969
3928
|
var pseudoArgs = selector.substring(argsStart, i - 1);
|
|
3970
3929
|
var fullMatch = selector.substring(pseudoStart, i);
|
|
3971
|
-
|
|
3930
|
+
|
|
3972
3931
|
// Store match in same format as regex: [fullMatch, pseudoName, pseudoArgs, startIndex]
|
|
3973
3932
|
matches.push([fullMatch, pseudoName, pseudoArgs, pseudoStart]);
|
|
3974
3933
|
}
|
|
3975
|
-
|
|
3934
|
+
|
|
3976
3935
|
// Move back one since loop will increment
|
|
3977
3936
|
i--;
|
|
3978
3937
|
}
|
|
3979
3938
|
}
|
|
3980
3939
|
}
|
|
3981
|
-
|
|
3940
|
+
|
|
3982
3941
|
return matches;
|
|
3983
3942
|
}
|
|
3984
3943
|
|
|
@@ -4082,6 +4041,23 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
4082
4041
|
var pseudoClass = pseudoClassMatches[j][1];
|
|
4083
4042
|
if (selectorListPseudoClasses.hasOwnProperty(pseudoClass)) {
|
|
4084
4043
|
var nestedSelectors = parseAndSplitNestedSelectors(pseudoClassMatches[j][2]);
|
|
4044
|
+
|
|
4045
|
+
// Check if ANY selector in the list contains & (nesting selector)
|
|
4046
|
+
// If so, skip validation for the entire selector list since & will be replaced at runtime
|
|
4047
|
+
var hasAmpersand = false;
|
|
4048
|
+
for (var k = 0; k < nestedSelectors.length; k++) {
|
|
4049
|
+
if (/&/.test(nestedSelectors[k])) {
|
|
4050
|
+
hasAmpersand = true;
|
|
4051
|
+
break;
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
|
|
4055
|
+
// If any selector has &, skip validation for this entire pseudo-class
|
|
4056
|
+
if (hasAmpersand) {
|
|
4057
|
+
continue;
|
|
4058
|
+
}
|
|
4059
|
+
|
|
4060
|
+
// Otherwise, validate each selector normally
|
|
4085
4061
|
for (var i = 0; i < nestedSelectors.length; i++) {
|
|
4086
4062
|
var nestedSelector = nestedSelectors[i];
|
|
4087
4063
|
if (!validatedSelectorsCache.hasOwnProperty(nestedSelector)) {
|
|
@@ -4118,10 +4094,10 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
4118
4094
|
var inAttr = false;
|
|
4119
4095
|
var inSingleQuote = false;
|
|
4120
4096
|
var inDoubleQuote = false;
|
|
4121
|
-
|
|
4097
|
+
|
|
4122
4098
|
for (var i = 0; i < selector.length; i++) {
|
|
4123
4099
|
var char = selector[i];
|
|
4124
|
-
|
|
4100
|
+
|
|
4125
4101
|
if (inSingleQuote) {
|
|
4126
4102
|
if (char === "'" && selector[i - 1] !== "\\") {
|
|
4127
4103
|
inSingleQuote = false;
|
|
@@ -4148,18 +4124,18 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
4148
4124
|
}
|
|
4149
4125
|
}
|
|
4150
4126
|
}
|
|
4151
|
-
|
|
4127
|
+
|
|
4152
4128
|
if (pipeIndex === -1) {
|
|
4153
4129
|
return true; // No namespace, always valid
|
|
4154
4130
|
}
|
|
4155
|
-
|
|
4131
|
+
|
|
4156
4132
|
var namespacePrefix = selector.substring(0, pipeIndex);
|
|
4157
|
-
|
|
4133
|
+
|
|
4158
4134
|
// Universal namespace (*|) and default namespace (|) are always valid
|
|
4159
4135
|
if (namespacePrefix === '*' || namespacePrefix === '') {
|
|
4160
4136
|
return true;
|
|
4161
4137
|
}
|
|
4162
|
-
|
|
4138
|
+
|
|
4163
4139
|
// Check if the custom namespace prefix is defined
|
|
4164
4140
|
return definedNamespacePrefixes.hasOwnProperty(namespacePrefix);
|
|
4165
4141
|
}
|
|
@@ -4168,22 +4144,92 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
4168
4144
|
* Processes a CSS selector text
|
|
4169
4145
|
*
|
|
4170
4146
|
* @param {string} selectorText - The CSS selector text to process
|
|
4171
|
-
* @returns {string} The processed selector text with normalized whitespace
|
|
4147
|
+
* @returns {string} The processed selector text with normalized whitespace and invalid selectors removed
|
|
4172
4148
|
*/
|
|
4173
4149
|
function processSelectorText(selectorText) {
|
|
4174
|
-
//
|
|
4175
|
-
|
|
4176
|
-
// TODO: Move these validation logic to a shared function to be reused in CSSStyleRule.selectorText setter
|
|
4177
|
-
|
|
4178
|
-
/**
|
|
4179
|
-
* Normalizes whitespace and preserving quoted strings.
|
|
4180
|
-
* Replaces all newline characters (CRLF, CR, or LF) with spaces while keeping quoted
|
|
4181
|
-
* strings (single or double quotes) intact, including any escaped characters within them.
|
|
4182
|
-
*/
|
|
4183
|
-
return selectorText.replace(/(['"])(?:\\.|[^\\])*?\1|(\r\n|\r|\n)/g, function(match, _, newline) {
|
|
4150
|
+
// Normalize whitespace first
|
|
4151
|
+
var normalized = selectorText.replace(/(['"])(?:\\.|[^\\])*?\1|(\r\n|\r|\n)/g, function (match, _, newline) {
|
|
4184
4152
|
if (newline) return " ";
|
|
4185
4153
|
return match;
|
|
4186
4154
|
});
|
|
4155
|
+
|
|
4156
|
+
// Recursively process pseudo-classes to handle nesting
|
|
4157
|
+
return processNestedPseudoClasses(normalized);
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4160
|
+
/**
|
|
4161
|
+
* Recursively processes pseudo-classes to filter invalid selectors
|
|
4162
|
+
*
|
|
4163
|
+
* @param {string} selectorText - The CSS selector text to process
|
|
4164
|
+
* @param {number} depth - Current recursion depth (to prevent infinite loops)
|
|
4165
|
+
* @returns {string} The processed selector text with invalid selectors removed
|
|
4166
|
+
*/
|
|
4167
|
+
function processNestedPseudoClasses(selectorText, depth) {
|
|
4168
|
+
// Prevent infinite recursion
|
|
4169
|
+
if (typeof depth === 'undefined') {
|
|
4170
|
+
depth = 0;
|
|
4171
|
+
}
|
|
4172
|
+
if (depth > 10) {
|
|
4173
|
+
return selectorText;
|
|
4174
|
+
}
|
|
4175
|
+
|
|
4176
|
+
var pseudoClassMatches = extractPseudoClasses(selectorText);
|
|
4177
|
+
|
|
4178
|
+
// If no pseudo-classes found, return as-is
|
|
4179
|
+
if (pseudoClassMatches.length === 0) {
|
|
4180
|
+
return selectorText;
|
|
4181
|
+
}
|
|
4182
|
+
|
|
4183
|
+
// Build result by processing matches from right to left (to preserve positions)
|
|
4184
|
+
var result = selectorText;
|
|
4185
|
+
|
|
4186
|
+
for (var j = pseudoClassMatches.length - 1; j >= 0; j--) {
|
|
4187
|
+
var pseudoClass = pseudoClassMatches[j][1];
|
|
4188
|
+
if (selectorListPseudoClasses.hasOwnProperty(pseudoClass)) {
|
|
4189
|
+
var fullMatch = pseudoClassMatches[j][0];
|
|
4190
|
+
var pseudoArgs = pseudoClassMatches[j][2];
|
|
4191
|
+
var matchStart = pseudoClassMatches[j][3];
|
|
4192
|
+
|
|
4193
|
+
// Check if ANY selector contains & BEFORE processing
|
|
4194
|
+
var nestedSelectorsRaw = parseAndSplitNestedSelectors(pseudoArgs);
|
|
4195
|
+
var hasAmpersand = false;
|
|
4196
|
+
for (var k = 0; k < nestedSelectorsRaw.length; k++) {
|
|
4197
|
+
if (/&/.test(nestedSelectorsRaw[k])) {
|
|
4198
|
+
hasAmpersand = true;
|
|
4199
|
+
break;
|
|
4200
|
+
}
|
|
4201
|
+
}
|
|
4202
|
+
|
|
4203
|
+
// If & is present, skip all processing (keep everything unchanged)
|
|
4204
|
+
if (hasAmpersand) {
|
|
4205
|
+
continue;
|
|
4206
|
+
}
|
|
4207
|
+
|
|
4208
|
+
// Recursively process the arguments
|
|
4209
|
+
var processedArgs = processNestedPseudoClasses(pseudoArgs, depth + 1);
|
|
4210
|
+
var nestedSelectors = parseAndSplitNestedSelectors(processedArgs);
|
|
4211
|
+
|
|
4212
|
+
// Filter out invalid selectors
|
|
4213
|
+
var validSelectors = [];
|
|
4214
|
+
for (var i = 0; i < nestedSelectors.length; i++) {
|
|
4215
|
+
var nestedSelector = nestedSelectors[i];
|
|
4216
|
+
if (basicSelectorValidator(nestedSelector)) {
|
|
4217
|
+
validSelectors.push(nestedSelector);
|
|
4218
|
+
}
|
|
4219
|
+
}
|
|
4220
|
+
|
|
4221
|
+
// Reconstruct the pseudo-class with only valid selectors
|
|
4222
|
+
var newArgs = validSelectors.join(', ');
|
|
4223
|
+
var newPseudoClass = ':' + pseudoClass + '(' + newArgs + ')';
|
|
4224
|
+
|
|
4225
|
+
// Replace in the result string using position (processing right to left preserves positions)
|
|
4226
|
+
result = result.substring(0, matchStart) + newPseudoClass + result.substring(matchStart + fullMatch.length);
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
|
|
4230
|
+
return result;
|
|
4231
|
+
|
|
4232
|
+
return normalized;
|
|
4187
4233
|
}
|
|
4188
4234
|
|
|
4189
4235
|
/**
|
|
@@ -4197,6 +4243,12 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
4197
4243
|
// TODO: The same validations here needs to be reused in CSSStyleRule.selectorText setter
|
|
4198
4244
|
// TODO: Move these validation logic to a shared function to be reused in CSSStyleRule.selectorText setter
|
|
4199
4245
|
|
|
4246
|
+
// Check for empty selector lists in pseudo-classes (e.g., :is(), :not(), :where(), :has())
|
|
4247
|
+
// These are invalid after filtering out invalid selectors
|
|
4248
|
+
if (/:(?:is|not|where|has)\(\s*\)/.test(selectorText)) {
|
|
4249
|
+
return false;
|
|
4250
|
+
}
|
|
4251
|
+
|
|
4200
4252
|
// Check for newlines inside single or double quotes using regex
|
|
4201
4253
|
// This matches any quoted string (single or double) containing a newline
|
|
4202
4254
|
var quotedNewlineRegExp = /(['"])(?:\\.|[^\\])*?\1/g;
|
|
@@ -4236,12 +4288,22 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
4236
4288
|
// Print the error but continue parsing the sheet
|
|
4237
4289
|
try {
|
|
4238
4290
|
throw error;
|
|
4239
|
-
} catch(e) {
|
|
4291
|
+
} catch (e) {
|
|
4240
4292
|
errorHandler && errorHandler(e);
|
|
4241
4293
|
}
|
|
4242
4294
|
};
|
|
4243
4295
|
|
|
4296
|
+
// Helper functions to check character types
|
|
4297
|
+
function isSelectorStartChar(char) {
|
|
4298
|
+
return '.:#&*['.indexOf(char) !== -1;
|
|
4299
|
+
}
|
|
4300
|
+
|
|
4301
|
+
function isWhitespaceChar(char) {
|
|
4302
|
+
return ' \t\n\r'.indexOf(char) !== -1;
|
|
4303
|
+
}
|
|
4304
|
+
|
|
4244
4305
|
var endingIndex = token.length - 1;
|
|
4306
|
+
var initialEndingIndex = endingIndex;
|
|
4245
4307
|
|
|
4246
4308
|
for (var character; (character = token.charAt(i)); i++) {
|
|
4247
4309
|
if (i === endingIndex) {
|
|
@@ -4251,8 +4313,9 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
4251
4313
|
case "layerBlock":
|
|
4252
4314
|
if (character !== ";") {
|
|
4253
4315
|
token += ";";
|
|
4254
|
-
|
|
4316
|
+
endingIndex += 1;
|
|
4255
4317
|
}
|
|
4318
|
+
break;
|
|
4256
4319
|
case "value":
|
|
4257
4320
|
if (character !== "}") {
|
|
4258
4321
|
if (character === ";") {
|
|
@@ -4280,7 +4343,7 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
4280
4343
|
}
|
|
4281
4344
|
}
|
|
4282
4345
|
}
|
|
4283
|
-
|
|
4346
|
+
|
|
4284
4347
|
// Handle escape sequences before processing special characters
|
|
4285
4348
|
// If we encounter a backslash, add both the backslash and the next character to buffer
|
|
4286
4349
|
// and skip the next iteration to prevent the escaped character from being interpreted
|
|
@@ -4289,813 +4352,991 @@ CSSOM.parse = function parse(token, opts, errorHandler) {
|
|
|
4289
4352
|
i++; // Skip the next character
|
|
4290
4353
|
continue;
|
|
4291
4354
|
}
|
|
4292
|
-
|
|
4293
|
-
switch (character) {
|
|
4294
4355
|
|
|
4295
|
-
|
|
4296
|
-
case "\t":
|
|
4297
|
-
case "\r":
|
|
4298
|
-
case "\n":
|
|
4299
|
-
case "\f":
|
|
4300
|
-
if (SIGNIFICANT_WHITESPACE[state]) {
|
|
4301
|
-
buffer += character;
|
|
4302
|
-
}
|
|
4303
|
-
break;
|
|
4356
|
+
switch (character) {
|
|
4304
4357
|
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
if (
|
|
4311
|
-
|
|
4358
|
+
case " ":
|
|
4359
|
+
case "\t":
|
|
4360
|
+
case "\r":
|
|
4361
|
+
case "\n":
|
|
4362
|
+
case "\f":
|
|
4363
|
+
if (SIGNIFICANT_WHITESPACE[state]) {
|
|
4364
|
+
buffer += character;
|
|
4312
4365
|
}
|
|
4313
|
-
} while (token[index - 2] === '\\');
|
|
4314
|
-
if (index === 0) {
|
|
4315
4366
|
break;
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
state = 'importRule';
|
|
4325
|
-
if (i === endingIndex) {
|
|
4326
|
-
token += ';'
|
|
4367
|
+
|
|
4368
|
+
// String
|
|
4369
|
+
case '"':
|
|
4370
|
+
index = i + 1;
|
|
4371
|
+
do {
|
|
4372
|
+
index = token.indexOf('"', index) + 1;
|
|
4373
|
+
if (!index) {
|
|
4374
|
+
parseError('Unmatched "');
|
|
4327
4375
|
}
|
|
4376
|
+
} while (token[index - 2] === '\\');
|
|
4377
|
+
if (index === 0) {
|
|
4328
4378
|
break;
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4379
|
+
}
|
|
4380
|
+
buffer += token.slice(i, index);
|
|
4381
|
+
i = index - 1;
|
|
4382
|
+
switch (state) {
|
|
4383
|
+
case 'before-value':
|
|
4384
|
+
state = 'value';
|
|
4385
|
+
break;
|
|
4386
|
+
case 'importRule-begin':
|
|
4387
|
+
state = 'importRule';
|
|
4388
|
+
if (i === endingIndex) {
|
|
4389
|
+
token += ';'
|
|
4390
|
+
}
|
|
4391
|
+
break;
|
|
4392
|
+
case 'namespaceRule-begin':
|
|
4393
|
+
state = 'namespaceRule';
|
|
4394
|
+
if (i === endingIndex) {
|
|
4395
|
+
token += ';'
|
|
4396
|
+
}
|
|
4397
|
+
break;
|
|
4398
|
+
}
|
|
4399
|
+
break;
|
|
4400
|
+
|
|
4401
|
+
case "'":
|
|
4402
|
+
index = i + 1;
|
|
4403
|
+
do {
|
|
4404
|
+
index = token.indexOf("'", index) + 1;
|
|
4405
|
+
if (!index) {
|
|
4406
|
+
parseError("Unmatched '");
|
|
4333
4407
|
}
|
|
4408
|
+
} while (token[index - 2] === '\\');
|
|
4409
|
+
if (index === 0) {
|
|
4334
4410
|
break;
|
|
4335
|
-
}
|
|
4336
|
-
break;
|
|
4337
|
-
|
|
4338
|
-
case "'":
|
|
4339
|
-
index = i + 1;
|
|
4340
|
-
do {
|
|
4341
|
-
index = token.indexOf("'", index) + 1;
|
|
4342
|
-
if (!index) {
|
|
4343
|
-
parseError("Unmatched '");
|
|
4344
4411
|
}
|
|
4345
|
-
|
|
4346
|
-
|
|
4412
|
+
buffer += token.slice(i, index);
|
|
4413
|
+
i = index - 1;
|
|
4414
|
+
switch (state) {
|
|
4415
|
+
case 'before-value':
|
|
4416
|
+
state = 'value';
|
|
4417
|
+
break;
|
|
4418
|
+
case 'importRule-begin':
|
|
4419
|
+
state = 'importRule';
|
|
4420
|
+
break;
|
|
4421
|
+
case 'namespaceRule-begin':
|
|
4422
|
+
state = 'namespaceRule';
|
|
4423
|
+
break;
|
|
4424
|
+
}
|
|
4347
4425
|
break;
|
|
4348
|
-
}
|
|
4349
|
-
buffer += token.slice(i, index);
|
|
4350
|
-
i = index - 1;
|
|
4351
|
-
switch (state) {
|
|
4352
|
-
case 'before-value':
|
|
4353
|
-
state = 'value';
|
|
4354
|
-
break;
|
|
4355
|
-
case 'importRule-begin':
|
|
4356
|
-
state = 'importRule';
|
|
4357
|
-
break;
|
|
4358
|
-
case 'namespaceRule-begin':
|
|
4359
|
-
state = 'namespaceRule';
|
|
4360
|
-
break;
|
|
4361
|
-
}
|
|
4362
|
-
break;
|
|
4363
4426
|
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4427
|
+
// Comment
|
|
4428
|
+
case "/":
|
|
4429
|
+
if (token.charAt(i + 1) === "*") {
|
|
4430
|
+
i += 2;
|
|
4431
|
+
index = token.indexOf("*/", i);
|
|
4432
|
+
if (index === -1) {
|
|
4433
|
+
i = token.length - 1;
|
|
4434
|
+
buffer = "";
|
|
4435
|
+
} else {
|
|
4436
|
+
i = index + 1;
|
|
4437
|
+
}
|
|
4372
4438
|
} else {
|
|
4373
|
-
|
|
4439
|
+
buffer += character;
|
|
4374
4440
|
}
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
if (state === "importRule-begin") {
|
|
4379
|
-
buffer += " ";
|
|
4380
|
-
state = "importRule";
|
|
4381
|
-
}
|
|
4382
|
-
if (state === "namespaceRule-begin") {
|
|
4383
|
-
buffer += " ";
|
|
4384
|
-
state = "namespaceRule";
|
|
4385
|
-
}
|
|
4386
|
-
break;
|
|
4387
|
-
|
|
4388
|
-
// At-rule
|
|
4389
|
-
case "@":
|
|
4390
|
-
if (nestedSelectorRule) {
|
|
4391
|
-
if (styleRule && styleRule.constructor.name === "CSSNestedDeclarations") {
|
|
4392
|
-
currentScope.cssRules.push(styleRule);
|
|
4441
|
+
if (state === "importRule-begin") {
|
|
4442
|
+
buffer += " ";
|
|
4443
|
+
state = "importRule";
|
|
4393
4444
|
}
|
|
4394
|
-
if (
|
|
4395
|
-
|
|
4445
|
+
if (state === "namespaceRule-begin") {
|
|
4446
|
+
buffer += " ";
|
|
4447
|
+
state = "namespaceRule";
|
|
4396
4448
|
}
|
|
4397
|
-
nestedSelectorRule = null;
|
|
4398
|
-
}
|
|
4399
|
-
if (token.indexOf("@-moz-document", i) === i) {
|
|
4400
|
-
validateAtRule("@-moz-document", function(){
|
|
4401
|
-
state = "documentRule-begin";
|
|
4402
|
-
documentRule = new CSSOM.CSSDocumentRule();
|
|
4403
|
-
documentRule.__starts = i;
|
|
4404
|
-
i += "-moz-document".length;
|
|
4405
|
-
});
|
|
4406
|
-
buffer = "";
|
|
4407
|
-
break;
|
|
4408
|
-
} else if (token.indexOf("@media", i) === i) {
|
|
4409
|
-
validateAtRule("@media", function(){
|
|
4410
|
-
state = "atBlock";
|
|
4411
|
-
mediaRule = new CSSOM.CSSMediaRule();
|
|
4412
|
-
mediaRule.__starts = i;
|
|
4413
|
-
i += "media".length;
|
|
4414
|
-
});
|
|
4415
|
-
buffer = "";
|
|
4416
|
-
break;
|
|
4417
|
-
} else if (token.indexOf("@container", i) === i) {
|
|
4418
|
-
validateAtRule("@container", function(){
|
|
4419
|
-
state = "containerBlock";
|
|
4420
|
-
containerRule = new CSSOM.CSSContainerRule();
|
|
4421
|
-
containerRule.__starts = i;
|
|
4422
|
-
i += "container".length;
|
|
4423
|
-
});
|
|
4424
|
-
buffer = "";
|
|
4425
|
-
break;
|
|
4426
|
-
} else if (token.indexOf("@counter-style", i) === i) {
|
|
4427
|
-
validateAtRule("@counter-style", function(){
|
|
4428
|
-
state = "counterStyleBlock"
|
|
4429
|
-
counterStyleRule = new CSSOM.CSSCounterStyleRule();
|
|
4430
|
-
counterStyleRule.__starts = i;
|
|
4431
|
-
i += "counter-style".length;
|
|
4432
|
-
}, true);
|
|
4433
|
-
buffer = "";
|
|
4434
|
-
break;
|
|
4435
|
-
} else if (token.indexOf("@scope", i) === i) {
|
|
4436
|
-
validateAtRule("@scope", function(){
|
|
4437
|
-
state = "scopeBlock";
|
|
4438
|
-
scopeRule = new CSSOM.CSSScopeRule();
|
|
4439
|
-
scopeRule.__starts = i;
|
|
4440
|
-
i += "scope".length;
|
|
4441
|
-
});
|
|
4442
|
-
buffer = "";
|
|
4443
|
-
break;
|
|
4444
|
-
} else if (token.indexOf("@layer", i) === i) {
|
|
4445
|
-
validateAtRule("@layer", function(){
|
|
4446
|
-
state = "layerBlock"
|
|
4447
|
-
layerBlockRule = new CSSOM.CSSLayerBlockRule();
|
|
4448
|
-
layerBlockRule.__starts = i;
|
|
4449
|
-
i += "layer".length;
|
|
4450
|
-
});
|
|
4451
|
-
buffer = "";
|
|
4452
|
-
break;
|
|
4453
|
-
} else if (token.indexOf("@page", i) === i) {
|
|
4454
|
-
validateAtRule("@page", function(){
|
|
4455
|
-
state = "pageBlock"
|
|
4456
|
-
pageRule = new CSSOM.CSSPageRule();
|
|
4457
|
-
pageRule.__starts = i;
|
|
4458
|
-
i += "page".length;
|
|
4459
|
-
});
|
|
4460
|
-
buffer = "";
|
|
4461
|
-
break;
|
|
4462
|
-
} else if (token.indexOf("@supports", i) === i) {
|
|
4463
|
-
validateAtRule("@supports", function(){
|
|
4464
|
-
state = "conditionBlock";
|
|
4465
|
-
supportsRule = new CSSOM.CSSSupportsRule();
|
|
4466
|
-
supportsRule.__starts = i;
|
|
4467
|
-
i += "supports".length;
|
|
4468
|
-
});
|
|
4469
|
-
buffer = "";
|
|
4470
|
-
break;
|
|
4471
|
-
} else if (token.indexOf("@host", i) === i) {
|
|
4472
|
-
validateAtRule("@host", function(){
|
|
4473
|
-
state = "hostRule-begin";
|
|
4474
|
-
i += "host".length;
|
|
4475
|
-
hostRule = new CSSOM.CSSHostRule();
|
|
4476
|
-
hostRule.__starts = i;
|
|
4477
|
-
});
|
|
4478
|
-
buffer = "";
|
|
4479
|
-
break;
|
|
4480
|
-
} else if (token.indexOf("@starting-style", i) === i) {
|
|
4481
|
-
validateAtRule("@starting-style", function(){
|
|
4482
|
-
state = "startingStyleRule-begin";
|
|
4483
|
-
i += "starting-style".length;
|
|
4484
|
-
startingStyleRule = new CSSOM.CSSStartingStyleRule();
|
|
4485
|
-
startingStyleRule.__starts = i;
|
|
4486
|
-
});
|
|
4487
|
-
buffer = "";
|
|
4488
4449
|
break;
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
state = "fontFaceRule-begin";
|
|
4509
|
-
i += "font-face".length;
|
|
4510
|
-
fontFaceRule = new CSSOM.CSSFontFaceRule();
|
|
4511
|
-
fontFaceRule.__starts = i;
|
|
4512
|
-
}, true);
|
|
4513
|
-
break;
|
|
4514
|
-
} else {
|
|
4515
|
-
atKeyframesRegExp.lastIndex = i;
|
|
4516
|
-
var matchKeyframes = atKeyframesRegExp.exec(token);
|
|
4517
|
-
if (matchKeyframes && matchKeyframes.index === i) {
|
|
4518
|
-
state = "keyframesRule-begin";
|
|
4519
|
-
keyframesRule = new CSSOM.CSSKeyframesRule();
|
|
4520
|
-
keyframesRule.__starts = i;
|
|
4521
|
-
keyframesRule._vendorPrefix = matchKeyframes[1]; // Will come out as undefined if no prefix was found
|
|
4522
|
-
i += matchKeyframes[0].length - 1;
|
|
4450
|
+
|
|
4451
|
+
// At-rule
|
|
4452
|
+
case "@":
|
|
4453
|
+
if (nestedSelectorRule) {
|
|
4454
|
+
if (styleRule && styleRule.constructor.name === "CSSNestedDeclarations") {
|
|
4455
|
+
currentScope.cssRules.push(styleRule);
|
|
4456
|
+
}
|
|
4457
|
+
if (nestedSelectorRule.parentRule && nestedSelectorRule.parentRule.constructor.name === "CSSStyleRule") {
|
|
4458
|
+
styleRule = nestedSelectorRule.parentRule;
|
|
4459
|
+
}
|
|
4460
|
+
// Don't reset nestedSelectorRule here - preserve it through @-rules
|
|
4461
|
+
}
|
|
4462
|
+
if (token.indexOf("@-moz-document", i) === i) {
|
|
4463
|
+
validateAtRule("@-moz-document", function () {
|
|
4464
|
+
state = "documentRule-begin";
|
|
4465
|
+
documentRule = new CSSOM.CSSDocumentRule();
|
|
4466
|
+
documentRule.__starts = i;
|
|
4467
|
+
i += "-moz-document".length;
|
|
4468
|
+
});
|
|
4523
4469
|
buffer = "";
|
|
4524
4470
|
break;
|
|
4525
|
-
} else if (
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4471
|
+
} else if (token.indexOf("@media", i) === i) {
|
|
4472
|
+
validateAtRule("@media", function () {
|
|
4473
|
+
state = "atBlock";
|
|
4474
|
+
mediaRule = new CSSOM.CSSMediaRule();
|
|
4475
|
+
mediaRule.__starts = i;
|
|
4476
|
+
i += "media".length;
|
|
4477
|
+
});
|
|
4478
|
+
buffer = "";
|
|
4479
|
+
break;
|
|
4480
|
+
} else if (token.indexOf("@container", i) === i) {
|
|
4481
|
+
validateAtRule("@container", function () {
|
|
4482
|
+
state = "containerBlock";
|
|
4483
|
+
containerRule = new CSSOM.CSSContainerRule();
|
|
4484
|
+
containerRule.__starts = i;
|
|
4485
|
+
i += "container".length;
|
|
4486
|
+
});
|
|
4487
|
+
buffer = "";
|
|
4488
|
+
break;
|
|
4489
|
+
} else if (token.indexOf("@counter-style", i) === i) {
|
|
4490
|
+
validateAtRule("@counter-style", function () {
|
|
4491
|
+
state = "counterStyleBlock"
|
|
4492
|
+
counterStyleRule = new CSSOM.CSSCounterStyleRule();
|
|
4493
|
+
counterStyleRule.__starts = i;
|
|
4494
|
+
i += "counter-style".length;
|
|
4495
|
+
}, true);
|
|
4496
|
+
buffer = "";
|
|
4497
|
+
break;
|
|
4498
|
+
} else if (token.indexOf("@scope", i) === i) {
|
|
4499
|
+
validateAtRule("@scope", function () {
|
|
4500
|
+
state = "scopeBlock";
|
|
4501
|
+
scopeRule = new CSSOM.CSSScopeRule();
|
|
4502
|
+
scopeRule.__starts = i;
|
|
4503
|
+
i += "scope".length;
|
|
4504
|
+
});
|
|
4505
|
+
buffer = "";
|
|
4506
|
+
break;
|
|
4507
|
+
} else if (token.indexOf("@layer", i) === i) {
|
|
4508
|
+
validateAtRule("@layer", function () {
|
|
4509
|
+
state = "layerBlock"
|
|
4510
|
+
layerBlockRule = new CSSOM.CSSLayerBlockRule();
|
|
4511
|
+
layerBlockRule.__starts = i;
|
|
4512
|
+
i += "layer".length;
|
|
4513
|
+
});
|
|
4514
|
+
buffer = "";
|
|
4515
|
+
break;
|
|
4516
|
+
} else if (token.indexOf("@page", i) === i) {
|
|
4517
|
+
validateAtRule("@page", function () {
|
|
4518
|
+
state = "pageBlock"
|
|
4519
|
+
pageRule = new CSSOM.CSSPageRule();
|
|
4520
|
+
pageRule.__starts = i;
|
|
4521
|
+
i += "page".length;
|
|
4522
|
+
});
|
|
4523
|
+
buffer = "";
|
|
4524
|
+
break;
|
|
4525
|
+
} else if (token.indexOf("@supports", i) === i) {
|
|
4526
|
+
validateAtRule("@supports", function () {
|
|
4527
|
+
state = "conditionBlock";
|
|
4528
|
+
supportsRule = new CSSOM.CSSSupportsRule();
|
|
4529
|
+
supportsRule.__starts = i;
|
|
4530
|
+
i += "supports".length;
|
|
4531
|
+
});
|
|
4532
|
+
buffer = "";
|
|
4533
|
+
break;
|
|
4534
|
+
} else if (token.indexOf("@host", i) === i) {
|
|
4535
|
+
validateAtRule("@host", function () {
|
|
4536
|
+
state = "hostRule-begin";
|
|
4537
|
+
i += "host".length;
|
|
4538
|
+
hostRule = new CSSOM.CSSHostRule();
|
|
4539
|
+
hostRule.__starts = i;
|
|
4540
|
+
});
|
|
4541
|
+
buffer = "";
|
|
4542
|
+
break;
|
|
4543
|
+
} else if (token.indexOf("@starting-style", i) === i) {
|
|
4544
|
+
validateAtRule("@starting-style", function () {
|
|
4545
|
+
state = "startingStyleRule-begin";
|
|
4546
|
+
i += "starting-style".length;
|
|
4547
|
+
startingStyleRule = new CSSOM.CSSStartingStyleRule();
|
|
4548
|
+
startingStyleRule.__starts = i;
|
|
4549
|
+
});
|
|
4550
|
+
buffer = "";
|
|
4551
|
+
break;
|
|
4552
|
+
} else if (token.indexOf("@import", i) === i) {
|
|
4553
|
+
buffer = "";
|
|
4554
|
+
validateAtRule("@import", function () {
|
|
4555
|
+
state = "importRule-begin";
|
|
4556
|
+
i += "import".length;
|
|
4557
|
+
buffer += "@import";
|
|
4558
|
+
}, true);
|
|
4559
|
+
break;
|
|
4560
|
+
} else if (token.indexOf("@namespace", i) === i) {
|
|
4561
|
+
buffer = "";
|
|
4562
|
+
validateAtRule("@namespace", function () {
|
|
4563
|
+
state = "namespaceRule-begin";
|
|
4564
|
+
i += "namespace".length;
|
|
4565
|
+
buffer += "@namespace";
|
|
4566
|
+
}, true);
|
|
4567
|
+
break;
|
|
4568
|
+
} else if (token.indexOf("@font-face", i) === i) {
|
|
4569
|
+
buffer = "";
|
|
4570
|
+
// @font-face can be nested only inside CSSScopeRule or CSSConditionRule
|
|
4571
|
+
// and only if there's no CSSStyleRule in the parent chain
|
|
4572
|
+
var cannotBeNested = true;
|
|
4573
|
+
if (currentScope !== topScope) {
|
|
4574
|
+
var hasStyleRuleInChain = false;
|
|
4575
|
+
var hasValidParent = false;
|
|
4576
|
+
|
|
4577
|
+
// Check currentScope
|
|
4578
|
+
if (currentScope.constructor.name === 'CSSStyleRule') {
|
|
4579
|
+
hasStyleRuleInChain = true;
|
|
4580
|
+
} else if (currentScope instanceof CSSOM.CSSScopeRule || currentScope instanceof CSSOM.CSSConditionRule) {
|
|
4581
|
+
hasValidParent = true;
|
|
4582
|
+
}
|
|
4531
4583
|
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4584
|
+
// Check ancestorRules for CSSStyleRule
|
|
4585
|
+
if (!hasStyleRuleInChain) {
|
|
4586
|
+
for (var j = 0; j < ancestorRules.length; j++) {
|
|
4587
|
+
if (ancestorRules[j].constructor.name === 'CSSStyleRule') {
|
|
4588
|
+
hasStyleRuleInChain = true;
|
|
4589
|
+
break;
|
|
4590
|
+
}
|
|
4591
|
+
if (ancestorRules[j] instanceof CSSOM.CSSScopeRule || ancestorRules[j] instanceof CSSOM.CSSConditionRule) {
|
|
4592
|
+
hasValidParent = true;
|
|
4593
|
+
}
|
|
4594
|
+
}
|
|
4595
|
+
}
|
|
4596
|
+
|
|
4597
|
+
// Allow nesting if we have a valid parent and no style rule in the chain
|
|
4598
|
+
if (hasValidParent && !hasStyleRuleInChain) {
|
|
4599
|
+
cannotBeNested = false;
|
|
4600
|
+
}
|
|
4601
|
+
}
|
|
4602
|
+
validateAtRule("@font-face", function () {
|
|
4603
|
+
state = "fontFaceRule-begin";
|
|
4604
|
+
i += "font-face".length;
|
|
4605
|
+
fontFaceRule = new CSSOM.CSSFontFaceRule();
|
|
4606
|
+
fontFaceRule.__starts = i;
|
|
4607
|
+
}, cannotBeNested);
|
|
4608
|
+
break;
|
|
4609
|
+
} else {
|
|
4610
|
+
atKeyframesRegExp.lastIndex = i;
|
|
4611
|
+
var matchKeyframes = atKeyframesRegExp.exec(token);
|
|
4612
|
+
if (matchKeyframes && matchKeyframes.index === i) {
|
|
4613
|
+
state = "keyframesRule-begin";
|
|
4614
|
+
keyframesRule = new CSSOM.CSSKeyframesRule();
|
|
4615
|
+
keyframesRule.__starts = i;
|
|
4616
|
+
keyframesRule._vendorPrefix = matchKeyframes[1]; // Will come out as undefined if no prefix was found
|
|
4617
|
+
i += matchKeyframes[0].length - 1;
|
|
4546
4618
|
buffer = "";
|
|
4547
|
-
state = "before-selector";
|
|
4548
|
-
i += ruleClosingMatch.index + ruleClosingMatch[0].length;
|
|
4549
4619
|
break;
|
|
4620
|
+
} else if (state === "selector") {
|
|
4621
|
+
state = "atRule";
|
|
4550
4622
|
}
|
|
4551
4623
|
}
|
|
4624
|
+
buffer += character;
|
|
4625
|
+
break;
|
|
4552
4626
|
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
}
|
|
4557
|
-
|
|
4558
|
-
currentScope = parentRule = styleRule;
|
|
4559
|
-
styleRule.selectorText = processSelectorText(buffer.trim());
|
|
4560
|
-
styleRule.style.__starts = i;
|
|
4561
|
-
styleRule.__parentStyleSheet = styleSheet;
|
|
4562
|
-
buffer = "";
|
|
4563
|
-
state = "before-name";
|
|
4564
|
-
} else if (state === "atBlock") {
|
|
4565
|
-
mediaRule.media.mediaText = buffer.trim();
|
|
4566
|
-
|
|
4567
|
-
if (parentRule) {
|
|
4568
|
-
mediaRule.__parentRule = parentRule;
|
|
4569
|
-
pushToAncestorRules(parentRule);
|
|
4570
|
-
}
|
|
4571
|
-
|
|
4572
|
-
currentScope = parentRule = mediaRule;
|
|
4573
|
-
mediaRule.__parentStyleSheet = styleSheet;
|
|
4574
|
-
buffer = "";
|
|
4575
|
-
state = "before-selector";
|
|
4576
|
-
} else if (state === "containerBlock") {
|
|
4577
|
-
containerRule.__conditionText = buffer.trim();
|
|
4578
|
-
|
|
4579
|
-
if (parentRule) {
|
|
4580
|
-
containerRule.__parentRule = parentRule;
|
|
4581
|
-
pushToAncestorRules(parentRule);
|
|
4582
|
-
}
|
|
4583
|
-
currentScope = parentRule = containerRule;
|
|
4584
|
-
containerRule.__parentStyleSheet = styleSheet;
|
|
4585
|
-
buffer = "";
|
|
4586
|
-
state = "before-selector";
|
|
4587
|
-
} else if (state === "counterStyleBlock") {
|
|
4588
|
-
// TODO: Validate counter-style name. At least that it cannot be empty nor multiple
|
|
4589
|
-
counterStyleRule.name = buffer.trim().replace(/\n/g, "");
|
|
4590
|
-
currentScope = parentRule = counterStyleRule;
|
|
4591
|
-
counterStyleRule.__parentStyleSheet = styleSheet;
|
|
4592
|
-
buffer = "";
|
|
4593
|
-
} else if (state === "conditionBlock") {
|
|
4594
|
-
supportsRule.__conditionText = buffer.trim();
|
|
4595
|
-
|
|
4596
|
-
if (parentRule) {
|
|
4597
|
-
supportsRule.__parentRule = parentRule;
|
|
4598
|
-
pushToAncestorRules(parentRule);
|
|
4599
|
-
}
|
|
4600
|
-
|
|
4601
|
-
currentScope = parentRule = supportsRule;
|
|
4602
|
-
supportsRule.__parentStyleSheet = styleSheet;
|
|
4603
|
-
buffer = "";
|
|
4604
|
-
state = "before-selector";
|
|
4605
|
-
} else if (state === "scopeBlock") {
|
|
4606
|
-
var parsedScopePrelude = parseScopePrelude(buffer.trim());
|
|
4607
|
-
|
|
4608
|
-
if (parsedScopePrelude.hasStart) {
|
|
4609
|
-
scopeRule.__start = parsedScopePrelude.startSelector;
|
|
4627
|
+
case "{":
|
|
4628
|
+
if (currentScope === topScope) {
|
|
4629
|
+
nestedSelectorRule = null;
|
|
4610
4630
|
}
|
|
4611
|
-
if (
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
scopeRule.__end = parsedScopePrelude.endSelector;
|
|
4631
|
+
if (state === 'before-selector') {
|
|
4632
|
+
parseError("Unexpected {");
|
|
4633
|
+
i = ignoreBalancedBlock(i, token.slice(i));
|
|
4634
|
+
break;
|
|
4616
4635
|
}
|
|
4636
|
+
if (state === "selector" || state === "atRule") {
|
|
4637
|
+
if (!nestedSelectorRule && buffer.indexOf(";") !== -1) {
|
|
4638
|
+
var ruleClosingMatch = token.slice(i).match(forwardRuleClosingBraceRegExp);
|
|
4639
|
+
if (ruleClosingMatch) {
|
|
4640
|
+
styleRule = null;
|
|
4641
|
+
buffer = "";
|
|
4642
|
+
state = "before-selector";
|
|
4643
|
+
i += ruleClosingMatch.index + ruleClosingMatch[0].length;
|
|
4644
|
+
break;
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4617
4647
|
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
scopeRule.__parentStyleSheet = styleSheet;
|
|
4624
|
-
buffer = "";
|
|
4625
|
-
state = "before-selector";
|
|
4626
|
-
} else if (state === "layerBlock") {
|
|
4627
|
-
layerBlockRule.name = buffer.trim();
|
|
4648
|
+
// Ensure styleRule exists before trying to set properties on it
|
|
4649
|
+
if (!styleRule) {
|
|
4650
|
+
styleRule = new CSSOM.CSSStyleRule();
|
|
4651
|
+
styleRule.__starts = i;
|
|
4652
|
+
}
|
|
4628
4653
|
|
|
4629
|
-
|
|
4654
|
+
var originalParentRule = parentRule;
|
|
4630
4655
|
|
|
4631
|
-
if (isValidName) {
|
|
4632
4656
|
if (parentRule) {
|
|
4633
|
-
|
|
4657
|
+
styleRule.__parentRule = parentRule;
|
|
4634
4658
|
pushToAncestorRules(parentRule);
|
|
4635
4659
|
}
|
|
4636
|
-
|
|
4637
|
-
currentScope = parentRule = layerBlockRule;
|
|
4638
|
-
layerBlockRule.__parentStyleSheet = styleSheet;
|
|
4639
|
-
}
|
|
4640
|
-
buffer = "";
|
|
4641
|
-
state = "before-selector";
|
|
4642
|
-
} else if (state === "pageBlock") {
|
|
4643
|
-
pageRule.selectorText = buffer.trim();
|
|
4644
|
-
|
|
4645
|
-
if (parentRule) {
|
|
4646
|
-
pageRule.__parentRule = parentRule;
|
|
4647
|
-
pushToAncestorRules(parentRule);
|
|
4648
|
-
}
|
|
4649
4660
|
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4661
|
+
currentScope = parentRule = styleRule;
|
|
4662
|
+
var processedSelectorText = processSelectorText(buffer.trim());
|
|
4663
|
+
// In a nested selector, ensure each selector contains '&' at the beginning, except for selectors that already have '&' somewhere
|
|
4664
|
+
if (originalParentRule && originalParentRule.constructor.name === "CSSStyleRule") {
|
|
4665
|
+
styleRule.selectorText = parseAndSplitNestedSelectors(processedSelectorText).map(function (sel) {
|
|
4666
|
+
// Add & at the beginning if there's no & in the selector, or if it starts with a combinator
|
|
4667
|
+
return (sel.indexOf('&') === -1 || startsWithCombinatorRegExp.test(sel)) ? '& ' + sel : sel;
|
|
4668
|
+
}).join(', ');
|
|
4669
|
+
} else {
|
|
4670
|
+
styleRule.selectorText = processedSelectorText;
|
|
4671
|
+
}
|
|
4672
|
+
styleRule.style.__starts = i;
|
|
4673
|
+
styleRule.__parentStyleSheet = styleSheet;
|
|
4674
|
+
buffer = "";
|
|
4675
|
+
state = "before-name";
|
|
4676
|
+
} else if (state === "atBlock") {
|
|
4677
|
+
mediaRule.media.mediaText = buffer.trim();
|
|
4659
4678
|
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4679
|
+
if (parentRule) {
|
|
4680
|
+
mediaRule.__parentRule = parentRule;
|
|
4681
|
+
pushToAncestorRules(parentRule);
|
|
4682
|
+
// If entering @media from within a CSSStyleRule, set nestedSelectorRule
|
|
4683
|
+
// so that & selectors and declarations work correctly inside
|
|
4684
|
+
if (parentRule.constructor.name === "CSSStyleRule" && !nestedSelectorRule) {
|
|
4685
|
+
nestedSelectorRule = parentRule;
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4669
4688
|
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4689
|
+
currentScope = parentRule = mediaRule;
|
|
4690
|
+
pushToAncestorRules(mediaRule);
|
|
4691
|
+
mediaRule.__parentStyleSheet = styleSheet;
|
|
4692
|
+
styleRule = null; // Reset styleRule when entering @-rule
|
|
4693
|
+
buffer = "";
|
|
4694
|
+
state = "before-selector";
|
|
4695
|
+
} else if (state === "containerBlock") {
|
|
4696
|
+
containerRule.__conditionText = buffer.trim();
|
|
4674
4697
|
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
fontFaceRule.__parentRule = parentRule;
|
|
4678
|
-
}
|
|
4679
|
-
fontFaceRule.__parentStyleSheet = styleSheet;
|
|
4680
|
-
styleRule = fontFaceRule;
|
|
4681
|
-
buffer = "";
|
|
4682
|
-
state = "before-name";
|
|
4683
|
-
} else if (state === "keyframesRule-begin") {
|
|
4684
|
-
keyframesRule.name = buffer.trim();
|
|
4685
|
-
if (parentRule) {
|
|
4686
|
-
pushToAncestorRules(parentRule);
|
|
4687
|
-
keyframesRule.__parentRule = parentRule;
|
|
4688
|
-
}
|
|
4689
|
-
keyframesRule.__parentStyleSheet = styleSheet;
|
|
4690
|
-
currentScope = parentRule = keyframesRule;
|
|
4691
|
-
buffer = "";
|
|
4692
|
-
state = "keyframeRule-begin";
|
|
4693
|
-
} else if (state === "keyframeRule-begin") {
|
|
4694
|
-
styleRule = new CSSOM.CSSKeyframeRule();
|
|
4695
|
-
styleRule.keyText = buffer.trim();
|
|
4696
|
-
styleRule.__starts = i;
|
|
4697
|
-
buffer = "";
|
|
4698
|
-
state = "before-name";
|
|
4699
|
-
} else if (state === "documentRule-begin") {
|
|
4700
|
-
// FIXME: what if this '{' is in the url text of the match function?
|
|
4701
|
-
documentRule.matcher.matcherText = buffer.trim();
|
|
4702
|
-
if (parentRule) {
|
|
4703
|
-
pushToAncestorRules(parentRule);
|
|
4704
|
-
documentRule.__parentRule = parentRule;
|
|
4705
|
-
}
|
|
4706
|
-
currentScope = parentRule = documentRule;
|
|
4707
|
-
documentRule.__parentStyleSheet = styleSheet;
|
|
4708
|
-
buffer = "";
|
|
4709
|
-
state = "before-selector";
|
|
4710
|
-
} else if (state === "before-name" || state === "name") {
|
|
4711
|
-
if (styleRule.constructor.name === "CSSNestedDeclarations") {
|
|
4712
|
-
if (styleRule.style.length) {
|
|
4713
|
-
parentRule.cssRules.push(styleRule);
|
|
4714
|
-
styleRule.__parentRule = parentRule;
|
|
4715
|
-
styleRule.__parentStyleSheet = styleSheet;
|
|
4716
|
-
pushToAncestorRules(parentRule);
|
|
4717
|
-
} else {
|
|
4718
|
-
// If the styleRule is empty, we can assume that it's a nested selector
|
|
4698
|
+
if (parentRule) {
|
|
4699
|
+
containerRule.__parentRule = parentRule;
|
|
4719
4700
|
pushToAncestorRules(parentRule);
|
|
4701
|
+
if (parentRule.constructor.name === "CSSStyleRule" && !nestedSelectorRule) {
|
|
4702
|
+
nestedSelectorRule = parentRule;
|
|
4703
|
+
}
|
|
4720
4704
|
}
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
styleRule
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
}
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
nestedSelectorRule = styleRule;
|
|
4705
|
+
currentScope = parentRule = containerRule;
|
|
4706
|
+
pushToAncestorRules(containerRule);
|
|
4707
|
+
containerRule.__parentStyleSheet = styleSheet;
|
|
4708
|
+
styleRule = null; // Reset styleRule when entering @-rule
|
|
4709
|
+
buffer = "";
|
|
4710
|
+
state = "before-selector";
|
|
4711
|
+
} else if (state === "counterStyleBlock") {
|
|
4712
|
+
var counterStyleName = buffer.trim().replace(/\n/g, "");
|
|
4713
|
+
// Validate: name cannot be empty, contain whitespace, or contain dots
|
|
4714
|
+
var isValidCounterStyleName = counterStyleName.length > 0 && !/[\s.]/.test(counterStyleName);
|
|
4715
|
+
|
|
4716
|
+
if (isValidCounterStyleName) {
|
|
4717
|
+
counterStyleRule.name = counterStyleName;
|
|
4718
|
+
currentScope = parentRule = counterStyleRule;
|
|
4719
|
+
counterStyleRule.__parentStyleSheet = styleSheet;
|
|
4720
|
+
}
|
|
4721
|
+
buffer = "";
|
|
4722
|
+
} else if (state === "conditionBlock") {
|
|
4723
|
+
supportsRule.__conditionText = buffer.trim();
|
|
4741
4724
|
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4725
|
+
if (parentRule) {
|
|
4726
|
+
supportsRule.__parentRule = parentRule;
|
|
4727
|
+
pushToAncestorRules(parentRule);
|
|
4728
|
+
if (parentRule.constructor.name === "CSSStyleRule" && !nestedSelectorRule) {
|
|
4729
|
+
nestedSelectorRule = parentRule;
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4746
4732
|
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
var hasOpenBraceBefore = openBraceBeforeMatch && openBraceBeforeMatch[0] === '{';
|
|
4752
|
-
if (hasOpenBraceBefore) {
|
|
4753
|
-
// Is a selector
|
|
4754
|
-
buffer += character;
|
|
4755
|
-
} else {
|
|
4756
|
-
// Is a declaration
|
|
4757
|
-
name = buffer.trim();
|
|
4733
|
+
currentScope = parentRule = supportsRule;
|
|
4734
|
+
pushToAncestorRules(supportsRule);
|
|
4735
|
+
supportsRule.__parentStyleSheet = styleSheet;
|
|
4736
|
+
styleRule = null; // Reset styleRule when entering @-rule
|
|
4758
4737
|
buffer = "";
|
|
4759
|
-
state = "before-
|
|
4760
|
-
}
|
|
4761
|
-
|
|
4762
|
-
buffer += character;
|
|
4763
|
-
}
|
|
4764
|
-
break;
|
|
4738
|
+
state = "before-selector";
|
|
4739
|
+
} else if (state === "scopeBlock") {
|
|
4740
|
+
var parsedScopePrelude = parseScopePrelude(buffer.trim());
|
|
4765
4741
|
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4742
|
+
if (parsedScopePrelude.hasStart) {
|
|
4743
|
+
scopeRule.__start = parsedScopePrelude.startSelector;
|
|
4744
|
+
}
|
|
4745
|
+
if (parsedScopePrelude.hasEnd) {
|
|
4746
|
+
scopeRule.__end = parsedScopePrelude.endSelector;
|
|
4747
|
+
}
|
|
4748
|
+
if (parsedScopePrelude.hasOnlyEnd) {
|
|
4749
|
+
scopeRule.__end = parsedScopePrelude.endSelector;
|
|
4750
|
+
}
|
|
4771
4751
|
|
|
4772
|
-
if (
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4752
|
+
if (parentRule) {
|
|
4753
|
+
scopeRule.__parentRule = parentRule;
|
|
4754
|
+
pushToAncestorRules(parentRule);
|
|
4755
|
+
if (parentRule.constructor.name === "CSSStyleRule" && !nestedSelectorRule) {
|
|
4756
|
+
nestedSelectorRule = parentRule;
|
|
4757
|
+
}
|
|
4777
4758
|
}
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
//
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
}
|
|
4785
|
-
|
|
4786
|
-
valueParenthesisDepth++;
|
|
4787
|
-
buffer += character;
|
|
4788
|
-
} else {
|
|
4789
|
-
buffer += character;
|
|
4790
|
-
}
|
|
4791
|
-
break;
|
|
4759
|
+
currentScope = parentRule = scopeRule;
|
|
4760
|
+
pushToAncestorRules(scopeRule);
|
|
4761
|
+
scopeRule.__parentStyleSheet = styleSheet;
|
|
4762
|
+
styleRule = null; // Reset styleRule when entering @-rule
|
|
4763
|
+
buffer = "";
|
|
4764
|
+
state = "before-selector";
|
|
4765
|
+
} else if (state === "layerBlock") {
|
|
4766
|
+
layerBlockRule.name = buffer.trim();
|
|
4792
4767
|
|
|
4793
|
-
|
|
4794
|
-
if (state === 'value-parenthesis') {
|
|
4795
|
-
valueParenthesisDepth--;
|
|
4796
|
-
if (valueParenthesisDepth === 0) state = 'value';
|
|
4797
|
-
}
|
|
4798
|
-
buffer += character;
|
|
4799
|
-
break;
|
|
4768
|
+
var isValidName = layerBlockRule.name.length === 0 || layerBlockRule.name.match(cssCustomIdentifierRegExp) !== null;
|
|
4800
4769
|
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4770
|
+
if (isValidName) {
|
|
4771
|
+
if (parentRule) {
|
|
4772
|
+
layerBlockRule.__parentRule = parentRule;
|
|
4773
|
+
pushToAncestorRules(parentRule);
|
|
4774
|
+
if (parentRule.constructor.name === "CSSStyleRule" && !nestedSelectorRule) {
|
|
4775
|
+
nestedSelectorRule = parentRule;
|
|
4776
|
+
}
|
|
4777
|
+
}
|
|
4809
4778
|
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4779
|
+
currentScope = parentRule = layerBlockRule;
|
|
4780
|
+
pushToAncestorRules(layerBlockRule);
|
|
4781
|
+
layerBlockRule.__parentStyleSheet = styleSheet;
|
|
4782
|
+
}
|
|
4783
|
+
styleRule = null; // Reset styleRule when entering @-rule
|
|
4815
4784
|
buffer = "";
|
|
4816
|
-
state = "before-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4785
|
+
state = "before-selector";
|
|
4786
|
+
} else if (state === "pageBlock") {
|
|
4787
|
+
pageRule.selectorText = buffer.trim();
|
|
4788
|
+
|
|
4789
|
+
if (parentRule) {
|
|
4790
|
+
pageRule.__parentRule = parentRule;
|
|
4791
|
+
pushToAncestorRules(parentRule);
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4794
|
+
currentScope = parentRule = pageRule;
|
|
4795
|
+
pageRule.__parentStyleSheet = styleSheet;
|
|
4796
|
+
styleRule = pageRule;
|
|
4821
4797
|
buffer = "";
|
|
4822
4798
|
state = "before-name";
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
state = "before-selector";
|
|
4827
|
-
break;
|
|
4828
|
-
case "importRule":
|
|
4829
|
-
var isValid = topScope.cssRules.length === 0 || topScope.cssRules.some(function (rule) {
|
|
4830
|
-
return ['CSSImportRule', 'CSSLayerStatementRule'].indexOf(rule.constructor.name) !== -1
|
|
4831
|
-
});
|
|
4832
|
-
if (isValid) {
|
|
4833
|
-
importRule = new CSSOM.CSSImportRule();
|
|
4834
|
-
importRule.__parentStyleSheet = importRule.styleSheet.__parentStyleSheet = styleSheet;
|
|
4835
|
-
importRule.cssText = buffer + character;
|
|
4836
|
-
topScope.cssRules.push(importRule);
|
|
4799
|
+
} else if (state === "hostRule-begin") {
|
|
4800
|
+
if (parentRule) {
|
|
4801
|
+
pushToAncestorRules(parentRule);
|
|
4837
4802
|
}
|
|
4803
|
+
|
|
4804
|
+
currentScope = parentRule = hostRule;
|
|
4805
|
+
pushToAncestorRules(hostRule);
|
|
4806
|
+
hostRule.__parentStyleSheet = styleSheet;
|
|
4838
4807
|
buffer = "";
|
|
4839
4808
|
state = "before-selector";
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
try {
|
|
4847
|
-
// Validate namespace syntax before creating the rule
|
|
4848
|
-
var testNamespaceRule = new CSSOM.CSSNamespaceRule();
|
|
4849
|
-
testNamespaceRule.cssText = buffer + character;
|
|
4850
|
-
|
|
4851
|
-
namespaceRule = testNamespaceRule;
|
|
4852
|
-
namespaceRule.__parentStyleSheet = styleSheet;
|
|
4853
|
-
topScope.cssRules.push(namespaceRule);
|
|
4854
|
-
|
|
4855
|
-
// Track the namespace prefix for validation
|
|
4856
|
-
if (namespaceRule.prefix) {
|
|
4857
|
-
definedNamespacePrefixes[namespaceRule.prefix] = namespaceRule.namespaceURI;
|
|
4858
|
-
}
|
|
4859
|
-
} catch(e) {
|
|
4860
|
-
parseError(e.message);
|
|
4809
|
+
} else if (state === "startingStyleRule-begin") {
|
|
4810
|
+
if (parentRule) {
|
|
4811
|
+
startingStyleRule.__parentRule = parentRule;
|
|
4812
|
+
pushToAncestorRules(parentRule);
|
|
4813
|
+
if (parentRule.constructor.name === "CSSStyleRule" && !nestedSelectorRule) {
|
|
4814
|
+
nestedSelectorRule = parentRule;
|
|
4861
4815
|
}
|
|
4862
4816
|
}
|
|
4817
|
+
|
|
4818
|
+
currentScope = parentRule = startingStyleRule;
|
|
4819
|
+
pushToAncestorRules(startingStyleRule);
|
|
4820
|
+
startingStyleRule.__parentStyleSheet = styleSheet;
|
|
4821
|
+
styleRule = null; // Reset styleRule when entering @-rule
|
|
4863
4822
|
buffer = "";
|
|
4864
4823
|
state = "before-selector";
|
|
4865
|
-
break;
|
|
4866
|
-
case "layerBlock":
|
|
4867
|
-
var nameListStr = buffer.trim().split(",").map(function (name) {
|
|
4868
|
-
return name.trim();
|
|
4869
|
-
});
|
|
4870
|
-
var isInvalid = parentRule !== undefined || nameListStr.some(function (name) {
|
|
4871
|
-
return name.trim().match(cssCustomIdentifierRegExp) === null;
|
|
4872
|
-
});
|
|
4873
4824
|
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
layerStatementRule.__starts = layerBlockRule.__starts;
|
|
4878
|
-
layerStatementRule.__ends = i;
|
|
4879
|
-
layerStatementRule.nameList = nameListStr;
|
|
4880
|
-
topScope.cssRules.push(layerStatementRule);
|
|
4825
|
+
} else if (state === "fontFaceRule-begin") {
|
|
4826
|
+
if (parentRule) {
|
|
4827
|
+
fontFaceRule.__parentRule = parentRule;
|
|
4881
4828
|
}
|
|
4829
|
+
fontFaceRule.__parentStyleSheet = styleSheet;
|
|
4830
|
+
styleRule = fontFaceRule;
|
|
4882
4831
|
buffer = "";
|
|
4883
|
-
state = "before-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
break;
|
|
4890
|
-
|
|
4891
|
-
case "}":
|
|
4892
|
-
if (state === "counterStyleBlock") {
|
|
4893
|
-
// FIXME : Implement cssText get setter that parses the real implementation
|
|
4894
|
-
counterStyleRule.cssText = "@counter-style " + counterStyleRule.name + " { " + buffer.trim().replace(/\n/g, " ").replace(/(['"])(?:\\.|[^\\])*?\1|(\s{2,})/g, function(match, quote) {
|
|
4895
|
-
return quote ? match : ' ';
|
|
4896
|
-
}) + " }";
|
|
4897
|
-
buffer = "";
|
|
4898
|
-
state = "before-selector";
|
|
4899
|
-
}
|
|
4900
|
-
|
|
4901
|
-
switch (state) {
|
|
4902
|
-
case "value":
|
|
4903
|
-
styleRule.style.setProperty(name, buffer.trim(), priority, parseError);
|
|
4904
|
-
priority = "";
|
|
4905
|
-
/* falls through */
|
|
4906
|
-
case "before-value":
|
|
4907
|
-
case "before-name":
|
|
4908
|
-
case "name":
|
|
4909
|
-
styleRule.__ends = i + 1;
|
|
4910
|
-
|
|
4911
|
-
if (parentRule === styleRule) {
|
|
4912
|
-
parentRule = ancestorRules.pop()
|
|
4832
|
+
state = "before-name";
|
|
4833
|
+
} else if (state === "keyframesRule-begin") {
|
|
4834
|
+
keyframesRule.name = buffer.trim();
|
|
4835
|
+
if (parentRule) {
|
|
4836
|
+
pushToAncestorRules(parentRule);
|
|
4837
|
+
keyframesRule.__parentRule = parentRule;
|
|
4913
4838
|
}
|
|
4914
|
-
|
|
4839
|
+
keyframesRule.__parentStyleSheet = styleSheet;
|
|
4840
|
+
currentScope = parentRule = keyframesRule;
|
|
4841
|
+
buffer = "";
|
|
4842
|
+
state = "keyframeRule-begin";
|
|
4843
|
+
} else if (state === "keyframeRule-begin") {
|
|
4844
|
+
styleRule = new CSSOM.CSSKeyframeRule();
|
|
4845
|
+
styleRule.keyText = buffer.trim();
|
|
4846
|
+
styleRule.__starts = i;
|
|
4847
|
+
buffer = "";
|
|
4848
|
+
state = "before-name";
|
|
4849
|
+
} else if (state === "documentRule-begin") {
|
|
4850
|
+
// FIXME: what if this '{' is in the url text of the match function?
|
|
4851
|
+
documentRule.matcher.matcherText = buffer.trim();
|
|
4915
4852
|
if (parentRule) {
|
|
4916
|
-
|
|
4853
|
+
pushToAncestorRules(parentRule);
|
|
4854
|
+
documentRule.__parentRule = parentRule;
|
|
4917
4855
|
}
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4856
|
+
currentScope = parentRule = documentRule;
|
|
4857
|
+
pushToAncestorRules(documentRule);
|
|
4858
|
+
documentRule.__parentStyleSheet = styleSheet;
|
|
4859
|
+
buffer = "";
|
|
4860
|
+
state = "before-selector";
|
|
4861
|
+
} else if (state === "before-name" || state === "name") {
|
|
4862
|
+
// @font-face and similar rules don't support nested selectors
|
|
4863
|
+
// If we encounter a nested selector block inside them, skip it
|
|
4864
|
+
if (styleRule.constructor.name === "CSSFontFaceRule" ||
|
|
4865
|
+
styleRule.constructor.name === "CSSKeyframeRule" ||
|
|
4866
|
+
(styleRule.constructor.name === "CSSPageRule" && parentRule === styleRule)) {
|
|
4867
|
+
// Skip the nested block
|
|
4868
|
+
var ruleClosingMatch = token.slice(i).match(forwardRuleClosingBraceRegExp);
|
|
4869
|
+
if (ruleClosingMatch) {
|
|
4870
|
+
i += ruleClosingMatch.index + ruleClosingMatch[0].length - 1;
|
|
4871
|
+
buffer = "";
|
|
4872
|
+
state = "before-name";
|
|
4873
|
+
break;
|
|
4874
|
+
}
|
|
4922
4875
|
}
|
|
4923
4876
|
|
|
4924
|
-
if (styleRule.constructor.name === "
|
|
4925
|
-
if (styleRule
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
if (styleRule.parentRule) {
|
|
4931
|
-
styleRule.parentRule.cssRules.push(styleRule);
|
|
4877
|
+
if (styleRule.constructor.name === "CSSNestedDeclarations") {
|
|
4878
|
+
if (styleRule.style.length) {
|
|
4879
|
+
parentRule.cssRules.push(styleRule);
|
|
4880
|
+
styleRule.__parentRule = parentRule;
|
|
4881
|
+
styleRule.__parentStyleSheet = styleSheet;
|
|
4882
|
+
pushToAncestorRules(parentRule);
|
|
4932
4883
|
} else {
|
|
4933
|
-
|
|
4884
|
+
// If the styleRule is empty, we can assume that it's a nested selector
|
|
4885
|
+
pushToAncestorRules(parentRule);
|
|
4934
4886
|
}
|
|
4887
|
+
} else {
|
|
4888
|
+
currentScope = parentRule = styleRule;
|
|
4889
|
+
pushToAncestorRules(parentRule);
|
|
4890
|
+
styleRule.__parentStyleSheet = styleSheet;
|
|
4935
4891
|
}
|
|
4892
|
+
|
|
4893
|
+
styleRule = new CSSOM.CSSStyleRule();
|
|
4894
|
+
var processedSelectorText = processSelectorText(buffer.trim());
|
|
4895
|
+
// In a nested selector, ensure each selector contains '&' at the beginning, except for selectors that already have '&' somewhere
|
|
4896
|
+
if (parentRule.constructor.name === "CSSScopeRule" || (parentRule.constructor.name !== "CSSStyleRule" && parentRule.parentRule === null)) {
|
|
4897
|
+
styleRule.selectorText = processedSelectorText;
|
|
4898
|
+
} else {
|
|
4899
|
+
styleRule.selectorText = parseAndSplitNestedSelectors(processedSelectorText).map(function (sel) {
|
|
4900
|
+
// Add & at the beginning if there's no & in the selector, or if it starts with a combinator
|
|
4901
|
+
return (sel.indexOf('&') === -1 || startsWithCombinatorRegExp.test(sel)) ? '& ' + sel : sel;
|
|
4902
|
+
}).join(', ');
|
|
4903
|
+
}
|
|
4904
|
+
styleRule.style.__starts = i - buffer.length;
|
|
4905
|
+
styleRule.__parentRule = parentRule;
|
|
4906
|
+
// Only set nestedSelectorRule if we're directly inside a CSSStyleRule or CSSScopeRule,
|
|
4907
|
+
// not inside other grouping rules like @media/@supports
|
|
4908
|
+
if (parentRule.constructor.name === "CSSStyleRule" || parentRule.constructor.name === "CSSScopeRule") {
|
|
4909
|
+
nestedSelectorRule = styleRule;
|
|
4910
|
+
}
|
|
4911
|
+
|
|
4936
4912
|
buffer = "";
|
|
4937
|
-
|
|
4938
|
-
|
|
4913
|
+
state = "before-name";
|
|
4914
|
+
}
|
|
4915
|
+
break;
|
|
4916
|
+
|
|
4917
|
+
case ":":
|
|
4918
|
+
if (state === "name") {
|
|
4919
|
+
// It can be a nested selector, let's check
|
|
4920
|
+
var openBraceBeforeMatch = token.slice(i).match(/[{;}]/);
|
|
4921
|
+
var hasOpenBraceBefore = openBraceBeforeMatch && openBraceBeforeMatch[0] === '{';
|
|
4922
|
+
if (hasOpenBraceBefore) {
|
|
4923
|
+
// Is a selector
|
|
4924
|
+
buffer += character;
|
|
4939
4925
|
} else {
|
|
4940
|
-
|
|
4926
|
+
// Is a declaration
|
|
4927
|
+
name = buffer.trim();
|
|
4928
|
+
buffer = "";
|
|
4929
|
+
state = "before-value";
|
|
4941
4930
|
}
|
|
4931
|
+
} else {
|
|
4932
|
+
buffer += character;
|
|
4933
|
+
}
|
|
4934
|
+
break;
|
|
4942
4935
|
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4936
|
+
case "(":
|
|
4937
|
+
if (state === 'value') {
|
|
4938
|
+
// ie css expression mode
|
|
4939
|
+
if (buffer.trim() === 'expression') {
|
|
4940
|
+
var info = (new CSSOM.CSSValueExpression(token, i)).parse();
|
|
4941
|
+
|
|
4942
|
+
if (info.error) {
|
|
4943
|
+
parseError(info.error);
|
|
4944
|
+
} else {
|
|
4945
|
+
buffer += info.expression;
|
|
4946
|
+
i = info.idx;
|
|
4946
4947
|
}
|
|
4947
|
-
styleRule = null;
|
|
4948
4948
|
} else {
|
|
4949
|
-
|
|
4950
|
-
|
|
4949
|
+
state = 'value-parenthesis';
|
|
4950
|
+
//always ensure this is reset to 1 on transition
|
|
4951
|
+
//from value to value-parenthesis
|
|
4952
|
+
valueParenthesisDepth = 1;
|
|
4953
|
+
buffer += character;
|
|
4951
4954
|
}
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4955
|
+
} else if (state === 'value-parenthesis') {
|
|
4956
|
+
valueParenthesisDepth++;
|
|
4957
|
+
buffer += character;
|
|
4958
|
+
} else {
|
|
4959
|
+
buffer += character;
|
|
4960
|
+
}
|
|
4961
|
+
break;
|
|
4962
|
+
|
|
4963
|
+
case ")":
|
|
4964
|
+
if (state === 'value-parenthesis') {
|
|
4965
|
+
valueParenthesisDepth--;
|
|
4966
|
+
if (valueParenthesisDepth === 0) state = 'value';
|
|
4967
|
+
}
|
|
4968
|
+
buffer += character;
|
|
4969
|
+
break;
|
|
4970
|
+
|
|
4971
|
+
case "!":
|
|
4972
|
+
if (state === "value" && token.indexOf("!important", i) === i) {
|
|
4973
|
+
priority = "important";
|
|
4974
|
+
i += "important".length;
|
|
4975
|
+
} else {
|
|
4976
|
+
buffer += character;
|
|
4977
|
+
}
|
|
4978
|
+
break;
|
|
4979
|
+
|
|
4980
|
+
case ";":
|
|
4981
|
+
switch (state) {
|
|
4982
|
+
case "before-value":
|
|
4983
|
+
case "before-name":
|
|
4984
|
+
parseError("Unexpected ;");
|
|
4985
|
+
buffer = "";
|
|
4986
|
+
state = "before-name";
|
|
4987
|
+
break;
|
|
4988
|
+
case "value":
|
|
4989
|
+
styleRule.style.setProperty(name, buffer.trim(), priority, parseError);
|
|
4990
|
+
priority = "";
|
|
4991
|
+
buffer = "";
|
|
4992
|
+
state = "before-name";
|
|
4993
|
+
break;
|
|
4994
|
+
case "atRule":
|
|
4995
|
+
buffer = "";
|
|
4996
|
+
state = "before-selector";
|
|
4997
|
+
break;
|
|
4998
|
+
case "importRule":
|
|
4999
|
+
var isValid = topScope.cssRules.length === 0 || topScope.cssRules.some(function (rule) {
|
|
5000
|
+
return ['CSSImportRule', 'CSSLayerStatementRule'].indexOf(rule.constructor.name) !== -1
|
|
5001
|
+
});
|
|
5002
|
+
if (isValid) {
|
|
5003
|
+
importRule = new CSSOM.CSSImportRule();
|
|
5004
|
+
importRule.__parentStyleSheet = importRule.styleSheet.__parentStyleSheet = styleSheet;
|
|
5005
|
+
importRule.parse(buffer + character);
|
|
5006
|
+
topScope.cssRules.push(importRule);
|
|
4962
5007
|
}
|
|
4963
|
-
|
|
5008
|
+
buffer = "";
|
|
5009
|
+
state = "before-selector";
|
|
4964
5010
|
break;
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
if (
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
5011
|
+
case "namespaceRule":
|
|
5012
|
+
var isValid = topScope.cssRules.length === 0 || topScope.cssRules.every(function (rule) {
|
|
5013
|
+
return ['CSSImportRule', 'CSSLayerStatementRule', 'CSSNamespaceRule'].indexOf(rule.constructor.name) !== -1
|
|
5014
|
+
});
|
|
5015
|
+
if (isValid) {
|
|
5016
|
+
try {
|
|
5017
|
+
// Validate namespace syntax before creating the rule
|
|
5018
|
+
var testNamespaceRule = new CSSOM.CSSNamespaceRule();
|
|
5019
|
+
testNamespaceRule.parse(buffer + character);
|
|
5020
|
+
|
|
5021
|
+
namespaceRule = testNamespaceRule;
|
|
5022
|
+
namespaceRule.__parentStyleSheet = styleSheet;
|
|
5023
|
+
topScope.cssRules.push(namespaceRule);
|
|
5024
|
+
|
|
5025
|
+
// Track the namespace prefix for validation
|
|
5026
|
+
if (namespaceRule.prefix) {
|
|
5027
|
+
definedNamespacePrefixes[namespaceRule.prefix] = namespaceRule.namespaceURI;
|
|
5028
|
+
}
|
|
5029
|
+
} catch (e) {
|
|
5030
|
+
parseError(e.message);
|
|
5031
|
+
}
|
|
5032
|
+
}
|
|
5033
|
+
buffer = "";
|
|
5034
|
+
state = "before-selector";
|
|
5035
|
+
break;
|
|
5036
|
+
case "layerBlock":
|
|
5037
|
+
var nameListStr = buffer.trim().split(",").map(function (name) {
|
|
5038
|
+
return name.trim();
|
|
5039
|
+
});
|
|
5040
|
+
var isInvalid = nameListStr.some(function (name) {
|
|
5041
|
+
return name.trim().match(cssCustomIdentifierRegExp) === null;
|
|
5042
|
+
});
|
|
5043
|
+
|
|
5044
|
+
// Check if there's a CSSStyleRule in the parent chain
|
|
5045
|
+
var hasStyleRuleParent = false;
|
|
5046
|
+
if (parentRule) {
|
|
5047
|
+
var checkParent = parentRule;
|
|
5048
|
+
while (checkParent) {
|
|
5049
|
+
if (checkParent.constructor.name === "CSSStyleRule") {
|
|
5050
|
+
hasStyleRuleParent = true;
|
|
5051
|
+
break;
|
|
4989
5052
|
}
|
|
5053
|
+
checkParent = checkParent.__parentRule;
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
|
|
5057
|
+
if (!isInvalid && !hasStyleRuleParent) {
|
|
5058
|
+
layerStatementRule = new CSSOM.CSSLayerStatementRule();
|
|
5059
|
+
layerStatementRule.__parentStyleSheet = styleSheet;
|
|
5060
|
+
layerStatementRule.__starts = layerBlockRule.__starts;
|
|
5061
|
+
layerStatementRule.__ends = i;
|
|
5062
|
+
layerStatementRule.nameList = nameListStr;
|
|
5063
|
+
|
|
5064
|
+
// Add to parent rule if nested, otherwise to top scope
|
|
5065
|
+
if (parentRule) {
|
|
5066
|
+
layerStatementRule.__parentRule = parentRule;
|
|
5067
|
+
parentRule.cssRules.push(layerStatementRule);
|
|
4990
5068
|
} else {
|
|
4991
|
-
|
|
4992
|
-
parentRule !== prevScope && parentRule.cssRules.push(prevScope);
|
|
4993
|
-
break;
|
|
5069
|
+
topScope.cssRules.push(layerStatementRule);
|
|
4994
5070
|
}
|
|
4995
5071
|
}
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5072
|
+
buffer = "";
|
|
5073
|
+
state = "before-selector";
|
|
5074
|
+
break;
|
|
5075
|
+
default:
|
|
5076
|
+
buffer += character;
|
|
5077
|
+
break;
|
|
5078
|
+
}
|
|
5079
|
+
break;
|
|
5080
|
+
|
|
5081
|
+
case "}":
|
|
5082
|
+
if (state === "counterStyleBlock") {
|
|
5083
|
+
// FIXME : Implement missing properties on CSSCounterStyleRule interface and update parse method
|
|
5084
|
+
// For now it's just assigning entire rule text
|
|
5085
|
+
counterStyleRule.parse("@counter-style " + counterStyleRule.name + " { " + buffer + " }");
|
|
5086
|
+
buffer = "";
|
|
5087
|
+
state = "before-selector";
|
|
5088
|
+
}
|
|
5089
|
+
|
|
5090
|
+
switch (state) {
|
|
5091
|
+
case "value":
|
|
5092
|
+
styleRule.style.setProperty(name, buffer.trim(), priority, parseError);
|
|
5093
|
+
priority = "";
|
|
5094
|
+
/* falls through */
|
|
5095
|
+
case "before-value":
|
|
5096
|
+
case "before-name":
|
|
5097
|
+
case "name":
|
|
5098
|
+
styleRule.__ends = i + 1;
|
|
5099
|
+
|
|
5100
|
+
if (parentRule === styleRule) {
|
|
5101
|
+
parentRule = ancestorRules.pop()
|
|
5102
|
+
}
|
|
5103
|
+
|
|
5104
|
+
if (parentRule) {
|
|
5105
|
+
styleRule.__parentRule = parentRule;
|
|
5004
5106
|
}
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
if (openingBraceLen === closingBraceLen) {
|
|
5015
|
-
// If the number of opening and closing braces are equal, we can assume that the new selector is starting outside the nestedSelectorRule
|
|
5016
|
-
nestedSelectorRule.__ends = i + 1;
|
|
5107
|
+
styleRule.__parentStyleSheet = styleSheet;
|
|
5108
|
+
|
|
5109
|
+
if (currentScope === styleRule) {
|
|
5110
|
+
currentScope = parentRule || topScope;
|
|
5111
|
+
}
|
|
5112
|
+
|
|
5113
|
+
if (styleRule.constructor.name === "CSSStyleRule" && !isValidSelectorText(styleRule.selectorText)) {
|
|
5114
|
+
if (styleRule === nestedSelectorRule) {
|
|
5017
5115
|
nestedSelectorRule = null;
|
|
5018
|
-
parentRule = null;
|
|
5019
5116
|
}
|
|
5117
|
+
parseError('Invalid CSSStyleRule (selectorText = "' + styleRule.selectorText + '")', styleRule.parentRule !== null);
|
|
5118
|
+
} else {
|
|
5119
|
+
if (styleRule.parentRule) {
|
|
5120
|
+
styleRule.parentRule.cssRules.push(styleRule);
|
|
5121
|
+
} else {
|
|
5122
|
+
currentScope.cssRules.push(styleRule);
|
|
5123
|
+
}
|
|
5124
|
+
}
|
|
5125
|
+
buffer = "";
|
|
5126
|
+
if (currentScope.constructor === CSSOM.CSSKeyframesRule) {
|
|
5127
|
+
state = "keyframeRule-begin";
|
|
5020
5128
|
} else {
|
|
5021
|
-
|
|
5129
|
+
state = "before-selector";
|
|
5130
|
+
}
|
|
5022
5131
|
|
|
5132
|
+
if (styleRule.constructor.name === "CSSNestedDeclarations") {
|
|
5133
|
+
if (currentScope !== topScope) {
|
|
5134
|
+
// Only set nestedSelectorRule if currentScope is CSSStyleRule or CSSScopeRule
|
|
5135
|
+
// Not for other grouping rules like @media/@supports
|
|
5136
|
+
if (currentScope.constructor.name === "CSSStyleRule" || currentScope.constructor.name === "CSSScopeRule") {
|
|
5137
|
+
nestedSelectorRule = currentScope;
|
|
5138
|
+
}
|
|
5139
|
+
}
|
|
5140
|
+
styleRule = null;
|
|
5141
|
+
} else {
|
|
5142
|
+
// Update nestedSelectorRule when closing a CSSStyleRule
|
|
5143
|
+
if (styleRule === nestedSelectorRule) {
|
|
5144
|
+
var selector = styleRule.selectorText && styleRule.selectorText.trim();
|
|
5145
|
+
// Check if this is proper nesting (&.class, &:pseudo) vs prepended & (& :is, & .class with space)
|
|
5146
|
+
// Prepended & has pattern "& X" where X starts with : or .
|
|
5147
|
+
var isPrependedAmpersand = selector && selector.match(/^&\s+[:\.]/);
|
|
5148
|
+
|
|
5149
|
+
// Check if parent is a grouping rule that can contain nested selectors
|
|
5150
|
+
var isGroupingRule = currentScope && currentScope instanceof CSSOM.CSSGroupingRule;
|
|
5151
|
+
|
|
5152
|
+
if (!isPrependedAmpersand && isGroupingRule) {
|
|
5153
|
+
// Proper nesting - set nestedSelectorRule to parent for more nested selectors
|
|
5154
|
+
// But only if it's a CSSStyleRule or CSSScopeRule, not other grouping rules like @media
|
|
5155
|
+
if (currentScope.constructor.name === "CSSStyleRule" || currentScope.constructor.name === "CSSScopeRule") {
|
|
5156
|
+
nestedSelectorRule = currentScope;
|
|
5157
|
+
}
|
|
5158
|
+
// If currentScope is another type of grouping rule (like @media), keep nestedSelectorRule unchanged
|
|
5159
|
+
} else {
|
|
5160
|
+
// Prepended & or not nested in grouping rule - reset to prevent CSSNestedDeclarations
|
|
5161
|
+
nestedSelectorRule = null;
|
|
5162
|
+
}
|
|
5163
|
+
} else if (nestedSelectorRule && currentScope instanceof CSSOM.CSSGroupingRule) {
|
|
5164
|
+
// When closing a nested rule that's not the nestedSelectorRule itself,
|
|
5165
|
+
// maintain nestedSelectorRule if we're still inside a grouping rule
|
|
5166
|
+
// This ensures declarations after nested selectors inside @media/@supports etc. work correctly
|
|
5167
|
+
}
|
|
5168
|
+
styleRule = null;
|
|
5169
|
+
break;
|
|
5023
5170
|
}
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5171
|
+
case "keyframeRule-begin":
|
|
5172
|
+
case "before-selector":
|
|
5173
|
+
case "selector":
|
|
5174
|
+
// End of media/supports/document rule.
|
|
5175
|
+
if (!parentRule) {
|
|
5176
|
+
parseError("Unexpected }");
|
|
5177
|
+
|
|
5178
|
+
var hasPreviousStyleRule = currentScope.cssRules.length && currentScope.cssRules[currentScope.cssRules.length - 1].constructor.name === "CSSStyleRule";
|
|
5179
|
+
if (hasPreviousStyleRule) {
|
|
5180
|
+
i = ignoreBalancedBlock(i, token.slice(i), 1);
|
|
5181
|
+
}
|
|
5027
5182
|
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
break;
|
|
5031
|
-
}
|
|
5032
|
-
break;
|
|
5183
|
+
break;
|
|
5184
|
+
}
|
|
5033
5185
|
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5186
|
+
while (ancestorRules.length > 0) {
|
|
5187
|
+
parentRule = ancestorRules.pop();
|
|
5188
|
+
|
|
5189
|
+
if (parentRule instanceof CSSOM.CSSGroupingRule && (parentRule.constructor.name !== 'CSSStyleRule' || parentRule.__parentRule)) {
|
|
5190
|
+
if (nestedSelectorRule) {
|
|
5191
|
+
if (nestedSelectorRule.parentRule) {
|
|
5192
|
+
prevScope = nestedSelectorRule;
|
|
5193
|
+
currentScope = nestedSelectorRule.parentRule;
|
|
5194
|
+
if (currentScope.cssRules.findIndex(function (rule) {
|
|
5195
|
+
return rule === prevScope
|
|
5196
|
+
}) === -1) {
|
|
5197
|
+
currentScope.cssRules.push(prevScope);
|
|
5198
|
+
}
|
|
5199
|
+
nestedSelectorRule = currentScope;
|
|
5200
|
+
} else {
|
|
5201
|
+
// If nestedSelectorRule doesn't have a parentRule, we're closing a grouping rule
|
|
5202
|
+
// inside a top-level CSSStyleRule. We need to push currentScope to the parentRule.
|
|
5203
|
+
prevScope = currentScope;
|
|
5204
|
+
// Push to actual parent from ancestorRules if available
|
|
5205
|
+
var actualParent = ancestorRules.length > 0 ? ancestorRules[ancestorRules.length - 1] : nestedSelectorRule;
|
|
5206
|
+
actualParent !== prevScope && actualParent.cssRules.push(prevScope);
|
|
5207
|
+
// Update currentScope to the nestedSelectorRule before breaking
|
|
5208
|
+
currentScope = actualParent;
|
|
5209
|
+
parentRule = actualParent;
|
|
5210
|
+
break;
|
|
5211
|
+
}
|
|
5212
|
+
} else {
|
|
5213
|
+
prevScope = currentScope;
|
|
5214
|
+
parentRule !== prevScope && parentRule.cssRules.push(prevScope);
|
|
5215
|
+
break;
|
|
5216
|
+
}
|
|
5055
5217
|
}
|
|
5056
5218
|
}
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
if
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5219
|
+
|
|
5220
|
+
// If currentScope has a __parentRule and wasn't added yet, add it
|
|
5221
|
+
if (ancestorRules.length === 0 && currentScope.__parentRule && currentScope.__parentRule.cssRules) {
|
|
5222
|
+
if (currentScope.__parentRule.cssRules.findIndex(function (rule) {
|
|
5223
|
+
return rule === currentScope
|
|
5224
|
+
}) === -1) {
|
|
5225
|
+
currentScope.__parentRule.cssRules.push(currentScope);
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
|
|
5229
|
+
// Only handle top-level rule closing if we processed all ancestors
|
|
5230
|
+
if (ancestorRules.length === 0 && currentScope.parentRule == null) {
|
|
5231
|
+
currentScope.__ends = i + 1;
|
|
5232
|
+
if (currentScope !== topScope && topScope.cssRules.findIndex(function (rule) {
|
|
5233
|
+
return rule === currentScope
|
|
5234
|
+
}) === -1) {
|
|
5235
|
+
topScope.cssRules.push(currentScope);
|
|
5236
|
+
}
|
|
5237
|
+
currentScope = topScope;
|
|
5238
|
+
if (nestedSelectorRule === parentRule) {
|
|
5239
|
+
// Check if this selector is really starting inside another selector
|
|
5240
|
+
var nestedSelectorTokenToCurrentSelectorToken = token.slice(nestedSelectorRule.__starts, i + 1);
|
|
5241
|
+
var openingBraceMatch = nestedSelectorTokenToCurrentSelectorToken.match(/{/g);
|
|
5242
|
+
var closingBraceMatch = nestedSelectorTokenToCurrentSelectorToken.match(/}/g);
|
|
5243
|
+
var openingBraceLen = openingBraceMatch && openingBraceMatch.length;
|
|
5244
|
+
var closingBraceLen = closingBraceMatch && closingBraceMatch.length;
|
|
5245
|
+
|
|
5246
|
+
if (openingBraceLen === closingBraceLen) {
|
|
5247
|
+
// If the number of opening and closing braces are equal, we can assume that the new selector is starting outside the nestedSelectorRule
|
|
5248
|
+
nestedSelectorRule.__ends = i + 1;
|
|
5249
|
+
nestedSelectorRule = null;
|
|
5250
|
+
parentRule = null;
|
|
5251
|
+
}
|
|
5074
5252
|
} else {
|
|
5253
|
+
parentRule = null;
|
|
5254
|
+
}
|
|
5255
|
+
} else {
|
|
5256
|
+
currentScope = parentRule;
|
|
5257
|
+
}
|
|
5258
|
+
|
|
5259
|
+
buffer = "";
|
|
5260
|
+
state = "before-selector";
|
|
5261
|
+
break;
|
|
5262
|
+
}
|
|
5263
|
+
break;
|
|
5264
|
+
|
|
5265
|
+
default:
|
|
5266
|
+
switch (state) {
|
|
5267
|
+
case "before-selector":
|
|
5268
|
+
state = "selector";
|
|
5269
|
+
if ((styleRule || scopeRule) && parentRule) {
|
|
5270
|
+
// Assuming it's a declaration inside Nested Selector OR a Nested Declaration
|
|
5271
|
+
// If Declaration inside Nested Selector let's keep the same styleRule
|
|
5272
|
+
if (!isSelectorStartChar(character) && !isWhitespaceChar(character) && parentRule instanceof CSSOM.CSSGroupingRule) {
|
|
5273
|
+
// parentRule.__parentRule = styleRule;
|
|
5274
|
+
state = "before-name";
|
|
5275
|
+
if (styleRule !== parentRule) {
|
|
5276
|
+
styleRule = new CSSOM.CSSNestedDeclarations();
|
|
5277
|
+
styleRule.__starts = i;
|
|
5278
|
+
}
|
|
5279
|
+
}
|
|
5280
|
+
|
|
5281
|
+
} else if (nestedSelectorRule && parentRule && parentRule instanceof CSSOM.CSSGroupingRule) {
|
|
5282
|
+
if (isSelectorStartChar(character)) {
|
|
5283
|
+
// If starting with a selector character, create CSSStyleRule instead of CSSNestedDeclarations
|
|
5075
5284
|
styleRule = new CSSOM.CSSStyleRule();
|
|
5076
|
-
styleRule.__starts = i;
|
|
5285
|
+
styleRule.__starts = i;
|
|
5286
|
+
} else if (!isWhitespaceChar(character)) {
|
|
5287
|
+
// Starting a declaration (not whitespace, not a selector)
|
|
5288
|
+
state = "before-name";
|
|
5289
|
+
// Check if we should create CSSNestedDeclarations
|
|
5290
|
+
// This happens if: parent has cssRules OR nestedSelectorRule exists (indicating CSSStyleRule in hierarchy)
|
|
5291
|
+
if (parentRule.cssRules.length || nestedSelectorRule) {
|
|
5292
|
+
currentScope = parentRule;
|
|
5293
|
+
// Only set nestedSelectorRule if parentRule is CSSStyleRule or CSSScopeRule
|
|
5294
|
+
if (parentRule.constructor.name === "CSSStyleRule" || parentRule.constructor.name === "CSSScopeRule") {
|
|
5295
|
+
nestedSelectorRule = parentRule;
|
|
5296
|
+
}
|
|
5297
|
+
styleRule = new CSSOM.CSSNestedDeclarations();
|
|
5298
|
+
styleRule.__starts = i;
|
|
5299
|
+
} else {
|
|
5300
|
+
if (parentRule.constructor.name === "CSSStyleRule") {
|
|
5301
|
+
styleRule = parentRule;
|
|
5302
|
+
} else {
|
|
5303
|
+
styleRule = new CSSOM.CSSStyleRule();
|
|
5304
|
+
styleRule.__starts = i;
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5077
5307
|
}
|
|
5078
5308
|
}
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5309
|
+
break;
|
|
5310
|
+
case "before-name":
|
|
5311
|
+
state = "name";
|
|
5312
|
+
break;
|
|
5313
|
+
case "before-value":
|
|
5314
|
+
state = "value";
|
|
5315
|
+
break;
|
|
5316
|
+
case "importRule-begin":
|
|
5317
|
+
state = "importRule";
|
|
5318
|
+
break;
|
|
5319
|
+
case "namespaceRule-begin":
|
|
5320
|
+
state = "namespaceRule";
|
|
5321
|
+
break;
|
|
5322
|
+
}
|
|
5323
|
+
buffer += character;
|
|
5324
|
+
break;
|
|
5325
|
+
}
|
|
5326
|
+
|
|
5327
|
+
// Auto-close all unclosed nested structures
|
|
5328
|
+
// Check AFTER processing the character, at the ORIGINAL ending index
|
|
5329
|
+
// Only add closing braces if CSS is incomplete (not at top scope)
|
|
5330
|
+
if (i === initialEndingIndex && (currentScope !== topScope || ancestorRules.length > 0)) {
|
|
5331
|
+
var needsClosing = ancestorRules.length;
|
|
5332
|
+
if (currentScope !== topScope && ancestorRules.indexOf(currentScope) === -1) {
|
|
5333
|
+
needsClosing += 1;
|
|
5334
|
+
}
|
|
5335
|
+
// Add closing braces for all unclosed structures
|
|
5336
|
+
for (var closeIdx = 0; closeIdx < needsClosing; closeIdx++) {
|
|
5337
|
+
token += "}";
|
|
5338
|
+
endingIndex += 1;
|
|
5096
5339
|
}
|
|
5097
|
-
buffer += character;
|
|
5098
|
-
break;
|
|
5099
5340
|
}
|
|
5100
5341
|
}
|
|
5101
5342
|
|