From e27e8362f9cf83b4a9ad5f4c3a2a31c020ef3c1b Mon Sep 17 00:00:00 2001 From: AnSq Date: Thu, 6 Aug 2026 08:58:27 -0700 Subject: [PATCH 1/3] Use ESLint and Stylelint to check for potential errors and enforce a consistent coding style * ESLint checks JS, JSON, and some CSS * Stylelint checks CSS * Stylistic plugins for both enforce coding style * Adds GitHub workflow to run checks on push and PR * Adds pre-commit hook to run checks that devs can install * Update CONTRIBUTING.md --- .gitattributes | 2 + .github/workflows/lint.yml | 32 + .gitignore | 3 + CONTRIBUTING.md | 9 + eslint.config.js | 134 ++ package-lock.json | 2744 ++++++++++++++++++++++++++++--- package.json | 14 +- pre-commit | 50 + sources/css/critical.css | 106 +- sources/css/style.css | 98 +- sources/js/app.js | 237 +-- sources/js/constants.js | 4 +- sources/js/functions.js | 43 +- sources/js/icons.js | 12 +- sources/js/moreInfo.js | 6 +- sources/tests/app.test.js | 10 +- sources/tests/functions.test.js | 10 +- sources/tests/tasks.test.js | 18 +- sources/tests/version.test.js | 2 +- stylelint.config.mjs | 45 + vite.config.js | 8 +- 21 files changed, 3098 insertions(+), 489 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 eslint.config.js create mode 100644 pre-commit create mode 100644 stylelint.config.mjs diff --git a/.gitattributes b/.gitattributes index dfe0770..903d9d2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,4 @@ # Auto detect text files and perform LF normalization * text=auto + +pre-commit eol=lf diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..4c4f037 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,32 @@ +name: Lint + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Node.js + uses: actions/setup-node@v6 + with: + node-version: '24' + cache: 'npm' + + - name: Install dependencies + run: npm install + + - parallel: + - name: ESLint + run: npm run lint:js + + - name: Stylelint + run: npm run lint:css diff --git a/.gitignore b/.gitignore index 1503da4..3bb52ea 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ /.vite/ /.coverage/ +.eslintcache +.stylelintcache + # Log files *.log npm-debug.log* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 18b359c..4cf7191 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,6 +32,15 @@ If you encounter a bug, graphical glitch, or something isn't working as expected **Create a Pull Request:** Do you have a feature you would like added, or a task that you would like added that could benefit other Tenno? Fork the repository, and create a pull request! +### Coding Style + +This project uses [ESLint](https://eslint.org/) and [Stylelint](https://stylelint.io/) to enforce a consistent coding style. +A GitHub workflow will check your code automatically when you push changes or create a pull request. +You can also run the checks locally with `npm run lint`, and [a git pre-commit hook is provided](./pre-commit) that you can install. +Extensions may also be available for your editor. + +### AI Policy + You must disclose any use of AI that went in to preparing your pull request by **both**: 1. Marking the appropriate box in the pull request template, *and* diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..407d459 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,134 @@ +import js from "@eslint/js"; +import globals from "globals"; +import json from "@eslint/json"; +import css from "@eslint/css"; +import { defineConfig } from "eslint/config"; +import stylistic from "@stylistic/eslint-plugin"; + +export default defineConfig([ + { ignores: [".coverage/**/*"] }, + { + linterOptions: { + reportUnusedInlineConfigs: "warn", + }, + }, + { + files: ["sources/**/*.{js,mjs,cjs}", "*.config.*js"], + plugins: { js }, + languageOptions: { + globals: globals.browser, + }, + extends: [ + "js/recommended", + stylistic.configs.customize({ + indent: 4, + semi: true, + quotes: "double", + jsx: false, + arrowParens: true, + quoteProps: "consistent", + }), + ], + rules: { + // "important" stuff + "curly": ["error", "all"], + "eqeqeq": ["error", "always"], + "no-var": "error", + "prefer-const": "error", + "radix": "error", + // niche stuff + "array-callback-return": "error", + "no-duplicate-imports": "error", + "no-self-compare": "error", + "no-template-curly-in-string": "warn", + "no-unreachable-loop": "error", + "no-use-before-define": ["error", "nofunc"], + "block-scoped-var": "error", + "consistent-return": "error", + "default-param-last": "error", + "dot-notation": "warn", + "func-style": ["error", "declaration"], + "no-empty-function": "error", + "no-extend-native": "error", + "no-labels": "error", + "no-implicit-coercion": "error", + "no-lone-blocks": "error", + "no-lonely-if": "error", + "no-new-wrappers": "error", + "no-object-constructor": "error", + "no-proto": "error", + "no-return-assign": ["error", "always"], + "no-sequences": ["error", { "allowInParentheses": false }], + "no-shadow": "error", + "no-throw-literal": "error", + "no-unused-expressions": "error", + "no-useless-concat": "error", + "no-useless-rename": "error", + "no-void": "error", + "prefer-arrow-callback": "error", + "prefer-numeric-literals": "error", + "unicode-bom": "error", + // eval + "no-eval": "error", + "no-implied-eval": "error", + "no-new-func": "error", + "no-script-url": "error", + // complexity + "complexity": ["warn", 20], + "id-length": ["warn", { "min": 1, "max": 30 }], + "max-depth": ["warn", 4], + "max-lines-per-function": ["warn", { + "max": 60, + "skipBlankLines": true, + "skipComments": true, + }], + "max-nested-callbacks": ["warn", 4], + "max-params": ["warn", 4], + // stylistic + "@stylistic/quotes": ["error", "double", { "avoidEscape": true }], + "@stylistic/brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "@stylistic/no-multiple-empty-lines": ["error", { "max": 2 }], + "@stylistic/max-statements-per-line": ["error", { "max": 2 }], + "@stylistic/object-curly-spacing": ["error", "always", { "emptyObjects": "never" }], + }, + }, + { + files: ["sources/tests/*.js", "*.config.*js"], + languageOptions: { + globals: globals.node, + }, + }, + { + files: ["sources/**/*.json"], + plugins: { json }, + language: "json/json", + extends: ["json/recommended"], + }, + { + files: ["sources/**/*.css"], + plugins: { css }, + language: "css/css", + extends: ["css/recommended"], + languageOptions: { + tolerant: true, + }, + rules: { + /* allowUnknownVariables suppresses errors from variables defined in other files. + Stylelint does proper checking for this kind of error with its `referenceFiles` feature. */ + "css/no-invalid-properties": ["error", { "allowUnknownVariables": true }], + "css/use-baseline": ["warn", { + "available": "widely", + "allowProperties": [ + "backdrop-filter", // baseline 2024 + ], + "allowPropertyValues": { + "background-attachment": ["fixed"], // only unavailable in iOS + }, + "allowAtRules": [ + "starting-style", // baseline 2024 + ], + }], + "css/no-important": "warn", + }, + }, +]); diff --git a/package-lock.json b/package-lock.json index 07d1c85..646611c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,21 @@ "version": "5.3", "license": "GPL-3.0-or-later", "devDependencies": { + "@eslint/css": "^1.4.0", + "@eslint/js": "^10.0.1", + "@eslint/json": "^2.0.1", + "@stylistic/eslint-plugin": "^5.10.0", + "@stylistic/stylelint-config": "^5.0.0", "@vitest/coverage-v8": "^4.1.5", "@vitest/ui": "^4.1.5", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", + "eslint": "^10.8.0", + "globals": "^17.8.0", "jsdom": "^29.1.1", "sanitize.css": "^13.0.0", + "stylelint": "^17.14.1", + "stylelint-config-standard": "^40.0.0", "vite": "^8.0.16", "vite-plugin-singlefile": "^2.3.3", "vitest": "^4.1.5" @@ -71,6 +80,28 @@ "dev": true, "license": "MIT" }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/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/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -82,9 +113,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -144,6 +175,67 @@ "specificity": "bin/cli.js" } }, + "node_modules/@cacheable/memory": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz", + "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/utils": "^2.5.0", + "@keyv/bigmap": "^1.3.1", + "hookified": "^1.15.1", + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", + "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.4.0", + "hookified": "^1.15.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/memory/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, + "node_modules/@cacheable/utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz", + "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.5.1", + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/utils/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, "node_modules/@csstools/color-helpers": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", @@ -165,9 +257,9 @@ } }, "node_modules/@csstools/css-calc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.0.tgz", - "integrity": "sha512-bR9e6o2BDB12jzN/gIbjHa5wLJ4UjD1CB9pM7ehlc0ddk6EBz+yYS1EV2MF55/HUxrHcB/hehAyt5vhsA3hx7w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.3.0.tgz", + "integrity": "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==", "dev": true, "funding": [ { @@ -240,9 +332,9 @@ } }, "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.3.tgz", - "integrity": "sha512-SH60bMfrRCJF3morcdk57WklujF4Jr/EsQUzqkarfHXEFcAR1gg7fS/chAE922Sehgzc1/+Tz5H3Ypa1HiEKrg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.7.tgz", + "integrity": "sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==", "dev": true, "funding": [ { @@ -284,6 +376,76 @@ "node": ">=20.19.0" } }, + "node_modules/@csstools/media-query-list-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-5.0.0.tgz", + "integrity": "sha512-T9lXmZOfnam3eMERPsszjY5NK0jX8RmThmmm99FZ8b7z8yMaFZWKwLWGZuTwdO3ddRY5fy13GmmEYZXB4I98Eg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/selector-resolve-nested": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-4.0.1.tgz", + "integrity": "sha512-j3vdQu0XwLME5qOTWxm8cnmvsf423R2YL6DbKklCHZwkDm7UdKNu6RPlw4REIJhSlKBICY3B70/7QZdicLqZgg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.1.1" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-6.0.0.tgz", + "integrity": "sha512-4sSgl78OtOXEX/2d++8A83zHNTgwCJMaR24FvsYL7Uf/VS8HZk9PTwR51elTbGqMuwH3szLvvOXEaVnqn0Z3zA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.1.1" + } + }, "node_modules/@emnapi/core": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", @@ -318,6 +480,186 @@ "tslib": "^2.4.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "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/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/css": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@eslint/css/-/css-1.4.0.tgz", + "integrity": "sha512-OnRNKgnbX+tufPuZc2kOJS+v1iIARvfJHRNEAVwN77DBpojl+rGjEP8NKTL6pEZ7BR+HtwIuSSdrymEFlANGxg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "@eslint/css-tree": "^4.0.4", + "@eslint/plugin-kit": "^0.7.2" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/css-tree": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@eslint/css-tree/-/css-tree-4.0.5.tgz", + "integrity": "sha512-iPmijIAq4hlIJB86PYmY/fcZORHtjphSqICDbwuw32A/JmkhZQ/K/6TjHE03zqf3n5yABpVcbRAMG8Mi9ojy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.29.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/css-tree/node_modules/mdn-data": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.29.0.tgz", + "integrity": "sha512-pVxQFCcaYUEAH853+v7yoI/qzhxXSq1bTb9obMYGYAN1c3Hen+XDCEvr296XhstrwlSTNgOR7mCSD4JPjbJe5A==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/json/-/json-2.0.1.tgz", + "integrity": "sha512-Thz2j92ceUF3Bq/0TuWb3MWn3Z+Cwc8k5ptF0fakl2D4Mp8mSx07Xr1aQM4R5NoihzarWUdxfOmQ8DesGy4jOg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanwhocodes/momoa": "^3.3.10", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, "node_modules/@exodus/bytes": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz", @@ -336,6 +678,82 @@ } } }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/momoa": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-3.3.10.tgz", + "integrity": "sha512-KWiFQpSAqEIyrTXko3hFNLeQvSK8zXlJQzhhxsyVn58WFRYXST99b3Nqnu+ttOtjds2Pl2grUHGpe2NzhPynuQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -363,6 +781,13 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "dev": true, + "license": "MIT" + }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz", @@ -382,20 +807,58 @@ "@emnapi/runtime": "^1.7.1" } }, - "node_modules/@oxc-project/types": { - "version": "0.133.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", - "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.133.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", + "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "dev": true, "license": "MIT" }, @@ -681,12 +1144,112 @@ "dev": true, "license": "MIT" }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "dev": true }, + "node_modules/@stylistic/eslint-plugin": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.10.0.tgz", + "integrity": "sha512-nPK52ZHvot8Ju/0A4ucSX1dcPV2/1clx0kLcH5wDmrE4naKso7TUC/voUyU1O9OTKTrR6MYip6LP0ogEMQ9jPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/types": "^8.56.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "estraverse": "^5.3.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^9.0.0 || ^10.0.0" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@stylistic/stylelint-config": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@stylistic/stylelint-config/-/stylelint-config-5.0.0.tgz", + "integrity": "sha512-AW6S27wEm4DzB+uOZMvRkONIu0ba50VRbFte7qYJgGP4dacS8kAuj8HZJ+s+8kE4GK3XXBcSKLb75a+NfJlbiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@stylistic/stylelint-plugin": "^5.1.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "stylelint": "^17.6.0" + } + }, + "node_modules/@stylistic/stylelint-plugin": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-5.2.1.tgz", + "integrity": "sha512-BMRWJVtO16uADJmKcGi6mreei/QYdOviABXuaCeHEc3T3pxo4wFYYSvnxIoyiPVfDJqX+DxQdnGkuc6KxsRaSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0", + "@csstools/media-query-list-parser": "^5.0.0", + "postcss": "^8.5.8", + "postcss-selector-parser": "^7.1.1", + "postcss-value-parser": "^4.2.0", + "style-search": "^0.1.0" + }, + "peerDependencies": { + "stylelint": "^17.6.0" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", @@ -714,12 +1277,40 @@ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/types": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.65.0.tgz", + "integrity": "sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@vitest/coverage-v8": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.5.tgz", @@ -907,6 +1498,29 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/ajv": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", @@ -942,6 +1556,42 @@ } } }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -973,6 +1623,26 @@ "@types/estree": "^1.0.0" } }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/bidi-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", @@ -983,6 +1653,19 @@ "require-from-string": "^2.0.2" } }, + "node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -996,6 +1679,40 @@ "node": ">=8" } }, + "node_modules/cacheable": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz", + "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/memory": "^2.2.0", + "@cacheable/utils": "^2.5.0", + "hookified": "^1.15.0", + "keyv": "^5.6.0", + "qified": "^0.10.1" + } + }, + "node_modules/cacheable/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, + "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/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -1005,12 +1722,91 @@ "node": ">=18" } }, + "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/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "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 }, + "node_modules/cosmiconfig": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", + "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-functions-list": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz", + "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/css-tree": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", @@ -1025,6 +1821,19 @@ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/data-urls": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", @@ -1039,6 +1848,24 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/decimal.js": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", @@ -1046,6 +1873,13 @@ "dev": true, "license": "MIT" }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -1056,28 +1890,291 @@ "node": ">=8" } }, + "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/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-module-lexer": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true }, - "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fast-deep-equal": { + "node_modules/eslint": { + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.0.tgz", + "integrity": "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ==", + "dev": true, + "license": "MIT", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "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/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-uri": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", @@ -1095,6 +2192,26 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -1119,6 +2236,19 @@ "dev": true, "license": "MIT" }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -1132,6 +2262,37 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "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": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/flatted": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", @@ -1154,103 +2315,392 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.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==", + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/html-encoding-sniffer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", - "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@exodus/bytes": "^1.6.0" + "is-glob": "^4.0.3" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": ">=10.13.0" } }, - "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==", + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "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==", + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, "engines": { - "node": ">=0.12.0" + "node": ">=6" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "license": "MIT" + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } }, - "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==", + "node_modules/globals": { + "version": "17.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.8.0.tgz", + "integrity": "sha512-Zz/LMDZScFmkakeL2cTHzf+PbWKdpU3uclqkZT7TjDG58j5WPt0PpA+n9uPI24fZtlw07q0OtEi84K+umsRzqQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/globby": { + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-16.2.2.tgz", + "integrity": "sha512-NLvV9ubZ6NDsJaOpKPy3cQeJpKi9DcWiyCiFUpJPA0YihRqiE6RWaLUmgNNPr8MgPpLZjnBjSmou7uZBRJv9wA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "@sindresorhus/merge-streams": "^4.0.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.5", + "is-path-inside": "^4.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.4.0" }, "engines": { - "node": ">=10" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "node_modules/globby/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/js-tokens": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", - "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", "dev": true, "license": "MIT" }, - "node_modules/jsdom": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", - "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", + "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/hashery": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", + "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^1.15.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/hookified": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", + "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "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/html-tags": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-5.1.0.tgz", + "integrity": "sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "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-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "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-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "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-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-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1288,6 +2738,20 @@ } } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "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/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -1295,6 +2759,47 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", @@ -1568,6 +3073,36 @@ "url": "https://opencollective.com/parcel" } }, + "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": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "11.3.6", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.6.tgz", @@ -1615,6 +3150,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mathml-tag-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-4.0.0.tgz", + "integrity": "sha512-aa6AU2Pcx0VP/XWnh8IGL0SYSgQHDT6Ucror2j2mXeFAlN3ahaNs8EZtG1YiticMkSLj3Gt6VPFfZogt7G5iFQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/mdn-data": { "version": "2.27.1", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", @@ -1622,21 +3168,44 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/meow": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-14.1.0.tgz", + "integrity": "sha512-EDYo6VlmtnumlcBCbh1gLJ//9jvM/ndXHfVXIFrZVr6fGcwTUyCTFNTLCKuY3ffbK8L/+3Mzqnd58RojiZqHVw==", "dev": true, "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "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/micromatch/node_modules/picomatch": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", @@ -1649,6 +3218,22 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -1659,10 +3244,17 @@ "node": ">=10" } }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.17", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", + "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", "dev": true, "funding": [ { @@ -1678,6 +3270,23 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "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/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/obug": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", @@ -1688,6 +3297,88 @@ "https://opencollective.com/debug" ] }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "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", + "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": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "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/parse5": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", @@ -1714,6 +3405,26 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "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-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/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1721,197 +3432,693 @@ "dev": true, "license": "ISC" }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", + "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-safe-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", + "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz", + "integrity": "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qified": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz", + "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^2.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/qified/node_modules/hookified": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz", + "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "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/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rolldown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", + "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.133.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "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/sanitize.css": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", + "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/std-env": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", + "dev": true + }, + "node_modules/string-width": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", + "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true, + "license": "ISC" + }, + "node_modules/stylelint": { + "version": "17.14.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.14.1.tgz", + "integrity": "sha512-xVQwyiuxALUBNB2fBe0tmNemg9KqLtdj3T64mioFDar79B2cU8LIyz+3KL6LdiHs9NkeNfwxpKSaIVOY8f112g==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@csstools/css-calc": "^3.2.1", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-syntax-patches-for-csstree": "^1.1.6", + "@csstools/css-tokenizer": "^4.0.0", + "@csstools/media-query-list-parser": "^5.0.0", + "@csstools/selector-resolve-nested": "^4.0.0", + "@csstools/selector-specificity": "^6.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^9.0.2", + "css-functions-list": "^3.3.3", + "css-tree": "^3.2.1", + "debug": "^4.4.3", + "fast-glob": "^3.3.3", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^11.1.5", + "global-modules": "^2.0.0", + "globby": "^16.2.1", + "globjoin": "^0.1.4", + "html-tags": "^5.1.0", + "ignore": "^7.0.5", + "import-meta-resolve": "^4.2.0", + "mathml-tag-names": "^4.0.0", + "meow": "^14.1.0", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.5.16", + "postcss-safe-parser": "^7.0.1", + "postcss-selector-parser": "^7.1.4", + "postcss-value-parser": "^4.2.0", + "string-width": "^8.2.1", + "supports-hyperlinks": "^4.5.0", + "svg-tags": "^1.0.0", + "table": "^6.9.0", + "write-file-atomic": "^7.0.1" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": ">=20.19.0" } }, - "node_modules/postcss": { - "version": "8.5.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", - "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "node_modules/stylelint-config-recommended": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-18.0.0.tgz", + "integrity": "sha512-mxgT2XY6YZ3HWWe3Di8umG6aBmWmHTblTgu/f10rqFXnyWxjKWwNdjSWkgkwCtxIKnqjSJzvFmPT5yabVIRxZg==", "dev": true, "funding": [ { "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "url": "https://opencollective.com/stylelint" }, { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "stylelint": "^17.0.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "40.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-40.0.0.tgz", + "integrity": "sha512-EznGJxOUhtWck2r6dJpbgAdPATIzvpLdK9+i5qPd4Lx70es66TkBPljSg4wN3Qnc6c4h2n+WbUrUynQ3fanjHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" }, { "type": "github", - "url": "https://github.com/sponsors/ai" + "url": "https://github.com/sponsors/stylelint" } ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "stylelint-config-recommended": "^18.0.0" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=20.19.0" + }, + "peerDependencies": { + "stylelint": "^17.0.0" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz", + "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "flat-cache": "^6.1.23" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/stylelint/node_modules/flat-cache": { + "version": "6.1.23", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz", + "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cacheable": "^2.5.0", + "flatted": "^3.4.2", + "hookified": "^1.15.0" + } + }, + "node_modules/stylelint/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 4" } }, - "node_modules/rolldown": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", - "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", + "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": { - "@oxc-project/types": "=0.133.0", - "@rolldown/pluginutils": "^1.0.0" - }, - "bin": { - "rolldown": "bin/cli.mjs" + "has-flag": "^4.0.0" }, "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.3", - "@rolldown/binding-darwin-arm64": "1.0.3", - "@rolldown/binding-darwin-x64": "1.0.3", - "@rolldown/binding-freebsd-x64": "1.0.3", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", - "@rolldown/binding-linux-arm64-gnu": "1.0.3", - "@rolldown/binding-linux-arm64-musl": "1.0.3", - "@rolldown/binding-linux-ppc64-gnu": "1.0.3", - "@rolldown/binding-linux-s390x-gnu": "1.0.3", - "@rolldown/binding-linux-x64-gnu": "1.0.3", - "@rolldown/binding-linux-x64-musl": "1.0.3", - "@rolldown/binding-openharmony-arm64": "1.0.3", - "@rolldown/binding-wasm32-wasi": "1.0.3", - "@rolldown/binding-win32-arm64-msvc": "1.0.3", - "@rolldown/binding-win32-x64-msvc": "1.0.3" + "node": ">=8" } }, - "node_modules/sanitize.css": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", - "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "node_modules/supports-hyperlinks": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-4.5.0.tgz", + "integrity": "sha512-ZW2OvfeCXrNTbLakPUzjQG922EeGCOteFSVoek5DKStTh898wf7zgtuFlzQN8HfZCxC3Eh02yJVrRW51hADf+w==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "xmlchars": "^2.2.0" + "has-flag": "^5.0.1", + "supports-color": "^10.2.2" }, "engines": { - "node": ">=v12.22.7" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, - "node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-5.0.1.tgz", + "integrity": "sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", "dev": true }, - "node_modules/sirv": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", - "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=18" + "node": ">=10.0.0" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "node_modules/table/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": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true - }, - "node_modules/std-env": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", - "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", - "dev": true - }, - "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==", + "node_modules/table/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": { - "has-flag": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "node_modules/table/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" + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } }, "node_modules/tinybench": { "version": "2.9.0", @@ -2031,6 +4238,19 @@ "license": "0BSD", "optional": true }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/undici": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", @@ -2041,6 +4261,36 @@ "node": ">=20.18.1" } }, + "node_modules/unicorn-magic": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz", + "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, "node_modules/vite": { "version": "8.0.16", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", @@ -2284,6 +4534,22 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, + "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/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -2300,6 +4566,29 @@ "node": ">=8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/write-file-atomic": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", + "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", + "dev": true, + "license": "ISC", + "dependencies": { + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", @@ -2316,6 +4605,19 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true, "license": "MIT" + }, + "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 dfebfca..e6f15c5 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,10 @@ "build-release": "vite build --mode release", "preview": "vite preview", "test": "vitest", - "test:ui": "vitest --ui --open=false --coverage" + "test:ui": "vitest --ui --open=false --coverage", + "lint": "npm run lint:js && npm run lint:css", + "lint:js": "eslint --concurrency=auto --cache", + "lint:css": "stylelint \"sources/**/*.css\" --cache" }, "repository": { "type": "git", @@ -29,12 +32,21 @@ }, "homepage": "https://warframetools.com/Task-Checklist/", "devDependencies": { + "@eslint/css": "^1.4.0", + "@eslint/js": "^10.0.1", + "@eslint/json": "^2.0.1", + "@stylistic/eslint-plugin": "^5.10.0", + "@stylistic/stylelint-config": "^5.0.0", "@vitest/coverage-v8": "^4.1.5", "@vitest/ui": "^4.1.5", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", + "eslint": "^10.8.0", + "globals": "^17.8.0", "jsdom": "^29.1.1", "sanitize.css": "^13.0.0", + "stylelint": "^17.14.1", + "stylelint-config-standard": "^40.0.0", "vite": "^8.0.16", "vite-plugin-singlefile": "^2.3.3", "vitest": "^4.1.5" diff --git a/pre-commit b/pre-commit new file mode 100644 index 0000000..6efd652 --- /dev/null +++ b/pre-commit @@ -0,0 +1,50 @@ +#!/bin/bash +# This is a git pre-commit hook to check for linting errors. +# Copy or symlink this file into .git/hooks/ to install it. + +if [[ -t 1 && -z "$NO_COLOR" ]]; then + color="--color" +else + color="--no-color" +fi + +if [[ pre-commit -nt .git/hooks/pre-commit ]]; then + echo "The pre-commit hook version distributed by the repository is newer than the installed version. You may wish to update." + stat -c "repository: %y : %n" pre-commit + stat -c "installed: %y : %n" .git/hooks/pre-commit + echo +fi + +# Redirect output to stderr. +exec 1>&2 + +# Run commands in the background and redirect their output to new file descriptors +exec 3< <(npm run -s test -- run --silent --reporter=minimal --bail=1 $color 2>&1); test_pid=$! +exec 4< <(npm run -s lint:js -- $color 2>&1); js_pid=$! +exec 5< <(npm run -s lint:css -- $color 2>&1); css_pid=$! + +# Wait for commands to complete and capture their exit codes +wait $test_pid; test_exit=$? +wait $js_pid; js_exit=$? +wait $css_pid; css_exit=$? + +if [[ $test_exit != 0 || $js_exit != 0 || $css_exit != 0 ]]; then + msg="Fix errors before committing, or skip this check with --no-verify" + echo -e "$msg\n" # this message is for the Commit button in the vscode ui + if [[ $test_exit != 0 ]]; then + echo "----- Vitest report - (exit code $test_exit) --------------" + cat <&3 + echo -e "Only the first failing test is reported. Run \`npm run test\` to check for more.\n" + fi + if [[ $js_exit != 0 ]]; then + echo "----- ESLint report - (exit code $js_exit) --------------" + cat <&4 + fi + if [[ $css_exit != 0 ]]; then + echo "----- Stylelint report - (exit code $css_exit) -----------" + cat <&5 + fi + echo -e "--------------------------------------------------\n" + echo "$msg" # this message is for if you're committing on a terminal + exit 1 +fi diff --git a/sources/css/critical.css b/sources/css/critical.css index 26e9782..b29be6f 100644 --- a/sources/css/critical.css +++ b/sources/css/critical.css @@ -1,37 +1,37 @@ /* @font-face rules for self-hosted Inter font */ @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap; - src: url('/fonts/inter-v18-latin-regular.woff2') format('woff2'); + src: url("/fonts/inter-v18-latin-regular.woff2") format("woff2"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap; - src: url('/fonts/inter-v18-latin-500.woff2') format('woff2'); + src: url("/fonts/inter-v18-latin-500.woff2") format("woff2"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap; - src: url('/fonts/inter-v18-latin-600.woff2') format('woff2'); + src: url("/fonts/inter-v18-latin-600.woff2") format("woff2"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap; - src: url('/fonts/inter-v18-latin-700.woff2') format('woff2'); + src: url("/fonts/inter-v18-latin-700.woff2") format("woff2"); } /* --- Global Theme Variables (Critical for initial paint) --- */ :root { /* Default: Dark Mode */ - --bg-content: rgba(31, 41, 55, 0.95); + --bg-content: rgb(31 41 55 / 95%); --text-primary: #f3f4f6; --text-secondary: #9ca3af; --text-muted: #6b7280; @@ -41,27 +41,27 @@ --border-color: #4b5563; --checkbox-check-color: var(--text-primary); --checkbox-lock-color: var(--text-primary); - --checkbox-bg: rgba(255, 255, 255, 0.1); + --checkbox-bg: rgb(255 255 255 / 10%); --checkbox-border: var(--text-muted); --checkbox-checked-bg: var(--text-header); --checkbox-checked-border: var(--text-muted); - --checkbox-locked-bg: hsla(17, 100%, 70%, 0.15); + --checkbox-locked-bg: hsl(17deg 100% 70% / 15%); --checkbox-locked-border: var(--text-muted); --link-color: var(--text-header); --link-hover-color: var(--text-primary); --theme-toggle-border: var(--border-color); - --theme-toggle-hover-bg: rgba(255, 255, 255, 0.1); + --theme-toggle-hover-bg: rgb(255 255 255 / 10%); --theme-toggle-hover-border: var(--text-secondary); --theme-toggle-color: var(--text-secondary); - --section-header-hover-bg: rgba(255, 255, 255, 0.05); + --section-header-hover-bg: rgb(255 255 255 / 5%); --confirm-bg: #f59e0b; --confirm-hover-bg: #d97706; --confirm-text: #1f2937; --error-bg: #ef4444; --error-border: #dc2626; - --error-text: #ffffff; - --error-button-bg: rgba(255, 255, 255, 0.1); - --error-button-hover-bg: rgba(255, 255, 255, 0.2); + --error-text: white; + --error-button-bg: rgb(255 255 255 / 10%); + --error-button-hover-bg: rgb(255 255 255 / 20%); --menu-panel-bg: #272e3a; --menu-panel-border: #374151; --menu-title-color: var(--text-primary); @@ -77,7 +77,7 @@ } body.light-mode { - --bg-content: rgba(255, 255, 255, 0.95); + --bg-content: rgb(255 255 255 / 95%); --text-primary: #1f2937; --text-secondary: #4b5563; --text-muted: #6b7280; @@ -87,21 +87,21 @@ body.light-mode { --border-color: #e5e7eb; --checkbox-check-color: var(--text-primary); --checkbox-lock-color: var(--text-primary); - --checkbox-bg: rgba(0, 0, 0, 0.02); + --checkbox-bg: rgb(0 0 0 / 2%); --checkbox-border: #cbd5e1; - --checkbox-locked-bg: hsla(17, 100%, 30%, 0.15); + --checkbox-locked-bg: hsl(17deg 100% 30% / 15%); --link-color: var(--text-header); --link-hover-color: var(--text-primary); --theme-toggle-border: #d1d5db; - --theme-toggle-hover-bg: rgba(0, 0, 0, 0.05); + --theme-toggle-hover-bg: rgb(0 0 0 / 5%); --theme-toggle-hover-border: var(--text-muted); --theme-toggle-color: var(--text-muted); - --section-header-hover-bg: rgba(0, 0, 0, 0.03); + --section-header-hover-bg: rgb(0 0 0 / 3%); --error-bg: #fee2e2; --error-border: #f87171; --error-text: #b91c1c; - --error-button-bg: rgba(0, 0, 0, 0.05); - --error-button-hover-bg: rgba(0, 0, 0, 0.1); + --error-button-bg: rgb(0 0 0 / 5%); + --error-button-hover-bg: rgb(0 0 0 / 10%); --menu-panel-bg: #f9fafb; --menu-panel-border: var(--border-color); --menu-title-color: var(--text-primary); @@ -138,7 +138,7 @@ body.light-mode { /* --- Base Body Styles --- */ body { - font-family: 'Inter', sans-serif; + font-family: "Inter", sans-serif; background-size: cover; background-position: center center; background-repeat: no-repeat; @@ -152,12 +152,12 @@ body { body::before { content: ""; position: fixed; - top: 0; left: 0; right: 0; bottom: 0; - background-color: rgba(0, 0, 0, 0.6); + inset: 0; + background-color: rgb(0 0 0 / 60%); z-index: -1; } body.light-mode::before { - background-color: rgba(255, 255, 255, 0.6); + background-color: rgb(255 255 255 / 60%); } /* --- Content Box Element Styling --- */ @@ -170,8 +170,8 @@ body.light-mode::before { margin: 2rem auto; padding: 2rem; border-radius: 0.5rem; - box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), - 0 8px 10px -6px rgb(0 0 0 / 0.1); + box-shadow: 0 20px 25px -5px rgb(0 0 0 / 10%), + 0 8px 10px -6px rgb(0 0 0 / 10%); @media (width < 48rem) { padding: 1.5rem; margin: 0 auto; @@ -230,6 +230,20 @@ h1 { margin-bottom: 0.5rem; } +.task-info-expander { + --current-cycle-svg-size: 1.125rem; + --task-info-expander-svg-mr: 0.2em; +} + +.current-cycle svg { + width: var(--current-cycle-svg-size); + height: var(--current-cycle-svg-size); +} +.info-line svg { + width: 0.9375rem; + height: 0.9375rem; +} + /* Theme switching animation */ @media (prefers-reduced-motion: no-preference) { body { transition: background-color 0.3s ease, color 0.3s ease; } @@ -259,7 +273,8 @@ h1 { .parent-task-header[aria-expanded="false"] .collapse-btn svg { transform: rotate(-90deg); } -.section-content, .subtask-collapsible { +.section-content, +.subtask-collapsible { display: grid; grid-template-rows: 1fr; overflow: hidden; @@ -267,15 +282,18 @@ h1 { padding-left: 0.5rem; } @media (prefers-reduced-motion: no-preference) { - .section-content, .subtask-collapsible { - transition: grid-template-rows 0.5s cubic-bezier(.23,1,.32,1), opacity 0.5s ease-in-out; + .section-content, + .subtask-collapsible { + transition: grid-template-rows 0.5s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.5s ease-in-out; } } -.section-content.collapsed, .subtask-collapsible.collapsed { +.section-content.collapsed, +.subtask-collapsible.collapsed { opacity: 0.5; grid-template-rows: 0fr; } -.section-content > :first-child, .subtask-collapsible > :first-child { +.section-content > :first-child, +.subtask-collapsible > :first-child { min-height: 0; } @@ -310,7 +328,7 @@ body:not(.light-mode) #sun-icon { display: none; } dialog { background-color: var(--menu-panel-bg); border: 1px solid var(--menu-panel-border); - box-shadow: 0 8px 16px rgba(0,0,0,0.2); + box-shadow: 0 8px 16px rgb(0 0 0 / 20%); border-radius: 0.5rem; } dialog > div { @@ -359,22 +377,8 @@ dialog > div { } #error-display.visible { display: flex; } #error-message { flex-grow: 1; } -#error-copy-button, #error-close-button { +#error-copy-button, +#error-close-button { cursor: pointer; flex-shrink: 0; } - - -.task-info-expander { - --current-cycle-svg-size: 1.125rem; - --task-info-expander-svg-mr: 0.2em; -} - -.current-cycle svg { - width: var(--current-cycle-svg-size); - height: var(--current-cycle-svg-size); -} -.info-line svg { - width: 0.9375rem; - height: 0.9375rem; -} diff --git a/sources/css/style.css b/sources/css/style.css index d7eca21..14ae7f6 100644 --- a/sources/css/style.css +++ b/sources/css/style.css @@ -3,11 +3,11 @@ /* --- Background Image Styles --- */ /* Paths are relative to this style.css file (e.g., if style.css is in sources/css/ and images are in sources/img/) */ -#bg-image-0 { background-image: url('../img/garuda-fortuna.webp'); } -#bg-image-1 { background-image: url('../img/gara-eidolon.webp'); } -#bg-image-2 { background-image: url('../img/heart-of-deimos-warframe.webp'); } -#bg-image-3 { background-image: url('../img/duviri.webp'); } -#bg-image-4 { background-image: url('../img/perita.webp'); } +#bg-image-0 { background-image: url("../img/garuda-fortuna.webp"); } +#bg-image-1 { background-image: url("../img/gara-eidolon.webp"); } +#bg-image-2 { background-image: url("../img/heart-of-deimos-warframe.webp"); } +#bg-image-3 { background-image: url("../img/duviri.webp"); } +#bg-image-4 { background-image: url("../img/perita.webp"); } /* Add more #bg-image-X rules if you have more images */ .daily-background-image { @@ -31,7 +31,6 @@ #checklist-container h2:hover { background-color: var(--section-header-hover-bg); } -.task-description { color: var(--text-label); } #save-info { margin-top: 1rem; @@ -43,7 +42,7 @@ margin-top: 0.25rem; } #save-status { - color: rgb(22 163 74 / 1); + color: rgb(22 163 74 / 100%); opacity: 0; font-size: 0.875rem; line-height: 1.25rem; @@ -118,6 +117,7 @@ a.git-hash-text { margin-bottom: 0.25rem; } .task-description { + color: var(--text-label); flex: 1 1 0%; margin-left: 0.5rem; cursor: pointer; @@ -160,7 +160,7 @@ a.git-hash-text { opacity: 1; } .section-is-hidden-by-user { - display: none !important; + display: none; } .hide-section-button { background-color: var(--hide-section-btn-bg); @@ -188,15 +188,15 @@ a.git-hash-text { font-variant-numeric: tabular-nums; } - /* --- Interactive Elements (Using Variables) --- */ input[type="checkbox"] { - appearance: none; -webkit-appearance: none; -moz-appearance: none; + appearance: none; width: 1.25rem; height: 1.25rem; margin: 0.125rem 0.5rem 0.125rem 0; border: 2px solid var(--checkbox-border); - border-radius: 0.25rem; cursor: pointer; + border-radius: 0.25rem; + cursor: pointer; position: relative; transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out; background-color: var(--checkbox-bg); @@ -248,36 +248,35 @@ input[type="checkbox"]:indeterminate::after { cursor: pointer; line-height: 1.5; } -/* Specific Button Colors (Default State) */ -#reset-daily-button:not(.confirming) { background-color: #3b82f6; border-color: #3b82f6; color: white;} -#reset-daily-button:not(.confirming):hover { background-color: #2563eb; border-color: #2563eb; color: white;} -#reset-weekly-button:not(.confirming) { background-color: #14b8a6; border-color: #14b8a6; color: white;} -#reset-weekly-button:not(.confirming):hover { background-color: #0d9488; border-color: #0d9488; color: white;} -#reset-button:not(.confirming) { background-color: #ef4444; border-color: #ef4444; color: white;} -#reset-button:not(.confirming):hover { background-color: #dc2626; border-color: #dc2626; color: white;} -#unhide-tasks-button:not(.confirming) { background-color: #8b5cf6; border-color: #8b5cf6; color: white; } +/* Specific Button Colors (Default State) */ /* stylelint-disable declaration-block-single-line-max-declarations, @stylistic/block-opening-brace-space-before */ +#reset-daily-button:not(.confirming) { background-color: #3b82f6; border-color: #3b82f6; color: white; } +#reset-daily-button:not(.confirming):hover { background-color: #2563eb; border-color: #2563eb; color: white; } +#reset-weekly-button:not(.confirming) { background-color: #14b8a6; border-color: #14b8a6; color: white; } +#reset-weekly-button:not(.confirming):hover { background-color: #0d9488; border-color: #0d9488; color: white; } +#reset-button:not(.confirming) { background-color: #ef4444; border-color: #ef4444; color: white; } +#reset-button:not(.confirming):hover { background-color: #dc2626; border-color: #dc2626; color: white; } +#unhide-tasks-button:not(.confirming) { background-color: #8b5cf6; border-color: #8b5cf6; color: white; } #unhide-tasks-button:not(.confirming):hover { background-color: #7c3aed; border-color: #7c3aed; color: white; } - +/* stylelint-enable declaration-block-single-line-max-declarations, @stylistic/block-opening-brace-space-before */ /* Confirmation State Styling (Applies to all reset buttons) */ .menu-btn.confirming { background-color: var(--confirm-bg); border-color: var(--confirm-bg); - color: var(--confirm-text) !important; + color: var(--confirm-text); } .menu-btn.confirming:hover { background-color: var(--confirm-hover-bg); border-color: var(--confirm-hover-bg); } - /* Theme Toggle Button Specifics (Non-critical hover states) */ -#theme-toggle-button:hover, #hamburger-button:hover { +#theme-toggle-button:hover, +#hamburger-button:hover { background-color: var(--theme-toggle-hover-bg); border-color: var(--theme-toggle-hover-border); } - /* Error Display (Non-critical hover states for buttons) */ #error-copy-button { background-color: var(--error-button-bg); @@ -290,13 +289,15 @@ input[type="checkbox"]:indeterminate::after { } #error-copy-button:hover { background-color: var(--error-button-hover-bg); } #error-close-button { - background: none; border: none; + background: none; + border: none; color: var(--error-text); - font-size: 1.5rem; line-height: 1; + font-size: 1.5rem; + line-height: 1; padding: 0 0.5rem; opacity: 0.7; } - #error-close-button:hover { opacity: 1; } +#error-close-button:hover { opacity: 1; } /* Hamburger Menu (Non-critical hover states) */ .menu-close-button:hover { @@ -340,7 +341,7 @@ dialog hr { dialog { --dialog-anim-duration: 0.15s; --dialog-anim-easing: ease-out; - transition: transform var(--dialog-anim-duration) cubic-bezier(.25,1,.5,1), + transition: transform var(--dialog-anim-duration) cubic-bezier(0.25, 1, 0.5, 1), opacity var(--dialog-anim-duration) var(--dialog-anim-easing), display var(--dialog-anim-duration) allow-discrete, overlay var(--dialog-anim-duration) allow-discrete; @@ -370,7 +371,6 @@ dialog hr { } } - /* Task Icons */ .task-icon { height: 1.5em; @@ -403,7 +403,9 @@ body:not(.light-mode) img.icon-filter { overflow: hidden; } @media (prefers-reduced-motion: no-preference) { - .task-info-expander { transition: grid-template-rows 200ms; /* https://css-tricks.com/css-grid-can-do-auto-height-transitions/ */ } + .task-info-expander { + transition: grid-template-rows 0.2s; /* https://css-tricks.com/css-grid-can-do-auto-height-transitions/ */ + } } .task-item .checked .task-info-expander { grid-template-rows: 0fr; @@ -418,6 +420,7 @@ body:not(.light-mode) img.icon-filter { font-size: 90%; color: color-mix(in hsl, var(--text-label) 50%, var(--text-secondary) 50%); margin-left: 0.5em; + /* eslint-disable-next-line css/use-baseline -- (text-indent: hanging; baseline 2026) only relevant on very narrow screens for only a small effect */ text-indent: calc(var(--current-cycle-svg-size) + var(--task-info-expander-svg-mr)) hanging; } .cycle-icon { @@ -448,7 +451,8 @@ body:not(.light-mode) img.icon-filter { color: var(--text-label); } -#cycle-schedule, #more-info { +#cycle-schedule, +#more-info { table { margin: auto; } @@ -458,7 +462,8 @@ body:not(.light-mode) img.icon-filter { text-decoration: underline var(--menu-panel-border) 1px; text-underline-offset: 0.25em; } - th::before, th::after { + th::before, /* eslint-disable-line css/no-invalid-properties -- eslint bug workaround */ + th::after { content: "\00a0\00a0\00a0\00a0"; /* some no-break spaces added so the underline extends a bit on both sides */ } :is(th, td):not(:last-child) { @@ -467,7 +472,8 @@ body:not(.light-mode) img.icon-filter { td { vertical-align: top; } - th, td:not(:has(.cycle-icon)) { + th, + td { text-align: center; } td:has(.cycle-icon) { @@ -488,16 +494,14 @@ body:not(.light-mode) img.icon-filter { /* More Info */ #more-info { - p:not(:last-child):not(:has(+ :is(ul, table))), table { + p:not(:last-child, :has(+ :is(ul, table))), /* eslint-disable-line css/no-invalid-properties -- eslint bug workaround */ + table { margin-bottom: 1em; } ul { list-style: "\2212 " outside; padding-left: 2em; } - th, td { - text-align: center; - } a { color: var(--link-color); text-decoration: underline; @@ -526,7 +530,7 @@ body:not(.light-mode) img.icon-filter { content: "|"; margin: 0 0.5em; } -.info-line > span > span { +.info-line > span > span { /* stylelint-disable-line no-descending-specificity -- the complained-about selector cannot match the same element as this */ /* keep the info line icon on the same line as the first word of the info line item. * e.g.: {prereq_icon}[NO_BREAK]Mastery[BREAK_OK]Rank[BREAK_OK]3 */ white-space: nowrap; @@ -553,10 +557,10 @@ body:not(.light-mode) img.icon-filter { } @media (prefers-reduced-motion: no-preference) { .task-expander { - transition: grid-template-rows 200ms; + transition: grid-template-rows 0.2s; } .task-expander > .task-item { - transition: margin 200ms; + transition: margin 0.2s; } } @@ -565,28 +569,28 @@ body.hide-completed-tasks .task-expander:has(> .task-item > .checked), body.hide-completed-tasks .task-expander:has(> .parent-task-container > .parent-task-header > .checked) { grid-template-rows: 0fr; @media (prefers-reduced-motion: no-preference) { - transition: grid-template-rows 200ms 5s; + transition: grid-template-rows 0.2s 5s; } @media (prefers-reduced-motion: reduce) { transition: grid-template-rows 0s 5s; } &::after { - background-color: color(from var(--checkbox-checked-bg) srgb r g b / 0.25); + background-color: color(from var(--checkbox-checked-bg) srgb r g b / 25%); width: 0; } } body.hide-completed-tasks .task-expander > .task-item:has(> .checked) { margin: 0; @media (prefers-reduced-motion: no-preference) { - transition: margin 200ms 5s; + transition: margin 0.2s 5s; } @media (prefers-reduced-motion: reduce) { transition: margin 0s 5s; } } /* countdown bar */ -.task-expander { +.task-expander { /* stylelint-disable-line no-descending-specificity -- better to group blocks by function than split them up by specificity */ position: relative; } .task-expander::after { @@ -612,16 +616,14 @@ body.hide-completed-tasks .task-expander > .task-item:has(> .checked) { .list-stats > div { overflow: hidden; display: flex; + margin-bottom: 0.5em; } body.hide-completed-tasks .list-stats:has(> div > button[data-count]:not([data-count="0"])), /* with autohide, show when any stat is nonzero */ body:not(.hide-completed-tasks) .list-stats:has(> div > button:not(.stats-completed)[data-count]:not([data-count="0"])) /* without autohide, show when any stat except completed is nonzero */ { grid-template-rows: 1fr; } @media (prefers-reduced-motion: no-preference) { - .list-stats { transition: grid-template-rows 200ms; } -} -.list-stats > div { - margin-bottom: 0.5em; + .list-stats { transition: grid-template-rows 0.2s; } } .list-stats > div > button[data-count="0"], /* hide stat when equal to 0 */ body:not(.hide-completed-tasks) .list-stats .stats-completed /* hide completed when autohide is off */ { diff --git a/sources/js/app.js b/sources/js/app.js index 0555c42..3b6567e 100644 --- a/sources/js/app.js +++ b/sources/js/app.js @@ -27,26 +27,26 @@ import * as svgIcons from "./icons.js"; // --- Configuration --- // Array of background div IDs (must match IDs in sources/index.html) const dailyBackgroundImageIds = [ - 'bg-image-0', - 'bg-image-1', - 'bg-image-2', - 'bg-image-3', - 'bg-image-4', + "bg-image-0", + "bg-image-1", + "bg-image-2", + "bg-image-3", + "bg-image-4", // Add more IDs if you add more background image divs in HTML ]; export const APP_VERSION = "5.3.1"; const GIT_COMMIT_HASH_LONG = import.meta.env.VITE_GIT_COMMIT_HASH; -const GIT_COMMIT_HASH = GIT_COMMIT_HASH_LONG.slice(0,7); +const GIT_COMMIT_HASH = GIT_COMMIT_HASH_LONG.slice(0, 7); const WARFRAME_VERSION = "43.5.4"; -const THEME_STORAGE_KEY = 'warframeChecklistTheme'; +const THEME_STORAGE_KEY = "warframeChecklistTheme"; // only update DATA_STORAGE_KEY when the data storage format changes // in a backwards-incompatible way (this should be *very* rare) const DATA_STORAGE_KEY = "warframeChecklistData_format1"; // --- Task Data --- -import tasks from "./tasks.json" with {type: "json"}; -import cycles from "./cycles.json" with {type: "json"}; +import tasks from "./tasks.json" with { type: "json" }; +import cycles from "./cycles.json" with { type: "json" }; import moreInfo from "./moreInfo.js"; // --- DOM Elements (defined after DOMContentLoaded) --- @@ -62,7 +62,7 @@ const confirmState = { all: { timeout: null, isConfirming: false }, daily: { timeout: null, isConfirming: false }, weekly: { timeout: null, isConfirming: false }, - unhide: { timeout: null, isConfirming: false } + unhide: { timeout: null, isConfirming: false }, }; let checklistData = newChecklistData(); @@ -115,7 +115,7 @@ function initializeDOMElements() { * `callback` function with the task definition object as a parameter. */ function forEachTask(callback) { - let stack = []; + const stack = []; for (const section in tasks) { for (let i = 0; i < tasks[section].length; i++) { // top-level tasks are not pushed in reverse order because they're immediately popped @@ -124,9 +124,9 @@ function forEachTask(callback) { const t = stack.pop(); callback(t); // do the thing if (t.subtasks) { - for (let i = t.subtasks.length - 1; i >= 0 ; i--) { + for (let j = t.subtasks.length - 1; j >= 0; j--) { /* eslint-disable-line max-depth */ // subtasks are pushed in reverse order so that they're popped in the correct order - stack.push(t.subtasks[i]); + stack.push(t.subtasks[j]); } } } @@ -176,7 +176,7 @@ function displayError(message) { function hideError() { if (!errorDisplayElement) { return; } errorDisplayElement.classList.remove("visible"); - errorMessageElement.textContent = ''; + errorMessageElement.textContent = ""; if (errorCopyButton) { errorCopyButton.textContent = "Copy"; } } @@ -208,16 +208,16 @@ function copyErrorToClipboard() { function applyTheme(theme) { if (!bodyElement || !themeToggleButton) { return; } - if (theme === 'light') { - bodyElement.classList.add('light-mode'); + if (theme === "light") { + bodyElement.classList.add("light-mode"); } else { - bodyElement.classList.remove('light-mode'); + bodyElement.classList.remove("light-mode"); } currentTheme = theme; } function handleThemeToggle() { - const newTheme = currentTheme === 'light' ? 'dark' : 'light'; + const newTheme = currentTheme === "light" ? "dark" : "light"; applyTheme(newTheme); try { localStorage.setItem(THEME_STORAGE_KEY, newTheme); @@ -233,10 +233,10 @@ function loadThemePreference() { return; } - if (bodyElement.classList.contains('light-mode')) { - currentTheme = 'light'; + if (bodyElement.classList.contains("light-mode")) { + currentTheme = "light"; } else { - currentTheme = 'dark'; + currentTheme = "dark"; } try { const storedTheme = localStorage.getItem(THEME_STORAGE_KEY); @@ -259,8 +259,8 @@ function updateLastSavedDisplay(timestamp) { function showSaveStatus() { if (!saveStatusElement) { return; } clearTimeout(saveStatusTimeout); - saveStatusElement.style.opacity = '1'; - saveStatusTimeout = setTimeout(() => { saveStatusElement.style.opacity = '0'; }, 1500); + saveStatusElement.style.opacity = "1"; + saveStatusTimeout = setTimeout(() => { saveStatusElement.style.opacity = "0"; }, 1500); } function setDailyBackground() { @@ -273,14 +273,14 @@ function setDailyBackground() { const dayOfYear = getUTCDayOfYear(now); const imageIndex = dayOfYear % backgroundDivs.length; - console.log(`Setting daily background to show div: ${backgroundDivs[imageIndex] ? backgroundDivs[imageIndex].id : 'N/A'} (Index: ${imageIndex})`); + console.log(`Setting daily background to show div: ${backgroundDivs[imageIndex] ? backgroundDivs[imageIndex].id : "N/A"} (Index: ${imageIndex})`); backgroundDivs.forEach((div, index) => { if (div) { // Ensure div exists if (index === imageIndex) { - div.style.display = 'block'; + div.style.display = "block"; } else { - div.style.display = 'none'; + div.style.display = "none"; } } }); @@ -318,8 +318,8 @@ function displayLocalResetTimes() { tasks.other.forEach((task) => displayOtherTaskCountdown(task)); } catch (e) { console.error("Error calculating or displaying local reset times:", e); - if (dailyResetTimeElement) { dailyResetTimeElement.innerHTML = `(Resets 00:00 UTC)`; } - if (weeklyResetTimeElement) { weeklyResetTimeElement.innerHTML = `(Resets Mon 00:00 UTC)`; } + if (dailyResetTimeElement) { dailyResetTimeElement.innerHTML = "(Resets 00:00 UTC)"; } + if (weeklyResetTimeElement) { weeklyResetTimeElement.innerHTML = "(Resets Mon 00:00 UTC)"; } } } @@ -346,7 +346,7 @@ export function displayOtherTaskCountdown(task) { } } else { // task not available resetTimer.innerHTML = `(Available in ${formatCountdown(taskTimes.nextResetTimestamp - now.getTime())})`; - if (checklistData.notificationsSent[leaveNotifId]) {delete checklistData.notificationsSent[leaveNotifId];} + if (checklistData.notificationsSent[leaveNotifId]) { delete checklistData.notificationsSent[leaveNotifId]; } } } else { // always available task resetTimer.innerHTML = `(Resets in ${formatCountdown(taskTimes.nextResetTimestamp - now.getTime())})`; @@ -391,7 +391,7 @@ function runAutoResets() { const todayUTCString = getUTCDateString(now); const lastDailyResetDate = checklistData.lastDailyReset ? new Date(checklistData.lastDailyReset) : null; - let lastDailyResetUTCString = lastDailyResetDate ? getUTCDateString(lastDailyResetDate) : null; + const lastDailyResetUTCString = lastDailyResetDate ? getUTCDateString(lastDailyResetDate) : null; if (!lastDailyResetUTCString || lastDailyResetUTCString !== todayUTCString) { console.log(`Performing daily auto-reset (UTC). Today: ${todayUTCString}, Last Reset: ${lastDailyResetUTCString}`); resetSection("daily", false); @@ -493,7 +493,7 @@ function showNotification(title, body) { } } -function createChecklistItem(task) { +function createChecklistItem(task) { /* eslint-disable-line complexity, max-lines-per-function */ const isChecked = checklistData.progress[task.id] || false; const isAvailable = calcTaskTimes(task, new Date()).isAvailable; @@ -592,7 +592,7 @@ function createChecklistItem(task) { let skipTooltip; if (isAvailable) { let when = "this cycle"; - if (task.id.startsWith("daily_")) { when = "today"; } + if (task.id.startsWith("daily_")) { when = "today"; } /* eslint-disable-line @stylistic/brace-style */ else if (task.id.startsWith("weekly_")) { when = "this week"; } skipTooltip = `Skip task ${when}: ${task.title}`; } else { @@ -649,14 +649,14 @@ function createChecklistItem(task) { subtaskList.appendChild(makeSectionStats(task.id)); calcSectionStats(task.id, subtaskList); - subtaskCollapsible.appendChild(subtaskList) + subtaskCollapsible.appendChild(subtaskList); taskItem.appendChild(subtaskCollapsible); updateIncompleteSubtaskCount(task, taskItem); // On Click -> Collapse/Expand parentHeaderDiv.addEventListener("click", (e) => { - if (e.target !== checkbox && !checkbox.contains(e.target) && !controlsContainer.contains(e.target) && !collapseButton.contains(e.target) ) { + if (e.target !== checkbox && !checkbox.contains(e.target) && !controlsContainer.contains(e.target) && !collapseButton.contains(e.target)) { toggleCollapseSubtasks(task); } }); @@ -667,8 +667,7 @@ function createChecklistItem(task) { // Checkbox Changed -> Change Subtasks Checkboxes checkbox.addEventListener("change", checkboxChangeAction(task)); - - } else { //no subtasks + } else { // no subtasks taskItem.appendChild(checkbox); if (task.icon) { taskItem.appendChild(icon); } taskItem.appendChild(taskDescription); @@ -704,7 +703,7 @@ function checkboxChangeAction(task) { // don't know about the checkbox status of the originating event. So we attach that status to the // `detail` of a CustomEvent, which takes priority over the local status. (Recursive firings like this // allow for nested subtasks of arbitrary depth) - subCheckbox.dispatchEvent(new CustomEvent("change", {detail: currentlyChecked})); + subCheckbox.dispatchEvent(new CustomEvent("change", { detail: currentlyChecked })); }); updateIncompleteSubtaskCount(task); } else { @@ -714,28 +713,28 @@ function checkboxChangeAction(task) { calcSectionStats(task.section); saveData(); - } + }; } function hideOrSkipTaskAction(task, skip) { return (event) => { event.stopPropagation(); - if (skip) { checklistData.skippedTasks[task.id] = true; } + if (skip) { checklistData.skippedTasks[task.id] = true; } /* eslint-disable-line @stylistic/brace-style */ else { checklistData.hiddenTasks[task.id] = true; } const taskItem = event.target.closest(".task-item"); taskItem.classList.add("hidden-task"); updateParentCheckboxes(task); updateSectionControls(taskItem.closest("section").id); saveData(false); - } + }; } function updateParentCheckboxes(task) { let t = task; - while (t.parentId) { // walk up the task tree + while (t.parentId) { // walk up the task tree calcSectionStats(t.parentId); - let parentTaskDefinition = getTaskById(t.parentId); + const parentTaskDefinition = getTaskById(t.parentId); if (parentTaskDefinition && parentTaskDefinition.subtasks) { const allSubtasksDone = parentTaskDefinition.subtasks.every((st) => (checklistData.progress[st.id] || checklistData.hiddenTasks[st.id] || checklistData.skippedTasks[st.id])); @@ -749,7 +748,7 @@ function updateParentCheckboxes(task) { if (parentDescription) { parentDescription.classList.toggle("checked", allSubtasksDone); } } - t = parentTaskDefinition; // move up a level + t = parentTaskDefinition; // move up a level } calcSectionStats(task.section); saveData(); @@ -765,10 +764,10 @@ function toggleCollapseSubtasks(task) { updateIncompleteSubtaskCount(task); } -function updateIncompleteSubtaskCount(task, queryFrom=document) { +function updateIncompleteSubtaskCount(task, queryFrom = document) { if (task.subtasks) { const element = queryFrom.querySelector(`#${task.id} ~ .collapse-btn .incomplete-count > div`); - const unchecked = queryFrom.querySelectorAll(`input[data-parent-id="${task.id}"]:not(:checked, :indeterminate, .hidden-task *)`) + const unchecked = queryFrom.querySelectorAll(`input[data-parent-id="${task.id}"]:not(:checked, :indeterminate, .hidden-task *)`); element.innerText = unchecked.length; element.parentElement.dataset.count = unchecked.length; element.parentElement.title = `${unchecked.length} incomplete subtasks of ${task.title}`; @@ -778,7 +777,7 @@ function updateIncompleteSubtaskCount(task, queryFrom=document) { function taskDialogHeaderSetup(task, dialog) { dialog.querySelector(":scope header .task-title").innerHTML = task?.title || ""; - let taskIcon = dialog.querySelector(":scope .menu-title img.task-icon"); + const taskIcon = dialog.querySelector(":scope .menu-title img.task-icon"); taskIcon.className = "task-icon"; // remove possible `icon-filter` from previous opening taskIcon.src = ""; if (task?.icon) { @@ -798,7 +797,7 @@ function showScheduleAction(task, cycleIndex, isAvailable) { thead.innerHTML = ""; tbody.innerHTML = ""; - let header = `Date`; + let header = "Date"; for (const column of cycles[task.id].columns) { header += `${column.name}`; } @@ -837,7 +836,7 @@ function showScheduleAction(task, cycleIndex, isAvailable) { tbody.innerHTML += row; } scheduleDialog.showModal(); - } + }; } function showMoreInfoAction(task) { @@ -845,10 +844,10 @@ function showMoreInfoAction(task) { taskDialogHeaderSetup(task, moreInfoDialog); document.getElementById("more-info-content").innerHTML = task.moreInfo; moreInfoDialog.showModal(); - } + }; } -function makeInfoLine(task, appendTo) { +function makeInfoLine(task, appendTo) { /* eslint-disable-line max-lines-per-function */ const hasCycle = Object.hasOwn(cycles, task.id); const hasInfoLine = ["location", "npc", "terminal", "prereq", "info", "moreInfo"].some((prop) => task[prop]); @@ -907,7 +906,7 @@ function makeInfoLine(task, appendTo) { // Info Line if (hasInfoLine) { - if (task.npc && task.terminal) {console.warn(`[${task.id}] Tasks should specify only one of [npc, terminal].`);} + if (task.npc && task.terminal) { console.warn(`[${task.id}] Tasks should specify only one of [npc, terminal].`); } const infoLine = document.createElement("div"); infoLine.classList.add("info-line"); let infoLineHTML = ""; @@ -952,7 +951,7 @@ function populateSection(section) { sectionElement.appendChild(makeSectionStats(section)); calcSectionStats(section); - let updatedParents = new Set(); + const updatedParents = new Set(); forEachTask((task) => { if (task.section === section && task.parentId && !task.subtasks && !updatedParents.has(task.parentId)) { // if the task is a non-root leaf node in the current section, and the first among its siblings @@ -970,7 +969,7 @@ function populateSection(section) { * @param parent - what task list to count stats on. This can be the name of a section, or the id of a task with subtasks. * @param queryFrom - DOM element to find the stats box in. Defaults to `document`. Override this if the element is not inserted into the document yet. */ -function calcSectionStats(parent, queryFrom=document) { +function calcSectionStats(parent, queryFrom = document) { let taskList; if (parent.includes("_")) { taskList = getTaskById(parent).subtasks; @@ -979,15 +978,15 @@ function calcSectionStats(parent, queryFrom=document) { } const statsBox = queryFrom.querySelector(`#stats_${parent} > div`); - let stats = { + const stats = { completed: 0, skipped: 0, - hidden: 0 - } + hidden: 0, + }; for (const task of taskList) { - if (checklistData.progress[task.id]) { stats.completed++; } + if (checklistData.progress[task.id]) { stats.completed++; } if (checklistData.skippedTasks[task.id]) { stats.skipped++; } - if (checklistData.hiddenTasks[task.id]) { stats.hidden++; } + if (checklistData.hiddenTasks[task.id]) { stats.hidden++; } } statsBox.innerHTML = ""; @@ -995,8 +994,8 @@ function calcSectionStats(parent, queryFrom=document) { const statIcons = { completed: "✔", skipped: svgIcons.skipIcon, - hidden: svgIcons.hideIcon - } + hidden: svgIcons.hideIcon, + }; for (const stat in stats) { const statButton = document.createElement("button"); @@ -1074,7 +1073,7 @@ function showHiddenTasksAction(parent, taskList, stat) { } hiddenTasksDialog.showModal(); - } + }; } function hiddenTasksButtonAction(taskElement, task, stat) { @@ -1098,7 +1097,7 @@ function hiddenTasksButtonAction(taskElement, task, stat) { if (!hiddenTasksDialog.querySelector("li > :not(.hidden-task)")) { hiddenTasksDialog.close(); } - } + }; } function resetSpecificButtonState(buttonElement, defaultText, stateKey) { @@ -1107,7 +1106,7 @@ function resetSpecificButtonState(buttonElement, defaultText, stateKey) { confirmState[stateKey].timeout = null; confirmState[stateKey].isConfirming = false; buttonElement.textContent = defaultText; - buttonElement.classList.remove('confirming'); + buttonElement.classList.remove("confirming"); console.log(`Button ${buttonElement.id} state reverted.`); } @@ -1121,10 +1120,12 @@ function handleResetConfirmation(buttonElement, confirmKey, defaultText, resetAc Object.keys(confirmState).forEach((key) => { if (key !== confirmKey && confirmState[key].isConfirming) { let btnElement, btnText; - if (key === 'all') { btnElement = resetButton; btnText = 'Reset All Checks'; } - else if (key === 'daily') { btnElement = resetDailyButton; btnText = 'Reset Daily Checks'; } - else if (key === 'weekly') { btnElement = resetWeeklyButton; btnText = 'Reset Weekly Checks'; } - else if (key === 'unhide') { btnElement = unhideTasksButton; btnText = 'Unhide All Tasks'; } + /* eslint-disable @stylistic/max-statements-per-line, @stylistic/brace-style */ + if (key === "all") { btnElement = resetButton; btnText = "Reset All Checks"; } + else if (key === "daily") { btnElement = resetDailyButton; btnText = "Reset Daily Checks"; } + else if (key === "weekly") { btnElement = resetWeeklyButton; btnText = "Reset Weekly Checks"; } + else if (key === "unhide") { btnElement = unhideTasksButton; btnText = "Unhide All Tasks"; } + /* eslint-enable @stylistic/max-statements-per-line, @stylistic/brace-style */ if (btnElement) { resetSpecificButtonState(btnElement, btnText, key); } @@ -1138,8 +1139,8 @@ function handleResetConfirmation(buttonElement, confirmKey, defaultText, resetAc resetSpecificButtonState(buttonElement, defaultText, confirmKey); } else { confirmState[confirmKey].isConfirming = true; - buttonElement.textContent = 'Are you Sure?'; - buttonElement.classList.add('confirming'); + buttonElement.textContent = "Are you Sure?"; + buttonElement.classList.add("confirming"); clearTimeout(confirmState[confirmKey].timeout); confirmState[confirmKey].timeout = setTimeout(() => { @@ -1158,7 +1159,7 @@ function resetAllAction() { console.log("Checklist reset complete."); } -function resetSection(section, resetAltRefTasks=false) { +function resetSection(section, resetAltRefTasks = false) { const validSections = ["daily", "weekly"]; if (!validSections.includes(section)) { console.error("Section '%s' is not a valid section name: %s", section, validSections); @@ -1180,7 +1181,7 @@ function resetSection(section, resetAltRefTasks=false) { tasks[section].forEach(resetTask); const now = new Date().toISOString(); - if (section === "daily") { checklistData.lastDailyReset = now; } + if (section === "daily") { checklistData.lastDailyReset = now; } /* eslint-disable-line @stylistic/brace-style */ else if (section === "weekly") { checklistData.lastWeeklyReset = now; } saveData(); if (didReset) { @@ -1198,17 +1199,17 @@ function resetWeeklyAction() { } function handleSectionToggle(event) { - const header = event.target.closest('.section-toggle'); + const header = event.target.closest(".section-toggle"); if (!header) { return; } - const contentId = header.getAttribute('aria-controls'); + const contentId = header.getAttribute("aria-controls"); const contentDiv = document.getElementById(contentId); if (!contentDiv) { return; } - const isExpanded = header.getAttribute('aria-expanded') === 'true'; - header.setAttribute('aria-expanded', !isExpanded); - contentDiv.classList.toggle('collapsed', isExpanded); - console.log(`Toggled section ${contentId} to ${!isExpanded ? 'expanded' : 'collapsed'}`); + const isExpanded = header.getAttribute("aria-expanded") === "true"; + header.setAttribute("aria-expanded", !isExpanded); + contentDiv.classList.toggle("collapsed", isExpanded); + console.log(`Toggled section ${contentId} to ${isExpanded ? "collapsed" : "expanded"}`); } function unhideAllAction() { @@ -1228,35 +1229,35 @@ function updateSectionControls(sectionElementId) { const sectionElement = document.getElementById(sectionElementId); if (!sectionElement) { return; } - const hideSectionButton = sectionElement.querySelector('.hide-section-button'); + const hideSectionButton = sectionElement.querySelector(".hide-section-button"); if (!hideSectionButton) { return; } if (checklistData.manuallyHiddenSections[sectionElementId]) { - sectionElement.classList.add('section-is-hidden-by-user'); - hideSectionButton.classList.remove('visible'); + sectionElement.classList.add("section-is-hidden-by-user"); + hideSectionButton.classList.remove("visible"); return; } else { - sectionElement.classList.remove('section-is-hidden-by-user'); + sectionElement.classList.remove("section-is-hidden-by-user"); } - const contentUl = sectionElement.querySelector('.section-content ul'); + const contentUl = sectionElement.querySelector(".section-content ul"); if (!contentUl) { - hideSectionButton.classList.remove('visible'); + hideSectionButton.classList.remove("visible"); return; } - const allTaskItems = Array.from(contentUl.querySelectorAll('li.task-item')); + const allTaskItems = Array.from(contentUl.querySelectorAll("li.task-item")); if (allTaskItems.length === 0) { - hideSectionButton.classList.remove('visible'); + hideSectionButton.classList.remove("visible"); return; } const allTasksIndividuallyHidden = allTaskItems.every((item) => item.classList.contains("hidden-task")); if (allTasksIndividuallyHidden) { - hideSectionButton.classList.add('visible'); + hideSectionButton.classList.add("visible"); } else { - hideSectionButton.classList.remove('visible'); + hideSectionButton.classList.remove("visible"); } } @@ -1279,7 +1280,7 @@ function saveData(showStatus = true) { } catch (e) { console.error("Error saving data to localStorage:", e); let userMessage = "Could not save progress."; - if (e.name === 'QuotaExceededError' || (e.code && (e.code === 22 || e.code === 1014))) { + if (e.name === "QuotaExceededError" || (e.code && (e.code === 22 || e.code === 1014))) { userMessage = "Could not save progress. Browser storage might be full."; } displayError(userMessage); @@ -1293,7 +1294,7 @@ function loadData() { const parsedData = JSON.parse(savedData); if (parsedData && typeof parsedData === "object") { for (const key of Object.keys(checklistData)) { - if (key in parsedData) { + if (key in parsedData) { /* eslint-disable-line max-depth */ checklistData[key] = parsedData[key]; } } @@ -1306,7 +1307,7 @@ function loadData() { } } -export function loadAndInitializeApp() { +export function loadAndInitializeApp() { /* eslint-disable-line max-lines-per-function */ initializeDOMElements(); hideError(); loadThemePreference(); @@ -1319,7 +1320,7 @@ export function loadAndInitializeApp() { updateLastSavedDisplay(checklistData.lastSaved); // Setup event listeners - if (appVersionElement) { appVersionElement.textContent = APP_VERSION; } + if (appVersionElement) { appVersionElement.textContent = APP_VERSION; } /* eslint-disable-line @stylistic/brace-style */ else { console.error("App version element not found!"); } if (gitHashElement) { @@ -1327,8 +1328,9 @@ export function loadAndInitializeApp() { gitHashElement.href = `https://github.com/warframe-tools/Task-Checklist/tree/${GIT_COMMIT_HASH_LONG}`; } else { console.error("git hash element not found!"); } - if (wfVersionElement) { wfVersionElement.textContent = `Warframe Version ${WARFRAME_VERSION}`; } - else { console.error("Warframe version element not found!"); } + if (wfVersionElement) { + wfVersionElement.textContent = `Warframe Version ${WARFRAME_VERSION}`; + } else { console.error("Warframe version element not found!"); } if (hideCompletedToggle) { hideCompletedToggle.addEventListener("change", (event) => { @@ -1338,59 +1340,64 @@ export function loadAndInitializeApp() { }); hideCompletedToggle.checked = checklistData.hideCompletedTasks; bodyElement.classList.toggle("hide-completed-tasks", checklistData.hideCompletedTasks); - } - else { console.error("Hide Completed Toggle not found!"); } + } else { console.error("Hide Completed Toggle not found!"); } - if (resetDailyButton) { resetDailyButton.addEventListener('click', () => handleResetConfirmation(resetDailyButton, 'daily', 'Reset Daily Checks', resetDailyAction)); } - else { console.error("Reset Daily button element not found!"); } + if (resetDailyButton) { + resetDailyButton.addEventListener("click", () => handleResetConfirmation(resetDailyButton, "daily", "Reset Daily Checks", resetDailyAction)); + } else { console.error("Reset Daily button element not found!"); } - if (resetWeeklyButton) { resetWeeklyButton.addEventListener('click', () => handleResetConfirmation(resetWeeklyButton, 'weekly', 'Reset Weekly Checks', resetWeeklyAction)); } - else { console.error("Reset Weekly button element not found!"); } + if (resetWeeklyButton) { + resetWeeklyButton.addEventListener("click", () => handleResetConfirmation(resetWeeklyButton, "weekly", "Reset Weekly Checks", resetWeeklyAction)); + } else { console.error("Reset Weekly button element not found!"); } - if (resetButton) { resetButton.addEventListener('click', () => handleResetConfirmation(resetButton, 'all', 'Reset All Checks', resetAllAction)); } - else { console.error("Reset All button element not found!"); } + if (resetButton) { + resetButton.addEventListener("click", () => handleResetConfirmation(resetButton, "all", "Reset All Checks", resetAllAction)); + } else { console.error("Reset All button element not found!"); } - if (unhideTasksButton) { unhideTasksButton.addEventListener('click', () => handleResetConfirmation(unhideTasksButton, 'unhide', 'Unhide All Tasks', unhideAllAction)); } - else { console.error("Unhide Tasks button not found!");} + if (unhideTasksButton) { + unhideTasksButton.addEventListener("click", () => handleResetConfirmation(unhideTasksButton, "unhide", "Unhide All Tasks", unhideAllAction)); + } else { console.error("Unhide Tasks button not found!"); } - if (themeToggleButton) { themeToggleButton.addEventListener('click', handleThemeToggle); } - else { console.error("Theme toggle button not found!"); } + if (themeToggleButton) { + themeToggleButton.addEventListener("click", handleThemeToggle); + } else { console.error("Theme toggle button not found!"); } - if (hamburgerButton) { hamburgerButton.addEventListener('click', () => {optionsMenu.showModal();}); } - else { console.error("Hamburger button not found!"); } + if (hamburgerButton) { + hamburgerButton.addEventListener("click", () => { optionsMenu.showModal(); }); + } else { console.error("Hamburger button not found!"); } sectionToggles.forEach((toggle) => { toggle.addEventListener("click", handleSectionToggle); }); try { - document.getElementById('checklist-container').addEventListener('click', function(event) { - if (event.target.classList.contains('hide-section-button')) { + document.getElementById("checklist-container").addEventListener("click", (event) => { + if (event.target.classList.contains("hide-section-button")) { const sectionId = event.target.dataset.sectionId; if (sectionId) { const sectionElement = document.getElementById(sectionId); if (sectionElement) { checklistData.manuallyHiddenSections[sectionId] = true; - sectionElement.classList.add('section-is-hidden-by-user'); - event.target.classList.remove('visible'); + sectionElement.classList.add("section-is-hidden-by-user"); + event.target.classList.remove("visible"); saveData(false); console.log(`Section ${sectionId} manually hidden.`); } } } }); - } catch (e) { + } catch { console.error("Checklist container not found!"); } if (errorCloseButton) { - errorCloseButton.addEventListener('click', hideError); + errorCloseButton.addEventListener("click", hideError); } else { console.error("Error close button not found!"); } if (errorCopyButton) { - errorCopyButton.addEventListener('click', copyErrorToClipboard); + errorCopyButton.addEventListener("click", copyErrorToClipboard); } else { console.error("Error copy button not found!"); } for (const dialog of document.getElementsByTagName("dialog")) { @@ -1418,7 +1425,7 @@ document.addEventListener("DOMContentLoaded", () => { try { loadAndInitializeApp(); startCountdown(); - } catch(error) { + } catch (error) { console.error("Critical Error during app.js initialization:", error); const errDisp = document.getElementById("error-display"); const errMsg = document.getElementById("error-message"); diff --git a/sources/js/constants.js b/sources/js/constants.js index 2c8253b..a2f4d11 100644 --- a/sources/js/constants.js +++ b/sources/js/constants.js @@ -4,7 +4,7 @@ export const MILLISECONDS_PER_MINUTE = 60 * MILLISECONDS_PER_SECOND; export const MILLISECONDS_PER_HOUR = 60 * MILLISECONDS_PER_MINUTE; export const MILLISECONDS_PER_DAY = 24 * MILLISECONDS_PER_HOUR; -export const SERVER_TIMEZONE = "America/Toronto"; // used for determining Daylight Saving Time +export const SERVER_TIMEZONE = "America/Toronto"; // used for determining Daylight Saving Time export const BASE_OF_OPERATIONS_TOOLTIP = 'Base of Operations'; @@ -17,7 +17,7 @@ export const TASKLIST_STAT_NAMES = { export const TASKLIST_STAT_PROPERTIES = { "completed": "progress", "skipped": "skippedTasks", - "hidden": "hiddenTasks" + "hidden": "hiddenTasks", }; export const SECTION_NAMES = { diff --git a/sources/js/functions.js b/sources/js/functions.js index 7b8bddb..9da275f 100644 --- a/sources/js/functions.js +++ b/sources/js/functions.js @@ -28,7 +28,7 @@ export function newChecklistData() { }; } -const taskIcons = import.meta.glob("../img/icons/**/*.png", {eager: true, query: '?url', import: 'default'}); +const taskIcons = import.meta.glob("../img/icons/**/*.png", { eager: true, query: "?url", import: "default" }); export function iconURL(iconName) { return taskIcons["../img/icons/" + iconName]; } @@ -51,7 +51,7 @@ export function makeTaskIcon(task) { export function makeCycleIcon(cycleData) { if (cycleData.icon) { - const src = iconURL(`cycles/${cycleData.icon}`) + const src = iconURL(`cycles/${cycleData.icon}`); let classList = "cycle-icon"; if (cycleData.iconFilter) { classList += " icon-filter"; @@ -63,12 +63,15 @@ export function makeCycleIcon(cycleData) { } export function formatTimestamp(timestamp) { - if (!timestamp) return 'Never'; + if (!timestamp) { return "Never"; } try { const date = new Date(timestamp); - if (isNaN(date.getTime())) return 'Invalid Date'; - return date.toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' }); - } catch (e) { console.error("Error formatting timestamp:", e); return 'Error'; } + if (isNaN(date.getTime())) { return "Invalid Date"; } + return date.toLocaleString(undefined, { dateStyle: "medium", timeStyle: "short" }); + } catch (e) { + console.error("Error formatting timestamp:", e); + return "Error"; + } } export function getMostRecentMondayMidnightUTC() { @@ -91,8 +94,8 @@ export function getNextDailyMidnightUTC() { export function getUTCDateString(dateObj) { const year = dateObj.getUTCFullYear(); - const month = (dateObj.getUTCMonth() + 1).toString().padStart(2, '0'); - const day = dateObj.getUTCDate().toString().padStart(2, '0'); + const month = (dateObj.getUTCMonth() + 1).toString().padStart(2, "0"); + const day = dateObj.getUTCDate().toString().padStart(2, "0"); return `${year}-${month}-${day}`; } @@ -113,7 +116,7 @@ export function formatCountdown(ms) { ms %= C.MILLISECONDS_PER_MINUTE; const seconds = Math.floor(ms / C.MILLISECONDS_PER_SECOND); - const pad = (num) => String(num).padStart(2, '0'); + function pad(num) { return String(num).padStart(2, "0"); } if (days > 0) { return `${days}d ${pad(hours)}:${pad(minutes)}:${pad(seconds)}`; @@ -127,16 +130,16 @@ export function formatCountdown(ms) { * Case insensitive. Integers only. */ export function parseDuration(str) { - if (!str || typeof str !== "string") {return undefined;} + if (!str || typeof str !== "string") { return undefined; } const map = { "d": C.MILLISECONDS_PER_DAY, "h": C.MILLISECONDS_PER_HOUR, "m": C.MILLISECONDS_PER_MINUTE, - "s": C.MILLISECONDS_PER_SECOND + "s": C.MILLISECONDS_PER_SECOND, }; return str.toLowerCase().matchAll(/((\d+)([a-z]))/g).toArray().reduce((acc, curr) => { - const n = parseInt(curr[2]); + const n = parseInt(curr[2], 10); let mult; if (Object.hasOwn(map, curr[3])) { mult = map[curr[3]]; @@ -150,10 +153,10 @@ export function parseDuration(str) { /** returns whether the given date is in Daylight Saving Time in the named timezone */ export function isDst(date, timezone) { - if (typeof date === "undefined" || Number.isNaN(date)) {return undefined;} - if (typeof date === "number" || typeof date === "string") {date = new Date(date);} + if (typeof date === "undefined" || Number.isNaN(date)) { return undefined; } + if (typeof date === "number" || typeof date === "string") { date = new Date(date); } - const dateFormat = Intl.DateTimeFormat("en-CA", {timeZone: timezone, timeZoneName: "shortOffset"}); + const dateFormat = Intl.DateTimeFormat("en-CA", { timeZone: timezone, timeZoneName: "shortOffset" }); function wholeHourOffset(d) { // returns the whole hour part of the UTC offset as an integer. @@ -165,7 +168,7 @@ export function isDst(date, timezone) { const year = date.getUTCFullYear(); const janOffset = wholeHourOffset(new Date(Date.UTC(year, 0, 1))); const julOffset = wholeHourOffset(new Date(Date.UTC(year, 6, 1))); - if (janOffset === julOffset) {return false;} + if (janOffset === julOffset) { return false; } const currentOffset = wholeHourOffset(date); const dstOffset = Math.max(janOffset, julOffset); return currentOffset === dstOffset; @@ -206,14 +209,14 @@ export function calcTaskTimes(task, date) { let thisCycleLeaveTimestamp = prevResetTimestamp + parseDuration(task.duration); if (task.observesDst) { - if (isDst(nextResetTimestamp, C.SERVER_TIMEZONE)) {nextResetTimestamp -= C.MILLISECONDS_PER_HOUR;} - if (isDst(thisCycleLeaveTimestamp, C.SERVER_TIMEZONE)) {thisCycleLeaveTimestamp -= C.MILLISECONDS_PER_HOUR;} + if (isDst(nextResetTimestamp, C.SERVER_TIMEZONE)) { nextResetTimestamp -= C.MILLISECONDS_PER_HOUR; } + if (isDst(thisCycleLeaveTimestamp, C.SERVER_TIMEZONE)) { thisCycleLeaveTimestamp -= C.MILLISECONDS_PER_HOUR; } } let isAvailable = true; - if (task.duration) {isAvailable = (date.getTime() < thisCycleLeaveTimestamp);} + if (task.duration) { isAvailable = (date.getTime() < thisCycleLeaveTimestamp); } - return {nextResetTimestamp, thisCycleLeaveTimestamp, isAvailable}; + return { nextResetTimestamp, thisCycleLeaveTimestamp, isAvailable }; } export function factionIcon(name) { diff --git a/sources/js/icons.js b/sources/js/icons.js index 1cdbffd..d9f8cfb 100644 --- a/sources/js/icons.js +++ b/sources/js/icons.js @@ -1,3 +1,5 @@ +/* eslint-disable @stylistic/operator-linebreak, @stylistic/indent */ + /* Heroicons https://heroicons.com/ * MIT license https://github.com/tailwindlabs/heroicons/blob/master/LICENSE */ @@ -25,7 +27,7 @@ const eyeOutline = c-4.638 0-8.573-3.007-9.963-7.178Z" /> -` +`; const bellOutline = ` @@ -100,7 +102,7 @@ const calendarDays16 = a.75.75 0 0 0-1.5 0V3h-5V1.75A.75.75 0 0 0 4.75 1ZM3.5 7a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v4.5a1 1 0 0 1-1 1h-7 a1 1 0 0 1-1-1V7Z" /> -` +`; /* Lucide icons https://github.com/lucide-icons/lucide @@ -110,11 +112,13 @@ const calendarDays16 = // https://icon-sets.iconify.design/lucide/skip-forward/ const skipForward = ` - -` +`; + +/* eslint-enable @stylistic/indent */ export { chevronDownOutline as collapseIcon, eyeSlashOutline as hideIcon, diff --git a/sources/js/moreInfo.js b/sources/js/moreInfo.js index e213152..24846fb 100644 --- a/sources/js/moreInfo.js +++ b/sources/js/moreInfo.js @@ -12,7 +12,7 @@ const factions = `

The Faction Syndicates are ${factionIcon("FactionSigilBusiness.png")}The Perrin Sequence, ${factionIcon("FactionSigilAssassins.png")}Red Veil, and ${factionIcon("FactionSigilChurch.png")}New Loka.

-

Pledge your loyalty to a faction syndicate at the Syndicates console in your ${C.BASE_OF_OPERATIONS_TOOLTIP}.

` +

Pledge your loyalty to a faction syndicate at the Syndicates console in your ${C.BASE_OF_OPERATIONS_TOOLTIP}.

`; export default { daily_first_win_bonus: `

Your first completed mission after the daily reset gives double base credit rewards. This only applies to the end-of-mission bonus, and does not apply to credits picked up in the mission.

@@ -70,5 +70,5 @@ export default {

Each week, a random planet will reward double bonus Vault resources (and double reward track progress) for missions played there.

Check the current boosted planet and track your reward progress in the Clan menu.

Note: You can use the "Clan Only" matchmaking option to join squads with your Clan or Alliance members, but playing with Alliance members does not give bonus Vault resources or reward progress.

-

* Descendia missions do not contribute to Clan Weekly Initiatives.

` -} +

* Descendia missions do not contribute to Clan Weekly Initiatives.

`, +}; diff --git a/sources/tests/app.test.js b/sources/tests/app.test.js index 49fde38..f5f35b3 100644 --- a/sources/tests/app.test.js +++ b/sources/tests/app.test.js @@ -9,7 +9,7 @@ beforeEach(() => { afterEach(() => { vi.useRealTimers(); -}) +}); describe("displayOtherTaskCountdown({period, duration, ref, observesDst})", () => { beforeEach(() => { @@ -50,9 +50,9 @@ describe("displayOtherTaskCountdown({period, duration, ref, observesDst})", () = ["14d", "2d", "2022-12-30T09:00:00-05:00", true, "2024-11-03T09:00:00-05:00", "(Available in 12d 00:00:00)"], ])("(%s, %s, %s, %s) @ %s -> %s", ([period, duration, ref, observesDst, date, countdown]) => { vi.setSystemTime(date); - app.displayOtherTaskCountdown({id: "other_test", period, duration, ref, observesDst}); + app.displayOtherTaskCountdown({ id: "other_test", period, duration, ref, observesDst }); expect(document.querySelector(".other-countdown").textContent).toEqual(countdown); - }) + }); }); describe("getTaskById", () => { @@ -64,8 +64,8 @@ describe("getTaskById", () => { ["weekly_netracells", "NetraRequiemIcon.png"], // 2nd level weekly ["daily_kim_hex_parent", "KIM/RetroPfpG.png"], // both a parent and child ["daily_kim_kaya", "KIM/RetroPfpH.png"], // 3rd level task - ["fake_task_id", undefined] + ["fake_task_id", undefined], ])("%s", ([id, icon]) => { expect(app.getTaskById(id)?.icon).toEqual(icon); - }) + }); }); diff --git a/sources/tests/functions.test.js b/sources/tests/functions.test.js index dbb78d6..7cc162e 100644 --- a/sources/tests/functions.test.js +++ b/sources/tests/functions.test.js @@ -47,7 +47,7 @@ describe("Daylight Saving Time", () => { ["2025-10-05T01:59:59+10:30", "Australia/Lord_Howe", false], // just before start ["2025-10-05T02:00:00+10:30", "Australia/Lord_Howe", true], // just after start ["2025-10-05T03:00:00+11:00", "Australia/Lord_Howe", true], // just after start - ])(`isDst(%s, %s) -> %o`, ([d, tz, expected]) => { + ])("isDst(%s, %s) -> %o", ([d, tz, expected]) => { expect(isDst(new Date(d), tz)).toBe(expected); expect(isDst(new Date(d).getTime(), tz)).toBe(expected); expect(isDst(d, tz)).toBe(expected); @@ -63,8 +63,8 @@ describe("parseDuration", () => { ["12h", 43_200_000], ["14d", 1_209_600_000], ["2d3H10M12s", 184_212_000], - ["1m, 359h 1d 3d, 5m6s 4h", 1_652_766_000] - ])(`parseDuration(%s) -> %i`, ([d, expected]) => { + ["1m, 359h 1d 3d, 5m6s 4h", 1_652_766_000], + ])("parseDuration(%s) -> %i", ([d, expected]) => { expect(parseDuration(d)).toEqual(expected); }); @@ -75,8 +75,8 @@ describe("parseDuration", () => { test.for([ ["1s 10n", 1, 1000], ["10y5w2d3h8x10m12s13g", 4, 184_212_000], - ["1m, 359h 9p1d 3d, 5m6s 4h\t1234v", 2, 1_652_766_000] - ])(`parseDuration(%s) warn %i`, ([d, warnings, expected]) => { + ["1m, 359h 9p1d 3d, 5m6s 4h\t1234v", 2, 1_652_766_000], + ])("parseDuration(%s) warn %i", ([d, warnings, expected]) => { const consoleWarn = vi.spyOn(console, "warn"); expect(parseDuration(d)).toEqual(expected); expect(consoleWarn).toHaveBeenCalledTimes(warnings); diff --git a/sources/tests/tasks.test.js b/sources/tests/tasks.test.js index 6446031..fec81ae 100644 --- a/sources/tests/tasks.test.js +++ b/sources/tests/tasks.test.js @@ -2,10 +2,10 @@ import { describe, expect, test } from "vitest"; import Ajv from "ajv/dist/2020"; import addFormats from "ajv-formats"; -import tasks from "../js/tasks.json" with {type: "json"}; -import tasks_schema from "./tasks.schema.json" with {type: "json"}; -import cycles from "../js/cycles.json" with {type: "json"}; -import cycles_schema from "./cycles.schema.json" with {type: "json"}; +import tasks from "../js/tasks.json" with { type: "json" }; +import tasks_schema from "./tasks.schema.json" with { type: "json" }; +import cycles from "../js/cycles.json" with { type: "json" }; +import cycles_schema from "./cycles.schema.json" with { type: "json" }; import moreInfo from "../js/moreInfo"; const ajv = new Ajv({ allErrors: true }); @@ -17,7 +17,7 @@ const validate_cycles_schema = ajv.compile(cycles_schema); describe("valildate task definitions", () => { test.for([ ["tasks", validate_tasks_schema, tasks], - ["cycles", validate_cycles_schema, cycles] + ["cycles", validate_cycles_schema, cycles], ])("validate %s against schema", ([which, validation_function, data]) => { const valid = validation_function(data); if (!valid) { console.error(validation_function.errors); } @@ -26,8 +26,8 @@ describe("valildate task definitions", () => { }); // flatten the nested tree of [sub]tasks into an array - let stack = []; - let flatTasks = []; + const stack = []; + const flatTasks = []; for (const section in tasks) { for (const t of tasks[section]) { stack.push(t); @@ -46,7 +46,7 @@ describe("valildate task definitions", () => { const task_ids = flatTasks.map((t) => t.id); test("verify unique task ids", () => { - let used_ids = []; + const used_ids = []; for (const id of task_ids) { expect(used_ids, "task ids must be unique").not.toContain(id); used_ids.push(id); @@ -58,7 +58,7 @@ describe("valildate task definitions", () => { describe("verify equal `order` lengths", () => { test.for(cycle_keys_for_test)("%s", ([task_id]) => { for (const col of cycles[task_id].columns) { - expect(col.order.length, "column lengths are not equal").toEqual(cycles[task_id].columns[0].order.length) + expect(col.order.length, "column lengths are not equal").toEqual(cycles[task_id].columns[0].order.length); } }); }); diff --git a/sources/tests/version.test.js b/sources/tests/version.test.js index 4779748..6dac8a3 100644 --- a/sources/tests/version.test.js +++ b/sources/tests/version.test.js @@ -12,6 +12,6 @@ describe("check version numbers", () => { test("SECURITY.md", () => { const security = readFileSync(path.resolve(__dirname, "../../SECURITY.md"), "utf-8"); const major = security.match(/\| Version \| Supported\s*\|[\r\n]*\| -* \| -* \|[\r\n]*\| (\d+)\.x\.x/)[1]; - expect(major, "SECURITY.md version number does not match app.js APP_VERSION major version number").toEqual(APP_VERSION.split(".")[0]) + expect(major, "SECURITY.md version number does not match app.js APP_VERSION major version number").toEqual(APP_VERSION.split(".")[0]); }); }); diff --git a/stylelint.config.mjs b/stylelint.config.mjs new file mode 100644 index 0000000..4fa8f81 --- /dev/null +++ b/stylelint.config.mjs @@ -0,0 +1,45 @@ +/** @type {import("stylelint").Config} */ +export default { + "referenceFiles": ["sources/**/*.css"], + "extends": [ + "stylelint-config-standard", + "@stylistic/stylelint-config", + ], + "reportInvalidScopeDisables": true, + "reportNeedlessDisables": true, + "reportUnscopedDisables": true, + "rules": { + "font-family-name-quotes": "always-unless-keyword", + "value-keyword-case": ["lower", { "ignoreKeywords": ["currentColor"] }], + "color-hex-length": null, + "property-no-vendor-prefix": [true, { "severity": "warning" }], + "selector-no-deprecated": true, + "no-descending-specificity": [true, { "severity": "warning" }], + "selector-no-invalid": true, + "no-unknown-animations": true, + "no-unknown-custom-media": true, + "no-unknown-custom-properties": true, + "unit-no-unknown": true, + "at-rule-property-required-list": { + "font-face": ["font-family", "src", "font-style", "font-weight", "font-display"], + }, + "color-named": ["always-where-possible", { "severity": "warning" }], + "declaration-no-important": [true, { "severity": "warning" }], + "unit-disallowed-list": ["ms"], // use "s" instead + "font-weight-notation": "numeric", + // complexity + "max-nesting-depth": [3, { "severity": "warning" }], + "selector-max-compound-selectors": [5, { "severity": "warning" }], + // empty lines + "rule-empty-line-before": null, + "at-rule-empty-line-before": null, + "comment-empty-line-before": null, + "declaration-empty-line-before": null, + "custom-property-empty-line-before": null, + // stylistic + "@stylistic/indentation": [4, { "ignore": "value" }], + "@stylistic/declaration-colon-newline-after": null, + "@stylistic/max-line-length": null, + "@stylistic/unicode-bom": "never", + }, +}; diff --git a/vite.config.js b/vite.config.js index c4d7e3d..68cac98 100644 --- a/vite.config.js +++ b/vite.config.js @@ -11,7 +11,7 @@ export default defineConfig(({ mode }) => ({ cacheDir: "../.vite", plugins: [ - mode === "release" ? viteSingleFile({removeViteModuleLoader: true}) : null, + mode === "release" ? viteSingleFile({ removeViteModuleLoader: true }) : null, ], build: { @@ -24,7 +24,7 @@ export default defineConfig(({ mode }) => ({ restoreMocks: true, coverage: { reportsDirectory: "../.coverage", - exclude: ["img/", "*.json"] - } - } + exclude: ["img/", "*.json"], + }, + }, })); From 4e91bfde028c42f21662ee6d508a72848af3b1be Mon Sep 17 00:00:00 2001 From: AnSq Date: Mon, 10 Aug 2026 08:52:23 -0700 Subject: [PATCH 2/3] don't use eslint for css --- eslint.config.js | 28 ---------------------------- package-lock.json | 41 ++--------------------------------------- package.json | 1 - sources/css/style.css | 5 ++--- 4 files changed, 4 insertions(+), 71 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 407d459..16e0625 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,7 +1,6 @@ import js from "@eslint/js"; import globals from "globals"; import json from "@eslint/json"; -import css from "@eslint/css"; import { defineConfig } from "eslint/config"; import stylistic from "@stylistic/eslint-plugin"; @@ -104,31 +103,4 @@ export default defineConfig([ language: "json/json", extends: ["json/recommended"], }, - { - files: ["sources/**/*.css"], - plugins: { css }, - language: "css/css", - extends: ["css/recommended"], - languageOptions: { - tolerant: true, - }, - rules: { - /* allowUnknownVariables suppresses errors from variables defined in other files. - Stylelint does proper checking for this kind of error with its `referenceFiles` feature. */ - "css/no-invalid-properties": ["error", { "allowUnknownVariables": true }], - "css/use-baseline": ["warn", { - "available": "widely", - "allowProperties": [ - "backdrop-filter", // baseline 2024 - ], - "allowPropertyValues": { - "background-attachment": ["fixed"], // only unavailable in iOS - }, - "allowAtRules": [ - "starting-style", // baseline 2024 - ], - }], - "css/no-important": "warn", - }, - }, ]); diff --git a/package-lock.json b/package-lock.json index 646611c..a062364 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,14 @@ { "name": "task-checklist", - "version": "5.3", + "version": "5.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "task-checklist", - "version": "5.3", + "version": "5.3.1", "license": "GPL-3.0-or-later", "devDependencies": { - "@eslint/css": "^1.4.0", "@eslint/js": "^10.0.1", "@eslint/json": "^2.0.1", "@stylistic/eslint-plugin": "^5.10.0", @@ -563,42 +562,6 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/css": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@eslint/css/-/css-1.4.0.tgz", - "integrity": "sha512-OnRNKgnbX+tufPuZc2kOJS+v1iIARvfJHRNEAVwN77DBpojl+rGjEP8NKTL6pEZ7BR+HtwIuSSdrymEFlANGxg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^1.2.1", - "@eslint/css-tree": "^4.0.4", - "@eslint/plugin-kit": "^0.7.2" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/@eslint/css-tree": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@eslint/css-tree/-/css-tree-4.0.5.tgz", - "integrity": "sha512-iPmijIAq4hlIJB86PYmY/fcZORHtjphSqICDbwuw32A/JmkhZQ/K/6TjHE03zqf3n5yABpVcbRAMG8Mi9ojy8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdn-data": "2.29.0", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/@eslint/css-tree/node_modules/mdn-data": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.29.0.tgz", - "integrity": "sha512-pVxQFCcaYUEAH853+v7yoI/qzhxXSq1bTb9obMYGYAN1c3Hen+XDCEvr296XhstrwlSTNgOR7mCSD4JPjbJe5A==", - "dev": true, - "license": "CC0-1.0" - }, "node_modules/@eslint/js": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", diff --git a/package.json b/package.json index e6f15c5..4c6563a 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ }, "homepage": "https://warframetools.com/Task-Checklist/", "devDependencies": { - "@eslint/css": "^1.4.0", "@eslint/js": "^10.0.1", "@eslint/json": "^2.0.1", "@stylistic/eslint-plugin": "^5.10.0", diff --git a/sources/css/style.css b/sources/css/style.css index 14ae7f6..f336a5e 100644 --- a/sources/css/style.css +++ b/sources/css/style.css @@ -420,7 +420,6 @@ body:not(.light-mode) img.icon-filter { font-size: 90%; color: color-mix(in hsl, var(--text-label) 50%, var(--text-secondary) 50%); margin-left: 0.5em; - /* eslint-disable-next-line css/use-baseline -- (text-indent: hanging; baseline 2026) only relevant on very narrow screens for only a small effect */ text-indent: calc(var(--current-cycle-svg-size) + var(--task-info-expander-svg-mr)) hanging; } .cycle-icon { @@ -462,7 +461,7 @@ body:not(.light-mode) img.icon-filter { text-decoration: underline var(--menu-panel-border) 1px; text-underline-offset: 0.25em; } - th::before, /* eslint-disable-line css/no-invalid-properties -- eslint bug workaround */ + th::before, th::after { content: "\00a0\00a0\00a0\00a0"; /* some no-break spaces added so the underline extends a bit on both sides */ } @@ -494,7 +493,7 @@ body:not(.light-mode) img.icon-filter { /* More Info */ #more-info { - p:not(:last-child, :has(+ :is(ul, table))), /* eslint-disable-line css/no-invalid-properties -- eslint bug workaround */ + p:not(:last-child, :has(+ :is(ul, table))), table { margin-bottom: 1em; } From 198fba9b947eacd75a7eaa0942da8e49b7765b0a Mon Sep 17 00:00:00 2001 From: AnSq Date: Sun, 11 Oct 2026 16:25:29 -0700 Subject: [PATCH 3/3] Update to U44.1.1 * added weekly_cryobells, weekly_icebind, and weekly_melica * updated Descendia location to include Sanctum Anatomica * elements with tooltip no longer need `tooltip` class. just having a `title` attribute is enough * replaced some `&` with `&` * cycle text now parses html entities * v5.3.3 --- package-lock.json | 4 +-- package.json | 2 +- sources/css/style.css | 9 +++--- sources/img/icons/tasks/Melica.png | Bin 0 -> 9749 bytes sources/js/app.js | 16 +++++----- sources/js/constants.js | 2 +- sources/js/cycles.json | 2 +- sources/js/tasks.json | 46 +++++++++++++++++++++++------ 8 files changed, 55 insertions(+), 26 deletions(-) create mode 100644 sources/img/icons/tasks/Melica.png diff --git a/package-lock.json b/package-lock.json index 8818fb8..721c810 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "task-checklist", - "version": "5.3.2", + "version": "5.3.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "task-checklist", - "version": "5.3.2", + "version": "5.3.3", "license": "GPL-3.0-or-later", "devDependencies": { "@eslint/js": "^10.0.1", diff --git a/package.json b/package.json index 988a956..63a958d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "task-checklist", - "version": "5.3.2", + "version": "5.3.3", "description": "A Warframe Task Checklist to track daily, weekly, and other tasks. Built with HTML, CSS, and vanilla JavaScript, processed with Vite.", "type": "module", "scripts": { diff --git a/sources/css/style.css b/sources/css/style.css index f336a5e..204e353 100644 --- a/sources/css/style.css +++ b/sources/css/style.css @@ -27,6 +27,11 @@ cursor: pointer; } +[title] { /* has tooltip */ + text-decoration: underline dotted; + cursor: pointer; +} + /* --- Content Box Element Styling (Non-Critical Parts) --- */ #checklist-container h2:hover { background-color: var(--section-header-hover-bg); @@ -542,10 +547,6 @@ body:not(.light-mode) img.icon-filter { .info-line svg path { fill: var(--text-secondary); } -.tooltip { - text-decoration: underline dotted; - cursor: pointer; -} /* Hidden task animation */ .task-expander:has(> .task-item.hidden-task) { diff --git a/sources/img/icons/tasks/Melica.png b/sources/img/icons/tasks/Melica.png new file mode 100644 index 0000000000000000000000000000000000000000..818b2843ad1318c2b3dd53c5395e084825db628a GIT binary patch literal 9749 zcmeI2Wm6nX)2J5-t^tBOBuKDb+?~bU-91=vcU#=ugFC@xA-KCsa3{FSxu4&0-maSN znQEz;>%-J^RYxi*NTH(;p#T5?bZM}-%71q7e+vojKiw^X=>P!00hHv_B>p@8pZp(z z|8EI2vff7gclnQ>DhjFq7+5&?PY8%e$SA02=opw-*q?E5@xI^_5E2oSkdl#8P*PFT z(0=_!N6*0cor#%+l?@1D=iubx=Hcbz7Z4N@77-N_mynbKOUua0$tx%-DXXZescUFz zY3u0f=^Gdt8Jn1znOj&|S=-p!+5d2GbaHn2>FVb0;pye=uTTTb&;Q`;it89W;| zejPz@Jsl~gt94xmafi2DA42_f0=L1L_`$|#4p9}kqU)Zkt-S0P5)hacr zb$;6{RH#=je#F+!De4d&nMS%4oghtx`$?%}sZ98ElL>PGe-!H28Ajucp6BhsF;TckKut;TeY|RR?gk3hsnK8&5 zm!kByHX8e=6jOh0Jp2wOE8dbsGBqq=c-!5&akfu7!OyJ^{i!nw^07-|aPa$Es#cOF zDaN`)+x3ocVUz-Q6+5-Qm9Mq)8y?C#YfTxTZjdz3;bw3A53>x#UjVs=_LxIPO^prr zN8pRmp-n~Fu$CC_1U{ib67!0Xx*3LZ5n@FTf*k*GimI!`*n*PYh(QAP@|x_}{{UGN z8f*sdq>**ffI{r6$aLEk8eyCm!yueFV_l5W@@3;d_xZPZnKe?dz~#>Ya(k zOcix~*ulR4$(nh~0|hekS+JI=wc2>3G3R8&CXQ?6bD0K>AJMs5wErYbRgS2rM+5Ox z$|_{~$cVG3;5iqfxuERbf3_Y4tAC7b7U3K+8wzsqjQ8{=6}KzaGz$r_a5IGa4K0zi z8w^mF*$jX%c!bdQPgaoq|IMDweJfMZUaTSHNl7DVZb?i|x|w2jP)!MADcM@Om=3yn z&*^q|Sih92g*qjH3R?YnL8iqH?)YB!XKip$+}Tb`-cNiQ1#}m2#gTB10rvA7pU8J- zyS|O(4`=cU4!@L!#ccGPPP?yn2K$Z###-P1+|Ac-hU|CCVd9$&ihtHw4{$s;VNUvk ztIOdo0FFo?6wtdg{;~?Z$8h!!B#Y$=8lT3EyS=+}60s<@F{NaXVL2cZ>@>eSp>_Et z7lDDPxTez&bbN^G&oB#%lO4R7HpB1=C#z7j6i(VcjT#42{9ujaR`*ITA3xgaS-M=& zfP(cx#xGraE$P{Bx(mar{N73hb&$4w!2dS8-bikb=f2I|KiR=JzAfG{wn@bu{99|X zJILgb-sUgzKb#y3xa*IBam=>gJN&)}8-hpP4aO7*E||gyW_(d}_y(j-ZRG&`(5D}t z5Yknv?~IQ7A#X~E0|Rm@GLv*b^z(BH{p-9D=}AL)`!jvmh}4&K7;@Er4v;~S{UOpI zvrIYy#K6I)0zLCyM$c^~i{l71p#7ThOzq`;{Vx){b1zb0hUD3go{fKKez<^;GcYgq-+Jb`yh%Ho8>=z|4ISTpz&JBNw*` z%No5x85{%)$1n_;>7V%2$b0$e$s(AY1-@p7P&Sg70tAbDw$mA|aU~NRu)Mz(N5<#& z3LT6b)X0m+0R`ZkrN3oRNLvs@zI2;8C#O=4gA`_KSrzp zlnXAor`xLs59GP$ zl9|K@`uqnL?vG5qW1D!cPi1!C?6xH<1XMD$@13^s9NRy!3SnYUjFe_oQU#W&ipP;}=qD9~A@b`!_JZ?4nR<$aEZSkFR9$;#@s zI0FRY+)oS4`ZXT0A-T&c0R|7#0=mjo{;Km(?(cQ-#xndybj-77mosL+0I&*2dz>kH z8eJIjHCT*fN8*^8poLw^n)oZ@9X>tjP7h(b zcL3C$O|m6j3p7oFm?r?gnIzfP{bYjg+T!<&Z$Oi#Hwh)YWVDh$sZK|?$5}?* z6c?y~G>Ds-qo4E zL#k%>eVb6z$lNT{pw=RoFFTdfb}`D{`#zi7Pz^p=-#3+;^{Su1iVQ>83PZV1wJZTwiuKI&#EA*<%TEi{59LL;0(gHhJur#TF zgLGz+e6!;c*4LDMb}LHzw*ShBl;HN zbc6kH+&Vl&hzvlW)+cI4n`I}HHO@w!DH9%DjK7i3{ofJm`f$rxGvthP;uT_`;t~=o z=cYsf)im&cVW#i=X>GPkgTJ}vU6prZLEnR!TIP(vTHk?#406BdScMW5(9Oa&1P|br z!J>wMr_fMKtwH9l(;dchRM7iemv}qwp%sej0VN~{3{A#i1$^MpTK?gST)1A zC2k+^MYDS}kMTQyVuokex}SchZCH+8;wo?VYHE|?8Mpg|o(N1pG)?i<^0JkLoE$^? zVDX#~R4(fGn$(#azy)me>F@nQP*C<7#%ZBMq+4uCC%Ews8yvyEW#wY?Y-&nvv;P0^ ziOn860I4M@ffk9Ea8r-f`A{c)2qFncBjGYKh2D%A_$AscO}>`TEdsJj(;o%l=EH&d zNRPV=bmbKxdeperx1K8+{Tf(37c-NiDqx$c!%beTjb7psG1K~vpCO9S+`>|z@k?Nr z@=+Ix$LW3oaEymf8jjE$hA2idO4e`P?DgIFoqgR|7nkfLO-N8_bNhjdyV0zRKY`k- z{VEW0kCv{q6AQPzB33W?(h5v2UfOfdef6UWxh~uj=L11slUhvy_gyjy1{;Wf37p7- zGP07B%fNz26saLXnhIpP14@9i`NdnMydE>ILxVYf4Wn$fJHcm@XVOV7|RQgTV@@A27X0t1;v1Ock8ml zq9C{uHYX&k{)tmVIuf7brB&jRMhIUz&#sO7?<$ubr>Acbz&2T+JV?kd(g|#hi4lqR6NlqZg=Yk z1$^OdbbmihGJqGq@GGkK(CA5Aape5FnMabb;dhUdQxOFSZmyIsQ% z+*!0RPthleQ8i27x2LIRB!B(=9%D<(kTF=D4+av<_nGWN@_7sHpe_%TX^C~=!QL5<*;EoJjFkpA9+}w($jwgZLBZ;-gsB7mBWTg6a<*#pDtN$ot|V!XMn@I}EvU z88%_>@7@&yM^~mwnwGI5sVH8&rC{{1#YI27VE=Lq|F6^6FbgB*T~|yWDc7eT@0Jv=movTY(&4ercRO5JUORdQRf z;<(_gtfkA+x66fpB~Zxca5hnCOG2dc*>s@akl?6-O>tD_5m1uZU&8a_)l2H?u0l<9 zIA&YF!>IO>>6RYOTl=b~W;J6RdjuEI-r;fvo(XhLs z;p=NIi~R}(RwPJ7{3=ub3NQD?ajzr(7aqzdpSgtg>(#=BkUI7mk8&bElJAx%3)=TW z?^kjD@2d7Ze9kOF#$HhO;VQ4F0@nSdlr z86vURbobSul=8c5m$8OvY}-r50;_kCNHm*BwN0FH23uWK@k*{2$0{mxv!h_e-hpDv zSUc5ERTn1)Mtj^hm?Bk;Z4g4J#uYg@OAy{+Uwo>_vwtauvF!f=hsnE>tXd<5;`&0p z(CGlL6Tu9*C?>vWe@-RxGToW*Dnc9%jq@g$%Ow35laFR;P|vF8sXVdQnKh6XTT_~t z{4Qn}qm3@q;J}WF+(WeR5QB@iEU&rwFj$MPGJqdibhGwc-LypPskeLbmKQ#1r{><@ z_)F=Ccs+9*S@Ub-@s|I0+{Inx+73hi$L(--%!)PRZbDP#1Bf?jA6w&fVbpf|%kNsI zo`Vx(Ihq+R7SudegLd@3@!S5t;tYJ8xucLcT7o@0g8p@`akjEWVnm8PBjT9oqaM4zrb7JC6QgNj_F1_MVi@sjx&{p@$Dwweaoa+L7% znz7gg@iL`OAwu^L-G(G)(#bS;l1-JjVM)F0aGX1rpO==_h<-{_{|SA-{O}Y*v6&pQy1;50`@MLz3Y0q1C%R!nu zf}nWg=hf9ObUZx+#-mu7-{nF%yg0@;(*rGFr{3|i>#;;;uDvy;k1+oZd93N8YUyRp zmd<$p>uQV>T$R0cH$c^?d*QES8U@$aURDjnm(29=dTeo1)NyJ23%7iV@_t>0-5-CT z@CA;qV^aINHhvL1K5p|{(MIIl)%x6O6sMCgD48|{s<%gJ_vvQFpdPu-k{n4>Ss(`+ zadhIYIrw+ukLS4#ORW&0>g^}l_}5^lgS$hkLgSlbiE zTqrRK5&zluIY^JYo2doRPLB*@J=P;-7a21jz7>{)-NWi$V-Q27mcQbccM%1&>8Q`T z!hA}c@;RLCxmCekA}h=`pq1^LM`lZ;=MV3BJD-jmajvJ4%%Bl>tbX0(`{*JvB(Wwb z`IHjP`lbUpFY)=?GSayln?+dX0RFEfakQmS`jRqWWtBduB^1*EH1%T4A9DPmgV?-w zfT|V+-PG!SHIS2ph}a>#M$;h8`rd_V3M9_s+gZE*=3Fz9y%?ardbOvO*$pa+<-Hyb zt)^rA2($brkU)jK#(^$2J2HE77~SKF`HOotgbePB!n5U3UZo%*&(k`Od1dX>Vc?qgE^_CqIbmHOF5oXS##jBbDi4d4)$mARO>-dapsxV+b`5f=XK*E99(Mad=sT&!Pu;=IEYGK=p=ssHQC*6Ux!f7(QX zhb!MM0Jm&q+3+ZjM);qT4)$$_f@ zq`)Lr|Bay6Lg29YXv&N27aXY}(4<)D3~&Z(CzTDI|DNAb)6z;3S-U7@5OVTV)eARXXUq8u zUDgJET|z|C&RKXt*W#uUy_RA*{wg#qMF)ZoJ=3Y2LGC=-)53Lf08Q`HkO;SLu zZEFpc)-ekcnd*n7ui#~3y0-h5|7z}{lVpX?Yw)`NIP*EC4!fDs^oDvn`MNaRifmz@ zxcfCsENn9A75Ve00KdIiWI39JceJk-V@SW9LA?J|xr|14 zf@&{rTuE9`%^7B?D1CJYAJYp6cGp$VC^??CjIngp;H4~U={#RC@pHT{6V1bOe~vhi zW7F!ZbQGH)9jio1j+v~V_djX{;AfL64zvPUirse}8~hCh*eN&YP4$fE2DyvAOM+ii z8Jfoka%!q0v&-my+c!qd(6_M}^!@(*eK1A=&4mnK#`i+{Bh|GQ#}r{1Iz}g(5avK0 z&LiyTAoq9d?vVbO7HjST#M54qhVmT#P00?~#2a8J(on31-i4iL0i#%$y?whvAt9=* z%j?uc(G%<*xviSVkkk3gN5eoX{1DwUPk!Ia8&N{%5oLDoXt6qrT|l4$BzehSna3aM zwbOJWbl|jNp7th92IdkEfD3UZHlpS+->`&91huRvy>X>D6%d!f$-=dD&lJ>?GL z_tI#Y$8!?FX>4%?yag_Oo!@p*Cc8G_4@!bNUZMO;S7y9Lz#NT@2;zL&bL=TDCKxd`z5ulj6zDXK4!)Ki0Bxx2Y1Hvn%g}ghc{GN=Wl1F zXn8N|bDt=iZAa zQ_+4@n8;yX#3-{c}A(YR0uu10wdIpvcG~>;S>d(r_m~x8Rb=Z<0{Rt|AJCj(Cu5z!of8Idz5GT1Pp8D{PxlF0pcx0umYsiY6%K`N?=lw7mIdd7|T= zYdB2MsF=KKL6r+oV2dhG0ZGb!QP{gS$>u{to#1d2TUe9JQ?bj=ml51)AQMO#a4P?*=IgV!UGk@U>xMJ^eJh==-z(_$pWZv7dDdGigA@fViTvXEBbV{ zIXDu+_rTGMAU|;GgysxYn?WX;=Sm|z_3O`w;@hnL{wW^%UDO2;VZ%bXM#NihZDj1K z95S@M-|nsjLP0FyJeRu3)d(pDoF93WWnbZtS*zNS&Tw(2Q-b7t^F6b;t33)$_(F)wW}~ zu1x2N5Y$dc`vBm{M$c$A>RrlCz7j0+h3GvS!^O#8eV|Ak-Duf&X;f}lx_WxO@oDpR zDc(wvG{Xn0T|&rHuIP&b&#!T`BoTnm0)Zj9vF9tXVsn8UsISG4CF6h=r384Jq3^6O zn%eR-Rzrq@iCjmPZr;CWOm0L_`TV63oFG&&BJn-Ip1Siz_ zM6FIBA?jt<7o#nN67eeA_RH-!aEx_J?XE53 z@1HEubDb0lk=11;!|cyzq9RiM%iNEqVOCfvNu;QHiFZ1L&5pQr%OD=sNz7g!&h7pZ z99=JhS4EI^X{;qJ9v4Ewznaz`_r5go%uBa$ZRC-L|3Tx3Txf5MUzS7=^ z@KoB_`Abv*FUE^9G*Cv9-|r+B%V@|YPfIHnW;PC~i|Al)?+%5gv9L&18TbjIo^ezm zq(!0+r~-C&cFq8c>KX2g`mAfXtUO4w2nd|Vu9XTtiJIt0Ct7UFwK~E=m={ ziWYsh*eDHKiC;TvNQ@_);X?1swTqG2jrWKD4&{aXxsV*bey&|An@}E^z)NtVa6u4f zhI@I-EG=BH$x^!h`G^KP9)j$B&f)oD713{e?Ce~wkyV^zMLI4J`zP)J zrjl@lUb4t-qZIY-GM-?v77F-XSaMH%!*MXvMqPgBqkLHGw=7}A^9mn?^}h(ZQ-+k( zYO-jcQUPBgFziQjPf?v?Bg&SEx<;yqo?)&)5JVPL=>T*o-{c9P9)+Jv__H3ECt1@~ z#vO6J%86}`H|IvYigx)>o^;^$=tEcji!DgxOl;5@7j4O9SUnj*Sz(&RcU1|b;8ls@ z3qO+DP*^xi5j7D(T}3ga_4HE>URi;`6+x{v%0P&A2NE)M3ob?rFYko>=it9avB3CO zhEkY4eU#Gv*fR~o~ ztHEUJ>uuTE48Qzv*pgCfNR)COE^TaCSrXVp` z#6=0_;9WR@9E#x?-4vFSp>4mh(i$X5E^>xXQ| zY>(NzG6@is9UPzI(^-OMk^??xC8Ue)R!ZwY5J1LLMjypP;ZO#DomXE)0{x+6id_(K zOsYu8m=c)|!Zx+33n)Qcd2xMV(WW7>x=2p@AXNj#*X(qk^~>j z&k#+iI63vryh!ZrNsC>QU9mE8Xp*nsp<3qsU(>xLW@LFI?UP*-tLf%Q5KK>S;t&Z} z-G1y)PGURH0N0BvE60KpQ@xF<^pyh}6dJ`Q9pkVJC2iBLKS9IUF2A)d1bueU>}Wy} zpr&Ce`Ym>uPxCRCtUNGp5Q^1$|RY32x#2_UQ zvSx2F#`+4G~mFIR1l`3<;}s$iRJmp!Cm?wPcw$ zHRGJ${formatCountdown(dailyDiff)})`; + dailyResetTimeElement.innerHTML = `(Resets in ${formatCountdown(dailyDiff)})`; } // Weekly @@ -309,7 +309,7 @@ function displayLocalResetTimes() { } const weeklyDiff = nextWeeklyResetTimestamp - now; if (weeklyResetTimeElement) { - weeklyResetTimeElement.innerHTML = `(Resets in ${formatCountdown(weeklyDiff)})`; + weeklyResetTimeElement.innerHTML = `(Resets in ${formatCountdown(weeklyDiff)})`; } // Other @@ -336,7 +336,7 @@ export function displayOtherTaskCountdown(task) { if (taskTimes.isAvailable) { const diff = taskTimes.thisCycleLeaveTimestamp - now.getTime(); - resetTimer.innerHTML = `(Available for ${formatCountdown(diff)})`; + resetTimer.innerHTML = `(Available for ${formatCountdown(diff)})`; // Leaving soon notification (Arrival notification is handled in otherTaskReset, the same as always available tasks) if (diff < C.MILLISECONDS_PER_HOUR && checklistData.notificationPreferences[task.id] && checklistData.notificationsSent[leaveNotifId] !== resetCount) { @@ -345,11 +345,11 @@ export function displayOtherTaskCountdown(task) { saveData(false); } } else { // task not available - resetTimer.innerHTML = `(Available in ${formatCountdown(taskTimes.nextResetTimestamp - now.getTime())})`; + resetTimer.innerHTML = `(Available in ${formatCountdown(taskTimes.nextResetTimestamp - now.getTime())})`; if (checklistData.notificationsSent[leaveNotifId]) { delete checklistData.notificationsSent[leaveNotifId]; } } } else { // always available task - resetTimer.innerHTML = `(Resets in ${formatCountdown(taskTimes.nextResetTimestamp - now.getTime())})`; + resetTimer.innerHTML = `(Resets in ${formatCountdown(taskTimes.nextResetTimestamp - now.getTime())})`; } } @@ -891,7 +891,7 @@ function makeInfoLine(task, appendTo) { /* eslint-disable-line max-lines-per-fun currentCycle.innerHTML += makeCycleIcon(cycleData); const cycleText = document.createElement("span"); - cycleText.textContent = cycleData.text; + cycleText.innerHTML = cycleData.text; currentCycle.appendChild(cycleText); const showSchedule = document.createElement("button"); diff --git a/sources/js/constants.js b/sources/js/constants.js index a2f4d11..2a2ca34 100644 --- a/sources/js/constants.js +++ b/sources/js/constants.js @@ -6,7 +6,7 @@ export const MILLISECONDS_PER_DAY = 24 * MILLISECONDS_PER_HOUR; export const SERVER_TIMEZONE = "America/Toronto"; // used for determining Daylight Saving Time -export const BASE_OF_OPERATIONS_TOOLTIP = 'Base of Operations'; +export const BASE_OF_OPERATIONS_TOOLTIP = 'Base of Operations'; export const TASKLIST_STAT_NAMES = { "completed": "Completed", diff --git a/sources/js/cycles.json b/sources/js/cycles.json index ca0559c..eb49aff 100644 --- a/sources/js/cycles.json +++ b/sources/js/cycles.json @@ -109,7 +109,7 @@ { "text": "Incarnon Adapters for Bo, Furax, Furis, Latron, and Strun", "icon": "IncarnonEvolveIconSmall.png", "iconFilter": true }, { "text": "Incarnon Adapters for Boltor, Bronco, Ceramic Dagger, Lex, and Magistar", "icon": "IncarnonEvolveIconSmall.png", "iconFilter": true }, { "text": "Incarnon Adapters for Atomos, Dual Ichor, Dual Toxocyst, Miter, and Torid", "icon": "IncarnonEvolveIconSmall.png", "iconFilter": true }, - { "text": "Incarnon Adapters for Ack & Brunt, Burston, Nami Solo, Soma, and Vasto", "icon": "IncarnonEvolveIconSmall.png", "iconFilter": true }, + { "text": "Incarnon Adapters for Ack & Brunt, Burston, Nami Solo, Soma, and Vasto", "icon": "IncarnonEvolveIconSmall.png", "iconFilter": true }, { "text": "Incarnon Adapters for Despair, Dread, Hate, Sibear, and Zylok", "icon": "IncarnonEvolveIconSmall.png", "iconFilter": true }, { "text": "Incarnon Adapters for Cestra, Dera, Okina, Sicarus, and Sybaris", "icon": "IncarnonEvolveIconSmall.png", "iconFilter": true }, { "text": "Incarnon Adapters for Ballistica, Destreza, Obex, Stug, and Vectis", "icon": "IncarnonEvolveIconSmall.png", "iconFilter": true } diff --git a/sources/js/tasks.json b/sources/js/tasks.json index 85a2215..94be6d8 100644 --- a/sources/js/tasks.json +++ b/sources/js/tasks.json @@ -231,7 +231,7 @@ }, { "id": "daily_kim_minerva_velimir", - "title": "MomToxicated & PapaPolar (Minerva & Velimir)", + "title": "MomToxicated & PapaPolar (Minerva & Velimir)", "icon": "KIM/RetroPfpI.png", "noIconFilter": true, "prereq": "Rank 5 The Hex" @@ -303,7 +303,7 @@ "icon": "IconCommand.png", "location": "Fortuna, Venus", "npc": "Ticker", - "prereq": "Rising Tide & Command Intrinsics 1" + "prereq": "Rising Tide & Command Intrinsics 1" }, { "id": "daily_marie", @@ -368,7 +368,7 @@ { "id": "weekly_duviri_circuit", "title": "Duviri Circuit (Normal)", - "text": "Check weekly Warframe options & run Circuit if desired.", + "text": "Check weekly Warframe options & run Circuit if desired.", "icon": "IconDuviriCategory256.png", "location": "Base of Operations/Dormizone", "terminal": "Navigation", @@ -377,11 +377,11 @@ { "id": "weekly_duviri_circuit_sp", "title": "Duviri Circuit (Steel Path)", - "text": "Check weekly Incarnon Adapters & run Circuit if desired.", + "text": "Check weekly Incarnon Adapters & run Circuit if desired.", "icon": "IconDuviriCategory256.png", "location": "Base of Operations/Dormizone", "terminal": "Navigation", - "prereq": "Steel Path unlocked & The Duviri Paradox" + "prereq": "Steel Path unlocked & The Duviri Paradox" }, { "id": "weekly_search_pulses", @@ -421,6 +421,25 @@ } ] }, + { + "id": "weekly_cryobells", + "title": "Cryobells", + "text": "Harvest 3 Cryobells from Yuvan Peak.", + "icon": "Melica.png", + "location": "Yuvan Peak, Earth", + "prereq": "Angels of the Zariman & Whispers in the Walls", + "info": "Up to 6 Cryobells can be owned at a time" + }, + { + "id": "weekly_icebind", + "title": "The Icebind", + "text": "Spend Cryobells to run six-player Icebind missions.", + "icon": "Melica.png", + "location": "Yuvan Peak, Earth", + "npc": "Cephalon Melica", + "prereq": "Angels of the Zariman, Whispers in the Walls, & unlocked EDA or ETA", + "info":"Costs 1 Cryobell per player per successful mission" + }, { "id": "weekly_calendar", "title": "1999 Calendar", @@ -444,16 +463,16 @@ "title": "The Descendia (Normal)", "text": "Weekly Tower gamemode for various resources.", "icon": "Heat_d.png", - "location": "Dark Refractory (Base of Operations)", - "terminal": "Navigation" + "location": "Base of Operations or Sanctum Anatomica, Deimos", + "terminal": "Dark Refractory" }, { "id": "weekly_descendia_sp", "title": "The Descendia (Steel Path)", "text": "Weekly Tower gamemode for various resources.", "icon": "Heat_d.png", - "location": "Dark Refractory (Base of Operations)", - "terminal": "Navigation" + "location": "Base of Operations or Sanctum Anatomica, Deimos", + "terminal": "Dark Refractory" }, { "id": "weekly_oops_all_eximus", @@ -558,6 +577,15 @@ "location": "Pontis Tower, Uranus", "npc": "Hunhow", "prereq": "Jade Shadows: Constellations" + }, + { + "id": "weekly_melica", + "title": "Cephalon Melica", + "text": "Trade Entropic Kuva for Kuva.", + "icon": "Melica.png", + "location": "Yuvan Peak, Earth", + "npc": "Cephalon Melica", + "prereq": "Angels of the Zariman & Whispers in the Walls" } ] }