Sorry, the diff of this file is too big to display
@@ -5,3 +5,9 @@ "use strict"; | ||
| const idlUtils = require("../../../generated/idl/utils.js"); | ||
| const propertyDefinitions = require("../../../generated/css-property-definitions"); | ||
| const propertyDescriptors = require("../../../generated/css-property-descriptors"); | ||
| const propertyMetadata = require("../../../generated/css-property-metadata"); | ||
| const { asciiLowercase } = require("../helpers/strings"); | ||
| const computedStyle = require("./helpers/computed-style"); | ||
| const cssValues = require("./helpers/css-values"); | ||
| const csstree = require("./helpers/patched-csstree"); | ||
| const { | ||
@@ -15,7 +21,3 @@ borderProperties, | ||
| } = require("./helpers/shorthand-properties"); | ||
| const { | ||
| hasVarFunc, isGlobalKeyword, parsePropertyValue | ||
| } = require("./helpers/css-values"); | ||
| const csstree = require("./helpers/patched-csstree"); | ||
| const { asciiLowercase } = require("../helpers/strings"); | ||
| const { systemColors } = require("./helpers/system-colors"); | ||
@@ -25,3 +27,3 @@ class CSSStyleDeclarationImpl { | ||
| // `_priorities` and `#values` together represent the spec's "declarations". | ||
| #computed; | ||
| _computed; | ||
| _readonly = false; | ||
@@ -34,6 +36,9 @@ _priorities = new Map(); | ||
| // Internal private fields. | ||
| #computedValueOpts = new Map(); | ||
| #cachedPropertyValues = new Map(); | ||
| constructor(globalObject, args, { computed, ownerNode, parentRule } = {}) { | ||
| this._globalObject = globalObject; | ||
| this.#computed = Boolean(computed); | ||
| this._computed = Boolean(computed); | ||
| this.parentRule = parentRule || null; | ||
@@ -49,3 +54,3 @@ this.#ownerNode = ownerNode || null; | ||
| get cssText() { | ||
| if (this.#computed) { | ||
| if (this._computed) { | ||
| return ""; | ||
@@ -94,29 +99,39 @@ } | ||
| this._priorities.clear(); | ||
| try { | ||
| this.#updating = true; | ||
| const valueObj = csstree.parse(text, { context: "declarationList", parseValue: false }); | ||
| if (valueObj?.children) { | ||
| const properties = new Map(); | ||
| let shouldSkipNext = false; | ||
| for (const item of valueObj.children) { | ||
| if (item.type === "Atrule") { | ||
| continue; | ||
| } | ||
| if (item.type === "Rule") { | ||
| shouldSkipNext = true; | ||
| continue; | ||
| } | ||
| if (shouldSkipNext === true) { | ||
| shouldSkipNext = false; | ||
| continue; | ||
| } | ||
| const { | ||
| important, | ||
| property, | ||
| value: { value } | ||
| } = item; | ||
| if (typeof property === "string" && typeof value === "string") { | ||
| const priority = important ? "important" : ""; | ||
| const isCustomProperty = property.startsWith("--"); | ||
| if (isCustomProperty || hasVarFunc(value)) { | ||
| this.#updating = true; | ||
| const valueObj = csstree.parse(text, { context: "declarationList", parseValue: false }); | ||
| if (valueObj?.children) { | ||
| const properties = new Map(); | ||
| let shouldSkipNext = false; | ||
| for (const item of valueObj.children) { | ||
| if (item.type === "Atrule") { | ||
| continue; | ||
| } | ||
| if (item.type === "Rule") { | ||
| shouldSkipNext = true; | ||
| continue; | ||
| } | ||
| if (shouldSkipNext === true) { | ||
| shouldSkipNext = false; | ||
| continue; | ||
| } | ||
| const { | ||
| important, | ||
| property, | ||
| value: { value } | ||
| } = item; | ||
| if (typeof property === "string" && typeof value === "string") { | ||
| const priority = important ? "important" : ""; | ||
| const isCustomProperty = property.startsWith("--"); | ||
| if (isCustomProperty || cssValues.hasVarFunc(value)) { | ||
| if (properties.has(property)) { | ||
| const { priority: itemPriority } = properties.get(property); | ||
| if (!itemPriority) { | ||
| properties.set(property, { property, value, priority }); | ||
| } | ||
| } else { | ||
| properties.set(property, { property, value, priority }); | ||
| } | ||
| } else { | ||
| const parsedValue = cssValues.parsePropertyValue(property, value); | ||
| if (parsedValue) { | ||
| if (properties.has(property)) { | ||
@@ -131,30 +146,15 @@ const { priority: itemPriority } = properties.get(property); | ||
| } else { | ||
| const parsedValue = parsePropertyValue(property, value); | ||
| if (parsedValue) { | ||
| if (properties.has(property)) { | ||
| const { priority: itemPriority } = properties.get(property); | ||
| if (!itemPriority) { | ||
| properties.set(property, { property, value, priority }); | ||
| } | ||
| } else { | ||
| properties.set(property, { property, value, priority }); | ||
| } | ||
| } else { | ||
| this.removeProperty(property); | ||
| } | ||
| this.removeProperty(property); | ||
| } | ||
| } | ||
| } | ||
| const parsedProperties = prepareProperties(properties); | ||
| for (const [property, item] of parsedProperties) { | ||
| const { priority, value } = item; | ||
| this._priorities.set(property, priority); | ||
| this.setProperty(property, value, priority); | ||
| } | ||
| } | ||
| } catch { | ||
| return; | ||
| } finally { | ||
| this.#updating = false; | ||
| const parsedProperties = prepareProperties(properties); | ||
| for (const [property, item] of parsedProperties) { | ||
| const { priority, value } = item; | ||
| this._priorities.set(property, priority); | ||
| this.setProperty(property, value, priority); | ||
| } | ||
| } | ||
| this.#updating = false; | ||
| this.#updateStyleAttribute(); | ||
@@ -189,6 +189,21 @@ } | ||
| getPropertyValue(property) { | ||
| if (this.#values.has(property)) { | ||
| return this.#values.get(property).toString(); | ||
| const value = this.#values.get(property) ?? ""; | ||
| if (this._computed) { | ||
| if (this.#cachedPropertyValues.has(property)) { | ||
| const cachedValue = this.#cachedPropertyValues.get(property); | ||
| // Return the cached resolved value if the specified value haven't changed. | ||
| if (value === cachedValue.value) { | ||
| return cachedValue.resolvedValue; | ||
| } | ||
| } | ||
| const resolvedValue = this.#getComputedValue(property, value); | ||
| if (propertyDefinitions.has(property)) { | ||
| const { longhands } = propertyDefinitions.get(property); | ||
| if (!longhands) { | ||
| this.#cachedPropertyValues.set(property, { resolvedValue, value }); | ||
| } | ||
| } | ||
| return resolvedValue; | ||
| } | ||
| return ""; | ||
| return value; | ||
| } | ||
@@ -289,3 +304,3 @@ | ||
| #updateStyleAttribute() { | ||
| if (this.#computed || !this.#ownerNode || this.#ownerNode._settingCssText) { | ||
| if (this._computed || !this.#ownerNode || this.#ownerNode._settingCssText) { | ||
| return; | ||
@@ -325,2 +340,215 @@ } | ||
| #getComputedValue(property, value) { | ||
| // Invalid or unsupported property. | ||
| if (!propertyDefinitions.has(property) && !property.startsWith("--")) { | ||
| return ""; | ||
| } | ||
| const { inherited, initial = "", longhands } = cssValues.getPropertyDefinition(property); | ||
| const { caseSensitive, functionTypes = {} } = this.#getPropertyMetadata(property); | ||
| const isColor = Boolean(functionTypes.color || functionTypes.paint); | ||
| if (!value || cssValues.isGlobalKeyword(value)) { | ||
| value = computedStyle.replaceEmptyValueAndKeywords( | ||
| property, | ||
| value, | ||
| this.#ownerNode, | ||
| { inherit: inherited === "yes", initial, isColor, longhands } | ||
| ); | ||
| } | ||
| if (property === "color" && /currentcolor/i.test(value)) { | ||
| value = computedStyle.getInheritedPropertyValue( | ||
| property, | ||
| this.#ownerNode, | ||
| { inherit: true, initial, isColor } | ||
| ); | ||
| } | ||
| if (cssValues.hasVarFunc(value)) { | ||
| // TODO: Resolve css var(). | ||
| } | ||
| if (longhands) { | ||
| if (isColor) { | ||
| value = asciiLowercase(value); | ||
| if (systemColors.has(value)) { | ||
| return value; | ||
| } | ||
| } | ||
| return this.#resolveShorthand(property, value); | ||
| } | ||
| return this.#resolveLonghand(property, value, { caseSensitive, isColor }); | ||
| } | ||
| #getPropertyMetadata(property) { | ||
| if (propertyMetadata.has(property)) { | ||
| return propertyMetadata.get(property); | ||
| } | ||
| const value = this.#values.get(property) ?? ""; | ||
| // TODO: Also check if all or part of the value is quoted. | ||
| const caseSensitive = (cssValues.hasVarFunc(value) || value.startsWith("--")) ? true : undefined; | ||
| return { caseSensitive }; | ||
| } | ||
| #resolveShorthand(property, value) { | ||
| // TODO: resolve other shorthands e.g. background, flex etc. | ||
| switch (property) { | ||
| case "margin": | ||
| case "padding": { | ||
| return this.#resolvePositionShorthand(property); | ||
| } | ||
| default: { | ||
| if (property.startsWith("border")) { | ||
| return this.#resolveBorderShorthands(property); | ||
| } | ||
| return value; | ||
| } | ||
| } | ||
| } | ||
| #resolvePositionShorthand(property) { | ||
| const shorthandItem = shorthandProperties.get(property); | ||
| if (!shorthandItem || !shorthandItem.shorthandFor) { | ||
| return ""; | ||
| } | ||
| const longhandValues = []; | ||
| for (const [longhandProperty] of shorthandItem.shorthandFor) { | ||
| longhandValues.push(this.getPropertyValue(longhandProperty)); | ||
| } | ||
| return getPositionValue(longhandValues); | ||
| } | ||
| #resolveLonghand(property, value, { caseSensitive, isColor }) { | ||
| const options = this.#prepareComputedValueOpts(); | ||
| const parsedValue = cssValues.parsePropertyValue(property, value, { | ||
| caseSensitive, | ||
| ...options | ||
| }); | ||
| if (isColor) { | ||
| const resolvedValue = cssValues.serializeColor(parsedValue, options); | ||
| if (resolvedValue) { | ||
| return resolvedValue; | ||
| } | ||
| } | ||
| // TODO: Resolve special cases other than color. | ||
| return value; | ||
| } | ||
| #resolveBorderShorthands(property) { | ||
| switch (property) { | ||
| case "border": { | ||
| const values = []; | ||
| for (const item of ["top", "right", "bottom", "left"]) { | ||
| const value = this.getPropertyValue(`border-${item}`); | ||
| if (!value) { | ||
| return ""; | ||
| } | ||
| values.push(value); | ||
| } | ||
| const [top, right, bottom, left] = values; | ||
| if (top === right && top === bottom && top === left) { | ||
| return top; | ||
| } | ||
| return ""; | ||
| } | ||
| case "border-top": | ||
| case "border-right": | ||
| case "border-bottom": | ||
| case "border-left": { | ||
| const values = []; | ||
| for (const item of ["width", "style", "color"]) { | ||
| const value = this.getPropertyValue(`${property}-${item}`); | ||
| if (!value) { | ||
| return ""; | ||
| } | ||
| values.push(value); | ||
| } | ||
| return values.join(" "); | ||
| } | ||
| // border-width, border-style, border-color | ||
| default: { | ||
| return this.#resolvePositionShorthand(property); | ||
| } | ||
| } | ||
| } | ||
| // Options are used when resolving relative values or specified values. | ||
| #prepareComputedValueOpts() { | ||
| if (!this.#computedValueOpts.has("options")) { | ||
| this.#computedValueOpts.set("options", { format: "computedValue" }); | ||
| } | ||
| const options = this.#computedValueOpts.get("options"); | ||
| // Return the cached options if the specified raw values haven't changed. | ||
| const rawColorScheme = this.#values.get("color-scheme") ?? ""; | ||
| const rawColor = this.#values.get("color") ?? ""; | ||
| if ( | ||
| this.#computedValueOpts.get("rawColorScheme") === rawColorScheme && | ||
| this.#computedValueOpts.get("rawColor") === rawColor | ||
| ) { | ||
| return options; | ||
| } | ||
| // Store current raw values for future cache validation. | ||
| this.#computedValueOpts.set("rawColorScheme", rawColorScheme); | ||
| this.#computedValueOpts.set("rawColor", rawColor); | ||
| // Prepare color-scheme. | ||
| const colorScheme = computedStyle.replaceEmptyValueAndKeywords( | ||
| "color-scheme", | ||
| rawColorScheme, | ||
| this.#ownerNode, | ||
| { inherit: true, initial: "normal" } | ||
| ); | ||
| this.#cachedPropertyValues.set("color-scheme", { | ||
| resolvedValue: colorScheme, | ||
| value: rawColorScheme | ||
| }); | ||
| options.colorScheme = colorScheme; | ||
| // Prepare current color. | ||
| let currentColor = computedStyle.replaceEmptyValueAndKeywords( | ||
| "color", | ||
| rawColor, | ||
| this.#ownerNode, | ||
| { inherit: true, initial: "canvastext" } | ||
| ); | ||
| currentColor = asciiLowercase(currentColor); | ||
| // Replace currentcolor keyword. | ||
| if (currentColor === "currentcolor") { | ||
| currentColor = computedStyle.getInheritedPropertyValue( | ||
| "color", | ||
| this.#ownerNode, | ||
| { inherit: true, initial: "canvastext", isColor: true } | ||
| ); | ||
| } | ||
| // Resolve system colors. | ||
| if (systemColors.has(currentColor)) { | ||
| currentColor = cssValues.resolveSystemColorValue(currentColor, colorScheme); | ||
| } else { | ||
| // Resolve named colors. | ||
| if (/^[a-z]+$/.test(currentColor)) { | ||
| currentColor = cssValues.resolveColor(currentColor, { format: "computedValue" }); | ||
| } | ||
| this.#cachedPropertyValues.set("color", { | ||
| resolvedValue: currentColor, | ||
| value: rawColor | ||
| }); | ||
| } | ||
| options.currentColor = currentColor; | ||
| // TODO: Add customProperty, dimension etc. | ||
| // Store options. | ||
| this.#computedValueOpts.set("options", options); | ||
| return options; | ||
| } | ||
| /** | ||
@@ -340,3 +568,3 @@ * Helper to handle border property expansion. | ||
| if (property === "border") { | ||
| properties.set(property, { propery: property, value, priority }); | ||
| properties.set(property, { property, value, priority }); | ||
| } else { | ||
@@ -390,3 +618,3 @@ for (const itemProperty of this.#values.keys()) { | ||
| } | ||
| if (value && !hasVarFunc(value)) { | ||
| if (value && !cssValues.hasVarFunc(value)) { | ||
| const longhandValues = []; | ||
@@ -397,3 +625,3 @@ const shorthandItem = shorthandProperties.get(shorthandProperty); | ||
| if (longhandProperty === property) { | ||
| if (isGlobalKeyword(value)) { | ||
| if (cssValues.isGlobalKeyword(value)) { | ||
| hasGlobalKeyword = true; | ||
@@ -408,3 +636,3 @@ } | ||
| } | ||
| if (isGlobalKeyword(longhandValue)) { | ||
| if (cssValues.isGlobalKeyword(longhandValue)) { | ||
| hasGlobalKeyword = true; | ||
@@ -501,3 +729,3 @@ } | ||
| } | ||
| if (value && !hasVarFunc(value)) { | ||
| if (value && !cssValues.hasVarFunc(value)) { | ||
| const longhandValues = []; | ||
@@ -504,0 +732,0 @@ const { shorthandFor, position: shorthandPosition } = shorthandProperties.get(shorthandProperty); |
@@ -5,12 +5,12 @@ "use strict"; | ||
| const path = require("node:path"); | ||
| const { parseStyleSheet } = require("./css-parser"); | ||
| const CSSStyleRule = require("../../../../generated/idl/CSSStyleRule.js"); | ||
| const Specificity = require("@bramus/specificity").default; | ||
| const CSSImportRule = require("../../../../generated/idl/CSSImportRule.js"); | ||
| const CSSMediaRule = require("../../../../generated/idl/CSSMediaRule.js"); | ||
| const Specificity = require("@bramus/specificity").default; | ||
| const CSSStyleProperties = require("../../../../generated/idl/CSSStyleProperties.js"); | ||
| const { getSpecifiedColor, getComputedOrUsedColor } = require("./colors"); | ||
| const CSSStyleRule = require("../../../../generated/idl/CSSStyleRule.js"); | ||
| const { asciiLowercase } = require("../../helpers/strings"); | ||
| const { evaluateMediaList } = require("../MediaList-impl.js"); | ||
| const { deprecatedAliases, systemColors } = require("./system-colors"); | ||
| const { parseStyleSheet } = require("./css-parser"); | ||
| const { isGlobalKeyword } = require("./css-values"); | ||
| const { systemColors } = require("./system-colors"); | ||
@@ -23,96 +23,2 @@ const defaultStyleSheet = fs.readFileSync( | ||
| // Properties for which getResolvedValue is implemented. This is less than | ||
| // every supported property. | ||
| // https://drafts.csswg.org/indexes/#properties | ||
| const propertiesWithResolvedValueImplemented = { | ||
| "__proto__": null, | ||
| // https://drafts.csswg.org/css2/visufx.html#visibility | ||
| "visibility": { | ||
| inherited: true, | ||
| initial: "visible", | ||
| computedValue: "as-specified" | ||
| }, | ||
| // https://svgwg.org/svg2-draft/interact.html#PointerEventsProperty | ||
| "pointer-events": { | ||
| inherited: true, | ||
| initial: "auto", | ||
| computedValue: "as-specified" | ||
| }, | ||
| // https://drafts.csswg.org/css-backgrounds-3/#propdef-background-color | ||
| "background-color": { | ||
| inherited: false, | ||
| initial: "transparent", | ||
| computedValue: "computed-color" | ||
| }, | ||
| // https://drafts.csswg.org/css-logical-1/#propdef-border-block-end-color | ||
| "border-block-start-color": { | ||
| inherited: false, | ||
| initial: "currentcolor", | ||
| computedValue: "computed-color" | ||
| }, | ||
| "border-block-end-color": { | ||
| inherited: false, | ||
| initial: "currentcolor", | ||
| computedValue: "computed-color" | ||
| }, | ||
| "border-inline-start-color": { | ||
| inherited: false, | ||
| initial: "currentcolor", | ||
| computedValue: "computed-color" | ||
| }, | ||
| "border-inline-end-color": { | ||
| inherited: false, | ||
| initial: "currentcolor", | ||
| computedValue: "computed-color" | ||
| }, | ||
| // https://drafts.csswg.org/css-backgrounds-3/#propdef-border-bottom-color | ||
| "border-top-color": { | ||
| inherited: false, | ||
| initial: "currentcolor", | ||
| computedValue: "computed-color" | ||
| }, | ||
| "border-right-color": { | ||
| inherited: false, | ||
| initial: "currentcolor", | ||
| computedValue: "computed-color" | ||
| }, | ||
| "border-bottom-color": { | ||
| inherited: false, | ||
| initial: "currentcolor", | ||
| computedValue: "computed-color" | ||
| }, | ||
| "border-left-color": { | ||
| inherited: false, | ||
| initial: "currentcolor", | ||
| computedValue: "computed-color" | ||
| }, | ||
| // https://drafts.csswg.org/css-ui-4/#propdef-caret-color | ||
| "caret-color": { | ||
| inherited: true, | ||
| initial: "auto", | ||
| computedValue: "computed-color" | ||
| }, | ||
| // https://drafts.csswg.org/css-color-4/#propdef-color | ||
| "color": { | ||
| inherited: true, | ||
| initial: "canvastext", | ||
| computedValue: "computed-color" | ||
| }, | ||
| // https://drafts.csswg.org/css-ui-4/#propdef-outline-color | ||
| "outline-color": { | ||
| inherited: false, | ||
| initial: "invert", | ||
| computedValue: "computed-color" | ||
| }, | ||
| // https://drafts.csswg.org/css-display/#the-display-properties | ||
| // Currently only "as-specified" is supported as a computed value | ||
| "display": { | ||
| inherited: false, | ||
| initial: "inline", | ||
| computedValue: "as-specified" | ||
| } | ||
| }; | ||
| const implementedProperties = Object.keys(propertiesWithResolvedValueImplemented); | ||
| function getComputedStyleDeclaration(elementImpl) { | ||
@@ -133,2 +39,3 @@ const styleCache = elementImpl._ownerDocument._styleCache; | ||
| } | ||
| clonedDeclaration._readonly = true; | ||
@@ -138,8 +45,3 @@ return clonedDeclaration; | ||
| const declaration = prepareComputedStyleDeclaration(elementImpl, { styleCache }); | ||
| // TODO: Remove later. | ||
| for (const property of implementedProperties) { | ||
| declaration.setProperty(property, getResolvedValue(elementImpl, property)); | ||
| } | ||
| const declaration = prepareComputedStyleDeclaration(elementImpl, styleCache); | ||
| declaration._readonly = true; | ||
@@ -150,3 +52,3 @@ | ||
| function prepareComputedStyleDeclaration(elementImpl, { styleCache }) { | ||
| function prepareComputedStyleDeclaration(elementImpl, styleCache) { | ||
| const { style } = elementImpl; | ||
@@ -246,138 +148,123 @@ const declaration = CSSStyleProperties.createImpl(elementImpl._globalObject, [], { | ||
| function matches(selectorText, elementImpl) { | ||
| try { | ||
| const domSelector = elementImpl._ownerDocument._getDOMSelector(); | ||
| const { ast, match, pseudoElement } = domSelector.check(selectorText, elementImpl); | ||
| // `pseudoElement` is a pseudo-element selector (e.g. `::before`). | ||
| // However, we do not support getComputedStyle(element, pseudoElement), so `match` is set to `false`. | ||
| if (pseudoElement) { | ||
| return { | ||
| match: false | ||
| }; | ||
| } | ||
| return { ast, match, pseudoElement }; | ||
| } catch { | ||
| // fall through | ||
| const domSelector = elementImpl._ownerDocument._getDOMSelector(); | ||
| const { ast, match, pseudoElement } = domSelector.check(selectorText, elementImpl); | ||
| // `pseudoElement` is a pseudo-element selector (e.g. `::before`). | ||
| // However, we do not support getComputedStyle(element, pseudoElement), so `match` is set to `false`. | ||
| if (pseudoElement) { | ||
| return { | ||
| match: false | ||
| }; | ||
| } | ||
| return { | ||
| match: false | ||
| }; | ||
| return { ast, match, pseudoElement }; | ||
| } | ||
| // Naive implementation of https://drafts.csswg.org/css-cascade-4/#cascading | ||
| // based on the previous jsdom implementation of getComputedStyle. | ||
| // Does not implement https://drafts.csswg.org/css-cascade-4/#cascade-specificity, | ||
| // or rather specificity is only implemented by the order in which the matching | ||
| // rules appear. The last rule is the most specific while the first rule is | ||
| // the least specific. | ||
| function getCascadedPropertyValue(element, property) { | ||
| const cached = element._ownerDocument._styleCache.get(element); | ||
| if (cached) { | ||
| return cached.getPropertyValue(property); | ||
| } | ||
| return getComputedStyleDeclaration(element).getPropertyValue(property); | ||
| } | ||
| // https://drafts.csswg.org/css-cascade-4/#specified-value | ||
| function getSpecifiedValue(element, property) { | ||
| const { initial, inherited, computedValue } = propertiesWithResolvedValueImplemented[property]; | ||
| const cascade = getCascadedPropertyValue(element, property); | ||
| if (cascade !== "") { | ||
| if (computedValue === "computed-color") { | ||
| return getSpecifiedColor(cascade); | ||
| function replaceEmptyValueAndKeywords(property, value, elementImpl, { inherit, initial, isColor, longhands }) { | ||
| if (value === "") { | ||
| if (longhands) { | ||
| return ""; | ||
| } else if (!inherit || !elementImpl.parentElement) { | ||
| return initial; | ||
| } | ||
| return cascade; | ||
| value = getInheritedPropertyValue(property, elementImpl, { inherit, initial, isColor }); | ||
| } | ||
| // Defaulting | ||
| if (inherited && element.parentElement !== null) { | ||
| return getComputedValue(element.parentElement, property); | ||
| if (isGlobalKeyword(value)) { | ||
| value = replaceGlobalKeywords(property, value, elementImpl, { inherit, initial, isColor }); | ||
| } | ||
| // root element without parent element or inherited property | ||
| return initial; | ||
| return value; | ||
| } | ||
| // https://drafts.csswg.org/css-cascade-4/#computed-value | ||
| function getComputedValue(element, property) { | ||
| const { computedValue, inherited, initial } = propertiesWithResolvedValueImplemented[property]; | ||
| let specifiedValue = getSpecifiedValue(element, property); | ||
| // https://drafts.csswg.org/css-cascade/#defaulting-keywords | ||
| switch (specifiedValue) { | ||
| case "initial": { | ||
| specifiedValue = initial; | ||
| break; | ||
| function getInheritedPropertyValue(property, elementImpl, { inherit, initial, isColor }) { | ||
| const styleCache = elementImpl._ownerDocument._styleCache; | ||
| const { parentElement } = elementImpl; | ||
| if (!parentElement) { | ||
| return initial; | ||
| } | ||
| let parent = parentElement; | ||
| while (parent) { | ||
| let declaration; | ||
| if (styleCache.has(parent)) { | ||
| declaration = styleCache.get(parent); | ||
| } else { | ||
| declaration = prepareComputedStyleDeclaration(parent, styleCache); | ||
| } | ||
| case "inherit": { | ||
| if (element.parentElement !== null) { | ||
| specifiedValue = getComputedValue(element.parentElement, property); | ||
| } else { | ||
| specifiedValue = initial; | ||
| // For color-related properties, unset the _computed flag to retrieve the specified value. | ||
| // @asamuzakjp/css-color handles the resolution of the specified value. | ||
| if (isColor) { | ||
| declaration._computed = false; | ||
| } | ||
| let value = declaration.getPropertyValue(property); | ||
| if (isColor) { | ||
| // Restore the _computed flag. | ||
| declaration._computed = true; | ||
| // If the value is a system color value, retrieve it again as a computed value. | ||
| if (value && systemColors.has(asciiLowercase(value))) { | ||
| value = declaration.getPropertyValue(property); | ||
| } | ||
| break; | ||
| } | ||
| case "unset": { | ||
| if (inherited && element.parentElement !== null) { | ||
| specifiedValue = getComputedValue(element.parentElement, property); | ||
| } else { | ||
| specifiedValue = initial; | ||
| if (value) { | ||
| if (isColor && isGlobalKeyword(value)) { | ||
| return replaceGlobalKeywords(property, value, parent, { inherit, initial, isColor }); | ||
| } | ||
| return value; | ||
| } else if (!parent.parentElement || !inherit) { | ||
| break; | ||
| } | ||
| // TODO: https://drafts.csswg.org/css-cascade-5/#revert-layer | ||
| case "revert-layer": { | ||
| break; | ||
| } | ||
| // TODO: https://drafts.csswg.org/css-cascade-5/#default | ||
| case "revert": { | ||
| break; | ||
| } | ||
| default: { | ||
| // fall through; specifiedValue is not a CSS-wide keyword. | ||
| } | ||
| parent = parent.parentElement; | ||
| } | ||
| if (computedValue === "as-specified") { | ||
| return specifiedValue; | ||
| } else if (computedValue === "computed-color") { | ||
| let value = asciiLowercase(specifiedValue); | ||
| // https://drafts.csswg.org/css-color-4/#resolving-other-colors | ||
| if (specifiedValue === "currentcolor") { | ||
| if (property === "color") { | ||
| if (element.parentElement !== null) { | ||
| return getComputedValue(element.parentElement, "color"); | ||
| return initial; | ||
| } | ||
| function replaceGlobalKeywords(property, value, elementImpl, { inherit, initial, isColor }) { | ||
| let element = elementImpl; | ||
| while (element) { | ||
| switch (value) { | ||
| case "initial": { | ||
| return initial; | ||
| } | ||
| case "inherit": { | ||
| if (!element.parentElement) { | ||
| return initial; | ||
| } | ||
| value = initial; | ||
| } else { | ||
| return getComputedValue(element, "color"); | ||
| value = getInheritedPropertyValue(property, element, { inherit, initial, isColor }); | ||
| break; | ||
| } | ||
| } | ||
| if (systemColors.has(value) || deprecatedAliases.has(value)) { | ||
| let key = value; | ||
| if (deprecatedAliases.has(value)) { | ||
| key = deprecatedAliases.get(value); | ||
| case "unset": { | ||
| if (!inherit || !element.parentElement) { | ||
| return initial; | ||
| } | ||
| value = getInheritedPropertyValue(property, element, { inherit, initial, isColor }); | ||
| break; | ||
| } | ||
| const { light, dark } = systemColors.get(key); | ||
| const colorScheme = getCascadedPropertyValue(element, "color-scheme"); | ||
| if (colorScheme === "dark") { | ||
| return dark; | ||
| case "revert-layer": { | ||
| // TODO: https://drafts.csswg.org/css-cascade-5/#revert-layer | ||
| return value; | ||
| } | ||
| return light; | ||
| case "revert": { | ||
| // TODO: https://drafts.csswg.org/css-cascade-5/#default | ||
| return value; | ||
| } | ||
| default: { | ||
| // fall through; value is not a CSS-wide keyword. | ||
| } | ||
| } | ||
| return getComputedOrUsedColor(specifiedValue); | ||
| if (element.parentElement) { | ||
| if (!value) { | ||
| element = element.parentElement; | ||
| } else if (isGlobalKeyword(value)) { | ||
| return replaceGlobalKeywords(property, value, element, { inherit, initial, isColor }); | ||
| } else { | ||
| return value; | ||
| } | ||
| } else { | ||
| return initial; | ||
| } | ||
| } | ||
| throw new TypeError(`Internal error: unrecognized computed value instruction '${computedValue}'`); | ||
| return value; | ||
| } | ||
| // https://drafts.csswg.org/cssom/#resolved-value | ||
| // Only implements the properties that are defined in propertiesWithResolvedValueImplemented. | ||
| function getResolvedValue(element, property) { | ||
| // We can always use the computed value with the current set of propertiesWithResolvedValueImplemented: | ||
| // * Color properties end up with the used value, but we don't implement any actual differences between used and | ||
| // computed that https://drafts.csswg.org/css-cascade-5/#used-value gestures at. | ||
| // * The other properties fall back to the "any other property: The resolved value is the computed value." case. | ||
| return getComputedValue(element, property); | ||
| } | ||
| function invalidateStyleCache(elementImpl) { | ||
@@ -389,6 +276,6 @@ if (elementImpl._attached) { | ||
| module.exports = { | ||
| SHADOW_DOM_PSEUDO_REGEXP: /^::(?:part|slotted)\(/i, | ||
| getComputedStyleDeclaration, | ||
| invalidateStyleCache | ||
| }; | ||
| exports.SHADOW_DOM_PSEUDO_REGEXP = /^::(?:part|slotted)\(/i; | ||
| exports.getComputedStyleDeclaration = getComputedStyleDeclaration; | ||
| exports.getInheritedPropertyValue = getInheritedPropertyValue; | ||
| exports.invalidateStyleCache = invalidateStyleCache; | ||
| exports.replaceEmptyValueAndKeywords = replaceEmptyValueAndKeywords; |
@@ -11,2 +11,3 @@ "use strict"; | ||
| const { asciiLowercase } = require("../../helpers/strings"); | ||
| const { systemColors } = require("./system-colors"); | ||
@@ -20,50 +21,2 @@ // Constants | ||
| // System colors | ||
| // @see https://drafts.csswg.org/css-color/#css-system-colors | ||
| // @see https://drafts.csswg.org/css-color/#deprecated-system-colors | ||
| const SYS_COLORS = new Set([ | ||
| "accentcolor", | ||
| "accentcolortext", | ||
| "activeborder", | ||
| "activecaption", | ||
| "activetext", | ||
| "appworkspace", | ||
| "background", | ||
| "buttonborder", | ||
| "buttonface", | ||
| "buttonhighlight", | ||
| "buttonshadow", | ||
| "buttontext", | ||
| "canvas", | ||
| "canvastext", | ||
| "captiontext", | ||
| "field", | ||
| "fieldtext", | ||
| "graytext", | ||
| "highlight", | ||
| "highlighttext", | ||
| "inactiveborder", | ||
| "inactivecaption", | ||
| "inactivecaptiontext", | ||
| "infobackground", | ||
| "infotext", | ||
| "linktext", | ||
| "mark", | ||
| "marktext", | ||
| "menu", | ||
| "menutext", | ||
| "scrollbar", | ||
| "selecteditem", | ||
| "selecteditemtext", | ||
| "threeddarkshadow", | ||
| "threedface", | ||
| "threedhighlight", | ||
| "threedlightshadow", | ||
| "threedshadow", | ||
| "visitedtext", | ||
| "window", | ||
| "windowframe", | ||
| "windowtext" | ||
| ]); | ||
| // AST node types | ||
@@ -95,2 +48,11 @@ const AST_TYPES = Object.freeze({ | ||
| function getPropertyDefinition(property) { | ||
| if (propertyDefinitions.has(property)) { | ||
| return propertyDefinitions.get(property); | ||
| } else if (property.startsWith("--")) { | ||
| return { inherited: "yes", initial: "" }; | ||
| } | ||
| return {}; | ||
| } | ||
| /** | ||
@@ -173,3 +135,3 @@ * Checks if the value is a global keyword. | ||
| } | ||
| const cacheKey = `resolveCalc_${val}`; | ||
| const cacheKey = `resolveCalc_${val}_${opt.format}`; | ||
| const cachedValue = lruCache.get(cacheKey); | ||
@@ -520,12 +482,12 @@ if (typeof cachedValue === "string") { | ||
| * @param {Array<object>} val - The AST value. | ||
| * @param {object} [opt={ format: "specifiedValue" }] - The options for parsing. | ||
| * @returns {string|undefined} The serialized color. | ||
| */ | ||
| function serializeColor(val) { | ||
| function serializeColor(val, opt = { format: "specifiedValue" }) { | ||
| const [item] = val; | ||
| const { name, type, value } = item ?? {}; | ||
| const lowerCasedName = asciiLowercase(`${name}`); | ||
| switch (type) { | ||
| case AST_TYPES.FUNCTION: { | ||
| const res = resolveColor(`${name}(${value})`, { | ||
| format: "specifiedValue" | ||
| }); | ||
| const res = resolveColor(`${lowerCasedName}(${value})`, opt); | ||
| if (res) { | ||
@@ -537,5 +499,3 @@ return res; | ||
| case AST_TYPES.HASH: { | ||
| const res = resolveColor(`#${value}`, { | ||
| format: "specifiedValue" | ||
| }); | ||
| const res = resolveColor(`#${value}`, opt); | ||
| if (res) { | ||
@@ -547,8 +507,9 @@ return res; | ||
| case AST_TYPES.IDENTIFIER: { | ||
| if (SYS_COLORS.has(name)) { | ||
| return name; | ||
| if (systemColors.has(lowerCasedName)) { | ||
| if (opt.format === "specifiedValue") { | ||
| return lowerCasedName; | ||
| } | ||
| return resolveSystemColorValue(lowerCasedName, opt.colorScheme); | ||
| } | ||
| const res = resolveColor(name, { | ||
| format: "specifiedValue" | ||
| }); | ||
| const res = resolveColor(lowerCasedName, opt); | ||
| if (res) { | ||
@@ -711,3 +672,3 @@ return res; | ||
| default: { | ||
| return serializeColor(value, opt); | ||
| return serializeColor(value); | ||
| } | ||
@@ -738,6 +699,6 @@ } | ||
| case AST_TYPES.URL: { | ||
| return serializeURL(value, opt); | ||
| return serializeURL(value); | ||
| } | ||
| default: { | ||
| return serializeGradient(value, opt); | ||
| return serializeGradient(value); | ||
| } | ||
@@ -747,2 +708,13 @@ } | ||
| function resolveSystemColorValue(value, colorScheme = "normal") { | ||
| if (!systemColors.has(value)) { | ||
| return value; | ||
| } | ||
| const { light, dark } = systemColors.get(value); | ||
| if (colorScheme === "dark") { | ||
| return dark; | ||
| } | ||
| return light; | ||
| } | ||
| /** | ||
@@ -828,2 +800,3 @@ * Resolves a border shorthand value. | ||
| exports.AST_TYPES = AST_TYPES; | ||
| exports.getPropertyDefinition = getPropertyDefinition; | ||
| exports.hasCalcFunc = hasCalcFunc; | ||
@@ -836,2 +809,3 @@ exports.hasVarFunc = hasVarFunc; | ||
| exports.resolveCalc = resolveCalc; | ||
| exports.resolveColor = resolveColor; | ||
| exports.resolveColorValue = resolveColorValue; | ||
@@ -842,2 +816,3 @@ exports.resolveFunctionValue = resolveFunctionValue; | ||
| exports.resolveNumericValue = resolveNumericValue; | ||
| exports.resolveSystemColorValue = resolveSystemColorValue; | ||
| exports.serializeAngle = serializeAngle; | ||
@@ -844,0 +819,0 @@ exports.serializeColor = serializeColor; |
@@ -7,3 +7,2 @@ "use strict"; | ||
| const backgroundColor = require("../properties/backgroundColor"); | ||
| const backgroundSize = require("../properties/backgroundSize"); | ||
| const border = require("../properties/border"); | ||
@@ -217,4 +216,3 @@ const borderWidth = require("../properties/borderWidth"); | ||
| const { value: propertyValue } = properties.get(property); | ||
| const parsedValue = background.shorthandFor.get(property).parse(propertyValue); | ||
| const values = splitValue(parsedValue, { | ||
| const values = splitValue(propertyValue, { | ||
| delimiter: "," | ||
@@ -226,6 +224,6 @@ }); | ||
| if (property === backgroundColor.property) { | ||
| bgValues[bgLength - 1][property] = parsedValue[0]; | ||
| bgValues[bgLength - 1][property] = values[0]; | ||
| } else { | ||
| for (let i = 0; i < bgLength; i++) { | ||
| bgValues[i][property] = values[i]; | ||
| bgValues[i][property] = values[i] !== undefined ? values[i] : values[0]; | ||
| } | ||
@@ -236,10 +234,34 @@ } | ||
| const bg = []; | ||
| for (const [longhand, value] of Object.entries(bgValue)) { | ||
| if (!value || value === background.initialValues.get(longhand)) { | ||
| let hasPosition = false; | ||
| const originValue = bgValue["background-origin"]; | ||
| const clipValue = bgValue["background-clip"]; | ||
| const isDefaultBox = | ||
| originValue === background.initialValues.get("background-origin") && | ||
| clipValue === background.initialValues.get("background-clip"); | ||
| for (const longhand of background.initialValues.keys()) { | ||
| const value = bgValue[longhand]; | ||
| if (!value) { | ||
| continue; | ||
| } | ||
| if (longhand === backgroundSize.property) { | ||
| bg.push(`/ ${value}`); | ||
| } else { | ||
| bg.push(value); | ||
| if (longhand === "background-origin") { | ||
| if (!isDefaultBox) { | ||
| bg.push(originValue); | ||
| } | ||
| } else if (longhand === "background-clip") { | ||
| if (!isDefaultBox && originValue !== clipValue) { | ||
| bg.push(clipValue); | ||
| } | ||
| } else if (value !== background.initialValues.get(longhand)) { | ||
| if (longhand === "background-position") { | ||
| hasPosition = true; | ||
| bg.push(value); | ||
| } else if (longhand === "background-size") { | ||
| if (hasPosition) { | ||
| bg.push(`/ ${value}`); | ||
| } else { | ||
| bg.push(background.initialValues.get("background-position"), `/ ${value}`); | ||
| } | ||
| } else { | ||
| bg.push(value); | ||
| } | ||
| } | ||
@@ -1334,3 +1356,3 @@ } | ||
| const { logicalPropertyGroup: shorthandProperty } = propertyDefinitions.get(property) ?? {}; | ||
| if (borderProperties.has(property)) { | ||
| if (borderProperties.has(property) && !hasVarFunc(value)) { | ||
| borders.set(property, { property, value, priority }); | ||
@@ -1337,0 +1359,0 @@ } else if (shorthandProperties.has(shorthandProperty)) { |
| "use strict"; | ||
| // https://drafts.csswg.org/css-color-4/#css-system-colors | ||
| module.exports.systemColors = new Map([ | ||
| const systemColors = new Map([ | ||
| [ | ||
@@ -123,3 +123,3 @@ "accentcolor", { | ||
| // https://drafts.csswg.org/css-color-4/#deprecated-system-colors | ||
| module.exports.deprecatedAliases = new Map([ | ||
| const deprecatedAliases = new Map([ | ||
| ["activeborder", "buttonborder"], | ||
@@ -149,1 +149,11 @@ ["activecaption", "canvas"], | ||
| ]); | ||
| function getAllSystemColors() { | ||
| const allColors = new Map(systemColors); | ||
| for (const [alias, target] of deprecatedAliases) { | ||
| allColors.set(alias, systemColors.get(target)); | ||
| } | ||
| return allColors; | ||
| } | ||
| exports.systemColors = getAllSystemColors(); |
@@ -70,21 +70,38 @@ "use strict"; | ||
| const bg = []; | ||
| for (const [longhand, value] of Object.entries(bgValue)) { | ||
| let hasPosition = false; | ||
| const originValue = bgValue[backgroundOrigin.property]; | ||
| const clipValue = bgValue[backgroundClip.property]; | ||
| const isDefaultBox = | ||
| originValue === initialValues.get(backgroundOrigin.property) && | ||
| clipValue === initialValues.get(backgroundClip.property); | ||
| for (const [longhand] of shorthandFor) { | ||
| const value = bgValue[longhand]; | ||
| if (value) { | ||
| const arr = bgMap.get(longhand); | ||
| arr.push(value); | ||
| bgMap.set(longhand, arr); | ||
| if (value !== initialValues.get(longhand)) { | ||
| if (longhand === backgroundSize.property) { | ||
| bg.push(`/ ${value}`); | ||
| } else { | ||
| bg.push(value); | ||
| if (longhand === backgroundOrigin.property) { | ||
| if (!isDefaultBox) { | ||
| bg.push(originValue); | ||
| } | ||
| } else if (longhand === backgroundImage.property) { | ||
| if (v === "none") { | ||
| bg.push(value); | ||
| } else if (longhand === backgroundClip.property) { | ||
| if (!isDefaultBox && originValue !== clipValue) { | ||
| bg.push(clipValue); | ||
| } | ||
| } else if (longhand === backgroundColor.property) { | ||
| if (v === "transparent") { | ||
| } else if (value !== initialValues.get(longhand)) { | ||
| if (longhand === backgroundPosition.property) { | ||
| hasPosition = true; | ||
| bg.push(value); | ||
| } else if (longhand === backgroundSize.property) { | ||
| if (hasPosition) { | ||
| bg.push(`/ ${value}`); | ||
| } else { | ||
| bg.push(initialValues.get(backgroundPosition.property), `/ ${value}`); | ||
| } | ||
| } else { | ||
| bg.push(value); | ||
| } | ||
| } else if (longhand === backgroundImage.property && v === "none") { | ||
| bg.push(value); | ||
| } else if (longhand === backgroundColor.property && v === "transparent") { | ||
| bg.push(value); | ||
| } | ||
@@ -119,2 +136,5 @@ } | ||
| const val = this.getPropertyValue(longhand); | ||
| if (!val || parsers.hasVarFunc(val)) { | ||
| return ""; | ||
| } | ||
| if (longhand === backgroundImage.property) { | ||
@@ -128,3 +148,3 @@ if (val === "none" && v === "none" && this.getPropertyValue(backgroundColor.property) === "transparent") { | ||
| }); | ||
| l = imgValues.length; | ||
| l = Math.max(l, imgValues.length); | ||
| bgMap.set(longhand, imgValues); | ||
@@ -137,8 +157,7 @@ } | ||
| } else if (val !== initialValues.get(longhand)) { | ||
| bgMap.set( | ||
| longhand, | ||
| parsers.splitValue(val, { | ||
| delimiter: "," | ||
| }) | ||
| ); | ||
| const values = parsers.splitValue(val, { | ||
| delimiter: "," | ||
| }); | ||
| l = Math.max(l, values.length); | ||
| bgMap.set(longhand, values); | ||
| } | ||
@@ -156,49 +175,69 @@ } | ||
| for (let i = 0; i < l; i++) { | ||
| bgValues[i] = []; | ||
| } | ||
| for (const [longhand, values] of bgMap) { | ||
| for (let i = 0; i < l; i++) { | ||
| switch (longhand) { | ||
| case backgroundColor.property: { | ||
| if (i === l - 1) { | ||
| const value = values[0]; | ||
| if (parsers.hasVarFunc(value)) { | ||
| return ""; | ||
| } | ||
| if (value && value !== initialValues.get(longhand)) { | ||
| const bgValue = bgValues[i]; | ||
| bgValue.push(value); | ||
| } | ||
| } | ||
| break; | ||
| const bg = []; | ||
| let hasPosition = false; | ||
| let originValue, clipValue; | ||
| const originValues = bgMap.get(backgroundOrigin.property); | ||
| const clipValues = bgMap.get(backgroundClip.property); | ||
| if (originValues) { | ||
| if (originValues[i] !== undefined) { | ||
| originValue = originValues[i]; | ||
| } else { | ||
| originValue = initialValues.get(backgroundOrigin.property); | ||
| } | ||
| } else { | ||
| originValue = initialValues.get(backgroundOrigin.property); | ||
| } | ||
| if (clipValues) { | ||
| if (clipValues[i] !== undefined) { | ||
| clipValue = clipValues[i]; | ||
| } else { | ||
| clipValue = initialValues.get(backgroundClip.property); | ||
| } | ||
| } else { | ||
| clipValue = initialValues.get(backgroundClip.property); | ||
| } | ||
| const isDefaultBox = | ||
| originValue === initialValues.get(backgroundOrigin.property) && | ||
| clipValue === initialValues.get(backgroundClip.property); | ||
| for (const [longhand] of shorthandFor) { | ||
| let value; | ||
| if (bgMap.has(longhand)) { | ||
| const values = bgMap.get(longhand); | ||
| value = values[i] !== undefined ? values[i] : initialValues.get(longhand); | ||
| } else { | ||
| value = initialValues.get(longhand); | ||
| } | ||
| if (parsers.hasVarFunc(value)) { | ||
| return ""; | ||
| } | ||
| if (longhand === backgroundOrigin.property) { | ||
| if (!isDefaultBox) { | ||
| bg.push(originValue); | ||
| } | ||
| case backgroundSize.property: { | ||
| const value = values[i]; | ||
| if (parsers.hasVarFunc(value)) { | ||
| return ""; | ||
| } | ||
| if (value && value !== initialValues.get(longhand)) { | ||
| const bgValue = bgValues[i]; | ||
| bgValue.push(`/ ${value}`); | ||
| } | ||
| break; | ||
| } else if (longhand === backgroundClip.property) { | ||
| if (!isDefaultBox && originValue !== clipValue) { | ||
| bg.push(clipValue); | ||
| } | ||
| default: { | ||
| const value = values[i]; | ||
| if (parsers.hasVarFunc(value)) { | ||
| return ""; | ||
| } else if (longhand === backgroundColor.property) { | ||
| if (i === l - 1 && (value !== initialValues.get(longhand) || bgMap.has(longhand))) { | ||
| bg.push(value); | ||
| } | ||
| } else if (value !== initialValues.get(longhand)) { | ||
| if (longhand === backgroundPosition.property) { | ||
| hasPosition = true; | ||
| bg.push(value); | ||
| } else if (longhand === backgroundSize.property) { | ||
| if (hasPosition) { | ||
| bg.push(`/ ${value}`); | ||
| } else { | ||
| bg.push(initialValues.get(backgroundPosition.property), `/ ${value}`); | ||
| } | ||
| if (value && value !== initialValues.get(longhand)) { | ||
| const bgValue = bgValues[i]; | ||
| bgValue.push(value); | ||
| } | ||
| } else { | ||
| bg.push(value); | ||
| } | ||
| } | ||
| } | ||
| bgValues.push(bg.join(" ")); | ||
| } | ||
| const backgrounds = []; | ||
| for (const bgValue of bgValues) { | ||
| backgrounds.push(bgValue.join(" ")); | ||
| } | ||
| return backgrounds.join(", "); | ||
| return bgValues.join(", "); | ||
| }, | ||
@@ -205,0 +244,0 @@ enumerable: true, |
+3
-3
| { | ||
| "name": "jsdom", | ||
| "version": "29.0.1", | ||
| "version": "29.0.2", | ||
| "description": "A JavaScript implementation of many web standards", | ||
@@ -26,4 +26,4 @@ "keywords": [ | ||
| "dependencies": { | ||
| "@asamuzakjp/css-color": "^5.0.1", | ||
| "@asamuzakjp/dom-selector": "^7.0.3", | ||
| "@asamuzakjp/css-color": "^5.1.5", | ||
| "@asamuzakjp/dom-selector": "^7.0.6", | ||
| "@bramus/specificity": "^2.4.2", | ||
@@ -30,0 +30,0 @@ "@csstools/css-syntax-patches-for-csstree": "^1.1.1", |
| "use strict"; | ||
| // https://drafts.csswg.org/css-color-4/#named-color | ||
| const namedColors = { | ||
| __proto__: null, | ||
| aliceblue: [0xF0, 0xF8, 0xFF], | ||
| antiquewhite: [0xFA, 0xEB, 0xD7], | ||
| aqua: [0x00, 0xFF, 0xFF], | ||
| aquamarine: [0x7F, 0xFF, 0xD4], | ||
| azure: [0xF0, 0xFF, 0xFF], | ||
| beige: [0xF5, 0xF5, 0xDC], | ||
| bisque: [0xFF, 0xE4, 0xC4], | ||
| black: [0x00, 0x00, 0x00], | ||
| blanchedalmond: [0xFF, 0xEB, 0xCD], | ||
| blue: [0x00, 0x00, 0xFF], | ||
| blueviolet: [0x8A, 0x2B, 0xE2], | ||
| brown: [0xA5, 0x2A, 0x2A], | ||
| burlywood: [0xDE, 0xB8, 0x87], | ||
| cadetblue: [0x5F, 0x9E, 0xA0], | ||
| chartreuse: [0x7F, 0xFF, 0x00], | ||
| chocolate: [0xD2, 0x69, 0x1E], | ||
| coral: [0xFF, 0x7F, 0x50], | ||
| cornflowerblue: [0x64, 0x95, 0xED], | ||
| cornsilk: [0xFF, 0xF8, 0xDC], | ||
| crimson: [0xDC, 0x14, 0x3C], | ||
| cyan: [0x00, 0xFF, 0xFF], | ||
| darkblue: [0x00, 0x00, 0x8B], | ||
| darkcyan: [0x00, 0x8B, 0x8B], | ||
| darkgoldenrod: [0xB8, 0x86, 0x0B], | ||
| darkgray: [0xA9, 0xA9, 0xA9], | ||
| darkgreen: [0x00, 0x64, 0x00], | ||
| darkgrey: [0xA9, 0xA9, 0xA9], | ||
| darkkhaki: [0xBD, 0xB7, 0x6B], | ||
| darkmagenta: [0x8B, 0x00, 0x8B], | ||
| darkolivegreen: [0x55, 0x6B, 0x2F], | ||
| darkorange: [0xFF, 0x8C, 0x00], | ||
| darkorchid: [0x99, 0x32, 0xCC], | ||
| darkred: [0x8B, 0x00, 0x00], | ||
| darksalmon: [0xE9, 0x96, 0x7A], | ||
| darkseagreen: [0x8F, 0xBC, 0x8F], | ||
| darkslateblue: [0x48, 0x3D, 0x8B], | ||
| darkslategray: [0x2F, 0x4F, 0x4F], | ||
| darkslategrey: [0x2F, 0x4F, 0x4F], | ||
| darkturquoise: [0x00, 0xCE, 0xD1], | ||
| darkviolet: [0x94, 0x00, 0xD3], | ||
| deeppink: [0xFF, 0x14, 0x93], | ||
| deepskyblue: [0x00, 0xBF, 0xFF], | ||
| dimgray: [0x69, 0x69, 0x69], | ||
| dimgrey: [0x69, 0x69, 0x69], | ||
| dodgerblue: [0x1E, 0x90, 0xFF], | ||
| firebrick: [0xB2, 0x22, 0x22], | ||
| floralwhite: [0xFF, 0xFA, 0xF0], | ||
| forestgreen: [0x22, 0x8B, 0x22], | ||
| fuchsia: [0xFF, 0x00, 0xFF], | ||
| gainsboro: [0xDC, 0xDC, 0xDC], | ||
| ghostwhite: [0xF8, 0xF8, 0xFF], | ||
| gold: [0xFF, 0xD7, 0x00], | ||
| goldenrod: [0xDA, 0xA5, 0x20], | ||
| gray: [0x80, 0x80, 0x80], | ||
| green: [0x00, 0x80, 0x00], | ||
| greenyellow: [0xAD, 0xFF, 0x2F], | ||
| grey: [0x80, 0x80, 0x80], | ||
| honeydew: [0xF0, 0xFF, 0xF0], | ||
| hotpink: [0xFF, 0x69, 0xB4], | ||
| indianred: [0xCD, 0x5C, 0x5C], | ||
| indigo: [0x4B, 0x00, 0x82], | ||
| ivory: [0xFF, 0xFF, 0xF0], | ||
| khaki: [0xF0, 0xE6, 0x8C], | ||
| lavender: [0xE6, 0xE6, 0xFA], | ||
| lavenderblush: [0xFF, 0xF0, 0xF5], | ||
| lawngreen: [0x7C, 0xFC, 0x00], | ||
| lemonchiffon: [0xFF, 0xFA, 0xCD], | ||
| lightblue: [0xAD, 0xD8, 0xE6], | ||
| lightcoral: [0xF0, 0x80, 0x80], | ||
| lightcyan: [0xE0, 0xFF, 0xFF], | ||
| lightgoldenrodyellow: [0xFA, 0xFA, 0xD2], | ||
| lightgray: [0xD3, 0xD3, 0xD3], | ||
| lightgreen: [0x90, 0xEE, 0x90], | ||
| lightgrey: [0xD3, 0xD3, 0xD3], | ||
| lightpink: [0xFF, 0xB6, 0xC1], | ||
| lightsalmon: [0xFF, 0xA0, 0x7A], | ||
| lightseagreen: [0x20, 0xB2, 0xAA], | ||
| lightskyblue: [0x87, 0xCE, 0xFA], | ||
| lightslategray: [0x77, 0x88, 0x99], | ||
| lightslategrey: [0x77, 0x88, 0x99], | ||
| lightsteelblue: [0xB0, 0xC4, 0xDE], | ||
| lightyellow: [0xFF, 0xFF, 0xE0], | ||
| lime: [0x00, 0xFF, 0x00], | ||
| limegreen: [0x32, 0xCD, 0x32], | ||
| linen: [0xFA, 0xF0, 0xE6], | ||
| magenta: [0xFF, 0x00, 0xFF], | ||
| maroon: [0x80, 0x00, 0x00], | ||
| mediumaquamarine: [0x66, 0xCD, 0xAA], | ||
| mediumblue: [0x00, 0x00, 0xCD], | ||
| mediumorchid: [0xBA, 0x55, 0xD3], | ||
| mediumpurple: [0x93, 0x70, 0xDB], | ||
| mediumseagreen: [0x3C, 0xB3, 0x71], | ||
| mediumslateblue: [0x7B, 0x68, 0xEE], | ||
| mediumspringgreen: [0x00, 0xFA, 0x9A], | ||
| mediumturquoise: [0x48, 0xD1, 0xCC], | ||
| mediumvioletred: [0xC7, 0x15, 0x85], | ||
| midnightblue: [0x19, 0x19, 0x70], | ||
| mintcream: [0xF5, 0xFF, 0xFA], | ||
| mistyrose: [0xFF, 0xE4, 0xE1], | ||
| moccasin: [0xFF, 0xE4, 0xB5], | ||
| navajowhite: [0xFF, 0xDE, 0xAD], | ||
| navy: [0x00, 0x00, 0x80], | ||
| oldlace: [0xFD, 0xF5, 0xE6], | ||
| olive: [0x80, 0x80, 0x00], | ||
| olivedrab: [0x6B, 0x8E, 0x23], | ||
| orange: [0xFF, 0xA5, 0x00], | ||
| orangered: [0xFF, 0x45, 0x00], | ||
| orchid: [0xDA, 0x70, 0xD6], | ||
| palegoldenrod: [0xEE, 0xE8, 0xAA], | ||
| palegreen: [0x98, 0xFB, 0x98], | ||
| paleturquoise: [0xAF, 0xEE, 0xEE], | ||
| palevioletred: [0xDB, 0x70, 0x93], | ||
| papayawhip: [0xFF, 0xEF, 0xD5], | ||
| peachpuff: [0xFF, 0xDA, 0xB9], | ||
| peru: [0xCD, 0x85, 0x3F], | ||
| pink: [0xFF, 0xC0, 0xCB], | ||
| plum: [0xDD, 0xA0, 0xDD], | ||
| powderblue: [0xB0, 0xE0, 0xE6], | ||
| purple: [0x80, 0x00, 0x80], | ||
| rebeccapurple: [0x66, 0x33, 0x99], | ||
| red: [0xFF, 0x00, 0x00], | ||
| rosybrown: [0xBC, 0x8F, 0x8F], | ||
| royalblue: [0x41, 0x69, 0xE1], | ||
| saddlebrown: [0x8B, 0x45, 0x13], | ||
| salmon: [0xFA, 0x80, 0x72], | ||
| sandybrown: [0xF4, 0xA4, 0x60], | ||
| seagreen: [0x2E, 0x8B, 0x57], | ||
| seashell: [0xFF, 0xF5, 0xEE], | ||
| sienna: [0xA0, 0x52, 0x2D], | ||
| silver: [0xC0, 0xC0, 0xC0], | ||
| skyblue: [0x87, 0xCE, 0xEB], | ||
| slateblue: [0x6A, 0x5A, 0xCD], | ||
| slategray: [0x70, 0x80, 0x90], | ||
| slategrey: [0x70, 0x80, 0x90], | ||
| snow: [0xFF, 0xFA, 0xFA], | ||
| springgreen: [0x00, 0xFF, 0x7F], | ||
| steelblue: [0x46, 0x82, 0xB4], | ||
| tan: [0xD2, 0xB4, 0x8C], | ||
| teal: [0x00, 0x80, 0x80], | ||
| thistle: [0xD8, 0xBF, 0xD8], | ||
| tomato: [0xFF, 0x63, 0x47], | ||
| turquoise: [0x40, 0xE0, 0xD0], | ||
| violet: [0xEE, 0x82, 0xEE], | ||
| wheat: [0xF5, 0xDE, 0xB3], | ||
| white: [0xFF, 0xFF, 0xFF], | ||
| whitesmoke: [0xF5, 0xF5, 0xF5], | ||
| yellow: [0xFF, 0xFF, 0x00], | ||
| yellowgreen: [0x9A, 0xCD, 0x32] | ||
| }; | ||
| // Implements some of https://drafts.csswg.org/css-color-4/#resolving-sRGB-values and | ||
| // https://drafts.csswg.org/css-color-4/#serializing-sRGB-values, in a somewhat fragile way since | ||
| // we're not using a real parser/serializer. Attempts to cover: | ||
| // * hex colors | ||
| // * 'rgb()' and 'rgba()' values | ||
| // * named colors | ||
| // * 'transparent' | ||
| exports.getSpecifiedColor = color => { | ||
| const lowercasedColor = color.toLowerCase(); | ||
| if (Object.hasOwn(namedColors, lowercasedColor) || lowercasedColor === "transparent") { | ||
| return lowercasedColor; | ||
| } | ||
| return sharedSpecifiedAndComputedAndUsed(color); | ||
| }; | ||
| exports.getComputedOrUsedColor = color => { | ||
| const lowercasedColor = color.toLowerCase(); | ||
| const fromNamedColors = namedColors[lowercasedColor]; | ||
| if (fromNamedColors !== undefined) { | ||
| return `rgb(${fromNamedColors.join(", ")})`; | ||
| } | ||
| if (lowercasedColor === "transparent") { | ||
| return "rgba(0, 0, 0, 0)"; | ||
| } | ||
| return sharedSpecifiedAndComputedAndUsed(color); | ||
| }; | ||
| function sharedSpecifiedAndComputedAndUsed(color) { | ||
| if (/^#[0-9A-Fa-f]{6}$/.test(color) || /^#[0-9A-Fa-f]{3}$/.test(color)) { | ||
| return hexToRGB(color.slice(1)); | ||
| } | ||
| if (/^#[0-9A-Fa-f]{8}$/.test(color) || /^#[0-9A-Fa-f]{4}$/.test(color)) { | ||
| return hexToRGBA(color.slice(1)); | ||
| } | ||
| if (/^rgba?\(/.test(color)) { | ||
| return color.split(",").map(s => s.trim()).join(", "); | ||
| } | ||
| return color; | ||
| } | ||
| function hexToRGB(color) { | ||
| if (color.length === 6) { | ||
| const [r1, r2, g1, g2, b1, b2] = color.split(""); | ||
| return `rgb(${hexesToDecimals([r1, r2], [g1, g2], [b1, b2]).join(", ")})`; | ||
| } | ||
| if (color.length === 3) { | ||
| const [r1, g1, b1] = color.split(""); | ||
| return `rgb(${hexesToDecimals([r1, r1], [g1, g1], [b1, b1]).join(", ")})`; | ||
| } | ||
| return "rgb(0, 0, 0)"; | ||
| } | ||
| function hexToRGBA(color) { | ||
| if (color.length === 8) { | ||
| const [r1, r2, g1, g2, b1, b2, a1, a2] = color.split(""); | ||
| return `rgba(${hexesToDecimals([r1, r2], [g1, g2], [b1, b2]).join(", ")}, ${hexToPercent(a1, a2)})`; | ||
| } | ||
| if (color.length === 4) { | ||
| const [r1, g1, b1, a1] = color.split(""); | ||
| return `rgba(${hexesToDecimals([r1, r1], [g1, g1], [b1, b1]).join(", ")}, ${hexToPercent(a1, a1)})`; | ||
| } | ||
| return "rgba(0, 0, 0, 1)"; | ||
| } | ||
| function hexToDecimal(d1, d2) { | ||
| return parseInt(d1, 16) * 16 + parseInt(d2, 16); | ||
| } | ||
| function hexesToDecimals(...hexes) { | ||
| return hexes.map(pair => hexToDecimal(pair[0], pair[1])); | ||
| } | ||
| function hexToPercent(d1, d2) { | ||
| return Math.floor(1000 * hexToDecimal(d1, d2) / 255) / 1000; | ||
| } |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "border-block-end-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the border-block-end-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "border-block-start-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the border-block-start-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "border-collapse"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the border-collapse property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveKeywordValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "border-inline-end-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the border-inline-end-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "border-inline-start-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the border-inline-start-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "clear"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the clear property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveKeywordValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "float"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the float property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveKeywordValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "flood-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the flood-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "lighting-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the lighting-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "outline-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the outline-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "stop-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the stop-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "text-emphasis-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the text-emphasis-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "-webkit-text-fill-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the -webkit-text-fill-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
| "use strict"; | ||
| const parsers = require("../helpers/css-values"); | ||
| const property = "-webkit-text-stroke-color"; | ||
| const descriptor = { | ||
| set(v) { | ||
| v = v.trim(); | ||
| if (parsers.hasVarFunc(v)) { | ||
| this._setProperty(property, v); | ||
| } else { | ||
| const val = parse(v); | ||
| if (typeof val === "string") { | ||
| const priority = this._priorities.get(property) ?? ""; | ||
| this._setProperty(property, val, priority); | ||
| } | ||
| } | ||
| }, | ||
| get() { | ||
| return this.getPropertyValue(property); | ||
| }, | ||
| enumerable: true, | ||
| configurable: true | ||
| }; | ||
| /** | ||
| * Parses the -webkit-text-stroke-color property value. | ||
| * | ||
| * @param {string} v - The value to parse. | ||
| * @returns {string|undefined} The parsed value or undefined if invalid. | ||
| */ | ||
| function parse(v) { | ||
| if (v === "") { | ||
| return v; | ||
| } | ||
| const value = parsers.parsePropertyValue(property, v); | ||
| if (Array.isArray(value) && value.length === 1) { | ||
| return parsers.resolveColorValue(value); | ||
| } else if (typeof value === "string") { | ||
| return value; | ||
| } | ||
| return undefined; | ||
| } | ||
| module.exports = { | ||
| descriptor, | ||
| parse, | ||
| property | ||
| }; |
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
7027994
1.43%183634
3.93%652
-2.25%