aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/@acemir/cssom/lib/CSSStyleSheet.js
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
commit76cb9c2a39d477a64824a985ade40507e3bbade1 (patch)
tree41e997aa9c6f538d3a136af61dae9424db2005a9 /vanilla/node_modules/@acemir/cssom/lib/CSSStyleSheet.js
parent819a39a21ac992b1393244a4c283bbb125208c69 (diff)
downloadneko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.gz
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.bz2
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.zip
feat(vanilla): add testing infrastructure and tests (NK-wjnczv)
Diffstat (limited to 'vanilla/node_modules/@acemir/cssom/lib/CSSStyleSheet.js')
-rw-r--r--vanilla/node_modules/@acemir/cssom/lib/CSSStyleSheet.js371
1 files changed, 371 insertions, 0 deletions
diff --git a/vanilla/node_modules/@acemir/cssom/lib/CSSStyleSheet.js b/vanilla/node_modules/@acemir/cssom/lib/CSSStyleSheet.js
new file mode 100644
index 0000000..364607f
--- /dev/null
+++ b/vanilla/node_modules/@acemir/cssom/lib/CSSStyleSheet.js
@@ -0,0 +1,371 @@
+//.CommonJS
+var CSSOM = {
+ MediaList: require("./MediaList").MediaList,
+ StyleSheet: require("./StyleSheet").StyleSheet,
+ CSSRuleList: require("./CSSRuleList").CSSRuleList,
+ CSSStyleRule: require("./CSSStyleRule").CSSStyleRule,
+};
+var errorUtils = require("./errorUtils").errorUtils;
+///CommonJS
+
+
+/**
+ * @constructor
+ * @param {CSSStyleSheetInit} [opts] - CSSStyleSheetInit options.
+ * @param {string} [opts.baseURL] - The base URL of the stylesheet.
+ * @param {boolean} [opts.disabled] - The disabled attribute of the stylesheet.
+ * @param {MediaList | string} [opts.media] - The media attribute of the stylesheet.
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet
+ */
+CSSOM.CSSStyleSheet = function CSSStyleSheet(opts) {
+ CSSOM.StyleSheet.call(this);
+ this.__constructed = true;
+ this.__cssRules = new CSSOM.CSSRuleList();
+ this.__ownerRule = null;
+
+ if (opts && typeof opts === "object") {
+ if (opts.baseURL && typeof opts.baseURL === "string") {
+ this.__baseURL = opts.baseURL;
+ }
+ if (opts.media && typeof opts.media === "string") {
+ this.media.mediaText = opts.media;
+ }
+ if (typeof opts.disabled === "boolean") {
+ this.disabled = opts.disabled;
+ }
+ }
+};
+
+
+CSSOM.CSSStyleSheet.prototype = Object.create(CSSOM.StyleSheet.prototype);
+CSSOM.CSSStyleSheet.prototype.constructor = CSSOM.CSSStyleSheet;
+
+Object.setPrototypeOf(CSSOM.CSSStyleSheet, CSSOM.StyleSheet);
+
+Object.defineProperty(CSSOM.CSSStyleSheet.prototype, "cssRules", {
+ get: function() {
+ return this.__cssRules;
+ }
+});
+
+Object.defineProperty(CSSOM.CSSStyleSheet.prototype, "rules", {
+ get: function() {
+ return this.__cssRules;
+ }
+});
+
+Object.defineProperty(CSSOM.CSSStyleSheet.prototype, "ownerRule", {
+ get: function() {
+ return this.__ownerRule;
+ }
+});
+
+/**
+ * Used to insert a new rule into the style sheet. The new rule now becomes part of the cascade.
+ *
+ * sheet = new Sheet("body {margin: 0}")
+ * sheet.toString()
+ * -> "body{margin:0;}"
+ * sheet.insertRule("img {border: none}", 0)
+ * -> 0
+ * sheet.toString()
+ * -> "img{border:none;}body{margin:0;}"
+ *
+ * @param {string} rule
+ * @param {number} [index=0]
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-insertRule
+ * @return {number} The index within the style sheet's rule collection of the newly inserted rule.
+ */
+CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) {
+ if (rule === undefined && index === undefined) {
+ errorUtils.throwMissingArguments(this, 'insertRule', this.constructor.name);
+ }
+ if (index === void 0) {
+ index = 0;
+ }
+ index = Number(index);
+ if (index < 0) {
+ index = 4294967296 + index;
+ }
+ if (index > this.cssRules.length) {
+ errorUtils.throwIndexError(this, 'insertRule', this.constructor.name, index, this.cssRules.length);
+ }
+
+ var ruleToParse = String(rule);
+ var parseErrors = [];
+ var parsedSheet = CSSOM.parse(ruleToParse, undefined, function(err) {
+ parseErrors.push(err);
+ } );
+ if (parsedSheet.cssRules.length !== 1) {
+ errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
+ }
+ var cssRule = parsedSheet.cssRules[0];
+
+ // Helper function to find the last index of a specific rule constructor
+ function findLastIndexOfConstructor(rules, constructorName) {
+ for (var i = rules.length - 1; i >= 0; i--) {
+ if (rules[i].constructor.name === constructorName) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // Helper function to find the first index of a rule that's NOT of specified constructors
+ function findFirstNonConstructorIndex(rules, constructorNames) {
+ for (var i = 0; i < rules.length; i++) {
+ if (constructorNames.indexOf(rules[i].constructor.name) === -1) {
+ return i;
+ }
+ }
+ return rules.length;
+ }
+
+ // Validate rule ordering based on CSS specification
+ if (cssRule.constructor.name === 'CSSImportRule') {
+ if (this.__constructed === true) {
+ errorUtils.throwError(this, 'DOMException',
+ "Failed to execute 'insertRule' on '" + this.constructor.name + "': Can't insert @import rules into a constructed stylesheet.",
+ 'SyntaxError');
+ }
+ // @import rules cannot be inserted after @layer rules that already exist
+ // They can only be inserted at the beginning or after other @import rules
+ var firstLayerIndex = findFirstNonConstructorIndex(this.cssRules, ['CSSImportRule']);
+ if (firstLayerIndex < this.cssRules.length && this.cssRules[firstLayerIndex].constructor.name === 'CSSLayerStatementRule' && index > firstLayerIndex) {
+ errorUtils.throwError(this, 'DOMException',
+ "Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
+ 'HierarchyRequestError');
+ }
+
+ // Also cannot insert after @namespace or other rules
+ var firstNonImportIndex = findFirstNonConstructorIndex(this.cssRules, ['CSSImportRule']);
+ if (index > firstNonImportIndex && firstNonImportIndex < this.cssRules.length &&
+ this.cssRules[firstNonImportIndex].constructor.name !== 'CSSLayerStatementRule') {
+ errorUtils.throwError(this, 'DOMException',
+ "Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
+ 'HierarchyRequestError');
+ }
+ } else if (cssRule.constructor.name === 'CSSNamespaceRule') {
+ // @namespace rules can come after @layer and @import, but before any other rules
+ // They cannot come before @import rules
+ var firstImportIndex = -1;
+ for (var i = 0; i < this.cssRules.length; i++) {
+ if (this.cssRules[i].constructor.name === 'CSSImportRule') {
+ firstImportIndex = i;
+ break;
+ }
+ }
+ var firstNonImportNamespaceIndex = findFirstNonConstructorIndex(this.cssRules, [
+ 'CSSLayerStatementRule',
+ 'CSSImportRule',
+ 'CSSNamespaceRule'
+ ]);
+
+ // Cannot insert before @import rules
+ if (firstImportIndex !== -1 && index <= firstImportIndex) {
+ errorUtils.throwError(this, 'DOMException',
+ "Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
+ 'HierarchyRequestError');
+ }
+
+ // Cannot insert if there are already non-special rules
+ if (firstNonImportNamespaceIndex < this.cssRules.length) {
+ errorUtils.throwError(this, 'DOMException',
+ "Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
+ 'InvalidStateError');
+ }
+
+ // Cannot insert after other types of rules
+ if (index > firstNonImportNamespaceIndex) {
+ errorUtils.throwError(this, 'DOMException',
+ "Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
+ 'HierarchyRequestError');
+ }
+
+
+ } else if (cssRule.constructor.name === 'CSSLayerStatementRule') {
+ // @layer statement rules can be inserted anywhere before @import and @namespace
+ // No additional restrictions beyond what's already handled
+ } else {
+ // Any other rule cannot be inserted before @import and @namespace
+ var firstNonSpecialRuleIndex = findFirstNonConstructorIndex(this.cssRules, [
+ 'CSSLayerStatementRule',
+ 'CSSImportRule',
+ 'CSSNamespaceRule'
+ ]);
+
+ if (index < firstNonSpecialRuleIndex) {
+ errorUtils.throwError(this, 'DOMException',
+ "Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
+ 'HierarchyRequestError');
+ }
+
+ if (parseErrors.filter(function(error) { return !error.isNested; }).length !== 0) {
+ errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
+ }
+ }
+
+ cssRule.__parentStyleSheet = this;
+ this.cssRules.splice(index, 0, cssRule);
+ return index;
+};
+
+CSSOM.CSSStyleSheet.prototype.addRule = function(selector, styleBlock, index) {
+ if (index === void 0) {
+ index = this.cssRules.length;
+ }
+ this.insertRule(selector + "{" + styleBlock + "}", index);
+ return -1;
+};
+
+/**
+ * Used to delete a rule from the style sheet.
+ *
+ * sheet = new Sheet("img{border:none} body{margin:0}")
+ * sheet.toString()
+ * -> "img{border:none;}body{margin:0;}"
+ * sheet.deleteRule(0)
+ * sheet.toString()
+ * -> "body{margin:0;}"
+ *
+ * @param {number} index within the style sheet's rule list of the rule to remove.
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-deleteRule
+ */
+CSSOM.CSSStyleSheet.prototype.deleteRule = function(index) {
+ if (index === undefined) {
+ errorUtils.throwMissingArguments(this, 'deleteRule', this.constructor.name);
+ }
+ index = Number(index);
+ if (index < 0) {
+ index = 4294967296 + index;
+ }
+ if (index >= this.cssRules.length) {
+ errorUtils.throwIndexError(this, 'deleteRule', this.constructor.name, index, this.cssRules.length);
+ }
+ if (this.cssRules[index]) {
+ if (this.cssRules[index].constructor.name == "CSSNamespaceRule") {
+ var shouldContinue = this.cssRules.every(function (rule) {
+ return ['CSSImportRule','CSSLayerStatementRule','CSSNamespaceRule'].indexOf(rule.constructor.name) !== -1
+ });
+ if (!shouldContinue) {
+ errorUtils.throwError(this, 'DOMException', "Failed to execute 'deleteRule' on '" + this.constructor.name + "': Failed to delete rule.", "InvalidStateError");
+ }
+ }
+ if (this.cssRules[index].constructor.name == "CSSImportRule") {
+ this.cssRules[index].styleSheet.__parentStyleSheet = null;
+ }
+
+ this.cssRules[index].__parentStyleSheet = null;
+ }
+ this.cssRules.splice(index, 1);
+};
+
+CSSOM.CSSStyleSheet.prototype.removeRule = function(index) {
+ if (index === void 0) {
+ index = 0;
+ }
+ this.deleteRule(index);
+};
+
+
+/**
+ * Replaces the rules of a {@link CSSStyleSheet}
+ *
+ * @returns a promise
+ * @see https://www.w3.org/TR/cssom-1/#dom-cssstylesheet-replace
+ */
+CSSOM.CSSStyleSheet.prototype.replace = function(text) {
+ var _Promise;
+ if (this.__globalObject && this.__globalObject['Promise']) {
+ _Promise = this.__globalObject['Promise'];
+ } else {
+ _Promise = Promise;
+ }
+ var _setTimeout;
+ if (this.__globalObject && this.__globalObject['setTimeout']) {
+ _setTimeout = this.__globalObject['setTimeout'];
+ } else {
+ _setTimeout = setTimeout;
+ }
+ var sheet = this;
+ return new _Promise(function (resolve, reject) {
+ // If the constructed flag is not set, or the disallow modification flag is set, throw a NotAllowedError DOMException.
+ if (!sheet.__constructed || sheet.__disallowModification) {
+ reject(errorUtils.createError(sheet, 'DOMException',
+ "Failed to execute 'replaceSync' on '" + sheet.constructor.name + "': Not allowed.",
+ 'NotAllowedError'));
+ }
+ // Set the disallow modification flag.
+ sheet.__disallowModification = true;
+
+ // In parallel, do these steps:
+ _setTimeout(function() {
+ // Let rules be the result of running parse a stylesheet's contents from text.
+ var rules = new CSSOM.CSSRuleList();
+ CSSOM.parse(text, { styleSheet: sheet, cssRules: rules });
+ // If rules contains one or more @import rules, remove those rules from rules.
+ var i = 0;
+ while (i < rules.length) {
+ if (rules[i].constructor.name === 'CSSImportRule') {
+ rules.splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+ // Set sheet's CSS rules to rules.
+ sheet.__cssRules.splice.apply(sheet.__cssRules, [0, sheet.__cssRules.length].concat(rules));
+ // Unset sheet’s disallow modification flag.
+ delete sheet.__disallowModification;
+ // Resolve promise with sheet.
+ resolve(sheet);
+ })
+ });
+}
+
+/**
+ * Synchronously replaces the rules of a {@link CSSStyleSheet}
+ *
+ * @see https://www.w3.org/TR/cssom-1/#dom-cssstylesheet-replacesync
+ */
+CSSOM.CSSStyleSheet.prototype.replaceSync = function(text) {
+ var sheet = this;
+ // If the constructed flag is not set, or the disallow modification flag is set, throw a NotAllowedError DOMException.
+ if (!sheet.__constructed || sheet.__disallowModification) {
+ errorUtils.throwError(sheet, 'DOMException',
+ "Failed to execute 'replaceSync' on '" + sheet.constructor.name + "': Not allowed.",
+ 'NotAllowedError');
+ }
+ // Let rules be the result of running parse a stylesheet's contents from text.
+ var rules = new CSSOM.CSSRuleList();
+ CSSOM.parse(text, { styleSheet: sheet, cssRules: rules });
+ // If rules contains one or more @import rules, remove those rules from rules.
+ var i = 0;
+ while (i < rules.length) {
+ if (rules[i].constructor.name === 'CSSImportRule') {
+ rules.splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+ // Set sheet's CSS rules to rules.
+ sheet.__cssRules.splice.apply(sheet.__cssRules, [0, sheet.__cssRules.length].concat(rules));
+}
+
+/**
+ * NON-STANDARD
+ * @return {string} serialize stylesheet
+ */
+CSSOM.CSSStyleSheet.prototype.toString = function() {
+ var result = "";
+ var rules = this.cssRules;
+ for (var i=0; i<rules.length; i++) {
+ result += rules[i].cssText + "\n";
+ }
+ return result;
+};
+
+
+//.CommonJS
+exports.CSSStyleSheet = CSSOM.CSSStyleSheet;
+CSSOM.parse = require('./parse').parse; // Cannot be included sooner due to the mutual dependency between parse.js and CSSStyleSheet.js
+///CommonJS