From c6a11c240580d177419c51176ce1c9395bc0e17e Mon Sep 17 00:00:00 2001 From: "Eduardo M. Santos" Date: Mon, 2 Sep 2024 13:56:02 -0300 Subject: [PATCH] feat(typescript-migration): Migrate Colorus-js codebase to TypeScript (#23) * Migrate codebase to TypeScript - initial conversion and type annotations (#18) * refact!: remove old js files * feat!: major refactor and introduction of plugin system - refactor: restructure file organization for improved clarity and maintainability - feat: implement plugin system with enhanced TypeScript integration - refactor!: rename Colorus class to Color - feat: add defineColor helper function for simplified instance creation - refactor: rename functions and variables for better readability and maintainability - feat: expose ColorFormatter, parseColor, and isValidColor for public use - refactor: separate parsing and serialization logic into distinct modules - refactor: organize conversion functions into separate files based on color space - refactor: move grayscale, mix, and invert methods into plugins - feat: expose a few useful typescript types for public use * refact!: ensure code structure works with new tests * chore: update Jest config for TypeScript * test: add new unit test written in TypeScript * chore: clean up test files (remove unused comments and variables) * Migrate to Biome and remove ESLint (#20) * chore: upload initial biome config * chore!: remove old .eslintrc.json config * lint: update files after running new lint config * Build System Update for Typescript Migration & Plugin Separation (Issue #19) (#21) * refact!: remove built-in plugins Remove built-in plugins for the sake of improving separation of concerns, later we will add them as separate packages. * chore(tsconfig): upload initial tsconfig.json file * refact: fix issues reported by the new tsconfig.json * chore: update deps and configs in package.json * build: update build config Automatically generate types declaration file, and use esbuild to generate more optimized JS ESNext bundles. * refact!: clean and update types * chore: update NPM ignore config file * build(config): restruct the build process config * build(tsconfig): improve tsconfig.json * build: replace plugin to print bundle size Because of some bugs with the rollup-plugin-output-size, I've decided to go with a more simple alternative, the rollup-plugin-bundle-size. * refact!: Replace Color class with dye function - Improve type safety - Refact colorFormatter.ts - Rewrite unit tests - Add new helper functions * docs(CONTRIBUTING): add contributing guidelines * docs: Add comprehensive guide for working with plugins in Colorus.js * docs: Update README.md with improved structure and examples * ci: Add code quality workflow using Biome * ci: Add NPM CI workflow for testing and building * ci: Add GitHub Actions Workflows for CI/CD and Dependency Management (#22) * ci: update lint & format configs * fix: upload linter fixes * ci: add the Release workflow * ci: upload dependabout.yml workflow * ci: move dependabout.yml to .github/ folder * chore(linter): update biome.js included files prefs * chore(scripts): improve package.json scripts * fix: resolve linting errors reported by Biome * ci: refact CI workflow for build & test * ci: refact Code Quality workflow * ci: fix name of linting script * chore(package.json): bump version and update description * refact(type): improve DyeReturns type --- .eslintrc.json | 15 - .github/dependabot.yml | 6 + .github/workflows/ci.yml | 55 + .github/workflows/code-quality.yml | 39 + .github/workflows/node-ci.yml | 54 - .github/workflows/release.yml | 40 + .npmignore | 1 + .prettierrc | 18 +- @types/main.d.ts | 267 - CONTRIBUTING.md | 46 + README.md | 104 +- biome.json | 49 + docs/WORKING_WITH_PLUGINS.md | 72 + jest.config.js | 40 +- package-lock.json | 9945 ++++++++++++---------- package.json | 123 +- rollup.config.js | 89 +- src/accessibility.js | 29 - src/colorFormatter.js | 69 - src/colorNormalizer.js | 45 - src/compose.js | 89 - src/constants/errorMessages.ts | 14 + src/constants/namedColors.ts | 178 + src/conversion.js | 277 - src/conversions/cmykConversions.ts | 20 + src/conversions/hexConversions.ts | 25 + src/conversions/hslConversions.ts | 26 + src/conversions/hsvConversions.ts | 60 + src/conversions/rgbConversions.ts | 105 + src/core/accessibility.ts | 33 + src/core/colorAdjustments.ts | 58 + src/core/colorFormatter.ts | 71 + src/core/colorNormalizer.ts | 64 + src/core/colorParser.ts | 54 + src/core/colorTypeAnalyzer.ts | 106 + src/core/conversionHelpers.ts | 66 + src/core/inputSerializer.ts | 89 + src/core/pluginValidation.ts | 21 + src/cssNamedColors.js | 161 - src/dye.ts | 133 + src/helpers.js | 106 - src/helpers.ts | 76 + src/isValidColor.ts | 27 + src/main.js | 247 - src/main.ts | 5 + src/serialize.js | 118 - src/types.ts | 195 + test/__fixtures__/cmykColors.ts | 51 + test/__fixtures__/hexColors.ts | 49 + test/__fixtures__/hslColors.ts | 50 + test/__fixtures__/hsvColors.ts | 50 + test/__fixtures__/index.ts | 84 + test/__fixtures__/rgbColors.ts | 48 + test/accessibility.spec.js | 63 - test/colorFormatter.spec.js | 101 - test/colorNormalizer.spec.js | 53 - test/compose.spec.js | 159 - test/conversion.spec.js | 380 - test/conversions/cmykConversions.test.ts | 44 + test/conversions/hexConversions.test.ts | 16 + test/conversions/hslConversions.test.ts | 98 + test/conversions/hsvConversions.test.ts | 83 + test/conversions/rgbConversions.test.ts | 174 + test/core/accessibility.test.ts | 90 + test/core/colorAdjustments.test.ts | 93 + test/core/colorFormatter.test.ts | 14 + test/core/colorNormalizer.test.ts | 149 + test/core/colorParser.test.ts | 34 + test/core/colorTypeAnalyzer.test.ts | 157 + test/core/conversionHelpers.test.ts | 96 + test/core/inputSerializer.test.ts | 92 + test/core/pluginValidation.test.ts | 24 + test/dye.test.ts | 161 + test/helpers.spec.js | 141 - test/helpers.test.ts | 80 + test/isValidColor.test.ts | 40 + test/main.spec.js | 137 - test/serializer.spec.js | 228 - tsconfig.json | 25 + 79 files changed, 9133 insertions(+), 7461 deletions(-) delete mode 100644 .eslintrc.json create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/code-quality.yml delete mode 100644 .github/workflows/node-ci.yml create mode 100644 .github/workflows/release.yml delete mode 100644 @types/main.d.ts create mode 100644 CONTRIBUTING.md create mode 100644 biome.json create mode 100644 docs/WORKING_WITH_PLUGINS.md delete mode 100644 src/accessibility.js delete mode 100644 src/colorFormatter.js delete mode 100644 src/colorNormalizer.js delete mode 100644 src/compose.js create mode 100644 src/constants/errorMessages.ts create mode 100644 src/constants/namedColors.ts delete mode 100644 src/conversion.js create mode 100644 src/conversions/cmykConversions.ts create mode 100644 src/conversions/hexConversions.ts create mode 100644 src/conversions/hslConversions.ts create mode 100644 src/conversions/hsvConversions.ts create mode 100644 src/conversions/rgbConversions.ts create mode 100644 src/core/accessibility.ts create mode 100644 src/core/colorAdjustments.ts create mode 100644 src/core/colorFormatter.ts create mode 100644 src/core/colorNormalizer.ts create mode 100644 src/core/colorParser.ts create mode 100644 src/core/colorTypeAnalyzer.ts create mode 100644 src/core/conversionHelpers.ts create mode 100644 src/core/inputSerializer.ts create mode 100644 src/core/pluginValidation.ts delete mode 100644 src/cssNamedColors.js create mode 100644 src/dye.ts delete mode 100644 src/helpers.js create mode 100644 src/helpers.ts create mode 100644 src/isValidColor.ts delete mode 100644 src/main.js create mode 100644 src/main.ts delete mode 100644 src/serialize.js create mode 100644 src/types.ts create mode 100644 test/__fixtures__/cmykColors.ts create mode 100644 test/__fixtures__/hexColors.ts create mode 100644 test/__fixtures__/hslColors.ts create mode 100644 test/__fixtures__/hsvColors.ts create mode 100644 test/__fixtures__/index.ts create mode 100644 test/__fixtures__/rgbColors.ts delete mode 100644 test/accessibility.spec.js delete mode 100644 test/colorFormatter.spec.js delete mode 100644 test/colorNormalizer.spec.js delete mode 100644 test/compose.spec.js delete mode 100644 test/conversion.spec.js create mode 100644 test/conversions/cmykConversions.test.ts create mode 100644 test/conversions/hexConversions.test.ts create mode 100644 test/conversions/hslConversions.test.ts create mode 100644 test/conversions/hsvConversions.test.ts create mode 100644 test/conversions/rgbConversions.test.ts create mode 100644 test/core/accessibility.test.ts create mode 100644 test/core/colorAdjustments.test.ts create mode 100644 test/core/colorFormatter.test.ts create mode 100644 test/core/colorNormalizer.test.ts create mode 100644 test/core/colorParser.test.ts create mode 100644 test/core/colorTypeAnalyzer.test.ts create mode 100644 test/core/conversionHelpers.test.ts create mode 100644 test/core/inputSerializer.test.ts create mode 100644 test/core/pluginValidation.test.ts create mode 100644 test/dye.test.ts delete mode 100644 test/helpers.spec.js create mode 100644 test/helpers.test.ts create mode 100644 test/isValidColor.test.ts delete mode 100644 test/main.spec.js delete mode 100644 test/serializer.spec.js create mode 100644 tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 590c359..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true, - "node": true - }, - "root": true, - "plugins": ["jsdoc"], - "extends": ["google", "prettier"], - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, - "rules": {} -} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5fea649 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "npm" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..465f51c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,55 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + name: Test & Build + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [22.x] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + + - name: Display Node.js version + run: node -v + + - name: Install dependencies + run: npm ci + + - name: Cache node_modules + uses: actions/cache@v3 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Run linting + run: npm run lint + + - name: Run type-checking + run: npm run check-types + + - name: Run tests + run: npm test + + - name: Build the package + run: npm run build diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml new file mode 100644 index 0000000..530980c --- /dev/null +++ b/.github/workflows/code-quality.yml @@ -0,0 +1,39 @@ +name: Code Quality + +on: [pull_request] + +jobs: + quality: + name: Lint, Format & Organize + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [22.x] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dependencies + run: npm ci + + - name: Cache node modules + uses: actions/cache@v3 + with: + path: node_modules + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Setup Biome.js + uses: biomejs/setup-biome@v2 + with: + version: latest + + - name: Run linting + run: npm run lint + + - name: Run docs formating + run: npm run format diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml deleted file mode 100644 index 0f3b7b5..0000000 --- a/.github/workflows/node-ci.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Node.js CI - -on: - push: - branches: ["main","nodejs-workflows"] - pull_request: - branches: ["main"] - -jobs: - build: - - name: Build, Lint, and Test - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [18.x] - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - - name: Display Node.js version - run: node -v - - - name: Install dependencies - run: npm ci - - - name: Cache node_modules - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Build the project - run: npm run build --if-present - - - name: Lint the code - run: npm run lint - - - name: Run Prettier - run: npm run prettier - - - name: Run tests - run: npm test \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..4b28e21 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,40 @@ +name: Release + +on: + release: + types: [published] + +jobs: + publish: + name: NPM Publish + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x] + + permissions: + contents: read # Allow reading repository contents + id-token: write # Allow writing an OIDC token for authentication + + steps: + - uses: actions/checkout@v4 # Check out the repository code + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + registry-url: "https://registry.npmjs.org" + cache: "npm" + + - name: Install dependencies + run: npm ci + + - name: Build the project (if applicable) + run: npm run build --if-present + + - name: Publish to npm + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.npmignore b/.npmignore index bb0d066..3d8eca2 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,7 @@ coverage src test +build mock bun.lockb .gitignore diff --git a/.prettierrc b/.prettierrc index 1db6a7b..b67937f 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,11 +1,11 @@ { - "semi": false, - "singleQuote": true, - "tabWidth": 2, - "printWidth": 140, - "trailingComma": "none", - "arrowParens": "avoid", - "bracketSpacing": true, - "quoteProps": "as-needed", - "endOfLine": "auto" + "semi": false, + "singleQuote": false, + "tabWidth": 2, + "printWidth": 140, + "trailingComma": "none", + "arrowParens": "avoid", + "bracketSpacing": true, + "quoteProps": "as-needed", + "endOfLine": "auto" } diff --git a/@types/main.d.ts b/@types/main.d.ts deleted file mode 100644 index 8c75df9..0000000 --- a/@types/main.d.ts +++ /dev/null @@ -1,267 +0,0 @@ -/** - * The `colorus-js` module allows for easy manipulation and conversion of colors between different formats. - */ -declare module 'colorus-js' { - type ColorChannel = number | string - - export type BaseColor = { - [key in K]: T - } & { a?: T } - - export type AnyRgb = BaseColor<'r' | 'g' | 'b', T> - export type RgbColor = AnyRgb - - export type AnyHsl = BaseColor<'h' | 's' | 'l', T> - export type HslColor = AnyHsl - - export type AnyHsv = BaseColor<'h' | 's' | 'v', T> - export type HsvColor = AnyHsv - - export type AnyCmyk = BaseColor<'c' | 'm' | 'y' | 'k', T> - export type CmykColor = AnyCmyk - - export type AnyColorType = 'rgb' | 'hsl' | 'hsv' | 'cmyk' - - export type AnyColorObject = AnyRgb | AnyHsl | AnyHsv | AnyCmyk - - export type AnyColor = string | AnyColorObject - - export interface FormatOptions { - /** - * Whether to attempt to minify the output. - * @example - * // Minified: 'hsl(240,20,30,0.5)' - * // Default: 'hsl(240ยฐ, 20%, 30%, 0.5)' - */ - minify?: boolean - - /** - * Whether to generate CSSNext compatible formatting. - * @example - * // CSSNext: 'rgb(2 2 30 / 0.5)' - * // Legacy: 'rgba(2, 2, 30, 0.5)' - */ - CSSNext?: boolean - } - - export interface HexFormatOptions { - /** - * Whether to attempt to minify the output. - * @example - * // Minified: '#FFF' - * // Default: '#FFFFFF' - */ - minify?: boolean - } - - /** - * Represents a plugin function that extends the Colorus instance with custom methods. - * - * @param this The Colorus instance to which the plugin methods will be added. - * @param args Any additional arguments passed to the plugin method. - * - * @returns An object containing the plugin methods to be added to the Colorus instance. - * - Keys should be the names of the plugin methods. - * - Values should be the corresponding functions. - */ - export type ColorusPlugin = (this: Colorus, ...args: any[]) => any - - export interface ColorusOptions { - /** - * An optional object containing plugin functions to extend the Colorus instance. - */ - plugins?: { - [methodName: string]: ColorusPlugin - } - } - - /** - * Utility that provides methods for working with colors. - * - * @remarks - * The `Colorus` class allows for creating, manipulating, and formatting colors in various formats. - * It provides methods for converting between different color formats, modifying colors, - * calculating contrast ratios, and inverting colors. - * - * @example - * ``` - * // Create a new Colorus instance - * const color = new Colorus('rgb(255, 0, 0)'); - * - * color.colorType; // Returns: 'rgb' - * color.lighten(0.2).toHex(); // Returns: '#FF3333' - * ``` - */ - export class Colorus { - /** - * Constructs a new Colorus instance with the given input and optional plugins. - * @param input - The color input string or object. - * @param options - Optional configuration options, including plugins. - * @throws If the input is not `undefined` or a valid color format (e.g. `string` or `object`). - * @throws If `options` is not a plain object. - * @throws If `options.plugins` is present but not a plain object with method names as keys and plugin functions as values. - */ - constructor(input?: AnyColor, options?: ColorusOptions) - - /** - * Analytical method to quickly test the `input` for any valid color. - * @param input - The color input string or object. - * @returns The type of the color (e.g.: `'rgb'`) if the color is valid, otherwise `null`. - * @example - * Colorus.test('#F33'); // Returns: 'hex' - * Colorus.test({ r: 255, g: 0, b: 0 }); // Returns: 'rgb' - * Colorus.test('#c('); // Returns: null - */ - static test(input?: AnyColor | unknown): AnyColorType | null - - /** Get the type of the current color. */ - get colorType(): AnyColorType | undefined - - /** - * Get the relative luminance of the current color. - * @see {@link https://www.w3.org/TR/WCAG20-TECHS/G17.html | Techniques for WCAG 2.0 - G17} - * @returns The relative luminance. - */ - get luminance(): number - - /** Get the `sRGB` object representation of the current color. */ - get rgb(): RgbColor - - /** Get the `HSL` object representation of the current color. */ - get hsl(): HslColor - - /** Get the `HSV` object representation of the current color. */ - get hsv(): HsvColor - - /** Get the `CMYK` object representation of the current color. */ - get cmyk(): CmykColor - - /** - * Convert the current color to hexadecimal format. - * @param options Formatting options. - * @returns The hexadecimal representation of the color. - * @example - * new Colorus('rgb(0, 0, 0)').toHex({ minify: true }); // Returns: '#000' - */ - toHex(options?: HexFormatOptions): string - - /** - * Convert the current color to `RGB` string format. - * @param options Formatting options. - * @returns The `RGB` string representation of the color. - */ - toRgb(options?: FormatOptions): string - - /** - * Convert the current color to `HSL` string format. - * @param options Formatting options. - * @returns The `HSL` representation of the color. - */ - toHsl(options?: FormatOptions): string - - /** - * Convert the current color to `HSV` string format. - * @param options Formatting options. - * @returns The `HSV` string representation of the color. - */ - toHsv(options?: FormatOptions): string - - /** - * Convert the current color to `CMYK` string format. - * @param options Formatting options. - * @returns The `CMYK` string representation of the color. - */ - toCmyk(options?: FormatOptions): string - - /** - * Convert the current color to the nearest CSS named color. - * @see https://www.w3.org/TR/css-color-4/#named-colors - * @returns The nearest CSS named color. - * @example - * const color = new Colorus('#f00') - * color.toNamed() // Returns: 'red' - */ - toNamed(): string - - /** - * Mixes the current color with another color. - * @param input The color to mix with. - * @param amount The amount of mixing. (Default: `0.1`) - * @returns A new Colorus instance representing the mixed color. - * @example - * const color = new Colorus('#f00'); - * color.mix('#fff9e6', 0.45).toHex(); // Returns: '#FF7068' - */ - mix(input: AnyColor, amount?: number): Colorus - - /** - * Lightens the current color. - * @param amount The amount of lightening. (Default: `0.1`) - * @returns A new Colorus instance representing the lightened color. - */ - lighten(amount?: number): Colorus - - /** - * Darkens the current color. - * @param amount The amount of darkening. - * @returns A new Colorus instance representing the darkened color. - */ - darken(amount?: number): Colorus - - /** - * Saturates the current color. - * @param amount The amount of saturation. (Default: `0.1`) - * @returns A new Colorus instance representing the saturated color. - */ - saturate(amount?: number): Colorus - - /** - * Desaturates the current color. - * @param amount The amount of desaturation. - * @returns A new Colorus instance representing the desaturated color. - */ - desaturate(amount?: number): Colorus - - /** - * Changes the hue of the current color. - * @param amount The amount of hue change. (Default: `0.1`) - * @returns A new Colorus instance representing the color with changed hue. - */ - hue(amount?: number): Colorus - - /** - * Changes the alpha (opacity) of the current color. - * @param amount The amount of alpha change. (Default: `0.1`) - * @returns A new Colorus instance representing the color with changed alpha. - */ - alpha(amount?: number): Colorus - - /** - * Gets the contrast ratio between the foreground color and its adjacent background. - * @param backgroundColor The background color. - * @returns The contrast ratio between the instantiated color and the provided background color. - * @example - * new Colorus('#000').contrastRatio('#f3f3f3'); // Returns: 18.92 - */ - contrastRatio(backgroundColor: AnyColor): number - - /** - * Inverts the color using sRGB values. - * @returns A new Colorus instance representing the color with inverted color values. - */ - invert(): Colorus - - /** - * Converts the current color to grayscale. - * @param useNTSCFormula Whether to use the NTSC formula for conversion. (Default: `false`) - * @returns A new Colorus instance representing the grayscale color. - * @example - * // Create a Colorus instance representing an RGB color - * const color = new Colorus('rgb(50 168 82)'); - * color.grayscale().toRgb(); // Returns: 'rgb(137, 137, 137)' - * // Convert using the NTSC formula - * color.grayscale(true).toRgb(); // Returns 'rgb(123, 123, 123)' - */ - grayscale(useNTSCFormula?: boolean): Colorus - } -} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6e52563 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# Contributing to Colorus.js ๐ŸŽ‰ + +We welcome contributions to Colorus.js! Whether you're fixing bugs ๐Ÿ›, improving documentation ๐Ÿ“š, or adding new features through plugins โœจ, your help is valuable in making this library even better. + +## Future Plans: Mono-repo ๐Ÿ“ฆ + +In the future, we intend to transition the Colorus.js repository into a mono-repo structure. This will allow us to manage the core package and official plugins within a single repository, streamlining development and maintenance. + +## Core Functionality: Non-Extensible (Intentional) ๐Ÿ”’ + +| Core Functionality | Extensible via Plugins | +| -------------------------- | ---------------------- | +| Color creation (`dye`) | No | +| Color conversions | No | +| Color adjustments | No | +| Accessibility calculations | No | + +The plugin system provides a powerful and flexible mechanism for adding custom features and behaviors to color objects created by `dye`. We encourage you to leverage this system to enhance the capabilities of Colorus.js without modifying its core. ๐Ÿ’ช + +## Focus on Performance ๐Ÿš€ + +We're always looking for ways to improve the performance of Colorus.js. Contributions that enhance the speed or reduce the bundle size of the library are highly appreciated. If you have ideas for optimizations or performance improvements, please share them with us! + +## How to Contribute ๐Ÿ› ๏ธ + +1. **For complex or significant changes:** Please open an issue first to discuss your proposed changes with the maintainers. This helps ensure alignment with the project's goals and avoids potential conflicts or wasted effort. ๐Ÿ’ฌ + +2. **For simple fixes (e.g., typos, grammar):** Feel free to directly open a pull request. ๐Ÿ‘ + +3. In either case, follow these steps: + - Fork the repository and create a new branch for your feature or bug fix. ๐Ÿด + - Make your changes and ensure that the code is well-documented and tested. ๐Ÿงช + - Submit a pull request, clearly describing your changes and their benefits. ๐Ÿš€ + +## Documentation and Type Support ๐Ÿ“š + +Clear and comprehensive documentation is essential for any library, and Colorus.js is no exception. We strive to provide accurate and up-to-date documentation for all core functions, types, and the plugin system. Contributions that improve the documentation, add examples, or clarify usage are highly valued. +โœ๏ธ + +### Type Safety and Function Chaining ๐Ÿ”’โ›“๏ธ + +We place a strong emphasis on type safety. The function chaining mechanism, in particular, relies heavily on TypeScript's type inference to provide a smooth and error-free developer experience. When contributing, pay close attention to maintaining and enhancing the type definitions, especially when modifying or adding new features that interact with the chaining mechanism. + +We appreciate your interest in contributing to Colorus.js! Please don't hesitate to reach out if you have any questions or need further guidance. ๐Ÿ™Œ + +**Thank you for your support!** ๐Ÿ™ diff --git a/README.md b/README.md index 0067c44..b391120 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,60 @@ -# Colorus-js +

+ +

- +# Colorus.js -Colorus is a versatile tool designed for seamless color manipulation across various formats. Whether you're handling RGB, HSL, HSV, or CMYK colors, Colorus streamlines the process, offering a hassle-free experience for managing colors in your projects. +[![NPM](https://img.shields.io/badge/NPM-%23CB3837.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=black&color=black)](https://www.npmjs.com/package/colorus-js) +[![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white&labelColor=black&color=black)](https://www.typescriptlang.org/) +[![GitHub stars](https://img.shields.io/github/stars/supitsdu/colorus-js?style=for-the-badge&logo=Github&logoColor=white&labelColor=black&color=black)](https://github.com/supitsdu/colorus-js) -The key features of Colorus include: +A versatile and powerful color manipulation library for JavaScript. -- **Color Format Conversion**: Effortlessly convert between different color formats such as RGB, HSL, HSV, and CMYK using a straightforward API. -- **Color Manipulation**: Adjust colors with ease using functions like lightening, darkening, saturating, desaturating, mixing, or changing hue to achieve your desired effects. -- **Customizable Formatting**: Tailor the output format of colors to your needs with options for minification and CSSNext compatibility. -- **Contrast Ratio Calculation**: Ensure accessibility compliance by calculating the contrast ratio between colors, aiding in meeting web accessibility standards. +## Features -## Installation +- **Intuitive API:** Work with colors effortlessly using a simple and expressive function-based API. +- **Multiple Color Models:** Supports various color models, including RGB, HSL, HSV, and CMYK. +- **Flexible Input/Output:** Accepts color inputs in different formats (hex, rgb, hsl, etc.) and provides various output options. +- **Color Conversions:** Easily convert between different color models and formats. +- **Color Adjustments:** Perform common color adjustments like lightening, darkening, saturating, desaturating, and more. +- **Accessibility:** Calculate relative luminance and contrast ratios for improved accessibility. +- **Extensible:** Extend the core functionality with custom plugins. +- **TypeScript Support:** Provides full TypeScript support for enhanced type safety and developer experience. -You can install Colorus via npm: +### Usage -```sh -npm i colorus-js -``` - -## Usage +```javascript +import { dye } from "colorus-js" -```js -const { Colorus } = require('colorus-js') +const color = dye("#ff0000") // Create a color from a hex code -// Create a new Colorus instance -const color = new Colorus('rgb(255 0 0)') +console.log(color.rgb) // Output: { r: 255, g: 0, b: 0, a: 1 } +console.log(color.toHsl()) // Output: hsl(0, 100%, 50%) -console.log(color.colorType) // Returns: 'rgb' -console.log(color.lighten(0.2).toHex({ minify: true })) // Returns: '#F33' +const lighterColor = color.lighten(0.2) // Lighten the color by 20% +console.log(lighterColor.toHex()) // Output: #ff6666 ``` -## API Reference - -### `Colorus` +### Plugins -Utility that provides methods for working with colors. +Extend the `dye` function with custom methods using plugins. -#### Constructor +```javascript +const colorWithPlugin = dye("#0000ff", { + plugins: { + isBlue() { + return this.rgb.b > 200 + } + } +}) -Creates a new Colorus instance with the provided input. - -```ts -constructor(input?: AnyColor) +console.log(colorWithPlugin.isBlue()) // Output: true ``` -- `input`: The color input string or object. - -#### Properties - -- `colorType`: Get the type of the current color. -- `luminance`: Get the relative luminance of the current color. -- `rgb`: Get the `sRGB` object representation of the current color. -- `hsl`: Get the `HSL` object representation of the current color. -- `hsv`: Get the `HSV` object representation of the current color. -- `cmyk`: Get the `CMYK` object representation of the current color. - -#### Methods - -- `toHex(options): string`: Convert the current color to hexadecimal format. -- `toRgb(options): string`: Convert the current color to `RGB` string format. -- `toHsl(options): string`: Convert the current color to `HSL` string format. -- `toHsv(options): string`: Convert the current color to `HSV` string format. -- `toCmyk(options): string`: Convert the current color to `CMYK` string format. -- `toNamed(): string`: Convert the current color to its nearest [CSS named color](https://www.w3.org/TR/css-color-4/#named-colors) representation. -- `mix(input, amount): Colorus`: Mixes the current color with another color. -- `lighten(amount): Colorus`: Lightens the current color. -- `darken(amount): Colorus`: Darkens the current color. -- `saturate(amount): Colorus`: Saturates the current color. -- `desaturate(amount): Colorus`: Desaturates the current color. -- `hue(amount): Colorus`: Changes the hue of the current color. -- `alpha(amount): Colorus`: Changes the alpha (opacity) of the current color. -- `contrastRatio(backgroundColor): number`: Gets the contrast ratio between a foreground color and its adjacent background. -- `invert(): Colorus`: Inverts the color using sRGB values. -- `grayscale(): Colorus`: Converts the current color to grayscale. - -#### Static Methods +For more information see [Working with Plugins Guide](docs/WORKING_WITH_PLUGINS.md). -- `test(input): string | null`: An analytical method to quickly test the input for any valid color. Returns the type of the color (e.g.: `'rgb'`) if the color is valid, otherwise `null`. +## Contributing -## License +Contributions are welcome! Please read the [Contributing Guide](CONTRIBUTING.md). -This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. +[**Leave a star and help spread the hues! ๐ŸŽจโญ**](https://github.com/supitsdu/colorus-js) diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..288e26d --- /dev/null +++ b/biome.json @@ -0,0 +1,49 @@ +{ + "files": { + "ignore": ["node_modules", "coverage", "docs", ".github", "_test"], + "include": ["src/*.ts", "test/*.ts"] + }, + "organizeImports": { "enabled": true }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "ignore": [], + "attributePosition": "auto", + "indentStyle": "tab", + "indentWidth": 2, + "lineWidth": 80, + "lineEnding": "lf" + }, + "javascript": { + "formatter": { + "quoteStyle": "double", + "arrowParentheses": "asNeeded", + "bracketSameLine": false, + "bracketSpacing": true, + "jsxQuoteStyle": "double", + "quoteProperties": "asNeeded", + "semicolons": "always", + "trailingCommas": "all", + "lineEnding": "lf" + } + }, + "linter": { + "enabled": true, + "rules": { + "complexity": { + "noStaticOnlyClass": "warn" + }, + "suspicious": { + "noDebugger": "off", + "noConsoleLog": "info", + "noExplicitAny": "off", + "noConfusingVoidType": "off" + }, + "style": { + "noShoutyConstants": "warn", + "useNamingConvention": "error", + "noNonNullAssertion": "off" + } + } + } +} diff --git a/docs/WORKING_WITH_PLUGINS.md b/docs/WORKING_WITH_PLUGINS.md new file mode 100644 index 0000000..5dfd870 --- /dev/null +++ b/docs/WORKING_WITH_PLUGINS.md @@ -0,0 +1,72 @@ +# Working with Plugins + +**Colorus.js** offers a powerful plugin system to extend the capabilities of the `dye()` function, allowing you to add custom methods and functionalities to color objects. This guide will walk you through the process of creating, using, and understanding plugins in Colorus.js. + +## What are Plugins? ๐Ÿค” + +Plugins are essentially functions that you can attach to color objects created by the `dye()` function. These functions can access the color's properties and methods, enabling you to perform custom calculations, transformations, or any other color-related operations. ๐ŸŽจ + +### Defining a Plugin ๐Ÿงฉ + +A plugin is defined as a function that takes the color object as its `this` context and any additional arguments you might need + +```typescript +import type { Dye } from "colorus-js" + +export function myPlugin(this: Dye, ...args: any[]) { + // Access color properties and methods using 'this' keyword + console.debug(this.rgb) + console.debug(this.toHex()) + + // Perform custom logic or calculations... + + return someValue // Optionally return a value +} +``` + +### Using Plugins with `dye()` ๐Ÿงช + +You can attach plugins to a color object by passing them in the `options.plugins` object when calling `dye()`. + +```typescript +import { dye } from "colorus-js" +import { myPlugin } from "./myPlugin.ts" + +const color = dye("#ff0000", { + plugins: { + myPlugin, + isRed() { + return this.rgb.r > 200 && this.rgb.g < 50 && this.rgb.b < 50 + } + } +}) + +console.debug(color.myPlugin()) +console.debug(color.isRed()) +``` + +### Plugin Chaining โ›“๏ธ + +One of the powerful features of Colorus.js plugins is the ability to chain them with the core color manipulation methods. + +```typescript +const lighterColor = color.lighten(0.2) +console.debug(lighterColor.getHue()) +``` + +### Type Safety with Plugins โœ… + +Colorus.js leverages TypeScript to provide strong type safety when working with plugins. + +- The `this` context within plugin methods is automatically typed as a `DyeReturns` object, giving you access to all the core color properties and methods through autocompletion and type checking. ๐Ÿ‘ +- If your plugin returns a new color object, TypeScript will infer the correct type for the chained calls, ensuring that any subsequent plugin methods are also available. ๐Ÿ”„ + +### Important Considerations โš ๏ธ + +- **Plugin Naming:** Choose descriptive and unique names for your plugin methods to avoid conflicts with core methods or other plugins. ๐Ÿ“› +- **Side Effects:** Be mindful of side effects within your plugins. Avoid modifying the original color object directly unless that's the intended behavior. ๐Ÿงช +- **Performance:** If your plugin performs complex calculations, consider optimizing it for performance, especially if it will be used in computationally intensive scenarios. โšก + +### Conclusion + +The plugin system in Colorus.js opens up a world of possibilities for extending and customizing the library to fit your specific needs. We encourage you to explore this feature and create plugins that enhance your color manipulation workflows! ๐Ÿš€ diff --git a/jest.config.js b/jest.config.js index 0d0124d..1786558 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,30 +4,30 @@ */ export default { - // A map from regular expressions to paths to transformers - transform: { - '^.+\\.js$': '@swc/jest' - }, + // A map from regular expressions to paths to transformers + transform: { + "^.+\\.(ts|js)$": "@swc/jest", + }, - // Automatically clear mock calls, instances, contexts and results before every test - clearMocks: true, + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, - // Indicates whether the coverage information should be collected while executing the test - collectCoverage: true, + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, - // The directory where Jest should output its coverage files - coverageDirectory: 'coverage', + // The directory where Jest should output its coverage files + coverageDirectory: "coverage", - // Indicates which provider should be used to instrument code for coverage - coverageProvider: 'v8', - coverageReporters: ['html-spa'], + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "v8", + coverageReporters: ["html-spa"], - // An array of file extensions your modules use - moduleFileExtensions: ['js'], + // An array of file extensions your modules use + moduleFileExtensions: ["js", "ts"], - // A list of paths to directories that Jest should use to search for files in - roots: ['./test', './src'], + // A list of paths to directories that Jest should use to search for files in + roots: ["./test", "./src"], - // The glob patterns Jest uses to detect test files - testMatch: ['**/?(*.)+(spec|test).js'] -} + // The glob patterns Jest uses to detect test files + testMatch: ["**/?(*.)+(spec|test).(ts|js)"], +}; diff --git a/package-lock.json b/package-lock.json index 4af1897..2b76354 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,4544 +1,5405 @@ { - "name": "colorus-js", - "version": "0.9.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "colorus-js", - "version": "0.9.0", - "license": "MIT", - "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.7", - "@rollup/plugin-node-resolve": "^15.2.3", - "@rollup/plugin-swc": "^0.3.0", - "@swc/core": "^1.4.0", - "@swc/jest": "^0.2.36", - "eslint": "^8.57.0", - "eslint-config-google": "^0.14.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jsdoc": "^48.2.3", - "jest": "^29.7.0", - "prettier": "^3.2.5", - "rollup": "4.18.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helpers": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk/node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk/node_modules/ansi-styles/node_modules/color-convert": { - "version": "1.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/chalk/node_modules/ansi-styles/node_modules/color-convert/node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk/node_modules/supports-color/node_modules/has-flag": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.24.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@es-joy/jsdoccomment": { - "version": "0.43.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "^8.56.5", - "@types/estree": "^1.0.5", - "@typescript-eslint/types": "^7.2.0", - "comment-parser": "1.4.1", - "esquery": "^1.5.0", - "jsdoc-type-pratt-parser": "~4.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/node_modules/locate-path/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/node_modules/locate-path/node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml/node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/create-cache-key-function": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "25.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "glob": "^8.0.3", - "is-reference": "1.2.1", - "magic-string": "^0.30.3" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-builtin-module": "^3.2.1", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-swc": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "smob": "^1.4.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "@swc/core": "^1.3.0", - "rollup": "^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.0", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.0", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "dev": true, - "license": "MIT" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@swc/core": { - "version": "1.5.25", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.7" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.5.25", - "@swc/core-darwin-x64": "1.5.25", - "@swc/core-linux-arm-gnueabihf": "1.5.25", - "@swc/core-linux-arm64-gnu": "1.5.25", - "@swc/core-linux-arm64-musl": "1.5.25", - "@swc/core-linux-x64-gnu": "1.5.25", - "@swc/core-linux-x64-musl": "1.5.25", - "@swc/core-win32-arm64-msvc": "1.5.25", - "@swc/core-win32-ia32-msvc": "1.5.25", - "@swc/core-win32-x64-msvc": "1.5.25" - }, - "peerDependencies": { - "@swc/helpers": "*" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.5.25", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.5.25", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/@swc/jest": { - "version": "0.2.36", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/create-cache-key-function": "^29.7.0", - "@swc/counter": "^0.1.3", - "jsonc-parser": "^3.2.0" - }, - "engines": { - "npm": ">= 7.0.0" - }, - "peerDependencies": { - "@swc/core": "*" - } - }, - "node_modules/@swc/types": { - "version": "0.1.7", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@swc/counter": "^0.1.3" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/eslint": { - "version": "8.56.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.14.2", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/types": { - "version": "7.12.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "dev": true, - "license": "ISC" - }, - "node_modules/acorn": { - "version": "8.11.3", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/are-docs-informative": { - "version": "0.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.0", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001629", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui": { - "version": "8.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/co": { - "version": "4.6.0", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/comment-parser": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/create-jest": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dedent": { - "version": "1.5.3", - "dev": true, - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.792", - "dev": true, - "license": "ISC" - }, - "node_modules/emittery": { - "version": "0.13.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-google": { - "version": "0.14.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-jsdoc": { - "version": "48.2.8", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@es-joy/jsdoccomment": "~0.43.1", - "are-docs-informative": "^0.0.2", - "comment-parser": "1.4.1", - "debug": "^4.3.4", - "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "semver": "^7.6.2", - "spdx-expression-parse": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/esutils": { - "version": "2.0.3", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.17.1", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "dev": true, - "license": "ISC" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/function-bind": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "8.1.0", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/glob/node_modules/minimatch/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/human-signals": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/ignore": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "dev": true, - "license": "ISC" - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-module": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-reference": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.2", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-config/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdoc-type-pratt-parser": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/keyv": { - "version": "4.5.4", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/node-int64": { - "version": "0.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.14", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.0.1", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up/node_modules/locate-path/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up/node_modules/locate-path/node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.3.1", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/require-directory": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.18.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.0", - "@rollup/rollup-android-arm64": "4.18.0", - "@rollup/rollup-darwin-arm64": "4.18.0", - "@rollup/rollup-darwin-x64": "4.18.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", - "@rollup/rollup-linux-arm-musleabihf": "4.18.0", - "@rollup/rollup-linux-arm64-gnu": "4.18.0", - "@rollup/rollup-linux-arm64-musl": "4.18.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", - "@rollup/rollup-linux-riscv64-gnu": "4.18.0", - "@rollup/rollup-linux-s390x-gnu": "4.18.0", - "@rollup/rollup-linux-x64-gnu": "4.18.0", - "@rollup/rollup-linux-x64-musl": "4.18.0", - "@rollup/rollup-win32-arm64-msvc": "4.18.0", - "@rollup/rollup-win32-ia32-msvc": "4.18.0", - "@rollup/rollup-win32-x64-msvc": "4.18.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/semver": { - "version": "7.6.2", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "dev": true, - "license": "ISC" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/smob": { - "version": "1.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.18", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/tmpl": { - "version": "1.0.5", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "dev": true, - "license": "MIT" - }, - "node_modules/update-browserslist-db": { - "version": "1.0.16", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "license": "ISC" - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } + "name": "colorus-js", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "colorus-js", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@biomejs/biome": "1.8.3", + "@rollup/plugin-typescript": "^11.1.6", + "@swc/core": "^1.7.18", + "@swc/jest": "^0.2.36", + "@types/jest": "^29.5.12", + "jest": "^29.7.0", + "prettier": "^3.3.3", + "rollup": "4.18.0", + "rollup-plugin-bundle-size": "^1.0.3", + "rollup-plugin-dts": "^6.1.1", + "rollup-plugin-esbuild": "^6.1.1", + "tslib": "^2.7.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@biomejs/biome": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.8.3.tgz", + "integrity": "sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.8.3", + "@biomejs/cli-darwin-x64": "1.8.3", + "@biomejs/cli-linux-arm64": "1.8.3", + "@biomejs/cli-linux-arm64-musl": "1.8.3", + "@biomejs/cli-linux-x64": "1.8.3", + "@biomejs/cli-linux-x64-musl": "1.8.3", + "@biomejs/cli-win32-arm64": "1.8.3", + "@biomejs/cli-win32-x64": "1.8.3" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.8.3.tgz", + "integrity": "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.8.3.tgz", + "integrity": "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.8.3.tgz", + "integrity": "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.8.3.tgz", + "integrity": "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.8.3.tgz", + "integrity": "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.8.3.tgz", + "integrity": "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.8.3.tgz", + "integrity": "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.8.3.tgz", + "integrity": "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rollup/plugin-typescript": { + "version": "11.1.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz", + "integrity": "sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0||^4.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@swc/core": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.21.tgz", + "integrity": "sha512-7/cN0SZ+y2V6e0hsDD8koGR0QVh7Jl3r756bwaHLLSN+kReoUb/yVcLsA8iTn90JLME3DkQK4CPjxDCQiyMXNg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.7.21", + "@swc/core-darwin-x64": "1.7.21", + "@swc/core-linux-arm-gnueabihf": "1.7.21", + "@swc/core-linux-arm64-gnu": "1.7.21", + "@swc/core-linux-arm64-musl": "1.7.21", + "@swc/core-linux-x64-gnu": "1.7.21", + "@swc/core-linux-x64-musl": "1.7.21", + "@swc/core-win32-arm64-msvc": "1.7.21", + "@swc/core-win32-ia32-msvc": "1.7.21", + "@swc/core-win32-x64-msvc": "1.7.21" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.21.tgz", + "integrity": "sha512-hh5uOZ7jWF66z2TRMhhXtWMQkssuPCSIZPy9VHf5KvZ46cX+5UeECDthchYklEVZQyy4Qr6oxfh4qff/5spoMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.21.tgz", + "integrity": "sha512-lTsPquqSierQ6jWiWM7NnYXXZGk9zx3NGkPLHjPbcH5BmyiauX0CC/YJYJx7YmS2InRLyALlGmidHkaF4JY28A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.21.tgz", + "integrity": "sha512-AgSd0fnSzAqCvWpzzZCq75z62JVGUkkXEOpfdi99jj/tryPy38KdXJtkVWJmufPXlRHokGTBitalk33WDJwsbA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.21.tgz", + "integrity": "sha512-l+jw6RQ4Y43/8dIst0c73uQE+W3kCWrCFqMqC/xIuE/iqHOnvYK6YbA1ffOct2dImkHzNiKuoehGqtQAc6cNaQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.21.tgz", + "integrity": "sha512-29KKZXrTo/c9F1JFL9WsNvCa6UCdIVhHP5EfuYhlKbn5/YmSsNFkuHdUtZFEd5U4+jiShXDmgGCtLW2d08LIwg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.21.tgz", + "integrity": "sha512-HsP3JwddvQj5HvnjmOr+Bd5plEm6ccpfP5wUlm3hywzvdVkj+yR29bmD7UwpV/1zCQ60Ry35a7mXhKI6HQxFgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.21.tgz", + "integrity": "sha512-hYKLVeUTHqvFK628DFJEwxoX6p42T3HaQ4QjNtf3oKhiJWFh9iTRUrN/oCB5YI3R9WMkFkKh+99gZ/Dd0T5lsg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.21.tgz", + "integrity": "sha512-qyWAKW10aMBe6iUqeZ7NAJIswjfggVTUpDINpQGUJhz+pR71YZDidXgZXpaDB84YyDB2JAlRqd1YrLkl7CMiIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.21.tgz", + "integrity": "sha512-cy61wS3wgH5mEwBiQ5w6/FnQrchBDAdPsSh0dKSzNmI+4K8hDxS8uzdBycWqJXO0cc+mA77SIlwZC3hP3Kum2g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.21.tgz", + "integrity": "sha512-/rexGItJURNJOdae+a48M+loT74nsEU+PyRRVAkZMKNRtLoYFAr0cpDlS5FodIgGunp/nqM0bst4H2w6Y05IKA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@swc/jest": { + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.36.tgz", + "integrity": "sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/create-cache-key-function": "^29.7.0", + "@swc/counter": "^0.1.3", + "jsonc-parser": "^3.2.0" + }, + "engines": { + "npm": ">= 7.0.0" + }, + "peerDependencies": { + "@swc/core": "*" + } + }, + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/node": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", + "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001653", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz", + "integrity": "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz", + "integrity": "sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", + "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz", + "integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/maxmin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", + "integrity": "sha512-NWlApBjW9az9qRPaeg7CX4sQBWwytqz32bIEo1PW9pRW+kBP9KLRfJO3UC+TV31EcQZEUq7eMzikC7zt3zPJcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^1.0.0", + "figures": "^1.0.1", + "gzip-size": "^3.0.0", + "pretty-bytes": "^3.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/maxmin/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/maxmin/node_modules/gzip-size": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", + "integrity": "sha512-6s8trQiK+OMzSaCSVXX+iqIcLV9tC+E73jrJrJTyS4h/AJhlxHvzFKqM1YLDJWRGgHX8uLkBeXkA0njNj39L4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.1" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/maxmin/node_modules/pretty-bytes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", + "integrity": "sha512-eb7ZAeUTgfh294cElcu51w+OTRp/6ItW758LjwJSK72LDevcuJn0P4eD71PLMDGPwwatXmAmYHTkzvpKlJE3ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-bundle-size": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-bundle-size/-/rollup-plugin-bundle-size-1.0.3.tgz", + "integrity": "sha512-aWj0Pvzq90fqbI5vN1IvUrlf4utOqy+AERYxwWjegH1G8PzheMnrRIgQ5tkwKVtQMDP0bHZEACW/zLDF+XgfXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^1.1.3", + "maxmin": "^2.1.0" + } + }, + "node_modules/rollup-plugin-bundle-size/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup-plugin-bundle-size/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup-plugin-bundle-size/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup-plugin-bundle-size/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/rollup-plugin-bundle-size/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup-plugin-bundle-size/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/rollup-plugin-dts": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.1.1.tgz", + "integrity": "sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==", + "dev": true, + "license": "LGPL-3.0-only", + "dependencies": { + "magic-string": "^0.30.10" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.24.2" + }, + "peerDependencies": { + "rollup": "^3.29.4 || ^4", + "typescript": "^4.5 || ^5.0" + } + }, + "node_modules/rollup-plugin-esbuild": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-6.1.1.tgz", + "integrity": "sha512-CehMY9FAqJD5OUaE/Mi1r5z0kNeYxItmRO2zG4Qnv2qWKF09J2lTy5GUzjJR354ZPrLkCj4fiBN41lo8PzBUhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.5", + "debug": "^4.3.4", + "es-module-lexer": "^1.3.1", + "get-tsconfig": "^4.7.2" + }, + "engines": { + "node": ">=14.18.0" + }, + "peerDependencies": { + "esbuild": ">=0.18.0", + "rollup": "^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } } diff --git a/package.json b/package.json index 119a7b3..6591deb 100644 --- a/package.json +++ b/package.json @@ -1,64 +1,63 @@ { - "name": "colorus-js", - "version": "0.9.0", - "description": "Sleek and powerful color manipulation library for JavaScript.", - "type": "module", - "sideEffects": false, - "main": "./dist/main.js", - "module": "./dist/main.js", - "files": [ - "dist", - "@types", - "README.md", - "LICENSE" - ], - "exports": { - ".": { - "import": "./dist/main.js", - "require": "./dist/main.cjs", - "types": "./@types/main.d.ts" - } - }, - "scripts": { - "lint": "eslint ./src/*.js", - "lint:fix": "eslint --fix ./src/*.js", - "prettier": "prettier --check src", - "prettier:fix": "prettier --write src", - "format": "npm run lint:fix && npm run prettier:fix", - "test": "jest", - "build": "rollup -c" - }, - "author": "Eduardo M. Santos", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/supitsdu/colorus-js.git" - }, - "bugs": { - "url": "https://github.com/supitsdu/colorus-js/issues" - }, - "homepage": "https://github.com/supitsdu/colorus-js/", - "keywords": [ - "color", - "colours", - "hex", - "rgb", - "hsl", - "convert", - "adjust" - ], - "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.7", - "@rollup/plugin-node-resolve": "^15.2.3", - "@rollup/plugin-swc": "^0.3.0", - "@swc/core": "^1.4.0", - "@swc/jest": "^0.2.36", - "eslint": "^8.57.0", - "eslint-config-google": "^0.14.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jsdoc": "^48.2.3", - "jest": "^29.7.0", - "prettier": "^3.2.5", - "rollup": "4.18.0" - } + "name": "colorus-js", + "version": "1.0.0", + "description": "Extend, enhance, create! ๐ŸŽจ Colorus.js: Your extensible, type-safe color library.", + "type": "module", + "sideEffects": false, + "main": "./dist/main.js", + "module": "./dist/main.js", + "types": "./dist/main.d.ts", + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "exports": { + ".": { + "import": "./dist/main.js", + "require": "./dist/main.cjs", + "types": "./dist/main.d.ts" + } + }, + "scripts": { + "check-types": "tsc --noEmit", + "lint:fix": "biome check --write", + "lint": "biome ci", + "format": "prettier --check *.md", + "test": "jest", + "build": "rollup -c" + }, + "author": "Eduardo M. Santos", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/supitsdu/colorus-js.git" + }, + "bugs": { + "url": "https://github.com/supitsdu/colorus-js/issues" + }, + "homepage": "https://github.com/supitsdu/colorus-js/", + "keywords": [ + "color", + "colours", + "hex", + "rgb", + "hsl", + "convert", + "adjust" + ], + "devDependencies": { + "@biomejs/biome": "1.8.3", + "@rollup/plugin-typescript": "^11.1.6", + "@swc/core": "^1.7.18", + "@swc/jest": "^0.2.36", + "@types/jest": "^29.5.12", + "jest": "^29.7.0", + "prettier": "^3.3.3", + "rollup": "4.18.0", + "rollup-plugin-bundle-size": "^1.0.3", + "rollup-plugin-dts": "^6.1.1", + "rollup-plugin-esbuild": "^6.1.1", + "tslib": "^2.7.0" + } } diff --git a/rollup.config.js b/rollup.config.js index 2506cb6..4862f8f 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,26 +1,65 @@ -import { nodeResolve } from '@rollup/plugin-node-resolve' -import commonjs from '@rollup/plugin-commonjs' -import swc from '@rollup/plugin-swc' +// This Rollup configuration defines a three-phase build process: +// +// 1. Transpile TypeScript to JavaScript and generate declaration files (`.d.ts`). +// 2. Bundle and minify the JavaScript code using esbuild, creating both CommonJS and ES module outputs. +// 3. Bundle TypeScript declaration files into a single file for distribution. +// +// The `tsconfig.json` file is used for TypeScript compilation settings, including the output location for declaration files. -export default { - input: 'src/main.js', - output: [ - { - file: 'dist/main.js', - format: 'es' - }, - { - file: 'dist/main.cjs', - format: 'cjs' - } - ], - plugins: [ - nodeResolve(), // resolve node_modules - commonjs(), - swc({ - swc: { - minify: true - } - }) // transpile JavaScript code using SWC - ] -} +import esbuild from "rollup-plugin-esbuild"; +import typescript from "@rollup/plugin-typescript"; +import dts from "rollup-plugin-dts"; +import bundleSize from "rollup-plugin-bundle-size"; + +export default [ + // Phase 1: Transpile TypeScript to JavaScript and generate declaration files (`.d.ts`) + { + input: "src/main.ts", // Entry point of your TypeScript code + plugins: [ + typescript(), // Compiles TypeScript to JavaScript. See: https://github.com/rollup/plugins/tree/master/packages/typescript + bundleSize(), // Prints bundle size. See: https://github.com/sindresorhus/maxmin + ], + output: { + file: "build/main.js", // Output the compiled JavaScript to this file + format: "es", // Use ECMAScript module format + exports: "auto", // Let Rollup determine how to handle exports + }, + }, + + // Phase 2: Bundle and minify the JavaScript code using esbuild + { + input: "build/main.js", // Take the output from phase 1 as input + plugins: [ + esbuild({ + minify: true, // Minify the code to reduce file size + target: "esnext", // Target the latest JavaScript features + minifyIdentifiers: true, // Shorten variable and function names + minifySyntax: true, // Remove unnecessary whitespace and syntax + minifyWhitespace: true, // Further reduce whitespace + }), // See: https://github.com/egoist/rollup-plugin-esbuild + bundleSize(), + ], + output: [ + { + file: "dist/main.cjs", // Output a CommonJS module + format: "cjs", + exports: "auto", + }, + { + file: "dist/main.js", // Output an ES module + format: "esm", + exports: "auto", + }, + ], + }, + + // Phase 3: Bundle TypeScript declaration files into a single file + { + input: "build/@types/main.d.ts", // Take the output from phase 1 as TypeScript declarations, as configured in tsconfig.json ("declarationDir") + plugins: [ + dts(), // Bundles .d.ts files. See: https://github.com/Swatinem/rollup-plugin-dts + bundleSize(), + ], + output: [{ file: "dist/main.d.ts", format: "esm", exports: "auto" }], // Output the bundled declarations + }, +]; diff --git a/src/accessibility.js b/src/accessibility.js deleted file mode 100644 index be681cc..0000000 --- a/src/accessibility.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Calculate the relative luminance of an sRGB color. - * @param {object} color - An object containing the sRGB components of the color. - * @return {number} The luminance value of the color. - */ -export const relativeLuminance = ({ r, g, b }) => { - const fn = c => { - c /= 255 - return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4 - } - - return fn(r) * 0.2126 + fn(g) * 0.7152 + fn(b) * 0.0722 -} - -/** - * Calculate the contrast ratio between two relative luminance values. - * @param {number} L1 - The relative luminance of the lighter color. - * @param {number} L2 - The relative luminance of the darker color. - * @return {number} The contrast ratio between the two colors. - */ -export const calculateContrastRatio = (L1, L2) => (Math.max(L1, L2) + 0.05) / (Math.min(L1, L2) + 0.05) - -/** - * Calculate the contrast ratio between a foreground color and its adjacent background. - * @param {object} fg - The sRGB color values of the foreground. - * @param {object} bg - The sRGB color values of the background. - * @return {number} The contrast ratio between the two colors. - */ -export const contrastRatio = (fg, bg) => calculateContrastRatio(relativeLuminance(fg), relativeLuminance(bg)) diff --git a/src/colorFormatter.js b/src/colorFormatter.js deleted file mode 100644 index 5250137..0000000 --- a/src/colorFormatter.js +++ /dev/null @@ -1,69 +0,0 @@ -import { Round } from './colorNormalizer' - -/** A class for formatting color values into various formats. */ -class ColorFormatter { - #spacer - #percent - #degree - #suffix - #alpha - - /** - * Constructs a ColorFormatter object. - * @param {object} options - Options for formatting. - * @param {boolean} options.minify - Whether to minify the output. - * @param {boolean} options.CSSNext - Whether to use CSSNext compatible formatting. - */ - constructor({ minify, CSSNext } = {}) { - const space = minify !== true ? ' ' : '' - const alphaSpacer = CSSNext === true ? `${space}/${space}` : `,${space}` - - this.#spacer = CSSNext === true ? ' ' : `,${space}` - this.#percent = minify !== true ? '%' : '' - this.#degree = minify !== true ? 'ยฐ' : '' - this.#suffix = a => (a == 1 || CSSNext == true ? '' : 'a') - this.#alpha = a => (a == 1 ? '' : `${alphaSpacer}${a}`) - } - - /** - * Format RGB color string. - * @param {object} input A valid RGB color object, - * @return {string} the RGB color string. - */ - rgb(input) { - const { r, g, b, a } = Round.rgb(input) - return `rgb${this.#suffix(a)}(${r}${this.#spacer}${g}${this.#spacer}${b}${this.#alpha(a)})` - } - - /** - * Format HSL color string. - * @param {object} input A valid HSL color object, - * @return {string} the HSL color string. - */ - hsl(input) { - const { h, s, l, a } = Round.hsl(input) - return `hsl${this.#suffix(a)}(${h}${this.#degree}${this.#spacer}${s}${this.#percent}${this.#spacer}${l}${this.#percent}${this.#alpha(a)})` - } - - /** - * Format HSV color string. - * @param {object} input A valid HSV color object, - * @return {string} the HSV color string. - */ - hsv(input) { - const { h, s, v, a } = Round.hsv(input) - return `hsv${this.#suffix(a)}(${h}${this.#degree}${this.#spacer}${s}${this.#percent}${this.#spacer}${v}${this.#percent}${this.#alpha(a)})` - } - - /** - * Format CMYK color string. - * @param {object} input A valid CMYK color object, - * @return {string} the CMYK color string. - */ - cmyk(input) { - const { c, m, k, y, a } = Round.cmyk(input) - return `cmyk${this.#suffix(a)}(${c}${this.#percent}${this.#spacer}${m}${this.#percent}${this.#spacer}${y}${this.#percent}${this.#spacer}${k}${this.#percent}${this.#alpha(a)})` - } -} - -export default ColorFormatter diff --git a/src/colorNormalizer.js b/src/colorNormalizer.js deleted file mode 100644 index 1a4f733..0000000 --- a/src/colorNormalizer.js +++ /dev/null @@ -1,45 +0,0 @@ -import { utmost, precision } from './helpers' - -// Helper functions to process different types of color values -export const degree = (value, fn = Math.round) => fn(utmost(value, 360)) || 0 -export const percent = (value, fn = Math.round) => fn(utmost(value, 100)) || 0 -export const eightBit = (value, fn = Math.round) => fn(utmost(value, 255)) || 0 -export const alpha = (value, fn = precision) => fn(utmost(value, 1)) || 0 - -/** Base class for rounding/clamping color values */ -class ColorNormalizer { - /** Rounds or clamps an HSL color object. - * @param {object} input HSL color object. - * @return {object} An valid HSL color object - */ - static hsl({ h, s, l, a = 1 }) { - return { h: degree(h, this.fn), s: percent(s, this.fn), l: percent(l, this.fn), a: alpha(a) } - } - - /** Rounds or clamps an HSV color object. - * @param {object} input HSV color object. - * @return {object} An valid HSV color object - */ - static hsv({ h, s, v, a = 1 }) { - return { h: degree(h, this.fn), s: percent(s, this.fn), v: percent(v, this.fn), a: alpha(a) } - } - - /** Rounds or clamps an RGB color object. - * @param {object} input RGB color object. - * @return {object} An valid RGB color object - */ - static rgb({ r, g, b, a = 1 }) { - return { r: eightBit(r, this.fn), g: eightBit(g, this.fn), b: eightBit(b, this.fn), a: alpha(a) } - } - - /** Rounds or clamps an CMYK color object. - * @param {object} input CMYK color object. - * @return {object} An valid CMYK color object - */ - static cmyk({ c, m, y, k, a = 1 }) { - return { c: percent(c, this.fn), m: percent(m, this.fn), y: percent(y, this.fn), k: percent(k, this.fn), a: alpha(a) } - } -} - -export const Round = Object.assign(Object.create(ColorNormalizer), { fn: Math.round }) -export const Clamp = Object.assign(Object.create(ColorNormalizer), { fn: precision }) diff --git a/src/compose.js b/src/compose.js deleted file mode 100644 index b868df4..0000000 --- a/src/compose.js +++ /dev/null @@ -1,89 +0,0 @@ -import { nan, precision } from './helpers' -import { Clamp } from './colorNormalizer' - -/** - * Modifies the given `value` by a certain `amount`. - * - * @param {number} value - The value to modify. - * @param {number} amount - The amount to modify the `value` by, a value between 0 and 1. - * @return {number} The modified `value`. - */ -export const modBy = (value, amount) => { - amount = Number(amount) - - if (nan(amount)) return value - - return precision((1 + amount) * value) -} - -/** - * Interpolates between two RGB colors based on a given amount. - * @param {object} primary - The primary color in RGB format. - * @param {object} secondary - The secondary color in RGB format. - * @param {number} amount - A value between 0 and 1, indicating the strength of interpolation. - * @return {object} An object containing interpolated RGB and optional alpha values. - */ -export const mix = ({ r, g, b, a = 1 }, { r: R, g: G, b: B, a: A = 1 }, amount = 0.1) => { - const mixBy = (p, s) => p * (1 - amount) + s * amount - - return Clamp.rgb({ r: mixBy(r, R), g: mixBy(g, G), b: mixBy(b, B), a: mixBy(a * 100, A * 100) }) -} - -/** - * Lightens an HSL color by the specified amount. - * @param {object} color - HSL color object to lighten. - * @param {number} amount - A value between 0 and 1. - * @return {object} New HSL color object. - */ -export const lighten = ({ h, s, l, a = 1 }, amount) => { - return Clamp.hsl({ h, s, l: modBy(l, amount), a }) -} - -/** - * Saturate an HSL color by the specified amount. - * @param {object} color - HSL color object to lighten. - * @param {number} amount - A value between 0 and 1. - * @return {object} New HSL color object. - */ -export const saturate = ({ h, s, l, a = 1 }, amount) => { - return Clamp.hsl({ h, s: modBy(s, amount), l: l, a }) -} - -/** - * Adjust the hue of a HSL color. - * @param {object} color - HSL color object.. - * @param {number} amount - A value between 0 and 1. - * @return {object} New HSL color object. - */ -export const hue = ({ h, s, l, a = 1 }, amount) => { - return Clamp.hsl({ h: modBy(h, amount), s, l, a }) -} - -/** - * Adjust the alpha channel of a RGB color. - * @param {object} color - RGB color object.. - * @param {number} amount - A value between 0 and 1. - * @return {object} New RGB color object. - */ -export const alpha = ({ r, g, b, a = 1 }, amount) => { - return Clamp.rgb({ r, g, b, a: modBy(a, amount) }) -} - -/** - * Invert an RGB color. - * @param {object} color - RGB color object. - * @return {object} New RGB color object. - */ -export const invert = ({ r, g, b, a = 1 }) => ({ r: 255 - r, g: 255 - g, b: 255 - b, a }) - -/** - * Converts an RGB color to grayscale. - * @param {Object} color - An object representing an RGBA color. - * @param {boolean} [useNTSCFormula=false] - Whether to use the NTSC formula for conversion. (Default: `false`) - * @return {Object} An object representing the grayscale color. - */ -export const rgbToGray = ({ r, g, b, a = 1 }, useNTSCFormula = false) => { - const y = useNTSCFormula ? 0.299 * r + 0.587 * g + 0.114 * b : 0.2126 * r + 0.7152 * g + 0.0722 * b - - return { r: y, g: y, b: y, a } -} diff --git a/src/constants/errorMessages.ts b/src/constants/errorMessages.ts new file mode 100644 index 0000000..30b5b8c --- /dev/null +++ b/src/constants/errorMessages.ts @@ -0,0 +1,14 @@ +export const errorMessages = { + invalidOptions: "Invalid options: Expected a plain object.", + invalidPlugins: + "Invalid plugins: Expected a plain object with method names as keys.", + invalidPlugin: (methodName: string) => + `Invalid plugin for '${methodName}': Expected a function.`, + invalidPluginOverwrite: (methodName: string) => + `Invalid plugin for '${methodName}': Overwritring an existing method is not allowed.`, + invalidColorString: (input: string) => `Invalid color string: ${input}`, + invalidColorObject: (input: unknown) => + `Invalid color object: ${JSON.stringify(input)}`, + invalidColorType: + "Invalid color type, expected a valid color string or object.", +}; diff --git a/src/constants/namedColors.ts b/src/constants/namedColors.ts new file mode 100644 index 0000000..ab31b69 --- /dev/null +++ b/src/constants/namedColors.ts @@ -0,0 +1,178 @@ +import type { ExecMatchClone, NamedColorsParsers } from "../types"; + +export const namedColorsMap = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "00ffff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000000", + blanchedalmond: "ffebcd", + blue: "0000ff", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "00ffff", + darkblue: "00008b", + darkcyan: "008b8b", + darkgoldenrod: "b8860b", + darkgray: "a9a9a9", + darkgreen: "006400", + darkgrey: "a9a9a9", + darkkhaki: "bdb76b", + darkmagenta: "8b008b", + darkolivegreen: "556b2f", + darkorange: "ff8c00", + darkorchid: "9932cc", + darkred: "8b0000", + darksalmon: "e9967a", + darkseagreen: "8fbc8f", + darkslateblue: "483d8b", + darkslategray: "2f4f4f", + darkslategrey: "2f4f4f", + darkturquoise: "00ced1", + darkviolet: "9400d3", + deeppink: "ff1493", + deepskyblue: "00bfff", + dimgray: "696969", + dimgrey: "696969", + dodgerblue: "1e90ff", + firebrick: "b22222", + floralwhite: "fffaf0", + forestgreen: "228b22", + fuchsia: "ff00ff", + gainsboro: "dcdcdc", + ghostwhite: "f8f8ff", + gold: "ffd700", + goldenrod: "daa520", + gray: "808080", + green: "008000", + greenyellow: "adff2f", + grey: "808080", + honeydew: "f0fff0", + hotpink: "ff69b4", + indianred: "cd5c5c", + indigo: "4b0082", + ivory: "fffff0", + khaki: "f0e68c", + lavender: "e6e6fa", + lavenderblush: "fff0f5", + lawngreen: "7cfc00", + lemonchiffon: "fffacd", + lightblue: "add8e6", + lightcoral: "f08080", + lightcyan: "e0ffff", + lightgoldenrodyellow: "fafad2", + lightgray: "d3d3d3", + lightgreen: "90ee90", + lightgrey: "d3d3d3", + lightpink: "ffb6c1", + lightsalmon: "ffa07a", + lightseagreen: "20b2aa", + lightskyblue: "87cefa", + lightslategray: "778899", + lightslategrey: "778899", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "00ff00", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "ff00ff", + maroon: "800000", + mediumaquamarine: "66cdaa", + mediumblue: "0000cd", + mediumorchid: "ba55d3", + mediumpurple: "9370db", + mediumseagreen: "3cb371", + mediumslateblue: "7b68ee", + mediumspringgreen: "00fa9a", + mediumturquoise: "48d1cc", + mediumvioletred: "c71585", + midnightblue: "191970", + mintcream: "f5fffa", + mistyrose: "ffe4e1", + moccasin: "ffe4b5", + navajowhite: "ffdead", + navy: "000080", + oldlace: "fdf5e6", + olive: "808000", + olivedrab: "6b8e23", + orange: "ffa500", + orangered: "ff4500", + orchid: "da70d6", + palegoldenrod: "eee8aa", + palegreen: "98fb98", + paleturquoise: "afeeee", + palevioletred: "db7093", + papayawhip: "ffefd5", + peachpuff: "ffdab9", + peru: "cd853f", + pink: "ffc0cb", + plum: "dda0dd", + powderblue: "b0e0e6", + purple: "800080", + rebeccapurple: "663399", + red: "ff0000", + rosybrown: "bc8f8f", + royalblue: "4169e1", + saddlebrown: "8b4513", + salmon: "fa8072", + sandybrown: "f4a460", + seagreen: "2e8b57", + seashell: "fff5ee", + sienna: "a0522d", + silver: "c0c0c0", + skyblue: "87ceeb", + slateblue: "6a5acd", + slategray: "708090", + slategrey: "708090", + snow: "fffafa", + springgreen: "00ff7f", + steelblue: "4682b4", + tan: "d2b48c", + teal: "008080", + thistle: "d8bfd8", + tomato: "ff6347", + turquoise: "40e0d0", + violet: "ee82ee", + wheat: "f5deb3", + white: "ffffff", + whitesmoke: "f5f5f5", + yellow: "ffff00", + yellowgreen: "9acd32", +}; + +/** + * Formats a named color into its standardized CSS representation. + * + * @param name - The named color string (e.g., "Red", "Rebecca Purple", "slate-grey"). + * @returns The standardized CSS named color (e.g., "red", "rebeccapurple", "slategrey") or the original input if not found. + */ +const formatNamedColor = (name: string): string => + name.toLowerCase().replace(/[\s-]+/g, ""); + +const execMatch: ExecMatchClone = { + pattern: { + lastIndex: 0, + exec(input: string) { + const color = formatNamedColor(input); + if (!Object.hasOwn(namedColorsMap, color)) return null; + const match = namedColorsMap[color as keyof typeof namedColorsMap]; + return match !== undefined ? [match] : null; + }, + }, +}; + +export default { + colors: namedColorsMap, + ...execMatch, +} as NamedColorsParsers; diff --git a/src/conversion.js b/src/conversion.js deleted file mode 100644 index 1093bcf..0000000 --- a/src/conversion.js +++ /dev/null @@ -1,277 +0,0 @@ -import CSSNamedColors from './cssNamedColors' -import { Clamp, Round, eightBit } from './colorNormalizer' -import { hexString } from './helpers' - -/** - * Calculates the Euclidean distance between two RGB colors. - * @param {object} primary - The first RGB color string. - * @param {object} secondary - The second RGB color string. - * @return {number} The distance between the two colors. - */ -export const computeColorDistance = ({ r: r1, g: g1, b: b1 }, { r: r2, g: g2, b: b2 }) => - Math.sqrt(Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2)) - -/** - * Converts RGB values to the nearest CSS named color. - * @param {object} color - The RGB color object. - * @return {string} The name of the color. - */ -export function rgbToNamedColor({ r, g, b }) { - let closestColor = undefined - let shortestDistance = Infinity - - for (const [name, color] of Object.entries(CSSNamedColors.colors)) { - const distance = computeColorDistance({ r, g, b }, hexToRgb(color)) - - if (distance < shortestDistance) { - shortestDistance = distance - closestColor = name - } - } - - return closestColor -} - -/** - * Calculates the hue component of an HSV color object. - * @param {object} rgb - An RGB color object. - * @param {object} params - Parameters including segment, maxRgb, and minRgb. - * @return {number} The hue component of the HSV color. - */ -export function computeHsvHue({ r, g, b }, { segment, maxRgb, minRgb }) { - let h = 0 - - if (segment === h) return h - - const delta = maxRgb - minRgb - const rDelta = (r - minRgb) / delta - const gDelta = (g - minRgb) / delta - const bDelta = (b - minRgb) / delta - - // Calculate hue based on which color component is the max - if (r === maxRgb) { - h = (60 * (gDelta - bDelta)) % 360 - } else if (g === maxRgb) { - h = 60 * (bDelta - rDelta) + 120 - } else { - h = 60 * (rDelta - gDelta) + 240 - } - - // Ensure hue is within [0, 360) - if (h < 0) { - h += 360 - } - - return h -} - -/** - * Check if an HEX color is shortanable by comparing the RGB components. - * @param {number} r the red channel component of RGB color - * @param {number} g the green channel component of RGB color - * @param {number} b the blue channel component of RGB color - * @param {number} a the alpha channel component of RGBA color - * @return {boolean} - */ -export const isRgbShortanable = (r, g, b, a = 1) => r % 17 === 0 && g % 17 === 0 && b % 17 === 0 && a % 17 === 0 - -/** - * Converts RGB color object to HEX color string. - * @param {object} rgb an valid RGB color object - * @param {object} [options={}] options to customize output format and precision - * @param {boolean} [options.minify=false] set `true` for minified hexadecimal notation. - * @return {string} an HEX string - */ -export function rgbToHex({ r, g, b, a } = {}, { minify = false } = {}) { - const { r: R, g: G, b: B, a: A } = Round.rgb({ r, g, b, a }) - - const alphaInEightBit = eightBit(A * 255) - - let value = hexString((R << 16) | (G << 8) | B, 6) - - if (alphaInEightBit < 255) { - const alphaHex = hexString(alphaInEightBit, 2) - value += alphaHex - } - - if (minify && isRgbShortanable(R, G, B, alphaInEightBit)) { - value = value.replace(/(.)\1/g, '$1') - } - - return `#${value}` -} - -/** - * Converts a HEX color into an RGB color object representation. - * @param {string} hex - A valid HEX color without the hashtag "#". The alpha channel is optional. - * @return {object} An RGB color object representation. - */ -export function hexToRgb(hex) { - const delta = parseInt(hex, 16) - const value = {} - - if (hex.length === 6) { - value.r = (delta >> 16) & 255 - value.g = (delta >> 8) & 255 - value.b = delta & 255 - value.a = 1 - } else { - value.r = (delta >> 24) & 255 - value.g = (delta >> 16) & 255 - value.b = (delta >> 8) & 255 - value.a = (delta & 255) / 255 - } - - return Clamp.rgb(value) -} - -/** - * Converts an HSL color to its HSV representation. - * @param {object} hsl - An HSL color object. - * @return {object} - An HSV color object representation. - */ -export function hslToHsv({ h, s, l, a = 1 }) { - const deltaS = (s * (l < 50 ? l : 100 - l)) / 100 - const v = l + deltaS - - s = deltaS > 0 ? ((2 * deltaS) / (l + deltaS)) * 100 : 0 - - return Clamp.hsv({ h, s, v, a }) -} - -/** - * Converts HSV color object into its HSL representation using interconversion. - * @param {object} hsv - An HSV color object. - * @return {object} - An HSL color object representation. - */ -export function hsvToHsl({ h, s, v, a = 1 }) { - const deltaL = ((200 - s) * v) / 100 - - const l = deltaL / 2 - - if (deltaL > 0 && deltaL < 200) { - s = ((s * v) / 100 / (deltaL <= 100 ? deltaL : 200 - deltaL)) * 100 - } else { - s = 0 - } - - return Clamp.hsl({ h, s, l, a }) -} - -/** - * Converts an RGB color object into its HSV representation. - * @param {object} rgb - An RGB color object. - * @return {object} - An HSV color object representation. - */ -export function rgbToHsv({ r, g, b, a = 1 }) { - // Find maximum and minimum values among RGB components - const maxRgb = Math.max(r, g, b) - const minRgb = Math.min(r, g, b) - const segment = maxRgb - minRgb - - // Calculate value (brightness) - const v = (maxRgb / 255) * 100 - const s = (maxRgb > 0 ? segment / maxRgb : 0) * 100 - const h = computeHsvHue({ r, g, b }, { segment, maxRgb, minRgb }) - - return Clamp.hsv({ h, s, v, a }) -} - -/** - * Converts an RGB color object into its CMYK representation. - * @param {object} rgb - An RGB color object. - * @return {object} An CMYK color object representation. - */ -export function rgbToCmyk({ r, g, b, a = 1 }) { - r /= 255 - g /= 255 - b /= 255 - - const k = 1 - Math.max(r, g, b) - const c = (1 - r - k) / (1 - k) - const m = (1 - g - k) / (1 - k) - const y = (1 - b - k) / (1 - k) - - return Clamp.cmyk({ c: c * 100, m: m * 100, y: y * 100, k: k * 100, a }) -} - -/** - * Converts an CMYK color object into its RGB representation. - * @param {object} cmyk - An CMYK color object. - * @return {object} An RGB color object representation. - */ -export function cmykToRgb({ c, m, y, k, a = 1 }) { - c /= 100 - m /= 100 - y /= 100 - k /= 100 - - const r = 255 * ((1 - c) * (1 - k)) - const g = 255 * ((1 - m) * (1 - k)) - const b = 255 * ((1 - y) * (1 - k)) - - return Clamp.rgb({ r, g, b, a }) -} - -/** - * Converts an HSV color object into its RGB representation. - * @param {object} hsv - An HSV color object. - * @return {object} An RGB color object representation. - */ -export function hsvToRgb({ h, s, v, a = 1 }) { - // Convert degrees to the range [0, 6] - const hueRange = (h / 60) % 6 - // Normalize saturation and value to the range [0, 1] - const saturation = s / 100 - const value = v / 100 - - // Calculate chroma, second largest component, and minimum component - const chroma = value * saturation - const secondLargestComponent = chroma * (1 - Math.abs((hueRange % 2) - 1)) - const minComponent = value - chroma - - let red - let green - let blue - - // Determine the RGB components based on the hue range - if (0 <= hueRange && hueRange < 1) { - ;[red, green, blue] = [chroma, secondLargestComponent, 0] - } else if (1 <= hueRange && hueRange < 2) { - ;[red, green, blue] = [secondLargestComponent, chroma, 0] - } else if (2 <= hueRange && hueRange < 3) { - ;[red, green, blue] = [0, chroma, secondLargestComponent] - } else if (3 <= hueRange && hueRange < 4) { - ;[red, green, blue] = [0, secondLargestComponent, chroma] - } else if (4 <= hueRange && hueRange < 5) { - ;[red, green, blue] = [secondLargestComponent, 0, chroma] - } else { - ;[red, green, blue] = [chroma, 0, secondLargestComponent] - } - - // Clamp and return RGB values - return Clamp.rgb({ - r: (red + minComponent) * 255, - g: (green + minComponent) * 255, - b: (blue + minComponent) * 255, - a: a - }) -} - -/** - * Converts HSL color object into its RGB representation using HSV interconversion. - * @param {object} input - An HSL color object. - * @return {object} An RGB color object representation. - */ -export function hslToRgb({ h, s, l, a = 1 }) { - return hsvToRgb(hslToHsv({ h, s, l, a })) -} - -/** - * Converts RGB color object into its HSL representation using HSV interconversion. - * @param {object} input - An RGB color object. - * @return {object} An HSL color object representation. - */ -export function rgbToHsl({ r, g, b, a = 1 }) { - return hsvToHsl(rgbToHsv({ r, g, b, a })) -} diff --git a/src/conversions/cmykConversions.ts b/src/conversions/cmykConversions.ts new file mode 100644 index 0000000..130dc72 --- /dev/null +++ b/src/conversions/cmykConversions.ts @@ -0,0 +1,20 @@ +import { Clamp } from "../core/colorNormalizer"; +import type { Cmyk, Rgb } from "../types"; + +/** + * Converts an Cmyk color object into its Rgb representation. + * @param {object} cmyk - An Cmyk color object. + * @return {object} An Rgb color object representation. + */ +export function cmykToRgb({ c, m, y, k, a = 1 }: Cmyk): Rgb { + c /= 100; + m /= 100; + y /= 100; + k /= 100; + + const r = 255 * ((1 - c) * (1 - k)); + const g = 255 * ((1 - m) * (1 - k)); + const b = 255 * ((1 - y) * (1 - k)); + + return Clamp.rgb({ r, g, b, a }); +} diff --git a/src/conversions/hexConversions.ts b/src/conversions/hexConversions.ts new file mode 100644 index 0000000..448bd45 --- /dev/null +++ b/src/conversions/hexConversions.ts @@ -0,0 +1,25 @@ +import { Clamp } from "../core/colorNormalizer"; +import type { AnyObject, Rgb } from "../types"; + +/** + * Converts a HEX color into an Rgb color object representation. + * @param hex - A valid HEX color without the hashtag "#". The alpha channel is optional. + */ +export function hexToRgb(hex: string): Rgb { + const delta = Number.parseInt(hex, 16); + const value: AnyObject = {}; + + if (hex.length === 6) { + value.r = (delta >> 16) & 255; + value.g = (delta >> 8) & 255; + value.b = delta & 255; + value.a = 1; + } else { + value.r = (delta >> 24) & 255; + value.g = (delta >> 16) & 255; + value.b = (delta >> 8) & 255; + value.a = (delta & 255) / 255; + } + + return Clamp.rgb(value); +} diff --git a/src/conversions/hslConversions.ts b/src/conversions/hslConversions.ts new file mode 100644 index 0000000..eda32fb --- /dev/null +++ b/src/conversions/hslConversions.ts @@ -0,0 +1,26 @@ +import { Clamp } from "../core/colorNormalizer"; +import type { Hsl, Hsv, Rgb } from "../types"; +import { hsvToRgb } from "./hsvConversions"; + +/** + * Converts an Hsl color to its Hsv representation. + * @param {object} hsl - An Hsl color object. + * @return {object} - An Hsv color object representation. + */ +export function hslToHsv({ h, s, l, a = 1 }: Hsl): Hsv { + const deltaS = (s * (l < 50 ? l : 100 - l)) / 100; + const v = l + deltaS; + + const S = deltaS > 0 ? ((2 * deltaS) / (l + deltaS)) * 100 : 0; + + return Clamp.hsv({ h, s: S, v, a }); +} + +/** + * Converts Hsl color object into its Rgb representation using Hsv interconversion. + * @param {object} input - An Hsl color object. + * @return {object} An Rgb color object representation. + */ +export function hslToRgb({ h, s, l, a = 1 }: Hsl): Rgb { + return hsvToRgb(hslToHsv({ h, s, l, a })); +} diff --git a/src/conversions/hsvConversions.ts b/src/conversions/hsvConversions.ts new file mode 100644 index 0000000..4bbd00d --- /dev/null +++ b/src/conversions/hsvConversions.ts @@ -0,0 +1,60 @@ +import { Clamp } from "../core/colorNormalizer"; +import type { Hsl, Hsv, Rgb } from "../types"; + +/** + * Converts Hsv color object into its Hsl representation using interconversion. + * @param hsv - An Hsv color object. + */ +export function hsvToHsl({ h, s, v, a = 1 }: Hsv): Hsl { + const deltaL = ((200 - s) * v) / 100; + + const l = deltaL / 2; + + if (deltaL > 0 && deltaL < 200) { + s = ((s * v) / 100 / (deltaL <= 100 ? deltaL : 200 - deltaL)) * 100; + } else { + s = 0; + } + + return Clamp.hsl({ h, s, l, a }); +} + +/** + * Converts an Hsv color object into its Rgb representation. + * @param hsv - An Hsv color object. + */ +export function hsvToRgb({ h, s, v, a = 1 }: Hsv): Rgb { + const hueRange = (h / 60) % 6; + const saturation = s / 100; + const value = v / 100; + + const chroma = value * saturation; + const secondLargestComponent = chroma * (1 - Math.abs((hueRange % 2) - 1)); + const minComponent = value - chroma; + + let red: number; + let green: number; + let blue: number; + + // Determine the Rgb components based on the hue range + if (0 <= hueRange && hueRange < 1) { + [red, green, blue] = [chroma, secondLargestComponent, 0]; + } else if (1 <= hueRange && hueRange < 2) { + [red, green, blue] = [secondLargestComponent, chroma, 0]; + } else if (2 <= hueRange && hueRange < 3) { + [red, green, blue] = [0, chroma, secondLargestComponent]; + } else if (3 <= hueRange && hueRange < 4) { + [red, green, blue] = [0, secondLargestComponent, chroma]; + } else if (4 <= hueRange && hueRange < 5) { + [red, green, blue] = [secondLargestComponent, 0, chroma]; + } else { + [red, green, blue] = [chroma, 0, secondLargestComponent]; + } + + return Clamp.rgb({ + r: (red + minComponent) * 255, + g: (green + minComponent) * 255, + b: (blue + minComponent) * 255, + a: a, + }); +} diff --git a/src/conversions/rgbConversions.ts b/src/conversions/rgbConversions.ts new file mode 100644 index 0000000..b205672 --- /dev/null +++ b/src/conversions/rgbConversions.ts @@ -0,0 +1,105 @@ +import { namedColorsMap } from "../constants/namedColors"; +import { Clamp, Round, eightBit } from "../core/colorNormalizer"; +import { + computeColorDistance, + computeHsvHue, + isRgbShortanable, +} from "../core/conversionHelpers"; +import { hexString } from "../helpers"; +import type { Cmyk, FormatOptions, Hsl, Hsv, Rgb } from "../types"; +import { hexToRgb } from "./hexConversions"; +import { hsvToHsl } from "./hsvConversions"; + +/** + * Converts Rgb values to the nearest CSS named color. + * @param color - The Rgb color object. + */ +export function rgbToNamedColor({ r, g, b }: Rgb): string { + let closestColor = "black"; + let shortestDistance = Number.POSITIVE_INFINITY; + + for (const [name, color] of Object.entries(namedColorsMap)) { + const distance = computeColorDistance({ r, g, b }, hexToRgb(color)); + + if (distance < shortestDistance) { + shortestDistance = distance; + closestColor = name; + } + } + + return closestColor; +} + +/** + * Converts Rgb color object to HEX color string. + * @param rgb an valid Rgb color object + * @param options options to customize output format and precision + * @param options.minify set `true` for minified hexadecimal notation. + */ +export function rgbToHex( + { r, g, b, a = 1 }: Rgb, + options?: FormatOptions, +): string { + const { minify } = { minify: false, ...options }; + + const { r: R, g: G, b: B, a: A } = Round.rgb({ r, g, b, a }); + + const alphaInEightBit = eightBit(A * 255); + + let value = hexString((R << 16) | (G << 8) | B, 6); + + if (alphaInEightBit < 255) { + const alphaHex = hexString(alphaInEightBit, 2); + value += alphaHex; + } + + if (minify && isRgbShortanable(R, G, B, alphaInEightBit)) { + value = value.replace(/(.)\1/g, "$1"); + } + + return `#${value}`; +} + +/** + * Converts an Rgb color object into its Hsv representation. + * @param {object} rgb - An Rgb color object. + * @return {object} - An Hsv color object representation. + */ +export function rgbToHsv({ r, g, b, a = 1 }: Rgb): Hsv { + const maxRgb = Math.max(r, g, b); + const minRgb = Math.min(r, g, b); + const segment = maxRgb - minRgb; + + const v = (maxRgb / 255) * 100; + const s = (maxRgb > 0 ? segment / maxRgb : 0) * 100; + const h = computeHsvHue({ r, g, b }, { segment, maxRgb, minRgb }); + + return Clamp.hsv({ h, s, v, a }); +} + +/** + * Converts an Rgb color object into its Cmyk representation. + * @param {object} rgb - An Rgb color object. + * @return {object} An Cmyk color object representation. + */ +export function rgbToCmyk({ r, g, b, a = 1 }: Rgb): Cmyk { + const R = r / 255; + const G = g / 255; + const B = b / 255; + + const k = 1 - Math.max(R, G, B); + const c = (1 - R - k) / (1 - k); + const m = (1 - G - k) / (1 - k); + const y = (1 - B - k) / (1 - k); + + return Clamp.cmyk({ c: c * 100, m: m * 100, y: y * 100, k: k * 100, a }); +} + +/** + * Converts Rgb color object into its Hsl representation using Hsv interconversion. + * @param {object} input - An Rgb color object. + * @return {object} An Hsl color object representation. + */ +export function rgbToHsl({ r, g, b, a = 1 }: Rgb): Hsl { + return hsvToHsl(rgbToHsv({ r, g, b, a })); +} diff --git a/src/core/accessibility.ts b/src/core/accessibility.ts new file mode 100644 index 0000000..3780935 --- /dev/null +++ b/src/core/accessibility.ts @@ -0,0 +1,33 @@ +import type { Rgb } from "../types"; + +/** + * Calculate the relative luminance of an sRGB color. + * @param {object} color - An object containing the sRGB components of the color. + * @return The luminance value of the color. + */ +export const relativeLuminance = ({ r, g, b }: Rgb): number => { + const fn = (c: number) => { + const d = c / 255; + return d <= 0.03928 ? d / 12.92 : ((d + 0.055) / 1.055) ** 2.4; + }; + + return fn(r) * 0.2126 + fn(g) * 0.7152 + fn(b) * 0.0722; +}; + +/** + * Calculate the contrast ratio between two relative luminance values. + * @param L1 - The relative luminance of the lighter color. + * @param L2 - The relative luminance of the darker color. + * @return The contrast ratio between the two colors. + */ +export const calculateContrastRatio = (L1: number, L2: number): number => + (Math.max(L1, L2) + 0.05) / (Math.min(L1, L2) + 0.05); + +/** + * Calculate the contrast ratio between a foreground color and its adjacent background. + * @param fg - The sRGB color values of the foreground. + * @param bg - The sRGB color values of the background. + * @return The contrast ratio between the two colors. + */ +export const contrastRatio = (fg: Rgb, bg: Rgb) => + calculateContrastRatio(relativeLuminance(fg), relativeLuminance(bg)); diff --git a/src/core/colorAdjustments.ts b/src/core/colorAdjustments.ts new file mode 100644 index 0000000..e369e01 --- /dev/null +++ b/src/core/colorAdjustments.ts @@ -0,0 +1,58 @@ +import { nan, precision } from "../helpers"; +import type { Hsl, Rgb } from "../types"; +import { Clamp } from "./colorNormalizer"; + +/** + * Modifies the given `value` by a certain `amount`. + * + * @param value - The value to modify. + * @param amount - The amount to modify the `value` by, a value between 0 and 1. + * @return The modified `value`. + */ +export const modBy = (value: number, amount: number): number => { + const a = Number(amount); + + if (nan(a)) return value; + + return precision((1 + a) * value); +}; + +/** + * Lightens an Hsl color by the specified amount. + * @param color - Hsl color object to lighten. + * @param amount - A value between 0 and 1. + * @return New Hsl color object. + */ +export const lighten = (color: Hsl, amount: number): Hsl => { + return Clamp.hsl({ ...color, l: modBy(color.l, amount) }); +}; + +/** + * Saturate an Hsl color by the specified amount. + * @param color - Hsl color object to lighten. + * @param amount - A value between 0 and 1. + * @return New Hsl color object. + */ +export const saturate = (color: Hsl, amount: number): Hsl => { + return Clamp.hsl({ ...color, s: modBy(color.s, amount) }); +}; + +/** + * Adjust the hue of a Hsl color. + * @param color - Hsl color object.. + * @param amount - A value between 0 and 1. + * @return New Hsl color object. + */ +export const hue = (color: Hsl, amount: number): Hsl => { + return Clamp.hsl({ ...color, h: modBy(color.h, amount) }); +}; + +/** + * Adjust the alpha channel of a Rgb color. + * @param color - Rgb color object.. + * @param amount - A value between 0 and 1. + * @return New Rgb color object. + */ +export const alpha = (color: Rgb, amount: number): Rgb => { + return Clamp.rgb({ ...color, a: modBy(color.a ?? 1, amount) }); // Handle optional alpha +}; diff --git a/src/core/colorFormatter.ts b/src/core/colorFormatter.ts new file mode 100644 index 0000000..a49efa2 --- /dev/null +++ b/src/core/colorFormatter.ts @@ -0,0 +1,71 @@ +import { Round } from "./colorNormalizer"; + +import type { Cmyk, FormatOptions, Hsl, Hsv, Rgb } from "../types"; + +interface FormatPrefs { + spacer: string; + percent: string; + suffix: (a?: number) => string; + alpha: (a?: number) => string; +} + +const processFormatOptions = ({ + minify, + cssNext, +}: FormatOptions = {}): FormatPrefs => { + const space = !minify ? " " : ""; + const alphaSpacer = cssNext ? `${space}/${space}` : `,${space}`; + + return { + spacer: cssNext ? " " : `,${space}`, + percent: !minify ? "%" : "", + suffix: (a?: number) => (a === 1 || cssNext ? "" : "a"), + alpha: (a?: number) => (a === 1 ? "" : `${alphaSpacer}${a}`), + }; +}; + +export default { + /** + * Converts an RGB Object into its string representation. + * @param input An valid RGB object. + * @returns an color string supported by CSS and other styling tools. + */ + rgb(input: Rgb, options?: FormatOptions) { + const { r, g, b, a } = Round.rgb(input); + const { suffix, spacer, alpha } = processFormatOptions(options); + return `rgb${suffix(a)}(${r}${spacer}${g}${spacer}${b}${alpha(a)})`; + }, + + /** + * Converts an HSL Object into its string representation. + * @param input An valid HSL object. + * @returns a color string supported by CSS and other styling tools. + */ + hsl(input: Hsl, options?: FormatOptions): string { + const { h, s, l, a } = Round.hsl(input); + const { suffix, spacer, percent, alpha } = processFormatOptions(options); + return `hsl${suffix(a)}(${h}${spacer}${s}${percent}${spacer}${l}${percent}${alpha(a)})`; + }, + + /** + * Converts an HSV Object into its string representation. + * @param input An valid HSV object. + * @returns a color string supported by CSS and other styling tools. + */ + hsv(input: Hsv, options?: FormatOptions): string { + const { h, s, v, a } = Round.hsv(input); + const { suffix, spacer, percent, alpha } = processFormatOptions(options); + return `hsv${suffix(a)}(${h}${spacer}${s}${percent}${spacer}${v}${percent}${alpha(a)})`; + }, + + /** + * Converts an CMYK Object into its string representation. + * @param input An valid CMYK object. + * @returns a color string supported by CSS and other styling tools. + */ + cmyk(input: Cmyk, options?: FormatOptions): string { + const { c, m, k, y, a } = Round.cmyk(input); + const { suffix, spacer, percent, alpha } = processFormatOptions(options); + return `cmyk${suffix(a)}(${c}${percent}${spacer}${m}${percent}${spacer}${y}${percent}${spacer}${k}${percent}${alpha(a)})`; + }, +}; diff --git a/src/core/colorNormalizer.ts b/src/core/colorNormalizer.ts new file mode 100644 index 0000000..650bcb7 --- /dev/null +++ b/src/core/colorNormalizer.ts @@ -0,0 +1,64 @@ +import { precision, utmost } from "../helpers"; +import type { ColorNormalizers } from "../types"; + +type Helper = ( + value: string | number, + fn?: (value: number) => number, +) => number; + +export const degree: Helper = (value, fn = Math.round): number => + fn(utmost(value, 360)) || 0; + +export const percent: Helper = (value, fn = Math.round): number => + fn(utmost(value, 100)) || 0; + +export const eightBit: Helper = (value, fn = Math.round): number => + fn(utmost(value, 255)) || 0; + +export const alpha: Helper = (value, fn = precision): number => + fn(utmost(value, 1)) || 0; + +export const Round: ColorNormalizers = { + fn: Math.round, + + rgb({ r, g, b, a = 1 }) { + return { + r: eightBit(r, this.fn), + g: eightBit(g, this.fn), + b: eightBit(b, this.fn), + a: alpha(a), + }; + }, + + hsl({ h, s, l, a = 1 }) { + return { + h: degree(h, this.fn), + s: percent(s, this.fn), + l: percent(l, this.fn), + a: alpha(a), + }; + }, + + hsv({ h, s, v, a = 1 }) { + return { + h: degree(h, this.fn), + s: percent(s, this.fn), + v: percent(v, this.fn), + a: alpha(a), + }; + }, + + cmyk({ c, m, y, k, a = 1 }) { + return { + c: percent(c, this.fn), + m: percent(m, this.fn), + y: percent(y, this.fn), + k: percent(k, this.fn), + a: alpha(a), + }; + }, +}; + +export const Clamp: ColorNormalizers = Object.assign(Object.create(Round), { + fn: precision, +}); diff --git a/src/core/colorParser.ts b/src/core/colorParser.ts new file mode 100644 index 0000000..f81b6cc --- /dev/null +++ b/src/core/colorParser.ts @@ -0,0 +1,54 @@ +import { hexToRgb } from "../conversions/hexConversions"; +import { padString } from "../helpers"; +import { execColorStringTest } from "./colorTypeAnalyzer"; + +import type { AnyColorData, ColorParsers } from "../types"; + +export const colorParsers: ColorParsers = { + hex: match => hexToRgb(padString(match[1])), + rgb: match => ({ + r: Number(match[1]), + g: Number(match[2]), + b: Number(match[3]), + a: Number(match[4]) || 1, + }), + hsl: match => ({ + h: Number(match[1]), + s: Number(match[2]), + l: Number(match[3]), + a: Number(match[4]) || 1, + }), + hsv: match => ({ + h: Number(match[1]), + s: Number(match[2]), + v: Number(match[3]), + a: Number(match[4]) || 1, + }), + cmyk: match => ({ + c: Number(match[1]), + m: Number(match[2]), + y: Number(match[3]), + k: Number(match[4]), + a: Number(match[5]) || 1, + }), + named: (match: string[]) => hexToRgb(match[0]), +}; + +/** + * Parses a color string and converts it to a color object. + * ``` + * parseColor('hsl(360,0,100)') // Returns: { colorType: "hsl", colorObject: { h: 360, s: 0, l: 100, a: 1 } } + * ``` + * @param input - The input color string. + */ +export function parseColor(input?: string): AnyColorData | null { + const result = execColorStringTest(input); + return result != null + ? { + originalInput: input, + isValid: true, + value: colorParsers[result[0]](result[1]), + format: result[0], + } + : null; +} diff --git a/src/core/colorTypeAnalyzer.ts b/src/core/colorTypeAnalyzer.ts new file mode 100644 index 0000000..a3925fb --- /dev/null +++ b/src/core/colorTypeAnalyzer.ts @@ -0,0 +1,106 @@ +import namedColors from "../constants/namedColors"; +import { isString, nan } from "../helpers"; +import type { + AnyColorData, + AnyObject, + ColorPatterns, + SupportedColorFormat, +} from "../types"; + +export const isColorData = ( + input: Record, +): input is AnyColorData => + "format" in input || + "value" in input || + "isValid" in input || + "originalInput" in input; + +export const colorPatterns: ColorPatterns = [ + ["hex", /^#([a-f\d]{8}|[a-f\d]{6}|[a-f\d]{3,4})$/iy], + [ + "rgb", + /^rgba?\(\s*(\d{1,3})(?:\s*,\s*|\s+)(\d{1,3})(?:\s*,\s*|\s+)(\d{1,3})(?:\s*(?:,|\/)\s*(0?\.\d+|1|0))?\s*\)$/iy, + ], + [ + "hsl", + /^hsla?\(\s*(\d{1,3})(?:deg|ยฐ)?(?:\s*,\s*|\s+)(\d{1,3})%?(?:\s*,\s*|\s+)(\d{1,3})%?(?:\s*(?:,|\/)\s*(0?\.\d+|1|0))?\s*\)$/iy, + ], + [ + "hsv", + /^hsva?\(\s*(\d{1,3})(?:deg|ยฐ)?(?:\s*,\s*|\s+)(\d{1,3})%?(?:\s*,\s*|\s+)(\d{1,3})%?(?:\s*(?:,|\/)\s*(0?\.\d+|1|0))?\s*\)$/iy, + ], + [ + "cmyk", + /^cmyka?\(\s*(\d{1,3})%?(?:\s*,\s*|\s+)(\d{1,3})%?(?:\s*,\s*|\s+)(\d{1,3})%?(?:\s*,\s*|\s+)(\d{1,3})%?(?:\s*(?:,|\/)\s*(0?\.\d+|1|0))?\s*\)$/iy, + ], + ["named", namedColors.pattern], +]; + +/** + * Performs a test on a color string. + * ``` + * execColorStringTest('hsl(360,0,100)') // Returns: "hsl" + * ``` + * @param input - The input color string. + */ +export function execColorStringTest( + input = "", +): [SupportedColorFormat, string[]] | null { + if (!isString(input) || !input) return null; + + for (const [name, pattern] of colorPatterns) { + pattern.lastIndex = 0; + const match = pattern.exec(input); + if (match !== null) return [name, match]; + } + + return null; +} + +/** + * Determine the color type based on the provided color object. + * @param colorObject - The color object to be analyzed. + * @return The determined color type ('rgb', 'hsl', 'hsv', 'cmyk'). + */ +export const determineColorType = (colorObject?: Record) => { + if (!colorObject) return undefined; + + if (isRgbObject(colorObject)) return "rgb"; + if (isHslObject(colorObject)) return "hsl"; + if (isHsvObject(colorObject)) return "hsv"; + if (isCmykObject(colorObject)) return "cmyk"; + + return undefined; +}; + +/** + * Checks if the provided object represents an Rgb color. + * @param input - The object to be checked. + * @return True if the object represents an Rgb color, false otherwise. + */ +export const isRgbObject = ({ r, g, b, a = 1 }: AnyObject): boolean => + !(nan(r) || nan(g) || nan(b) || nan(a)); + +/** + * Checks if the provided object represents an Hsl color. + * @param input - The object to be checked. + * @return True if the object represents an Hsl color, false otherwise. + */ +export const isHslObject = ({ h, s, l, a = 1 }: AnyObject): boolean => + !(nan(h) || nan(s) || nan(l) || nan(a)); + +/** + * Checks if the provided object represents an Hsv color. + * @param input - The object to be checked. + * @return True if the object represents an Hsv color, false otherwise. + */ +export const isHsvObject = ({ h, s, v, a = 1 }: AnyObject): boolean => + !(nan(h) || nan(s) || nan(v) || nan(a)); + +/** + * Checks if the provided object represents a Cmyk color. + * @param input - The object to be checked. + * @return True if the object represents a Cmyk color, false otherwise. + */ +export const isCmykObject = ({ c, m, y, k, a = 1 }: AnyObject): boolean => + !(nan(c) || nan(m) || nan(y) || nan(k) || nan(a)); diff --git a/src/core/conversionHelpers.ts b/src/core/conversionHelpers.ts new file mode 100644 index 0000000..bdedcf7 --- /dev/null +++ b/src/core/conversionHelpers.ts @@ -0,0 +1,66 @@ +import type { AnyRgb } from "../types"; + +/** + * Check if an HEX color is shortanable by comparing the Rgb components. + * @param r the red channel component of Rgb color + * @param g the green channel component of Rgb color + * @param b the blue channel component of Rgb color + * @param a the alpha channel component of RGBA color + */ +export const isRgbShortanable = ( + r: number, + g: number, + b: number, + a = 255, +): boolean => !(r % 17 !== 0 || g % 17 !== 0 || b % 17 !== 0 || a % 17 !== 0); + +/** + * Calculates the Euclidean distance between two Rgb colors. + * @param primary - The first Rgb color string. + * @param secondary - The second Rgb color string. + */ +export const computeColorDistance = ( + { r: r1, g: g1, b: b1 }: AnyRgb, + { r: r2, g: g2, b: b2 }: AnyRgb, +): number => Math.sqrt((r1 - r2) ** 2 + (g1 - g2) ** 2 + (b1 - b2) ** 2); + +interface ComputeHsvHueParams { + segment: number; + maxRgb: number; + minRgb: number; +} + +/** + * Calculates the hue component of an Hsv color object. + * @param rgb - An Rgb color object. + * @param params - Parameters including segment, maxRgb, and minRgb. + */ +export function computeHsvHue( + { r, g, b }: AnyRgb, + { segment, maxRgb, minRgb }: ComputeHsvHueParams, +): number { + let h = 0; + + if (segment === h) return h; + + const delta = maxRgb - minRgb; + const rDelta = (r - minRgb) / delta; + const gDelta = (g - minRgb) / delta; + const bDelta = (b - minRgb) / delta; + + // Calculate hue based on which color component is the max + if (r === maxRgb) { + h = (60 * (gDelta - bDelta)) % 360; + } else if (g === maxRgb) { + h = 60 * (bDelta - rDelta) + 120; + } else { + h = 60 * (rDelta - gDelta) + 240; + } + + // Ensure hue is within [0, 360) + if (h < 0) { + h += 360; + } + + return h; +} diff --git a/src/core/inputSerializer.ts b/src/core/inputSerializer.ts new file mode 100644 index 0000000..00892c8 --- /dev/null +++ b/src/core/inputSerializer.ts @@ -0,0 +1,89 @@ +import { errorMessages } from "../constants/errorMessages"; +import { cmykToRgb } from "../conversions/cmykConversions"; +import { hslToRgb } from "../conversions/hslConversions"; +import { hsvToRgb } from "../conversions/hsvConversions"; +import { isObject, isString, isUndefined } from "../helpers"; +import type { + AnyColorData, + ColorConverters, + ColorData, + ColorObject, +} from "../types"; +import { Clamp } from "./colorNormalizer"; +import { parseColor } from "./colorParser"; +import { determineColorType, isColorData } from "./colorTypeAnalyzer"; + +export const fallbackColor: ColorData = { + originalInput: undefined, + isValid: false, + value: { r: 0, g: 0, b: 0, a: 1 }, + format: undefined, +}; + +const converters: ColorConverters = { + rgb: input => Clamp.rgb(input), + hsl: input => hslToRgb(Clamp.hsl(input)), + hsv: input => hsvToRgb(Clamp.hsv(input)), + cmyk: input => cmykToRgb(Clamp.cmyk(input)), +}; + +/** + * Converts a color object to a standardized format (Rgb). + * + * @param input - The input color object or `AnyColorData`. + * @returns The standardized `ColorData` with the color represented in Rgb format. + */ +export function fromObject( + input: AnyColorData | ColorObject | unknown | null, +): ColorData { + if (!isObject(input)) { + throw new TypeError(errorMessages.invalidColorType); + } + + const hasData = isColorData(input); + + const value = hasData ? input.value : input; + if (!value) { + throw new TypeError(errorMessages.invalidColorType); + } + + const originalInput = ( + hasData ? input.originalInput || value : value + ) as ColorObject; + + const colorTypeFromObject = determineColorType(value); + if (!colorTypeFromObject || !Object.hasOwn(converters, colorTypeFromObject)) { + throw new TypeError(errorMessages.invalidColorObject(value)); + } + + const format = hasData ? input.format : colorTypeFromObject; + + return { + originalInput: originalInput, + isValid: value !== undefined && format !== undefined, + value: converters[colorTypeFromObject](value as ColorObject), + format, + }; +} + +/** + * Processes a color input (string or object) and returns its standardized ColorData representation. + * + * @param input - The color input (string, color object, or undefined). + * @returns The standardized ColorData representation of the input color. + * @throws {TypeError} If the input is not a valid color string or object. + */ +export function processColorInput( + input?: unknown | string | ColorObject | ColorData, +): ColorData { + if (isString(input)) { + const parsedColorData = parseColor(input); + if (parsedColorData !== null) return fromObject(parsedColorData); + + throw new TypeError(errorMessages.invalidColorString(input)); + } + + if (isUndefined(input)) return fallbackColor; + + return fromObject(input); +} diff --git a/src/core/pluginValidation.ts b/src/core/pluginValidation.ts new file mode 100644 index 0000000..f33cf04 --- /dev/null +++ b/src/core/pluginValidation.ts @@ -0,0 +1,21 @@ +import { errorMessages } from "../constants/errorMessages"; +import type { DyePlugins } from "../types"; + +/** + * Check if the plugin is Not a Plugin + * @param plugins An key-value object with plugin functions to apply. + * @param name Method name of the Plugin + * @return True if the plugins is not valid, undefined in case it's valid. + */ +export const isValidPlugin = ( + plugins: DyePlugins, + name: string, +): name is keyof typeof plugins => { + if (!Object.hasOwn(plugins, name)) return false; + + if (typeof plugins[name] !== "function") { + throw new TypeError(errorMessages.invalidPlugin(name)); + } + + return true; +}; diff --git a/src/cssNamedColors.js b/src/cssNamedColors.js deleted file mode 100644 index b5ffaa5..0000000 --- a/src/cssNamedColors.js +++ /dev/null @@ -1,161 +0,0 @@ -const CSSNamedColors = { - colors: { - aliceblue: 'f0f8ff', - antiquewhite: 'faebd7', - aqua: '00ffff', - aquamarine: '7fffd4', - azure: 'f0ffff', - beige: 'f5f5dc', - bisque: 'ffe4c4', - black: '000000', - blanchedalmond: 'ffebcd', - blue: '0000ff', - blueviolet: '8a2be2', - brown: 'a52a2a', - burlywood: 'deb887', - cadetblue: '5f9ea0', - chartreuse: '7fff00', - chocolate: 'd2691e', - coral: 'ff7f50', - cornflowerblue: '6495ed', - cornsilk: 'fff8dc', - crimson: 'dc143c', - cyan: '00ffff', - darkblue: '00008b', - darkcyan: '008b8b', - darkgoldenrod: 'b8860b', - darkgray: 'a9a9a9', - darkgreen: '006400', - darkgrey: 'a9a9a9', - darkkhaki: 'bdb76b', - darkmagenta: '8b008b', - darkolivegreen: '556b2f', - darkorange: 'ff8c00', - darkorchid: '9932cc', - darkred: '8b0000', - darksalmon: 'e9967a', - darkseagreen: '8fbc8f', - darkslateblue: '483d8b', - darkslategray: '2f4f4f', - darkslategrey: '2f4f4f', - darkturquoise: '00ced1', - darkviolet: '9400d3', - deeppink: 'ff1493', - deepskyblue: '00bfff', - dimgray: '696969', - dimgrey: '696969', - dodgerblue: '1e90ff', - firebrick: 'b22222', - floralwhite: 'fffaf0', - forestgreen: '228b22', - fuchsia: 'ff00ff', - gainsboro: 'dcdcdc', - ghostwhite: 'f8f8ff', - gold: 'ffd700', - goldenrod: 'daa520', - gray: '808080', - green: '008000', - greenyellow: 'adff2f', - grey: '808080', - honeydew: 'f0fff0', - hotpink: 'ff69b4', - indianred: 'cd5c5c', - indigo: '4b0082', - ivory: 'fffff0', - khaki: 'f0e68c', - lavender: 'e6e6fa', - lavenderblush: 'fff0f5', - lawngreen: '7cfc00', - lemonchiffon: 'fffacd', - lightblue: 'add8e6', - lightcoral: 'f08080', - lightcyan: 'e0ffff', - lightgoldenrodyellow: 'fafad2', - lightgray: 'd3d3d3', - lightgreen: '90ee90', - lightgrey: 'd3d3d3', - lightpink: 'ffb6c1', - lightsalmon: 'ffa07a', - lightseagreen: '20b2aa', - lightskyblue: '87cefa', - lightslategray: '778899', - lightslategrey: '778899', - lightsteelblue: 'b0c4de', - lightyellow: 'ffffe0', - lime: '00ff00', - limegreen: '32cd32', - linen: 'faf0e6', - magenta: 'ff00ff', - maroon: '800000', - mediumaquamarine: '66cdaa', - mediumblue: '0000cd', - mediumorchid: 'ba55d3', - mediumpurple: '9370db', - mediumseagreen: '3cb371', - mediumslateblue: '7b68ee', - mediumspringgreen: '00fa9a', - mediumturquoise: '48d1cc', - mediumvioletred: 'c71585', - midnightblue: '191970', - mintcream: 'f5fffa', - mistyrose: 'ffe4e1', - moccasin: 'ffe4b5', - navajowhite: 'ffdead', - navy: '000080', - oldlace: 'fdf5e6', - olive: '808000', - olivedrab: '6b8e23', - orange: 'ffa500', - orangered: 'ff4500', - orchid: 'da70d6', - palegoldenrod: 'eee8aa', - palegreen: '98fb98', - paleturquoise: 'afeeee', - palevioletred: 'db7093', - papayawhip: 'ffefd5', - peachpuff: 'ffdab9', - peru: 'cd853f', - pink: 'ffc0cb', - plum: 'dda0dd', - powderblue: 'b0e0e6', - purple: '800080', - rebeccapurple: '663399', - red: 'ff0000', - rosybrown: 'bc8f8f', - royalblue: '4169e1', - saddlebrown: '8b4513', - salmon: 'fa8072', - sandybrown: 'f4a460', - seagreen: '2e8b57', - seashell: 'fff5ee', - sienna: 'a0522d', - silver: 'c0c0c0', - skyblue: '87ceeb', - slateblue: '6a5acd', - slategray: '708090', - slategrey: '708090', - snow: 'fffafa', - springgreen: '00ff7f', - steelblue: '4682b4', - tan: 'd2b48c', - teal: '008080', - thistle: 'd8bfd8', - tomato: 'ff6347', - turquoise: '40e0d0', - violet: 'ee82ee', - wheat: 'f5deb3', - white: 'ffffff', - whitesmoke: 'f5f5f5', - yellow: 'ffff00', - yellowgreen: '9acd32' - }, - pattern: {} -} - -CSSNamedColors.pattern.lastIndex = 0 -CSSNamedColors.pattern.exec = input => { - const match = CSSNamedColors.colors[input] - return match != undefined ? [match] : null -} - -export default CSSNamedColors diff --git a/src/dye.ts b/src/dye.ts new file mode 100644 index 0000000..56f1837 --- /dev/null +++ b/src/dye.ts @@ -0,0 +1,133 @@ +/** + * @file Defines the core `dye` function for creating and manipulating color objects in the colorus-js library. + * + * The `dye` function serves as the main entry point for working with colors. It accepts various color inputs (strings or objects) and optional configuration options, including plugins for extending functionality. + * + * It returns a `DyeReturns` object that provides access to color properties, conversion methods, adjustment methods, and any custom plugin methods. + */ + +// Core library modules +import { contrastRatio, relativeLuminance } from "./core/accessibility"; +import { alpha, hue, lighten, saturate } from "./core/colorAdjustments"; +import colorFormatter from "./core/colorFormatter"; +import { fallbackColor, processColorInput } from "./core/inputSerializer"; +import { isValidPlugin } from "./core/pluginValidation"; + +// Conversion utilities +import { + rgbToCmyk, + rgbToHex, + rgbToHsl, + rgbToHsv, + rgbToNamedColor, +} from "./conversions/rgbConversions"; + +// Helper functions +import { isObject, isUndefined } from "./helpers"; + +// Constants +import { errorMessages } from "./constants/errorMessages"; + +// Types +import type { + ColorInput, + Dye, + DyeOptions, + DyePlugins, + DyeReturns, +} from "./types"; + +function isValidDyeOptions

( + options?: DyeOptions

, +): options is DyeOptions

{ + if (isUndefined(options)) return false; + + if ( + !isObject(options) || + (!isUndefined(options.plugins) && !isObject(options.plugins)) || + (!isUndefined(options.formatOptions) && !isObject(options.formatOptions)) + ) { + return false; + } + + return true; +} + +/** + * Creates a color object for manipulation and conversion. + * + * @param {ColorInput} input - The color input (string or object). + * @param {DyeOptions

} [options] - Optional configuration (plugins, format options). + * + * @returns {DyeReturns

} The color object with core and plugin methods. + */ +export function dye

( + input: ColorInput, + options: DyeOptions

= {}, +): DyeReturns

{ + try { + const processedInput = processColorInput(input); + + if (!isValidDyeOptions(options)) { + throw new TypeError(errorMessages.invalidOptions); + } + + const result: Dye

= { + ...processedInput, + + get luminance() { + return relativeLuminance(result.rgb); + }, + + get rgb() { + return result.value || fallbackColor.value; + }, + + get hsl() { + return rgbToHsl(result.rgb); + }, + + get hsv() { + return rgbToHsv(result.rgb); + }, + + get cmyk() { + return rgbToCmyk(result.rgb); + }, + + toHex: () => rgbToHex(result.rgb, options.formatOptions), + toRgb: () => colorFormatter.rgb(result.rgb, options.formatOptions), + toHsl: () => colorFormatter.hsl(result.hsl, options.formatOptions), + toHsv: () => colorFormatter.hsv(result.hsv, options.formatOptions), + toCmyk: () => colorFormatter.cmyk(result.cmyk, options.formatOptions), + toNamed: () => rgbToNamedColor(result.rgb), + + lighten: (amount = 0.1) => dye(lighten(result.hsl, amount), options), + darken: (amount = 0.1) => dye(lighten(result.hsl, -amount), options), + saturate: (amount = 0.1) => dye(saturate(result.hsl, amount), options), + desaturate: (amount = 0.1) => dye(saturate(result.hsl, -amount), options), + hue: (amount = 0.1) => dye(hue(result.hsl, amount), options), + alpha: (amount = 0.1) => dye(alpha(result.rgb, amount), options), + contrastRatio: bgColor => contrastRatio(result.rgb, dye(bgColor).rgb), + }; + + for (const methodName in options.plugins) { + if (isValidPlugin(options.plugins, methodName)) { + (result as any)[methodName] = (...args: unknown[]) => + options.plugins?.[methodName]?.call(result, ...args); + } + } + + return result as DyeReturns

; + } catch (err) { + if (err instanceof TypeError) { + throw new TypeError(`Invalid dye() usage: ${err.message}`); + } + + if (err instanceof Error) { + throw new Error(err.message); + } + + throw new Error("An unknown error occurred during color processing."); + } +} diff --git a/src/helpers.js b/src/helpers.js deleted file mode 100644 index e1fa628..0000000 --- a/src/helpers.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Clamps a value between a minimum and maximum limit. - * - * - If the input value is greater than the maximum, the maximum will be returned. - * - If the input value is less than the minimum, the minimum will be returned. - * - * The clamped value is guaranteed to be greater than or equal to zero. - * - * @param {number} v - The input value to clamp - * @param {number} max - The maximum value for the input - * @return {number} The clamped value between 0 and max - */ -export const utmost = (v, max) => Math.max(Math.min(Number(v), max), 0) - -/** - * Returns the input value with a precision level of two decimal places. - * - * @param {number} value - The input value to format - * @return {number} The input value formatted with the specified precision - */ -export const precision = value => (Math.trunc(value) !== value ? Math.round(value * 100) / 100 : value) - -/** - * Converts the input to a string with radix 16 (HEX). - * - * @param {number} input - The RGB channel values. - * @param {number} [minSize=6] - Minimum size of the HEX string. If not provided, defaults to 6. - * @return {string} An HEX string. (e.g., "FF" or "00FF00" depending on the minSize value.) - */ -export const hexString = (input, minSize) => input.toString(16).padStart(minSize, '0').toUpperCase() - -/** - * Converts a minified HEX color into a HEX 6 or 8. - * - * **Warning**: Only use this with minified HEX strings. - * - * @param {string} minHex - A minified HEX string. (e.g., "FFF" or "E3EF".) - * @return {string} A HEX string with a length of 6 or 8. - */ -export const padString = minHex => { - if (minHex.length > 4) return minHex - - let value = '' - - for (const slice of minHex) { - value += slice + slice - } - - return value -} - -/** - * Check if input is NOT a Number (NaN) - * @param {*} v - The value to check against. - * @return {Boolean} `true` if it is not an number, `false` otherwise. - */ -export const nan = v => typeof v != 'number' || isNaN(v) || !isFinite(v) - -/** - * Check if input is NOT a Object (NaO) - * @param {*} v - The object to check against. - * @return {Boolean} `true` if it is not an object, `false` otherwise. - */ -export const nao = v => typeof v !== 'object' || Array.isArray(v) - -/** - * Check if the plugin is Not a Plugin - * @param {Object} plugins An key-value object with plugin functions to apply. - * @param {string} name Method name of the Plugin - * @return {boolean|undefined} True if the plugins is not valid, undefined in case it's valid. - */ -export const isNotPlugin = function (plugins, name) { - if (!Object.hasOwnProperty.call(plugins, name)) return true - - if (typeof plugins[name] !== 'function') { - throw new TypeError(`Invalid plugin for '${name}': Expected a function.`) - } -} - -/** - * Checks if the provided object represents an RGB color. - * @param {object} obj - The object to be checked. - * @return {boolean} True if the object represents an RGB color, false otherwise. - */ -export const isRgbObject = ({ r, g, b, a = 1 }) => !(nan(r) || nan(g) || nan(b) || nan(a)) - -/** - * Checks if the provided object represents an HSL color. - * @param {object} obj - The object to be checked. - * @return {boolean} True if the object represents an HSL color, false otherwise. - */ -export const isHslObject = ({ h, s, l, a = 1 }) => !(nan(h) || nan(s) || nan(l) || nan(a)) - -/** - * Checks if the provided object represents an HSV color. - * @param {object} obj - The object to be checked. - * @return {boolean} True if the object represents an HSV color, false otherwise. - */ -export const isHsvObject = ({ h, s, v, a = 1 }) => !(nan(h) || nan(s) || nan(v) || nan(a)) - -/** - * Checks if the provided object represents a CMYK color. - * @param {object} obj - The object to be checked. - * @return {boolean} True if the object represents a CMYK color, false otherwise. - */ -export const isCmykObject = ({ c, m, y, k, a = 1 }) => !(nan(c) || nan(m) || nan(y) || nan(k) || nan(a)) diff --git a/src/helpers.ts b/src/helpers.ts new file mode 100644 index 0000000..f5e0344 --- /dev/null +++ b/src/helpers.ts @@ -0,0 +1,76 @@ +import type { AnyObject } from "./types"; + +/** + * Clamps a value between a minimum and maximum limit. + * + * - If the input value is greater than the maximum, the maximum will be returned. + * - If the input value is less than the minimum, the minimum will be returned. + * + * The clamped value is guaranteed to be greater than or equal to zero. + * + * @param v - The input value to clamp + * @param max - The maximum value for the input + * @return The clamped value between 0 and max + */ +export const utmost = (v: number | string, max: number): number => + Math.max(Math.min(Number(v), max), 0); + +/** + * Returns the input value with a precision level of two decimal places. + * + * @param value - The input value to format + * @return The input value formatted with the specified precision + */ +export const precision = (value: number): number => + Math.trunc(value) !== value ? Math.round(value * 100) / 100 : value; + +/** + * Converts the input to a string with radix 16 (HEX). + * + * @param input - The Rgb channel values. + * @param minSize - Minimum size of the HEX string. If not provided, defaults to 6. + * @return An HEX string. (e.g., "FF" or "00FF00" depending on the minSize value.) + */ +export const hexString = (input: number, minSize: number): string => + input.toString(16).padStart(minSize, "0").toUpperCase(); + +/** + * Converts a minified HEX color into a HEX 6 or 8. + * + * **Warning**: Only use this with minified HEX strings. + * + * @param minHex - A minified HEX string. (e.g., "FFF" or "E3EF".) + * @return A HEX string with a length of 6 or 8. + */ +export const padString = (minHex: string): string => { + if (minHex.length > 4) return minHex; + + let value = ""; + + for (const slice of minHex) { + value += slice + slice; + } + + return value; +}; + +/** + * Check if input is NOT a Number (NaN) + * @param v - The value to check against. + * @return `true` if it is not an number, `false` otherwise. + */ +export const nan = (v: unknown): boolean => + typeof v !== "number" || Number.isNaN(v) || !Number.isFinite(v); + +/** + * Check if input is a valid object + * @param v - The object to check against. + * @return `true` if it is not an object, `false` otherwise. + */ +export const isObject = (v: unknown): v is AnyObject => + !(typeof v !== "object" || Array.isArray(v) || v === null); + +export const isUndefined = (v: unknown): v is undefined => + typeof v === "undefined"; + +export const isString = (v: unknown): v is string => typeof v === "string"; diff --git a/src/isValidColor.ts b/src/isValidColor.ts new file mode 100644 index 0000000..9e37952 --- /dev/null +++ b/src/isValidColor.ts @@ -0,0 +1,27 @@ +import { + determineColorType, + execColorStringTest, +} from "./core/colorTypeAnalyzer"; +import { isObject, isString } from "./helpers"; +import type { AnyObject, SupportedColorFormat } from "./types"; + +/** Tests the `input` for a valid color. + * @param input - The color input string or object. + * @return The type of the string (e.g.: `rgb`) if color is valid, otherwise `null`. + */ +export function isValidColor( + input: object | string | unknown, +): SupportedColorFormat | null { + if (!input) return null; + + if (isObject(input)) { + return determineColorType(input as AnyObject) || null; + } + + if (isString(input)) { + const match = execColorStringTest(input); + if (match) return match[0]; + } + + return null; +} diff --git a/src/main.js b/src/main.js deleted file mode 100644 index 3d5c0b6..0000000 --- a/src/main.js +++ /dev/null @@ -1,247 +0,0 @@ -import { contrastRatio, relativeLuminance } from './accessibility' -import ColorFormatter from './colorFormatter' -import * as compose from './compose' -import * as conversion from './conversion' -import { nao, isNotPlugin } from './helpers' -import * as serialize from './serialize' - -/** - * Validates the options object passed to the Colorus constructor. - * - * @param {Object} [options={}] - An optional configuration object. - * @param {Object} [options.plugins] - An optional object containing plugin functions to extend the Colorus instance. - * - Keys should be the names of the plugin methods. - * - Values should be functions that take the Colorus instance as `this` and any additional arguments. - * - * @throws {TypeError} If `options` is not a plain object or if `options.plugins` is present but not a plain object. - */ -function validateOptions(options = {}) { - if (nao(options)) { - throw new TypeError( - `Invalid options: Expected a plain object with method names as keys. Received ${Array.isArray(options) ? 'an array' : typeof options}` - ) - } - - const { plugins } = options - - if (typeof plugins !== 'undefined' && nao(plugins)) { - throw new TypeError( - `Invalid plugins: Expected a plain object with method names as keys. Received ${Array.isArray(plugins) ? 'an array' : typeof plugins}` - ) - } -} - -/** - * Utility class providing methods for working with colors. - */ -export class Colorus { - #data = {} - - /** - * Constructs a new Colorus instance with the given input and optional plugins. - * @param {string|Object} input - The color input string or object. - * @param {Object} [options] - Optional configuration options. - * @param {Object} [options.plugins] - An key-value object with plugin functions to apply. - */ - constructor(input, options = {}) { - this.#data = serialize.fromUserInput(input) - - validateOptions(options) - - for (const methodName in options.plugins) { - if (isNotPlugin(options.plugins, methodName)) continue - - this[methodName] = function (...args) { - return options.plugins[methodName].call(this, ...args) - } - } - } - - /** Tests the `input` for a valid color. - * @param {unknown} input - The color input string or object. - * @return {string|null} The type of the string (e.g.: `rgb`) if color is valid, otherwise `null`. - */ - static test(input) { - return serialize.fromUserInput(input, { analytical: true }).colorType || null - } - - /** - * Gets the type of the current color. - * @return {string} The color type. - */ - get colorType() { - return this.#data.colorType - } - - /** - * Gets the relative luminance of the current color. - * @link [WCAG 2.0 Adherence](https://www.w3.org/TR/WCAG20-TECHS/G17.html) - * @return {number} The relative luminance. - */ - get luminance() { - return relativeLuminance(this.rgb) - } - - /** - * Gets the RGB object representation of the current color. - * @return {object} The RGB representation. - */ - get rgb() { - return this.#data.colorObject - } - - /** - * Gets the HSL object representation of the current color. - * @return {object} The HSL representation. - */ - get hsl() { - return conversion.rgbToHsl(this.rgb) - } - - /** - * Gets the HSV representation of the current color. - * @return {object} The HSV representation. - */ - get hsv() { - return conversion.rgbToHsv(this.rgb) - } - - /** - * Gets the CMYK representation of the current color. - * @return {object} The CMYK representation. - */ - get cmyk() { - return conversion.rgbToCmyk(this.rgb) - } - - /** - * Converts the current color to hexadecimal format. - * @param {object} [options] - Formatting options. - * @return {string} The hexadecimal representation of the color. - */ - toHex = options => conversion.rgbToHex(this.rgb, options) - - /** - * Converts the current color to RGB format. - * @param {object} [options] - Formatting options. - * @return {string} The RGB representation of the color. - */ - toRgb = options => new ColorFormatter(options).rgb(this.rgb) - - /** - * Converts the current color to HSL format. - * @param {object} [options] - Formatting options. - * @return {string} The HSL representation of the color. - */ - toHsl = options => new ColorFormatter(options).hsl(this.hsl) - - /** - * Converts the current color to HSV format. - * @param {object} [options] - Formatting options. - * @return {string} The HSV representation of the color. - */ - toHsv = options => new ColorFormatter(options).hsv(this.hsv) - - /** - * Converts the current color to CMYK format. - * @param {object} [options] - Formatting options. - * @return {string} The CMYK representation of the color. - */ - toCmyk = options => new ColorFormatter(options).cmyk(this.cmyk) - - /** - * Converts the current color to its nearest CSS named color representation. - * @return {string} The CSS named color. - */ - toNamed = () => conversion.rgbToNamedColor(this.rgb) - - /** - * Mixes the current color with another color. - * @param {string|Object} input - The color to mix with. - * @param {number} [amount=0.1] - The amount of mixing. - * @return {Colorus} A new Colorus instance representing the mixed color. - */ - mix(input, amount = 0.1) { - return new Colorus(compose.mix(this.rgb, new Colorus(input).rgb, amount)) - } - - /** - * Lightens the current color. - * @param {number} [amount=0.1] - The amount of lightening. - * @return {Colorus} A new Colorus instance representing the lightened color. - */ - lighten(amount = 0.1) { - return new Colorus(compose.lighten(this.hsl, amount)) - } - - /** - * Darkens the current color. - * @param {number} [amount=0.1] - The amount of darkening. - * @return {Colorus} A new Colorus instance representing the darkened color. - */ - darken(amount = 0.1) { - return new Colorus(compose.lighten(this.hsl, -amount)) - } - - /** - * Saturates the current color. - * @param {number} [amount=0.1] - The amount of saturation. - * @return {Colorus} A new Colorus instance representing the saturated color. - */ - saturate(amount = 0.1) { - return new Colorus(compose.saturate(this.hsl, amount)) - } - - /** - * Desaturates the current color. - * @param {number} [amount=0.1] - The amount of desaturation. - * @return {Colorus} A new Colorus instance representing the desaturated color. - */ - desaturate(amount = 0.1) { - return new Colorus(compose.saturate(this.hsl, -amount)) - } - - /** - * Changes the hue of the current color. - * @param {number} [amount=0.1] - The amount of hue change. - * @return {Colorus} A new Colorus instance representing the color with changed hue. - */ - hue(amount = 0.1) { - return new Colorus(compose.hue(this.hsl, amount)) - } - - /** - * Changes the alpha (opacity) of the current color. - * @param {number} [amount=0.1] - The amount of alpha change. - * @return {Colorus} A new Colorus instance representing the color with changed alpha. - */ - alpha(amount = 0.1) { - return new Colorus(compose.alpha(this.rgb, amount)) - } - - /** - * Calculates the contrast ratio between a foreground color and its adjacent background. - * @param {object} backgroundColor - The background color. - * @return {number} The contrast ratio between the instantiated color and the provided background color. - */ - contrastRatio(backgroundColor) { - return contrastRatio(this.rgb, new Colorus(backgroundColor).rgb) - } - - /** - * Inverts the color using sRGB values. - * @return {Colorus} A new Colorus instance representing the color with inverted color values. - */ - invert() { - return new Colorus(compose.invert(this.rgb)) - } - - /** - * Converts the current color to grayscale. - * @param {boolean} [useNTSCFormula=false] - Whether to use the NTSC formula for conversion. (Default: `false`) - * @return {Colorus} A new Colorus object representing the grayscale color. - */ - grayscale(useNTSCFormula = false) { - return new Colorus(compose.rgbToGray(this.rgb, useNTSCFormula)) - } -} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..2c9a946 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,5 @@ +export { isValidColor } from "./isValidColor"; + +export { dye } from "./dye"; + +export type { Dye, Cmyk, Hsl, Hsv, Rgb } from "./types"; diff --git a/src/serialize.js b/src/serialize.js deleted file mode 100644 index eb43c76..0000000 --- a/src/serialize.js +++ /dev/null @@ -1,118 +0,0 @@ -import { Clamp } from './colorNormalizer' -import { cmykToRgb, hexToRgb, hslToRgb, hsvToRgb } from './conversion' -import CSSNamedColors from './cssNamedColors' -import { isCmykObject, isHslObject, isHsvObject, isRgbObject, nao, padString } from './helpers' - -const colorPatterns = [ - ['hex', /^#([a-f\d]{8}|[a-f\d]{6}|[a-f\d]{3,4})$/iy], - ['rgb', /^rgba?\(\s*(\d{1,3})(?:\s*\,\s*|\s+)(\d{1,3})(?:\s*\,\s*|\s+)(\d{1,3})(?:\s*(?:\,|\/)\s*(0?\.\d+|1|0))?\s*\)$/iy], - ['hsl', /^hsla?\(\s*(\d{1,3})(?:deg|ยฐ)?(?:\s*\,\s*|\s+)(\d{1,3})%?(?:\s*\,\s*|\s+)(\d{1,3})%?(?:\s*(?:\,|\/)\s*(0?\.\d+|1|0))?\s*\)$/iy], - ['hsv', /^hsva?\(\s*(\d{1,3})(?:deg|ยฐ)?(?:\s*\,\s*|\s+)(\d{1,3})%?(?:\s*\,\s*|\s+)(\d{1,3})%?(?:\s*(?:\,|\/)\s*(0?\.\d+|1|0))?\s*\)$/iy], - [ - 'cmyk', - /^cmyka?\(\s*(\d{1,3})%?(?:\s*\,\s*|\s+)(\d{1,3})%?(?:\s*\,\s*|\s+)(\d{1,3})%?(?:\s*\,\s*|\s+)(\d{1,3})%?(?:\s*(?:\,|\/)\s*(0?\.\d+|1|0))?\s*\)$/iy - ], - ['named', CSSNamedColors.pattern] -] - -const colorParsers = { - hex: match => hexToRgb(padString(match[1])), - rgb: match => ({ r: Number(match[1]), g: Number(match[2]), b: Number(match[3]), a: Number(match[4]) || 1 }), - hsl: match => ({ h: Number(match[1]), s: Number(match[2]), l: Number(match[3]), a: Number(match[4]) || 1 }), - hsv: match => ({ h: Number(match[1]), s: Number(match[2]), v: Number(match[3]), a: Number(match[4]) || 1 }), - cmyk: match => ({ c: Number(match[1]), m: Number(match[2]), y: Number(match[3]), k: Number(match[4]), a: Number(match[5]) || 1 }), - named: match => hexToRgb(match[0]) -} - -const colorSerializers = { - rgb: ({ r, g, b, a }) => Clamp.rgb({ r, g, b, a }), - hsl: ({ h, s, l, a }) => hslToRgb(Clamp.hsl({ h, s, l, a })), - hsv: ({ h, s, v, a }) => hsvToRgb(Clamp.hsv({ h, s, v, a })), - cmyk: ({ c, m, y, k, a }) => cmykToRgb(Clamp.cmyk({ c, m, y, k, a })) -} - -export const fallbackColor = { colorType: undefined, colorObject: { r: 0, g: 0, b: 0, a: 1 } } - -/** - * Determine the color type based on the provided color object. - * @param {object} colorObject - The color object to be analyzed. - * @return {string} The determined color type ('rgb', 'hsl', 'hsv', 'cmyk'). - */ -export const determineColorType = colorObject => { - if (!colorObject) return undefined - - if (isRgbObject(colorObject)) return 'rgb' - else if (isHslObject(colorObject)) return 'hsl' - else if (isHsvObject(colorObject)) return 'hsv' - else if (isCmykObject(colorObject)) return 'cmyk' - - return undefined -} - -/** - * Converts a color object to a standardized format. - * ```js - * fromObject({ colorObject: { h: 360, s: 0, l: 100, a: 1 } }) // Returns: { colorType: "hsl", colorObject: { r: 255, g: 255, b: 255, a: 1 } } - * ``` - * @param {{colorType:string,colorObject:object}} input - The input color object. - * @param {boolean} [skipSerialization=false] - If true, only performs type checking without serialization to standardized format. - * @return {{colorType:string,colorObject:object}} An object containing the type of color and its color values. - */ -export function fromObject(input, skipSerialization = false) { - const colorTypeFromObject = determineColorType(input?.colorObject) - const colorType = colorParsers.hasOwnProperty(input?.colorType) ? input?.colorType : colorTypeFromObject - - if (skipSerialization) return { colorType, colorObject: input?.colorObject } - - if (colorSerializers[colorTypeFromObject]) { - return { - colorType, - colorObject: colorSerializers[colorTypeFromObject](input?.colorObject) - } - } - return fallbackColor -} - -/** - * Parses a color string and converts it to a color object. - * ``` - * parse('hsl(360,0,100)') // Returns: { colorType: "hsl", colorObject: { h: 360, s: 0, l: 100, a: 1 } } - * ``` - * @param {string} input - The input color string. - * @param {boolean} [skipParsing=false] - If true, only performs type checking without parsing into a object. - * @return {{colorType:string,colorObject:object}|null} An object containing the type of color and its color values. - */ -export function parse(input, skipParsing = false) { - for (const [name, pattern] of colorPatterns) { - pattern.lastIndex = 0 - const match = pattern.exec(input) - if (match !== null) { - return { - colorType: name, - colorObject: skipParsing !== true ? colorParsers[name](match) : undefined - } - } - } - return null -} - -/** - * Attemps to serializes an color input to a standardized color object. - * @param {unknown} input - The input color string or object. - * @param {object} [options] - An optional object containing configuration options. - * @param {boolean} [options.analytical=false] - If true, only performs color analysis without parsing into a standardized format. - * @return {{colorType:string,colorObject:object}} An object containing the type of color and its color values. - * @throws {TypeError} If the input is not a valid color string or object. - */ -export function fromUserInput(input, { analytical } = { analytical: false }) { - if (typeof input === 'undefined') { - return fallbackColor - } else if (typeof input === 'string') { - return fromObject(parse(input, analytical), analytical) - } else if (!nao(input)) { - return fromObject({ colorObject: input }, analytical) - } else { - if (analytical) return { colorType: undefined } - throw new TypeError('Invalid color type, expected and valid color string or object.') - } -} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..faa20d0 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,195 @@ +import type { namedColorsMap } from "./constants/namedColors"; + +export type AnyObject = Record; + +export interface AnyRgb { + r: number; + g: number; + b: number; + a?: number; +} +export interface Rgb extends AnyRgb { + a: number; +} + +export interface AnyHsl { + h: number; + s: number; + l: number; + a?: number; +} + +export interface Hsl extends AnyHsl { + a: number; +} + +export interface AnyHsv { + h: number; + s: number; + v: number; + a?: number; +} + +export interface Hsv extends AnyHsv { + a: number; +} + +export interface AnyCmyk { + c: number; + m: number; + y: number; + k: number; + a?: number; +} + +export interface Cmyk extends AnyCmyk { + a: number; +} + +export type SupportedColorFormat = + | "rgb" + | "hsl" + | "hsv" + | "cmyk" + | "hex" + | "named"; + +export type ColorObject = AnyRgb | AnyHsl | AnyHsv | AnyCmyk; + +export type ColorInput = string | ColorObject; + +export type ColorData = { + originalInput?: ColorInput; + isValid: boolean; + value: C; + format?: SupportedColorFormat; +}; + +export type AnyColorData = Partial>; + +export type NamedColors = keyof typeof namedColorsMap; + +export type ColorConverters = { + [MethodKey in Exclude]: ( + colorObject: ColorObject, + ) => Rgb; +}; +export type ExecMatchClone = { + pattern: { + lastIndex: number; + exec: (input: string) => string[] | null; + }; +}; + +export type ColorPatterns = [ + SupportedColorFormat, + RegExp | ExecMatchClone["pattern"], +][]; + +export type NamedColorsParsers = { + colors: Record; +} & ExecMatchClone; + +export type ColorParsers = Omit< + { + hex: (input: I) => Rgb; + rgb: (input: I) => Rgb; + hsv: (input: I) => Hsv; + hsl: (input: I) => Hsl; + cmyk: (input: I) => Cmyk; + named: (input: I) => Rgb; + }, + E +>; + +export type ColorNormalizers = { + rgb: (input: AnyObject) => Rgb; + hsv: (input: AnyObject) => Hsv; + hsl: (input: AnyObject) => Hsl; + cmyk: (input: AnyObject) => Cmyk; + fn: (x: number) => number; +}; + +export interface FormatOptions { + /** Whether to attempt to minify the output. */ + minify?: boolean; + + /** Whether to generate CSSNext compatible formatting. */ + cssNext?: boolean; +} + +/** + * Represents a plugin function that extends the Color instance with custom methods. + * + * @param this The Color instance to which the plugin methods will be added. + * @param args Any additional arguments passed to the plugin method. + */ +type Plugin> = ( + this: ThisArg, + ...args: any[] +) => T | void; + +export type DyePlugins = Record>; + +export interface DyeOptions { + /** An object containing the plugin methods to be added to the Colorus instance. */ + plugins?: T; + formatOptions?: FormatOptions; +} + +export type Dye

= { + /** The color value in RGB format, if available. */ + value?: Rgb; + /** The original format of the color input (e.g., 'hex', 'rgb', 'hsl'). */ + format?: SupportedColorFormat; + /** The original input used to create the color. */ + originalInput?: ColorInput; + /** Indicates whether the color input was valid. */ + isValid?: boolean; + /** Calculates and returns the relative luminance of the color. */ + luminance: number; + /** Returns the RGB representation of the color. */ + rgb: Rgb; + /** Converts and returns the color in HSL format. */ + hsl: Hsl; + /** Converts and returns the color in HSV format. */ + hsv: Hsv; + /** Converts and returns the color in CMYK format. */ + cmyk: Cmyk; + /** Converts the color to a hexadecimal string representation. */ + toHex: () => string; + /** Converts the color to an RGB string representation. */ + toRgb: () => string; + /** Converts the color to an HSL string representation. */ + toHsl: () => string; + /** Converts the color to an HSV string representation. */ + toHsv: () => string; + /** Converts the color to a CMYK string representation. */ + toCmyk: () => string; + /** Converts the color to its nearest CSS named color. */ + toNamed: () => string; + /** Creates a new lighter color. */ + lighten: (amount?: number) => DyeReturns

; + /** Creates a new darker color. */ + darken: (amount?: number) => DyeReturns

; + /** Creates a new more saturated color. */ + saturate: (amount?: number) => DyeReturns

; + /** Creates a new less saturated color. */ + desaturate: (amount?: number) => DyeReturns

; + /** Creates a new color with adjusted hue. */ + hue: (amount?: number) => DyeReturns

; + /** Creates a new color with adjusted alpha (opacity). */ + alpha: (amount?: number) => DyeReturns

; + /** Calculates the contrast ratio between this color and a background color. */ + contrastRatio: (bgColor: ColorInput) => number; +}; + +/** Represents the return type of the `dye` function, encompassing both the core properties and any additional plugin methods. */ +export type DyeReturns

= Dye

& { + [K in keyof P]: P[K] extends Plugin + ? ( + this: ThisArg, + ...params: Parameters + ) => R extends DyeReturns

? DyeReturns

: R + : never; +}; diff --git a/test/__fixtures__/cmykColors.ts b/test/__fixtures__/cmykColors.ts new file mode 100644 index 0000000..198c5e4 --- /dev/null +++ b/test/__fixtures__/cmykColors.ts @@ -0,0 +1,51 @@ +import type { TestColors } from "."; + +export const cmykColors: TestColors["cmyk"] = { + black: { + object: { c: 0, m: 0, y: 0, k: 100, a: 1 }, + string: "cmyk(0%, 0%, 0%, 100%)", + }, + white: { + object: { c: 0, m: 0, y: 0, k: 0, a: 1 }, + string: "cmyk(0%, 0%, 0%, 0%)", + }, + red: { + object: { c: 0, m: 100, y: 100, k: 0, a: 1 }, + string: "cmyk(0%, 100%, 100%, 0%)", + }, + lime: { + object: { c: 100, m: 0, y: 100, k: 0, a: 1 }, + string: "cmyk(100%, 0%, 100%, 0%)", + }, + blue: { + object: { c: 100, m: 100, y: 0, k: 0, a: 1 }, + string: "cmyk(100%, 100%, 0%, 0%)", + }, + yellow: { + object: { c: 0, m: 0, y: 100, k: 0, a: 1 }, + string: "cmyk(0%, 0%, 100%, 0%)", + }, + aqua: { + object: { c: 100, m: 0, y: 0, k: 0, a: 1 }, + string: "cmyk(100%, 0%, 0%, 0%)", + }, + fuchsia: { + object: { c: 0, m: 100, y: 0, k: 0, a: 1 }, + string: "cmyk(0%, 100%, 0%, 0%)", + }, + orange: { + object: { c: 0, m: 33, y: 100, k: 0, a: 1 }, + string: "cmyk(0%, 33%, 100%, 0%)", + rgb: { r: 255, g: 170.85, b: 0, a: 1 }, + }, + brown: { + object: { c: 0, m: 75, y: 75, k: 35, a: 1 }, + string: "cmyk(0%, 75%, 75%, 35%)", + rgb: { r: 165.75, g: 41.44, b: 41.44, a: 1 }, + }, + lightgray: { + object: { c: 0, m: 0, y: 0, k: 17, a: 1 }, + string: "cmyk(0%, 0%, 0%, 17%)", + rgb: { r: 211.65, g: 211.65, b: 211.65, a: 1 }, + }, +}; diff --git a/test/__fixtures__/hexColors.ts b/test/__fixtures__/hexColors.ts new file mode 100644 index 0000000..9f63c91 --- /dev/null +++ b/test/__fixtures__/hexColors.ts @@ -0,0 +1,49 @@ +import type { TestColors } from "."; +import { rgbColors } from "./rgbColors"; + +export const hexColors: TestColors["hex"] = { + black: { + object: rgbColors.black.object, + string: "#000000", + }, + white: { + object: rgbColors.white.object, + string: "#ffffff", + }, + red: { + object: rgbColors.red.object, + string: "#ff0000", + }, + lime: { + object: rgbColors.lime.object, + string: "#00ff00", + }, + blue: { + object: rgbColors.blue.object, + string: "#0000ff", + }, + yellow: { + object: rgbColors.yellow.object, + string: "#ffff00", + }, + aqua: { + object: rgbColors.aqua.object, + string: "#00ffff", + }, + fuchsia: { + object: rgbColors.fuchsia.object, + string: "#ff00ff", + }, + orange: { + object: rgbColors.orange.object, + string: "#ffaa00", + }, + brown: { + object: rgbColors.brown.object, + string: "#a52a2a", + }, + lightgray: { + object: rgbColors.lightgray.object, + string: "#d3d3d3", + }, +}; diff --git a/test/__fixtures__/hslColors.ts b/test/__fixtures__/hslColors.ts new file mode 100644 index 0000000..cf9bb84 --- /dev/null +++ b/test/__fixtures__/hslColors.ts @@ -0,0 +1,50 @@ +import type { TestColors } from "."; + +export const hslColors: TestColors["hsl"] = { + white: { + object: { h: 0, s: 0, l: 100, a: 1 }, + string: "hsl(0, 0%, 100%)", + }, + black: { + object: { h: 0, s: 0, l: 0, a: 1 }, + string: "hsl(0, 0%, 0%)", + }, + red: { + object: { h: 0, s: 100, l: 50, a: 1 }, + string: "hsl(0, 100%, 50%)", + }, + lime: { + object: { h: 120, s: 100, l: 50, a: 1 }, + string: "hsl(120, 100%, 50%)", + }, + blue: { + object: { h: 240, s: 100, l: 50, a: 1 }, + string: "hsl(240, 100%, 50%)", + }, + yellow: { + object: { h: 60, s: 100, l: 50, a: 1 }, + string: "hsl(60, 100%, 50%)", + }, + aqua: { + object: { h: 180, s: 100, l: 50, a: 1 }, + string: "hsl(180, 100%, 50%)", + }, + fuchsia: { + object: { h: 300, s: 100, l: 50, a: 1 }, + string: "hsl(300, 100%, 50%)", + }, + orange: { + object: { h: 40, s: 100, l: 50, a: 1 }, + string: "hsl(40, 100%, 50%)", + }, + brown: { + object: { h: 0, s: 59, l: 41, a: 1 }, + string: "hsl(0, 59%, 41%)", + rgb: { r: 166.23, g: 42.87, b: 42.87, a: 1 }, + }, + lightgray: { + object: { h: 0, s: 0, l: 83, a: 1 }, + string: "hsl(0, 0%, 83%)", + rgb: { r: 211.65, g: 211.65, b: 211.65, a: 1 }, + }, +}; diff --git a/test/__fixtures__/hsvColors.ts b/test/__fixtures__/hsvColors.ts new file mode 100644 index 0000000..72ab6dd --- /dev/null +++ b/test/__fixtures__/hsvColors.ts @@ -0,0 +1,50 @@ +import type { TestColors } from "."; + +export const hsvColors: TestColors["hsv"] = { + white: { + object: { h: 0, s: 0, v: 100, a: 1 }, + string: "hsv(0, 0%, 100%)", + }, + black: { + object: { h: 0, s: 0, v: 0, a: 1 }, + string: "hsv(0, 0%, 0%)", + }, + red: { + object: { h: 0, s: 100, v: 100, a: 1 }, + string: "hsv(0, 100%, 100%)", + }, + lime: { + object: { h: 120, s: 100, v: 100, a: 1 }, + string: "hsv(120, 100%, 100%)", + }, + blue: { + object: { h: 240, s: 100, v: 100, a: 1 }, + string: "hsv(240, 100%, 100%)", + }, + yellow: { + object: { h: 60, s: 100, v: 100, a: 1 }, + string: "hsv(60, 100%, 100%)", + }, + aqua: { + object: { h: 180, s: 100, v: 100, a: 1 }, + string: "hsv(180, 100%, 100%)", + }, + fuchsia: { + object: { h: 300, s: 100, v: 100, a: 1 }, + string: "hsv(300, 100%, 100%)", + }, + orange: { + object: { h: 40, s: 100, v: 100, a: 1 }, + string: "hsv(40, 100%, 100%)", + }, + brown: { + object: { h: 0, s: 75, v: 65, a: 1 }, + string: "hsv(0, 75%, 65%)", + rgb: { r: 165.75, g: 41.44, b: 41.44, a: 1 }, + }, + lightgray: { + object: { h: 0, s: 0, v: 83, a: 1 }, + string: "hsv(0, 0%, 83%)", + rgb: { r: 211.65, g: 211.65, b: 211.65, a: 1 }, + }, +}; diff --git a/test/__fixtures__/index.ts b/test/__fixtures__/index.ts new file mode 100644 index 0000000..1d1d082 --- /dev/null +++ b/test/__fixtures__/index.ts @@ -0,0 +1,84 @@ +import type { Cmyk, ColorObject, Hsl, Hsv, Rgb } from "../../src/types"; +import { cmykColors } from "./cmykColors"; +import { hexColors } from "./hexColors"; +import { hslColors } from "./hslColors"; +import { hsvColors } from "./hsvColors"; +import { rgbColors } from "./rgbColors"; + +export type ColorNames = + | "black" + | "white" + | "red" + | "lime" + | "blue" + | "yellow" + | "aqua" + | "fuchsia" + | "orange" + | "brown" + | "lightgray"; + +export type ColorRepresentations = { + object: T; + string: string; + rgb?: Rgb; +}; + +export type FormatColorMap< + T extends ColorObject = Rgb, + C extends string = ColorNames, +> = Record>; + +export interface TestColors { + rgb: FormatColorMap; + hsl: FormatColorMap; + hsv: FormatColorMap; + cmyk: FormatColorMap; + hex: FormatColorMap; + withAlpha: (color: ColorObject, value?: number) => ColorObject; +} + +export const testColors: TestColors = { + withAlpha: (color, value = 0.5) => ({ ...color, a: value }), + hex: hexColors, + rgb: rgbColors, + hsl: hslColors, + hsv: hsvColors, + cmyk: cmykColors, +}; + +export type Formats = keyof typeof testColors; + +export type TestColorObject = ColorRepresentations & { colorName: string }; + +type TestColorsFunc = ( + format: Formats, + color: TestColorObject, + expectedRgb: Rgb, +) => void; + +export function forEachColorFormat< + N extends string, + F extends Omit, +>(name: N, func: TestColorsFunc, formats: F) { + it.each(formats)(name, format => { + const colors = testColors[format as keyof TestColors] as FormatColorMap; + + for (const [colorName, colorData] of Object.entries(colors)) { + const expectedRgb = colorData?.rgb || testColors.rgb[colorName].object; + const color = { ...colorData, colorName }; + + func(format, color, expectedRgb); + } + }); +} + +export function forEachMethod( + name: N, + func: (method: string) => void, + methods: M, +) { + it.each(methods)(name, method => { + func(method); + }); +} diff --git a/test/__fixtures__/rgbColors.ts b/test/__fixtures__/rgbColors.ts new file mode 100644 index 0000000..48b03a9 --- /dev/null +++ b/test/__fixtures__/rgbColors.ts @@ -0,0 +1,48 @@ +import type { TestColors } from "."; + +export const rgbColors: TestColors["rgb"] = { + black: { + object: { r: 0, g: 0, b: 0, a: 1 }, + string: "rgb(0, 0, 0)", + }, + white: { + object: { r: 255, g: 255, b: 255, a: 1 }, + string: "rgb(255, 255, 255)", + }, + red: { + object: { r: 255, g: 0, b: 0, a: 1 }, + string: "rgb(255, 0, 0)", + }, + lime: { + object: { r: 0, g: 255, b: 0, a: 1 }, + string: "rgb(0, 255, 0)", + }, + blue: { + object: { r: 0, g: 0, b: 255, a: 1 }, + string: "rgb(0, 0, 255)", + }, + yellow: { + object: { r: 255, g: 255, b: 0, a: 1 }, + string: "rgb(255, 255, 0)", + }, + aqua: { + object: { r: 0, g: 255, b: 255, a: 1 }, + string: "rgb(0, 255, 255)", + }, + fuchsia: { + object: { r: 255, g: 0, b: 255, a: 1 }, + string: "rgb(255, 0, 255)", + }, + orange: { + object: { r: 255, g: 170, b: 0, a: 1 }, + string: "rgb(255, 170, 0)", + }, + brown: { + object: { r: 165, g: 42, b: 42, a: 1 }, + string: "rgb(165, 42, 42)", + }, + lightgray: { + object: { r: 211, g: 211, b: 211, a: 1 }, + string: "rgb(211, 211, 211)", + }, +}; diff --git a/test/accessibility.spec.js b/test/accessibility.spec.js deleted file mode 100644 index fbc995e..0000000 --- a/test/accessibility.spec.js +++ /dev/null @@ -1,63 +0,0 @@ -import { calculateContrastRatio, contrastRatio, relativeLuminance } from '../src/accessibility' - -describe('relativeLuminance', () => { - it('should calculate the luminance of a black color correctly', () => { - const color = { r: 0, g: 0, b: 0 } - expect(relativeLuminance(color)).toBe(0) - }) - - it('should calculate the luminance of a white color correctly', () => { - const color = { r: 255, g: 255, b: 255 } - expect(relativeLuminance(color)).toBe(1) - }) - - it('should calculate the luminance of a gray color correctly', () => { - const color = { r: 128, g: 128, b: 128 } - expect(relativeLuminance(color)).toBeCloseTo(0.215, 2) - }) - - it('should calculate the luminance of a custom color correctly', () => { - const color = { r: 100, g: 200, b: 50 } - expect(relativeLuminance(color)).toBeCloseTo(0.442, 2) - }) - - it('should calculate the luminance of a color with maximum RGB values correctly', () => { - const color = { r: 255, g: 255, b: 255 } - expect(relativeLuminance(color)).toBe(1) - }) - - it('should calculate the luminance of a color with minimum RGB values correctly', () => { - const color = { r: 0, g: 0, b: 0 } - expect(relativeLuminance(color)).toBe(0) - }) -}) - -describe('calculateContrastRatio', () => { - it('calculates contrast ratio between two luminance values', () => { - // Test case where L1 > L2 - expect(calculateContrastRatio(0.7, 0.05)).toBeCloseTo(7.5, 2) - - // Test case where L2 > L1 - expect(calculateContrastRatio(0.05, 0.7)).toBeCloseTo(7.5, 2) - - // Test case where L1 = L2 - expect(calculateContrastRatio(0.1, 0.1)).toBeCloseTo(1, 2) - }) -}) - -describe('contrastRatio', () => { - it('calculates contrast ratio between foreground and background colors', () => { - const higherLuminance = { r: 255, g: 255, b: 255 } - const lowerLuminance = { r: 0, g: 0, b: 0 } - - // Test case where foreground has higher luminance - expect(contrastRatio(higherLuminance, lowerLuminance)).toBeCloseTo(21, 2) - - // Test case where background has higher luminance - expect(contrastRatio(lowerLuminance, higherLuminance)).toBeCloseTo(21, 2) - - // Test case where foreground and background have equal luminance - const equalLuminance = { r: 128, g: 128, b: 128 } // gray - expect(contrastRatio(equalLuminance, equalLuminance)).toBeCloseTo(1, 3) - }) -}) diff --git a/test/colorFormatter.spec.js b/test/colorFormatter.spec.js deleted file mode 100644 index bbff5b1..0000000 --- a/test/colorFormatter.spec.js +++ /dev/null @@ -1,101 +0,0 @@ -import ColorFormatter from '../src/colorFormatter' - -describe('RGB string representation', () => { - it('should create legacy RGB string', () => { - expect(new ColorFormatter().rgb({ r: 20, g: 100, b: 5, a: 0.5 })).toBe('rgba(20, 100, 5, 0.5)') - }) - - it('should create modern RGB color', () => { - expect(new ColorFormatter({ CSSNext: true }).rgb({ r: 20, g: 100, b: 5, a: 0.5 })).toBe('rgb(20 100 5 / 0.5)') - }) - - it('should create minified legacy RGB color', () => { - expect(new ColorFormatter({ minify: true }).rgb({ r: 20, g: 100, b: 5, a: 0.5 })).toBe('rgba(20,100,5,0.5)') - }) - - it('should create minified modern RGB color', () => { - expect(new ColorFormatter({ minify: true, CSSNext: true }).rgb({ r: 20, g: 100, b: 5, a: 0.5 })).toBe('rgb(20 100 5/0.5)') - }) - - it('should omit the alpha channel when its value is equal to one.', () => { - expect(new ColorFormatter().rgb({ r: 20, g: 100, b: 5, a: 1 })).toBe('rgb(20, 100, 5)') - expect(new ColorFormatter({ minify: true }).rgb({ r: 20, g: 100, b: 5, a: 1 })).toBe('rgb(20,100,5)') - expect(new ColorFormatter({ CSSNext: true }).rgb({ r: 20, g: 100, b: 5, a: 1 })).toBe('rgb(20 100 5)') - expect(new ColorFormatter({ minify: true, CSSNext: true }).rgb({ r: 20, g: 100, b: 5, a: 1 })).toBe('rgb(20 100 5)') - }) -}) - -describe('HSL string representation', () => { - it('should create legacy HSL string', () => { - expect(new ColorFormatter().hsl({ h: 30, s: 40, l: 85, a: 0.5 })).toBe('hsla(30ยฐ, 40%, 85%, 0.5)') - }) - - it('should create modern HSL color', () => { - expect(new ColorFormatter({ CSSNext: true }).hsl({ h: 30, s: 40, l: 85, a: 0.5 })).toBe('hsl(30ยฐ 40% 85% / 0.5)') - }) - - it('should create minified legacy HSL color', () => { - expect(new ColorFormatter({ minify: true }).hsl({ h: 30, s: 40, l: 85, a: 0.5 })).toBe('hsla(30,40,85,0.5)') - }) - - it('should create minified modern HSL color', () => { - expect(new ColorFormatter({ minify: true, CSSNext: true }).hsl({ h: 30, s: 40, l: 85, a: 0.5 })).toBe('hsl(30 40 85/0.5)') - }) - - it('should omit the alpha channel when its value is equal to one.', () => { - expect(new ColorFormatter().hsl({ h: 30, s: 40, l: 85, a: 1 })).toBe('hsl(30ยฐ, 40%, 85%)') - expect(new ColorFormatter({ minify: true }).hsl({ h: 30, s: 40, l: 85, a: 1 })).toBe('hsl(30,40,85)') - expect(new ColorFormatter({ CSSNext: true }).hsl({ h: 30, s: 40, l: 85, a: 1 })).toBe('hsl(30ยฐ 40% 85%)') - expect(new ColorFormatter({ minify: true, CSSNext: true }).hsl({ h: 30, s: 40, l: 85, a: 1 })).toBe('hsl(30 40 85)') - }) -}) - -describe('HSV string representation', () => { - it('should create legacy HSV string', () => { - expect(new ColorFormatter().hsv({ h: 30, s: 40, v: 85, a: 0.5 })).toBe('hsva(30ยฐ, 40%, 85%, 0.5)') - }) - - it('should create modern HSV color', () => { - expect(new ColorFormatter({ CSSNext: true }).hsv({ h: 30, s: 40, v: 85, a: 0.5 })).toBe('hsv(30ยฐ 40% 85% / 0.5)') - }) - - it('should create minified legacy HSV color', () => { - expect(new ColorFormatter({ minify: true }).hsv({ h: 30, s: 40, v: 85, a: 0.5 })).toBe('hsva(30,40,85,0.5)') - }) - - it('should create minified modern HSV color', () => { - expect(new ColorFormatter({ minify: true, CSSNext: true }).hsv({ h: 30, s: 40, v: 85, a: 0.5 })).toBe('hsv(30 40 85/0.5)') - }) - - it('should omit the alpha channel when its value is equal to one.', () => { - expect(new ColorFormatter().hsv({ h: 30, s: 40, v: 85, a: 1 })).toBe('hsv(30ยฐ, 40%, 85%)') - expect(new ColorFormatter({ minify: true }).hsv({ h: 30, s: 40, v: 85, a: 1 })).toBe('hsv(30,40,85)') - expect(new ColorFormatter({ CSSNext: true }).hsv({ h: 30, s: 40, v: 85, a: 1 })).toBe('hsv(30ยฐ 40% 85%)') - expect(new ColorFormatter({ minify: true, CSSNext: true }).hsv({ h: 30, s: 40, v: 85, a: 1 })).toBe('hsv(30 40 85)') - }) -}) - -describe('CMYK string representation', () => { - it('should create legacy CMYK string', () => { - expect(new ColorFormatter().cmyk({ c: 30, m: 2, y: 10, k: 1, a: 0.5 })).toBe('cmyka(30%, 2%, 10%, 1%, 0.5)') - }) - - it('should create modern CMYK color', () => { - expect(new ColorFormatter({ CSSNext: true }).cmyk({ c: 30, m: 2, y: 10, k: 1, a: 0.5 })).toBe('cmyk(30% 2% 10% 1% / 0.5)') - }) - - it('should create minified legacy CMYK color', () => { - expect(new ColorFormatter({ minify: true }).cmyk({ c: 30, m: 2, y: 10, k: 1, a: 0.5 })).toBe('cmyka(30,2,10,1,0.5)') - }) - - it('should create minified modern CMYK color', () => { - expect(new ColorFormatter({ minify: true, CSSNext: true }).cmyk({ c: 30, m: 2, y: 10, k: 1, a: 0.5 })).toBe('cmyk(30 2 10 1/0.5)') - }) - - it('should omit the alpha channel when its value is equal to one.', () => { - expect(new ColorFormatter().cmyk({ c: 30, m: 2, y: 10, k: 1, a: 1 })).toBe('cmyk(30%, 2%, 10%, 1%)') - expect(new ColorFormatter({ minify: true }).cmyk({ c: 30, m: 2, y: 10, k: 1, a: 1 })).toBe('cmyk(30,2,10,1)') - expect(new ColorFormatter({ CSSNext: true }).cmyk({ c: 30, m: 2, y: 10, k: 1, a: 1 })).toBe('cmyk(30% 2% 10% 1%)') - expect(new ColorFormatter({ minify: true, CSSNext: true }).cmyk({ c: 30, m: 2, y: 10, k: 1, a: 1 })).toBe('cmyk(30 2 10 1)') - }) -}) diff --git a/test/colorNormalizer.spec.js b/test/colorNormalizer.spec.js deleted file mode 100644 index f6b8a75..0000000 --- a/test/colorNormalizer.spec.js +++ /dev/null @@ -1,53 +0,0 @@ -import { Clamp, Round } from '../src/colorNormalizer' - -describe('Clamp', () => { - it('should clamp RGB values', () => { - const input = { r: 256, g: -256, b: 212, a: 2 } - const match = { r: 255, g: 0, b: 212, a: 1 } - expect(Clamp.rgb(input)).toEqual(match) - }) - - it('should clamp HSL values', () => { - const input = { h: 500, s: -60, l: 212, a: 2 } - const match = { h: 360, s: 0, l: 100, a: 1 } - expect(Clamp.hsl(input)).toEqual(match) - }) - - it('should clamp HSV values', () => { - const input = { h: 500, s: -60, v: 212, a: 2 } - const match = { h: 360, s: 0, v: 100, a: 1 } - expect(Clamp.hsv(input)).toEqual(match) - }) - - it('should clamp CMYK values', () => { - const input = { c: 500, m: -60, y: 212, k: 12, a: 2 } - const match = { c: 100, m: 0, y: 100, k: 12, a: 1 } - expect(Clamp.cmyk(input)).toEqual(match) - }) -}) - -describe('Round', () => { - it('should round RGB values', () => { - const input = { r: 25.2013, g: -0.23, b: 54.7822, a: 2 } - const match = { r: 25, g: 0, b: 55, a: 1 } - expect(Round.rgb(input)).toEqual(match) - }) - - it('should round HSL values', () => { - const input = { h: 250.181, s: 50, l: 80.9128, a: 2 } - const match = { h: 250, s: 50, l: 81, a: 1 } - expect(Round.hsl(input)).toEqual(match) - }) - - it('should round HSV values', () => { - const input = { h: 250.181, s: 50, v: 80.9128, a: 2 } - const match = { h: 250, s: 50, v: 81, a: 1 } - expect(Round.hsv(input)).toEqual(match) - }) - - it('should round CMYK values', () => { - const input = { c: 500, m: -60, y: 12.9, k: 12.1982, a: 2 } - const match = { c: 100, m: 0, y: 13, k: 12, a: 1 } - expect(Round.cmyk(input)).toEqual(match) - }) -}) diff --git a/test/compose.spec.js b/test/compose.spec.js deleted file mode 100644 index 11ce66b..0000000 --- a/test/compose.spec.js +++ /dev/null @@ -1,159 +0,0 @@ -import { modBy, mix, lighten, saturate, hue, alpha, rgbToGray, invert } from '../src/compose' - -describe('modBy', () => { - test('should correctly modify a value', () => { - const value = 50 - const amount = 0.4 - const result = modBy(value, amount) - expect(result).toBeCloseTo(70) - }) - - test('should return the same value if amount is NaN', () => { - const value = 50 - const amount = NaN - const result = modBy(value, amount) - expect(result).toBe(value) - }) -}) - -describe('mix', () => { - test('should mix two RGB colors correctly', () => { - const primaryColor = { r: 255, g: 0, b: 0 } - const secondaryColor = { r: 0, g: 255, b: 0 } - const amount = 0.5 - const result = mix(primaryColor, secondaryColor, amount) - expect(result).toEqual({ r: 127.5, g: 127.5, b: 0, a: 1 }) - }) - - test('should clamp alpha value to 100', () => { - const primaryColor = { r: 255, g: 0, b: 0, a: 0.5 } - const secondaryColor = { r: 0, g: 255, b: 0, a: 0.5 } - const amount = 0.5 - const result = mix(primaryColor, secondaryColor, amount) - expect(result.a).toBe(1) - }) -}) - -describe('lighten', () => { - test('should lighten an HSL color correctly', () => { - const color = { h: 120, s: 50, l: 50 } - const amount = 0.2 - const result = lighten(color, amount) - expect(result.l).toBe(60) - }) - - test('should not modify hue and saturation', () => { - const color = { h: 180, s: 70, l: 30 } - const amount = 0.1 - const result = lighten(color, amount) - expect(result.h).toBe(color.h) - expect(result.s).toBe(color.s) - }) -}) - -describe('saturate', () => { - test('should saturate an HSL color correctly', () => { - const color = { h: 180, s: 50, l: 50 } - const amount = 0.3 - const result = saturate(color, amount) - expect(result.s).toBe(65) - }) - - test('should not modify hue and lightness', () => { - const color = { h: 240, s: 80, l: 70 } - const amount = 0.1 - const result = saturate(color, amount) - expect(result.h).toBe(color.h) - expect(result.l).toBe(color.l) - }) -}) - -describe('invert', () => { - test('should invert black to white correctly', () => { - const color = { r: 255, g: 255, b: 255 } - const result = invert(color) - expect(result.r).toBe(0) - expect(result.g).toBe(0) - expect(result.b).toBe(0) - }) - - test('should invert white to black correctly', () => { - const color = { r: 0, g: 0, b: 0 } - const result = invert(color) - expect(result.r).toBe(255) - expect(result.g).toBe(255) - expect(result.b).toBe(255) - }) -}) - -describe('hue', () => { - test('should adjust hue of an HSL color correctly', () => { - const color = { h: 180, s: 50, l: 50 } - const amount = 0.3 - const result = hue(color, amount) - expect(result.h).toBe(234) - }) - - test('should not modify saturation and lightness', () => { - const color = { h: 240, s: 80, l: 70 } - const amount = 0.1 - const result = hue(color, amount) - expect(result.s).toBe(color.s) - expect(result.l).toBe(color.l) - }) -}) - -describe('alpha', () => { - test('should adjust alpha channel of an RGB color correctly', () => { - const color = { h: 180, s: 50, l: 50, a: 0.54 } - const amount = 0.3 - const result = alpha(color, amount) - expect(result.a).toBe(0.7) - }) - - test('should not modify R, G, and B channels', () => { - const color = { r: 90, g: 80, b: 70, a: 0.54 } - const amount = 0.1 - const result = alpha(color, amount) - expect(result.r).toBe(color.r) - expect(result.g).toBe(color.g) - expect(result.b).toBe(color.b) - }) -}) - -describe('rgbToGray', () => { - // Test for converting RGB to grayscale without using the NTSC formula - it('should convert RGB to grayscale without NTSC formula', () => { - const color = { r: 50, g: 168, b: 82, a: 1 } - const result = rgbToGray(color) - expect(result).toEqual({ r: 136.704, g: 136.704, b: 136.704, a: 1 }) - }) - - // Test for converting RGB to grayscale using the NTSC formula - it('should convert RGB to grayscale with NTSC formula', () => { - const color = { r: 50, g: 168, b: 82, a: 1 } - const result = rgbToGray(color, true) - expect(result).toEqual({ r: 122.914, g: 122.914, b: 122.914, a: 1 }) - }) - - // Test for converting black (0, 0, 0) to grayscale without NTSC formula - it('should convert black color to grayscale without NTSC formula', () => { - const color = { r: 0, g: 0, b: 0, a: 1 } - const result = rgbToGray(color) - expect(result).toEqual({ r: 0, g: 0, b: 0, a: 1 }) - }) - - // Test for converting white (255, 255, 255) to grayscale using the NTSC formula - it('should convert white color to grayscale with NTSC formula', () => { - const color = { r: 255, g: 255, b: 255, a: 1 } - const result = rgbToGray(color, true) - expect(result).toEqual({ r: 255, g: 255, b: 255, a: 1 }) - }) - - // Test for converting a color with alpha channel - it('should preserve alpha channel when converting to grayscale', () => { - const color = { r: 120, g: 60, b: 200, a: 0.5 } - const result = rgbToGray(color) - expect(result).toEqual({ r: 82.864, g: 82.864, b: 82.864, a: 0.5 }) - }) -}) diff --git a/test/conversion.spec.js b/test/conversion.spec.js deleted file mode 100644 index 28f5c05..0000000 --- a/test/conversion.spec.js +++ /dev/null @@ -1,380 +0,0 @@ -import { rgbToHex, hexToRgb, hslToHsv, hsvToHsl, rgbToHsv, hsvToRgb, hslToRgb, rgbToNamedColor } from '../src/conversion' - -describe('rgbToHex()', () => { - const validRgb = { r: 100, g: 200, b: 30 } - const validRgba = { r: 100, g: 200, b: 30, a: 0.5 } - - it('converts a valid RGB object to a HEX string', () => { - const rgb = validRgb - const result = rgbToHex(rgb) - - expect(result).toBe('#64C81E') - }) - - it('converts a valid RGB object to a HEX shortened string if possible', () => { - const rgb = { r: 51, g: 51, b: 51, a: 0.8 } - const result = rgbToHex(rgb, { minify: true }) - - expect(result).toBe('#333C') - }) - - it('converts a valid RGBA object to a HEX string with an alpha channel', () => { - const rgba = validRgba - const result = rgbToHex(rgba) - - expect(result).toBe('#64C81E80') - }) - - it('returns #000000 when given an RGB object with r, g, and b equal to 0', () => { - const rgb = { r: 0, g: 0, b: 0 } - const result = rgbToHex(rgb) - - expect(result).toBe('#000000') - }) -}) - -describe('hexToRgb', () => { - const validHex = '64c81e' - const validHexAlpha = '64c81ecc' - - it('converts a valid HEX string to an RGB object', () => { - const hex = validHex - - const rgb = hexToRgb(hex) - - expect(rgb.r).toBe(100) - expect(rgb.g).toBe(200) - expect(rgb.b).toBe(30) - expect(rgb.a).toBe(1) - }) - - it('converts a valid HEX string with an alpha channel to an RGB object with alpha', () => { - const hex = validHexAlpha - - const rgb = hexToRgb(hex) - - expect(rgb.r).toBe(100) - expect(rgb.g).toBe(200) - expect(rgb.b).toBe(30) - expect(rgb.a).toBe(0.8) - }) - - it('returns an RGB object with r, g, and b equal to 0 when given #000000', () => { - const hex = '000000' - - const rgb = hexToRgb(hex) - - expect(rgb.r).toBe(0) - expect(rgb.g).toBe(0) - expect(rgb.b).toBe(0) - expect(rgb.a).toBe(1) - }) -}) - -describe('hslToHsv()', () => { - it('converts an HSL color object to HSV correctly', () => { - const hsl = { h: 120, s: 50, l: 75 } - const hsv = hslToHsv(hsl) - - expect(hsv.h).toBe(120) - expect(hsv.s).toBe(28.57) - expect(hsv.v).toBe(87.5) - }) - - it('converts an HSLA color object to HSVA correctly', () => { - const hsl = { h: 120, s: 50, l: 75, a: 0.5 } - const hsv = hslToHsv(hsl) - - expect(hsv.h).toBe(120, 5) - expect(hsv.s).toBe(28.57, 5) - expect(hsv.v).toBe(87.5, 5) - expect(hsv.a).toBe(0.5, 5) - }) - - it('handles saturation of 0 correctly', () => { - const hsl = { h: 120, s: 0, l: 75, a: 0.5 } - const hsv = hslToHsv(hsl) - - expect(hsv.h).toBe(120, 5) - expect(hsv.s).toBe(0, 5) - expect(hsv.v).toBe(75, 5) - expect(hsv.a).toBe(0.5, 5) - }) - - it('handles lightness of 0 and 100 correctly', () => { - const hsl1 = { h: 120, s: 50, l: 0, a: 0.5 } - const hsl2 = { h: 120, s: 50, l: 100, a: 0.5 } - const hsv1 = hslToHsv(hsl1) - const hsv2 = hslToHsv(hsl2) - - expect(hsv1.h).toBe(120, 5) - expect(hsv1.s).toBe(0, 5) - expect(hsv1.v).toBe(0, 5) - expect(hsv1.a).toBe(0.5, 5) - - expect(hsv2.h).toBe(120, 5) - expect(hsv2.s).toBe(0, 5) - expect(hsv2.v).toBe(100, 5) - expect(hsv2.a).toBe(0.5, 5) - }) -}) - -describe('hsvToHsl()', () => { - it('converts an HSV color object to HSL correctly', () => { - const hsv = { h: 120, s: 100, v: 100 } - const hsl = hsvToHsl(hsv) - - expect(hsl.h).toBe(120) - expect(hsl.s).toBe(100) - expect(hsl.l).toBe(50) - }) - - it('converts an HSVA color object to HSLA correctly', () => { - const hsv = { h: 120, s: 100, v: 100, a: 0.5 } - const hsl = hsvToHsl(hsv) - - expect(hsl.h).toBe(120) - expect(hsl.s).toBe(100) - expect(hsl.l).toBe(50) - expect(hsl.a).toBe(0.5) - }) - - it('handles saturation of 0 correctly', () => { - const hsv = { h: 120, s: 0, v: 75, a: 0.5 } - const hsl = hsvToHsl(hsv) - - expect(hsl.h).toBe(120) - expect(hsl.s).toBe(0) - expect(hsl.l).toBe(75) - expect(hsl.a).toBe(0.5) - }) - - it('handles lightness of 0 and 100 correctly', () => { - const hsv1 = { h: 120, s: 50, v: 0 } - const hsv2 = { h: 120, s: 50, v: 100 } - const hsl1 = hsvToHsl(hsv1) - const hsl2 = hsvToHsl(hsv2) - - expect(hsl1.h).toBe(120) - expect(hsl1.s).toBe(0) - expect(hsl1.l).toBe(0) - - expect(hsl2.h).toBe(120) - expect(hsl2.s).toBe(100) - expect(hsl2.l).toBe(75) - }) -}) - -describe('rgbToHsv()', () => { - it('converts an RGB color object to HSV correctly', () => { - const rgb = { r: 230, g: 24, b: 120 } - const hsv = rgbToHsv(rgb) - - expect(hsv.h).toBe(332.04) - expect(hsv.s).toBe(89.57) - expect(hsv.v).toBe(90.2) - expect(hsv.a).toBe(1) - }) - - it('converts an RGBA color object to HSVA correctly', () => { - const rgb = { r: 230, g: 24, b: 120, a: 0.5 } - const hsv = rgbToHsv(rgb) - - expect(hsv.h).toBe(332.04) - expect(hsv.s).toBe(89.57) - expect(hsv.v).toBe(90.2) - expect(hsv.a).toBe(0.5) - }) - - it('handles maximum red value correctly', () => { - const rgb = { r: 255, g: 0, b: 0 } - const hsv = rgbToHsv(rgb) - - expect(hsv.h).toBe(0) - expect(hsv.s).toBe(100) - expect(hsv.v).toBe(100) - expect(hsv.a).toBe(1) - }) - - it('handles maximum green value correctly', () => { - const rgb = { r: 0, g: 255, b: 0 } - const hsv = rgbToHsv(rgb) - - expect(hsv.h).toBe(120) - expect(hsv.s).toBe(100) - expect(hsv.v).toBe(100) - expect(hsv.a).toBe(1) - }) - - it('handles maximum blue value correctly', () => { - const rgb = { r: 0, g: 0, b: 255 } - const hsv = rgbToHsv(rgb) - - expect(hsv.h).toBe(240) - expect(hsv.s).toBe(100) - expect(hsv.v).toBe(100) - expect(hsv.a).toBe(1) - }) - - it('handles grayscale values correctly', () => { - const rgb = { r: 128, g: 128, b: 128 } - const hsv = rgbToHsv(rgb) - - expect(hsv.h).toBe(0) - expect(hsv.s).toBe(0) - expect(hsv.v).toBe(50.2) - expect(hsv.a).toBe(1) - }) -}) - -describe('hsvToRgb()', () => { - // Test case 1: Validate basic conversion - it('converts an HSV color object to RGB correctly', () => { - const hsv = { h: 120, s: 100, v: 100 } - const rgb = hsvToRgb(hsv) - - expect(rgb.r).toBe(0) - expect(rgb.g).toBe(255) - expect(rgb.b).toBe(0) - expect(rgb.a).toBe(1) - }) - - // Test case 2: Validate conversion with alpha channel - it('converts an HSVA color object to RGBA correctly', () => { - const hsv = { h: 120, s: 100, v: 100, a: 0.5 } - const rgb = hsvToRgb(hsv) - - expect(rgb.r).toBe(0) - expect(rgb.g).toBe(255) - expect(rgb.b).toBe(0) - expect(rgb.a).toBe(0.5) - }) - - // Test case 3: Validate boundary for saturation - it('handles saturation of 0 correctly', () => { - const hsv = { h: 120, s: 0, v: 75 } - const rgb = hsvToRgb(hsv) - - expect(rgb.r).toBe(191.25) - expect(rgb.g).toBe(191.25) - expect(rgb.b).toBe(191.25) - expect(rgb.a).toBe(1) - }) - - // Test case 4: Validate boundary for lightness - it('handles lightness of 0 correctly', () => { - const hsv = { h: 120, s: 50, v: 0 } - const rgb = hsvToRgb(hsv) - - expect(rgb.r).toBe(0) - expect(rgb.g).toBe(0) - expect(rgb.b).toBe(0) - expect(rgb.a).toBe(1) - }) - - // Test case 5: Validate lightness of 100 - it('handles lightness of 100 correctly', () => { - const hsv = { h: 120, s: 50, v: 100 } - const rgb = hsvToRgb(hsv) - - expect(rgb.r).toBe(127.5) - expect(rgb.g).toBe(255) - expect(rgb.b).toBe(127.5) - expect(rgb.a).toBe(1) - }) -}) - -describe('hslToRgb', () => { - it('converts valid HSL to RGB', () => { - const input = { h: 120, s: 50, l: 30, a: 1 } - const rgb = hslToRgb(input) - - expect(rgb.r).toBe(38.25) - expect(rgb.g).toBe(114.75) - expect(rgb.b).toBe(38.25) - expect(rgb.a).toBe(1) - }) - - it('handles max hue', () => { - const input = { h: 360, s: 50, l: 30, a: 1 } - const rgb = hslToRgb(input) - - expect(rgb.r).toBe(114.75) - expect(rgb.g).toBe(38.25) - expect(rgb.b).toBe(38.25) - expect(rgb.a).toBe(1) - }) - - it('handles min hue', () => { - const input = { h: 0, s: 50, l: 30, a: 1 } - const rgb = hslToRgb(input) - - expect(rgb.r).toBe(114.75) - expect(rgb.g).toBe(38.25) - expect(rgb.b).toBe(38.25) - expect(rgb.a).toBe(1) - }) - - it('handles max saturation', () => { - const input = { h: 120, s: 100, l: 30, a: 1 } - const rgb = hslToRgb(input) - - expect(rgb.r).toBe(0) - expect(rgb.g).toBe(153) - expect(rgb.b).toBe(0) - expect(rgb.a).toBe(1) - }) - - it('handles min saturation', () => { - const input = { h: 120, s: 0.1, l: 30, a: 1 } - const rgb = hslToRgb(input) - - expect(rgb.r).toBe(76.42) - expect(rgb.g).toBe(76.58) - expect(rgb.b).toBe(76.42) - expect(rgb.a).toBe(1) - }) - - it('handles max lightness', () => { - const input = { h: 120, s: 50, l: 100, a: 1 } - const rgb = hslToRgb(input) - - expect(rgb.r).toBe(255) - expect(rgb.g).toBe(255) - expect(rgb.b).toBe(255) - expect(rgb.a).toBe(1) - }) - - it('handles min lightness', () => { - const input = { h: 120, s: 50, l: 0, a: 1 } - const rgb = hslToRgb(input) - - expect(rgb.r).toBe(0) - expect(rgb.g).toBe(0) - expect(rgb.b).toBe(0) - expect(rgb.a).toBe(1) - }) -}) - -describe('rgbToNamedColor', () => { - it('converts a red color from RGB to CSS named color correctly', () => { - const input = { r: 255, g: 0, b: 0, a: 1 } - const named = rgbToNamedColor(input) - - expect(named).toBe('red') - }) - - it('converts a green color from RGB to CSS named color correctly', () => { - const input = { r: 0, g: 128, b: 0, a: 1 } - const named = rgbToNamedColor(input) - - expect(named).toBe('green') - }) - - it('converts a blue color from RGB to CSS named color correctly', () => { - const input = { r: 0, g: 0, b: 255, a: 1 } - const named = rgbToNamedColor(input) - - expect(named).toBe('blue') - }) -}) diff --git a/test/conversions/cmykConversions.test.ts b/test/conversions/cmykConversions.test.ts new file mode 100644 index 0000000..f83cc4a --- /dev/null +++ b/test/conversions/cmykConversions.test.ts @@ -0,0 +1,44 @@ +import { cmykToRgb } from "../../src/conversions/cmykConversions"; + +describe("CMYK Color Conversion", () => { + describe("cmykToRgb", () => { + it("should convert basic CMYK colors to RGB", () => { + expect(cmykToRgb({ c: 0, m: 100, y: 100, k: 0, a: 1 })).toEqual({ + r: 255, + g: 0, + b: 0, + a: 1, + }); + expect(cmykToRgb({ c: 100, m: 0, y: 100, k: 0, a: 1 })).toEqual({ + r: 0, + g: 255, + b: 0, + a: 1, + }); + expect(cmykToRgb({ c: 100, m: 100, y: 0, k: 0, a: 1 })).toEqual({ + r: 0, + g: 0, + b: 255, + a: 1, + }); + }); + + it("should handle alpha values correctly", () => { + expect(cmykToRgb({ c: 0, m: 100, y: 100, k: 0, a: 0.5 })).toEqual({ + r: 255, + g: 0, + b: 0, + a: 0.5, + }); + }); + + it("should handle grayscale colors correctly", () => { + expect(cmykToRgb({ c: 0, m: 0, y: 0, k: 50, a: 1 })).toEqual({ + r: 127.5, + g: 127.5, + b: 127.5, + a: 1, + }); + }); + }); +}); diff --git a/test/conversions/hexConversions.test.ts b/test/conversions/hexConversions.test.ts new file mode 100644 index 0000000..9850974 --- /dev/null +++ b/test/conversions/hexConversions.test.ts @@ -0,0 +1,16 @@ +import { hexToRgb } from "../../src/conversions/hexConversions"; + +describe("HEX Color Conversion", () => { + describe("hexToRgb", () => { + it("should convert basic 6-digit hex colors to RGB", () => { + expect(hexToRgb("ff0000")).toEqual({ r: 255, g: 0, b: 0, a: 1 }); + expect(hexToRgb("00ff00")).toEqual({ r: 0, g: 255, b: 0, a: 1 }); + expect(hexToRgb("0000ff")).toEqual({ r: 0, g: 0, b: 255, a: 1 }); + }); + + it("should handle 8-digit hex colors with alpha correctly", () => { + expect(hexToRgb("ff000080")).toEqual({ r: 255, g: 0, b: 0, a: 0.5 }); + expect(hexToRgb("00ff00ff")).toEqual({ r: 0, g: 255, b: 0, a: 1 }); + }); + }); +}); diff --git a/test/conversions/hslConversions.test.ts b/test/conversions/hslConversions.test.ts new file mode 100644 index 0000000..e09fc02 --- /dev/null +++ b/test/conversions/hslConversions.test.ts @@ -0,0 +1,98 @@ +import { hslToHsv, hslToRgb } from "../../src/conversions/hslConversions"; + +describe("HSL Color Conversions", () => { + describe("hslToHsv", () => { + it("should convert basic HSL colors to HSV", () => { + expect(hslToHsv({ h: 0, s: 100, l: 50, a: 1 })).toEqual({ + h: 0, + s: 100, + v: 100, + a: 1, + }); + expect(hslToHsv({ h: 120, s: 50, l: 62.5, a: 1 })).toEqual({ + h: 120, + s: 46.15, + v: 81.25, + a: 1, + }); + expect(hslToHsv({ h: 240, s: 25, l: 12.5, a: 1 })).toEqual({ + h: 240, + s: 40, + v: 15.63, + a: 1, + }); + }); + + it("should handle alpha values correctly", () => { + expect(hslToHsv({ h: 0, s: 100, l: 50, a: 0.5 })).toEqual({ + h: 0, + s: 100, + v: 100, + a: 0.5, + }); + }); + + it("should handle edge cases correctly", () => { + expect(hslToHsv({ h: 270, s: 0, l: 100, a: 0.5 })).toEqual({ + h: 270, + s: 0, + v: 100, + a: 0.5, + }); + + expect(hslToHsv({ h: 270, s: 100, l: 0, a: 0.5 })).toEqual({ + h: 270, + s: 0, + v: 0, + a: 0.5, + }); + }); + }); + + describe("hslToRgb", () => { + it("should convert basic HSL colors to RGB", () => { + expect(hslToRgb({ h: 0, s: 100, l: 50, a: 1 })).toEqual({ + r: 255, + g: 0, + b: 0, + a: 1, + }); + expect(hslToRgb({ h: 120, s: 50, l: 50, a: 1 })).toEqual({ + r: 63.74, + g: 191.25, + b: 63.74, + a: 1, + }); + expect(hslToRgb({ h: 240, s: 100, l: 50, a: 1 })).toEqual({ + r: 0, + g: 0, + b: 255, + a: 1, + }); + }); + + it("should handle alpha values correctly", () => { + expect(hslToRgb({ h: 0, s: 100, l: 50, a: 0.5 })).toEqual({ + r: 255, + g: 0, + b: 0, + a: 0.5, + }); + }); + + it("should handle grayscale colors correctly", () => { + expect(hslToRgb({ h: 0, s: 0, l: 0, a: 1 })).toEqual({ + r: 0, + g: 0, + b: 0, + a: 1, + }); + expect(hslToRgb({ h: 0, s: 0, l: 100, a: 1 })).toEqual({ + r: 255, + g: 255, + b: 255, + a: 1, + }); + }); + }); +}); diff --git a/test/conversions/hsvConversions.test.ts b/test/conversions/hsvConversions.test.ts new file mode 100644 index 0000000..b56e32e --- /dev/null +++ b/test/conversions/hsvConversions.test.ts @@ -0,0 +1,83 @@ +import { hsvToHsl, hsvToRgb } from "../../src/conversions/hsvConversions"; + +describe("HSV Color Conversions", () => { + describe("hsvToHsl", () => { + it("should convert basic HSV colors to HSL", () => { + expect(hsvToHsl({ h: 0, s: 100, v: 100, a: 1 })).toEqual({ + h: 0, + s: 100, + l: 50, + a: 1, + }); + expect(hsvToHsl({ h: 120, s: 50, v: 75, a: 1 })).toEqual({ + h: 120, + s: 42.86, + l: 56.25, + a: 1, + }); + expect(hsvToHsl({ h: 240, s: 25, v: 25, a: 1 })).toEqual({ + h: 240, + s: 14.29, + l: 21.88, + a: 1, + }); + }); + + it("should handle alpha values correctly", () => { + expect(hsvToHsl({ h: 0, s: 100, v: 100, a: 0.5 })).toEqual({ + h: 0, + s: 100, + l: 50, + a: 0.5, + }); + }); + + it("should handle edge cases correctly", () => { + expect(hsvToHsl({ h: 270, s: 0, v: 100, a: 0.5 })).toEqual({ + h: 270, + s: 0, + l: 100, + a: 0.5, + }); + + expect(hsvToHsl({ h: 270, s: 100, v: 0, a: 0.5 })).toEqual({ + h: 270, + s: 0, + l: 0, + a: 0.5, + }); + }); + }); + + describe("hsvToRgb", () => { + it("should convert basic HSV colors to RGB", () => { + expect(hsvToRgb({ h: 0, s: 100, v: 100, a: 1 })).toEqual({ + r: 255, + g: 0, + b: 0, + a: 1, + }); + expect(hsvToRgb({ h: 120, s: 50, v: 75, a: 1 })).toEqual({ + r: 95.63, + g: 191.25, + b: 95.63, + a: 1, + }); + expect(hsvToRgb({ h: 240, s: 25, v: 25, a: 1 })).toEqual({ + r: 47.81, + g: 47.81, + b: 63.75, + a: 1, + }); + }); + + it("should handle alpha values correctly", () => { + expect(hsvToRgb({ h: 0, s: 100, v: 100, a: 0.5 })).toEqual({ + r: 255, + g: 0, + b: 0, + a: 0.5, + }); + }); + }); +}); diff --git a/test/conversions/rgbConversions.test.ts b/test/conversions/rgbConversions.test.ts new file mode 100644 index 0000000..1c9320a --- /dev/null +++ b/test/conversions/rgbConversions.test.ts @@ -0,0 +1,174 @@ +import { + rgbToCmyk, + rgbToHex, + rgbToHsl, + rgbToHsv, + rgbToNamedColor, +} from "../../src/conversions/rgbConversions"; +import { forEachColorFormat } from "../__fixtures__"; + +describe("RGB Color Conversions", () => { + describe("rgbToNamedColor", () => { + forEachColorFormat( + "should return the correct named color for basic colors", + (_, color, rgb) => { + expect(rgbToNamedColor(rgb)).toBe(color.colorName); + }, + ["rgb"], + ); + + it("should return the closest named color for non-exact matches", () => { + expect(rgbToNamedColor({ r: 250, g: 8, b: 7, a: 1 })).toBe("red"); + expect(rgbToNamedColor({ r: 8, g: 255, b: 7, a: 1 })).toBe("lime"); + expect(rgbToNamedColor({ r: 8, g: 7, b: 255, a: 1 })).toBe("blue"); + }); + }); + + describe("rgbToHex", () => { + forEachColorFormat( + "should convert basic rgb colors to %s", + (_, color, rgb) => { + expect(rgbToHex(rgb)).toBe(color.string.toUpperCase()); + }, + ["hex"], + ); + + it("should handle alpha values correctly", () => { + expect(rgbToHex({ r: 255, g: 0, b: 0, a: 0.5 })).toBe("#FF000080"); + }); + + it("should minify hex values when possible", () => { + expect(rgbToHex({ r: 255, g: 0, b: 0, a: 1 }, { minify: true })).toBe( + "#F00", + ); + }); + }); + + describe("rgbToHsv", () => { + it("should convert basic RGB colors to HSV", () => { + expect(rgbToHsv({ r: 255, g: 0, b: 0, a: 1 })).toEqual({ + h: 0, + s: 100, + v: 100, + a: 1, + }); + expect(rgbToHsv({ r: 0, g: 255, b: 0, a: 1 })).toEqual({ + h: 120, + s: 100, + v: 100, + a: 1, + }); + expect(rgbToHsv({ r: 0, g: 0, b: 255, a: 1 })).toEqual({ + h: 240, + s: 100, + v: 100, + a: 1, + }); + }); + + it("should handle alpha values correctly", () => { + expect(rgbToHsv({ r: 255, g: 0, b: 0, a: 0.5 })).toEqual({ + h: 0, + s: 100, + v: 100, + a: 0.5, + }); + }); + + it("should handle grayscale colors correctly", () => { + expect(rgbToHsv({ r: 128, g: 128, b: 128, a: 1 })).toEqual({ + h: 0, + s: 0, + v: 50.2, + a: 1, + }); + }); + }); + + describe("rgbToCmyk", () => { + it("should convert basic RGB colors to CMYK", () => { + expect(rgbToCmyk({ r: 255, g: 0, b: 0, a: 1 })).toEqual({ + c: 0, + m: 100, + y: 100, + k: 0, + a: 1, + }); + expect(rgbToCmyk({ r: 0, g: 255, b: 0, a: 1 })).toEqual({ + c: 100, + m: 0, + y: 100, + k: 0, + a: 1, + }); + expect(rgbToCmyk({ r: 0, g: 0, b: 255, a: 1 })).toEqual({ + c: 100, + m: 100, + y: 0, + k: 0, + a: 1, + }); + }); + + it("should handle alpha values correctly", () => { + expect(rgbToCmyk({ r: 255, g: 0, b: 0, a: 0.5 })).toEqual({ + c: 0, + m: 100, + y: 100, + k: 0, + a: 0.5, + }); + }); + + it("should handle grayscale colors correctly", () => { + expect(rgbToCmyk({ r: 128, g: 128, b: 128, a: 1 })).toEqual({ + c: 0, + m: 0, + y: 0, + k: 49.8, + a: 1, + }); + }); + }); + + describe("rgbToHsl", () => { + it("should convert basic RGB colors to HSL", () => { + expect(rgbToHsl({ r: 255, g: 0, b: 0, a: 1 })).toEqual({ + h: 0, + s: 100, + l: 50, + a: 1, + }); + expect(rgbToHsl({ r: 0, g: 255, b: 0, a: 1 })).toEqual({ + h: 120, + s: 100, + l: 50, + a: 1, + }); + expect(rgbToHsl({ r: 0, g: 0, b: 255, a: 1 })).toEqual({ + h: 240, + s: 100, + l: 50, + a: 1, + }); + }); + + it("should handle alpha values correctly", () => { + expect(rgbToHsl({ r: 255, g: 0, b: 0, a: 0.5 })).toEqual({ + h: 0, + s: 100, + l: 50, + a: 0.5, + }); + }); + + it("should handle grayscale colors correctly", () => { + expect(rgbToHsl({ r: 128, g: 128, b: 128, a: 1 })).toEqual({ + h: 0, + s: 0, + l: 50.2, + a: 1, + }); + }); + }); +}); diff --git a/test/core/accessibility.test.ts b/test/core/accessibility.test.ts new file mode 100644 index 0000000..54e260d --- /dev/null +++ b/test/core/accessibility.test.ts @@ -0,0 +1,90 @@ +import { + calculateContrastRatio, + contrastRatio, + relativeLuminance, +} from "../../src/core/accessibility"; +import { testColors } from "../__fixtures__"; + +describe("Accessibility functions", () => { + describe("relativeLuminance", () => { + it("should calculate luminance correctly for black", () => { + expect(relativeLuminance(testColors.rgb.black.object)).toBe(0); + }); + + it("should calculate luminance correctly for white", () => { + expect(relativeLuminance(testColors.rgb.white.object)).toBe(1); + }); + + it("should calculate luminance correctly for a lightgray", () => { + expect(relativeLuminance(testColors.rgb.lightgray.object)).toBeCloseTo( + 0.65, + 1, + ); + }); + }); + + describe("calculateContrastRatio", () => { + it("should calculate contrast ratio correctly for black and white", () => { + const blackLuminance = 0; + const whiteLuminance = 1; + expect(calculateContrastRatio(whiteLuminance, blackLuminance)).toBe(21); + }); + + it("should handle cases where L1 is less than L2", () => { + const L1 = 0.3; + const L2 = 0.7; + expect(calculateContrastRatio(L1, L2)).toBe( + calculateContrastRatio(L2, L1), + ); + }); + + it("should handle cases where L1 is equal to L2", () => { + const L1 = 0.5; + const L2 = 0.5; + expect(calculateContrastRatio(L1, L2)).toBe(1); + }); + + it("should handle cases where L1 is close to L2", () => { + const L1 = 0.4; + const L2 = 0.41; + expect(calculateContrastRatio(L1, L2)).toBeCloseTo(1.04, 1); + }); + + it("should handle cases where L1 is much higher than L2", () => { + const L1 = 0.9; + const L2 = 0.1; + expect(calculateContrastRatio(L1, L2)).toBeCloseTo(6.33, 1); + }); + + it("should handle cases where L1 is much lower than L2", () => { + const L1 = 0.1; + const L2 = 0.9; + expect(calculateContrastRatio(L1, L2)).toBeCloseTo(6.33, 1); + }); + }); + + describe("contrastRatio", () => { + it("should calculate contrast ratio correctly for two colors", () => { + const { white, black } = testColors.rgb; + expect(contrastRatio(white.object, black.object)).toBeCloseTo(21); + }); + + it("should calculate contrast ratio correctly for black and light gray", () => { + const { black, lightgray } = testColors.rgb; + expect(contrastRatio(lightgray.object, black.object)).toBeCloseTo( + 14.02, + 1, + ); + }); + + it("should calculate contrast ratio correctly for blue and yellow", () => { + const { yellow, blue } = testColors.rgb; + expect(contrastRatio(yellow.object, blue.object)).toBeCloseTo(8.0, 1); + }); + + it("should calculate contrast ratio correctly for red and lime", () => { + const { lime, red } = testColors.rgb; + expect(contrastRatio(lime.object, red.object)).toBeCloseTo(2.91, 1); + }); + }); +}); diff --git a/test/core/colorAdjustments.test.ts b/test/core/colorAdjustments.test.ts new file mode 100644 index 0000000..3516fbe --- /dev/null +++ b/test/core/colorAdjustments.test.ts @@ -0,0 +1,93 @@ +import { + alpha, + hue, + lighten, + modBy, + saturate, +} from "../../src/core/colorAdjustments"; +import { testColors } from "../__fixtures__"; + +const hslColor = testColors.hsl; + +describe("Color Adjustment Functions", () => { + describe("modBy", () => { + it("should modify a value by the given amount", () => { + expect(modBy(50, 0.2)).toBe(60); + expect(modBy(100, -0.3)).toBe(70); + }); + + it("should clamp the result to be within 0 and the specified maximum", () => { + expect(modBy(80, 0.5)).toBe(120); + expect(modBy(80, 1)).toBe(160); + expect(modBy(50, -1)).toBe(0); + }); + + it("should handle string input for value", () => { + // @ts-expect-error Ignores since the function can actually handle this + expect(modBy("80", 0.2)).toBe(96); + }); + + it("should return the original value if amount is NaN", () => { + expect(modBy(50, Number.NaN)).toBe(50); + // @ts-expect-error Ignores for testing of invalid amount + expect(modBy(50, "invalid")).toBe(50); + }); + + it("should round the result to two decimal places if necessary", () => { + expect(modBy(33.3333, 0.1)).toBe(36.67); + }); + }); + + describe("lighten", () => { + it("should lighten an HSL color by the default amount", () => { + const lightened = lighten(hslColor.blue.object, 0.1); + expect(lightened).toEqual({ h: 240, s: 100, l: 55, a: 1 }); + }); + + it("should lighten an HSL color by a specific amount", () => { + const lightened = lighten(hslColor.blue.object, 0.3); + expect(lightened).toEqual({ h: 240, s: 100, l: 65, a: 1 }); + }); + }); + + describe("saturate", () => { + it("should adjust saturation of HSL color", () => { + const newColor = saturate(hslColor.orange.object, 0.2); + expect(newColor).toEqual({ h: 40, s: 100, l: 50, a: 1 }); + }); + + it("should clamp saturation value between 0 and 1", () => { + const color = { h: 120, s: 150, l: 50, a: 1 }; + const newColor = saturate(color, 2); + expect(newColor).toEqual({ h: 120, s: 100, l: 50, a: 1 }); + }); + }); + + describe("hue", () => { + it("should adjust hue of HSL color", () => { + const newColor = hue(hslColor.orange.object, 0.2); + expect(newColor).toEqual({ h: 48, s: 100, l: 50, a: 1 }); + }); + + it("should wrap hue value around 360 degrees", () => { + const color = { h: 350, s: 50, l: 50, a: 1 }; + const newColor = hue(color, 0.2); + expect(newColor).toEqual({ h: 360, s: 50, l: 50, a: 1 }); + }); + }); + + describe("alpha", () => { + it("should adjust alpha channel of RGB color", () => { + const color = { r: 255, g: 128, b: 64, a: 0.5 }; + const newColor = alpha(color, 0.2); + expect(newColor).toEqual({ r: 255, g: 128, b: 64, a: 0.6 }); + }); + + it("should handle optional alpha channel", () => { + const color = { r: 255, g: 128, b: 64 }; + // @ts-expect-error It expects an alpha, but as safe guard should work without + const newColor = alpha(color, 0.2); + expect(newColor).toEqual({ r: 255, g: 128, b: 64, a: 1 }); + }); + }); +}); diff --git a/test/core/colorFormatter.test.ts b/test/core/colorFormatter.test.ts new file mode 100644 index 0000000..cdb3128 --- /dev/null +++ b/test/core/colorFormatter.test.ts @@ -0,0 +1,14 @@ +import colorFormatter from "../../src/core/colorFormatter"; +import { forEachColorFormat } from "../__fixtures__"; + +describe("ColorFormatter", () => { + describe("ColorFormatter - Format Valid Color Object", () => { + forEachColorFormat( + "should format valid %s color to string", + (format, color) => { + expect(colorFormatter[format](color.object)).toBe(color.string); + }, + ["rgb", "cmyk", "hsl", "hsv"], + ); + }); +}); diff --git a/test/core/colorNormalizer.test.ts b/test/core/colorNormalizer.test.ts new file mode 100644 index 0000000..26af39f --- /dev/null +++ b/test/core/colorNormalizer.test.ts @@ -0,0 +1,149 @@ +import { + Clamp, + Round, + alpha, + degree, + eightBit, + percent, +} from "../../src/core/colorNormalizer"; + +describe("Color Normalizers", () => { + describe("Value Converters", () => { + describe("degree", () => { + it("should convert value to degree (0-360)", () => { + expect(degree(720)).toBe(360); + expect(degree(-120)).toBe(0); + expect(degree(180)).toBe(180); + }); + + it("should round value to nearest integer", () => { + expect(degree(180.5)).toBe(181); + }); + }); + + describe("percent", () => { + it("should convert value to percent (0-100)", () => { + expect(percent(200)).toBe(100); + expect(percent(-50)).toBe(0); + expect(percent(75)).toBe(75); + }); + + it("should round value to nearest integer", () => { + expect(percent(75.5)).toBe(76); + }); + }); + + describe("eightBit", () => { + it("should convert value to 8-bit integer (0-255)", () => { + expect(eightBit(512)).toBe(255); + expect(eightBit(-128)).toBe(0); + expect(eightBit(192)).toBe(192); + }); + + it("should round value to nearest integer", () => { + expect(eightBit(192.5)).toBe(193); + }); + }); + + describe("alpha", () => { + it("should convert value to alpha (0-1)", () => { + expect(alpha(2)).toBe(1); + expect(alpha(-0.5)).toBe(0); + expect(alpha(0.75)).toBe(0.75); + }); + + it("should precision value to 3 decimal places", () => { + expect(alpha(0.75321)).toBe(0.75); + }); + }); + }); + + describe("Color Object Normalizers", () => { + describe("Round", () => { + it("should round RGB values to nearest integer", () => { + const rgb = { r: 128.5, g: 64.2, b: 192.8, a: 0.5 }; + const roundedRgb = Round.rgb(rgb); + expect(roundedRgb).toEqual({ r: 129, g: 64, b: 193, a: 0.5 }); + }); + + it("should round HSL values to nearest integer", () => { + const hsl = { h: 120.5, s: 75.2, l: 50.1, a: 0.5 }; + const roundedHsl = Round.hsl(hsl); + expect(roundedHsl).toEqual({ h: 121, s: 75, l: 50, a: 0.5 }); + }); + + it("should round HSV values to nearest integer", () => { + const hsv = { h: 240.5, s: 80.2, v: 60.2, a: 0.5 }; + const roundedHsv = Round.hsv(hsv); + expect(roundedHsv).toEqual({ h: 241, s: 80, v: 60, a: 0.5 }); + }); + + it("should round CMYK values to nearest integer", () => { + const cmyk = { c: 50.5, m: 30.2, y: 20.8, k: 10.5, a: 0.5 }; + const roundedCmyk = Round.cmyk(cmyk); + expect(roundedCmyk).toEqual({ c: 51, m: 30, y: 21, k: 11, a: 0.5 }); + }); + }); + + describe("Clamp", () => { + it("should precision RGB values to 3 decimal places", () => { + const rgb = { r: 128.512, g: 64.234, b: 192.876, a: 0.512 }; + const clampedRgb = Clamp.rgb(rgb); + expect(clampedRgb).toEqual({ + r: 128.51, + g: 64.23, + b: 192.88, + a: 0.51, + }); + }); + + it("should precision HSL values to 3 decimal places", () => { + const hsl = { h: 120.512, s: 75.3, l: 51.2, a: 0.512 }; + const clampedHsl = Clamp.hsl(hsl); + expect(clampedHsl).toEqual({ h: 120.51, s: 75.3, l: 51.2, a: 0.51 }); + }); + + it("should precision HSV values to 3 decimal places", () => { + const hsv = { h: 240.512, s: 75.3, v: 51.2, a: 0.512 }; + const clampedHsv = Clamp.hsv(hsv); + expect(clampedHsv).toEqual({ h: 240.51, s: 75.3, v: 51.2, a: 0.51 }); + }); + + it("should precision CMYK values to 3 decimal places", () => { + const cmyk = { c: 50.512, m: 30.234, y: 20.876, k: 10.512, a: 0.512 }; + const clampedCmyk = Clamp.cmyk(cmyk); + expect(clampedCmyk).toEqual({ + c: 50.51, + m: 30.23, + y: 20.88, + k: 10.51, + a: 0.51, + }); + }); + + it("should clamp RGB values to valid range", () => { + const rgb = { r: 300, g: -10, b: 150, a: 2 }; + const clampedRgb = Clamp.rgb(rgb); + expect(clampedRgb).toEqual({ r: 255, g: 0, b: 150, a: 1 }); + }); + + it("should clamp HSL values to valid range", () => { + const hsl = { h: 420, s: -20, l: 10.21, a: 2 }; + const clampedHsl = Clamp.hsl(hsl); + expect(clampedHsl).toEqual({ h: 360, s: 0, l: 10.21, a: 1 }); + }); + + it("should clamp HSV values to valid range", () => { + const hsv = { h: 420, s: -20, v: 10.21, a: 2 }; + const clampedHsv = Clamp.hsv(hsv); + expect(clampedHsv).toEqual({ h: 360, s: 0, v: 10.21, a: 1 }); + }); + + it("should clamp CMYK values to valid range", () => { + const cmyk = { c: 150, m: -20, y: 50, k: 200, a: 2 }; + const clampedCmyk = Clamp.cmyk(cmyk); + expect(clampedCmyk).toEqual({ c: 100, m: 0, y: 50, k: 100, a: 1 }); + }); + }); + }); +}); diff --git a/test/core/colorParser.test.ts b/test/core/colorParser.test.ts new file mode 100644 index 0000000..7901c72 --- /dev/null +++ b/test/core/colorParser.test.ts @@ -0,0 +1,34 @@ +import { parseColor } from "../../src/core/colorParser"; +import { forEachColorFormat } from "../__fixtures__"; + +describe("parseColor Function", () => { + describe("Handling Error", () => { + it("should return null for an invalid color string", () => { + expect(parseColor("invalidcolor")).toBeNull(); + }); + + it("should return null for an empty string", () => { + expect(parseColor("")).toBeNull(); + }); + + it("should return null for undefined input", () => { + expect(parseColor()).toBeNull(); + expect(parseColor(undefined)).toBeNull(); + }); + }); + + describe("Color String Parsing", () => { + forEachColorFormat( + "should parse from a %s string", + (format, color) => { + expect(parseColor(color.string)).toEqual({ + originalInput: color.string, + isValid: true, + value: color.object, + format, + }); + }, + ["hex", "rgb", "hsl", "hsv", "cmyk"], + ); + }); +}); diff --git a/test/core/colorTypeAnalyzer.test.ts b/test/core/colorTypeAnalyzer.test.ts new file mode 100644 index 0000000..b935f45 --- /dev/null +++ b/test/core/colorTypeAnalyzer.test.ts @@ -0,0 +1,157 @@ +import { + determineColorType, + execColorStringTest, + isCmykObject, + isColorData, + isHslObject, + isHsvObject, + isRgbObject, +} from "../../src/core/colorTypeAnalyzer"; +import { forEachColorFormat, testColors } from "../__fixtures__"; + +describe("Color Type Analyzis", () => { + describe("Helper Functions", () => { + describe("isColorData", () => { + it("should return true for a valid color data object", () => { + const colorData = { format: "hex", value: "#ff0000" }; + expect(isColorData(colorData)).toBeTruthy(); + }); + + it('should return true for a color data object with "value" property', () => { + const colorData = { value: "rgb(255, 0, 0)" }; + expect(isColorData(colorData)).toBeTruthy(); + }); + + it('should return true for a color data object with "isValid" property', () => { + const colorData = { isValid: true }; + expect(isColorData(colorData)).toBeTruthy(); + }); + + it('should return true for a color data object with "originalInput" property', () => { + const colorData = { originalInput: "hsl(360, 0, 100)" }; + expect(isColorData(colorData)).toBeTruthy(); + }); + + it("should return false for an invalid color data object", () => { + const colorData = { foo: "bar" }; + expect(isColorData(colorData)).toBeFalsy(); + }); + }); + + describe("execColorStringTest", () => { + describe("Handling Error", () => { + it("should return null for an invalid color string", () => { + const result = execColorStringTest("invalidcolor"); + expect(result).toBeNull(); + }); + + it("should return null for an empty string", () => { + const result = execColorStringTest(""); + expect(result).toBeNull(); + }); + }); + + describe("Default Behavior", () => { + forEachColorFormat( + "should recognize %s color string", + (format, color) => { + color.object.a = undefined; + + const res = execColorStringTest(color.string); + + expect(res![0]).toBe(format); + expect(res![1][0]).toEqual(color.string); + }, + ["cmyk", "hex", "hsl", "hsv", "rgb"], + ); + }); + }); + }); + + describe("Color Type Identification", () => { + describe("determineColorType Function", () => { + describe("Handling Error", () => { + it("should return undefined for an invalid color object", () => { + const invalidColor = { x: 10, y: 20 }; + expect(determineColorType(invalidColor)).toBeUndefined(); + }); + + it("should return undefined for null or undefined input", () => { + // @ts-expect-error + expect(determineColorType(null)).toBeUndefined(); + expect(determineColorType(undefined)).toBeUndefined(); + }); + }); + + describe("Default Behavior", () => { + forEachColorFormat( + "should identify %s color object", + (format, color) => { + expect(determineColorType(color.object)).toBe(format); + }, + ["rgb", "hsl", "hsv", "cmyk"], + ); + }); + }); + + describe("isRgbObject Function", () => { + it("should return true for valid RGB color objects", () => { + expect(isRgbObject(testColors.rgb.red.object)).toBeTruthy(); + expect( + isRgbObject(testColors.withAlpha(testColors.rgb.red.object)), + ).toBeTruthy(); + }); + + it("should return false for invalid RGB color objects", () => { + expect(isRgbObject({ r: 255, g: 0 })).toBeFalsy(); + expect(isRgbObject({ r: "255", g: 0, b: 0 })).toBeFalsy(); + expect(isRgbObject({ h: 0, s: 100, l: 50 })).toBeFalsy(); + }); + }); + + describe("isHslObject Function", () => { + it("should return true for valid HSL color objects", () => { + expect(isHslObject(testColors.hsl.red.object)).toBeTruthy(); + expect( + isHslObject(testColors.withAlpha(testColors.hsl.red.object)), + ).toBeTruthy(); + }); + + it("should return false for invalid HSL color objects", () => { + expect(isHslObject({ h: 255, s: 0 })).toBeFalsy(); + expect(isHslObject({ h: "255", s: 0, l: 0 })).toBeFalsy(); + expect(isHslObject({ r: 0, g: 100, b: 50 })).toBeFalsy(); + }); + }); + + describe("isHsvObject Function", () => { + it("should return true for valid HSV color objects", () => { + expect(isHsvObject(testColors.hsv.red.object)).toBeTruthy(); + expect( + isHsvObject(testColors.withAlpha(testColors.hsv.red.object)), + ).toBeTruthy(); + }); + + it("should return false for invalid HSV color objects", () => { + expect(isHsvObject({ h: 255, s: 0 })).toBeFalsy(); + expect(isHsvObject({ h: "255", s: 0, v: 0 })).toBeFalsy(); + expect(isHsvObject({ r: 0, g: 100, b: 50 })).toBeFalsy(); + }); + }); + + describe("isCmykObject Function", () => { + it("should return true for valid CMYK color objects", () => { + expect(isCmykObject(testColors.cmyk.aqua.object)).toBeTruthy(); + expect( + isCmykObject(testColors.withAlpha(testColors.cmyk.aqua.object)), + ).toBeTruthy(); + }); + + it("should return false for invalid CMYK color objects", () => { + expect(isCmykObject({ c: 0, m: 100, y: 100 })).toBeFalsy(); + expect(isCmykObject({ c: "0", m: 100, y: 100, k: 0 })).toBeFalsy(); + expect(isCmykObject({ r: 0, g: 100, b: 50 })).toBeFalsy(); + }); + }); + }); +}); diff --git a/test/core/conversionHelpers.test.ts b/test/core/conversionHelpers.test.ts new file mode 100644 index 0000000..23599b8 --- /dev/null +++ b/test/core/conversionHelpers.test.ts @@ -0,0 +1,96 @@ +import { + computeColorDistance, + computeHsvHue, + isRgbShortanable, +} from "../../src/core/conversionHelpers"; +import { testColors } from "../__fixtures__"; + +const { red, brown, blue, aqua, lime, white, black } = testColors.rgb; + +describe("Conversion Helper Functions", () => { + describe("Color String Shortening", () => { + describe("isRgbShortanable Function", () => { + it("should return false for non-shortenable RGB colors", () => { + expect(isRgbShortanable(128, 128, 128)).toBeFalsy(); + expect(isRgbShortanable(34, 128, 17)).toBeFalsy(); + expect(isRgbShortanable(17, 34, 170, 150)).toBeFalsy(); + }); + + it("should return true for shortenable RGB colors", () => { + expect(isRgbShortanable(34, 51, 17)).toBeTruthy(); + expect(isRgbShortanable(0, 170, 187)).toBeTruthy(); + expect(isRgbShortanable(255, 0, 0)).toBeTruthy(); + expect(isRgbShortanable(0, 255, 0)).toBeTruthy(); + expect(isRgbShortanable(0, 0, 255)).toBeTruthy(); + expect(isRgbShortanable(17, 34, 170, 153)).toBeTruthy(); + }); + + it("should handle the default alpha value of 255", () => { + expect(isRgbShortanable(34, 51, 17)).toBeTruthy(); + }); + }); + }); + + describe("Color Distance Calculation", () => { + describe("computeColorDistance function", () => { + it("should calculate the distance between two identical colors as 0", () => { + expect(computeColorDistance(red.object, red.object)).toBe(0); + }); + + it("should calculate the distance between black and white", () => { + // Euclidean distance in 3D space: sqrt((255-0)^2 + (255-0)^2 + (255-0)^2) = sqrt(3*255^2) = 441.67 + expect(computeColorDistance(black.object, white.object)).toBeCloseTo( + 441.67, + 2, + ); + }); + + it("should calculate the distance between two similar colors", () => { + expect(computeColorDistance(red.object, brown.object)).toBeCloseTo( + 107.83, + 1, + ); + }); + + it("should handle colors with alpha values (ignoring alpha)", () => { + const redWithAlpha = { ...red.object, a: 0.65 }; + expect(computeColorDistance(red.object, redWithAlpha)).toBe(0); + }); + }); + }); + + describe("HSV Hue Calculation", () => { + describe("computeHsvHue function", () => { + it("should return 0 when segment is 0", () => { + const params = { segment: 0, maxRgb: 255, minRgb: 255 }; + expect(computeHsvHue(white.object, params)).toBe(0); + }); + + it("should calculate hue correctly when red is max", () => { + const params = { segment: 255, maxRgb: 255, minRgb: 0 }; + expect(computeHsvHue(red.object, params)).toBe(0); + }); + + it("should calculate hue correctly when green is max", () => { + const params = { segment: 255, maxRgb: 255, minRgb: 0 }; + expect(computeHsvHue(lime.object, params)).toBe(120); + }); + + it("should calculate hue correctly when blue is max", () => { + const params = { segment: 255, maxRgb: 255, minRgb: 0 }; + expect(computeHsvHue(blue.object, params)).toBe(240); + }); + + it("should handle intermediate colors", () => { + const params = { segment: 128, maxRgb: 128, minRgb: 0 }; + expect(computeHsvHue(brown.object, params)).toBeCloseTo(297.65, 1); + }); + + it("should normalize negative hue values", () => { + const params = { segment: 255, maxRgb: 255, minRgb: 0 }; + const expectedHue = 180; + expect(computeHsvHue(aqua.object, params)).toBe(expectedHue); + }); + }); + }); +}); diff --git a/test/core/inputSerializer.test.ts b/test/core/inputSerializer.test.ts new file mode 100644 index 0000000..10cef6f --- /dev/null +++ b/test/core/inputSerializer.test.ts @@ -0,0 +1,92 @@ +import { + fallbackColor, + fromObject, + processColorInput, +} from "../../src/core/inputSerializer"; +import type { AnyObject } from "../../src/types"; +import { forEachColorFormat, testColors } from "../__fixtures__"; + +describe("Color Input Processing", () => { + describe("fromObject Helper", () => { + describe("Error Handling", () => { + it("should throw error for null or undefined input", () => { + expect(() => fromObject(null)).toThrow(); + expect(() => fromObject(undefined)).toThrow(); + }); + + it("should throw error for unsupported color types", () => { + const input: AnyObject = { x: 100, y: 200 }; + expect(() => fromObject(input)).toThrow(); + }); + }); + }); + + describe("processColorInput Function", () => { + describe("Error Handling", () => { + it("should throw TypeError for invalid color strings", () => { + const input = "invalid color"; + expect(() => processColorInput(input)).toThrow(TypeError); + }); + + it("should throw TypeError for invalid color objects", () => { + const input: AnyObject = { x: 100, y: 200 }; + expect(() => processColorInput(input)).toThrow(TypeError); + }); + }); + + describe("Default Behavior", () => { + it("should return fallbackColor for undefined input", () => { + expect(processColorInput(undefined)).toEqual(fallbackColor); + }); + + it("should handle ColorData input and return the same ColorData", () => { + const input = { + isValid: true, + format: "rgb", + value: testColors.rgb.white.object, + }; + + const expectedOutput = { + originalInput: input.value, + isValid: true, + value: input.value, + format: input.format, + }; + + expect(processColorInput(input)).toEqual(expectedOutput); + }); + }); + + describe("Color Conversions", () => { + describe("Object Type Conversions", () => { + forEachColorFormat( + "should handle valid %s color object", + (format, color, expectedRgb) => { + const result = processColorInput(color.object); + + expect(result.format).toBe(format); + expect(result.isValid).toBeTruthy(); + expect(result.value).toEqual(expectedRgb); + expect(result.originalInput).toEqual(color.object); + }, + ["rgb", "hsl", "hsv", "cmyk"], + ); + }); + + describe("String Type Conversions", () => { + forEachColorFormat( + "should handle valid %s color strings", + (format, color, expectedRgb) => { + const result = processColorInput(color.string); + + expect(result.format).toBe(format); + expect(result.isValid).toBeTruthy(); + expect(result.value).toEqual(expectedRgb); + expect(result.originalInput).toEqual(color.string); + }, + ["hex", "rgb", "hsl", "hsv", "cmyk"], + ); + }); + }); + }); +}); diff --git a/test/core/pluginValidation.test.ts b/test/core/pluginValidation.test.ts new file mode 100644 index 0000000..045335a --- /dev/null +++ b/test/core/pluginValidation.test.ts @@ -0,0 +1,24 @@ +import { isValidPlugin } from "../../src/core/pluginValidation"; + +describe("Plugin Validation", () => { + describe("isValidPlugin function", () => { + it("should correctly identify an valid plugin", () => { + const plugins = { + myPlugin: function () { + return this.object; + }, + }; + + expect(isValidPlugin(plugins, "myPlugin")).toBeTruthy(); + }); + + it("should correctly identify an invalid plugin", () => { + const plugins = { + notFunction: "hello", + }; + + // @ts-expect-error should report error for invalid type + expect(() => isValidPlugin(plugins, "notFunction")).toThrow(); + }); + }); +}); diff --git a/test/dye.test.ts b/test/dye.test.ts new file mode 100644 index 0000000..26e1365 --- /dev/null +++ b/test/dye.test.ts @@ -0,0 +1,161 @@ +import { dye } from "../src/dye"; + +import { forEachColorFormat, forEachMethod, testColors } from "./__fixtures__"; + +describe("dye Function", () => { + describe("Error Handling", () => { + it("should throw an error for invalid input", () => { + expect(() => dye("invalid color")).toThrow(TypeError); + // @ts-expect-error Should ignore error for invalid color format + expect(() => dye({ x: 10, y: 20 })).toThrow(TypeError); + }); + }); + + describe("Color Instance Properties and Methods", () => { + it("should calculate luminance correctly", () => { + const color = dye("#ff0000"); + expect(color.luminance).toBeCloseTo(0.2126); + }); + + describe("Object Representations (Conversions)", () => { + forEachMethod( + "should make the Color.%s() getter public", + method => { + const color = testColors[method].white; + const result = dye(color.string); + + expect(result[method]).toEqual(color.object); + }, + ["rgb", "hsl", "hsv", "cmyk"], + ); + }); + + describe("String Representations (Conversions)", () => { + const methods = { + toRgb: "rgb", + toHsl: "hsl", + toHsv: "hsv", + toCmyk: "cmyk", + }; + forEachMethod( + "should make the Color.%s() getter public", + method => { + const color = testColors[methods[method]].white; + const result = dye(color.object); + + expect(result[method]()).toEqual(color.string); + }, + ["toRgb", "toHsl", "toHsv", "toCmyk"], + ); + }); + + describe("Named Colors (Conversions)", () => { + forEachColorFormat( + "should convert from %s to named color", + (_, color) => { + const result = dye(color.string); + expect(result.toNamed()).toBe(color.colorName); + }, + ["hex", "rgb", "hsl", "hsv", "cmyk"], + ); + }); + + describe("Adjustments Methods", () => { + forEachMethod( + "should make the Color.%s() method public", + method => { + const color = dye("#fff"); + expect(color).toHaveProperty(method); + }, + [ + "lighten", + "darken", + "saturate", + "desaturate", + "hue", + "alpha", + "contrastRatio", + ], + ); + }); + }); + + describe("Color Instance Creation", () => { + describe("Object Type", () => { + forEachColorFormat( + "should create a Color instance from a %s string", + (format, color, expectedRgb) => { + const instance = dye(color.object); + + expect(instance.isValid).toBeTruthy(); + expect(instance.format).toBe(format); + expect(instance.originalInput).toBe(color.object); + expect(instance.value).toEqual(expectedRgb); + }, + ["rgb", "hsl", "hsv", "cmyk"], + ); + }); + + describe("String Type", () => { + forEachColorFormat( + "should create a Color instance from a %s string", + (format, color, expectedRgb) => { + const instance = dye(color.string); + + expect(instance.isValid).toBeTruthy(); + expect(instance.format).toBe(format); + expect(instance.originalInput).toBe(color.string); + expect(instance.value).toEqual(expectedRgb); + }, + ["hex", "rgb", "hsl", "hsv", "cmyk"], + ); + }); + }); + + describe("Plugin Functionality", () => { + forEachColorFormat( + "should add a plugin for a %s string Color instance", + (_, color) => { + const result = dye(color.string, { + plugins: { + getHue: function () { + return this.hsl.h; + }, + }, + }); + + expect(result).toHaveProperty("getHue"); + expect(typeof result.getHue).toBe("function"); + }, + ["hex", "rgb", "hsl", "hsv", "cmyk"], + ); + + it("should allow the plugin method to access the Colorus instance data", () => { + const color = dye("rgb(20, 120, 80)", { + plugins: { + getHue: function () { + return this.hsl.h; + }, + }, + }); + + expect(color.getHue()).toBe(156); + }); + + it("should handle multiple plugin methods", () => { + const color = dye("#FF0000", { + plugins: { + getHue: function () { + return this.hsl.h; + }, + isRed: function () { + return this.rgb.r === 255 && this.rgb.g === 0 && this.rgb.b === 0; + }, + }, + }); + + expect(color.getHue()).toBe(0); + expect(color.isRed()).toBeTruthy(); + }); + }); +}); diff --git a/test/helpers.spec.js b/test/helpers.spec.js deleted file mode 100644 index 6b25d58..0000000 --- a/test/helpers.spec.js +++ /dev/null @@ -1,141 +0,0 @@ -import { hexString, padString, precision, utmost } from '../src/helpers' - -describe('utmost', () => { - it('returns the input value when it is less than the maximum', () => { - const inputValue = 50 - const maxValue = 100 - - expect(utmost(inputValue, maxValue)).toBe(inputValue) - }) - - it('returns the maximum value when the input value equals the maximum', () => { - const inputValue = 100 - const maxValue = 100 - - expect(utmost(inputValue, maxValue)).toBe(maxValue) - }) - - it('returns the maximum value when the input value is greater than the maximum', () => { - const inputValue = 150 - const maxValue = 100 - - expect(utmost(inputValue, maxValue)).toBe(maxValue) - }) - - it('returns 0 when the input value is negative', () => { - const inputValue = -50 - const maxValue = 100 - - expect(utmost(inputValue, maxValue)).toBe(0) - }) - - it('returns 0 when the input value is 0', () => { - const inputValue = 0 - const maxValue = 100 - - expect(utmost(inputValue, maxValue)).toBe(0) - }) - - it('returns the input value when it is slightly greater than 0', () => { - const inputValue = 0.01 - const maxValue = 100 - - expect(utmost(inputValue, maxValue)).toBeCloseTo(inputValue) - }) -}) - -describe('hexString', () => { - const defaultMinSize = 6 - const validInputRgb = 42 - - it('converts the input to a HEX string with radix 16', () => { - const input = validInputRgb - const minSize = defaultMinSize - - const result = hexString(input, minSize) - - expect(result.length).toBe(minSize) - expect(Number.isNaN(parseInt(result, 16))).toBe(false) - }) - - it('returns the correct HEX string for a single-channel RGB input', () => { - const input = 10 - const minSize = 2 - - const result = hexString(input, minSize) - - expect(result).toBe('0A') - }) - - it('returns the correct HEX string for a three-channel RGB input', () => { - const input = 12345 - const minSize = 5 - - const result = hexString(input, minSize) - - expect(result).toBe('03039') - }) - - it('pads the HEX string with leading zeros if the input is smaller than the minSize', () => { - const input = 10 - const minSize = 4 - - const result = hexString(input, minSize) - - expect(result).toBe('000A') - }) -}) - -describe('padString', () => { - test('pads single-character minified HEX strings to 6 characters', () => { - const input = 'eee' - const output = padString(input) - expect(output).toBe('eeeeee') - }) - - test('pads double-character minified HEX strings to 8 characters', () => { - const input = 'e3ef' - const output = padString(input) - expect(output).toBe('ee33eeff') - }) - - test('handles max-length input (6 characters) without padding', () => { - const input = '00ff00' - const output = padString(input) - expect(output).toBe('00ff00') - }) - - test('handles max-length input + 1 (7 characters) without padding', () => { - const input = '00ff000' - const output = padString(input) - expect(output).toBe('00ff000') - }) -}) - -describe('precision()', () => { - test('Formats positive numbers with specified precision', () => { - expect(precision(3.14159)).toBe(3.14) - }) - - test('Formats negative numbers with specified precision', () => { - expect(precision(-3.14159)).toBe(-3.14) - expect(precision(-2.71828)).toBe(-2.72) - expect(precision(-1.61803)).toBe(-1.62) - }) - - test('Preserves integer values without decimal part', () => { - expect(precision(123)).toBe(123) - expect(precision(456)).toBe(456) - expect(precision(789)).toBe(789) - }) - - test('Allows maximum precision of 20 decimal places', () => { - expect(precision(0.000000000000000012345)).toBe(0) - expect(precision(0.1234567890123456789)).toBe(0.12) - }) - - test('Uses default max precision of 2 if max parameter is undefined', () => { - expect(precision(3.14159)).toBeCloseTo(3.14) - expect(precision(-2.71828)).toBeCloseTo(-2.72) - }) -}) diff --git a/test/helpers.test.ts b/test/helpers.test.ts new file mode 100644 index 0000000..f7a4e0d --- /dev/null +++ b/test/helpers.test.ts @@ -0,0 +1,80 @@ +import { + hexString, + isObject, + nan, + padString, + precision, + utmost, +} from "../src/helpers"; + +describe("Helper Functions", () => { + describe("Number Utilities", () => { + describe("utmost", () => { + it("should clamp values within the specified range", () => { + expect(utmost(50, 100)).toBe(50); + expect(utmost(150, 100)).toBe(100); + expect(utmost(-50, 100)).toBe(0); + expect(utmost("75", 100)).toBe(75); + expect(utmost("120", 100)).toBe(100); + }); + }); + + describe("precision", () => { + it("should round to two decimal places", () => { + expect(precision(3.1419)).toBe(3.14); + expect(precision(12.3456)).toBe(12.35); + expect(precision(10)).toBe(10); + }); + }); + }); + + describe("String Utilities", () => { + describe("hexString", () => { + it("should convert numbers to uppercase hex strings with padding", () => { + expect(hexString(255, 2)).toBe("FF"); + expect(hexString(255, 4)).toBe("00FF"); + expect(hexString(4095, 3)).toBe("FFF"); + expect(hexString(4095, 6)).toBe("000FFF"); + }); + }); + + describe("padString", () => { + it("should pad short hex strings", () => { + expect(padString("abc")).toBe("aabbcc"); + expect(padString("f0f")).toBe("ff00ff"); + expect(padString("123a")).toBe("112233aa"); + }); + + it("should not pad long hex strings", () => { + expect(padString("abcdef")).toBe("abcdef"); + expect(padString("12345678")).toBe("12345678"); + }); + }); + }); + + describe("Type Checks", () => { + describe("nan", () => { + it("should correctly identify NaN values", () => { + expect(nan(Number.NaN)).toBeTruthy(); + expect(nan("not a number")).toBeTruthy(); + expect(nan(Number.POSITIVE_INFINITY)).toBeTruthy(); + expect(nan(Number.NEGATIVE_INFINITY)).toBeTruthy(); + expect(nan(123)).toBeFalsy(); + expect(nan(0)).toBeFalsy(); + expect(nan(3.14)).toBeFalsy(); + }); + }); + + describe("isObject", () => { + it("should correctly identify objects", () => { + expect(isObject({})).toBeTruthy(); + expect(isObject({ a: 1, b: "hello" })).toBeTruthy(); + expect(isObject([])).toBeFalsy(); + expect(isObject(null)).toBeFalsy(); + expect(isObject(undefined)).toBeFalsy(); + expect(isObject("string")).toBeFalsy(); + expect(isObject(123)).toBeFalsy(); + }); + }); + }); +}); diff --git a/test/isValidColor.test.ts b/test/isValidColor.test.ts new file mode 100644 index 0000000..ea4d0cd --- /dev/null +++ b/test/isValidColor.test.ts @@ -0,0 +1,40 @@ +import { isValidColor } from "../src/isValidColor"; +import { forEachColorFormat } from "./__fixtures__"; + +describe("isValidColor", () => { + it("should return null for an invalid color object", () => { + expect(isValidColor({ x: 10, y: 20 })).toBeNull(); + }); + + it("should return null for an invalid color string", () => { + expect(isValidColor("invalidcolor")).toBeNull(); + }); + + it("should return null for an empty string", () => { + expect(isValidColor("")).toBeNull(); + }); + + it("should return null for undefined", () => { + expect(isValidColor(undefined)).toBeNull(); + }); + + it("should return null for null", () => { + expect(isValidColor(null)).toBeNull(); + }); + + describe("Validation - Color String", () => { + forEachColorFormat( + "should parse from a %s string", + (format, color) => expect(isValidColor(color.string)).toBe(format), + ["hex", "rgb", "hsl", "hsv", "cmyk"], + ); + }); + + describe("Validation - Color Object", () => { + forEachColorFormat( + "should parse from a %s string", + (format, color) => expect(isValidColor(color.object)).toBe(format), + ["rgb", "hsl", "hsv", "cmyk"], + ); + }); +}); diff --git a/test/main.spec.js b/test/main.spec.js deleted file mode 100644 index a640eb6..0000000 --- a/test/main.spec.js +++ /dev/null @@ -1,137 +0,0 @@ -import { Colorus } from '../src/main' - -describe('Plugin Functionality', () => { - it('should add a plugin method to the Colorus instance', () => { - const color = new Colorus('#333', { - plugins: { - getHue: function () { - return this.hsl.h - } - } - }) - - expect(color).toHaveProperty('getHue') - expect(typeof color.getHue).toBe('function') - }) - - it('should allow the plugin method to access the Colorus instance data', () => { - const color = new Colorus('rgb(20, 120, 80)', { - plugins: { - getHue: function () { - return this.hsl.h - } - } - }) - - expect(color.getHue()).toBe(156) - }) - - it('should handle multiple plugin methods', () => { - const color = new Colorus('#FF0000', { - plugins: { - getHue: function () { - return this.hsl.h - }, - isRed: function () { - return this.rgb.r === 255 && this.rgb.g === 0 && this.rgb.b === 0 - } - } - }) - - expect(color.getHue()).toBe(0) - expect(color.isRed()).toBe(true) - }) -}) - -describe('Colorus.darken()', () => { - it('darkens by default amount', () => { - expect(new Colorus('#333').darken().toHex()).toBe('#2E2E2E') - }) - - it('darkens by a specific amount', () => { - expect(new Colorus('#333').darken(0.2).toHex()).toBe('#292929') - }) - - it('darkens to max value from current lightness value', () => { - expect(new Colorus('#333').darken(1).toHex()).toBe('#000000') - }) - - it('darkens by a specific amount', () => { - expect(new Colorus('#333').darken(0.2).toHex()).toBe('#292929') - }) - - it('darkening of a light color', () => { - expect(new Colorus('#FFF').darken().toHex()).toBe('#E6E6E6') - }) - - it('darkening by a large amount', () => { - expect(new Colorus('#666').darken(0.6).toHex()).toBe('#292929') - }) -}) - -describe('Colorus.desaturate()', () => { - it('desaturates by default amount', () => { - expect(new Colorus('#3646d1').desaturate().toHex()).toBe('#3E4CC9') - }) - - it('desaturates by a specific amount', () => { - expect(new Colorus('#3646d1').desaturate(0.2).toHex()).toBe('#4652C1') - }) - - it('desaturates to max value from current lightness value', () => { - expect(new Colorus('#3646d1').desaturate(1).toHex()).toBe('#848484') - }) - - it('desaturates by a specific amount', () => { - expect(new Colorus('#3646d1').desaturate(0.2).toHex()).toBe('#4652C1') - }) - - it('desaturating of a light color', () => { - expect(new Colorus('#FFF').desaturate().toHex()).toBe('#FFFFFF') - }) - - it('desaturating by a large amount', () => { - expect(new Colorus('#3646d1').desaturate(0.8).toHex()).toBe('#747793') - }) -}) - -describe('Colorus.test()', () => { - test('should return "hex" for valid hex color input', () => { - expect(Colorus.test('#F33')).toBe('hex') - expect(Colorus.test('#FF0000')).toBe('hex') - expect(Colorus.test('#00ff00')).toBe('hex') - }) - - test('should return "rgb" for valid RGB color object input', () => { - expect(Colorus.test({ r: 255, g: 0, b: 0 })).toBe('rgb') - expect(Colorus.test({ r: 0, g: 255, b: 0 })).toBe('rgb') - expect(Colorus.test({ r: 0, g: 0, b: 255 })).toBe('rgb') - }) - - test('should return "hsl" for valid HSL color object input', () => { - expect(Colorus.test({ h: 0, s: 100, l: 50 })).toBe('hsl') - expect(Colorus.test({ h: 240, s: 100, l: 50 })).toBe('hsl') - }) - - test('should return "hsv" for valid HSV color object input', () => { - expect(Colorus.test({ h: 0, s: 100, v: 100 })).toBe('hsv') - expect(Colorus.test({ h: 240, s: 100, v: 100 })).toBe('hsv') - }) - - test('should return "cmyk" for valid CMYK color object input', () => { - expect(Colorus.test({ c: 0, m: 100, y: 100, k: 0 })).toBe('cmyk') - expect(Colorus.test({ c: 0, m: 0, y: 0, k: 100 })).toBe('cmyk') - }) - - test('should return null for invalid color input', () => { - expect(Colorus.test('invalid')).toBeNull() - expect(Colorus.test(null)).toBeNull() - expect(Colorus.test(undefined)).toBeNull() - }) -}) - -describe('Colorus.invert()', () => { - test('should invert colors correctly', () => { - expect(new Colorus('crimson').invert().toRgb()).toBe('rgb(35, 235, 195)') - }) -}) diff --git a/test/serializer.spec.js b/test/serializer.spec.js deleted file mode 100644 index 5571c96..0000000 --- a/test/serializer.spec.js +++ /dev/null @@ -1,228 +0,0 @@ -import { parse, fromObject, determineColorType, fromUserInput } from '../src/serialize' - -describe('determineColorType function', () => { - it('should return "rgb" for a valid RGB color object', () => { - const colorObject = { r: 255, g: 0, b: 128 } - expect(determineColorType(colorObject)).toBe('rgb') - }) - - it('should return "hsl" for a valid HSL color object', () => { - const colorObject = { h: 180, s: 50, l: 50 } - expect(determineColorType(colorObject)).toBe('hsl') - }) - - it('should return "hsv" for a valid HSV color object', () => { - const colorObject = { h: 240, s: 100, v: 100 } - expect(determineColorType(colorObject)).toBe('hsv') - }) - - it('should return "cmyk" for a valid CMYK color object', () => { - const colorObject = { c: 0, m: 100, y: 100, k: 0 } - expect(determineColorType(colorObject)).toBe('cmyk') - }) - - it('should return undefined for an invalid color object', () => { - const colorObject = { invalidProp: 'invalidValue' } - expect(determineColorType(colorObject)).toBeUndefined() - }) - - it('should return undefined for a null color object', () => { - const colorObject = null - expect(determineColorType(colorObject)).toBeUndefined() - }) - - it('should return undefined for an undefined color object', () => { - const colorObject = undefined - expect(determineColorType(colorObject)).toBeUndefined() - }) -}) - -describe('fromObject function', () => { - it('should return the input object unchanged if skipSerialization is true', () => { - const input = { colorType: 'rgb', colorObject: { r: 255, g: 0, b: 128 } } - const result = fromObject(input, true) - expect(result).toEqual(input) - }) - - it('should serialize RGB color object if skipSerialization is false', () => { - const input = { colorObject: { r: 255, g: 0, b: 128 } } - const expectedOutput = { colorType: 'rgb', colorObject: { r: 255, g: 0, b: 128, a: 1 } } - const result = fromObject(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should serialize HSL color object if skipSerialization is false', () => { - const input = { colorObject: { h: 360, s: 0, l: 100, a: 1 } } - const expectedOutput = { colorType: 'hsl', colorObject: { r: 255, g: 255, b: 255, a: 1 } } - const result = fromObject(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should serialize HSV color object if skipSerialization is false', () => { - const input = { colorObject: { h: 360, s: 0, v: 100, a: 1 } } - const expectedOutput = { colorType: 'hsv', colorObject: { r: 255, g: 255, b: 255, a: 1 } } - const result = fromObject(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should serialize CMYK color object if skipSerialization is false', () => { - const input = { colorObject: { c: 100, m: 0, y: 0, k: 0, a: 1 } } - const expectedOutput = { colorType: 'cmyk', colorObject: { r: 0, g: 255, b: 255, a: 1 } } - const result = fromObject(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should determine type from colorObject if input colorType is not recognized', () => { - const input = { colorType: 'invalid', colorObject: { r: 255, g: 0, b: 128 } } - const fallbackColor = { colorType: 'rgb', colorObject: { r: 255, g: 0, b: 128, a: 1 } } - const result = fromObject(input) - expect(result.colorType).toBe(fallbackColor.colorType) - expect(result.colorObject).toEqual(fallbackColor.colorObject) - }) - - it('should return fallback color if input object is undefined', () => { - const result = fromObject(undefined) - const fallbackColor = { colorType: undefined, colorObject: { r: 0, g: 0, b: 0, a: 1 } } - expect(result.colorType).toBe(fallbackColor.colorType) - expect(result.colorObject).toEqual(fallbackColor.colorObject) - }) -}) - -describe('parse function', () => { - it('should parse RGB color string', () => { - const input = 'rgb(255, 0, 128)' - const expectedOutput = { colorType: 'rgb', colorObject: { r: 255, g: 0, b: 128, a: 1 } } - const result = parse(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse RGBA color string', () => { - const input = 'rgba(255, 0, 128, 0.5)' - const expectedOutput = { colorType: 'rgb', colorObject: { r: 255, g: 0, b: 128, a: 0.5 } } - const result = parse(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse HSL color string', () => { - const input = 'hsl(360, 100%, 50%)' - const expectedOutput = { colorType: 'hsl', colorObject: { h: 360, s: 100, l: 50, a: 1 } } - const result = parse(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse HSLA color string', () => { - const input = 'hsla(360, 100%, 50%, 0.5)' - const expectedOutput = { colorType: 'hsl', colorObject: { h: 360, s: 100, l: 50, a: 0.5 } } - const result = parse(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse HSV color string', () => { - const input = 'hsv(120, 100%, 100%)' - const expectedOutput = { colorType: 'hsv', colorObject: { h: 120, s: 100, v: 100, a: 1 } } - const result = parse(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse HSVA color string', () => { - const input = 'hsva(120, 100%, 100%, 0.5)' - const expectedOutput = { colorType: 'hsv', colorObject: { h: 120, s: 100, v: 100, a: 0.5 } } - const result = parse(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse CMYK color string', () => { - const input = 'cmyk(100%, 0%, 0%, 0%)' - const expectedOutput = { colorType: 'cmyk', colorObject: { c: 100, m: 0, y: 0, k: 0, a: 1 } } - const result = parse(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse CMYKA color string', () => { - const input = 'cmyka(100%, 0%, 0%, 0%, 0.5)' - const expectedOutput = { colorType: 'cmyk', colorObject: { c: 100, m: 0, y: 0, k: 0, a: 0.5 } } - const result = parse(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse CSS named color string', () => { - const input = 'red' - const expectedOutput = { colorType: 'named', colorObject: { r: 255, g: 0, b: 0, a: 1 } } - const result = parse(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should return null for invalid color string', () => { - const input = 'invalid color string' - const result = parse(input) - expect(result).toBeNull() - }) - - it('should return only colorType when skipParsing is true', () => { - const input = 'rgb(255, 0, 128)' - const result = parse(input, true) - expect(result.colorType).toBe('rgb') - expect(result.colorObject).toBeUndefined() - }) -}) - -describe('fromUserInput function', () => { - it('should return fallback color for undefined input', () => { - const result = fromUserInput(undefined) - const fallbackColor = { colorType: undefined, colorObject: { r: 0, g: 0, b: 0, a: 1 } } - expect(result.colorType).toBe(fallbackColor.colorType) - expect(result.colorObject).toEqual(fallbackColor.colorObject) - }) - - it('should parse and serialize RGB color string input', () => { - const input = 'rgb(255, 0, 128)' - const expectedOutput = { colorType: 'rgb', colorObject: { r: 255, g: 0, b: 128, a: 1 } } - const result = fromUserInput(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse and serialize CSS named color string input', () => { - const input = 'aliceblue' - const expectedOutput = { colorType: 'named', colorObject: { r: 240, g: 248, b: 255, a: 1 } } - const result = fromUserInput(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should parse and serialize color object input', () => { - const input = { r: 255, g: 0, b: 128 } - const expectedOutput = { colorType: 'rgb', colorObject: { r: 255, g: 0, b: 128, a: 1 } } - const result = fromUserInput(input) - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toEqual(expectedOutput.colorObject) - }) - - it('should throw TypeError for invalid input', () => { - const input = 123 // Invalid input - expect(() => { - fromUserInput(input) - }).toThrow(TypeError) - }) - - it('should only perform color analysis when analytical option is true', () => { - const input = 'rgb(255, 0, 128)' - const result = fromUserInput(input, { analytical: true }) - const expectedOutput = { colorType: 'rgb', colorObject: undefined } - expect(result.colorType).toBe(expectedOutput.colorType) - expect(result.colorObject).toBe(expectedOutput.colorObject) - }) -}) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..abf9118 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +// This tsconfig.json file defines the TypeScript compiler options for the project. +// It ensures type safety, generates declaration files, and configures the output for seamless integration with the Rollup build process. + +// For detailed information on TypeScript compiler options, refer to: +// https://www.typescriptlang.org/tsconfig + +{ + "compilerOptions": { + "declaration": true, // Generate .d.ts declaration files for better tooling and type safety. + "declarationDir": "build/@types/", // Place declaration files in this directory. + "emitDeclarationOnly": false, // Emit both JavaScript and declaration files. + "declarationMap": false, // Don't generate source maps for declaration files. + "rootDir": "src", // Specify the root directory for source files. + "outDir": "build", // Output compiled JavaScript files to this directory. + "moduleResolution": "node", // Use Node.js' module resolution strategy. + "esModuleInterop": true, // Enables interoperability between CommonJS and ES Modules. + "verbatimModuleSyntax": true, // Preserve 'import' and 'export' statements in the output. + "target": "esnext", // Compile to the latest JavaScript version. + "module": "esnext", // Use the latest ECMAScript module syntax. + "strict": true, // Enable all strict type-checking options. + "composite": false // Don't enable project references for incremental builds. + }, + "include": ["src/**/*.ts"], // Include all TypeScript files within the 'src' directory and its subdirectories. + "exclude": ["node_modules", "dist"] // Exclude the 'node_modules' and 'dist' directories from compilation. +}