CSSGroupingRule.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. //.CommonJS
  2. var CSSOM = {
  3. CSSRule: require("./CSSRule").CSSRule,
  4. CSSRuleList: require("./CSSRuleList").CSSRuleList,
  5. parse: require('./parse').parse
  6. };
  7. var errorUtils = require("./errorUtils").errorUtils;
  8. ///CommonJS
  9. /**
  10. * @constructor
  11. * @see https://drafts.csswg.org/cssom/#the-cssgroupingrule-interface
  12. */
  13. CSSOM.CSSGroupingRule = function CSSGroupingRule() {
  14. CSSOM.CSSRule.call(this);
  15. this.__cssRules = new CSSOM.CSSRuleList();
  16. };
  17. CSSOM.CSSGroupingRule.prototype = Object.create(CSSOM.CSSRule.prototype);
  18. CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
  19. Object.setPrototypeOf(CSSOM.CSSGroupingRule, CSSOM.CSSRule);
  20. Object.defineProperty(CSSOM.CSSGroupingRule.prototype, "cssRules", {
  21. get: function() {
  22. return this.__cssRules;
  23. }
  24. });
  25. /**
  26. * Used to insert a new CSS rule to a list of CSS rules.
  27. *
  28. * @example
  29. * cssGroupingRule.cssText
  30. * -> "body{margin:0;}"
  31. * cssGroupingRule.insertRule("img{border:none;}", 1)
  32. * -> 1
  33. * cssGroupingRule.cssText
  34. * -> "body{margin:0;}img{border:none;}"
  35. *
  36. * @param {string} rule
  37. * @param {number} [index]
  38. * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-insertrule
  39. * @return {number} The index within the grouping rule's collection of the newly inserted rule.
  40. */
  41. CSSOM.CSSGroupingRule.prototype.insertRule = function insertRule(rule, index) {
  42. if (rule === undefined && index === undefined) {
  43. errorUtils.throwMissingArguments(this, 'insertRule', this.constructor.name);
  44. }
  45. if (index === void 0) {
  46. index = 0;
  47. }
  48. index = Number(index);
  49. if (index < 0) {
  50. index = 4294967296 + index;
  51. }
  52. if (index > this.cssRules.length) {
  53. errorUtils.throwIndexError(this, 'insertRule', this.constructor.name, index, this.cssRules.length);
  54. }
  55. var ruleToParse = processedRuleToParse = String(rule);
  56. ruleToParse = ruleToParse.trim().replace(/^\/\*[\s\S]*?\*\/\s*/, "");
  57. var isNestedSelector = this.constructor.name === "CSSStyleRule";
  58. if (isNestedSelector === false) {
  59. var currentRule = this;
  60. while (currentRule.parentRule) {
  61. currentRule = currentRule.parentRule;
  62. if (currentRule.constructor.name === "CSSStyleRule") {
  63. isNestedSelector = true;
  64. break;
  65. }
  66. }
  67. }
  68. if (isNestedSelector) {
  69. processedRuleToParse = 's { n { } ' + ruleToParse + '}';
  70. }
  71. var isScopeRule = this.constructor.name === "CSSScopeRule";
  72. if (isScopeRule) {
  73. if (isNestedSelector) {
  74. processedRuleToParse = 's { ' + '@scope {' + ruleToParse + '}}';
  75. } else {
  76. processedRuleToParse = '@scope {' + ruleToParse + '}';
  77. }
  78. }
  79. var parsedRules = new CSSOM.CSSRuleList();
  80. CSSOM.parse(processedRuleToParse, {
  81. styleSheet: this.parentStyleSheet,
  82. cssRules: parsedRules
  83. });
  84. if (isScopeRule) {
  85. if (isNestedSelector) {
  86. parsedRules = parsedRules[0].cssRules[0].cssRules;
  87. } else {
  88. parsedRules = parsedRules[0].cssRules
  89. }
  90. }
  91. if (isNestedSelector) {
  92. parsedRules = parsedRules[0].cssRules.slice(1);
  93. }
  94. if (parsedRules.length !== 1) {
  95. if (isNestedSelector && parsedRules.length === 0 && ruleToParse.indexOf('@font-face') === 0) {
  96. errorUtils.throwError(this, 'DOMException',
  97. "Failed to execute 'insertRule' on '" + this.constructor.name + "': " +
  98. "Only conditional nested group rules, style rules, @scope rules, @apply rules, and nested declaration rules may be nested.",
  99. 'HierarchyRequestError');
  100. } else {
  101. errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
  102. }
  103. }
  104. var cssRule = parsedRules[0];
  105. if (cssRule.constructor.name === 'CSSNestedDeclarations' && cssRule.style.length === 0) {
  106. errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
  107. }
  108. // Check for rules that cannot be inserted inside a CSSGroupingRule
  109. if (cssRule.constructor.name === 'CSSImportRule' || cssRule.constructor.name === 'CSSNamespaceRule') {
  110. var ruleKeyword = cssRule.constructor.name === 'CSSImportRule' ? '@import' : '@namespace';
  111. errorUtils.throwError(this, 'DOMException',
  112. "Failed to execute 'insertRule' on '" + this.constructor.name + "': " +
  113. "'" + ruleKeyword + "' rules cannot be inserted inside a group rule.",
  114. 'HierarchyRequestError');
  115. }
  116. // Check for CSSLayerStatementRule (@layer statement rules)
  117. if (cssRule.constructor.name === 'CSSLayerStatementRule') {
  118. errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
  119. }
  120. cssRule.__parentRule = this;
  121. this.cssRules.splice(index, 0, cssRule);
  122. return index;
  123. };
  124. /**
  125. * Used to delete a rule from the grouping rule.
  126. *
  127. * cssGroupingRule.cssText
  128. * -> "img{border:none;}body{margin:0;}"
  129. * cssGroupingRule.deleteRule(0)
  130. * cssGroupingRule.cssText
  131. * -> "body{margin:0;}"
  132. *
  133. * @param {number} index within the grouping rule's rule list of the rule to remove.
  134. * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-deleterule
  135. */
  136. CSSOM.CSSGroupingRule.prototype.deleteRule = function deleteRule(index) {
  137. if (index === undefined) {
  138. errorUtils.throwMissingArguments(this, 'deleteRule', this.constructor.name);
  139. }
  140. index = Number(index);
  141. if (index < 0) {
  142. index = 4294967296 + index;
  143. }
  144. if (index >= this.cssRules.length) {
  145. errorUtils.throwIndexError(this, 'deleteRule', this.constructor.name, index, this.cssRules.length);
  146. }
  147. this.cssRules[index].__parentRule = null;
  148. this.cssRules[index].__parentStyleSheet = null;
  149. this.cssRules.splice(index, 1);
  150. };
  151. //.CommonJS
  152. exports.CSSGroupingRule = CSSOM.CSSGroupingRule;
  153. ///CommonJS