diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index ac11fe41..00000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - env: { - browser: true, - es6: true, - node: true, - }, - parser: '@typescript-eslint/parser', - parserOptions: { - sourceType: 'module', - }, - plugins: ['@typescript-eslint'], - extends: ['plugin:@typescript-eslint/recommended'], - rules: { - '@typescript-eslint/no-explicit-any': 'off', - }, -} diff --git a/.github/ISSUE_TEMPLATE/---bug-report.yml b/.github/ISSUE_TEMPLATE/---bug-report.yml index 725d0180..8bacfb9a 100644 --- a/.github/ISSUE_TEMPLATE/---bug-report.yml +++ b/.github/ISSUE_TEMPLATE/---bug-report.yml @@ -1,6 +1,6 @@ -name: "\U0001F41B Bug report" +name: 🐛 Bug report description: Something's not working -labels: ["bug"] +labels: [bug] body: - type: textarea validations: diff --git a/.github/ISSUE_TEMPLATE/---documentation.yml b/.github/ISSUE_TEMPLATE/---documentation.yml index df2c0af6..c28b8e7b 100644 --- a/.github/ISSUE_TEMPLATE/---documentation.yml +++ b/.github/ISSUE_TEMPLATE/---documentation.yml @@ -1,6 +1,6 @@ -name: "\U0001F4DA Documentation" +name: 📚 Documentation description: How do I ... ? -labels: ["documentation"] +labels: [documentation] body: - type: textarea validations: diff --git a/.github/ISSUE_TEMPLATE/---feature-suggestion.yml b/.github/ISSUE_TEMPLATE/---feature-suggestion.yml index 649cbafa..cb9bdab8 100644 --- a/.github/ISSUE_TEMPLATE/---feature-suggestion.yml +++ b/.github/ISSUE_TEMPLATE/---feature-suggestion.yml @@ -1,6 +1,6 @@ -name: "\U0001F195 Feature suggestion" +name: 🆕 Feature suggestion description: Suggest an idea -labels: ["enhancement"] +labels: [enhancement] body: - type: textarea validations: diff --git a/.github/ISSUE_TEMPLATE/---help-wanted.yml b/.github/ISSUE_TEMPLATE/---help-wanted.yml index 2407d54e..ed69f20f 100644 --- a/.github/ISSUE_TEMPLATE/---help-wanted.yml +++ b/.github/ISSUE_TEMPLATE/---help-wanted.yml @@ -1,6 +1,6 @@ -name: "\U0001F198 Help" +name: 🆘 Help description: I need help with ... -labels: ["help"] +labels: [help] body: - type: textarea validations: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9c04e8d..2e93ac20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 18 - cache: 'pnpm' + cache: pnpm - name: 📦 Install dependencies run: pnpm install @@ -35,7 +35,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 18 - cache: 'pnpm' + cache: pnpm - name: 📦 Install dependencies run: pnpm install diff --git a/README.md b/README.md index b03d28f5..b72e824f 100644 --- a/README.md +++ b/README.md @@ -48,10 +48,13 @@ yarn add -D fontaine ```js import { FontaineTransform } from 'fontaine' +// Astro config - astro.config.mjs +import { defineConfig } from 'astro/config' + const options = { fallbacks: ['BlinkMacSystemFont', 'Segoe UI', 'Helvetica Neue', 'Arial', 'Noto Sans'], // You may need to resolve assets like `/fonts/Roboto.woff2` to a particular directory - resolvePath: (id) => 'file:///path/to/public/dir' + id, + resolvePath: id => `file:///path/to/public/dir${id}`, // overrideName: (originalName) => `${name} override` // sourcemap: false // skipFontFaceGeneration: (fallbackName) => fallbackName === 'Roboto override' @@ -83,9 +86,9 @@ function fontainePlugin(_context, _options) { plugins: [ fontaine.FontaineTransform.webpack(options), ], - }; + } }, - }; + } } // Gatsby config - gatsby-node.js @@ -97,17 +100,13 @@ exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => { actions.replaceWebpackConfig(config) } -// Astro config - astro.config.mjs -import { defineConfig } from 'astro/config' -import { FontaineTransform } from 'fontaine' - export default defineConfig({ integrations: [], vite: { plugins: [ FontaineTransform.vite({ fallbacks: ['Arial'], - resolvePath: (id) => new URL(`./public${id}`, import.meta.url), // id is the font src value in the CSS + resolvePath: id => new URL(`./public${id}`, import.meta.url), // id is the font src value in the CSS }), ], }, diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..3b614a0d --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,3 @@ +import antfu from '@antfu/eslint-config' + +export default antfu() diff --git a/lint-staged.config.cjs b/lint-staged.config.cjs deleted file mode 100644 index 69462c22..00000000 --- a/lint-staged.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - '*.{js,ts,mjs,cjs}': ['pnpm lint:eslint', 'pnpm lint:prettier'], - '{!(package)*.json,*.code-snippets,.*rc}': [ - 'pnpm lint:prettier --parser json', - ], - 'package.json': ['pnpm lint:prettier'], -} diff --git a/package.json b/package.json index b878701e..78811ecc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,14 @@ { "name": "fontaine", + "type": "module", "version": "0.4.1", + "packageManager": "pnpm@8.15.4", "description": "Automatic font fallback based on font metrics", + "author": { + "name": "Daniel Roe ", + "url": "https://github.com/danielroe" + }, + "license": "MIT", "repository": "unjs/fontaine", "keywords": [ "fonts", @@ -9,13 +16,7 @@ "web-vitals", "performance" ], - "author": { - "name": "Daniel Roe ", - "url": "https://github.com/danielroe" - }, - "license": "MIT", "sideEffects": false, - "type": "module", "exports": { ".": { "import": "./dist/index.mjs", @@ -33,12 +34,8 @@ "dev": "vitest", "demo": "vite dev playground", "demo:dev": "pnpm demo --config test/vite.config.mjs", - "lint": "pnpm lint:all:eslint && pnpm lint:all:prettier", - "lint:all:eslint": "pnpm lint:eslint --ext .ts,.js,.mjs,.cjs .", - "lint:all:prettier": "pnpm lint:prettier \"{src,test}/**/*.{js,json,ts}\"", - "lint:eslint": "eslint --fix", - "lint:prettier": "prettier --write --log-level warn", - "prepare": "husky install && pnpm build", + "lint": "eslint --fix .", + "prepare": "simple-git-hooks install && pnpm build", "prepublishOnly": "pnpm lint && pnpm test", "release": "pnpm test && bumpp && npm publish", "test": "vitest run" @@ -53,6 +50,7 @@ "unplugin": "^1.8.3" }, "devDependencies": { + "@antfu/eslint-config": "^2.8.0", "@nuxtjs/eslint-config-typescript": "latest", "@types/node": "20.11.25", "@types/serve-handler": "6.1.4", @@ -65,10 +63,10 @@ "eslint-plugin-prettier": "latest", "execa": "8.0.1", "get-port-please": "3.1.2", - "husky": "latest", "lint-staged": "15.2.2", "prettier": "latest", "serve-handler": "6.1.5", + "simple-git-hooks": "^2.10.0", "typescript": "5.4.2", "unbuild": "latest", "vite": "5.1.5", @@ -77,5 +75,12 @@ "resolutions": { "fontaine": "link:." }, - "packageManager": "pnpm@8.15.4" + "simple-git-hooks": { + "pre-commit": "npx lint-staged" + }, + "lint-staged": { + "*.{js,ts,mjs,cjs,json,.*rc}": [ + "pnpm eslint --fix" + ] + } } diff --git a/playground/vite.config.mjs b/playground/vite.config.mjs index babf86f8..8be5b2dd 100644 --- a/playground/vite.config.mjs +++ b/playground/vite.config.mjs @@ -6,7 +6,7 @@ export default defineConfig({ FontaineTransform.vite({ fallbacks: ['Arial'], // resolve absolute URL -> file - resolvePath: id => new URL('.' + id, import.meta.url), + resolvePath: id => new URL(`.${id}`, import.meta.url), }), ], }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 34265c58..f399dda0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,6 +33,9 @@ importers: specifier: ^1.8.3 version: 1.8.3 devDependencies: + '@antfu/eslint-config': + specifier: ^2.8.0 + version: 2.8.0(@vue/compiler-sfc@3.4.21)(eslint@8.57.0)(typescript@5.4.2)(vitest@1.3.1) '@nuxtjs/eslint-config-typescript': specifier: latest version: 12.1.0(eslint@8.57.0)(typescript@5.4.2) @@ -69,9 +72,6 @@ importers: get-port-please: specifier: 3.1.2 version: 3.1.2 - husky: - specifier: latest - version: 9.0.11 lint-staged: specifier: 15.2.2 version: 15.2.2 @@ -81,6 +81,9 @@ importers: serve-handler: specifier: 6.1.5 version: 6.1.5 + simple-git-hooks: + specifier: ^2.10.0 + version: 2.10.0 typescript: specifier: 5.4.2 version: 5.4.2 @@ -118,6 +121,104 @@ packages: '@jridgewell/trace-mapping': 0.3.19 dev: true + /@antfu/eslint-config@2.8.0(@vue/compiler-sfc@3.4.21)(eslint@8.57.0)(typescript@5.4.2)(vitest@1.3.1): + resolution: {integrity: sha512-5qdNKqJ6qWev17ulCikrYs6/AvLFKaOOdUAfuKPwpv0XFwzJWMnjOqoVpoExpMr9G5iIKjzU168gO30Jab/uNA==} + hasBin: true + peerDependencies: + '@unocss/eslint-plugin': '>=0.50.0' + astro-eslint-parser: ^0.16.3 + eslint: '>=8.40.0' + eslint-plugin-astro: ^0.31.4 + eslint-plugin-format: '>=0.1.0' + eslint-plugin-react: ^7.33.2 + eslint-plugin-react-hooks: ^4.6.0 + eslint-plugin-react-refresh: ^0.4.4 + eslint-plugin-svelte: ^2.34.1 + prettier-plugin-astro: ^0.13.0 + prettier-plugin-slidev: ^1.0.5 + svelte-eslint-parser: ^0.33.1 + peerDependenciesMeta: + '@unocss/eslint-plugin': + optional: true + astro-eslint-parser: + optional: true + eslint-plugin-astro: + optional: true + eslint-plugin-format: + optional: true + eslint-plugin-react: + optional: true + eslint-plugin-react-hooks: + optional: true + eslint-plugin-react-refresh: + optional: true + eslint-plugin-svelte: + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-slidev: + optional: true + svelte-eslint-parser: + optional: true + dependencies: + '@antfu/eslint-define-config': 1.23.0-2 + '@antfu/install-pkg': 0.3.1 + '@eslint-types/jsdoc': 46.8.2-1 + '@eslint-types/typescript-eslint': 7.0.2 + '@eslint-types/unicorn': 51.0.1 + '@stylistic/eslint-plugin': 1.6.3(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/eslint-plugin': 7.1.1(@typescript-eslint/parser@7.1.1)(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/parser': 7.1.1(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + eslint-config-flat-gitignore: 0.1.3 + eslint-merge-processors: 0.1.0(eslint@8.57.0) + eslint-plugin-antfu: 2.1.2(eslint@8.57.0) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) + eslint-plugin-i: 2.29.1(@typescript-eslint/parser@7.1.1)(eslint@8.57.0) + eslint-plugin-jsdoc: 48.2.0(eslint@8.57.0) + eslint-plugin-jsonc: 2.13.0(eslint@8.57.0) + eslint-plugin-markdown: 3.0.1(eslint@8.57.0) + eslint-plugin-n: 16.6.2(eslint@8.57.0) + eslint-plugin-no-only-tests: 3.1.0 + eslint-plugin-perfectionist: 2.6.0(eslint@8.57.0)(typescript@5.4.2)(vue-eslint-parser@9.4.2) + eslint-plugin-toml: 0.9.2(eslint@8.57.0) + eslint-plugin-unicorn: 51.0.1(eslint@8.57.0) + eslint-plugin-unused-imports: 3.1.0(@typescript-eslint/eslint-plugin@7.1.1)(eslint@8.57.0) + eslint-plugin-vitest: 0.3.22(@typescript-eslint/eslint-plugin@7.1.1)(eslint@8.57.0)(typescript@5.4.2)(vitest@1.3.1) + eslint-plugin-vue: 9.22.0(eslint@8.57.0) + eslint-plugin-yml: 1.12.2(eslint@8.57.0) + eslint-processor-vue-blocks: 0.1.1(@vue/compiler-sfc@3.4.21)(eslint@8.57.0) + globals: 14.0.0 + jsonc-eslint-parser: 2.4.0 + local-pkg: 0.5.0 + parse-gitignore: 2.0.0 + picocolors: 1.0.0 + prompts: 2.4.2 + toml-eslint-parser: 0.9.3 + vue-eslint-parser: 9.4.2(eslint@8.57.0) + yaml-eslint-parser: 1.2.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@vue/compiler-sfc' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + - svelte + - typescript + - vitest + dev: true + + /@antfu/eslint-define-config@1.23.0-2: + resolution: {integrity: sha512-LvxY21+ZhpuBf/aHeBUtGQhSEfad4PkNKXKvDOSvukaM3XVTfBhwmHX2EKwAsdq5DlfjbT3qqYyMiueBIO5iDQ==} + engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>= 8.6.0'} + dev: true + + /@antfu/install-pkg@0.3.1: + resolution: {integrity: sha512-A3zWY9VeTPnxlMiZtsGHw2lSd3ghwvL8s9RiGOtqvDxhhFfZ781ynsGBa/iUnDJ5zBrmTFQrJDud3TGgRISaxw==} + dependencies: + execa: 8.0.1 + dev: true + /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} @@ -333,6 +434,15 @@ packages: - encoding dev: false + /@es-joy/jsdoccomment@0.42.0: + resolution: {integrity: sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==} + engines: {node: '>=16'} + dependencies: + comment-parser: 1.4.1 + esquery: 1.5.0 + jsdoc-type-pratt-parser: 4.0.0 + dev: true + /@esbuild/aix-ppc64@0.19.12: resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} engines: {node: '>=12'} @@ -928,6 +1038,18 @@ packages: engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true + /@eslint-types/jsdoc@46.8.2-1: + resolution: {integrity: sha512-FwD7V0xX0jyaqj8Ul5ZY+TAAPohDfVqtbuXJNHb+OIv1aTIqZi5+Zn3F2UwQ5O3BnQd2mTduyK0+HjGx3/AMFg==} + dev: true + + /@eslint-types/typescript-eslint@7.0.2: + resolution: {integrity: sha512-2F67MVKhkJ2rSwoYvNJzJULqZwR5rNYI/eWoIrKDQ14lMzfqzbpzCBvnHrivBYWTN+Az7MVX00TzDTrjOc+YNA==} + dev: true + + /@eslint-types/unicorn@51.0.1: + resolution: {integrity: sha512-RuuEK+dBISEikf7a8lrWOrDCUYv09sZfqLoG/kozH+5UqEvot1xMmGHXomGkTyB68rzjgJe0N4uESVyL62obJw==} + dev: true + /@eslint/eslintrc@2.1.4: resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1273,6 +1395,78 @@ packages: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true + /@stylistic/eslint-plugin-js@1.6.3(eslint@8.57.0): + resolution: {integrity: sha512-ckdz51oHxD2FaxgY2piJWJVJiwgp8Uu96s+as2yB3RMwavn3nHBrpliVukXY9S/DmMicPRB2+H8nBk23GDG+qA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + dependencies: + '@types/eslint': 8.56.5 + acorn: 8.11.3 + escape-string-regexp: 4.0.0 + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + dev: true + + /@stylistic/eslint-plugin-jsx@1.6.3(eslint@8.57.0): + resolution: {integrity: sha512-SRysCIg59Zvn3dJPqHziiHwuni4NNj1et5stAmivmyQ3Cdp2ULCB7tGxCF1OxpkwRlZQue3ZgdiM7EXfJKaf9w==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + dependencies: + '@stylistic/eslint-plugin-js': 1.6.3(eslint@8.57.0) + '@types/eslint': 8.56.5 + eslint: 8.57.0 + estraverse: 5.3.0 + picomatch: 4.0.1 + dev: true + + /@stylistic/eslint-plugin-plus@1.6.3(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-TuwQOdyVGycDPw5XeF7W4f3ZonAVzOAzORSaD2yGAJ0fRAbJ+l/v3CkKzIAqBBwWkc+c2aRMsWtLP2+viBnmlQ==} + peerDependencies: + eslint: '*' + dependencies: + '@types/eslint': 8.56.5 + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@stylistic/eslint-plugin-ts@1.6.3(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-v5GwZsPLblWM9uAIdaSi31Sed3XBWlTFQJ3b5upEmj6QsKYivA5nmIYutwqqL133QdVWjmC86pINlx2Muq3uNQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + dependencies: + '@stylistic/eslint-plugin-js': 1.6.3(eslint@8.57.0) + '@types/eslint': 8.56.5 + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@stylistic/eslint-plugin@1.6.3(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-WDa4FjhImp7YcztRaMG09svhKYYhi2Hc4p9ltQRSqyB4fsUUFm+GKzStqqH7xfjHnxacMJaOnaMGRTUqIIZDLA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + dependencies: + '@stylistic/eslint-plugin-js': 1.6.3(eslint@8.57.0) + '@stylistic/eslint-plugin-jsx': 1.6.3(eslint@8.57.0) + '@stylistic/eslint-plugin-plus': 1.6.3(eslint@8.57.0)(typescript@5.4.2) + '@stylistic/eslint-plugin-ts': 1.6.3(eslint@8.57.0)(typescript@5.4.2) + '@types/eslint': 8.56.5 + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@swc/helpers@0.4.14: resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==} dependencies: @@ -1286,6 +1480,13 @@ packages: tslib: 2.6.2 dev: false + /@types/eslint@8.56.5: + resolution: {integrity: sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.13 + dev: true + /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -1301,6 +1502,12 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true + /@types/mdast@3.0.15: + resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} + dependencies: + '@types/unist': 2.0.10 + dev: true + /@types/node@20.11.25: resolution: {integrity: sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==} dependencies: @@ -1324,6 +1531,10 @@ packages: '@types/node': 20.11.25 dev: true + /@types/unist@2.0.10: + resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + dev: true + /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.4.2): resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1654,6 +1865,48 @@ packages: pretty-format: 29.7.0 dev: true + /@vue/compiler-core@3.4.21: + resolution: {integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==} + dependencies: + '@babel/parser': 7.23.9 + '@vue/shared': 3.4.21 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-dom@3.4.21: + resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==} + dependencies: + '@vue/compiler-core': 3.4.21 + '@vue/shared': 3.4.21 + dev: true + + /@vue/compiler-sfc@3.4.21: + resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==} + dependencies: + '@babel/parser': 7.23.9 + '@vue/compiler-core': 3.4.21 + '@vue/compiler-dom': 3.4.21 + '@vue/compiler-ssr': 3.4.21 + '@vue/shared': 3.4.21 + estree-walker: 2.0.2 + magic-string: 0.30.8 + postcss: 8.4.35 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-ssr@3.4.21: + resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==} + dependencies: + '@vue/compiler-dom': 3.4.21 + '@vue/shared': 3.4.21 + dev: true + + /@vue/shared@3.4.21: + resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==} + dev: true + /acorn-jsx@5.3.2(acorn@8.11.3): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1730,6 +1983,11 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 + /are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + dev: true + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true @@ -1866,6 +2124,17 @@ packages: update-browserslist-db: 1.0.13(browserslist@4.22.1) dev: true + /browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001594 + electron-to-chromium: 1.4.694 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.23.0) + dev: true + /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -1939,6 +2208,10 @@ packages: resolution: {integrity: sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==} dev: true + /caniuse-lite@1.0.30001594: + resolution: {integrity: sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g==} + dev: true + /chai@4.3.10: resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} engines: {node: '>=4'} @@ -1975,6 +2248,18 @@ packages: engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} dev: true + /character-entities-legacy@1.1.4: + resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} + dev: true + + /character-entities@1.2.4: + resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} + dev: true + + /character-reference-invalid@1.1.4: + resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} + dev: true + /check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} dependencies: @@ -2005,6 +2290,11 @@ packages: engines: {node: '>=8'} dev: true + /ci-info@4.0.0: + resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + engines: {node: '>=8'} + dev: true + /citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} dependencies: @@ -2033,6 +2323,15 @@ packages: string-width: 7.1.0 dev: true + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + /clone@2.1.2: resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} engines: {node: '>=0.8'} @@ -2070,6 +2369,11 @@ packages: engines: {node: '>=16'} dev: true + /comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + dev: true + /commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} dev: true @@ -2096,6 +2400,12 @@ packages: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} dev: true + /core-js-compat@3.36.0: + resolution: {integrity: sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==} + dependencies: + browserslist: 4.23.0 + dev: true + /cross-fetch@3.1.8: resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} dependencies: @@ -2223,10 +2533,18 @@ packages: resolution: {integrity: sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w==} dev: true + /electron-to-chromium@1.4.694: + resolution: {integrity: sha512-kM3SwvGTYpBFJSc8jm4IYVMIOzDmAGd/Ry96O9elRiM6iEwHKNKhtXyFGzpfMMIGZD84W4/hyaULlMmNVvLQlQ==} + dev: true + /emoji-regex@10.3.0: resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} dev: true + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + /enhanced-resolve@5.15.0: resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} engines: {node: '>=10.13.0'} @@ -2235,6 +2553,11 @@ packages: tapable: 2.2.1 dev: true + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: true + /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: @@ -2420,6 +2743,32 @@ packages: engines: {node: '>=10'} dev: true + /eslint-compat-utils@0.1.2(eslint@8.57.0): + resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-compat-utils@0.4.1(eslint@8.57.0): + resolution: {integrity: sha512-5N7ZaJG5pZxUeNNJfUchurLVrunD1xJvyg5kYOIVF8kg1f3ajTikmAu/5fZ9w100omNPOoMjngRszh/Q/uFGMg==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + eslint: 8.57.0 + semver: 7.6.0 + dev: true + + /eslint-config-flat-gitignore@0.1.3: + resolution: {integrity: sha512-oQD+dEZv3RThN60tFqGFt+NJcO1DmssUcP+T/nlX+ZzEoEvVUYH0GU9X/VlmDXsbMsS9mONI1HrlxLgtKojw7w==} + dependencies: + find-up: 7.0.0 + parse-gitignore: 2.0.0 + dev: true + /eslint-config-prettier@9.1.0(eslint@8.57.0): resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true @@ -2477,6 +2826,14 @@ packages: - supports-color dev: true + /eslint-merge-processors@0.1.0(eslint@8.57.0): + resolution: {integrity: sha512-IvRXXtEajLeyssvW4wJcZ2etxkR9mUf4zpNwgI+m/Uac9RfXHskuJefkHUcawVzePnd6xp24enp5jfgdHzjRdQ==} + peerDependencies: + eslint: '*' + dependencies: + eslint: 8.57.0 + dev: true + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} @@ -2565,6 +2922,26 @@ packages: - supports-color dev: true + /eslint-plugin-antfu@2.1.2(eslint@8.57.0): + resolution: {integrity: sha512-s7ZTOM3uq0iqpp6gF0UEotnvup7f2PHBUftCytLZX0+6C9j9KadKZQh6bVVngAyFgsmeD9+gcBopOYLClb2oDg==} + peerDependencies: + eslint: '*' + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-plugin-es-x@7.5.0(eslint@8.57.0): + resolution: {integrity: sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.9.1 + eslint: 8.57.0 + eslint-compat-utils: 0.1.2(eslint@8.57.0) + dev: true + /eslint-plugin-es@3.0.1(eslint@8.57.0): resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} engines: {node: '>=8.10.0'} @@ -2587,6 +2964,39 @@ packages: regexpp: 3.2.0 dev: true + /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): + resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} + engines: {node: '>=6.5.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + escape-string-regexp: 1.0.5 + eslint: 8.57.0 + ignore: 5.2.4 + dev: true + + /eslint-plugin-i@2.29.1(@typescript-eslint/parser@7.1.1)(eslint@8.57.0): + resolution: {integrity: sha512-ORizX37MelIWLbMyqI7hi8VJMf7A0CskMmYkB+lkCX3aF4pkGV7kwx5bSEb4qx7Yce2rAf9s34HqDRPjGRZPNQ==} + engines: {node: '>=12'} + peerDependencies: + eslint: ^7.2.0 || ^8 + dependencies: + debug: 4.3.4 + doctrine: 3.0.0 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.1.1)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) + get-tsconfig: 4.7.2 + is-glob: 4.0.3 + minimatch: 3.1.2 + semver: 7.6.0 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + /eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==} engines: {node: '>=4'} @@ -2657,6 +3067,54 @@ packages: - supports-color dev: true + /eslint-plugin-jsdoc@48.2.0(eslint@8.57.0): + resolution: {integrity: sha512-O2B1XLBJnUCRkggFzUQ+PBYJDit8iAgXdlu8ucolqGrbmOWPvttZQZX8d1sC0MbqDMSLs8SHSQxaNPRY1RQREg==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + dependencies: + '@es-joy/jsdoccomment': 0.42.0 + are-docs-informative: 0.0.2 + comment-parser: 1.4.1 + debug: 4.3.4 + escape-string-regexp: 4.0.0 + eslint: 8.57.0 + esquery: 1.5.0 + is-builtin-module: 3.2.1 + semver: 7.6.0 + spdx-expression-parse: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-jsonc@2.13.0(eslint@8.57.0): + resolution: {integrity: sha512-2wWdJfpO/UbZzPDABuUVvlUQjfMJa2p2iQfYt/oWxOMpXCcjuiMUSaA02gtY/Dbu82vpaSqc+O7Xq6ECHwtIxA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + eslint: 8.57.0 + eslint-compat-utils: 0.4.1(eslint@8.57.0) + espree: 9.6.1 + graphemer: 1.4.0 + jsonc-eslint-parser: 2.4.0 + natural-compare: 1.4.0 + synckit: 0.6.2 + dev: true + + /eslint-plugin-markdown@3.0.1(eslint@8.57.0): + resolution: {integrity: sha512-8rqoc148DWdGdmYF6WSQFT3uQ6PO7zXYgeBpHAOAakX/zpq+NvFYbDA/H7PYzHajwtmaOzAwfxyl++x0g1/N9A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + eslint: 8.57.0 + mdast-util-from-markdown: 0.8.5 + transitivePeerDependencies: + - supports-color + dev: true + /eslint-plugin-n@15.7.0(eslint@8.57.0): resolution: {integrity: sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==} engines: {node: '>=12.22.0'} @@ -2674,7 +3132,32 @@ packages: semver: 7.5.4 dev: true - /eslint-plugin-node@11.1.0(eslint@8.57.0): + /eslint-plugin-n@16.6.2(eslint@8.57.0): + resolution: {integrity: sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + builtins: 5.0.1 + eslint: 8.57.0 + eslint-plugin-es-x: 7.5.0(eslint@8.57.0) + get-tsconfig: 4.7.2 + globals: 13.24.0 + ignore: 5.2.4 + is-builtin-module: 3.2.1 + is-core-module: 2.13.0 + minimatch: 3.1.2 + resolve: 1.22.6 + semver: 7.6.0 + dev: true + + /eslint-plugin-no-only-tests@3.1.0: + resolution: {integrity: sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==} + engines: {node: '>=5.0.0'} + dev: true + + /eslint-plugin-node@11.1.0(eslint@8.57.0): resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} engines: {node: '>=8.10.0'} peerDependencies: @@ -2689,6 +3172,34 @@ packages: semver: 6.3.1 dev: true + /eslint-plugin-perfectionist@2.6.0(eslint@8.57.0)(typescript@5.4.2)(vue-eslint-parser@9.4.2): + resolution: {integrity: sha512-hee0Fu5825v+WTIhrRIJdWO8biUgm9O+c4Q1AEXIIGsXDHrLv5cdXfVUdnQcYgGtI/4X+tdFu69iVofHCIkvtw==} + peerDependencies: + astro-eslint-parser: ^0.16.0 + eslint: '>=8.0.0' + svelte: '>=3.0.0' + svelte-eslint-parser: ^0.33.0 + vue-eslint-parser: '>=9.0.0' + peerDependenciesMeta: + astro-eslint-parser: + optional: true + svelte: + optional: true + svelte-eslint-parser: + optional: true + vue-eslint-parser: + optional: true + dependencies: + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + minimatch: 9.0.3 + natural-compare-lite: 1.4.0 + vue-eslint-parser: 9.4.2(eslint@8.57.0) + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5): resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -2719,6 +3230,21 @@ packages: eslint: 8.57.0 dev: true + /eslint-plugin-toml@0.9.2(eslint@8.57.0): + resolution: {integrity: sha512-ri0xf63PYf3pIq/WY9BIwrqxZmGTIwSkAO0bHddI0ajUwN4KGz6W8vOvdXFHOpRdRfzxlmXze/vfsY/aTEXESg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4 + eslint: 8.57.0 + eslint-compat-utils: 0.4.1(eslint@8.57.0) + lodash: 4.17.21 + toml-eslint-parser: 0.9.3 + transitivePeerDependencies: + - supports-color + dev: true + /eslint-plugin-unicorn@44.0.2(eslint@8.57.0): resolution: {integrity: sha512-GLIDX1wmeEqpGaKcnMcqRvMVsoabeF0Ton0EX4Th5u6Kmf7RM9WBl705AXFEsns56ESkEs0uyelLuUTvz9Tr0w==} engines: {node: '>=14.18'} @@ -2742,6 +3268,70 @@ packages: strip-indent: 3.0.0 dev: true + /eslint-plugin-unicorn@51.0.1(eslint@8.57.0): + resolution: {integrity: sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==} + engines: {node: '>=16'} + peerDependencies: + eslint: '>=8.56.0' + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint/eslintrc': 2.1.4 + ci-info: 4.0.0 + clean-regexp: 1.0.0 + core-js-compat: 3.36.0 + eslint: 8.57.0 + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.0.2 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.6.0 + strip-indent: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-unused-imports@3.1.0(@typescript-eslint/eslint-plugin@7.1.1)(eslint@8.57.0): + resolution: {integrity: sha512-9l1YFCzXKkw1qtAru1RWUtG2EVDZY0a0eChKXcL+EZ5jitG7qxdctu4RnvhOJHv4xfmUf7h+JJPINlVpGhZMrw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': 6 - 7 + eslint: '8' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 7.1.1(@typescript-eslint/parser@7.1.1)(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + eslint-rule-composer: 0.3.0 + dev: true + + /eslint-plugin-vitest@0.3.22(@typescript-eslint/eslint-plugin@7.1.1)(eslint@8.57.0)(typescript@5.4.2)(vitest@1.3.1): + resolution: {integrity: sha512-atkFGQ7aVgcuSeSMDqnyevIyUpfBPMnosksgEPrKE7Y8xQlqG/5z2IQ6UDau05zXaaFv7Iz8uzqvIuKshjZ0Zw==} + engines: {node: ^18.0.0 || >= 20.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': '*' + eslint: '>=8.0.0' + vitest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + vitest: + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 7.1.1(@typescript-eslint/parser@7.1.1)(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + vitest: 1.3.1(@types/node@20.11.25) + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /eslint-plugin-vue@9.17.0(eslint@8.57.0): resolution: {integrity: sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==} engines: {node: ^14.17.0 || >=16.0.0} @@ -2760,6 +3350,55 @@ packages: - supports-color dev: true + /eslint-plugin-vue@9.22.0(eslint@8.57.0): + resolution: {integrity: sha512-7wCXv5zuVnBtZE/74z4yZ0CM8AjH6bk4MQGm7hZjUC2DBppKU5ioeOk5LGSg/s9a1ZJnIsdPLJpXnu1Rc+cVHg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + eslint: 8.57.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.0.15 + semver: 7.6.0 + vue-eslint-parser: 9.4.2(eslint@8.57.0) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-yml@1.12.2(eslint@8.57.0): + resolution: {integrity: sha512-hvS9p08FhPT7i/ynwl7/Wt7ke7Rf4P2D6fT8lZlL43peZDTsHtH2A0SIFQ7Kt7+mJ6if6P+FX3iJhMkdnxQwpg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4 + eslint: 8.57.0 + eslint-compat-utils: 0.4.1(eslint@8.57.0) + lodash: 4.17.21 + natural-compare: 1.4.0 + yaml-eslint-parser: 1.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-processor-vue-blocks@0.1.1(@vue/compiler-sfc@3.4.21)(eslint@8.57.0): + resolution: {integrity: sha512-9+dU5lU881log570oBwpelaJmOfOzSniben7IWEDRYQPPWwlvaV7NhOtsTuUWDqpYT+dtKKWPsgz4OkOi+aZnA==} + peerDependencies: + '@vue/compiler-sfc': ^3.3.0 + eslint: ^8.50.0 + dependencies: + '@vue/compiler-sfc': 3.4.21 + eslint: 8.57.0 + dev: true + + /eslint-rule-composer@0.3.0: + resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} + engines: {node: '>=4.0.0'} + dev: true + /eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2975,6 +3614,15 @@ packages: path-exists: 4.0.0 dev: true + /find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + dev: true + /flat-cache@3.1.1: resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==} engines: {node: '>=12.0.0'} @@ -3063,6 +3711,11 @@ packages: engines: {node: '>=6.9.0'} dev: true + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + /get-east-asian-width@1.2.0: resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} engines: {node: '>=18'} @@ -3165,6 +3818,18 @@ packages: type-fest: 0.20.2 dev: true + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + dev: true + /globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} @@ -3269,12 +3934,6 @@ packages: engines: {node: '>=16.17.0'} dev: true - /husky@9.0.11: - resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} - engines: {node: '>=18'} - hasBin: true - dev: true - /ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -3318,6 +3977,17 @@ packages: side-channel: 1.0.4 dev: true + /is-alphabetical@1.0.4: + resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} + dev: true + + /is-alphanumerical@1.0.4: + resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} + dependencies: + is-alphabetical: 1.0.4 + is-decimal: 1.0.4 + dev: true + /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: @@ -3375,10 +4045,19 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-decimal@1.0.4: + resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} + dev: true + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + /is-fullwidth-code-point@4.0.0: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} @@ -3397,6 +4076,10 @@ packages: dependencies: is-extglob: 2.1.1 + /is-hexadecimal@1.0.4: + resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} + dev: true + /is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} dev: true @@ -3536,12 +4219,28 @@ packages: argparse: 2.0.1 dev: true + /jsdoc-type-pratt-parser@4.0.0: + resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + engines: {node: '>=12.0.0'} + dev: true + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true dev: true + /jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + dev: true + /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true @@ -3571,6 +4270,16 @@ packages: hasBin: true dev: true + /jsonc-eslint-parser@2.4.0: + resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + semver: 7.6.0 + dev: true + /jsonc-parser@3.2.1: resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} @@ -3668,6 +4377,13 @@ packages: p-locate: 5.0.0 dev: true + /locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-locate: 6.0.0 + dev: true + /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true @@ -3746,6 +4462,22 @@ packages: semver: 7.5.4 dev: true + /mdast-util-from-markdown@0.8.5: + resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} + dependencies: + '@types/mdast': 3.0.15 + mdast-util-to-string: 2.0.0 + micromark: 2.11.4 + parse-entities: 2.0.0 + unist-util-stringify-position: 2.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /mdast-util-to-string@2.0.0: + resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} + dev: true + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -3755,6 +4487,15 @@ packages: engines: {node: '>= 8'} dev: true + /micromark@2.11.4: + resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} + dependencies: + debug: 4.3.4 + parse-entities: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -3898,6 +4639,10 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + /natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true @@ -3922,6 +4667,10 @@ packages: resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} dev: true + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: true + /normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: @@ -4055,6 +4804,13 @@ packages: yocto-queue: 0.1.0 dev: true + /p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: true + /p-limit@5.0.0: resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} engines: {node: '>=18'} @@ -4076,6 +4832,13 @@ packages: p-limit: 3.1.0 dev: true + /p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-limit: 4.0.0 + dev: true + /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -4092,6 +4855,22 @@ packages: callsites: 3.1.0 dev: true + /parse-entities@2.0.0: + resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} + dependencies: + character-entities: 1.2.4 + character-entities-legacy: 1.1.4 + character-reference-invalid: 1.1.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + is-hexadecimal: 1.0.4 + dev: true + + /parse-gitignore@2.0.0: + resolution: {integrity: sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog==} + engines: {node: '>=14'} + dev: true + /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -4107,6 +4886,11 @@ packages: engines: {node: '>=8'} dev: true + /path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -4157,6 +4941,11 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + /picomatch@4.0.1: + resolution: {integrity: sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==} + engines: {node: '>=12'} + dev: true + /pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} @@ -4183,6 +4972,14 @@ packages: util-deprecate: 1.0.2 dev: true + /postcss-selector-parser@6.0.15: + resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + /postcss@8.4.35: resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} engines: {node: ^10 || ^12 || >=14} @@ -4304,6 +5101,18 @@ packages: engines: {node: '>=8'} dev: true + /regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -4509,6 +5318,12 @@ packages: engines: {node: '>=14'} dev: true + /simple-git-hooks@2.10.0: + resolution: {integrity: sha512-TtCytVYfV77pILCkzVxpOSgYKHQyaO7fBI/iwG5bLGb0dIo/v/K1Y1IZ5DN40RQu6WNNJiN0gkuRvSYjxOhFog==} + hasBin: true + requiresBuild: true + dev: true + /sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} dev: true @@ -4566,6 +5381,13 @@ packages: spdx-license-ids: 3.0.16 dev: true + /spdx-expression-parse@4.0.0: + resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.16 + dev: true + /spdx-license-ids@3.0.16: resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} dev: true @@ -4583,6 +5405,15 @@ packages: engines: {node: '>=0.6.19'} dev: true + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + /string-width@7.1.0: resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} engines: {node: '>=18'} @@ -4679,6 +5510,13 @@ packages: engines: {node: '>= 0.4'} dev: true + /synckit@0.6.2: + resolution: {integrity: sha512-Vhf+bUa//YSTYKseDiiEuQmhGCoIF3CVBhunm3r/DQnYiGT4JssmnKQc44BIyOZRK2pKjXXAgbhfmbeoC9CJpA==} + engines: {node: '>=12.20'} + dependencies: + tslib: 2.6.2 + dev: true + /synckit@0.8.8: resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} engines: {node: ^14.18.0 || >=16.0.0} @@ -4746,6 +5584,13 @@ packages: dependencies: is-number: 7.0.0 + /toml-eslint-parser@0.9.3: + resolution: {integrity: sha512-moYoCvkNUAPCxSW9jmHmRElhm4tVJpHL8ItC/+uYD0EpPSFXbck7yREz9tNdJVTSpHVod8+HoipcpbQ0oE6gsw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + eslint-visitor-keys: 3.4.3 + dev: true + /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: false @@ -4919,6 +5764,17 @@ packages: tiny-inflate: 1.0.3 dev: false + /unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + dev: true + + /unist-util-stringify-position@2.0.3: + resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} + dependencies: + '@types/unist': 2.0.10 + dev: true + /universalify@2.0.0: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} @@ -4960,6 +5816,17 @@ packages: picocolors: 1.0.0 dev: true + /update-browserslist-db@1.0.13(browserslist@4.23.0): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.23.0 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: @@ -5116,6 +5983,24 @@ packages: - supports-color dev: true + /vue-eslint-parser@9.4.2(eslint@8.57.0): + resolution: {integrity: sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4 + eslint: 8.57.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + lodash: 4.17.21 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + dev: true + /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} dev: false @@ -5174,6 +6059,15 @@ packages: stackback: 0.0.2 dev: true + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + /wrap-ansi@9.0.0: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} @@ -5192,6 +6086,11 @@ packages: engines: {node: '>=12'} dev: true + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} dev: true @@ -5200,11 +6099,38 @@ packages: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true + /yaml-eslint-parser@1.2.2: + resolution: {integrity: sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==} + engines: {node: ^14.17.0 || >=16.0.0} + dependencies: + eslint-visitor-keys: 3.4.3 + lodash: 4.17.21 + yaml: 2.3.4 + dev: true + /yaml@2.3.4: resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} engines: {node: '>= 14'} dev: true + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.2 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index f1ccb742..52fdbb5d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,2 @@ packages: - - "playground" + - playground diff --git a/src/css.ts b/src/css.ts index 2843ede8..1a1820f0 100644 --- a/src/css.ts +++ b/src/css.ts @@ -1,15 +1,52 @@ import type { Font } from '@capsizecss/unpack' import { - createRegExp, charIn, charNotIn, + createRegExp, exactly, whitespace, } from 'magic-regexp' +// See: https://github.com/seek-oss/capsize/blob/master/packages/core/src/round.ts +function toPercentage(value: number, fractionDigits = 4) { + const percentage = value * 100 + return `${+percentage.toFixed(fractionDigits)}%` +} + +function toCSS(properties: Record, indent = 2) { + return Object.entries(properties) + .map(([key, value]) => `${' '.repeat(indent)}${key}: ${value};`) + .join('\n') +} + +const QUOTES_RE = createRegExp( + charIn('"\'').at.lineStart().or(charIn('"\'').at.lineEnd()), + ['g'], +) + +const FAMILY_RE = createRegExp( + exactly('font-family:') + .and(whitespace.optionally()) + .and(charNotIn(';}').times.any().as('fontFamily')), +) + +const SOURCE_RE = createRegExp( + exactly('src:') + .and(whitespace.optionally()) + .and(charNotIn(';}').times.any().as('src')), + ['g'], +) + +const URL_RE = createRegExp( + exactly('url(').and(charNotIn(')').times.any().as('url')).and(')'), + ['g'], +) + +export const withoutQuotes = (str: string) => str.trim().replace(QUOTES_RE, '') + export function* parseFontFace( - css: string -): Generator<{ family?: string; source?: string }> { + css: string, +): Generator<{ family?: string, source?: string }> { const fontFamily = css.match(FAMILY_RE)?.groups.fontFamily const family = withoutQuotes(fontFamily?.split(',')[0] || '') @@ -18,9 +55,8 @@ export function* parseFontFace( for (const entry of sources /* c8 ignore next */ || []) { for (const url of entry.matchAll(URL_RE)) { const source = withoutQuotes(url.groups?.url || '') - if (source) { + if (source) yield { family, source } - } } } } @@ -28,14 +64,11 @@ export function* parseFontFace( yield { family: '', source: '' } } -export const generateFallbackName = (name: string) => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion +export function generateFallbackName(name: string) { const firstFamily = withoutQuotes(name.split(',').shift()!) return `${firstFamily} fallback` } -export const withoutQuotes = (str: string) => str.trim().replace(QUOTES_RE, '') - interface FallbackOptions { name: string font: string @@ -48,10 +81,7 @@ export type FontFaceMetrics = Pick< 'ascent' | 'descent' | 'lineGap' | 'unitsPerEm' | 'xWidthAvg' > -export const generateFontFace = ( - metrics: FontFaceMetrics, - fallback: FallbackOptions -) => { +export function generateFontFace(metrics: FontFaceMetrics, fallback: FallbackOptions) { const { name: fallbackName, font: fallbackFontName, @@ -67,8 +97,8 @@ export const generateFontFace = ( ? fallbackMetrics.xWidthAvg / fallbackMetrics.unitsPerEm : 1 - const sizeAdjust = - fallbackMetrics && preferredFontXAvgRatio && fallbackFontXAvgRatio + const sizeAdjust + = fallbackMetrics && preferredFontXAvgRatio && fallbackFontXAvgRatio ? preferredFontXAvgRatio / fallbackFontXAvgRatio : 1 @@ -81,7 +111,7 @@ export const generateFontFace = ( const declaration = { 'font-family': JSON.stringify(fallbackName), - src: `local(${JSON.stringify(fallbackFontName)})`, + 'src': `local(${JSON.stringify(fallbackFontName)})`, 'size-adjust': toPercentage(sizeAdjust), 'ascent-override': toPercentage(ascentOverride), 'descent-override': toPercentage(descentOverride), @@ -91,37 +121,3 @@ export const generateFontFace = ( return `@font-face {\n${toCSS(declaration)}\n}\n` } - -// See: https://github.com/seek-oss/capsize/blob/master/packages/core/src/round.ts -const toPercentage = (value: number, fractionDigits = 4) => { - const percentage = value * 100 - return +percentage.toFixed(fractionDigits) + '%' -} - -const toCSS = (properties: Record, indent = 2) => - Object.entries(properties) - .map(([key, value]) => ' '.repeat(indent) + `${key}: ${value};`) - .join('\n') - -const QUOTES_RE = createRegExp( - charIn('"\'').at.lineStart().or(charIn('"\'').at.lineEnd()), - ['g'] -) - -const FAMILY_RE = createRegExp( - exactly('font-family:') - .and(whitespace.optionally()) - .and(charNotIn(';}').times.any().as('fontFamily')) -) - -const SOURCE_RE = createRegExp( - exactly('src:') - .and(whitespace.optionally()) - .and(charNotIn(';}').times.any().as('src')), - ['g'] -) - -const URL_RE = createRegExp( - exactly('url(').and(charNotIn(')').times.any().as('url')).and(')'), - ['g'] -) diff --git a/src/metrics.ts b/src/metrics.ts index cb059999..8b2f9b8b 100644 --- a/src/metrics.ts +++ b/src/metrics.ts @@ -1,12 +1,14 @@ import { fileURLToPath } from 'node:url' -import { fromFile, fromUrl, Font } from '@capsizecss/unpack' +import type { Font } from '@capsizecss/unpack' +import { fromFile, fromUrl } from '@capsizecss/unpack' import { fontFamilyToCamelCase } from '@capsizecss/metrics' import { parseURL } from 'ufo' -import { FontFaceMetrics, withoutQuotes } from './css' +import type { FontFaceMetrics } from './css' +import { withoutQuotes } from './css' const metricCache: Record = {} -const filterRequiredMetrics = ({ +function filterRequiredMetrics({ ascent, descent, lineGap, @@ -15,49 +17,53 @@ const filterRequiredMetrics = ({ }: Pick< Font, 'ascent' | 'descent' | 'lineGap' | 'unitsPerEm' | 'xWidthAvg' ->) => ({ - ascent, - descent, - lineGap, - unitsPerEm, - xWidthAvg, -}) +>) { + return { + ascent, + descent, + lineGap, + unitsPerEm, + xWidthAvg, + } +} export async function getMetricsForFamily(family: string) { family = withoutQuotes(family) - if (family in metricCache) return metricCache[family] + if (family in metricCache) + return metricCache[family] try { const name = fontFamilyToCamelCase(family) const { entireMetricsCollection } = await import( '@capsizecss/metrics/entireMetricsCollection' ) - const metrics = - entireMetricsCollection[name as keyof typeof entireMetricsCollection] + const metrics + = entireMetricsCollection[name as keyof typeof entireMetricsCollection] const filteredMetrics = filterRequiredMetrics(metrics) metricCache[family] = filteredMetrics return filteredMetrics - } catch { + } + catch { metricCache[family] = null return null } } export async function readMetrics(_source: URL | string) { - const source = - typeof _source !== 'string' && 'href' in _source ? _source.href : _source + const source + = typeof _source !== 'string' && 'href' in _source ? _source.href : _source - if (source in metricCache) { + if (source in metricCache) return Promise.resolve(metricCache[source]) - } const { protocol } = parseURL(source) - if (!protocol) return null + if (!protocol) + return null - const metrics = - protocol === 'file:' + const metrics + = protocol === 'file:' ? await fromFile(fileURLToPath(source)) : await fromUrl(source) diff --git a/src/transform.ts b/src/transform.ts index 6001a4a0..d57de0b3 100644 --- a/src/transform.ts +++ b/src/transform.ts @@ -1,17 +1,17 @@ import { createUnplugin } from 'unplugin' import { anyOf, - createRegExp, - exactly, charIn, charNotIn, + createRegExp, + exactly, whitespace, } from 'magic-regexp' import MagicString from 'magic-string' -import { generateFontFace, parseFontFace, generateFallbackName } from './css' -import { getMetricsForFamily, readMetrics } from './metrics' import { parseURL } from 'ufo' import { isAbsolute, join } from 'pathe' +import { generateFallbackName, generateFontFace, parseFontFace } from './css' +import { getMetricsForFamily, readMetrics } from './metrics' export interface FontaineTransformOptions { css?: { value?: string } @@ -27,20 +27,44 @@ export interface FontaineTransformOptions { const supportedExtensions = ['woff2', 'woff', 'ttf'] +const FONT_FACE_RE = createRegExp( + exactly('@font-face') + .and(whitespace.times.any()) + .and('{') + .and(charNotIn('}').times.any()) + .and('}'), + ['g'], +) + +const FONT_FAMILY_RE = createRegExp( + charNotIn(';}') + .times.any() + .as('family') + .after(exactly('font-family:').and(whitespace.times.any())) + .before(charIn(';}').or(exactly('').at.lineEnd())), + ['g'], +) + +const CSS_RE = createRegExp( + exactly('.') + .and(anyOf('sass', 'css', 'scss')) + .at.lineEnd(), +) + export const FontaineTransform = createUnplugin( (options: FontaineTransformOptions) => { const cssContext = (options.css = options.css || {}) cssContext.value = '' const resolvePath = options.resolvePath || (id => id) - const fallbackName = - options.fallbackName || options.overrideName || generateFallbackName + const fallbackName + = options.fallbackName || options.overrideName || generateFallbackName - const skipFontFaceGeneration = - options.skipFontFaceGeneration || (() => false) + const skipFontFaceGeneration + = options.skipFontFaceGeneration || (() => false) function readMetricsFromId(path: string, importer: string) { - const resolvedPath = - isAbsolute(importer) && path.startsWith('.') + const resolvedPath + = isAbsolute(importer) && path.startsWith('.') ? join(importer, path) : resolvePath(path) return readMetrics(resolvedPath) @@ -59,32 +83,34 @@ export const FontaineTransform = createUnplugin( for (const match of code.matchAll(FONT_FACE_RE)) { const matchContent = match[0] - if (match.index === undefined || !matchContent) continue + if (match.index === undefined || !matchContent) + continue faceRanges.push([match.index, match.index + matchContent.length]) for (const { family, source } of parseFontFace(matchContent)) { - if (!family) continue - if (!supportedExtensions.some(e => source?.endsWith(e))) continue - if (skipFontFaceGeneration(fallbackName(family))) continue + if (!family) + continue + if (!supportedExtensions.some(e => source?.endsWith(e))) + continue + if (skipFontFaceGeneration(fallbackName(family))) + continue - const metrics = - (await getMetricsForFamily(family)) || - (source && - (await readMetricsFromId(source, id).catch(() => null))) + const metrics + = (await getMetricsForFamily(family)) + || (source + && (await readMetricsFromId(source, id).catch(() => null))) - if (!metrics) { + if (!metrics) continue - } // Iterate backwards: Browsers will use the last working font-face in the stylesheet for (let i = options.fallbacks.length - 1; i >= 0; i--) { const fallback = options.fallbacks[i] const fallbackMetrics = await getMetricsForFamily(fallback) - if (!fallbackMetrics) { + if (!fallbackMetrics) continue - } const fontFace = generateFontFace(metrics, { name: fallbackName(family), @@ -99,7 +125,8 @@ export const FontaineTransform = createUnplugin( for (const match of code.matchAll(FONT_FAMILY_RE)) { const { index, 0: matchContent } = match - if (index === undefined || !matchContent) continue + if (index === undefined || !matchContent) + continue // Skip font-family definitions _within_ @font-face blocks if (faceRanges.some(([start, end]) => index > start && index < end)) @@ -109,17 +136,18 @@ export const FontaineTransform = createUnplugin( .map(f => f.trim()) .filter(f => !f.startsWith('var(')) - if (!families.length || families[0] === 'inherit') continue + if (!families.length || families[0] === 'inherit') + continue s.overwrite( index, index + matchContent.length, - ' ' + + ` ${ [ families[0], `"${generateFallbackName(families[0])}"`, ...families.slice(1), - ].join(', ') + ].join(', ')}`, ) } @@ -133,29 +161,5 @@ export const FontaineTransform = createUnplugin( } }, } - } -) - -const FONT_FACE_RE = createRegExp( - exactly('@font-face') - .and(whitespace.times.any()) - .and('{') - .and(charNotIn('}').times.any()) - .and('}'), - ['g'] -) - -const FONT_FAMILY_RE = createRegExp( - charNotIn(';}') - .times.any() - .as('family') - .after(exactly('font-family:').and(whitespace.times.any())) - .before(charIn(';}').or(exactly('').at.lineEnd())), - ['g'] -) - -const CSS_RE = createRegExp( - exactly('.') - .and(anyOf('sass', 'css', 'scss')) - .at.lineEnd() + }, ) diff --git a/test/e2e.spec.ts b/test/e2e.spec.ts index 8fb121a2..62ef6744 100644 --- a/test/e2e.spec.ts +++ b/test/e2e.spec.ts @@ -1,17 +1,17 @@ -import { expect, it, describe } from 'vitest' +import { readFile, readdir } from 'node:fs/promises' +import { fileURLToPath } from 'node:url' +import { describe, expect, it } from 'vitest' import { execaCommand } from 'execa' -import { readdir, readFile } from 'fs/promises' -import { fileURLToPath } from 'url' import { join } from 'pathe' describe('fontaine', () => { it('e2e', async () => { const assetsDir = fileURLToPath( - new URL('../playground/dist/assets', import.meta.url) + new URL('../playground/dist/assets', import.meta.url), ) await $`pnpm vite build playground --config test/vite.config.mjs` const cssFile = await readdir(assetsDir).then(files => - files.find(f => f.endsWith('.css')) + files.find(f => f.endsWith('.css')), ) // @ts-expect-error there must be a file or we _want_ a test failure const css = await readFile(join(assetsDir, cssFile), 'utf-8') @@ -27,8 +27,9 @@ async function $(literals: TemplateStringsArray, ...values: any[]) { const cmd = literals.reduce( (result, current, i) => result + current + (values?.[i] != null ? `${values[i]}` : ''), - '' + '', ) + // eslint-disable-next-line no-console console.log(`${process.cwd()} $> ${cmd}`) const proc = execaCommand(cmd, { stdio: 'pipe', diff --git a/test/index.spec.ts b/test/index.spec.ts index 03a1caf4..3ae534ef 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -2,12 +2,12 @@ import { createServer } from 'node:http' import { fileURLToPath } from 'node:url' import { dirname } from 'pathe' import handler from 'serve-handler' -import { describe, it, expect } from 'vitest' +import { describe, expect, it } from 'vitest' import { getRandomPort } from 'get-port-please' import { + generateFallbackName, generateFontFace, parseFontFace, - generateFallbackName, } from '../src/css' import { getMetricsForFamily, readMetrics } from '../src/metrics' @@ -18,8 +18,8 @@ describe('generateFontFace', () => { const metrics = await readMetrics(fixtureURL) // @ts-expect-error if metrics is not defined the test should throw const result = generateFontFace(metrics, { - name: 'example fallback', - font: 'fallback', + 'name': 'example fallback', + 'font': 'fallback', 'font-weight': 'bold', }) expect(result).toMatchInlineSnapshot(` @@ -59,12 +59,12 @@ describe('getMetricsForFamily', () => { expect(await getMetricsForFamily('Merriweather Sans')).toEqual(metrics) expect( - // eslint-disable-next-line + generateFontFace(metrics!, { name: 'Merriweather Sans fallback', font: 'Arial', metrics: (await getMetricsForFamily('Arial'))!, - }) + }), ).toMatchInlineSnapshot(` "@font-face { font-family: "Merriweather Sans fallback"; @@ -93,12 +93,12 @@ describe('getMetricsForFamily', () => { expect(await getMetricsForFamily('IBM Plex Mono')).toEqual(metrics) expect( - // eslint-disable-next-line + generateFontFace(metrics!, { name: 'IBM Plex Mono fallback', font: 'Arial', metrics: (await getMetricsForFamily('Arial'))!, - }) + }), ).toMatchInlineSnapshot(` "@font-face { font-family: "IBM Plex Mono fallback"; @@ -126,7 +126,7 @@ describe('getMetricsForFamily', () => { describe('readMetrics', () => { it('reads font metrics from a file', async () => { const metrics = await readMetrics( - new URL('../playground/fonts/font.ttf', import.meta.url) + new URL('../playground/fonts/font.ttf', import.meta.url), ) expect(metrics).toMatchInlineSnapshot(` { @@ -142,7 +142,7 @@ describe('readMetrics', () => { const server = createServer((request, response) => handler(request, response, { public: dirname(fileURLToPath(fixtureURL)), - }) + }), ) const port = await getRandomPort() server.listen(port) @@ -172,7 +172,7 @@ describe('parseFontFace', () => { src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"), url("/fonts/OpenSans-Regular-webfont.woff") format("woff"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; - }` + }`, ).next().value expect(result).toMatchInlineSnapshot(` { @@ -184,7 +184,7 @@ describe('parseFontFace', () => { it('should handle incomplete font-faces', () => { for (const result of parseFontFace( `@font-face { - }` + }`, )) { expect(result).toMatchInlineSnapshot(` { @@ -198,7 +198,7 @@ describe('parseFontFace', () => { `@font-face { font-family: 'Something' src: url("") format("woff"), url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"); - }` + }`, ), ]).toMatchInlineSnapshot(` [ @@ -218,7 +218,7 @@ describe('parseFontFace', () => { for (const result of parseFontFace( `@font-face { src: local("Arial") url(); - }` + }`, )) { expect(result).toMatchInlineSnapshot(` { diff --git a/test/vite.config.mjs b/test/vite.config.mjs index 7e078a43..d0bdb85d 100644 --- a/test/vite.config.mjs +++ b/test/vite.config.mjs @@ -9,7 +9,7 @@ export default defineConfig({ fallbacks: ['Arial', 'Segoe UI'], // resolve absolute URL -> file resolvePath: id => - new URL(join('../playground', '.' + id), import.meta.url), + new URL(join('../playground', `.${id}`), import.meta.url), }), ], }) diff --git a/tsconfig.json b/tsconfig.json index 787168b2..124d1641 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,8 +2,8 @@ "compilerOptions": { "target": "ESNext", "module": "ESNext", - "strict": true, "moduleResolution": "Bundler", + "strict": true, "esModuleInterop": true } }