diff options
Diffstat (limited to 'vanilla/node_modules/@acemir/cssom/lib/CSSKeyframesRule.js')
| -rw-r--r-- | vanilla/node_modules/@acemir/cssom/lib/CSSKeyframesRule.js | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/vanilla/node_modules/@acemir/cssom/lib/CSSKeyframesRule.js b/vanilla/node_modules/@acemir/cssom/lib/CSSKeyframesRule.js new file mode 100644 index 0000000..a98cd78 --- /dev/null +++ b/vanilla/node_modules/@acemir/cssom/lib/CSSKeyframesRule.js @@ -0,0 +1,247 @@ +//.CommonJS +var CSSOM = { + CSSRule: require("./CSSRule").CSSRule, + CSSRuleList: require("./CSSRuleList").CSSRuleList, + parse: require("./parse").parse +}; +var errorUtils = require("./errorUtils").errorUtils; +///CommonJS + + +/** + * @constructor + * @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframesRule + */ +CSSOM.CSSKeyframesRule = function CSSKeyframesRule() { + CSSOM.CSSRule.call(this); + this.name = ''; + this.cssRules = new CSSOM.CSSRuleList(); + + // Set up initial indexed access + this._setupIndexedAccess(); + + // Override cssRules methods after initial setup, store references as non-enumerable properties + var self = this; + var originalPush = this.cssRules.push; + var originalSplice = this.cssRules.splice; + + // Create non-enumerable method overrides + Object.defineProperty(this.cssRules, 'push', { + value: function() { + var result = originalPush.apply(this, arguments); + self._setupIndexedAccess(); + return result; + }, + writable: true, + enumerable: false, + configurable: true + }); + + Object.defineProperty(this.cssRules, 'splice', { + value: function() { + var result = originalSplice.apply(this, arguments); + self._setupIndexedAccess(); + return result; + }, + writable: true, + enumerable: false, + configurable: true + }); +}; + +CSSOM.CSSKeyframesRule.prototype = Object.create(CSSOM.CSSRule.prototype); +CSSOM.CSSKeyframesRule.prototype.constructor = CSSOM.CSSKeyframesRule; + +Object.setPrototypeOf(CSSOM.CSSKeyframesRule, CSSOM.CSSRule); + +Object.defineProperty(CSSOM.CSSKeyframesRule.prototype, "type", { + value: 7, + writable: false +}); + +// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframesRule.cpp +Object.defineProperty(CSSOM.CSSKeyframesRule.prototype, "cssText", { + get: function() { + var values = ""; + var valuesArr = [" {"]; + if (this.cssRules.length) { + valuesArr.push(this.cssRules.reduce(function(acc, rule){ + if (rule.cssText !== "") { + acc.push(rule.cssText); + } + return acc; + }, []).join("\n ")); + } + values = valuesArr.join("\n ") + "\n}"; + var cssWideKeywords = ['initial', 'inherit', 'revert', 'revert-layer', 'unset', 'none']; + var processedName = cssWideKeywords.includes(this.name) ? '"' + this.name + '"' : this.name; + return "@" + (this._vendorPrefix || '') + "keyframes " + processedName + values; + } +}); + +/** + * Appends a new keyframe rule to the list of keyframes. + * + * @param {string} rule - The keyframe rule string to append (e.g., "50% { opacity: 0.5; }") + * @see https://www.w3.org/TR/css-animations-1/#dom-csskeyframesrule-appendrule + */ +CSSOM.CSSKeyframesRule.prototype.appendRule = function appendRule(rule) { + if (arguments.length === 0) { + errorUtils.throwMissingArguments(this, 'appendRule', 'CSSKeyframesRule'); + } + + var parsedRule; + try { + // Parse the rule string as a keyframe rule + var tempStyleSheet = CSSOM.parse("@keyframes temp { " + rule + " }"); + if (tempStyleSheet.cssRules.length > 0 && tempStyleSheet.cssRules[0].cssRules.length > 0) { + parsedRule = tempStyleSheet.cssRules[0].cssRules[0]; + } else { + throw new Error("Failed to parse keyframe rule"); + } + } catch (e) { + errorUtils.throwParseError(this, 'appendRule', 'CSSKeyframesRule', rule); + } + + parsedRule.__parentRule = this; + this.cssRules.push(parsedRule); +}; + +/** + * Deletes a keyframe rule that matches the specified key. + * + * @param {string} select - The keyframe selector to delete (e.g., "50%", "from", "to") + * @see https://www.w3.org/TR/css-animations-1/#dom-csskeyframesrule-deleterule + */ +CSSOM.CSSKeyframesRule.prototype.deleteRule = function deleteRule(select) { + if (arguments.length === 0) { + errorUtils.throwMissingArguments(this, 'deleteRule', 'CSSKeyframesRule'); + } + + var normalizedSelect = this._normalizeKeyText(select); + + for (var i = 0; i < this.cssRules.length; i++) { + var rule = this.cssRules[i]; + if (this._normalizeKeyText(rule.keyText) === normalizedSelect) { + rule.__parentRule = null; + this.cssRules.splice(i, 1); + return; + } + } +}; + +/** + * Finds and returns the keyframe rule that matches the specified key. + * When multiple rules have the same key, returns the last one. + * + * @param {string} select - The keyframe selector to find (e.g., "50%", "from", "to") + * @return {CSSKeyframeRule|null} The matching keyframe rule, or null if not found + * @see https://www.w3.org/TR/css-animations-1/#dom-csskeyframesrule-findrule + */ +CSSOM.CSSKeyframesRule.prototype.findRule = function findRule(select) { + if (arguments.length === 0) { + errorUtils.throwMissingArguments(this, 'findRule', 'CSSKeyframesRule'); + } + + var normalizedSelect = this._normalizeKeyText(select); + + // Iterate backwards to find the last matching rule + for (var i = this.cssRules.length - 1; i >= 0; i--) { + var rule = this.cssRules[i]; + if (this._normalizeKeyText(rule.keyText) === normalizedSelect) { + return rule; + } + } + + return null; +}; + +/** + * Normalizes keyframe selector text for comparison. + * Handles "from" -> "0%" and "to" -> "100%" conversions and trims whitespace. + * + * @private + * @param {string} keyText - The keyframe selector text to normalize + * @return {string} The normalized keyframe selector text + */ +CSSOM.CSSKeyframesRule.prototype._normalizeKeyText = function _normalizeKeyText(keyText) { + if (!keyText) return ''; + + var normalized = keyText.toString().trim().toLowerCase(); + + // Convert keywords to percentages for comparison + if (normalized === 'from') { + return '0%'; + } else if (normalized === 'to') { + return '100%'; + } + + return normalized; +}; + +/** + * Makes CSSKeyframesRule iterable over its cssRules. + * Allows for...of loops and other iterable methods. + */ +if (typeof Symbol !== 'undefined' && Symbol.iterator) { + CSSOM.CSSKeyframesRule.prototype[Symbol.iterator] = function() { + var index = 0; + var cssRules = this.cssRules; + + return { + next: function() { + if (index < cssRules.length) { + return { value: cssRules[index++], done: false }; + } else { + return { done: true }; + } + } + }; + }; +} + +/** + * Adds indexed getters for direct access to cssRules by index. + * This enables rule[0], rule[1], etc. access patterns. + * Works in environments where Proxy is not available (like jsdom). + */ +CSSOM.CSSKeyframesRule.prototype._setupIndexedAccess = function() { + // Remove any existing indexed properties + for (var i = 0; i < 1000; i++) { // reasonable upper limit + if (this.hasOwnProperty(i)) { + delete this[i]; + } else { + break; + } + } + + // Add indexed getters for current cssRules + for (var i = 0; i < this.cssRules.length; i++) { + (function(index) { + Object.defineProperty(this, index, { + get: function() { + return this.cssRules[index]; + }, + enumerable: false, + configurable: true + }); + }.call(this, i)); + } + + // Update length property + Object.defineProperty(this, 'length', { + get: function() { + return this.cssRules.length; + }, + enumerable: false, + configurable: true + }); +}; + + + + + +//.CommonJS +exports.CSSKeyframesRule = CSSOM.CSSKeyframesRule; +///CommonJS |
