aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/cssstyle/lib/utils
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/cssstyle/lib/utils
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/cssstyle/lib/utils')
-rw-r--r--vanilla/node_modules/cssstyle/lib/utils/allExtraProperties.js155
-rw-r--r--vanilla/node_modules/cssstyle/lib/utils/camelize.js37
-rw-r--r--vanilla/node_modules/cssstyle/lib/utils/propertyDescriptors.js55
-rw-r--r--vanilla/node_modules/cssstyle/lib/utils/strings.js173
4 files changed, 420 insertions, 0 deletions
diff --git a/vanilla/node_modules/cssstyle/lib/utils/allExtraProperties.js b/vanilla/node_modules/cssstyle/lib/utils/allExtraProperties.js
new file mode 100644
index 0000000..a8d8711
--- /dev/null
+++ b/vanilla/node_modules/cssstyle/lib/utils/allExtraProperties.js
@@ -0,0 +1,155 @@
+"use strict";
+
+/**
+ * This file contains all implemented properties that are not a part of any
+ * current specifications or drafts, but are handled by browsers nevertheless.
+ */
+
+const webkitProperties = [
+ "background-composite",
+ "border-after",
+ "border-after-color",
+ "border-after-style",
+ "border-after-width",
+ "border-before",
+ "border-before-color",
+ "border-before-style",
+ "border-before-width",
+ "border-end",
+ "border-end-color",
+ "border-end-style",
+ "border-end-width",
+ "border-fit",
+ "border-horizontal-spacing",
+ "border-start",
+ "border-start-color",
+ "border-start-style",
+ "border-start-width",
+ "border-vertical-spacing",
+ "color-correction",
+ "column-axis",
+ "column-break-after",
+ "column-break-before",
+ "column-break-inside",
+ "column-rule-color",
+ "flex-align",
+ "flex-item-align",
+ "flex-line-pack",
+ "flex-order",
+ "flex-pack",
+ "flex-wrap",
+ "font-size-delta",
+ "font-smoothing",
+ "highlight",
+ "hyphenate-limit-after",
+ "hyphenate-limit-before",
+ "locale",
+ "logical-height",
+ "logical-width",
+ "margin-after",
+ "margin-after-collapse",
+ "margin-before",
+ "margin-before-collapse",
+ "margin-bottom-collapse",
+ "margin-collapse",
+ "margin-end",
+ "margin-start",
+ "margin-top-collapse",
+ "marquee",
+ "marquee-direction",
+ "marquee-increment",
+ "marquee-repetition",
+ "marquee-speed",
+ "marquee-style",
+ "mask-attachment",
+ "mask-box-image-outset",
+ "mask-box-image-repeat",
+ "mask-box-image-slice",
+ "mask-box-image-source",
+ "mask-box-image-width",
+ "mask-position-x",
+ "mask-position-y",
+ "mask-repeat-x",
+ "mask-repeat-y",
+ "match-nearest-mail-blockquote-color",
+ "max-logical-height",
+ "max-logical-width",
+ "min-logical-height",
+ "min-logical-width",
+ "nbsp-mode",
+ "overflow-scrolling",
+ "padding-after",
+ "padding-before",
+ "padding-end",
+ "padding-start",
+ "perspective-origin-x",
+ "perspective-origin-y",
+ "region-break-after",
+ "region-break-before",
+ "region-break-inside",
+ "region-overflow",
+ "rtl-ordering",
+ "svg-shadow",
+ "tap-highlight-color",
+ "text-decorations-in-effect",
+ "text-emphasis-color",
+ "text-fill-color",
+ "text-security",
+ "text-size-adjust",
+ "text-stroke",
+ "text-stroke-color",
+ "text-stroke-width",
+ "transform",
+ "transform-origin-x",
+ "transform-origin-y",
+ "transform-origin-z",
+ "user-drag",
+ "user-modify",
+ "wrap",
+ "wrap-margin",
+ "wrap-padding",
+ "wrap-shape-inside",
+ "wrap-shape-outside",
+ "zoom"
+].map((prop) => `-webkit-${prop}`);
+
+module.exports = new Set([
+ "background-position-x",
+ "background-position-y",
+ "background-repeat-x",
+ "background-repeat-y",
+ "color-interpolation",
+ "color-profile",
+ "color-rendering",
+ "enable-background",
+ "glyph-orientation-horizontal",
+ "kerning",
+ "marker-offset",
+ "marks",
+ "pointer-events",
+ "shape-rendering",
+ "size",
+ "src",
+ "stop-color",
+ "stop-opacity",
+ "text-anchor",
+ "text-line-through",
+ "text-line-through-color",
+ "text-line-through-mode",
+ "text-line-through-style",
+ "text-line-through-width",
+ "text-overline",
+ "text-overline-color",
+ "text-overline-mode",
+ "text-overline-style",
+ "text-overline-width",
+ "text-rendering",
+ "text-underline",
+ "text-underline-color",
+ "text-underline-mode",
+ "text-underline-style",
+ "text-underline-width",
+ "unicode-range",
+ "vector-effect",
+ ...webkitProperties
+]);
diff --git a/vanilla/node_modules/cssstyle/lib/utils/camelize.js b/vanilla/node_modules/cssstyle/lib/utils/camelize.js
new file mode 100644
index 0000000..19aaf7d
--- /dev/null
+++ b/vanilla/node_modules/cssstyle/lib/utils/camelize.js
@@ -0,0 +1,37 @@
+"use strict";
+
+const { asciiLowercase } = require("./strings");
+
+// Utility to translate from `border-width` to `borderWidth`.
+// NOTE: For values prefixed with webkit, e.g. `-webkit-foo`, we need to provide
+// both `webkitFoo` and `WebkitFoo`. Here we only return `webkitFoo`.
+exports.dashedToCamelCase = function (dashed) {
+ if (dashed.startsWith("--")) {
+ return dashed;
+ }
+ let camel = "";
+ let nextCap = false;
+ // skip leading hyphen in vendor prefixed value, e.g. -webkit-foo
+ let i = /^-webkit-/.test(dashed) ? 1 : 0;
+ for (; i < dashed.length; i++) {
+ if (dashed[i] !== "-") {
+ camel += nextCap ? dashed[i].toUpperCase() : dashed[i];
+ nextCap = false;
+ } else {
+ nextCap = true;
+ }
+ }
+ return camel;
+};
+
+// Utility to translate from `borderWidth` to `border-width`.
+exports.camelCaseToDashed = function (camelCase) {
+ if (camelCase.startsWith("--")) {
+ return camelCase;
+ }
+ const dashed = asciiLowercase(camelCase.replace(/(?<=[a-z])[A-Z]/g, "-$&"));
+ if (/^webkit-/.test(dashed)) {
+ return `-${dashed}`;
+ }
+ return dashed;
+};
diff --git a/vanilla/node_modules/cssstyle/lib/utils/propertyDescriptors.js b/vanilla/node_modules/cssstyle/lib/utils/propertyDescriptors.js
new file mode 100644
index 0000000..f568d84
--- /dev/null
+++ b/vanilla/node_modules/cssstyle/lib/utils/propertyDescriptors.js
@@ -0,0 +1,55 @@
+"use strict";
+
+const parsers = require("../parsers");
+
+const { AST_TYPES } = parsers;
+
+const getPropertyDescriptor = (property) => ({
+ set(v) {
+ const value = parsers.prepareValue(v);
+ if (parsers.hasVarFunc(value)) {
+ this._setProperty(property, value);
+ } else {
+ const parsedValue = parsers.parsePropertyValue(property, v, {
+ globalObject: this._global,
+ inArray: true
+ });
+ if (Array.isArray(parsedValue)) {
+ if (parsedValue.length === 1) {
+ const [{ name, type, value: itemValue }] = parsedValue;
+ switch (type) {
+ case AST_TYPES.CALC: {
+ this._setProperty(property, `${name}(${itemValue})`);
+ break;
+ }
+ case AST_TYPES.GLOBAL_KEYWORD:
+ case AST_TYPES.IDENTIFIER: {
+ // Set the normalized name for keywords or identifiers.
+ this._setProperty(property, name);
+ break;
+ }
+ default: {
+ // Set the prepared value for Dimension, Function, etc.
+ this._setProperty(property, value);
+ }
+ }
+ } else {
+ // Set the prepared value for lists containing multiple values.
+ this._setProperty(property, value);
+ }
+ } else if (typeof parsedValue === "string") {
+ // Empty string.
+ this._setProperty(property, parsedValue);
+ }
+ }
+ },
+ get() {
+ return this.getPropertyValue(property);
+ },
+ enumerable: true,
+ configurable: true
+});
+
+module.exports = {
+ getPropertyDescriptor
+};
diff --git a/vanilla/node_modules/cssstyle/lib/utils/strings.js b/vanilla/node_modules/cssstyle/lib/utils/strings.js
new file mode 100644
index 0000000..c0227e0
--- /dev/null
+++ b/vanilla/node_modules/cssstyle/lib/utils/strings.js
@@ -0,0 +1,173 @@
+// Forked from https://github.com/jsdom/jsdom/blob/main/lib/jsdom/living/helpers/strings.js
+
+"use strict";
+
+// https://infra.spec.whatwg.org/#ascii-whitespace
+const asciiWhitespaceRe = /^[\t\n\f\r ]$/;
+exports.asciiWhitespaceRe = asciiWhitespaceRe;
+
+// https://infra.spec.whatwg.org/#ascii-lowercase
+exports.asciiLowercase = (s) => {
+ if (!/[^\x00-\x7f]/.test(s)) {
+ return s.toLowerCase();
+ }
+ const len = s.length;
+ const out = new Array(len);
+ for (let i = 0; i < len; i++) {
+ const code = s.charCodeAt(i);
+ // If the character is between 'A' (65) and 'Z' (90), convert using bitwise OR with 32
+ out[i] = code >= 65 && code <= 90 ? String.fromCharCode(code | 32) : s[i];
+ }
+ return out.join("");
+};
+
+// https://infra.spec.whatwg.org/#ascii-uppercase
+exports.asciiUppercase = (s) => {
+ if (!/[^\x00-\x7f]/.test(s)) {
+ return s.toUpperCase();
+ }
+ const len = s.length;
+ const out = new Array(len);
+ for (let i = 0; i < len; i++) {
+ const code = s.charCodeAt(i);
+ // If the character is between 'a' (97) and 'z' (122), convert using bitwise AND with ~32
+ out[i] = code >= 97 && code <= 122 ? String.fromCharCode(code & ~32) : s[i];
+ }
+ return out.join("");
+};
+
+// https://infra.spec.whatwg.org/#strip-newlines
+exports.stripNewlines = (s) => {
+ return s.replace(/[\n\r]+/g, "");
+};
+
+// https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace
+exports.stripLeadingAndTrailingASCIIWhitespace = (s) => {
+ return s.replace(/^[ \t\n\f\r]+/, "").replace(/[ \t\n\f\r]+$/, "");
+};
+
+// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
+exports.stripAndCollapseASCIIWhitespace = (s) => {
+ return s
+ .replace(/[ \t\n\f\r]+/g, " ")
+ .replace(/^[ \t\n\f\r]+/, "")
+ .replace(/[ \t\n\f\r]+$/, "");
+};
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#valid-simple-colour
+exports.isValidSimpleColor = (s) => {
+ return /^#[a-fA-F\d]{6}$/.test(s);
+};
+
+// https://infra.spec.whatwg.org/#ascii-case-insensitive
+exports.asciiCaseInsensitiveMatch = (a, b) => {
+ if (a.length !== b.length) {
+ return false;
+ }
+
+ for (let i = 0; i < a.length; ++i) {
+ if ((a.charCodeAt(i) | 32) !== (b.charCodeAt(i) | 32)) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-integers
+// Error is represented as null.
+const parseInteger = (exports.parseInteger = (input) => {
+ // The implementation here is slightly different from the spec's. We want to use parseInt(), but parseInt() trims
+ // Unicode whitespace in addition to just ASCII ones, so we make sure that the trimmed prefix contains only ASCII
+ // whitespace ourselves.
+ const numWhitespace = input.length - input.trimStart().length;
+ if (/[^\t\n\f\r ]/.test(input.slice(0, numWhitespace))) {
+ return null;
+ }
+ // We don't allow hexadecimal numbers here.
+ // eslint-disable-next-line radix
+ const value = parseInt(input, 10);
+ if (Number.isNaN(value)) {
+ return null;
+ }
+ // parseInt() returns -0 for "-0". Normalize that here.
+ return value === 0 ? 0 : value;
+});
+
+// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-non-negative-integers
+// Error is represented as null.
+exports.parseNonNegativeInteger = (input) => {
+ const value = parseInteger(input);
+ if (value === null) {
+ return null;
+ }
+ if (value < 0) {
+ return null;
+ }
+ return value;
+};
+
+// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-floating-point-number
+const floatingPointNumRe = /^-?(?:\d+|\d*\.\d+)(?:[eE][-+]?\d+)?$/;
+exports.isValidFloatingPointNumber = (str) => floatingPointNumRe.test(str);
+
+// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
+// Error is represented as null.
+exports.parseFloatingPointNumber = (str) => {
+ // The implementation here is slightly different from the spec's. We need to use parseFloat() in order to retain
+ // accuracy, but parseFloat() trims Unicode whitespace in addition to just ASCII ones, so we make sure that the
+ // trimmed prefix contains only ASCII whitespace ourselves.
+ const numWhitespace = str.length - str.trimStart().length;
+ if (/[^\t\n\f\r ]/.test(str.slice(0, numWhitespace))) {
+ return null;
+ }
+ const parsed = parseFloat(str);
+ return isFinite(parsed) ? parsed : null;
+};
+
+// https://infra.spec.whatwg.org/#split-on-ascii-whitespace
+exports.splitOnASCIIWhitespace = (str) => {
+ let position = 0;
+ const tokens = [];
+ while (position < str.length && asciiWhitespaceRe.test(str[position])) {
+ position++;
+ }
+ if (position === str.length) {
+ return tokens;
+ }
+ while (position < str.length) {
+ const start = position;
+ while (position < str.length && !asciiWhitespaceRe.test(str[position])) {
+ position++;
+ }
+ tokens.push(str.slice(start, position));
+ while (position < str.length && asciiWhitespaceRe.test(str[position])) {
+ position++;
+ }
+ }
+ return tokens;
+};
+
+// https://infra.spec.whatwg.org/#split-on-commas
+exports.splitOnCommas = (str) => {
+ let position = 0;
+ const tokens = [];
+ while (position < str.length) {
+ let start = position;
+ while (position < str.length && str[position] !== ",") {
+ position++;
+ }
+ let end = position;
+ while (start < str.length && asciiWhitespaceRe.test(str[start])) {
+ start++;
+ }
+ while (end > start && asciiWhitespaceRe.test(str[end - 1])) {
+ end--;
+ }
+ tokens.push(str.slice(start, end));
+ if (position < str.length) {
+ position++;
+ }
+ }
+ return tokens;
+};