Set up comprehensive frontend testing infrastructure

- Install Jest for unit testing with React Testing Library
- Install Playwright for end-to-end testing
- Configure Jest with proper TypeScript support and module mapping
- Create test setup files and utilities for both unit and e2e tests

Components:
* Jest configuration with coverage thresholds
* Playwright configuration with browser automation
* Unit tests for LoginForm, AuthContext, and useSocketIO hook
* E2E tests for authentication, dashboard, and agents workflows
* GitHub Actions workflow for automated testing
* Mock data and API utilities for consistent testing
* Test documentation with best practices

Testing features:
- Unit tests with 70% coverage threshold
- E2E tests with API mocking and user journey testing
- CI/CD integration for automated test runs
- Cross-browser testing support with Playwright
- Authentication system testing end-to-end

🚀 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-07-11 14:06:34 +10:00
parent c6d69695a8
commit aacb45156b
6109 changed files with 777927 additions and 1 deletions

20
frontend/node_modules/cssstyle/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) Chad Walker
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

11
frontend/node_modules/cssstyle/README.md generated vendored Normal file
View File

@@ -0,0 +1,11 @@
# CSSStyleDeclaration
A Node.js implementation of the CSS Object Model [`CSSStyleDeclaration` class](https://drafts.csswg.org/cssom/#the-cssstyledeclaration-interface).
## Background
This package is an extension of the `CSSStyleDeclaration` class in Nikita Vasilyev's [CSSOM](https://github.com/NV/CSSOM), with added support for modern specifications. The primary use case is for testing browser code in a Node environment.
It was originally created by Chad Walker, it is now maintained by the jsdom community.
Bug reports and pull requests are welcome.

View File

@@ -0,0 +1,613 @@
/**
* This is a fork from the CSS Style Declaration part of
* https://github.com/NV/CSSOM
*/
"use strict";
const CSSOM = require("rrweb-cssom");
const allExtraProperties = require("./allExtraProperties");
const allProperties = require("./generated/allProperties");
const implementedProperties = require("./generated/implementedProperties");
const generatedProperties = require("./generated/properties");
const { hasVarFunc, parseKeyword, parseShorthand, prepareValue, splitValue } = require("./parsers");
const { dashedToCamelCase } = require("./utils/camelize");
const { getPropertyDescriptor } = require("./utils/propertyDescriptors");
const { asciiLowercase } = require("./utils/strings");
/**
* @see https://drafts.csswg.org/cssom/#the-cssstyledeclaration-interface
*/
class CSSStyleDeclaration {
/**
* @param {Function} onChangeCallback
* @param {object} [opt]
* @param {object} [opt.context] - Window, Element or CSSRule.
*/
constructor(onChangeCallback, opt = {}) {
// Make constructor and internals non-enumerable.
Object.defineProperties(this, {
constructor: {
enumerable: false,
writable: true
},
// Window
_global: {
value: globalThis,
enumerable: false,
writable: true
},
// Element
_ownerNode: {
value: null,
enumerable: false,
writable: true
},
// CSSRule
_parentNode: {
value: null,
enumerable: false,
writable: true
},
_onChange: {
value: null,
enumerable: false,
writable: true
},
_values: {
value: new Map(),
enumerable: false,
writable: true
},
_priorities: {
value: new Map(),
enumerable: false,
writable: true
},
_length: {
value: 0,
enumerable: false,
writable: true
},
_computed: {
value: false,
enumerable: false,
writable: true
},
_readonly: {
value: false,
enumerable: false,
writable: true
},
_setInProgress: {
value: false,
enumerable: false,
writable: true
}
});
const { context } = opt;
if (context) {
if (typeof context.getComputedStyle === "function") {
this._global = context;
this._computed = true;
this._readonly = true;
} else if (context.nodeType === 1 && Object.hasOwn(context, "style")) {
this._global = context.ownerDocument.defaultView;
this._ownerNode = context;
} else if (Object.hasOwn(context, "parentRule")) {
this._parentRule = context;
// Find Window from the owner node of the StyleSheet.
const window = context?.parentStyleSheet?.ownerNode?.ownerDocument?.defaultView;
if (window) {
this._global = window;
}
}
}
if (typeof onChangeCallback === "function") {
this._onChange = onChangeCallback;
}
}
get cssText() {
if (this._computed) {
return "";
}
const properties = [];
for (let i = 0; i < this._length; i++) {
const property = this[i];
const value = this.getPropertyValue(property);
const priority = this.getPropertyPriority(property);
if (priority === "important") {
properties.push(`${property}: ${value} !${priority};`);
} else {
properties.push(`${property}: ${value};`);
}
}
return properties.join(" ");
}
set cssText(value) {
if (this._readonly) {
const msg = "cssText can not be modified.";
const name = "NoModificationAllowedError";
throw new this._global.DOMException(msg, name);
}
Array.prototype.splice.call(this, 0, this._length);
this._values.clear();
this._priorities.clear();
if (this._parentRule || (this._ownerNode && this._setInProgress)) {
return;
}
this._setInProgress = true;
let dummyRule;
try {
dummyRule = CSSOM.parse(`#bogus{${value}}`).cssRules[0].style;
} catch {
// Malformed css, just return.
return;
}
for (let i = 0; i < dummyRule.length; i++) {
const property = dummyRule[i];
this.setProperty(
property,
dummyRule.getPropertyValue(property),
dummyRule.getPropertyPriority(property)
);
}
this._setInProgress = false;
if (typeof this._onChange === "function") {
this._onChange(this.cssText);
}
}
get length() {
return this._length;
}
// This deletes indices if the new length is less then the current length.
// If the new length is more, it does nothing, the new indices will be
// undefined until set.
set length(len) {
for (let i = len; i < this._length; i++) {
delete this[i];
}
this._length = len;
}
// Readonly
get parentRule() {
return this._parentRule;
}
get cssFloat() {
return this.getPropertyValue("float");
}
set cssFloat(value) {
this._setProperty("float", value);
}
/**
* @param {string} property
*/
getPropertyPriority(property) {
return this._priorities.get(property) || "";
}
/**
* @param {string} property
*/
getPropertyValue(property) {
if (this._values.has(property)) {
return this._values.get(property).toString();
}
return "";
}
/**
* @param {...number} args
*/
item(...args) {
if (!args.length) {
const msg = "1 argument required, but only 0 present.";
throw new this._global.TypeError(msg);
}
let [index] = args;
index = parseInt(index);
if (Number.isNaN(index) || index < 0 || index >= this._length) {
return "";
}
return this[index];
}
/**
* @param {string} property
*/
removeProperty(property) {
if (this._readonly) {
const msg = `Property ${property} can not be modified.`;
const name = "NoModificationAllowedError";
throw new this._global.DOMException(msg, name);
}
if (!this._values.has(property)) {
return "";
}
const prevValue = this._values.get(property);
this._values.delete(property);
this._priorities.delete(property);
const index = Array.prototype.indexOf.call(this, property);
if (index >= 0) {
Array.prototype.splice.call(this, index, 1);
if (typeof this._onChange === "function") {
this._onChange(this.cssText);
}
}
return prevValue;
}
/**
* @param {string} property
* @param {string} value
* @param {string?} [priority] - "important" or null
*/
setProperty(property, value, priority = null) {
if (this._readonly) {
const msg = `Property ${property} can not be modified.`;
const name = "NoModificationAllowedError";
throw new this._global.DOMException(msg, name);
}
value = prepareValue(value, this._global);
if (value === "") {
this[property] = "";
this.removeProperty(property);
return;
}
const isCustomProperty = property.startsWith("--");
if (isCustomProperty) {
this._setProperty(property, value);
return;
}
property = asciiLowercase(property);
if (!allProperties.has(property) && !allExtraProperties.has(property)) {
return;
}
this[property] = value;
if (priority) {
this._priorities.set(property, priority);
} else {
this._priorities.delete(property);
}
}
}
// Internal methods
Object.defineProperties(CSSStyleDeclaration.prototype, {
_shorthandGetter: {
/**
* @param {string} property
* @param {object} shorthandFor
*/
value(property, shorthandFor) {
const parts = [];
for (const key of shorthandFor.keys()) {
const val = this.getPropertyValue(key);
if (hasVarFunc(val)) {
return "";
}
if (val !== "") {
parts.push(val);
}
}
if (parts.length) {
return parts.join(" ");
}
if (this._values.has(property)) {
return this.getPropertyValue(property);
}
return "";
},
enumerable: false
},
_implicitGetter: {
/**
* @param {string} property
* @param {Array.<string>} positions
*/
value(property, positions = []) {
const parts = [];
for (const position of positions) {
const val = this.getPropertyValue(`${property}-${position}`);
if (val === "" || hasVarFunc(val)) {
return "";
}
parts.push(val);
}
if (!parts.length) {
return "";
}
switch (positions.length) {
case 4: {
const [top, right, bottom, left] = parts;
if (top === right && top === bottom && right === left) {
return top;
}
if (top !== right && top === bottom && right === left) {
return `${top} ${right}`;
}
if (top !== right && top !== bottom && right === left) {
return `${top} ${right} ${bottom}`;
}
return `${top} ${right} ${bottom} ${left}`;
}
case 2: {
const [x, y] = parts;
if (x === y) {
return x;
}
return `${x} ${y}`;
}
default:
return "";
}
},
enumerable: false
},
_setProperty: {
/**
* @param {string} property
* @param {string} val
* @param {string?} [priority]
*/
value(property, val, priority = null) {
if (typeof val !== "string") {
return;
}
if (val === "") {
this.removeProperty(property);
return;
}
let originalText = "";
if (typeof this._onChange === "function") {
originalText = this.cssText;
}
if (this._values.has(property)) {
const index = Array.prototype.indexOf.call(this, property);
// The property already exists but is not indexed into `this` so add it.
if (index < 0) {
this[this._length] = property;
this._length++;
}
} else {
// New property.
this[this._length] = property;
this._length++;
}
this._values.set(property, val);
if (priority) {
this._priorities.set(property, priority);
} else {
this._priorities.delete(property);
}
if (
typeof this._onChange === "function" &&
this.cssText !== originalText &&
!this._setInProgress
) {
this._onChange(this.cssText);
}
},
enumerable: false
},
_shorthandSetter: {
/**
* @param {string} property
* @param {string} val
* @param {object} shorthandFor
*/
value(property, val, shorthandFor) {
val = prepareValue(val, this._global);
const obj = parseShorthand(val, shorthandFor);
if (!obj) {
return;
}
for (const subprop of Object.keys(obj)) {
// In case subprop is an implicit property, this will clear *its*
// subpropertiesX.
const camel = dashedToCamelCase(subprop);
this[camel] = obj[subprop];
// In case it gets translated into something else (0 -> 0px).
obj[subprop] = this[camel];
this.removeProperty(subprop);
// Don't add in empty properties.
if (obj[subprop] !== "") {
this._values.set(subprop, obj[subprop]);
}
}
for (const [subprop] of shorthandFor) {
if (!Object.hasOwn(obj, subprop)) {
this.removeProperty(subprop);
this._values.delete(subprop);
}
}
// In case the value is something like 'none' that removes all values,
// check that the generated one is not empty, first remove the property,
// if it already exists, then call the shorthandGetter, if it's an empty
// string, don't set the property.
this.removeProperty(property);
const calculated = this._shorthandGetter(property, shorthandFor);
if (calculated !== "") {
this._setProperty(property, calculated);
}
return obj;
},
enumerable: false
},
// Companion to shorthandSetter, but for the individual parts which takes
// position value in the middle.
_midShorthandSetter: {
/**
* @param {string} property
* @param {string} val
* @param {object} shorthandFor
* @param {Array.<string>} positions
*/
value(property, val, shorthandFor, positions = []) {
val = prepareValue(val, this._global);
const obj = this._shorthandSetter(property, val, shorthandFor);
if (!obj) {
return;
}
for (const position of positions) {
this.removeProperty(`${property}-${position}`);
this._values.set(`${property}-${position}`, val);
}
},
enumerable: false
},
_implicitSetter: {
/**
* @param {string} prefix
* @param {string} part
* @param {string} val
* @param {Function} isValid
* @param {Function} parser
* @param {Array.<string>} positions
*/
value(prefix, part, val, isValid, parser, positions = []) {
val = prepareValue(val, this._global);
if (typeof val !== "string") {
return;
}
part ||= "";
if (part) {
part = `-${part}`;
}
let parts = [];
if (val === "") {
parts.push(val);
} else {
const key = parseKeyword(val);
if (key) {
parts.push(key);
} else {
parts.push(...splitValue(val));
}
}
if (!parts.length || parts.length > positions.length || !parts.every(isValid)) {
return;
}
parts = parts.map((p) => parser(p));
this._setProperty(`${prefix}${part}`, parts.join(" "));
switch (positions.length) {
case 4:
if (parts.length === 1) {
parts.push(parts[0], parts[0], parts[0]);
} else if (parts.length === 2) {
parts.push(parts[0], parts[1]);
} else if (parts.length === 3) {
parts.push(parts[1]);
}
break;
case 2:
if (parts.length === 1) {
parts.push(parts[0]);
}
break;
default:
}
for (let i = 0; i < positions.length; i++) {
const property = `${prefix}-${positions[i]}${part}`;
this.removeProperty(property);
this._values.set(property, parts[i]);
}
},
enumerable: false
},
// Companion to implicitSetter, but for the individual parts.
// This sets the individual value, and checks to see if all sub-parts are
// set. If so, it sets the shorthand version and removes the individual parts
// from the cssText.
_subImplicitSetter: {
/**
* @param {string} prefix
* @param {string} part
* @param {string} val
* @param {Function} isValid
* @param {Function} parser
* @param {Array.<string>} positions
*/
value(prefix, part, val, isValid, parser, positions = []) {
val = prepareValue(val, this._global);
if (typeof val !== "string" || !isValid(val)) {
return;
}
val = parser(val);
const property = `${prefix}-${part}`;
this._setProperty(property, val);
const combinedPriority = this.getPropertyPriority(prefix);
const subparts = [];
for (const position of positions) {
subparts.push(`${prefix}-${position}`);
}
const parts = subparts.map((subpart) => this._values.get(subpart));
const priorities = subparts.map((subpart) => this.getPropertyPriority(subpart));
const [priority] = priorities;
// Combine into a single property if all values are set and have the same
// priority.
if (
priority === combinedPriority &&
parts.every((p) => p) &&
priorities.every((p) => p === priority)
) {
for (let i = 0; i < subparts.length; i++) {
this.removeProperty(subparts[i]);
this._values.set(subparts[i], parts[i]);
}
this._setProperty(prefix, parts.join(" "), priority);
} else {
this.removeProperty(prefix);
for (let i = 0; i < subparts.length; i++) {
// The property we're setting won't be important, the rest will either
// keep their priority or inherit it from the combined property
const subPriority = subparts[i] === property ? "" : priorities[i] || combinedPriority;
this._setProperty(subparts[i], parts[i], subPriority);
}
}
},
enumerable: false
}
});
// Properties
Object.defineProperties(CSSStyleDeclaration.prototype, generatedProperties);
// Additional properties
[...allProperties, ...allExtraProperties].forEach(function (property) {
if (!implementedProperties.has(property)) {
const declaration = getPropertyDescriptor(property);
Object.defineProperty(CSSStyleDeclaration.prototype, property, declaration);
const camel = dashedToCamelCase(property);
Object.defineProperty(CSSStyleDeclaration.prototype, camel, declaration);
if (/^webkit[A-Z]/.test(camel)) {
const pascal = camel.replace(/^webkit/, "Webkit");
Object.defineProperty(CSSStyleDeclaration.prototype, pascal, declaration);
}
}
});
exports.CSSStyleDeclaration = CSSStyleDeclaration;

View File

@@ -0,0 +1,49 @@
"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 allWebkitProperties = require("./allWebkitProperties");
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",
...allWebkitProperties
]);

View File

@@ -0,0 +1,114 @@
"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.
*/
module.exports = [
"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}`);

View File

@@ -0,0 +1,615 @@
"use strict";
// autogenerated - 2025-05-14
// https://www.w3.org/Style/CSS/all-properties.en.html
module.exports = new Set([
"-webkit-line-clamp",
"accent-color",
"align-content",
"align-items",
"align-self",
"alignment-baseline",
"all",
"anchor-name",
"anchor-scope",
"animation",
"animation-composition",
"animation-delay",
"animation-direction",
"animation-duration",
"animation-fill-mode",
"animation-iteration-count",
"animation-name",
"animation-play-state",
"animation-range",
"animation-range-end",
"animation-range-start",
"animation-timeline",
"animation-timing-function",
"appearance",
"aspect-ratio",
"azimuth",
"backface-visibility",
"background",
"background-attachment",
"background-blend-mode",
"background-clip",
"background-color",
"background-image",
"background-origin",
"background-position",
"background-repeat",
"background-size",
"baseline-shift",
"baseline-source",
"block-ellipsis",
"block-size",
"block-step",
"block-step-align",
"block-step-insert",
"block-step-round",
"block-step-size",
"bookmark-label",
"bookmark-level",
"bookmark-state",
"border",
"border-block",
"border-block-color",
"border-block-end",
"border-block-end-color",
"border-block-end-style",
"border-block-end-width",
"border-block-start",
"border-block-start-color",
"border-block-start-style",
"border-block-start-width",
"border-block-style",
"border-block-width",
"border-bottom",
"border-bottom-color",
"border-bottom-left-radius",
"border-bottom-right-radius",
"border-bottom-style",
"border-bottom-width",
"border-boundary",
"border-collapse",
"border-color",
"border-end-end-radius",
"border-end-start-radius",
"border-image",
"border-image-outset",
"border-image-repeat",
"border-image-slice",
"border-image-source",
"border-image-width",
"border-inline",
"border-inline-color",
"border-inline-end",
"border-inline-end-color",
"border-inline-end-style",
"border-inline-end-width",
"border-inline-start",
"border-inline-start-color",
"border-inline-start-style",
"border-inline-start-width",
"border-inline-style",
"border-inline-width",
"border-left",
"border-left-color",
"border-left-style",
"border-left-width",
"border-radius",
"border-right",
"border-right-color",
"border-right-style",
"border-right-width",
"border-spacing",
"border-start-end-radius",
"border-start-start-radius",
"border-style",
"border-top",
"border-top-color",
"border-top-left-radius",
"border-top-right-radius",
"border-top-style",
"border-top-width",
"border-width",
"bottom",
"box-decoration-break",
"box-shadow",
"box-sizing",
"box-snap",
"break-after",
"break-before",
"break-inside",
"caption-side",
"caret",
"caret-color",
"caret-shape",
"clear",
"clip",
"clip-path",
"clip-rule",
"color",
"color-adjust",
"color-interpolation-filters",
"color-scheme",
"column-count",
"column-fill",
"column-gap",
"column-rule",
"column-rule-break",
"column-rule-color",
"column-rule-outset",
"column-rule-style",
"column-rule-width",
"column-span",
"column-width",
"columns",
"contain",
"contain-intrinsic-block-size",
"contain-intrinsic-height",
"contain-intrinsic-inline-size",
"contain-intrinsic-size",
"contain-intrinsic-width",
"container",
"container-name",
"container-type",
"content",
"content-visibility",
"continue",
"counter-increment",
"counter-reset",
"counter-set",
"cue",
"cue-after",
"cue-before",
"cursor",
"direction",
"display",
"dominant-baseline",
"dynamic-range-limit",
"elevation",
"empty-cells",
"fill",
"fill-break",
"fill-color",
"fill-image",
"fill-opacity",
"fill-origin",
"fill-position",
"fill-repeat",
"fill-rule",
"fill-size",
"filter",
"flex",
"flex-basis",
"flex-direction",
"flex-flow",
"flex-grow",
"flex-shrink",
"flex-wrap",
"float",
"float-defer",
"float-offset",
"float-reference",
"flood-color",
"flood-opacity",
"flow-from",
"flow-into",
"font",
"font-family",
"font-feature-settings",
"font-kerning",
"font-language-override",
"font-optical-sizing",
"font-palette",
"font-size",
"font-size-adjust",
"font-stretch",
"font-style",
"font-synthesis",
"font-synthesis-position",
"font-synthesis-small-caps",
"font-synthesis-style",
"font-synthesis-weight",
"font-variant",
"font-variant-alternates",
"font-variant-caps",
"font-variant-east-asian",
"font-variant-emoji",
"font-variant-ligatures",
"font-variant-numeric",
"font-variant-position",
"font-variation-settings",
"font-weight",
"font-width",
"footnote-display",
"footnote-policy",
"forced-color-adjust",
"gap",
"glyph-orientation-vertical",
"grid",
"grid-area",
"grid-auto-columns",
"grid-auto-flow",
"grid-auto-rows",
"grid-column",
"grid-column-end",
"grid-column-start",
"grid-row",
"grid-row-end",
"grid-row-start",
"grid-template",
"grid-template-areas",
"grid-template-columns",
"grid-template-rows",
"hanging-punctuation",
"height",
"hyphenate-character",
"hyphenate-limit-chars",
"hyphenate-limit-last",
"hyphenate-limit-lines",
"hyphenate-limit-zone",
"hyphens",
"image-orientation",
"image-rendering",
"image-resolution",
"initial-letter",
"initial-letter-align",
"initial-letter-wrap",
"inline-size",
"inline-sizing",
"inset",
"inset-block",
"inset-block-end",
"inset-block-start",
"inset-inline",
"inset-inline-end",
"inset-inline-start",
"interpolate-size",
"isolation",
"item-cross",
"item-direction",
"item-flow",
"item-pack",
"item-slack",
"item-track",
"item-wrap",
"justify-content",
"justify-items",
"justify-self",
"left",
"letter-spacing",
"lighting-color",
"line-break",
"line-clamp",
"line-fit-edge",
"line-grid",
"line-height",
"line-height-step",
"line-padding",
"line-snap",
"list-style",
"list-style-image",
"list-style-position",
"list-style-type",
"margin",
"margin-block",
"margin-block-end",
"margin-block-start",
"margin-bottom",
"margin-break",
"margin-inline",
"margin-inline-end",
"margin-inline-start",
"margin-left",
"margin-right",
"margin-top",
"margin-trim",
"marker",
"marker-end",
"marker-knockout-left",
"marker-knockout-right",
"marker-mid",
"marker-pattern",
"marker-segment",
"marker-side",
"marker-start",
"mask",
"mask-border",
"mask-border-mode",
"mask-border-outset",
"mask-border-repeat",
"mask-border-slice",
"mask-border-source",
"mask-border-width",
"mask-clip",
"mask-composite",
"mask-image",
"mask-mode",
"mask-origin",
"mask-position",
"mask-repeat",
"mask-size",
"mask-type",
"max-block-size",
"max-height",
"max-inline-size",
"max-lines",
"max-width",
"min-block-size",
"min-height",
"min-inline-size",
"min-intrinsic-sizing",
"min-width",
"mix-blend-mode",
"nav-down",
"nav-left",
"nav-right",
"nav-up",
"object-fit",
"object-position",
"offset",
"offset-anchor",
"offset-distance",
"offset-path",
"offset-position",
"offset-rotate",
"opacity",
"order",
"orphans",
"outline",
"outline-color",
"outline-offset",
"outline-style",
"outline-width",
"overflow",
"overflow-anchor",
"overflow-block",
"overflow-clip-margin",
"overflow-clip-margin-block",
"overflow-clip-margin-block-end",
"overflow-clip-margin-block-start",
"overflow-clip-margin-bottom",
"overflow-clip-margin-inline",
"overflow-clip-margin-inline-end",
"overflow-clip-margin-inline-start",
"overflow-clip-margin-left",
"overflow-clip-margin-right",
"overflow-clip-margin-top",
"overflow-inline",
"overflow-wrap",
"overflow-x",
"overflow-y",
"overscroll-behavior",
"overscroll-behavior-block",
"overscroll-behavior-inline",
"overscroll-behavior-x",
"overscroll-behavior-y",
"padding",
"padding-block",
"padding-block-end",
"padding-block-start",
"padding-bottom",
"padding-inline",
"padding-inline-end",
"padding-inline-start",
"padding-left",
"padding-right",
"padding-top",
"page",
"page-break-after",
"page-break-before",
"page-break-inside",
"pause",
"pause-after",
"pause-before",
"perspective",
"perspective-origin",
"pitch",
"pitch-range",
"place-content",
"place-items",
"place-self",
"play-during",
"position",
"position-anchor",
"position-area",
"position-try",
"position-try-fallbacks",
"position-try-order",
"position-visibility",
"print-color-adjust",
"quotes",
"reading-flow",
"region-fragment",
"resize",
"rest",
"rest-after",
"rest-before",
"richness",
"right",
"rotate",
"row-gap",
"row-rule",
"row-rule-break",
"row-rule-color",
"row-rule-outset",
"row-rule-style",
"row-rule-width",
"ruby-align",
"ruby-merge",
"ruby-overhang",
"ruby-position",
"rule",
"rule-break",
"rule-color",
"rule-outset",
"rule-paint-order",
"rule-style",
"rule-width",
"running",
"scale",
"scroll-behavior",
"scroll-margin",
"scroll-margin-block",
"scroll-margin-block-end",
"scroll-margin-block-start",
"scroll-margin-bottom",
"scroll-margin-inline",
"scroll-margin-inline-end",
"scroll-margin-inline-start",
"scroll-margin-left",
"scroll-margin-right",
"scroll-margin-top",
"scroll-marker-group",
"scroll-padding",
"scroll-padding-block",
"scroll-padding-block-end",
"scroll-padding-block-start",
"scroll-padding-bottom",
"scroll-padding-inline",
"scroll-padding-inline-end",
"scroll-padding-inline-start",
"scroll-padding-left",
"scroll-padding-right",
"scroll-padding-top",
"scroll-snap-align",
"scroll-snap-stop",
"scroll-snap-type",
"scroll-start-target",
"scroll-timeline",
"scroll-timeline-axis",
"scroll-timeline-name",
"scrollbar-color",
"scrollbar-gutter",
"scrollbar-width",
"shape-image-threshold",
"shape-inside",
"shape-margin",
"shape-outside",
"slider-orientation",
"spatial-navigation-action",
"spatial-navigation-contain",
"spatial-navigation-function",
"speak",
"speak-as",
"speak-header",
"speak-numeral",
"speak-punctuation",
"speech-rate",
"stress",
"string-set",
"stroke",
"stroke-align",
"stroke-alignment",
"stroke-break",
"stroke-color",
"stroke-dash-corner",
"stroke-dash-justify",
"stroke-dashadjust",
"stroke-dasharray",
"stroke-dashcorner",
"stroke-dashoffset",
"stroke-image",
"stroke-linecap",
"stroke-linejoin",
"stroke-miterlimit",
"stroke-opacity",
"stroke-origin",
"stroke-position",
"stroke-repeat",
"stroke-size",
"stroke-width",
"tab-size",
"table-layout",
"text-align",
"text-align-all",
"text-align-last",
"text-autospace",
"text-box",
"text-box-edge",
"text-box-trim",
"text-combine-upright",
"text-decoration",
"text-decoration-color",
"text-decoration-line",
"text-decoration-skip",
"text-decoration-skip-box",
"text-decoration-skip-ink",
"text-decoration-skip-inset",
"text-decoration-skip-self",
"text-decoration-skip-spaces",
"text-decoration-style",
"text-decoration-thickness",
"text-emphasis",
"text-emphasis-color",
"text-emphasis-position",
"text-emphasis-skip",
"text-emphasis-style",
"text-group-align",
"text-indent",
"text-justify",
"text-orientation",
"text-overflow",
"text-shadow",
"text-spacing",
"text-spacing-trim",
"text-transform",
"text-underline-offset",
"text-underline-position",
"text-wrap",
"text-wrap-mode",
"text-wrap-style",
"timeline-scope",
"top",
"transform",
"transform-box",
"transform-origin",
"transform-style",
"transition",
"transition-behavior",
"transition-delay",
"transition-duration",
"transition-property",
"transition-timing-function",
"translate",
"unicode-bidi",
"user-select",
"vertical-align",
"view-timeline",
"view-timeline-axis",
"view-timeline-inset",
"view-timeline-name",
"view-transition-class",
"view-transition-group",
"view-transition-name",
"visibility",
"voice-balance",
"voice-duration",
"voice-family",
"voice-pitch",
"voice-range",
"voice-rate",
"voice-stress",
"voice-volume",
"volume",
"white-space",
"white-space-collapse",
"white-space-trim",
"widows",
"width",
"will-change",
"word-break",
"word-space-transform",
"word-spacing",
"word-wrap",
"wrap-after",
"wrap-before",
"wrap-flow",
"wrap-inside",
"wrap-through",
"writing-mode",
"z-index"
]);

View File

@@ -0,0 +1,79 @@
"use strict";
// autogenerated - 2025-06-25
// https://www.w3.org/Style/CSS/all-properties.en.html
module.exports = new Set([
"background",
"background-attachment",
"background-color",
"background-image",
"background-position",
"background-repeat",
"border",
"border-bottom",
"border-bottom-color",
"border-bottom-style",
"border-bottom-width",
"border-collapse",
"border-color",
"border-left",
"border-left-color",
"border-left-style",
"border-left-width",
"border-right",
"border-right-color",
"border-right-style",
"border-right-width",
"border-spacing",
"border-style",
"border-top",
"border-top-color",
"border-top-style",
"border-top-width",
"border-width",
"bottom",
"clear",
"clip",
"color",
"flex",
"flex-basis",
"flex-grow",
"flex-shrink",
"float",
"flood-color",
"font",
"font-family",
"font-size",
"font-style",
"font-variant",
"font-weight",
"height",
"left",
"lighting-color",
"line-height",
"margin",
"margin-bottom",
"margin-left",
"margin-right",
"margin-top",
"opacity",
"outline-color",
"padding",
"padding-bottom",
"padding-left",
"padding-right",
"padding-top",
"right",
"stop-color",
"top",
"-webkit-border-after-color",
"-webkit-border-before-color",
"-webkit-border-end-color",
"-webkit-border-start-color",
"-webkit-column-rule-color",
"-webkit-tap-highlight-color",
"-webkit-text-emphasis-color",
"-webkit-text-fill-color",
"-webkit-text-stroke-color",
"width"
]);

File diff suppressed because it is too large Load Diff

537
frontend/node_modules/cssstyle/lib/parsers.js generated vendored Normal file
View File

@@ -0,0 +1,537 @@
/**
* These are commonly used parsers for CSS Values they take a string to parse
* and return a string after it's been converted, if needed
*/
"use strict";
const { resolve: resolveColor, utils } = require("@asamuzakjp/css-color");
const { asciiLowercase } = require("./utils/strings");
const { cssCalc, isColor, isGradient, splitValue } = utils;
// CSS global values
// @see https://drafts.csswg.org/css-cascade-5/#defaulting-keywords
const GLOBAL_VALUE = Object.freeze(["initial", "inherit", "unset", "revert", "revert-layer"]);
// Numeric data types
const NUM_TYPE = Object.freeze({
UNDEFINED: 0,
VAR: 1,
NUMBER: 2,
PERCENT: 4,
LENGTH: 8,
ANGLE: 0x10,
CALC: 0x20
});
// System colors
// @see https://drafts.csswg.org/css-color/#css-system-colors
// @see https://drafts.csswg.org/css-color/#deprecated-system-colors
const SYS_COLOR = Object.freeze([
"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"
]);
// Regular expressions
const DIGIT = "(?:0|[1-9]\\d*)";
const NUMBER = `[+-]?(?:${DIGIT}(?:\\.\\d*)?|\\.\\d+)(?:e-?${DIGIT})?`;
const unitRegEx = new RegExp(`^(${NUMBER})([a-z]+|%)?$`, "i");
const urlRegEx = /^url\(\s*((?:[^)]|\\\))*)\s*\)$/;
const keywordRegEx = /^[a-z]+(?:-[a-z]+)*$/i;
const stringRegEx = /^("[^"]*"|'[^']*')$/;
const varRegEx = /^var\(/;
const varContainedRegEx = /(?<=[*/\s(])var\(/;
const calcRegEx =
/^(?:a?(?:cos|sin|tan)|abs|atan2|calc|clamp|exp|hypot|log|max|min|mod|pow|rem|round|sign|sqrt)\(/;
const functionRegEx = /^([a-z][a-z\d]*(?:-[a-z\d]+)*)\(/i;
const getNumericType = function getNumericType(val) {
if (varRegEx.test(val)) {
return NUM_TYPE.VAR;
}
if (calcRegEx.test(val)) {
return NUM_TYPE.CALC;
}
if (unitRegEx.test(val)) {
const [, , unit] = unitRegEx.exec(val);
if (!unit) {
return NUM_TYPE.NUMBER;
}
if (unit === "%") {
return NUM_TYPE.PERCENT;
}
if (/^(?:[cm]m|[dls]?v(?:[bhiw]|max|min)|in|p[ctx]|q|r?(?:[cl]h|cap|e[mx]|ic))$/i.test(unit)) {
return NUM_TYPE.LENGTH;
}
if (/^(?:deg|g?rad|turn)$/i.test(unit)) {
return NUM_TYPE.ANGLE;
}
}
return NUM_TYPE.UNDEFINED;
};
// Prepare stringified value.
exports.prepareValue = function prepareValue(value, globalObject = globalThis) {
// `null` is converted to an empty string.
// @see https://webidl.spec.whatwg.org/#LegacyNullToEmptyString
if (value === null) {
return "";
}
const type = typeof value;
switch (type) {
case "string":
return value.trim();
case "number":
return value.toString();
case "undefined":
return "undefined";
case "symbol":
throw new globalObject.TypeError("Can not convert symbol to string.");
default: {
const str = value.toString();
if (typeof str === "string") {
return str;
}
throw new globalObject.TypeError(`Can not convert ${type} to string.`);
}
}
};
exports.hasVarFunc = function hasVarFunc(val) {
return varRegEx.test(val) || varContainedRegEx.test(val);
};
exports.parseNumber = function parseNumber(val, restrictToPositive = false) {
if (val === "") {
return "";
}
const type = getNumericType(val);
switch (type) {
case NUM_TYPE.VAR:
return val;
case NUM_TYPE.CALC:
return cssCalc(val, {
format: "specifiedValue"
});
case NUM_TYPE.NUMBER: {
const num = parseFloat(val);
if (restrictToPositive && num < 0) {
return;
}
return `${num}`;
}
default:
if (varContainedRegEx.test(val)) {
return val;
}
}
};
exports.parseLength = function parseLength(val, restrictToPositive = false) {
if (val === "") {
return "";
}
const type = getNumericType(val);
switch (type) {
case NUM_TYPE.VAR:
return val;
case NUM_TYPE.CALC:
return cssCalc(val, {
format: "specifiedValue"
});
case NUM_TYPE.NUMBER:
if (parseFloat(val) === 0) {
return "0px";
}
return;
case NUM_TYPE.LENGTH: {
const [, numVal, unit] = unitRegEx.exec(val);
const num = parseFloat(numVal);
if (restrictToPositive && num < 0) {
return;
}
return `${num}${asciiLowercase(unit)}`;
}
default:
if (varContainedRegEx.test(val)) {
return val;
}
}
};
exports.parsePercent = function parsePercent(val, restrictToPositive = false) {
if (val === "") {
return "";
}
const type = getNumericType(val);
switch (type) {
case NUM_TYPE.VAR:
return val;
case NUM_TYPE.CALC:
return cssCalc(val, {
format: "specifiedValue"
});
case NUM_TYPE.NUMBER:
if (parseFloat(val) === 0) {
return "0%";
}
return;
case NUM_TYPE.PERCENT: {
const [, numVal, unit] = unitRegEx.exec(val);
const num = parseFloat(numVal);
if (restrictToPositive && num < 0) {
return;
}
return `${num}${asciiLowercase(unit)}`;
}
default:
if (varContainedRegEx.test(val)) {
return val;
}
}
};
// Either a length or a percent.
exports.parseMeasurement = function parseMeasurement(val, restrictToPositive = false) {
if (val === "") {
return "";
}
const type = getNumericType(val);
switch (type) {
case NUM_TYPE.VAR:
return val;
case NUM_TYPE.CALC:
return cssCalc(val, {
format: "specifiedValue"
});
case NUM_TYPE.NUMBER:
if (parseFloat(val) === 0) {
return "0px";
}
return;
case NUM_TYPE.LENGTH:
case NUM_TYPE.PERCENT: {
const [, numVal, unit] = unitRegEx.exec(val);
const num = parseFloat(numVal);
if (restrictToPositive && num < 0) {
return;
}
return `${num}${asciiLowercase(unit)}`;
}
default:
if (varContainedRegEx.test(val)) {
return val;
}
}
};
exports.parseAngle = function parseAngle(val, normalizeDeg = false) {
if (val === "") {
return "";
}
const type = getNumericType(val);
switch (type) {
case NUM_TYPE.VAR:
return val;
case NUM_TYPE.CALC:
return cssCalc(val, {
format: "specifiedValue"
});
case NUM_TYPE.NUMBER:
if (parseFloat(val) === 0) {
return "0deg";
}
return;
case NUM_TYPE.ANGLE: {
let [, numVal, unit] = unitRegEx.exec(val);
numVal = parseFloat(numVal);
unit = asciiLowercase(unit);
if (unit === "deg") {
if (normalizeDeg && numVal < 0) {
while (numVal < 0) {
numVal += 360;
}
}
numVal %= 360;
}
return `${numVal}${unit}`;
}
default:
if (varContainedRegEx.test(val)) {
return val;
}
}
};
exports.parseUrl = function parseUrl(val) {
if (val === "") {
return val;
}
const res = urlRegEx.exec(val);
if (!res) {
return;
}
let str = res[1];
// If it starts with single or double quotes, does it end with the same?
if ((str[0] === '"' || str[0] === "'") && str[0] !== str[str.length - 1]) {
return;
}
if (str[0] === '"' || str[0] === "'") {
str = str.substr(1, str.length - 2);
}
let urlstr = "";
let escaped = false;
for (let i = 0; i < str.length; i++) {
switch (str[i]) {
case "\\":
if (escaped) {
urlstr += "\\\\";
escaped = false;
} else {
escaped = true;
}
break;
case "(":
case ")":
case " ":
case "\t":
case "\n":
case "'":
if (!escaped) {
return;
}
urlstr += str[i];
escaped = false;
break;
case '"':
if (!escaped) {
return;
}
urlstr += '\\"';
escaped = false;
break;
default:
urlstr += str[i];
escaped = false;
}
}
return `url("${urlstr}")`;
};
exports.parseString = function parseString(val) {
if (val === "") {
return "";
}
if (!stringRegEx.test(val)) {
return;
}
val = val.substr(1, val.length - 2);
let str = "";
let escaped = false;
for (let i = 0; i < val.length; i++) {
switch (val[i]) {
case "\\":
if (escaped) {
str += "\\\\";
escaped = false;
} else {
escaped = true;
}
break;
case '"':
str += '\\"';
escaped = false;
break;
default:
str += val[i];
escaped = false;
}
}
return `"${str}"`;
};
exports.parseKeyword = function parseKeyword(val, validKeywords = []) {
if (val === "") {
return "";
}
if (varRegEx.test(val)) {
return val;
}
val = asciiLowercase(val.toString());
if (validKeywords.includes(val) || GLOBAL_VALUE.includes(val)) {
return val;
}
};
exports.parseColor = function parseColor(val) {
if (val === "") {
return "";
}
if (varRegEx.test(val)) {
return val;
}
if (/^[a-z]+$/i.test(val)) {
const v = asciiLowercase(val);
if (SYS_COLOR.includes(v)) {
return v;
}
}
const res = resolveColor(val, {
format: "specifiedValue"
});
if (res) {
return res;
}
return exports.parseKeyword(val);
};
exports.parseImage = function parseImage(val) {
if (val === "") {
return "";
}
if (varRegEx.test(val)) {
return val;
}
if (keywordRegEx.test(val)) {
return exports.parseKeyword(val, ["none"]);
}
const values = splitValue(val, {
delimiter: ",",
preserveComment: varContainedRegEx.test(val)
});
let isImage = Boolean(values.length);
for (let i = 0; i < values.length; i++) {
const image = values[i];
if (image === "") {
return "";
}
if (isGradient(image) || /^(?:none|inherit)$/i.test(image)) {
continue;
}
const imageUrl = exports.parseUrl(image);
if (imageUrl) {
values[i] = imageUrl;
} else {
isImage = false;
break;
}
}
if (isImage) {
return values.join(", ");
}
};
exports.parseFunction = function parseFunction(val) {
if (val === "") {
return {
name: null,
value: ""
};
}
if (functionRegEx.test(val) && val.endsWith(")")) {
if (varRegEx.test(val) || varContainedRegEx.test(val)) {
return {
name: "var",
value: val
};
}
const [, name] = functionRegEx.exec(val);
const value = val
.replace(new RegExp(`^${name}\\(`), "")
.replace(/\)$/, "")
.trim();
return {
name,
value
};
}
};
exports.parseShorthand = function parseShorthand(val, shorthandFor, preserve = false) {
const obj = {};
if (val === "" || exports.hasVarFunc(val)) {
for (const [property] of shorthandFor) {
obj[property] = "";
}
return obj;
}
const key = exports.parseKeyword(val);
if (key) {
if (key === "inherit") {
return obj;
}
return;
}
const parts = splitValue(val);
const shorthandArr = [...shorthandFor];
for (const part of parts) {
let partValid = false;
for (let i = 0; i < shorthandArr.length; i++) {
const [property, value] = shorthandArr[i];
if (value.isValid(part)) {
partValid = true;
obj[property] = value.parse(part);
if (!preserve) {
shorthandArr.splice(i, 1);
break;
}
}
}
if (!partValid) {
return;
}
}
return obj;
};
// Returns `false` for global values, e.g. "inherit".
exports.isValidColor = function isValidColor(val) {
if (SYS_COLOR.includes(asciiLowercase(val))) {
return true;
}
return isColor(val);
};
// Splits value into an array.
// @see https://github.com/asamuzaK/cssColor/blob/main/src/js/util.ts
exports.splitValue = splitValue;

View File

@@ -0,0 +1,52 @@
"use strict";
// FIXME:
// * support multiple backgrounds
// * also fix longhands
const parsers = require("../parsers");
const strings = require("../utils/strings");
const backgroundImage = require("./backgroundImage");
const backgroundPosition = require("./backgroundPosition");
const backgroundRepeat = require("./backgroundRepeat");
const backgroundAttachment = require("./backgroundAttachment");
const backgroundColor = require("./backgroundColor");
const shorthandFor = new Map([
["background-image", backgroundImage],
["background-position", backgroundPosition],
["background-repeat", backgroundRepeat],
["background-attachment", backgroundAttachment],
["background-color", backgroundColor]
]);
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (/^none$/i.test(v)) {
for (const [key] of shorthandFor) {
this._setProperty(key, "");
}
this._setProperty("background", strings.asciiLowercase(v));
} else if (parsers.hasVarFunc(v)) {
for (const [key] of shorthandFor) {
this._setProperty(key, "");
}
this._setProperty("background", v);
} else {
this._shorthandSetter("background", v, shorthandFor);
}
},
get() {
let val = this.getPropertyValue("background");
if (parsers.hasVarFunc(val)) {
return val;
}
val = this._shorthandGetter("background", shorthandFor);
if (parsers.hasVarFunc(val)) {
return "";
}
return val;
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,32 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = ["fixed", "scroll", "local"];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("background", "");
this._setProperty("background-attachment", v);
} else {
this._setProperty("background-attachment", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("background-attachment");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,35 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("background", "");
this._setProperty("background-color", v);
} else {
this._setProperty("background-color", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("background-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,31 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
return parsers.parseImage(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v, ["none"]) === "string") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("background", "");
this._setProperty("background-image", v);
} else {
this._setProperty("background-image", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("background-image");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,52 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const parts = parsers.splitValue(v);
if (!parts.length || parts.length > 2) {
return;
}
const validKeywordsX = ["left", "center", "right"];
const validKeywordsY = ["top", "center", "bottom"];
if (parts.length === 1) {
const dim = parsers.parseMeasurement(parts[0]);
if (dim) {
return dim;
}
const validKeywords = new Set([...validKeywordsX, ...validKeywordsY]);
return parsers.parseKeyword(v, [...validKeywords]);
}
const [partX, partY] = parts;
const posX = parsers.parseMeasurement(partX) || parsers.parseKeyword(partX, validKeywordsX);
if (posX) {
const posY = parsers.parseMeasurement(partY) || parsers.parseKeyword(partY, validKeywordsY);
if (posY) {
return `${posX} ${posY}`;
}
}
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("background", "");
this._setProperty("background-position", v);
} else {
this._setProperty("background-position", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("background-position");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,32 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = ["repeat", "repeat-x", "repeat-y", "no-repeat", "space", "round"];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("background", "");
this._setProperty("background-repeat", v);
} else {
this._setProperty("background-repeat", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("background-repeat");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,42 @@
"use strict";
const parsers = require("../parsers");
const borderWidth = require("./borderWidth");
const borderStyle = require("./borderStyle");
const borderColor = require("./borderColor");
const shorthandFor = new Map([
["border-width", borderWidth],
["border-style", borderStyle],
["border-color", borderColor]
]);
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (/^none$/i.test(v)) {
v = "";
}
if (parsers.hasVarFunc(v)) {
for (const [key] of shorthandFor) {
this._setProperty(key, "");
}
this._setProperty("border", v);
} else {
this._midShorthandSetter("border", v, shorthandFor, ["top", "right", "bottom", "left"]);
}
},
get() {
let val = this.getPropertyValue("border");
if (parsers.hasVarFunc(val)) {
return val;
}
val = this._shorthandGetter("border", shorthandFor);
if (parsers.hasVarFunc(val)) {
return "";
}
return val;
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
const borderTopWidth = require("./borderTopWidth");
const borderTopStyle = require("./borderTopStyle");
const borderTopColor = require("./borderTopColor");
const shorthandFor = new Map([
["border-bottom-width", borderTopWidth],
["border-bottom-style", borderTopStyle],
["border-bottom-color", borderTopColor]
]);
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
for (const [key] of shorthandFor) {
this._setProperty(key, "");
}
this._setProperty("border", "");
this._setProperty("border-bottom", v);
} else {
this._shorthandSetter("border-bottom", v, shorthandFor);
}
},
get() {
let val = this.getPropertyValue("border-bottom");
if (parsers.hasVarFunc(val)) {
return val;
}
val = this._shorthandGetter("border-bottom", shorthandFor);
if (parsers.hasVarFunc(val)) {
return "";
}
return val;
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,35 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-bottom", "");
this._setProperty("border-color", "");
}
this._setProperty("border-bottom-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-bottom-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,50 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = [
"none",
"hidden",
"dotted",
"dashed",
"solid",
"double",
"groove",
"ridge",
"inset",
"outset"
];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
const val = module.exports.parse(v);
if (val === "none" || val === "hidden") {
this._setProperty("border-bottom-style", "");
this._setProperty("border-bottom-color", "");
this._setProperty("border-bottom-width", "");
return;
}
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-bottom", "");
this._setProperty("border-style", "");
}
this._setProperty("border-bottom-style", val);
},
get() {
return this.getPropertyValue("border-bottom-style");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,36 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = ["thin", "medium", "thick"];
const key = parsers.parseKeyword(v, keywords);
if (key) {
return key;
}
return parsers.parseLength(v, true);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-bottom", "");
this._setProperty("border-width", "");
}
this._setProperty("border-bottom-width", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-bottom-width");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,26 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
return parsers.parseKeyword(v, ["collapse", "separate"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("border-collapse", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-collapse");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,43 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-color", v);
} else {
const positions = ["top", "right", "bottom", "left"];
this._implicitSetter(
"border",
"color",
v,
module.exports.isValid,
module.exports.parse,
positions
);
}
},
get() {
return this.getPropertyValue("border-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
const borderTopWidth = require("./borderTopWidth");
const borderTopStyle = require("./borderTopStyle");
const borderTopColor = require("./borderTopColor");
const shorthandFor = new Map([
["border-left-width", borderTopWidth],
["border-left-style", borderTopStyle],
["border-left-color", borderTopColor]
]);
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
for (const [key] of shorthandFor) {
this._setProperty(key, "");
}
this._setProperty("border", "");
this._setProperty("border-left", v);
} else {
this._shorthandSetter("border-left", v, shorthandFor);
}
},
get() {
let val = this.getPropertyValue("border-left");
if (parsers.hasVarFunc(val)) {
return val;
}
val = this._shorthandGetter("border-left", shorthandFor);
if (parsers.hasVarFunc(val)) {
return "";
}
return val;
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,35 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-left", "");
this._setProperty("border-color", "");
}
this._setProperty("border-left-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-left-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,50 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = [
"none",
"hidden",
"dotted",
"dashed",
"solid",
"double",
"groove",
"ridge",
"inset",
"outset"
];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
const val = module.exports.parse(v);
if (val === "none" || val === "hidden") {
this._setProperty("border-left-style", "");
this._setProperty("border-left-color", "");
this._setProperty("border-left-width", "");
return;
}
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-left", "");
this._setProperty("border-style", "");
}
this._setProperty("border-left-style", val);
},
get() {
return this.getPropertyValue("border-left-style");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,36 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = ["thin", "medium", "thick"];
const key = parsers.parseKeyword(v, keywords);
if (key) {
return key;
}
return parsers.parseLength(v, true);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-left", "");
this._setProperty("border-width", "");
}
this._setProperty("border-left-width", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-left-width");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
const borderTopWidth = require("./borderTopWidth");
const borderTopStyle = require("./borderTopStyle");
const borderTopColor = require("./borderTopColor");
const shorthandFor = new Map([
["border-right-width", borderTopWidth],
["border-right-style", borderTopStyle],
["border-right-color", borderTopColor]
]);
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
for (const [key] of shorthandFor) {
this._setProperty(key, "");
}
this._setProperty("border", "");
this._setProperty("border-right", v);
} else {
this._shorthandSetter("border-right", v, shorthandFor);
}
},
get() {
let val = this.getPropertyValue("border-right");
if (parsers.hasVarFunc(val)) {
return val;
}
val = this._shorthandGetter("border-right", shorthandFor);
if (parsers.hasVarFunc(val)) {
return "";
}
return val;
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,35 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-right", "");
this._setProperty("border-color", "");
}
this._setProperty("border-right-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-right-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,50 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = [
"none",
"hidden",
"dotted",
"dashed",
"solid",
"double",
"groove",
"ridge",
"inset",
"outset"
];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
const val = module.exports.parse(v);
if (val === "none" || val === "hidden") {
this._setProperty("border-right-style", "");
this._setProperty("border-right-color", "");
this._setProperty("border-right-width", "");
return;
}
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-right", "");
this._setProperty("border-style", "");
}
this._setProperty("border-right-style", val);
},
get() {
return this.getPropertyValue("border-right-style");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,36 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = ["thin", "medium", "thick"];
const key = parsers.parseKeyword(v, keywords);
if (key) {
return key;
}
return parsers.parseLength(v, true);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-right", "");
this._setProperty("border-width", "");
}
this._setProperty("border-right-width", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-right-width");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,45 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
if (v === "") {
return v;
}
const key = parsers.parseKeyword(v);
if (key) {
return key;
}
const parts = parsers.splitValue(v);
if (!parts.length || parts.length > 2) {
return;
}
const val = [];
for (const part of parts) {
const dim = parsers.parseLength(part);
if (!dim) {
return;
}
val.push(dim);
}
return val.join(" ");
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("border-spacing", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-spacing");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,54 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = [
"none",
"hidden",
"dotted",
"dashed",
"solid",
"double",
"groove",
"ridge",
"inset",
"outset"
];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (/^none$/i.test(v)) {
v = "";
}
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-style", v);
return;
}
const positions = ["top", "right", "bottom", "left"];
this._implicitSetter(
"border",
"style",
v,
module.exports.isValid,
module.exports.parse,
positions
);
},
get() {
return this.getPropertyValue("border-style");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
const borderTopWidth = require("./borderTopWidth");
const borderTopStyle = require("./borderTopStyle");
const borderTopColor = require("./borderTopColor");
const shorthandFor = new Map([
["border-top-width", borderTopWidth],
["border-top-style", borderTopStyle],
["border-top-color", borderTopColor]
]);
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
for (const [key] of shorthandFor) {
this._setProperty(key, "");
}
this._setProperty("border", "");
this._setProperty("border-top", v);
} else {
this._shorthandSetter("border-top", v, shorthandFor);
}
},
get() {
let val = this.getPropertyValue("border-top");
if (parsers.hasVarFunc(val)) {
return val;
}
val = this._shorthandGetter("border-top", shorthandFor);
if (parsers.hasVarFunc(val)) {
return "";
}
return val;
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,35 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-top", "");
this._setProperty("border-color", "");
}
this._setProperty("border-top-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-top-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,50 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = [
"none",
"hidden",
"dotted",
"dashed",
"solid",
"double",
"groove",
"ridge",
"inset",
"outset"
];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
const val = module.exports.parse(v);
if (val === "none" || val === "hidden" || v === "") {
this._setProperty("border-top-style", "");
this._setProperty("border-top-color", "");
this._setProperty("border-top-width", "");
return;
}
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-top", "");
this._setProperty("border-style", "");
}
this._setProperty("border-top-style", val);
},
get() {
return this.getPropertyValue("border-top-style");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,36 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = ["thin", "medium", "thick"];
const key = parsers.parseKeyword(v, keywords);
if (key) {
return key;
}
return parsers.parseLength(v, true);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-top", "");
this._setProperty("border-width", "");
}
this._setProperty("border-top-width", module.exports.parse(v));
},
get() {
return this.getPropertyValue("border-top-width");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,44 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = ["thin", "medium", "thick"];
const key = parsers.parseKeyword(v, keywords);
if (key) {
return key;
}
return parsers.parseLength(v, true);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("border", "");
this._setProperty("border-width", v);
} else {
const positions = ["top", "right", "bottom", "left"];
this._implicitSetter(
"border",
"width",
v,
module.exports.isValid,
module.exports.parse,
positions
);
}
},
get() {
return this.getPropertyValue("border-width");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const dim = parsers.parseMeasurement(v);
if (dim) {
return dim;
}
return parsers.parseKeyword(v, ["auto"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("bottom", module.exports.parse(v));
},
get() {
return this.getPropertyValue("bottom");
},
enumerable: true,
configurable: true
};

40
frontend/node_modules/cssstyle/lib/properties/clear.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = [
"inline-start",
"inline-end",
"block-start",
"block-end",
"left",
"right",
"top",
"bottom",
"both-inline",
"both-block",
"both",
"none"
];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("clear", module.exports.parse(v));
},
get() {
return this.getPropertyValue("clear");
},
enumerable: true,
configurable: true
};

54
frontend/node_modules/cssstyle/lib/properties/clip.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
"use strict";
// deprecated
// @see https://drafts.fxtf.org/css-masking/#clip-property
const parsers = require("../parsers");
const strings = require("../utils/strings");
module.exports.parse = function parse(v) {
if (v === "") {
return v;
}
const val = parsers.parseKeyword(v, ["auto"]);
if (val) {
return val;
}
// parse legacy <shape>
v = strings.asciiLowercase(v);
const matches = v.match(/^rect\(\s*(.*)\s*\)$/);
if (!matches) {
return;
}
const parts = matches[1].split(/\s*,\s*/);
if (parts.length !== 4) {
return;
}
const valid = parts.every(function (part, index) {
const measurement = parsers.parseMeasurement(part.trim());
parts[index] = measurement;
return typeof measurement === "string";
});
if (!valid) {
return;
}
return `rect(${parts.join(", ")})`;
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("clip", module.exports.parse(v));
},
get() {
return this.getPropertyValue("clip");
},
enumerable: true,
configurable: true
};

30
frontend/node_modules/cssstyle/lib/properties/color.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("color");
},
enumerable: true,
configurable: true
};

73
frontend/node_modules/cssstyle/lib/properties/flex.js generated vendored Normal file
View File

@@ -0,0 +1,73 @@
"use strict";
const parsers = require("../parsers");
const flexGrow = require("./flexGrow");
const flexShrink = require("./flexShrink");
const flexBasis = require("./flexBasis");
const shorthandFor = new Map([
["flex-grow", flexGrow],
["flex-shrink", flexShrink],
["flex-basis", flexBasis]
]);
module.exports.parse = function parse(v) {
const key = parsers.parseKeyword(v, ["auto", "none"]);
if (key) {
if (key === "auto") {
return "1 1 auto";
}
if (key === "none") {
return "0 0 auto";
}
if (key === "initial") {
return "0 1 auto";
}
return;
}
const obj = parsers.parseShorthand(v, shorthandFor);
if (obj) {
const flex = {
"flex-grow": "1",
"flex-shrink": "1",
"flex-basis": "0%"
};
const items = Object.entries(obj);
for (const [property, value] of items) {
flex[property] = value;
}
return [...Object.values(flex)].join(" ");
}
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._shorthandSetter("flex", "", shorthandFor);
this._setProperty("flex", v);
} else {
this._shorthandSetter("flex", module.exports.parse(v), shorthandFor);
}
},
get() {
let val = this.getPropertyValue("flex");
if (parsers.hasVarFunc(val)) {
return val;
}
val = this._shorthandGetter("flex", shorthandFor);
if (parsers.hasVarFunc(val)) {
return "";
}
return val;
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,33 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v);
if (val) {
return val;
}
const keywords = ["content", "auto", "min-content", "max-content"];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("flex", "");
this._setProperty("flex-basis", v);
} else {
this._setProperty("flex-basis", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("flex-basis");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,28 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
return parsers.parseNumber(v, true);
};
module.exports.isValid = function isValid(v) {
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("flex", "");
this._setProperty("flex-grow", v);
} else {
this._setProperty("flex-grow", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("flex-grow");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,28 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
return parsers.parseNumber(v, true);
};
module.exports.isValid = function isValid(v) {
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("flex", "");
this._setProperty("flex-shrink", v);
} else {
this._setProperty("flex-shrink", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("flex-shrink");
},
enumerable: true,
configurable: true
};

27
frontend/node_modules/cssstyle/lib/properties/float.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = ["left", "right", "none", "inline-start", "inline-end"];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("float", module.exports.parse(v));
},
get() {
return this.getPropertyValue("float");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("flood-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("flood-color");
},
enumerable: true,
configurable: true
};

189
frontend/node_modules/cssstyle/lib/properties/font.js generated vendored Normal file
View File

@@ -0,0 +1,189 @@
"use strict";
const parsers = require("../parsers");
const fontStyle = require("./fontStyle");
const fontVariant = require("./fontVariant");
const fontWeight = require("./fontWeight");
const fontSize = require("./fontSize");
const lineHeight = require("./lineHeight");
const fontFamily = require("./fontFamily");
const shorthandFor = new Map([
["font-style", fontStyle],
["font-variant", fontVariant],
["font-weight", fontWeight],
["font-size", fontSize],
["line-height", lineHeight],
["font-family", fontFamily]
]);
module.exports.parse = function parse(v) {
const keywords = ["caption", "icon", "menu", "message-box", "small-caption", "status-bar"];
const key = parsers.parseKeyword(v, keywords);
if (key) {
return key;
}
const [fontBlock, ...families] = parsers.splitValue(v, {
delimiter: ","
});
const [fontBlockA, fontBlockB] = parsers.splitValue(fontBlock, {
delimiter: "/"
});
const font = {
"font-style": "normal",
"font-variant": "normal",
"font-weight": "normal"
};
const fontFamilies = new Set();
if (fontBlockB) {
const [lineB, ...familiesB] = fontBlockB.trim().split(" ");
if (!lineB || !lineHeight.isValid(lineB) || !familiesB.length) {
return;
}
const lineHeightB = lineHeight.parse(lineB);
const familyB = familiesB.join(" ");
if (fontFamily.isValid(familyB)) {
fontFamilies.add(fontFamily.parse(familyB));
} else {
return;
}
const parts = parsers.splitValue(fontBlockA.trim());
const properties = ["font-style", "font-variant", "font-weight", "font-size"];
for (const part of parts) {
if (part === "normal") {
continue;
} else {
for (const property of properties) {
switch (property) {
case "font-style":
case "font-variant":
case "font-weight":
case "font-size": {
const value = shorthandFor.get(property);
if (value.isValid(part)) {
font[property] = value.parse(part);
}
break;
}
default:
}
}
}
}
if (Object.hasOwn(font, "font-size")) {
font["line-height"] = lineHeightB;
} else {
return;
}
} else {
// FIXME: Switch to toReversed() when we can drop Node.js 18 support.
const revParts = [...parsers.splitValue(fontBlockA.trim())].reverse();
const revFontFamily = [];
const properties = ["font-style", "font-variant", "font-weight", "line-height"];
font["font-style"] = "normal";
font["font-variant"] = "normal";
font["font-weight"] = "normal";
font["line-height"] = "normal";
let fontSizeA;
for (const part of revParts) {
if (fontSizeA) {
if (part === "normal") {
continue;
} else {
for (const property of properties) {
switch (property) {
case "font-style":
case "font-variant":
case "font-weight":
case "line-height": {
const value = shorthandFor.get(property);
if (value.isValid(part)) {
font[property] = value.parse(part);
}
break;
}
default:
}
}
}
} else if (fontSize.isValid(part)) {
fontSizeA = fontSize.parse(part);
} else if (fontFamily.isValid(part)) {
revFontFamily.push(part);
} else {
return;
}
}
const family = revFontFamily.reverse().join(" ");
if (fontSizeA && fontFamily.isValid(family)) {
font["font-size"] = fontSizeA;
fontFamilies.add(fontFamily.parse(family));
} else {
return;
}
}
for (const family of families) {
if (fontFamily.isValid(family)) {
fontFamilies.add(fontFamily.parse(family));
} else {
return;
}
}
font["font-family"] = [...fontFamilies].join(", ");
return font;
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (v === "" || parsers.hasVarFunc(v)) {
for (const [key] of shorthandFor) {
this._setProperty(key, "");
}
this._setProperty("font", v);
} else {
const obj = module.exports.parse(v);
if (!obj) {
return;
}
const str = new Set();
for (const [key] of shorthandFor) {
const val = obj[key];
if (typeof val === "string") {
this._setProperty(key, val);
if (val && val !== "normal" && !str.has(val)) {
if (key === "line-height") {
str.add(`/ ${val}`);
} else {
str.add(val);
}
}
}
}
this._setProperty("font", [...str].join(" "));
}
},
get() {
const val = this.getPropertyValue("font");
if (parsers.hasVarFunc(val)) {
return val;
}
const str = new Set();
for (const [key] of shorthandFor) {
const v = this.getPropertyValue(key);
if (parsers.hasVarFunc(v)) {
return "";
}
if (v && v !== "normal" && !str.has(v)) {
if (key === "line-height") {
str.add(`/ ${v}`);
} else {
str.add(`${v}`);
}
}
}
return [...str].join(" ");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,95 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
if (v === "") {
return v;
}
const keywords = [
"serif",
"sans-serif",
"cursive",
"fantasy",
"monospace",
"system-ui",
"math",
"ui-serif",
"ui-sans-serif",
"ui-monospace",
"ui-rounded"
];
const genericValues = ["fangsong", "kai", "khmer-mul", "nastaliq"];
const val = parsers.splitValue(v, {
delimiter: ","
});
const font = [];
let valid = false;
for (const i of val) {
const str = parsers.parseString(i);
if (str) {
font.push(str);
valid = true;
continue;
}
const key = parsers.parseKeyword(i, keywords);
if (key) {
font.push(key);
valid = true;
continue;
}
const obj = parsers.parseFunction(i);
if (obj) {
const { name, value } = obj;
if (name === "generic" && genericValues.includes(value)) {
font.push(`${name}(${value})`);
valid = true;
continue;
}
}
// This implementation does not strictly follow the specification.
// The spec does not require the first letter of the font-family to be
// capitalized, and unquoted font-family names are not restricted to ASCII.
// However, in the real world, the first letter of the ASCII font-family
// names are capitalized, and unquoted font-family names do not contain
// spaces, e.g. `Times`. And non-ASCII font-family names are quoted even
// without spaces, e.g. `"メイリオ"`.
// @see https://drafts.csswg.org/css-fonts/#font-family-prop
if (
i !== "undefined" &&
/^(?:[A-Z][A-Za-z\d-]+(?:\s+[A-Z][A-Za-z\d-]+)*|-?[a-z][a-z-]+)$/.test(i)
) {
font.push(i.trim());
valid = true;
continue;
}
if (!valid) {
return;
}
}
return font.join(", ");
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("font", "");
this._setProperty("font-family", v);
} else {
this._setProperty("font-family", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("font-family");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,47 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v, true);
if (val) {
return val;
}
const keywords = [
"xx-small",
"x-small",
"small",
"medium",
"large",
"x-large",
"xx-large",
"xxx-large",
"smaller",
"larger"
];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("font", "");
this._setProperty("font-size", v);
} else {
this._setProperty("font-size", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("font-size");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,32 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const keywords = ["normal", "italic", "oblique"];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("font", "");
this._setProperty("font-style", v);
} else {
this._setProperty("font-style", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("font-style");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,36 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const num = parsers.parseNumber(v, true);
if (num && parseFloat(num) <= 1000) {
return num;
}
const keywords = ["normal", "none", "small-caps"];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("font", "");
this._setProperty("font-valiant", v);
} else {
this._setProperty("font-variant", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("font-variant");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,36 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const num = parsers.parseNumber(v, true);
if (num && parseFloat(num) <= 1000) {
return num;
}
const keywords = ["normal", "bold", "lighter", "bolder"];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("font", "");
this._setProperty("font-weight", v);
} else {
this._setProperty("font-weight", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("font-weight");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,31 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const dim = parsers.parseMeasurement(v, true);
if (dim) {
return dim;
}
const keywords = ["auto", "min-content", "max-content", "fit-content"];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("height", module.exports.parse(v));
},
get() {
return this.getPropertyValue("height");
},
enumerable: true,
configurable: true
};

30
frontend/node_modules/cssstyle/lib/properties/left.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const dim = parsers.parseMeasurement(v);
if (dim) {
return dim;
}
return parsers.parseKeyword(v, ["auto"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("left", module.exports.parse(v));
},
get() {
return this.getPropertyValue("left");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("lighting-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("lighting-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,39 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseKeyword(v, ["normal"]);
if (val) {
return val;
}
const num = parsers.parseNumber(v, true);
if (num) {
return num;
}
return parsers.parseMeasurement(v, true);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("font", "");
this._setProperty("line-height", v);
} else {
this._setProperty("line-height", module.exports.parse(v));
}
},
get() {
return this.getPropertyValue("line-height");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,58 @@
"use strict";
const parsers = require("../parsers");
const positions = ["top", "right", "bottom", "left"];
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v);
if (val) {
return val;
}
return parsers.parseKeyword(v, ["auto"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._implicitSetter(
"margin",
"",
"",
module.exports.isValid,
module.exports.parse,
positions
);
this._setProperty("margin", v);
} else {
this._implicitSetter(
"margin",
"",
v,
module.exports.isValid,
module.exports.parse,
positions
);
}
},
get() {
const val = this._implicitGetter("margin", positions);
if (val === "") {
return this.getPropertyValue("margin");
}
if (parsers.hasVarFunc(val)) {
return "";
}
return val;
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v);
if (val) {
return val;
}
return parsers.parseKeyword(v, ["auto"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("margin", "");
this._setProperty("margin-bottom", v);
} else {
this._subImplicitSetter("margin", "bottom", v, module.exports.isValid, module.exports.parse, [
"top",
"right",
"bottom",
"left"
]);
}
},
get() {
return this.getPropertyValue("margin-bottom");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v);
if (val) {
return val;
}
return parsers.parseKeyword(v, ["auto"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("margin", "");
this._setProperty("margin-left", v);
} else {
this._subImplicitSetter("margin", "left", v, module.exports.isValid, module.exports.parse, [
"top",
"right",
"bottom",
"left"
]);
}
},
get() {
return this.getPropertyValue("margin-left");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v);
if (val) {
return val;
}
return parsers.parseKeyword(v, ["auto"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("margin", "");
this._setProperty("margin-right", v);
} else {
this._subImplicitSetter("margin", "right", v, module.exports.isValid, module.exports.parse, [
"top",
"right",
"bottom",
"left"
]);
}
},
get() {
return this.getPropertyValue("margin-right");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v);
if (val) {
return val;
}
return parsers.parseKeyword(v, ["auto"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("margin", "");
this._setProperty("margin-top", v);
} else {
this._subImplicitSetter("margin", "top", v, module.exports.isValid, module.exports.parse, [
"top",
"right",
"bottom",
"left"
]);
}
},
get() {
return this.getPropertyValue("margin-top");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,46 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
let num = parsers.parseNumber(v);
if (num) {
num = parseFloat(num);
if (num < 0) {
return "0";
} else if (num > 1) {
return "1";
}
return `${num}`;
}
let pct = parsers.parsePercent(v);
if (pct) {
pct = parseFloat(pct);
if (pct < 0) {
return "0%";
} else if (pct > 100) {
return "100%";
}
return `${pct}%`;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("opacity", module.exports.parse(v));
},
get() {
return this.getPropertyValue("opacity");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("outline-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("outline-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,58 @@
"use strict";
const parsers = require("../parsers");
const positions = ["top", "right", "bottom", "left"];
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v, true);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._implicitSetter(
"padding",
"",
"",
module.exports.isValid,
module.exports.parse,
positions
);
this._setProperty("padding", v);
} else {
this._implicitSetter(
"padding",
"",
v,
module.exports.isValid,
module.exports.parse,
positions
);
}
},
get() {
const val = this._implicitGetter("padding", positions);
if (val === "") {
return this.getPropertyValue("padding");
}
if (parsers.hasVarFunc(val)) {
return "";
}
return val;
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,42 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v, true);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("padding", "");
this._setProperty("padding-bottom", v);
} else {
this._subImplicitSetter(
"padding",
"bottom",
v,
module.exports.isValid,
module.exports.parse,
["top", "right", "bottom", "left"]
);
}
},
get() {
return this.getPropertyValue("padding-bottom");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v, true);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("padding", "");
this._setProperty("padding-left", v);
} else {
this._subImplicitSetter("padding", "left", v, module.exports.isValid, module.exports.parse, [
"top",
"right",
"bottom",
"left"
]);
}
},
get() {
return this.getPropertyValue("padding-left");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v, true);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("padding", "");
this._setProperty("padding-right", v);
} else {
this._subImplicitSetter("padding", "right", v, module.exports.isValid, module.exports.parse, [
"top",
"right",
"bottom",
"left"
]);
}
},
get() {
return this.getPropertyValue("padding-right");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,40 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseMeasurement(v, true);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
if (parsers.hasVarFunc(v)) {
this._setProperty("padding", "");
this._setProperty("padding-top", v);
} else {
this._subImplicitSetter("padding", "top", v, module.exports.isValid, module.exports.parse, [
"top",
"right",
"bottom",
"left"
]);
}
},
get() {
return this.getPropertyValue("padding-top");
},
enumerable: true,
configurable: true
};

30
frontend/node_modules/cssstyle/lib/properties/right.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const dim = parsers.parseMeasurement(v);
if (dim) {
return dim;
}
return parsers.parseKeyword(v, ["auto"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("right", module.exports.parse(v));
},
get() {
return this.getPropertyValue("right");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("stop-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("stop-color");
},
enumerable: true,
configurable: true
};

30
frontend/node_modules/cssstyle/lib/properties/top.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const dim = parsers.parseMeasurement(v);
if (dim) {
return dim;
}
return parsers.parseKeyword(v, ["auto"]);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("top", module.exports.parse(v));
},
get() {
return this.getPropertyValue("top");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("-webkit-border-after-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("-webkit-border-after-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("-webkit-border-before-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("-webkit-border-before-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("-webkit-border-end-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("-webkit-border-end-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("-webkit-border-start-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("-webkit-border-start-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("-webkit-column-rule-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("-webkit-column-rule-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("-webkit-tap-highlight-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("-webkit-tap-highlight-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("-webkit-text-emphasis-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("-webkit-text-emphasis-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("-webkit-text-fill-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("-webkit-text-fill-color");
},
enumerable: true,
configurable: true
};

View File

@@ -0,0 +1,30 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const val = parsers.parseColor(v);
if (val) {
return val;
}
return parsers.parseKeyword(v);
};
module.exports.isValid = function isValid(v) {
if (v === "" || typeof parsers.parseKeyword(v) === "string") {
return true;
}
return parsers.isValidColor(v);
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("-webkit-text-stroke-color", module.exports.parse(v));
},
get() {
return this.getPropertyValue("-webkit-text-stroke-color");
},
enumerable: true,
configurable: true
};

31
frontend/node_modules/cssstyle/lib/properties/width.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
"use strict";
const parsers = require("../parsers");
module.exports.parse = function parse(v) {
const dim = parsers.parseMeasurement(v, true);
if (dim) {
return dim;
}
const keywords = ["auto", "min-content", "max-content", "fit-content"];
return parsers.parseKeyword(v, keywords);
};
module.exports.isValid = function isValid(v) {
if (v === "") {
return true;
}
return typeof module.exports.parse(v) === "string";
};
module.exports.definition = {
set(v) {
v = parsers.prepareValue(v, this._global);
this._setProperty("width", module.exports.parse(v));
},
get() {
return this.getPropertyValue("width");
},
enumerable: true,
configurable: true
};

37
frontend/node_modules/cssstyle/lib/utils/camelize.js generated vendored Normal file
View File

@@ -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;
};

View File

@@ -0,0 +1,16 @@
"use strict";
const prepareValue = require("../parsers").prepareValue;
module.exports.getPropertyDescriptor = function getPropertyDescriptor(property) {
return {
set(v) {
this._setProperty(property, prepareValue(v));
},
get() {
return this.getPropertyValue(property);
},
enumerable: true,
configurable: true
};
};

167
frontend/node_modules/cssstyle/lib/utils/strings.js generated vendored Normal file
View File

@@ -0,0 +1,167 @@
// 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) => {
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) => {
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;
};

72
frontend/node_modules/cssstyle/package.json generated vendored Normal file
View File

@@ -0,0 +1,72 @@
{
"name": "cssstyle",
"description": "CSSStyleDeclaration Object Model implementation",
"keywords": [
"CSS",
"CSSStyleDeclaration",
"StyleSheet"
],
"version": "4.6.0",
"homepage": "https://github.com/jsdom/cssstyle",
"maintainers": [
{
"name": "Jon Sakas",
"email": "jon.sakas@gmail.com",
"url": "https://jon.sakas.co/"
},
{
"name": "Rafał Ruciński",
"email": "fatfisz@gmail.com",
"url": "https://fatfisz.com"
}
],
"contributors": [
{
"name": "Chad Walker",
"email": "chad@chad-cat-lore-eddie.com",
"url": "https://github.com/chad3814"
}
],
"repository": "jsdom/cssstyle",
"bugs": "https://github.com/jsdom/cssstyle/issues",
"directories": {
"lib": "./lib"
},
"files": [
"lib/"
],
"main": "./lib/CSSStyleDeclaration.js",
"dependencies": {
"@asamuzakjp/css-color": "^3.2.0",
"rrweb-cssom": "^0.8.0"
},
"devDependencies": {
"@babel/generator": "^7.26.9",
"@babel/parser": "^7.26.9",
"@babel/traverse": "^7.26.9",
"@babel/types": "^7.26.9",
"@domenic/eslint-config": "^4.0.1",
"eslint": "^9.22.0",
"eslint-config-prettier": "^10.1.1",
"eslint-plugin-prettier": "^5.2.3",
"globals": "^16.0.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.5.3",
"resolve": "^1.22.10"
},
"scripts": {
"download": "node ./scripts/downloadLatestProperties.mjs",
"generate": "run-p generate:*",
"generate:implemented_properties": "node ./scripts/generateImplementedProperties.mjs",
"generate:properties": "node ./scripts/generateProperties.js",
"lint": "npm run generate && eslint --max-warnings 0",
"lint:fix": "eslint --fix --max-warnings 0",
"prepublishOnly": "npm run lint && npm run test",
"test": "npm run generate && node --test",
"test-ci": "npm run lint && npm run test"
},
"license": "MIT",
"engines": {
"node": ">=18"
}
}