├── .editorconfig
├── .eslintignore
├── .eslintrc.cjs
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc
├── .typesafe-i18n.json
├── LICENSE
├── README.md
├── package.json
├── playwright.config.ts
├── pnpm-lock.yaml
├── src
├── app.d.ts
├── app.html
├── components
│ ├── HeadHrefLangs.svelte
│ ├── Header.svelte
│ └── LocaleSwitcher.svelte
├── hooks.server.ts
├── i18n
│ ├── de
│ │ └── index.ts
│ ├── en
│ │ └── index.ts
│ ├── formatters.ts
│ ├── i18n-svelte.ts
│ ├── i18n-types.ts
│ ├── i18n-util.async.ts
│ ├── i18n-util.sync.ts
│ ├── i18n-util.ts
│ ├── it
│ │ └── index.ts
│ └── ru
│ │ └── index.ts
├── index.test.ts
├── lib
│ └── index.ts
├── params
│ ├── l_about.ts
│ ├── l_english.ts
│ ├── l_news.ts
│ └── lang.ts
├── routes
│ ├── +error.svelte
│ ├── +layout.server.ts
│ ├── +layout.svelte
│ ├── +layout.ts
│ ├── [[lang=lang]]
│ │ ├── +layout.ts
│ │ ├── +page.svelte
│ │ ├── +page.ts
│ │ ├── [l_about=l_about]
│ │ │ ├── +page.svelte
│ │ │ ├── +page.ts
│ │ │ └── [l_english=l_english]
│ │ │ │ ├── +page.svelte
│ │ │ │ └── +page.ts
│ │ └── [l_news=l_news]
│ │ │ ├── +page.server.ts
│ │ │ ├── +page.svelte
│ │ │ ├── +page.ts
│ │ │ └── [post]
│ │ │ ├── +page.server.ts
│ │ │ ├── +page.svelte
│ │ │ └── +page.ts
│ └── api
│ │ └── spectators
│ │ └── +server.ts
├── styles
│ └── global.scss
└── utils
│ └── db.ts
├── static
└── favicon.png
├── svelte.config.js
├── tests
└── test.ts
├── tsconfig.json
└── vite.config.ts
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | indent_style = tab
7 | indent_size = 4
8 | charset = utf-8
9 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: [
4 | 'eslint:recommended',
5 | 'plugin:@typescript-eslint/recommended',
6 | 'plugin:svelte/recommended',
7 | 'prettier'
8 | ],
9 | parser: '@typescript-eslint/parser',
10 | plugins: ['@typescript-eslint'],
11 | parserOptions: {
12 | sourceType: 'module',
13 | ecmaVersion: 2020,
14 | extraFileExtensions: ['.svelte']
15 | },
16 | env: {
17 | browser: true,
18 | es2017: true,
19 | node: true
20 | },
21 | overrides: [
22 | {
23 | files: ['*.svelte'],
24 | parser: 'svelte-eslint-parser',
25 | parserOptions: {
26 | parser: '@typescript-eslint/parser'
27 | }
28 | }
29 | ]
30 | };
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /dist
5 | /.svelte-kit
6 | /package
7 | /coverage
8 | .env
9 | .env.*
10 | !.env.example
11 | vite.config.js.timestamp-*
12 | vite.config.ts.timestamp-*
13 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 | resolution-mode=highest
3 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /dist
5 | /.svelte-kit
6 | /package
7 | /coverage
8 | .env
9 | .env.*
10 | !.env.example
11 |
12 | # Ignore files for PNPM, NPM and YARN
13 | pnpm-lock.yaml
14 | package-lock.json
15 | yarn.lock
16 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": true,
3 | "singleQuote": true,
4 | "trailingComma": "none",
5 | "printWidth": 100,
6 | "plugins": ["prettier-plugin-svelte"],
7 | "pluginSearchDirs": ["."],
8 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
9 | }
10 |
--------------------------------------------------------------------------------
/.typesafe-i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "baseLocale": "en",
3 | "esmImports": true,
4 | "runAfterGenerator": "pnpm run format:i18n",
5 | "adapter": "svelte",
6 | "$schema": "https://unpkg.com/typesafe-i18n@5.24.3/schema/typesafe-i18n.json"
7 | }
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 rinart73
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Localize URL [](https://npmjs.org/package/sveltekit-localize-url)
2 |
3 | **SvelteKit library that handles URL localization and routing.**
4 |
5 | > **Note**
6 | > This package is WIP. It works but the future updates may introduce breaking changes to simplify setup or introduce features.
7 |
8 | ## Features
9 |
10 | - Supports 3 URL structure types:
11 | - Locale prefix except for the base locale (default) - `/about`, `/ru/o-nas`;
12 | - Prefix for every locale - `/en/about`, `/ru/o-nas`;
13 | - Separate domains for locales - `example.com/about`, `example.ru/o-nas`.
14 | - Validates current URL:
15 | - Redirects `/ru/about-us` to the corrected `/ru/o-nas`;
16 | - Supports partially localized pages - throws 404 if a page isn’t available for the requested locale.
17 | - Helps to build localized URLs;
18 | - Builds alternate URLs for the ` matchParam(param, localizedParam);
57 | ```
58 |
59 | When SvelteKit will match params, it will decide that **all of following paths are valid**:
60 |
61 | - `/about-us`
62 | - `/en/about-us`
63 | - `/ru/about-us`
64 | - `/it/about-us`
65 | - `/o-nas`
66 | - `/en/o-nas`
67 | - `/ru/o-nas`
68 | - `/it/o-nas`
69 |
70 | However the `validateUrlLocale()` function that is called in the `src/routes/[[lang=lang]]/+layout.ts` will take care of that by taking registered params and using them to construct a correct path for the current locale.
71 |
72 | - If the paths match, proceed;
73 | - If the paths don't match, redirect to a corrected URL;
74 | - If it can't construct a path for the current locale, throw 404.
75 |
76 | So in the end we'll get the following:
77 |
78 | - `/about-us` - Correct;
79 | - `/ru/o-nas` - Correct;
80 | - `/o-nas`, `/en/about-us`, `/en/o-nas` - Redirect to `/about-us`;
81 | - `/ru/about-us` - Redirect to `/ru/o-nas`;
82 | - `/it/about-us`, `/it/o-nas` - 404 Not Found.
83 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sveltekit-localize-url",
3 | "description": "SvelteKit library that handles URL localization and routing.",
4 | "version": "0.1.2",
5 | "author": "Rinart73",
6 | "license": "MIT",
7 | "homepage": "https://github.com/rinart73/sveltekit-localize-url",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/rinart73/sveltekit-localize-url"
11 | },
12 | "scripts": {
13 | "dev": "run-p dev:vite typesafe-i18n",
14 | "dev:vite": "vite dev",
15 | "build": "vite build && npm run package",
16 | "preview": "vite preview",
17 | "package": "svelte-kit sync && svelte-package && publint",
18 | "prepublishOnly": "npm run package",
19 | "test": "npm run npm run test:unit && test:integration",
20 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
21 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
22 | "lint": "prettier --plugin-search-dir . --check . && eslint .",
23 | "format": "prettier --plugin-search-dir . --write .",
24 | "format:i18n": "prettier --plugin-search-dir=. --write ./src/i18n",
25 | "test:integration": "playwright test",
26 | "test:unit": "vitest --coverage",
27 | "typesafe-i18n": "typesafe-i18n"
28 | },
29 | "exports": {
30 | ".": {
31 | "types": "./dist/index.d.ts",
32 | "svelte": "./dist/index.js"
33 | }
34 | },
35 | "files": [
36 | "dist",
37 | "!dist/**/*.test.*",
38 | "!dist/**/*.spec.*"
39 | ],
40 | "peerDependencies": {
41 | "svelte": "^4.0.0"
42 | },
43 | "devDependencies": {
44 | "@playwright/test": "^1.35.1",
45 | "@sveltejs/adapter-auto": "^2.1.0",
46 | "@sveltejs/kit": "^1.22.1",
47 | "@sveltejs/package": "^2.1.0",
48 | "@typescript-eslint/eslint-plugin": "^5.61.0",
49 | "@typescript-eslint/parser": "^5.61.0",
50 | "@vitest/coverage-v8": "^0.33.0",
51 | "eslint": "^8.44.0",
52 | "eslint-config-prettier": "^8.8.0",
53 | "eslint-plugin-svelte": "^2.32.2",
54 | "npm-run-all": "^4.1.5",
55 | "prettier": "^2.8.8",
56 | "prettier-plugin-svelte": "^2.10.1",
57 | "publint": "^0.1.16",
58 | "sass": "^1.63.6",
59 | "svelte": "^4.0.5",
60 | "svelte-check": "^3.4.5",
61 | "tslib": "^2.6.0",
62 | "typescript": "^5.1.6",
63 | "vite": "^4.4.2",
64 | "vitest": "^0.32.4",
65 | "typesafe-i18n": "^5.24.3"
66 | },
67 | "svelte": "./dist/index.js",
68 | "types": "./dist/index.d.ts",
69 | "type": "module"
70 | }
71 |
--------------------------------------------------------------------------------
/playwright.config.ts:
--------------------------------------------------------------------------------
1 | import type { PlaywrightTestConfig } from '@playwright/test';
2 |
3 | const config: PlaywrightTestConfig = {
4 | webServer: {
5 | command: 'npm run build && npm run preview',
6 | port: 4173
7 | },
8 | testDir: 'tests',
9 | testMatch: /(.+\.)?(test|spec)\.[jt]s/
10 | };
11 |
12 | export default config;
13 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | devDependencies:
8 | '@playwright/test':
9 | specifier: ^1.35.1
10 | version: 1.35.1
11 | '@sveltejs/adapter-auto':
12 | specifier: ^2.1.0
13 | version: 2.1.0(@sveltejs/kit@1.22.1)
14 | '@sveltejs/kit':
15 | specifier: ^1.22.1
16 | version: 1.22.1(svelte@4.0.5)(vite@4.4.2)
17 | '@sveltejs/package':
18 | specifier: ^2.1.0
19 | version: 2.1.0(svelte@4.0.5)(typescript@5.1.6)
20 | '@typescript-eslint/eslint-plugin':
21 | specifier: ^5.61.0
22 | version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.6)
23 | '@typescript-eslint/parser':
24 | specifier: ^5.61.0
25 | version: 5.61.0(eslint@8.44.0)(typescript@5.1.6)
26 | '@vitest/coverage-v8':
27 | specifier: ^0.33.0
28 | version: 0.33.0(vitest@0.32.4)
29 | eslint:
30 | specifier: ^8.44.0
31 | version: 8.44.0
32 | eslint-config-prettier:
33 | specifier: ^8.8.0
34 | version: 8.8.0(eslint@8.44.0)
35 | eslint-plugin-svelte:
36 | specifier: ^2.32.2
37 | version: 2.32.2(eslint@8.44.0)(svelte@4.0.5)
38 | npm-run-all:
39 | specifier: ^4.1.5
40 | version: 4.1.5
41 | prettier:
42 | specifier: ^2.8.8
43 | version: 2.8.8
44 | prettier-plugin-svelte:
45 | specifier: ^2.10.1
46 | version: 2.10.1(prettier@2.8.8)(svelte@4.0.5)
47 | publint:
48 | specifier: ^0.1.16
49 | version: 0.1.16
50 | sass:
51 | specifier: ^1.63.6
52 | version: 1.63.6
53 | svelte:
54 | specifier: ^4.0.5
55 | version: 4.0.5
56 | svelte-check:
57 | specifier: ^3.4.5
58 | version: 3.4.5(postcss@8.4.25)(sass@1.63.6)(svelte@4.0.5)
59 | tslib:
60 | specifier: ^2.6.0
61 | version: 2.6.0
62 | typesafe-i18n:
63 | specifier: ^5.24.3
64 | version: 5.24.3(typescript@5.1.6)
65 | typescript:
66 | specifier: ^5.1.6
67 | version: 5.1.6
68 | vite:
69 | specifier: ^4.4.2
70 | version: 4.4.2(@types/node@20.4.1)(sass@1.63.6)
71 | vitest:
72 | specifier: ^0.32.4
73 | version: 0.32.4(sass@1.63.6)
74 |
75 | packages:
76 |
77 | /@aashutoshrathi/word-wrap@1.2.6:
78 | resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
79 | engines: {node: '>=0.10.0'}
80 | dev: true
81 |
82 | /@ampproject/remapping@2.2.1:
83 | resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
84 | engines: {node: '>=6.0.0'}
85 | dependencies:
86 | '@jridgewell/gen-mapping': 0.3.3
87 | '@jridgewell/trace-mapping': 0.3.18
88 | dev: true
89 |
90 | /@bcoe/v8-coverage@0.2.3:
91 | resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
92 | dev: true
93 |
94 | /@esbuild/android-arm64@0.18.11:
95 | resolution: {integrity: sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==}
96 | engines: {node: '>=12'}
97 | cpu: [arm64]
98 | os: [android]
99 | requiresBuild: true
100 | dev: true
101 | optional: true
102 |
103 | /@esbuild/android-arm@0.18.11:
104 | resolution: {integrity: sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==}
105 | engines: {node: '>=12'}
106 | cpu: [arm]
107 | os: [android]
108 | requiresBuild: true
109 | dev: true
110 | optional: true
111 |
112 | /@esbuild/android-x64@0.18.11:
113 | resolution: {integrity: sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==}
114 | engines: {node: '>=12'}
115 | cpu: [x64]
116 | os: [android]
117 | requiresBuild: true
118 | dev: true
119 | optional: true
120 |
121 | /@esbuild/darwin-arm64@0.18.11:
122 | resolution: {integrity: sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==}
123 | engines: {node: '>=12'}
124 | cpu: [arm64]
125 | os: [darwin]
126 | requiresBuild: true
127 | dev: true
128 | optional: true
129 |
130 | /@esbuild/darwin-x64@0.18.11:
131 | resolution: {integrity: sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==}
132 | engines: {node: '>=12'}
133 | cpu: [x64]
134 | os: [darwin]
135 | requiresBuild: true
136 | dev: true
137 | optional: true
138 |
139 | /@esbuild/freebsd-arm64@0.18.11:
140 | resolution: {integrity: sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==}
141 | engines: {node: '>=12'}
142 | cpu: [arm64]
143 | os: [freebsd]
144 | requiresBuild: true
145 | dev: true
146 | optional: true
147 |
148 | /@esbuild/freebsd-x64@0.18.11:
149 | resolution: {integrity: sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==}
150 | engines: {node: '>=12'}
151 | cpu: [x64]
152 | os: [freebsd]
153 | requiresBuild: true
154 | dev: true
155 | optional: true
156 |
157 | /@esbuild/linux-arm64@0.18.11:
158 | resolution: {integrity: sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==}
159 | engines: {node: '>=12'}
160 | cpu: [arm64]
161 | os: [linux]
162 | requiresBuild: true
163 | dev: true
164 | optional: true
165 |
166 | /@esbuild/linux-arm@0.18.11:
167 | resolution: {integrity: sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==}
168 | engines: {node: '>=12'}
169 | cpu: [arm]
170 | os: [linux]
171 | requiresBuild: true
172 | dev: true
173 | optional: true
174 |
175 | /@esbuild/linux-ia32@0.18.11:
176 | resolution: {integrity: sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==}
177 | engines: {node: '>=12'}
178 | cpu: [ia32]
179 | os: [linux]
180 | requiresBuild: true
181 | dev: true
182 | optional: true
183 |
184 | /@esbuild/linux-loong64@0.18.11:
185 | resolution: {integrity: sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==}
186 | engines: {node: '>=12'}
187 | cpu: [loong64]
188 | os: [linux]
189 | requiresBuild: true
190 | dev: true
191 | optional: true
192 |
193 | /@esbuild/linux-mips64el@0.18.11:
194 | resolution: {integrity: sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==}
195 | engines: {node: '>=12'}
196 | cpu: [mips64el]
197 | os: [linux]
198 | requiresBuild: true
199 | dev: true
200 | optional: true
201 |
202 | /@esbuild/linux-ppc64@0.18.11:
203 | resolution: {integrity: sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==}
204 | engines: {node: '>=12'}
205 | cpu: [ppc64]
206 | os: [linux]
207 | requiresBuild: true
208 | dev: true
209 | optional: true
210 |
211 | /@esbuild/linux-riscv64@0.18.11:
212 | resolution: {integrity: sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==}
213 | engines: {node: '>=12'}
214 | cpu: [riscv64]
215 | os: [linux]
216 | requiresBuild: true
217 | dev: true
218 | optional: true
219 |
220 | /@esbuild/linux-s390x@0.18.11:
221 | resolution: {integrity: sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==}
222 | engines: {node: '>=12'}
223 | cpu: [s390x]
224 | os: [linux]
225 | requiresBuild: true
226 | dev: true
227 | optional: true
228 |
229 | /@esbuild/linux-x64@0.18.11:
230 | resolution: {integrity: sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==}
231 | engines: {node: '>=12'}
232 | cpu: [x64]
233 | os: [linux]
234 | requiresBuild: true
235 | dev: true
236 | optional: true
237 |
238 | /@esbuild/netbsd-x64@0.18.11:
239 | resolution: {integrity: sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==}
240 | engines: {node: '>=12'}
241 | cpu: [x64]
242 | os: [netbsd]
243 | requiresBuild: true
244 | dev: true
245 | optional: true
246 |
247 | /@esbuild/openbsd-x64@0.18.11:
248 | resolution: {integrity: sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==}
249 | engines: {node: '>=12'}
250 | cpu: [x64]
251 | os: [openbsd]
252 | requiresBuild: true
253 | dev: true
254 | optional: true
255 |
256 | /@esbuild/sunos-x64@0.18.11:
257 | resolution: {integrity: sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==}
258 | engines: {node: '>=12'}
259 | cpu: [x64]
260 | os: [sunos]
261 | requiresBuild: true
262 | dev: true
263 | optional: true
264 |
265 | /@esbuild/win32-arm64@0.18.11:
266 | resolution: {integrity: sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==}
267 | engines: {node: '>=12'}
268 | cpu: [arm64]
269 | os: [win32]
270 | requiresBuild: true
271 | dev: true
272 | optional: true
273 |
274 | /@esbuild/win32-ia32@0.18.11:
275 | resolution: {integrity: sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==}
276 | engines: {node: '>=12'}
277 | cpu: [ia32]
278 | os: [win32]
279 | requiresBuild: true
280 | dev: true
281 | optional: true
282 |
283 | /@esbuild/win32-x64@0.18.11:
284 | resolution: {integrity: sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==}
285 | engines: {node: '>=12'}
286 | cpu: [x64]
287 | os: [win32]
288 | requiresBuild: true
289 | dev: true
290 | optional: true
291 |
292 | /@eslint-community/eslint-utils@4.4.0(eslint@8.44.0):
293 | resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
294 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
295 | peerDependencies:
296 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
297 | dependencies:
298 | eslint: 8.44.0
299 | eslint-visitor-keys: 3.4.1
300 | dev: true
301 |
302 | /@eslint-community/regexpp@4.5.1:
303 | resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==}
304 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
305 | dev: true
306 |
307 | /@eslint/eslintrc@2.1.0:
308 | resolution: {integrity: sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==}
309 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
310 | dependencies:
311 | ajv: 6.12.6
312 | debug: 4.3.4
313 | espree: 9.6.0
314 | globals: 13.20.0
315 | ignore: 5.2.4
316 | import-fresh: 3.3.0
317 | js-yaml: 4.1.0
318 | minimatch: 3.1.2
319 | strip-json-comments: 3.1.1
320 | transitivePeerDependencies:
321 | - supports-color
322 | dev: true
323 |
324 | /@eslint/js@8.44.0:
325 | resolution: {integrity: sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==}
326 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
327 | dev: true
328 |
329 | /@humanwhocodes/config-array@0.11.10:
330 | resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
331 | engines: {node: '>=10.10.0'}
332 | dependencies:
333 | '@humanwhocodes/object-schema': 1.2.1
334 | debug: 4.3.4
335 | minimatch: 3.1.2
336 | transitivePeerDependencies:
337 | - supports-color
338 | dev: true
339 |
340 | /@humanwhocodes/module-importer@1.0.1:
341 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
342 | engines: {node: '>=12.22'}
343 | dev: true
344 |
345 | /@humanwhocodes/object-schema@1.2.1:
346 | resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
347 | dev: true
348 |
349 | /@istanbuljs/schema@0.1.3:
350 | resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
351 | engines: {node: '>=8'}
352 | dev: true
353 |
354 | /@jest/schemas@29.6.0:
355 | resolution: {integrity: sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==}
356 | engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
357 | dependencies:
358 | '@sinclair/typebox': 0.27.8
359 | dev: true
360 |
361 | /@jridgewell/gen-mapping@0.3.3:
362 | resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
363 | engines: {node: '>=6.0.0'}
364 | dependencies:
365 | '@jridgewell/set-array': 1.1.2
366 | '@jridgewell/sourcemap-codec': 1.4.15
367 | '@jridgewell/trace-mapping': 0.3.18
368 | dev: true
369 |
370 | /@jridgewell/resolve-uri@3.1.0:
371 | resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
372 | engines: {node: '>=6.0.0'}
373 | dev: true
374 |
375 | /@jridgewell/set-array@1.1.2:
376 | resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
377 | engines: {node: '>=6.0.0'}
378 | dev: true
379 |
380 | /@jridgewell/sourcemap-codec@1.4.14:
381 | resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
382 | dev: true
383 |
384 | /@jridgewell/sourcemap-codec@1.4.15:
385 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
386 | dev: true
387 |
388 | /@jridgewell/trace-mapping@0.3.18:
389 | resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==}
390 | dependencies:
391 | '@jridgewell/resolve-uri': 3.1.0
392 | '@jridgewell/sourcemap-codec': 1.4.14
393 | dev: true
394 |
395 | /@nodelib/fs.scandir@2.1.5:
396 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
397 | engines: {node: '>= 8'}
398 | dependencies:
399 | '@nodelib/fs.stat': 2.0.5
400 | run-parallel: 1.2.0
401 | dev: true
402 |
403 | /@nodelib/fs.stat@2.0.5:
404 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
405 | engines: {node: '>= 8'}
406 | dev: true
407 |
408 | /@nodelib/fs.walk@1.2.8:
409 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
410 | engines: {node: '>= 8'}
411 | dependencies:
412 | '@nodelib/fs.scandir': 2.1.5
413 | fastq: 1.15.0
414 | dev: true
415 |
416 | /@playwright/test@1.35.1:
417 | resolution: {integrity: sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==}
418 | engines: {node: '>=16'}
419 | hasBin: true
420 | dependencies:
421 | '@types/node': 20.4.1
422 | playwright-core: 1.35.1
423 | optionalDependencies:
424 | fsevents: 2.3.2
425 | dev: true
426 |
427 | /@polka/url@1.0.0-next.21:
428 | resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
429 | dev: true
430 |
431 | /@sinclair/typebox@0.27.8:
432 | resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
433 | dev: true
434 |
435 | /@sveltejs/adapter-auto@2.1.0(@sveltejs/kit@1.22.1):
436 | resolution: {integrity: sha512-o2pZCfATFtA/Gw/BB0Xm7k4EYaekXxaPGER3xGSY3FvzFJGTlJlZjBseaXwYSM94lZ0HniOjTokN3cWaLX6fow==}
437 | peerDependencies:
438 | '@sveltejs/kit': ^1.0.0
439 | dependencies:
440 | '@sveltejs/kit': 1.22.1(svelte@4.0.5)(vite@4.4.2)
441 | import-meta-resolve: 3.0.0
442 | dev: true
443 |
444 | /@sveltejs/kit@1.22.1(svelte@4.0.5)(vite@4.4.2):
445 | resolution: {integrity: sha512-idFhKVEHuCKbTETvuo3V7UShqSYX9JMKVJXP546dOTkh5ZRejo5XtKtsB5TCSwNBa0TH8hIV44/bnylaFhM1Vg==}
446 | engines: {node: ^16.14 || >=18}
447 | hasBin: true
448 | requiresBuild: true
449 | peerDependencies:
450 | svelte: ^3.54.0 || ^4.0.0-next.0
451 | vite: ^4.0.0
452 | dependencies:
453 | '@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.0.5)(vite@4.4.2)
454 | '@types/cookie': 0.5.1
455 | cookie: 0.5.0
456 | devalue: 4.3.2
457 | esm-env: 1.0.0
458 | kleur: 4.1.5
459 | magic-string: 0.30.1
460 | mime: 3.0.0
461 | sade: 1.8.1
462 | set-cookie-parser: 2.6.0
463 | sirv: 2.0.3
464 | svelte: 4.0.5
465 | undici: 5.22.1
466 | vite: 4.4.2(@types/node@20.4.1)(sass@1.63.6)
467 | transitivePeerDependencies:
468 | - supports-color
469 | dev: true
470 |
471 | /@sveltejs/package@2.1.0(svelte@4.0.5)(typescript@5.1.6):
472 | resolution: {integrity: sha512-c6PLH9G2YLQ48kqrS2XX422BrLNABBstSiapamchVJaQnOTXyJmUR8KmoCCySnzVy3PiYL6jg12UnoPmjW3SwA==}
473 | engines: {node: ^16.14 || >=18}
474 | hasBin: true
475 | peerDependencies:
476 | svelte: ^3.44.0 || ^4.0.0
477 | dependencies:
478 | chokidar: 3.5.3
479 | kleur: 4.1.5
480 | sade: 1.8.1
481 | svelte: 4.0.5
482 | svelte2tsx: 0.6.19(svelte@4.0.5)(typescript@5.1.6)
483 | transitivePeerDependencies:
484 | - typescript
485 | dev: true
486 |
487 | /@sveltejs/vite-plugin-svelte-inspector@1.0.3(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.0.5)(vite@4.4.2):
488 | resolution: {integrity: sha512-Khdl5jmmPN6SUsVuqSXatKpQTMIifoQPDanaxC84m9JxIibWvSABJyHpyys0Z+1yYrxY5TTEQm+6elh0XCMaOA==}
489 | engines: {node: ^14.18.0 || >= 16}
490 | peerDependencies:
491 | '@sveltejs/vite-plugin-svelte': ^2.2.0
492 | svelte: ^3.54.0 || ^4.0.0
493 | vite: ^4.0.0
494 | dependencies:
495 | '@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.0.5)(vite@4.4.2)
496 | debug: 4.3.4
497 | svelte: 4.0.5
498 | vite: 4.4.2(@types/node@20.4.1)(sass@1.63.6)
499 | transitivePeerDependencies:
500 | - supports-color
501 | dev: true
502 |
503 | /@sveltejs/vite-plugin-svelte@2.4.2(svelte@4.0.5)(vite@4.4.2):
504 | resolution: {integrity: sha512-ePfcC48ftMKhkT0OFGdOyycYKnnkT6i/buzey+vHRTR/JpQvuPzzhf1PtKqCDQfJRgoPSN2vscXs6gLigx/zGw==}
505 | engines: {node: ^14.18.0 || >= 16}
506 | peerDependencies:
507 | svelte: ^3.54.0 || ^4.0.0
508 | vite: ^4.0.0
509 | dependencies:
510 | '@sveltejs/vite-plugin-svelte-inspector': 1.0.3(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.0.5)(vite@4.4.2)
511 | debug: 4.3.4
512 | deepmerge: 4.3.1
513 | kleur: 4.1.5
514 | magic-string: 0.30.1
515 | svelte: 4.0.5
516 | svelte-hmr: 0.15.2(svelte@4.0.5)
517 | vite: 4.4.2(@types/node@20.4.1)(sass@1.63.6)
518 | vitefu: 0.2.4(vite@4.4.2)
519 | transitivePeerDependencies:
520 | - supports-color
521 | dev: true
522 |
523 | /@types/chai-subset@1.3.3:
524 | resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
525 | dependencies:
526 | '@types/chai': 4.3.5
527 | dev: true
528 |
529 | /@types/chai@4.3.5:
530 | resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==}
531 | dev: true
532 |
533 | /@types/cookie@0.5.1:
534 | resolution: {integrity: sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==}
535 | dev: true
536 |
537 | /@types/estree@1.0.1:
538 | resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
539 | dev: true
540 |
541 | /@types/istanbul-lib-coverage@2.0.4:
542 | resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==}
543 | dev: true
544 |
545 | /@types/json-schema@7.0.12:
546 | resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
547 | dev: true
548 |
549 | /@types/node@20.4.1:
550 | resolution: {integrity: sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==}
551 | dev: true
552 |
553 | /@types/pug@2.0.6:
554 | resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==}
555 | dev: true
556 |
557 | /@types/semver@7.5.0:
558 | resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
559 | dev: true
560 |
561 | /@typescript-eslint/eslint-plugin@5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.6):
562 | resolution: {integrity: sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g==}
563 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
564 | peerDependencies:
565 | '@typescript-eslint/parser': ^5.0.0
566 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
567 | typescript: '*'
568 | peerDependenciesMeta:
569 | typescript:
570 | optional: true
571 | dependencies:
572 | '@eslint-community/regexpp': 4.5.1
573 | '@typescript-eslint/parser': 5.61.0(eslint@8.44.0)(typescript@5.1.6)
574 | '@typescript-eslint/scope-manager': 5.61.0
575 | '@typescript-eslint/type-utils': 5.61.0(eslint@8.44.0)(typescript@5.1.6)
576 | '@typescript-eslint/utils': 5.61.0(eslint@8.44.0)(typescript@5.1.6)
577 | debug: 4.3.4
578 | eslint: 8.44.0
579 | graphemer: 1.4.0
580 | ignore: 5.2.4
581 | natural-compare-lite: 1.4.0
582 | semver: 7.5.4
583 | tsutils: 3.21.0(typescript@5.1.6)
584 | typescript: 5.1.6
585 | transitivePeerDependencies:
586 | - supports-color
587 | dev: true
588 |
589 | /@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.1.6):
590 | resolution: {integrity: sha512-yGr4Sgyh8uO6fSi9hw3jAFXNBHbCtKKFMdX2IkT3ZqpKmtAq3lHS4ixB/COFuAIJpwl9/AqF7j72ZDWYKmIfvg==}
591 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
592 | peerDependencies:
593 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
594 | typescript: '*'
595 | peerDependenciesMeta:
596 | typescript:
597 | optional: true
598 | dependencies:
599 | '@typescript-eslint/scope-manager': 5.61.0
600 | '@typescript-eslint/types': 5.61.0
601 | '@typescript-eslint/typescript-estree': 5.61.0(typescript@5.1.6)
602 | debug: 4.3.4
603 | eslint: 8.44.0
604 | typescript: 5.1.6
605 | transitivePeerDependencies:
606 | - supports-color
607 | dev: true
608 |
609 | /@typescript-eslint/scope-manager@5.61.0:
610 | resolution: {integrity: sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw==}
611 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
612 | dependencies:
613 | '@typescript-eslint/types': 5.61.0
614 | '@typescript-eslint/visitor-keys': 5.61.0
615 | dev: true
616 |
617 | /@typescript-eslint/type-utils@5.61.0(eslint@8.44.0)(typescript@5.1.6):
618 | resolution: {integrity: sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg==}
619 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
620 | peerDependencies:
621 | eslint: '*'
622 | typescript: '*'
623 | peerDependenciesMeta:
624 | typescript:
625 | optional: true
626 | dependencies:
627 | '@typescript-eslint/typescript-estree': 5.61.0(typescript@5.1.6)
628 | '@typescript-eslint/utils': 5.61.0(eslint@8.44.0)(typescript@5.1.6)
629 | debug: 4.3.4
630 | eslint: 8.44.0
631 | tsutils: 3.21.0(typescript@5.1.6)
632 | typescript: 5.1.6
633 | transitivePeerDependencies:
634 | - supports-color
635 | dev: true
636 |
637 | /@typescript-eslint/types@5.61.0:
638 | resolution: {integrity: sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ==}
639 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
640 | dev: true
641 |
642 | /@typescript-eslint/typescript-estree@5.61.0(typescript@5.1.6):
643 | resolution: {integrity: sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw==}
644 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
645 | peerDependencies:
646 | typescript: '*'
647 | peerDependenciesMeta:
648 | typescript:
649 | optional: true
650 | dependencies:
651 | '@typescript-eslint/types': 5.61.0
652 | '@typescript-eslint/visitor-keys': 5.61.0
653 | debug: 4.3.4
654 | globby: 11.1.0
655 | is-glob: 4.0.3
656 | semver: 7.5.4
657 | tsutils: 3.21.0(typescript@5.1.6)
658 | typescript: 5.1.6
659 | transitivePeerDependencies:
660 | - supports-color
661 | dev: true
662 |
663 | /@typescript-eslint/utils@5.61.0(eslint@8.44.0)(typescript@5.1.6):
664 | resolution: {integrity: sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ==}
665 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
666 | peerDependencies:
667 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
668 | dependencies:
669 | '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0)
670 | '@types/json-schema': 7.0.12
671 | '@types/semver': 7.5.0
672 | '@typescript-eslint/scope-manager': 5.61.0
673 | '@typescript-eslint/types': 5.61.0
674 | '@typescript-eslint/typescript-estree': 5.61.0(typescript@5.1.6)
675 | eslint: 8.44.0
676 | eslint-scope: 5.1.1
677 | semver: 7.5.4
678 | transitivePeerDependencies:
679 | - supports-color
680 | - typescript
681 | dev: true
682 |
683 | /@typescript-eslint/visitor-keys@5.61.0:
684 | resolution: {integrity: sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg==}
685 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
686 | dependencies:
687 | '@typescript-eslint/types': 5.61.0
688 | eslint-visitor-keys: 3.4.1
689 | dev: true
690 |
691 | /@vitest/coverage-v8@0.33.0(vitest@0.32.4):
692 | resolution: {integrity: sha512-Rj5IzoLF7FLj6yR7TmqsfRDSeaFki6NAJ/cQexqhbWkHEV2htlVGrmuOde3xzvFsCbLCagf4omhcIaVmfU8Okg==}
693 | peerDependencies:
694 | vitest: '>=0.32.0 <1'
695 | dependencies:
696 | '@ampproject/remapping': 2.2.1
697 | '@bcoe/v8-coverage': 0.2.3
698 | istanbul-lib-coverage: 3.2.0
699 | istanbul-lib-report: 3.0.0
700 | istanbul-lib-source-maps: 4.0.1
701 | istanbul-reports: 3.1.5
702 | magic-string: 0.30.1
703 | picocolors: 1.0.0
704 | std-env: 3.3.3
705 | test-exclude: 6.0.0
706 | v8-to-istanbul: 9.1.0
707 | vitest: 0.32.4(sass@1.63.6)
708 | transitivePeerDependencies:
709 | - supports-color
710 | dev: true
711 |
712 | /@vitest/expect@0.32.4:
713 | resolution: {integrity: sha512-m7EPUqmGIwIeoU763N+ivkFjTzbaBn0n9evsTOcde03ugy2avPs3kZbYmw3DkcH1j5mxhMhdamJkLQ6dM1bk/A==}
714 | dependencies:
715 | '@vitest/spy': 0.32.4
716 | '@vitest/utils': 0.32.4
717 | chai: 4.3.7
718 | dev: true
719 |
720 | /@vitest/runner@0.32.4:
721 | resolution: {integrity: sha512-cHOVCkiRazobgdKLnczmz2oaKK9GJOw6ZyRcaPdssO1ej+wzHVIkWiCiNacb3TTYPdzMddYkCgMjZ4r8C0JFCw==}
722 | dependencies:
723 | '@vitest/utils': 0.32.4
724 | p-limit: 4.0.0
725 | pathe: 1.1.1
726 | dev: true
727 |
728 | /@vitest/snapshot@0.32.4:
729 | resolution: {integrity: sha512-IRpyqn9t14uqsFlVI2d7DFMImGMs1Q9218of40bdQQgMePwVdmix33yMNnebXcTzDU5eiV3eUsoxxH5v0x/IQA==}
730 | dependencies:
731 | magic-string: 0.30.1
732 | pathe: 1.1.1
733 | pretty-format: 29.6.1
734 | dev: true
735 |
736 | /@vitest/spy@0.32.4:
737 | resolution: {integrity: sha512-oA7rCOqVOOpE6rEoXuCOADX7Lla1LIa4hljI2MSccbpec54q+oifhziZIJXxlE/CvI2E+ElhBHzVu0VEvJGQKQ==}
738 | dependencies:
739 | tinyspy: 2.1.1
740 | dev: true
741 |
742 | /@vitest/utils@0.32.4:
743 | resolution: {integrity: sha512-Gwnl8dhd1uJ+HXrYyV0eRqfmk9ek1ASE/LWfTCuWMw+d07ogHqp4hEAV28NiecimK6UY9DpSEPh+pXBA5gtTBg==}
744 | dependencies:
745 | diff-sequences: 29.4.3
746 | loupe: 2.3.6
747 | pretty-format: 29.6.1
748 | dev: true
749 |
750 | /acorn-jsx@5.3.2(acorn@8.10.0):
751 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
752 | peerDependencies:
753 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
754 | dependencies:
755 | acorn: 8.10.0
756 | dev: true
757 |
758 | /acorn-walk@8.2.0:
759 | resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
760 | engines: {node: '>=0.4.0'}
761 | dev: true
762 |
763 | /acorn@8.10.0:
764 | resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==}
765 | engines: {node: '>=0.4.0'}
766 | hasBin: true
767 | dev: true
768 |
769 | /ajv@6.12.6:
770 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
771 | dependencies:
772 | fast-deep-equal: 3.1.3
773 | fast-json-stable-stringify: 2.1.0
774 | json-schema-traverse: 0.4.1
775 | uri-js: 4.4.1
776 | dev: true
777 |
778 | /ansi-regex@5.0.1:
779 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
780 | engines: {node: '>=8'}
781 | dev: true
782 |
783 | /ansi-styles@3.2.1:
784 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
785 | engines: {node: '>=4'}
786 | dependencies:
787 | color-convert: 1.9.3
788 | dev: true
789 |
790 | /ansi-styles@4.3.0:
791 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
792 | engines: {node: '>=8'}
793 | dependencies:
794 | color-convert: 2.0.1
795 | dev: true
796 |
797 | /ansi-styles@5.2.0:
798 | resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
799 | engines: {node: '>=10'}
800 | dev: true
801 |
802 | /anymatch@3.1.3:
803 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
804 | engines: {node: '>= 8'}
805 | dependencies:
806 | normalize-path: 3.0.0
807 | picomatch: 2.3.1
808 | dev: true
809 |
810 | /argparse@2.0.1:
811 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
812 | dev: true
813 |
814 | /aria-query@5.3.0:
815 | resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
816 | dependencies:
817 | dequal: 2.0.3
818 | dev: true
819 |
820 | /array-buffer-byte-length@1.0.0:
821 | resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==}
822 | dependencies:
823 | call-bind: 1.0.2
824 | is-array-buffer: 3.0.2
825 | dev: true
826 |
827 | /array-union@2.1.0:
828 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
829 | engines: {node: '>=8'}
830 | dev: true
831 |
832 | /assertion-error@1.1.0:
833 | resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
834 | dev: true
835 |
836 | /available-typed-arrays@1.0.5:
837 | resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
838 | engines: {node: '>= 0.4'}
839 | dev: true
840 |
841 | /axobject-query@3.2.1:
842 | resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==}
843 | dependencies:
844 | dequal: 2.0.3
845 | dev: true
846 |
847 | /balanced-match@1.0.2:
848 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
849 | dev: true
850 |
851 | /binary-extensions@2.2.0:
852 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
853 | engines: {node: '>=8'}
854 | dev: true
855 |
856 | /brace-expansion@1.1.11:
857 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
858 | dependencies:
859 | balanced-match: 1.0.2
860 | concat-map: 0.0.1
861 | dev: true
862 |
863 | /brace-expansion@2.0.1:
864 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
865 | dependencies:
866 | balanced-match: 1.0.2
867 | dev: true
868 |
869 | /braces@3.0.2:
870 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
871 | engines: {node: '>=8'}
872 | dependencies:
873 | fill-range: 7.0.1
874 | dev: true
875 |
876 | /buffer-crc32@0.2.13:
877 | resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
878 | dev: true
879 |
880 | /busboy@1.6.0:
881 | resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
882 | engines: {node: '>=10.16.0'}
883 | dependencies:
884 | streamsearch: 1.1.0
885 | dev: true
886 |
887 | /cac@6.7.14:
888 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
889 | engines: {node: '>=8'}
890 | dev: true
891 |
892 | /call-bind@1.0.2:
893 | resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
894 | dependencies:
895 | function-bind: 1.1.1
896 | get-intrinsic: 1.2.1
897 | dev: true
898 |
899 | /callsites@3.1.0:
900 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
901 | engines: {node: '>=6'}
902 | dev: true
903 |
904 | /chai@4.3.7:
905 | resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==}
906 | engines: {node: '>=4'}
907 | dependencies:
908 | assertion-error: 1.1.0
909 | check-error: 1.0.2
910 | deep-eql: 4.1.3
911 | get-func-name: 2.0.0
912 | loupe: 2.3.6
913 | pathval: 1.1.1
914 | type-detect: 4.0.8
915 | dev: true
916 |
917 | /chalk@2.4.2:
918 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
919 | engines: {node: '>=4'}
920 | dependencies:
921 | ansi-styles: 3.2.1
922 | escape-string-regexp: 1.0.5
923 | supports-color: 5.5.0
924 | dev: true
925 |
926 | /chalk@4.1.2:
927 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
928 | engines: {node: '>=10'}
929 | dependencies:
930 | ansi-styles: 4.3.0
931 | supports-color: 7.2.0
932 | dev: true
933 |
934 | /check-error@1.0.2:
935 | resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
936 | dev: true
937 |
938 | /chokidar@3.5.3:
939 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
940 | engines: {node: '>= 8.10.0'}
941 | dependencies:
942 | anymatch: 3.1.3
943 | braces: 3.0.2
944 | glob-parent: 5.1.2
945 | is-binary-path: 2.1.0
946 | is-glob: 4.0.3
947 | normalize-path: 3.0.0
948 | readdirp: 3.6.0
949 | optionalDependencies:
950 | fsevents: 2.3.2
951 | dev: true
952 |
953 | /code-red@1.0.3:
954 | resolution: {integrity: sha512-kVwJELqiILQyG5aeuyKFbdsI1fmQy1Cmf7dQ8eGmVuJoaRVdwey7WaMknr2ZFeVSYSKT0rExsa8EGw0aoI/1QQ==}
955 | dependencies:
956 | '@jridgewell/sourcemap-codec': 1.4.15
957 | '@types/estree': 1.0.1
958 | acorn: 8.10.0
959 | estree-walker: 3.0.3
960 | periscopic: 3.1.0
961 | dev: true
962 |
963 | /color-convert@1.9.3:
964 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
965 | dependencies:
966 | color-name: 1.1.3
967 | dev: true
968 |
969 | /color-convert@2.0.1:
970 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
971 | engines: {node: '>=7.0.0'}
972 | dependencies:
973 | color-name: 1.1.4
974 | dev: true
975 |
976 | /color-name@1.1.3:
977 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
978 | dev: true
979 |
980 | /color-name@1.1.4:
981 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
982 | dev: true
983 |
984 | /concat-map@0.0.1:
985 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
986 | dev: true
987 |
988 | /convert-source-map@1.9.0:
989 | resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
990 | dev: true
991 |
992 | /cookie@0.5.0:
993 | resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
994 | engines: {node: '>= 0.6'}
995 | dev: true
996 |
997 | /cross-spawn@6.0.5:
998 | resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==}
999 | engines: {node: '>=4.8'}
1000 | dependencies:
1001 | nice-try: 1.0.5
1002 | path-key: 2.0.1
1003 | semver: 5.7.1
1004 | shebang-command: 1.2.0
1005 | which: 1.3.1
1006 | dev: true
1007 |
1008 | /cross-spawn@7.0.3:
1009 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
1010 | engines: {node: '>= 8'}
1011 | dependencies:
1012 | path-key: 3.1.1
1013 | shebang-command: 2.0.0
1014 | which: 2.0.2
1015 | dev: true
1016 |
1017 | /css-tree@2.3.1:
1018 | resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
1019 | engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
1020 | dependencies:
1021 | mdn-data: 2.0.30
1022 | source-map-js: 1.0.2
1023 | dev: true
1024 |
1025 | /cssesc@3.0.0:
1026 | resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
1027 | engines: {node: '>=4'}
1028 | hasBin: true
1029 | dev: true
1030 |
1031 | /debug@4.3.4:
1032 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
1033 | engines: {node: '>=6.0'}
1034 | peerDependencies:
1035 | supports-color: '*'
1036 | peerDependenciesMeta:
1037 | supports-color:
1038 | optional: true
1039 | dependencies:
1040 | ms: 2.1.2
1041 | dev: true
1042 |
1043 | /dedent-js@1.0.1:
1044 | resolution: {integrity: sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==}
1045 | dev: true
1046 |
1047 | /deep-eql@4.1.3:
1048 | resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
1049 | engines: {node: '>=6'}
1050 | dependencies:
1051 | type-detect: 4.0.8
1052 | dev: true
1053 |
1054 | /deep-is@0.1.4:
1055 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
1056 | dev: true
1057 |
1058 | /deepmerge@4.3.1:
1059 | resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
1060 | engines: {node: '>=0.10.0'}
1061 | dev: true
1062 |
1063 | /define-properties@1.2.0:
1064 | resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==}
1065 | engines: {node: '>= 0.4'}
1066 | dependencies:
1067 | has-property-descriptors: 1.0.0
1068 | object-keys: 1.1.1
1069 | dev: true
1070 |
1071 | /dequal@2.0.3:
1072 | resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
1073 | engines: {node: '>=6'}
1074 | dev: true
1075 |
1076 | /detect-indent@6.1.0:
1077 | resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
1078 | engines: {node: '>=8'}
1079 | dev: true
1080 |
1081 | /devalue@4.3.2:
1082 | resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==}
1083 | dev: true
1084 |
1085 | /diff-sequences@29.4.3:
1086 | resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==}
1087 | engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
1088 | dev: true
1089 |
1090 | /dir-glob@3.0.1:
1091 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
1092 | engines: {node: '>=8'}
1093 | dependencies:
1094 | path-type: 4.0.0
1095 | dev: true
1096 |
1097 | /doctrine@3.0.0:
1098 | resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
1099 | engines: {node: '>=6.0.0'}
1100 | dependencies:
1101 | esutils: 2.0.3
1102 | dev: true
1103 |
1104 | /error-ex@1.3.2:
1105 | resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
1106 | dependencies:
1107 | is-arrayish: 0.2.1
1108 | dev: true
1109 |
1110 | /es-abstract@1.21.2:
1111 | resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==}
1112 | engines: {node: '>= 0.4'}
1113 | dependencies:
1114 | array-buffer-byte-length: 1.0.0
1115 | available-typed-arrays: 1.0.5
1116 | call-bind: 1.0.2
1117 | es-set-tostringtag: 2.0.1
1118 | es-to-primitive: 1.2.1
1119 | function.prototype.name: 1.1.5
1120 | get-intrinsic: 1.2.1
1121 | get-symbol-description: 1.0.0
1122 | globalthis: 1.0.3
1123 | gopd: 1.0.1
1124 | has: 1.0.3
1125 | has-property-descriptors: 1.0.0
1126 | has-proto: 1.0.1
1127 | has-symbols: 1.0.3
1128 | internal-slot: 1.0.5
1129 | is-array-buffer: 3.0.2
1130 | is-callable: 1.2.7
1131 | is-negative-zero: 2.0.2
1132 | is-regex: 1.1.4
1133 | is-shared-array-buffer: 1.0.2
1134 | is-string: 1.0.7
1135 | is-typed-array: 1.1.10
1136 | is-weakref: 1.0.2
1137 | object-inspect: 1.12.3
1138 | object-keys: 1.1.1
1139 | object.assign: 4.1.4
1140 | regexp.prototype.flags: 1.5.0
1141 | safe-regex-test: 1.0.0
1142 | string.prototype.trim: 1.2.7
1143 | string.prototype.trimend: 1.0.6
1144 | string.prototype.trimstart: 1.0.6
1145 | typed-array-length: 1.0.4
1146 | unbox-primitive: 1.0.2
1147 | which-typed-array: 1.1.9
1148 | dev: true
1149 |
1150 | /es-set-tostringtag@2.0.1:
1151 | resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==}
1152 | engines: {node: '>= 0.4'}
1153 | dependencies:
1154 | get-intrinsic: 1.2.1
1155 | has: 1.0.3
1156 | has-tostringtag: 1.0.0
1157 | dev: true
1158 |
1159 | /es-to-primitive@1.2.1:
1160 | resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
1161 | engines: {node: '>= 0.4'}
1162 | dependencies:
1163 | is-callable: 1.2.7
1164 | is-date-object: 1.0.5
1165 | is-symbol: 1.0.4
1166 | dev: true
1167 |
1168 | /es6-promise@3.3.1:
1169 | resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==}
1170 | dev: true
1171 |
1172 | /esbuild@0.18.11:
1173 | resolution: {integrity: sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==}
1174 | engines: {node: '>=12'}
1175 | hasBin: true
1176 | requiresBuild: true
1177 | optionalDependencies:
1178 | '@esbuild/android-arm': 0.18.11
1179 | '@esbuild/android-arm64': 0.18.11
1180 | '@esbuild/android-x64': 0.18.11
1181 | '@esbuild/darwin-arm64': 0.18.11
1182 | '@esbuild/darwin-x64': 0.18.11
1183 | '@esbuild/freebsd-arm64': 0.18.11
1184 | '@esbuild/freebsd-x64': 0.18.11
1185 | '@esbuild/linux-arm': 0.18.11
1186 | '@esbuild/linux-arm64': 0.18.11
1187 | '@esbuild/linux-ia32': 0.18.11
1188 | '@esbuild/linux-loong64': 0.18.11
1189 | '@esbuild/linux-mips64el': 0.18.11
1190 | '@esbuild/linux-ppc64': 0.18.11
1191 | '@esbuild/linux-riscv64': 0.18.11
1192 | '@esbuild/linux-s390x': 0.18.11
1193 | '@esbuild/linux-x64': 0.18.11
1194 | '@esbuild/netbsd-x64': 0.18.11
1195 | '@esbuild/openbsd-x64': 0.18.11
1196 | '@esbuild/sunos-x64': 0.18.11
1197 | '@esbuild/win32-arm64': 0.18.11
1198 | '@esbuild/win32-ia32': 0.18.11
1199 | '@esbuild/win32-x64': 0.18.11
1200 | dev: true
1201 |
1202 | /escape-string-regexp@1.0.5:
1203 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
1204 | engines: {node: '>=0.8.0'}
1205 | dev: true
1206 |
1207 | /escape-string-regexp@4.0.0:
1208 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
1209 | engines: {node: '>=10'}
1210 | dev: true
1211 |
1212 | /eslint-config-prettier@8.8.0(eslint@8.44.0):
1213 | resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==}
1214 | hasBin: true
1215 | peerDependencies:
1216 | eslint: '>=7.0.0'
1217 | dependencies:
1218 | eslint: 8.44.0
1219 | dev: true
1220 |
1221 | /eslint-plugin-svelte@2.32.2(eslint@8.44.0)(svelte@4.0.5):
1222 | resolution: {integrity: sha512-Jgbop2fNZsoxxkklZAIbDNhwAPynvnCtUXLsEC6O2qax7N/pfe2cNqT0ZoBbubXKJitQQDEyVDQ1rZs4ZWcrTA==}
1223 | engines: {node: ^14.17.0 || >=16.0.0}
1224 | peerDependencies:
1225 | eslint: ^7.0.0 || ^8.0.0-0
1226 | svelte: ^3.37.0 || ^4.0.0
1227 | peerDependenciesMeta:
1228 | svelte:
1229 | optional: true
1230 | dependencies:
1231 | '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0)
1232 | '@jridgewell/sourcemap-codec': 1.4.15
1233 | debug: 4.3.4
1234 | eslint: 8.44.0
1235 | esutils: 2.0.3
1236 | known-css-properties: 0.27.0
1237 | postcss: 8.4.25
1238 | postcss-load-config: 3.1.4(postcss@8.4.25)
1239 | postcss-safe-parser: 6.0.0(postcss@8.4.25)
1240 | postcss-selector-parser: 6.0.13
1241 | semver: 7.5.4
1242 | svelte: 4.0.5
1243 | svelte-eslint-parser: 0.32.1(svelte@4.0.5)
1244 | transitivePeerDependencies:
1245 | - supports-color
1246 | - ts-node
1247 | dev: true
1248 |
1249 | /eslint-scope@5.1.1:
1250 | resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
1251 | engines: {node: '>=8.0.0'}
1252 | dependencies:
1253 | esrecurse: 4.3.0
1254 | estraverse: 4.3.0
1255 | dev: true
1256 |
1257 | /eslint-scope@7.2.0:
1258 | resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==}
1259 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
1260 | dependencies:
1261 | esrecurse: 4.3.0
1262 | estraverse: 5.3.0
1263 | dev: true
1264 |
1265 | /eslint-visitor-keys@3.4.1:
1266 | resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==}
1267 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
1268 | dev: true
1269 |
1270 | /eslint@8.44.0:
1271 | resolution: {integrity: sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==}
1272 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
1273 | hasBin: true
1274 | dependencies:
1275 | '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0)
1276 | '@eslint-community/regexpp': 4.5.1
1277 | '@eslint/eslintrc': 2.1.0
1278 | '@eslint/js': 8.44.0
1279 | '@humanwhocodes/config-array': 0.11.10
1280 | '@humanwhocodes/module-importer': 1.0.1
1281 | '@nodelib/fs.walk': 1.2.8
1282 | ajv: 6.12.6
1283 | chalk: 4.1.2
1284 | cross-spawn: 7.0.3
1285 | debug: 4.3.4
1286 | doctrine: 3.0.0
1287 | escape-string-regexp: 4.0.0
1288 | eslint-scope: 7.2.0
1289 | eslint-visitor-keys: 3.4.1
1290 | espree: 9.6.0
1291 | esquery: 1.5.0
1292 | esutils: 2.0.3
1293 | fast-deep-equal: 3.1.3
1294 | file-entry-cache: 6.0.1
1295 | find-up: 5.0.0
1296 | glob-parent: 6.0.2
1297 | globals: 13.20.0
1298 | graphemer: 1.4.0
1299 | ignore: 5.2.4
1300 | import-fresh: 3.3.0
1301 | imurmurhash: 0.1.4
1302 | is-glob: 4.0.3
1303 | is-path-inside: 3.0.3
1304 | js-yaml: 4.1.0
1305 | json-stable-stringify-without-jsonify: 1.0.1
1306 | levn: 0.4.1
1307 | lodash.merge: 4.6.2
1308 | minimatch: 3.1.2
1309 | natural-compare: 1.4.0
1310 | optionator: 0.9.3
1311 | strip-ansi: 6.0.1
1312 | strip-json-comments: 3.1.1
1313 | text-table: 0.2.0
1314 | transitivePeerDependencies:
1315 | - supports-color
1316 | dev: true
1317 |
1318 | /esm-env@1.0.0:
1319 | resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==}
1320 | dev: true
1321 |
1322 | /espree@9.6.0:
1323 | resolution: {integrity: sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==}
1324 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
1325 | dependencies:
1326 | acorn: 8.10.0
1327 | acorn-jsx: 5.3.2(acorn@8.10.0)
1328 | eslint-visitor-keys: 3.4.1
1329 | dev: true
1330 |
1331 | /esquery@1.5.0:
1332 | resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
1333 | engines: {node: '>=0.10'}
1334 | dependencies:
1335 | estraverse: 5.3.0
1336 | dev: true
1337 |
1338 | /esrecurse@4.3.0:
1339 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
1340 | engines: {node: '>=4.0'}
1341 | dependencies:
1342 | estraverse: 5.3.0
1343 | dev: true
1344 |
1345 | /estraverse@4.3.0:
1346 | resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
1347 | engines: {node: '>=4.0'}
1348 | dev: true
1349 |
1350 | /estraverse@5.3.0:
1351 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
1352 | engines: {node: '>=4.0'}
1353 | dev: true
1354 |
1355 | /estree-walker@3.0.3:
1356 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
1357 | dependencies:
1358 | '@types/estree': 1.0.1
1359 | dev: true
1360 |
1361 | /esutils@2.0.3:
1362 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
1363 | engines: {node: '>=0.10.0'}
1364 | dev: true
1365 |
1366 | /fast-deep-equal@3.1.3:
1367 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
1368 | dev: true
1369 |
1370 | /fast-glob@3.3.0:
1371 | resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==}
1372 | engines: {node: '>=8.6.0'}
1373 | dependencies:
1374 | '@nodelib/fs.stat': 2.0.5
1375 | '@nodelib/fs.walk': 1.2.8
1376 | glob-parent: 5.1.2
1377 | merge2: 1.4.1
1378 | micromatch: 4.0.5
1379 | dev: true
1380 |
1381 | /fast-json-stable-stringify@2.1.0:
1382 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
1383 | dev: true
1384 |
1385 | /fast-levenshtein@2.0.6:
1386 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
1387 | dev: true
1388 |
1389 | /fastq@1.15.0:
1390 | resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
1391 | dependencies:
1392 | reusify: 1.0.4
1393 | dev: true
1394 |
1395 | /file-entry-cache@6.0.1:
1396 | resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
1397 | engines: {node: ^10.12.0 || >=12.0.0}
1398 | dependencies:
1399 | flat-cache: 3.0.4
1400 | dev: true
1401 |
1402 | /fill-range@7.0.1:
1403 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
1404 | engines: {node: '>=8'}
1405 | dependencies:
1406 | to-regex-range: 5.0.1
1407 | dev: true
1408 |
1409 | /find-up@5.0.0:
1410 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
1411 | engines: {node: '>=10'}
1412 | dependencies:
1413 | locate-path: 6.0.0
1414 | path-exists: 4.0.0
1415 | dev: true
1416 |
1417 | /flat-cache@3.0.4:
1418 | resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==}
1419 | engines: {node: ^10.12.0 || >=12.0.0}
1420 | dependencies:
1421 | flatted: 3.2.7
1422 | rimraf: 3.0.2
1423 | dev: true
1424 |
1425 | /flatted@3.2.7:
1426 | resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
1427 | dev: true
1428 |
1429 | /for-each@0.3.3:
1430 | resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
1431 | dependencies:
1432 | is-callable: 1.2.7
1433 | dev: true
1434 |
1435 | /fs.realpath@1.0.0:
1436 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
1437 | dev: true
1438 |
1439 | /fsevents@2.3.2:
1440 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
1441 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
1442 | os: [darwin]
1443 | requiresBuild: true
1444 | dev: true
1445 | optional: true
1446 |
1447 | /function-bind@1.1.1:
1448 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
1449 | dev: true
1450 |
1451 | /function.prototype.name@1.1.5:
1452 | resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==}
1453 | engines: {node: '>= 0.4'}
1454 | dependencies:
1455 | call-bind: 1.0.2
1456 | define-properties: 1.2.0
1457 | es-abstract: 1.21.2
1458 | functions-have-names: 1.2.3
1459 | dev: true
1460 |
1461 | /functions-have-names@1.2.3:
1462 | resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
1463 | dev: true
1464 |
1465 | /get-func-name@2.0.0:
1466 | resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
1467 | dev: true
1468 |
1469 | /get-intrinsic@1.2.1:
1470 | resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==}
1471 | dependencies:
1472 | function-bind: 1.1.1
1473 | has: 1.0.3
1474 | has-proto: 1.0.1
1475 | has-symbols: 1.0.3
1476 | dev: true
1477 |
1478 | /get-symbol-description@1.0.0:
1479 | resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
1480 | engines: {node: '>= 0.4'}
1481 | dependencies:
1482 | call-bind: 1.0.2
1483 | get-intrinsic: 1.2.1
1484 | dev: true
1485 |
1486 | /glob-parent@5.1.2:
1487 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
1488 | engines: {node: '>= 6'}
1489 | dependencies:
1490 | is-glob: 4.0.3
1491 | dev: true
1492 |
1493 | /glob-parent@6.0.2:
1494 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
1495 | engines: {node: '>=10.13.0'}
1496 | dependencies:
1497 | is-glob: 4.0.3
1498 | dev: true
1499 |
1500 | /glob@7.2.3:
1501 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
1502 | dependencies:
1503 | fs.realpath: 1.0.0
1504 | inflight: 1.0.6
1505 | inherits: 2.0.4
1506 | minimatch: 3.1.2
1507 | once: 1.4.0
1508 | path-is-absolute: 1.0.1
1509 | dev: true
1510 |
1511 | /glob@8.1.0:
1512 | resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
1513 | engines: {node: '>=12'}
1514 | dependencies:
1515 | fs.realpath: 1.0.0
1516 | inflight: 1.0.6
1517 | inherits: 2.0.4
1518 | minimatch: 5.1.6
1519 | once: 1.4.0
1520 | dev: true
1521 |
1522 | /globals@13.20.0:
1523 | resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==}
1524 | engines: {node: '>=8'}
1525 | dependencies:
1526 | type-fest: 0.20.2
1527 | dev: true
1528 |
1529 | /globalthis@1.0.3:
1530 | resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
1531 | engines: {node: '>= 0.4'}
1532 | dependencies:
1533 | define-properties: 1.2.0
1534 | dev: true
1535 |
1536 | /globby@11.1.0:
1537 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
1538 | engines: {node: '>=10'}
1539 | dependencies:
1540 | array-union: 2.1.0
1541 | dir-glob: 3.0.1
1542 | fast-glob: 3.3.0
1543 | ignore: 5.2.4
1544 | merge2: 1.4.1
1545 | slash: 3.0.0
1546 | dev: true
1547 |
1548 | /gopd@1.0.1:
1549 | resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
1550 | dependencies:
1551 | get-intrinsic: 1.2.1
1552 | dev: true
1553 |
1554 | /graceful-fs@4.2.11:
1555 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
1556 | dev: true
1557 |
1558 | /graphemer@1.4.0:
1559 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
1560 | dev: true
1561 |
1562 | /has-bigints@1.0.2:
1563 | resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
1564 | dev: true
1565 |
1566 | /has-flag@3.0.0:
1567 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
1568 | engines: {node: '>=4'}
1569 | dev: true
1570 |
1571 | /has-flag@4.0.0:
1572 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
1573 | engines: {node: '>=8'}
1574 | dev: true
1575 |
1576 | /has-property-descriptors@1.0.0:
1577 | resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==}
1578 | dependencies:
1579 | get-intrinsic: 1.2.1
1580 | dev: true
1581 |
1582 | /has-proto@1.0.1:
1583 | resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
1584 | engines: {node: '>= 0.4'}
1585 | dev: true
1586 |
1587 | /has-symbols@1.0.3:
1588 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
1589 | engines: {node: '>= 0.4'}
1590 | dev: true
1591 |
1592 | /has-tostringtag@1.0.0:
1593 | resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
1594 | engines: {node: '>= 0.4'}
1595 | dependencies:
1596 | has-symbols: 1.0.3
1597 | dev: true
1598 |
1599 | /has@1.0.3:
1600 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
1601 | engines: {node: '>= 0.4.0'}
1602 | dependencies:
1603 | function-bind: 1.1.1
1604 | dev: true
1605 |
1606 | /hosted-git-info@2.8.9:
1607 | resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
1608 | dev: true
1609 |
1610 | /html-escaper@2.0.2:
1611 | resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
1612 | dev: true
1613 |
1614 | /ignore-walk@5.0.1:
1615 | resolution: {integrity: sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==}
1616 | engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
1617 | dependencies:
1618 | minimatch: 5.1.6
1619 | dev: true
1620 |
1621 | /ignore@5.2.4:
1622 | resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
1623 | engines: {node: '>= 4'}
1624 | dev: true
1625 |
1626 | /immutable@4.3.0:
1627 | resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==}
1628 | dev: true
1629 |
1630 | /import-fresh@3.3.0:
1631 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
1632 | engines: {node: '>=6'}
1633 | dependencies:
1634 | parent-module: 1.0.1
1635 | resolve-from: 4.0.0
1636 | dev: true
1637 |
1638 | /import-meta-resolve@3.0.0:
1639 | resolution: {integrity: sha512-4IwhLhNNA8yy445rPjD/lWh++7hMDOml2eHtd58eG7h+qK3EryMuuRbsHGPikCoAgIkkDnckKfWSk2iDla/ejg==}
1640 | dev: true
1641 |
1642 | /imurmurhash@0.1.4:
1643 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
1644 | engines: {node: '>=0.8.19'}
1645 | dev: true
1646 |
1647 | /inflight@1.0.6:
1648 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
1649 | dependencies:
1650 | once: 1.4.0
1651 | wrappy: 1.0.2
1652 | dev: true
1653 |
1654 | /inherits@2.0.4:
1655 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
1656 | dev: true
1657 |
1658 | /internal-slot@1.0.5:
1659 | resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
1660 | engines: {node: '>= 0.4'}
1661 | dependencies:
1662 | get-intrinsic: 1.2.1
1663 | has: 1.0.3
1664 | side-channel: 1.0.4
1665 | dev: true
1666 |
1667 | /is-array-buffer@3.0.2:
1668 | resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
1669 | dependencies:
1670 | call-bind: 1.0.2
1671 | get-intrinsic: 1.2.1
1672 | is-typed-array: 1.1.10
1673 | dev: true
1674 |
1675 | /is-arrayish@0.2.1:
1676 | resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
1677 | dev: true
1678 |
1679 | /is-bigint@1.0.4:
1680 | resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
1681 | dependencies:
1682 | has-bigints: 1.0.2
1683 | dev: true
1684 |
1685 | /is-binary-path@2.1.0:
1686 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
1687 | engines: {node: '>=8'}
1688 | dependencies:
1689 | binary-extensions: 2.2.0
1690 | dev: true
1691 |
1692 | /is-boolean-object@1.1.2:
1693 | resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
1694 | engines: {node: '>= 0.4'}
1695 | dependencies:
1696 | call-bind: 1.0.2
1697 | has-tostringtag: 1.0.0
1698 | dev: true
1699 |
1700 | /is-callable@1.2.7:
1701 | resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
1702 | engines: {node: '>= 0.4'}
1703 | dev: true
1704 |
1705 | /is-core-module@2.12.1:
1706 | resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==}
1707 | dependencies:
1708 | has: 1.0.3
1709 | dev: true
1710 |
1711 | /is-date-object@1.0.5:
1712 | resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
1713 | engines: {node: '>= 0.4'}
1714 | dependencies:
1715 | has-tostringtag: 1.0.0
1716 | dev: true
1717 |
1718 | /is-extglob@2.1.1:
1719 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
1720 | engines: {node: '>=0.10.0'}
1721 | dev: true
1722 |
1723 | /is-glob@4.0.3:
1724 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
1725 | engines: {node: '>=0.10.0'}
1726 | dependencies:
1727 | is-extglob: 2.1.1
1728 | dev: true
1729 |
1730 | /is-negative-zero@2.0.2:
1731 | resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
1732 | engines: {node: '>= 0.4'}
1733 | dev: true
1734 |
1735 | /is-number-object@1.0.7:
1736 | resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
1737 | engines: {node: '>= 0.4'}
1738 | dependencies:
1739 | has-tostringtag: 1.0.0
1740 | dev: true
1741 |
1742 | /is-number@7.0.0:
1743 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
1744 | engines: {node: '>=0.12.0'}
1745 | dev: true
1746 |
1747 | /is-path-inside@3.0.3:
1748 | resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
1749 | engines: {node: '>=8'}
1750 | dev: true
1751 |
1752 | /is-reference@3.0.1:
1753 | resolution: {integrity: sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==}
1754 | dependencies:
1755 | '@types/estree': 1.0.1
1756 | dev: true
1757 |
1758 | /is-regex@1.1.4:
1759 | resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
1760 | engines: {node: '>= 0.4'}
1761 | dependencies:
1762 | call-bind: 1.0.2
1763 | has-tostringtag: 1.0.0
1764 | dev: true
1765 |
1766 | /is-shared-array-buffer@1.0.2:
1767 | resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
1768 | dependencies:
1769 | call-bind: 1.0.2
1770 | dev: true
1771 |
1772 | /is-string@1.0.7:
1773 | resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
1774 | engines: {node: '>= 0.4'}
1775 | dependencies:
1776 | has-tostringtag: 1.0.0
1777 | dev: true
1778 |
1779 | /is-symbol@1.0.4:
1780 | resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
1781 | engines: {node: '>= 0.4'}
1782 | dependencies:
1783 | has-symbols: 1.0.3
1784 | dev: true
1785 |
1786 | /is-typed-array@1.1.10:
1787 | resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==}
1788 | engines: {node: '>= 0.4'}
1789 | dependencies:
1790 | available-typed-arrays: 1.0.5
1791 | call-bind: 1.0.2
1792 | for-each: 0.3.3
1793 | gopd: 1.0.1
1794 | has-tostringtag: 1.0.0
1795 | dev: true
1796 |
1797 | /is-weakref@1.0.2:
1798 | resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
1799 | dependencies:
1800 | call-bind: 1.0.2
1801 | dev: true
1802 |
1803 | /isexe@2.0.0:
1804 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
1805 | dev: true
1806 |
1807 | /istanbul-lib-coverage@3.2.0:
1808 | resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==}
1809 | engines: {node: '>=8'}
1810 | dev: true
1811 |
1812 | /istanbul-lib-report@3.0.0:
1813 | resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==}
1814 | engines: {node: '>=8'}
1815 | dependencies:
1816 | istanbul-lib-coverage: 3.2.0
1817 | make-dir: 3.1.0
1818 | supports-color: 7.2.0
1819 | dev: true
1820 |
1821 | /istanbul-lib-source-maps@4.0.1:
1822 | resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==}
1823 | engines: {node: '>=10'}
1824 | dependencies:
1825 | debug: 4.3.4
1826 | istanbul-lib-coverage: 3.2.0
1827 | source-map: 0.6.1
1828 | transitivePeerDependencies:
1829 | - supports-color
1830 | dev: true
1831 |
1832 | /istanbul-reports@3.1.5:
1833 | resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==}
1834 | engines: {node: '>=8'}
1835 | dependencies:
1836 | html-escaper: 2.0.2
1837 | istanbul-lib-report: 3.0.0
1838 | dev: true
1839 |
1840 | /js-yaml@4.1.0:
1841 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
1842 | hasBin: true
1843 | dependencies:
1844 | argparse: 2.0.1
1845 | dev: true
1846 |
1847 | /json-parse-better-errors@1.0.2:
1848 | resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==}
1849 | dev: true
1850 |
1851 | /json-schema-traverse@0.4.1:
1852 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
1853 | dev: true
1854 |
1855 | /json-stable-stringify-without-jsonify@1.0.1:
1856 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
1857 | dev: true
1858 |
1859 | /jsonc-parser@3.2.0:
1860 | resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
1861 | dev: true
1862 |
1863 | /kleur@4.1.5:
1864 | resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
1865 | engines: {node: '>=6'}
1866 | dev: true
1867 |
1868 | /known-css-properties@0.27.0:
1869 | resolution: {integrity: sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==}
1870 | dev: true
1871 |
1872 | /levn@0.4.1:
1873 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
1874 | engines: {node: '>= 0.8.0'}
1875 | dependencies:
1876 | prelude-ls: 1.2.1
1877 | type-check: 0.4.0
1878 | dev: true
1879 |
1880 | /lilconfig@2.1.0:
1881 | resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
1882 | engines: {node: '>=10'}
1883 | dev: true
1884 |
1885 | /load-json-file@4.0.0:
1886 | resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==}
1887 | engines: {node: '>=4'}
1888 | dependencies:
1889 | graceful-fs: 4.2.11
1890 | parse-json: 4.0.0
1891 | pify: 3.0.0
1892 | strip-bom: 3.0.0
1893 | dev: true
1894 |
1895 | /local-pkg@0.4.3:
1896 | resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
1897 | engines: {node: '>=14'}
1898 | dev: true
1899 |
1900 | /locate-character@3.0.0:
1901 | resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
1902 | dev: true
1903 |
1904 | /locate-path@6.0.0:
1905 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
1906 | engines: {node: '>=10'}
1907 | dependencies:
1908 | p-locate: 5.0.0
1909 | dev: true
1910 |
1911 | /lodash.merge@4.6.2:
1912 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
1913 | dev: true
1914 |
1915 | /loupe@2.3.6:
1916 | resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
1917 | dependencies:
1918 | get-func-name: 2.0.0
1919 | dev: true
1920 |
1921 | /lower-case@2.0.2:
1922 | resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
1923 | dependencies:
1924 | tslib: 2.6.0
1925 | dev: true
1926 |
1927 | /lru-cache@6.0.0:
1928 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
1929 | engines: {node: '>=10'}
1930 | dependencies:
1931 | yallist: 4.0.0
1932 | dev: true
1933 |
1934 | /magic-string@0.27.0:
1935 | resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
1936 | engines: {node: '>=12'}
1937 | dependencies:
1938 | '@jridgewell/sourcemap-codec': 1.4.15
1939 | dev: true
1940 |
1941 | /magic-string@0.30.1:
1942 | resolution: {integrity: sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==}
1943 | engines: {node: '>=12'}
1944 | dependencies:
1945 | '@jridgewell/sourcemap-codec': 1.4.15
1946 | dev: true
1947 |
1948 | /make-dir@3.1.0:
1949 | resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
1950 | engines: {node: '>=8'}
1951 | dependencies:
1952 | semver: 6.3.0
1953 | dev: true
1954 |
1955 | /mdn-data@2.0.30:
1956 | resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
1957 | dev: true
1958 |
1959 | /memorystream@0.3.1:
1960 | resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==}
1961 | engines: {node: '>= 0.10.0'}
1962 | dev: true
1963 |
1964 | /merge2@1.4.1:
1965 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
1966 | engines: {node: '>= 8'}
1967 | dev: true
1968 |
1969 | /micromatch@4.0.5:
1970 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
1971 | engines: {node: '>=8.6'}
1972 | dependencies:
1973 | braces: 3.0.2
1974 | picomatch: 2.3.1
1975 | dev: true
1976 |
1977 | /mime@3.0.0:
1978 | resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
1979 | engines: {node: '>=10.0.0'}
1980 | hasBin: true
1981 | dev: true
1982 |
1983 | /min-indent@1.0.1:
1984 | resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
1985 | engines: {node: '>=4'}
1986 | dev: true
1987 |
1988 | /minimatch@3.1.2:
1989 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
1990 | dependencies:
1991 | brace-expansion: 1.1.11
1992 | dev: true
1993 |
1994 | /minimatch@5.1.6:
1995 | resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
1996 | engines: {node: '>=10'}
1997 | dependencies:
1998 | brace-expansion: 2.0.1
1999 | dev: true
2000 |
2001 | /minimist@1.2.8:
2002 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
2003 | dev: true
2004 |
2005 | /mkdirp@0.5.6:
2006 | resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
2007 | hasBin: true
2008 | dependencies:
2009 | minimist: 1.2.8
2010 | dev: true
2011 |
2012 | /mlly@1.4.0:
2013 | resolution: {integrity: sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==}
2014 | dependencies:
2015 | acorn: 8.10.0
2016 | pathe: 1.1.1
2017 | pkg-types: 1.0.3
2018 | ufo: 1.1.2
2019 | dev: true
2020 |
2021 | /mri@1.2.0:
2022 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
2023 | engines: {node: '>=4'}
2024 | dev: true
2025 |
2026 | /mrmime@1.0.1:
2027 | resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==}
2028 | engines: {node: '>=10'}
2029 | dev: true
2030 |
2031 | /ms@2.1.2:
2032 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
2033 | dev: true
2034 |
2035 | /nanoid@3.3.6:
2036 | resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
2037 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
2038 | hasBin: true
2039 | dev: true
2040 |
2041 | /natural-compare-lite@1.4.0:
2042 | resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
2043 | dev: true
2044 |
2045 | /natural-compare@1.4.0:
2046 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
2047 | dev: true
2048 |
2049 | /nice-try@1.0.5:
2050 | resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
2051 | dev: true
2052 |
2053 | /no-case@3.0.4:
2054 | resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
2055 | dependencies:
2056 | lower-case: 2.0.2
2057 | tslib: 2.6.0
2058 | dev: true
2059 |
2060 | /normalize-package-data@2.5.0:
2061 | resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
2062 | dependencies:
2063 | hosted-git-info: 2.8.9
2064 | resolve: 1.22.2
2065 | semver: 5.7.1
2066 | validate-npm-package-license: 3.0.4
2067 | dev: true
2068 |
2069 | /normalize-path@3.0.0:
2070 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
2071 | engines: {node: '>=0.10.0'}
2072 | dev: true
2073 |
2074 | /npm-bundled@2.0.1:
2075 | resolution: {integrity: sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==}
2076 | engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
2077 | dependencies:
2078 | npm-normalize-package-bin: 2.0.0
2079 | dev: true
2080 |
2081 | /npm-normalize-package-bin@2.0.0:
2082 | resolution: {integrity: sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==}
2083 | engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
2084 | dev: true
2085 |
2086 | /npm-packlist@5.1.3:
2087 | resolution: {integrity: sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==}
2088 | engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
2089 | hasBin: true
2090 | dependencies:
2091 | glob: 8.1.0
2092 | ignore-walk: 5.0.1
2093 | npm-bundled: 2.0.1
2094 | npm-normalize-package-bin: 2.0.0
2095 | dev: true
2096 |
2097 | /npm-run-all@4.1.5:
2098 | resolution: {integrity: sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==}
2099 | engines: {node: '>= 4'}
2100 | hasBin: true
2101 | dependencies:
2102 | ansi-styles: 3.2.1
2103 | chalk: 2.4.2
2104 | cross-spawn: 6.0.5
2105 | memorystream: 0.3.1
2106 | minimatch: 3.1.2
2107 | pidtree: 0.3.1
2108 | read-pkg: 3.0.0
2109 | shell-quote: 1.8.1
2110 | string.prototype.padend: 3.1.4
2111 | dev: true
2112 |
2113 | /object-inspect@1.12.3:
2114 | resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
2115 | dev: true
2116 |
2117 | /object-keys@1.1.1:
2118 | resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
2119 | engines: {node: '>= 0.4'}
2120 | dev: true
2121 |
2122 | /object.assign@4.1.4:
2123 | resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==}
2124 | engines: {node: '>= 0.4'}
2125 | dependencies:
2126 | call-bind: 1.0.2
2127 | define-properties: 1.2.0
2128 | has-symbols: 1.0.3
2129 | object-keys: 1.1.1
2130 | dev: true
2131 |
2132 | /once@1.4.0:
2133 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
2134 | dependencies:
2135 | wrappy: 1.0.2
2136 | dev: true
2137 |
2138 | /optionator@0.9.3:
2139 | resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
2140 | engines: {node: '>= 0.8.0'}
2141 | dependencies:
2142 | '@aashutoshrathi/word-wrap': 1.2.6
2143 | deep-is: 0.1.4
2144 | fast-levenshtein: 2.0.6
2145 | levn: 0.4.1
2146 | prelude-ls: 1.2.1
2147 | type-check: 0.4.0
2148 | dev: true
2149 |
2150 | /p-limit@3.1.0:
2151 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
2152 | engines: {node: '>=10'}
2153 | dependencies:
2154 | yocto-queue: 0.1.0
2155 | dev: true
2156 |
2157 | /p-limit@4.0.0:
2158 | resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
2159 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
2160 | dependencies:
2161 | yocto-queue: 1.0.0
2162 | dev: true
2163 |
2164 | /p-locate@5.0.0:
2165 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
2166 | engines: {node: '>=10'}
2167 | dependencies:
2168 | p-limit: 3.1.0
2169 | dev: true
2170 |
2171 | /parent-module@1.0.1:
2172 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
2173 | engines: {node: '>=6'}
2174 | dependencies:
2175 | callsites: 3.1.0
2176 | dev: true
2177 |
2178 | /parse-json@4.0.0:
2179 | resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==}
2180 | engines: {node: '>=4'}
2181 | dependencies:
2182 | error-ex: 1.3.2
2183 | json-parse-better-errors: 1.0.2
2184 | dev: true
2185 |
2186 | /pascal-case@3.1.2:
2187 | resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==}
2188 | dependencies:
2189 | no-case: 3.0.4
2190 | tslib: 2.6.0
2191 | dev: true
2192 |
2193 | /path-exists@4.0.0:
2194 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
2195 | engines: {node: '>=8'}
2196 | dev: true
2197 |
2198 | /path-is-absolute@1.0.1:
2199 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
2200 | engines: {node: '>=0.10.0'}
2201 | dev: true
2202 |
2203 | /path-key@2.0.1:
2204 | resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==}
2205 | engines: {node: '>=4'}
2206 | dev: true
2207 |
2208 | /path-key@3.1.1:
2209 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
2210 | engines: {node: '>=8'}
2211 | dev: true
2212 |
2213 | /path-parse@1.0.7:
2214 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
2215 | dev: true
2216 |
2217 | /path-type@3.0.0:
2218 | resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==}
2219 | engines: {node: '>=4'}
2220 | dependencies:
2221 | pify: 3.0.0
2222 | dev: true
2223 |
2224 | /path-type@4.0.0:
2225 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
2226 | engines: {node: '>=8'}
2227 | dev: true
2228 |
2229 | /pathe@1.1.1:
2230 | resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==}
2231 | dev: true
2232 |
2233 | /pathval@1.1.1:
2234 | resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
2235 | dev: true
2236 |
2237 | /periscopic@3.1.0:
2238 | resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
2239 | dependencies:
2240 | '@types/estree': 1.0.1
2241 | estree-walker: 3.0.3
2242 | is-reference: 3.0.1
2243 | dev: true
2244 |
2245 | /picocolors@1.0.0:
2246 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
2247 | dev: true
2248 |
2249 | /picomatch@2.3.1:
2250 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
2251 | engines: {node: '>=8.6'}
2252 | dev: true
2253 |
2254 | /pidtree@0.3.1:
2255 | resolution: {integrity: sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==}
2256 | engines: {node: '>=0.10'}
2257 | hasBin: true
2258 | dev: true
2259 |
2260 | /pify@3.0.0:
2261 | resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==}
2262 | engines: {node: '>=4'}
2263 | dev: true
2264 |
2265 | /pkg-types@1.0.3:
2266 | resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==}
2267 | dependencies:
2268 | jsonc-parser: 3.2.0
2269 | mlly: 1.4.0
2270 | pathe: 1.1.1
2271 | dev: true
2272 |
2273 | /playwright-core@1.35.1:
2274 | resolution: {integrity: sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==}
2275 | engines: {node: '>=16'}
2276 | hasBin: true
2277 | dev: true
2278 |
2279 | /postcss-load-config@3.1.4(postcss@8.4.25):
2280 | resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
2281 | engines: {node: '>= 10'}
2282 | peerDependencies:
2283 | postcss: '>=8.0.9'
2284 | ts-node: '>=9.0.0'
2285 | peerDependenciesMeta:
2286 | postcss:
2287 | optional: true
2288 | ts-node:
2289 | optional: true
2290 | dependencies:
2291 | lilconfig: 2.1.0
2292 | postcss: 8.4.25
2293 | yaml: 1.10.2
2294 | dev: true
2295 |
2296 | /postcss-safe-parser@6.0.0(postcss@8.4.25):
2297 | resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==}
2298 | engines: {node: '>=12.0'}
2299 | peerDependencies:
2300 | postcss: ^8.3.3
2301 | dependencies:
2302 | postcss: 8.4.25
2303 | dev: true
2304 |
2305 | /postcss-scss@4.0.6(postcss@8.4.25):
2306 | resolution: {integrity: sha512-rLDPhJY4z/i4nVFZ27j9GqLxj1pwxE80eAzUNRMXtcpipFYIeowerzBgG3yJhMtObGEXidtIgbUpQ3eLDsf5OQ==}
2307 | engines: {node: '>=12.0'}
2308 | peerDependencies:
2309 | postcss: ^8.4.19
2310 | dependencies:
2311 | postcss: 8.4.25
2312 | dev: true
2313 |
2314 | /postcss-selector-parser@6.0.13:
2315 | resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==}
2316 | engines: {node: '>=4'}
2317 | dependencies:
2318 | cssesc: 3.0.0
2319 | util-deprecate: 1.0.2
2320 | dev: true
2321 |
2322 | /postcss@8.4.25:
2323 | resolution: {integrity: sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==}
2324 | engines: {node: ^10 || ^12 || >=14}
2325 | dependencies:
2326 | nanoid: 3.3.6
2327 | picocolors: 1.0.0
2328 | source-map-js: 1.0.2
2329 | dev: true
2330 |
2331 | /prelude-ls@1.2.1:
2332 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
2333 | engines: {node: '>= 0.8.0'}
2334 | dev: true
2335 |
2336 | /prettier-plugin-svelte@2.10.1(prettier@2.8.8)(svelte@4.0.5):
2337 | resolution: {integrity: sha512-Wlq7Z5v2ueCubWo0TZzKc9XHcm7TDxqcuzRuGd0gcENfzfT4JZ9yDlCbEgxWgiPmLHkBjfOtpAWkcT28MCDpUQ==}
2338 | peerDependencies:
2339 | prettier: ^1.16.4 || ^2.0.0
2340 | svelte: ^3.2.0 || ^4.0.0-next.0
2341 | dependencies:
2342 | prettier: 2.8.8
2343 | svelte: 4.0.5
2344 | dev: true
2345 |
2346 | /prettier@2.8.8:
2347 | resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
2348 | engines: {node: '>=10.13.0'}
2349 | hasBin: true
2350 | dev: true
2351 |
2352 | /pretty-format@29.6.1:
2353 | resolution: {integrity: sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==}
2354 | engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
2355 | dependencies:
2356 | '@jest/schemas': 29.6.0
2357 | ansi-styles: 5.2.0
2358 | react-is: 18.2.0
2359 | dev: true
2360 |
2361 | /publint@0.1.16:
2362 | resolution: {integrity: sha512-wJgk7HnXDT5Ap0DjFYbGz78kPkN44iQvDiaq8P63IEEyNU9mYXvaMd2cAyIM6OgqXM/IA3CK6XWIsRq+wjNpgw==}
2363 | engines: {node: '>=16'}
2364 | hasBin: true
2365 | dependencies:
2366 | npm-packlist: 5.1.3
2367 | picocolors: 1.0.0
2368 | sade: 1.8.1
2369 | dev: true
2370 |
2371 | /punycode@2.3.0:
2372 | resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
2373 | engines: {node: '>=6'}
2374 | dev: true
2375 |
2376 | /queue-microtask@1.2.3:
2377 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
2378 | dev: true
2379 |
2380 | /react-is@18.2.0:
2381 | resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
2382 | dev: true
2383 |
2384 | /read-pkg@3.0.0:
2385 | resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==}
2386 | engines: {node: '>=4'}
2387 | dependencies:
2388 | load-json-file: 4.0.0
2389 | normalize-package-data: 2.5.0
2390 | path-type: 3.0.0
2391 | dev: true
2392 |
2393 | /readdirp@3.6.0:
2394 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
2395 | engines: {node: '>=8.10.0'}
2396 | dependencies:
2397 | picomatch: 2.3.1
2398 | dev: true
2399 |
2400 | /regexp.prototype.flags@1.5.0:
2401 | resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==}
2402 | engines: {node: '>= 0.4'}
2403 | dependencies:
2404 | call-bind: 1.0.2
2405 | define-properties: 1.2.0
2406 | functions-have-names: 1.2.3
2407 | dev: true
2408 |
2409 | /resolve-from@4.0.0:
2410 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
2411 | engines: {node: '>=4'}
2412 | dev: true
2413 |
2414 | /resolve@1.22.2:
2415 | resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==}
2416 | hasBin: true
2417 | dependencies:
2418 | is-core-module: 2.12.1
2419 | path-parse: 1.0.7
2420 | supports-preserve-symlinks-flag: 1.0.0
2421 | dev: true
2422 |
2423 | /reusify@1.0.4:
2424 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
2425 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
2426 | dev: true
2427 |
2428 | /rimraf@2.7.1:
2429 | resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
2430 | hasBin: true
2431 | dependencies:
2432 | glob: 7.2.3
2433 | dev: true
2434 |
2435 | /rimraf@3.0.2:
2436 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
2437 | hasBin: true
2438 | dependencies:
2439 | glob: 7.2.3
2440 | dev: true
2441 |
2442 | /rollup@3.26.2:
2443 | resolution: {integrity: sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==}
2444 | engines: {node: '>=14.18.0', npm: '>=8.0.0'}
2445 | hasBin: true
2446 | optionalDependencies:
2447 | fsevents: 2.3.2
2448 | dev: true
2449 |
2450 | /run-parallel@1.2.0:
2451 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
2452 | dependencies:
2453 | queue-microtask: 1.2.3
2454 | dev: true
2455 |
2456 | /sade@1.8.1:
2457 | resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
2458 | engines: {node: '>=6'}
2459 | dependencies:
2460 | mri: 1.2.0
2461 | dev: true
2462 |
2463 | /safe-regex-test@1.0.0:
2464 | resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==}
2465 | dependencies:
2466 | call-bind: 1.0.2
2467 | get-intrinsic: 1.2.1
2468 | is-regex: 1.1.4
2469 | dev: true
2470 |
2471 | /sander@0.5.1:
2472 | resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==}
2473 | dependencies:
2474 | es6-promise: 3.3.1
2475 | graceful-fs: 4.2.11
2476 | mkdirp: 0.5.6
2477 | rimraf: 2.7.1
2478 | dev: true
2479 |
2480 | /sass@1.63.6:
2481 | resolution: {integrity: sha512-MJuxGMHzaOW7ipp+1KdELtqKbfAWbH7OLIdoSMnVe3EXPMTmxTmlaZDCTsgIpPCs3w99lLo9/zDKkOrJuT5byw==}
2482 | engines: {node: '>=14.0.0'}
2483 | hasBin: true
2484 | dependencies:
2485 | chokidar: 3.5.3
2486 | immutable: 4.3.0
2487 | source-map-js: 1.0.2
2488 | dev: true
2489 |
2490 | /semver@5.7.1:
2491 | resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
2492 | hasBin: true
2493 | dev: true
2494 |
2495 | /semver@6.3.0:
2496 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
2497 | hasBin: true
2498 | dev: true
2499 |
2500 | /semver@7.5.4:
2501 | resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
2502 | engines: {node: '>=10'}
2503 | hasBin: true
2504 | dependencies:
2505 | lru-cache: 6.0.0
2506 | dev: true
2507 |
2508 | /set-cookie-parser@2.6.0:
2509 | resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==}
2510 | dev: true
2511 |
2512 | /shebang-command@1.2.0:
2513 | resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
2514 | engines: {node: '>=0.10.0'}
2515 | dependencies:
2516 | shebang-regex: 1.0.0
2517 | dev: true
2518 |
2519 | /shebang-command@2.0.0:
2520 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
2521 | engines: {node: '>=8'}
2522 | dependencies:
2523 | shebang-regex: 3.0.0
2524 | dev: true
2525 |
2526 | /shebang-regex@1.0.0:
2527 | resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==}
2528 | engines: {node: '>=0.10.0'}
2529 | dev: true
2530 |
2531 | /shebang-regex@3.0.0:
2532 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
2533 | engines: {node: '>=8'}
2534 | dev: true
2535 |
2536 | /shell-quote@1.8.1:
2537 | resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
2538 | dev: true
2539 |
2540 | /side-channel@1.0.4:
2541 | resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
2542 | dependencies:
2543 | call-bind: 1.0.2
2544 | get-intrinsic: 1.2.1
2545 | object-inspect: 1.12.3
2546 | dev: true
2547 |
2548 | /siginfo@2.0.0:
2549 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
2550 | dev: true
2551 |
2552 | /sirv@2.0.3:
2553 | resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==}
2554 | engines: {node: '>= 10'}
2555 | dependencies:
2556 | '@polka/url': 1.0.0-next.21
2557 | mrmime: 1.0.1
2558 | totalist: 3.0.1
2559 | dev: true
2560 |
2561 | /slash@3.0.0:
2562 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
2563 | engines: {node: '>=8'}
2564 | dev: true
2565 |
2566 | /sorcery@0.11.0:
2567 | resolution: {integrity: sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==}
2568 | hasBin: true
2569 | dependencies:
2570 | '@jridgewell/sourcemap-codec': 1.4.15
2571 | buffer-crc32: 0.2.13
2572 | minimist: 1.2.8
2573 | sander: 0.5.1
2574 | dev: true
2575 |
2576 | /source-map-js@1.0.2:
2577 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
2578 | engines: {node: '>=0.10.0'}
2579 | dev: true
2580 |
2581 | /source-map@0.6.1:
2582 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
2583 | engines: {node: '>=0.10.0'}
2584 | dev: true
2585 |
2586 | /spdx-correct@3.2.0:
2587 | resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
2588 | dependencies:
2589 | spdx-expression-parse: 3.0.1
2590 | spdx-license-ids: 3.0.13
2591 | dev: true
2592 |
2593 | /spdx-exceptions@2.3.0:
2594 | resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==}
2595 | dev: true
2596 |
2597 | /spdx-expression-parse@3.0.1:
2598 | resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
2599 | dependencies:
2600 | spdx-exceptions: 2.3.0
2601 | spdx-license-ids: 3.0.13
2602 | dev: true
2603 |
2604 | /spdx-license-ids@3.0.13:
2605 | resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==}
2606 | dev: true
2607 |
2608 | /stackback@0.0.2:
2609 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
2610 | dev: true
2611 |
2612 | /std-env@3.3.3:
2613 | resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==}
2614 | dev: true
2615 |
2616 | /streamsearch@1.1.0:
2617 | resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
2618 | engines: {node: '>=10.0.0'}
2619 | dev: true
2620 |
2621 | /string.prototype.padend@3.1.4:
2622 | resolution: {integrity: sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==}
2623 | engines: {node: '>= 0.4'}
2624 | dependencies:
2625 | call-bind: 1.0.2
2626 | define-properties: 1.2.0
2627 | es-abstract: 1.21.2
2628 | dev: true
2629 |
2630 | /string.prototype.trim@1.2.7:
2631 | resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==}
2632 | engines: {node: '>= 0.4'}
2633 | dependencies:
2634 | call-bind: 1.0.2
2635 | define-properties: 1.2.0
2636 | es-abstract: 1.21.2
2637 | dev: true
2638 |
2639 | /string.prototype.trimend@1.0.6:
2640 | resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==}
2641 | dependencies:
2642 | call-bind: 1.0.2
2643 | define-properties: 1.2.0
2644 | es-abstract: 1.21.2
2645 | dev: true
2646 |
2647 | /string.prototype.trimstart@1.0.6:
2648 | resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==}
2649 | dependencies:
2650 | call-bind: 1.0.2
2651 | define-properties: 1.2.0
2652 | es-abstract: 1.21.2
2653 | dev: true
2654 |
2655 | /strip-ansi@6.0.1:
2656 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
2657 | engines: {node: '>=8'}
2658 | dependencies:
2659 | ansi-regex: 5.0.1
2660 | dev: true
2661 |
2662 | /strip-bom@3.0.0:
2663 | resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
2664 | engines: {node: '>=4'}
2665 | dev: true
2666 |
2667 | /strip-indent@3.0.0:
2668 | resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
2669 | engines: {node: '>=8'}
2670 | dependencies:
2671 | min-indent: 1.0.1
2672 | dev: true
2673 |
2674 | /strip-json-comments@3.1.1:
2675 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
2676 | engines: {node: '>=8'}
2677 | dev: true
2678 |
2679 | /strip-literal@1.0.1:
2680 | resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==}
2681 | dependencies:
2682 | acorn: 8.10.0
2683 | dev: true
2684 |
2685 | /supports-color@5.5.0:
2686 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
2687 | engines: {node: '>=4'}
2688 | dependencies:
2689 | has-flag: 3.0.0
2690 | dev: true
2691 |
2692 | /supports-color@7.2.0:
2693 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
2694 | engines: {node: '>=8'}
2695 | dependencies:
2696 | has-flag: 4.0.0
2697 | dev: true
2698 |
2699 | /supports-preserve-symlinks-flag@1.0.0:
2700 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
2701 | engines: {node: '>= 0.4'}
2702 | dev: true
2703 |
2704 | /svelte-check@3.4.5(postcss@8.4.25)(sass@1.63.6)(svelte@4.0.5):
2705 | resolution: {integrity: sha512-FsD/CUVdEI0F9sfylh1Fe15kDjvvbyBxzDpACPsdq0EASgaZukBXaMXofpxlgmWsgVET3OynMQlbtUQoWCz9Rw==}
2706 | hasBin: true
2707 | peerDependencies:
2708 | svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0
2709 | dependencies:
2710 | '@jridgewell/trace-mapping': 0.3.18
2711 | chokidar: 3.5.3
2712 | fast-glob: 3.3.0
2713 | import-fresh: 3.3.0
2714 | picocolors: 1.0.0
2715 | sade: 1.8.1
2716 | svelte: 4.0.5
2717 | svelte-preprocess: 5.0.4(postcss@8.4.25)(sass@1.63.6)(svelte@4.0.5)(typescript@5.1.6)
2718 | typescript: 5.1.6
2719 | transitivePeerDependencies:
2720 | - '@babel/core'
2721 | - coffeescript
2722 | - less
2723 | - postcss
2724 | - postcss-load-config
2725 | - pug
2726 | - sass
2727 | - stylus
2728 | - sugarss
2729 | dev: true
2730 |
2731 | /svelte-eslint-parser@0.32.1(svelte@4.0.5):
2732 | resolution: {integrity: sha512-GCSfeIzdgk53CaOzK+s/+l2igfTno3mWGkwoDYAwPes/rD9Al2fc7ksfopjx5UL87S7dw1eL73F6wNYiiuhzIA==}
2733 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
2734 | peerDependencies:
2735 | svelte: ^3.37.0 || ^4.0.0
2736 | peerDependenciesMeta:
2737 | svelte:
2738 | optional: true
2739 | dependencies:
2740 | eslint-scope: 7.2.0
2741 | eslint-visitor-keys: 3.4.1
2742 | espree: 9.6.0
2743 | postcss: 8.4.25
2744 | postcss-scss: 4.0.6(postcss@8.4.25)
2745 | svelte: 4.0.5
2746 | dev: true
2747 |
2748 | /svelte-hmr@0.15.2(svelte@4.0.5):
2749 | resolution: {integrity: sha512-q/bAruCvFLwvNbeE1x3n37TYFb3mTBJ6TrCq6p2CoFbSTNhDE9oAtEfpy+wmc9So8AG0Tja+X0/mJzX9tSfvIg==}
2750 | engines: {node: ^12.20 || ^14.13.1 || >= 16}
2751 | peerDependencies:
2752 | svelte: ^3.19.0 || ^4.0.0-next.0
2753 | dependencies:
2754 | svelte: 4.0.5
2755 | dev: true
2756 |
2757 | /svelte-preprocess@5.0.4(postcss@8.4.25)(sass@1.63.6)(svelte@4.0.5)(typescript@5.1.6):
2758 | resolution: {integrity: sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==}
2759 | engines: {node: '>= 14.10.0'}
2760 | requiresBuild: true
2761 | peerDependencies:
2762 | '@babel/core': ^7.10.2
2763 | coffeescript: ^2.5.1
2764 | less: ^3.11.3 || ^4.0.0
2765 | postcss: ^7 || ^8
2766 | postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0
2767 | pug: ^3.0.0
2768 | sass: ^1.26.8
2769 | stylus: ^0.55.0
2770 | sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0
2771 | svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0
2772 | typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0'
2773 | peerDependenciesMeta:
2774 | '@babel/core':
2775 | optional: true
2776 | coffeescript:
2777 | optional: true
2778 | less:
2779 | optional: true
2780 | postcss:
2781 | optional: true
2782 | postcss-load-config:
2783 | optional: true
2784 | pug:
2785 | optional: true
2786 | sass:
2787 | optional: true
2788 | stylus:
2789 | optional: true
2790 | sugarss:
2791 | optional: true
2792 | typescript:
2793 | optional: true
2794 | dependencies:
2795 | '@types/pug': 2.0.6
2796 | detect-indent: 6.1.0
2797 | magic-string: 0.27.0
2798 | postcss: 8.4.25
2799 | sass: 1.63.6
2800 | sorcery: 0.11.0
2801 | strip-indent: 3.0.0
2802 | svelte: 4.0.5
2803 | typescript: 5.1.6
2804 | dev: true
2805 |
2806 | /svelte2tsx@0.6.19(svelte@4.0.5)(typescript@5.1.6):
2807 | resolution: {integrity: sha512-h3b5OtcO8zyVL/RiB2zsDwCopeo/UH+887uyhgb2mjnewOFwiTxu+4IGuVwrrlyuh2onM2ktfUemNrNmQwXONQ==}
2808 | peerDependencies:
2809 | svelte: ^3.55 || ^4.0.0-next.0 || ^4.0
2810 | typescript: ^4.9.4 || ^5.0.0
2811 | dependencies:
2812 | dedent-js: 1.0.1
2813 | pascal-case: 3.1.2
2814 | svelte: 4.0.5
2815 | typescript: 5.1.6
2816 | dev: true
2817 |
2818 | /svelte@4.0.5:
2819 | resolution: {integrity: sha512-PHKPWP1wiWHBtsE57nCb8xiWB3Ht7/3Kvi3jac0XIxUM2rep8alO7YoAtgWeGD7++tFy46krilOrPW0mG3Dx+A==}
2820 | engines: {node: '>=16'}
2821 | dependencies:
2822 | '@ampproject/remapping': 2.2.1
2823 | '@jridgewell/sourcemap-codec': 1.4.15
2824 | '@jridgewell/trace-mapping': 0.3.18
2825 | acorn: 8.10.0
2826 | aria-query: 5.3.0
2827 | axobject-query: 3.2.1
2828 | code-red: 1.0.3
2829 | css-tree: 2.3.1
2830 | estree-walker: 3.0.3
2831 | is-reference: 3.0.1
2832 | locate-character: 3.0.0
2833 | magic-string: 0.30.1
2834 | periscopic: 3.1.0
2835 | dev: true
2836 |
2837 | /test-exclude@6.0.0:
2838 | resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
2839 | engines: {node: '>=8'}
2840 | dependencies:
2841 | '@istanbuljs/schema': 0.1.3
2842 | glob: 7.2.3
2843 | minimatch: 3.1.2
2844 | dev: true
2845 |
2846 | /text-table@0.2.0:
2847 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
2848 | dev: true
2849 |
2850 | /tinybench@2.5.0:
2851 | resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==}
2852 | dev: true
2853 |
2854 | /tinypool@0.5.0:
2855 | resolution: {integrity: sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==}
2856 | engines: {node: '>=14.0.0'}
2857 | dev: true
2858 |
2859 | /tinyspy@2.1.1:
2860 | resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==}
2861 | engines: {node: '>=14.0.0'}
2862 | dev: true
2863 |
2864 | /to-regex-range@5.0.1:
2865 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
2866 | engines: {node: '>=8.0'}
2867 | dependencies:
2868 | is-number: 7.0.0
2869 | dev: true
2870 |
2871 | /totalist@3.0.1:
2872 | resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
2873 | engines: {node: '>=6'}
2874 | dev: true
2875 |
2876 | /tslib@1.14.1:
2877 | resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
2878 | dev: true
2879 |
2880 | /tslib@2.6.0:
2881 | resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==}
2882 | dev: true
2883 |
2884 | /tsutils@3.21.0(typescript@5.1.6):
2885 | resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
2886 | engines: {node: '>= 6'}
2887 | peerDependencies:
2888 | typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
2889 | dependencies:
2890 | tslib: 1.14.1
2891 | typescript: 5.1.6
2892 | dev: true
2893 |
2894 | /type-check@0.4.0:
2895 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
2896 | engines: {node: '>= 0.8.0'}
2897 | dependencies:
2898 | prelude-ls: 1.2.1
2899 | dev: true
2900 |
2901 | /type-detect@4.0.8:
2902 | resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
2903 | engines: {node: '>=4'}
2904 | dev: true
2905 |
2906 | /type-fest@0.20.2:
2907 | resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
2908 | engines: {node: '>=10'}
2909 | dev: true
2910 |
2911 | /typed-array-length@1.0.4:
2912 | resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==}
2913 | dependencies:
2914 | call-bind: 1.0.2
2915 | for-each: 0.3.3
2916 | is-typed-array: 1.1.10
2917 | dev: true
2918 |
2919 | /typesafe-i18n@5.24.3(typescript@5.1.6):
2920 | resolution: {integrity: sha512-VqjGbIydOqtQjO81mGo++TjuqeC8YoxxgYrO1/ikXIS/l/Q6mAcz4yrt5AvqjdFHMt3gRm7oGbVI/yLyV+VTOg==}
2921 | hasBin: true
2922 | peerDependencies:
2923 | typescript: '>=3.5.1'
2924 | dependencies:
2925 | typescript: 5.1.6
2926 | dev: true
2927 |
2928 | /typescript@5.1.6:
2929 | resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==}
2930 | engines: {node: '>=14.17'}
2931 | hasBin: true
2932 | dev: true
2933 |
2934 | /ufo@1.1.2:
2935 | resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==}
2936 | dev: true
2937 |
2938 | /unbox-primitive@1.0.2:
2939 | resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
2940 | dependencies:
2941 | call-bind: 1.0.2
2942 | has-bigints: 1.0.2
2943 | has-symbols: 1.0.3
2944 | which-boxed-primitive: 1.0.2
2945 | dev: true
2946 |
2947 | /undici@5.22.1:
2948 | resolution: {integrity: sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==}
2949 | engines: {node: '>=14.0'}
2950 | dependencies:
2951 | busboy: 1.6.0
2952 | dev: true
2953 |
2954 | /uri-js@4.4.1:
2955 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
2956 | dependencies:
2957 | punycode: 2.3.0
2958 | dev: true
2959 |
2960 | /util-deprecate@1.0.2:
2961 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
2962 | dev: true
2963 |
2964 | /v8-to-istanbul@9.1.0:
2965 | resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==}
2966 | engines: {node: '>=10.12.0'}
2967 | dependencies:
2968 | '@jridgewell/trace-mapping': 0.3.18
2969 | '@types/istanbul-lib-coverage': 2.0.4
2970 | convert-source-map: 1.9.0
2971 | dev: true
2972 |
2973 | /validate-npm-package-license@3.0.4:
2974 | resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
2975 | dependencies:
2976 | spdx-correct: 3.2.0
2977 | spdx-expression-parse: 3.0.1
2978 | dev: true
2979 |
2980 | /vite-node@0.32.4(@types/node@20.4.1)(sass@1.63.6):
2981 | resolution: {integrity: sha512-L2gIw+dCxO0LK14QnUMoqSYpa9XRGnTTTDjW2h19Mr+GR0EFj4vx52W41gFXfMLqpA00eK4ZjOVYo1Xk//LFEw==}
2982 | engines: {node: '>=v14.18.0'}
2983 | hasBin: true
2984 | dependencies:
2985 | cac: 6.7.14
2986 | debug: 4.3.4
2987 | mlly: 1.4.0
2988 | pathe: 1.1.1
2989 | picocolors: 1.0.0
2990 | vite: 4.4.2(@types/node@20.4.1)(sass@1.63.6)
2991 | transitivePeerDependencies:
2992 | - '@types/node'
2993 | - less
2994 | - lightningcss
2995 | - sass
2996 | - stylus
2997 | - sugarss
2998 | - supports-color
2999 | - terser
3000 | dev: true
3001 |
3002 | /vite@4.4.2(@types/node@20.4.1)(sass@1.63.6):
3003 | resolution: {integrity: sha512-zUcsJN+UvdSyHhYa277UHhiJ3iq4hUBwHavOpsNUGsTgjBeoBlK8eDt+iT09pBq0h9/knhG/SPrZiM7cGmg7NA==}
3004 | engines: {node: ^14.18.0 || >=16.0.0}
3005 | hasBin: true
3006 | peerDependencies:
3007 | '@types/node': '>= 14'
3008 | less: '*'
3009 | lightningcss: ^1.21.0
3010 | sass: '*'
3011 | stylus: '*'
3012 | sugarss: '*'
3013 | terser: ^5.4.0
3014 | peerDependenciesMeta:
3015 | '@types/node':
3016 | optional: true
3017 | less:
3018 | optional: true
3019 | lightningcss:
3020 | optional: true
3021 | sass:
3022 | optional: true
3023 | stylus:
3024 | optional: true
3025 | sugarss:
3026 | optional: true
3027 | terser:
3028 | optional: true
3029 | dependencies:
3030 | '@types/node': 20.4.1
3031 | esbuild: 0.18.11
3032 | postcss: 8.4.25
3033 | rollup: 3.26.2
3034 | sass: 1.63.6
3035 | optionalDependencies:
3036 | fsevents: 2.3.2
3037 | dev: true
3038 |
3039 | /vitefu@0.2.4(vite@4.4.2):
3040 | resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==}
3041 | peerDependencies:
3042 | vite: ^3.0.0 || ^4.0.0
3043 | peerDependenciesMeta:
3044 | vite:
3045 | optional: true
3046 | dependencies:
3047 | vite: 4.4.2(@types/node@20.4.1)(sass@1.63.6)
3048 | dev: true
3049 |
3050 | /vitest@0.32.4(sass@1.63.6):
3051 | resolution: {integrity: sha512-3czFm8RnrsWwIzVDu/Ca48Y/M+qh3vOnF16czJm98Q/AN1y3B6PBsyV8Re91Ty5s7txKNjEhpgtGPcfdbh2MZg==}
3052 | engines: {node: '>=v14.18.0'}
3053 | hasBin: true
3054 | peerDependencies:
3055 | '@edge-runtime/vm': '*'
3056 | '@vitest/browser': '*'
3057 | '@vitest/ui': '*'
3058 | happy-dom: '*'
3059 | jsdom: '*'
3060 | playwright: '*'
3061 | safaridriver: '*'
3062 | webdriverio: '*'
3063 | peerDependenciesMeta:
3064 | '@edge-runtime/vm':
3065 | optional: true
3066 | '@vitest/browser':
3067 | optional: true
3068 | '@vitest/ui':
3069 | optional: true
3070 | happy-dom:
3071 | optional: true
3072 | jsdom:
3073 | optional: true
3074 | playwright:
3075 | optional: true
3076 | safaridriver:
3077 | optional: true
3078 | webdriverio:
3079 | optional: true
3080 | dependencies:
3081 | '@types/chai': 4.3.5
3082 | '@types/chai-subset': 1.3.3
3083 | '@types/node': 20.4.1
3084 | '@vitest/expect': 0.32.4
3085 | '@vitest/runner': 0.32.4
3086 | '@vitest/snapshot': 0.32.4
3087 | '@vitest/spy': 0.32.4
3088 | '@vitest/utils': 0.32.4
3089 | acorn: 8.10.0
3090 | acorn-walk: 8.2.0
3091 | cac: 6.7.14
3092 | chai: 4.3.7
3093 | debug: 4.3.4
3094 | local-pkg: 0.4.3
3095 | magic-string: 0.30.1
3096 | pathe: 1.1.1
3097 | picocolors: 1.0.0
3098 | std-env: 3.3.3
3099 | strip-literal: 1.0.1
3100 | tinybench: 2.5.0
3101 | tinypool: 0.5.0
3102 | vite: 4.4.2(@types/node@20.4.1)(sass@1.63.6)
3103 | vite-node: 0.32.4(@types/node@20.4.1)(sass@1.63.6)
3104 | why-is-node-running: 2.2.2
3105 | transitivePeerDependencies:
3106 | - less
3107 | - lightningcss
3108 | - sass
3109 | - stylus
3110 | - sugarss
3111 | - supports-color
3112 | - terser
3113 | dev: true
3114 |
3115 | /which-boxed-primitive@1.0.2:
3116 | resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
3117 | dependencies:
3118 | is-bigint: 1.0.4
3119 | is-boolean-object: 1.1.2
3120 | is-number-object: 1.0.7
3121 | is-string: 1.0.7
3122 | is-symbol: 1.0.4
3123 | dev: true
3124 |
3125 | /which-typed-array@1.1.9:
3126 | resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==}
3127 | engines: {node: '>= 0.4'}
3128 | dependencies:
3129 | available-typed-arrays: 1.0.5
3130 | call-bind: 1.0.2
3131 | for-each: 0.3.3
3132 | gopd: 1.0.1
3133 | has-tostringtag: 1.0.0
3134 | is-typed-array: 1.1.10
3135 | dev: true
3136 |
3137 | /which@1.3.1:
3138 | resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
3139 | hasBin: true
3140 | dependencies:
3141 | isexe: 2.0.0
3142 | dev: true
3143 |
3144 | /which@2.0.2:
3145 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
3146 | engines: {node: '>= 8'}
3147 | hasBin: true
3148 | dependencies:
3149 | isexe: 2.0.0
3150 | dev: true
3151 |
3152 | /why-is-node-running@2.2.2:
3153 | resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==}
3154 | engines: {node: '>=8'}
3155 | hasBin: true
3156 | dependencies:
3157 | siginfo: 2.0.0
3158 | stackback: 0.0.2
3159 | dev: true
3160 |
3161 | /wrappy@1.0.2:
3162 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
3163 | dev: true
3164 |
3165 | /yallist@4.0.0:
3166 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
3167 | dev: true
3168 |
3169 | /yaml@1.10.2:
3170 | resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
3171 | engines: {node: '>= 6'}
3172 | dev: true
3173 |
3174 | /yocto-queue@0.1.0:
3175 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
3176 | engines: {node: '>=10'}
3177 | dev: true
3178 |
3179 | /yocto-queue@1.0.0:
3180 | resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
3181 | engines: {node: '>=12.20'}
3182 | dev: true
3183 |
--------------------------------------------------------------------------------
/src/app.d.ts:
--------------------------------------------------------------------------------
1 | // See https://kit.svelte.dev/docs/types#app
2 | // for information about these interfaces
3 |
4 | import type { Locales, TranslationFunctions } from '$i18n/i18n-types.ts';
5 |
6 | declare global {
7 | namespace App {
8 | interface Error {
9 | message: string;
10 | link?: string;
11 | linkText?: string;
12 | }
13 |
14 | interface Locals {
15 | locale: Locales;
16 | LL: TranslationFunctions;
17 | }
18 |
19 | // interface Platform {}
20 | }
21 | }
22 |
23 | export {};
24 |
--------------------------------------------------------------------------------
/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | %sveltekit.head%
8 |
9 |
10 | %sveltekit.body%
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/HeadHrefLangs.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | {#if !$page.error}
9 |
10 | {#each buildAlternateLinks($page.data.LP).hreflang as [hreflang, href]}
11 |
12 | {/each}
13 |
14 |
15 |
16 | {/if}
17 |
--------------------------------------------------------------------------------
/src/components/Header.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
66 |
--------------------------------------------------------------------------------
/src/components/LocaleSwitcher.svelte:
--------------------------------------------------------------------------------
1 |
32 |
33 |
34 |
37 | {#each buildAlternateLinks($page.data.LP, $page.error).switcher as [lang, href]}
38 |
39 |
40 |
41 | {lang}
42 |
43 |
44 | {/each}
45 |
46 |
--------------------------------------------------------------------------------
/src/hooks.server.ts:
--------------------------------------------------------------------------------
1 | import type { Locales } from '$i18n/i18n-types.js';
2 | import { baseLocale, detectLocale, i18n, locales } from '$i18n/i18n-util.js';
3 | import { loadAllLocales } from '$i18n/i18n-util.sync.js';
4 | import { getLocaleFromUrl, getLocaleHomeHref, initLocalizeUrl } from '$lib/index.js';
5 | import { redirect, type Handle, type RequestEvent } from '@sveltejs/kit';
6 | import { initAcceptLanguageHeaderDetector } from 'typesafe-i18n/detectors';
7 |
8 | loadAllLocales();
9 | const L = i18n();
10 |
11 | export const handle: Handle = async ({ event, resolve }) => {
12 | // initialize Localize URL library on server
13 | initLocalizeUrl({
14 | baseLocale,
15 | locales
16 | });
17 | const locale = getLocaleFromUrl(event.url) as Locales;
18 |
19 | // track the first visit for language detection
20 | let hasVisited = true;
21 | // only count translateable part of the website (exclude API)
22 | if ((event.route.id ?? '').startsWith('/[[lang=lang]]')) {
23 | hasVisited = event.cookies.get('visited') === '1';
24 | }
25 | if (!hasVisited) {
26 | event.cookies.set('visited', '1', { path: '/' });
27 | }
28 |
29 | /**
30 | * Redirect first time home page visitor based on their detected locale.
31 | * ! WARNING: Google advises against this:
32 | * ! https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites#let-the-user-switch-the-page-language
33 | */
34 | if (!hasVisited && event.url.pathname === '/') {
35 | const detectedLocale = getPreferredLocale(event);
36 | if (detectedLocale !== locale) {
37 | const localeHomeUrl = getLocaleHomeHref(detectedLocale, event.url, true);
38 | throw redirect(302, localeHomeUrl);
39 | }
40 | }
41 |
42 | const LL = L[locale];
43 |
44 | // bind locale and translation functions to current request
45 | event.locals.locale = locale;
46 | event.locals.LL = LL;
47 |
48 | console.info(LL.log({ fileName: 'hooks.server.ts' }));
49 |
50 | // replace html lang attribute with correct language
51 | return resolve(event, { transformPageChunk: ({ html }) => html.replace('%lang%', locale) });
52 | };
53 |
54 | const getPreferredLocale = ({ request }: RequestEvent) => {
55 | // Detect the preferred language the user has configured in his browser
56 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language
57 | const acceptLanguageDetector = initAcceptLanguageHeaderDetector(request);
58 |
59 | return detectLocale(acceptLanguageDetector);
60 | };
61 |
--------------------------------------------------------------------------------
/src/i18n/de/index.ts:
--------------------------------------------------------------------------------
1 | import en from '$i18n/en/index.js';
2 | import type { Translation } from '../i18n-types.js';
3 |
4 | const de = {
5 | // Fallback
6 | ...(en as Translation),
7 |
8 | log: "Dieses Logging wurde von '{fileName}' aufgerufen",
9 | site: {
10 | name: 'Localize URL'
11 | },
12 | pageHome: {
13 | title: 'Startseite',
14 | welcome: 'Willkommen auf der Homepage',
15 | apiDescription: 'API-Aufrufe, die nicht von der Bibliothek betroffen sind',
16 | spectators: '{0} Zuschauer live',
17 | legend: {
18 | title: 'Legende',
19 | correct: 'Richtiger Link',
20 | fallback: 'Fallback-Link (führt zu einem anderen Gebietsschema)',
21 | vary: 'Richtiger Link (nur für unterstützte Gebietsschemas sichtbar)',
22 | redirect: 'Nicht übereinstimmender Link, Weiterleitung',
23 | error: 'Für dieses Gebietsschema nicht verfügbar'
24 | }
25 | },
26 | pageAbout: {
27 | title: 'Über uns',
28 | text: 'Über uns Seite sagt Hallo.'
29 | },
30 | pageEnglish: {
31 | title: 'Seite nur auf Englisch',
32 | text: ''
33 | },
34 | pageNews: {
35 | title: 'Nachricht'
36 | },
37 | pageError: {
38 | title404: 'Seite nicht gefunden',
39 | titleOffline: 'Es sieht so aus, als wären Sie offline',
40 | titleOther: 'Huch!',
41 | message404: 'Leider konnten wir die gewünschte Seite nicht finden.',
42 | messageNotTranslated: 'Leider ist diese Seite noch nicht in Ihrer Sprache verfügbar.',
43 | messageOffline: 'Laden Sie die Seite neu, sobald Sie das Internet gefunden haben.',
44 | messageOther: 'Bitte versuchen Sie, die Seite neu zu laden.',
45 | actionHome: 'Zur Startseite zurückkehren',
46 | actionBaseLocale: 'Diese Seite auf Englisch anzeigen'
47 | }
48 | } satisfies Translation;
49 |
50 | export default de;
51 |
--------------------------------------------------------------------------------
/src/i18n/en/index.ts:
--------------------------------------------------------------------------------
1 | import type { BaseTranslation } from '../i18n-types.js';
2 |
3 | const en = {
4 | log: "This log was called from '{fileName:string}'",
5 | site: {
6 | name: 'Localize URL'
7 | },
8 | pageHome: {
9 | title: 'Home page',
10 | welcome: 'Welcome to the home page',
11 | apiDescription: 'API calls that are not affected by the library',
12 | spectators: '{0} live spectator{{s}}',
13 | legend: {
14 | title: 'Legend',
15 | correct: 'Correct link',
16 | fallback: 'Fallback link (leads to another locale)',
17 | vary: 'Correct link (only visible for supported locales)',
18 | redirect: 'Mismatched link, redirect',
19 | error: 'Not available for this locale'
20 | }
21 | },
22 | pageAbout: {
23 | title: 'About',
24 | text: 'About us page says hello.'
25 | },
26 | pageEnglish: {
27 | title: 'English-only page',
28 | text: 'This page is only available in English.'
29 | },
30 | pageNews: {
31 | title: 'News'
32 | },
33 | pageError: {
34 | title404: 'Page Not Found',
35 | titleOffline: "It looks like you're offline",
36 | titleOther: 'Yikes!',
37 | message404: "Sorry, we weren't able to find the requested page.",
38 | messageNotTranslated: "Sorry, this page isn't available in your language.",
39 | messageOffline: "Reload the page once you've found the internet.",
40 | messageOther: 'Please try reloading the page.',
41 | actionHome: 'Return to home page',
42 | actionBaseLocale: 'Show this page in English'
43 | }
44 | } satisfies BaseTranslation;
45 |
46 | export default en;
47 |
--------------------------------------------------------------------------------
/src/i18n/formatters.ts:
--------------------------------------------------------------------------------
1 | import type { FormattersInitializer } from 'typesafe-i18n';
2 | import type { Locales, Formatters } from './i18n-types.js';
3 |
4 | export const initFormatters: FormattersInitializer = (locale: Locales) => {
5 | const formatters: Formatters = {
6 | // add your formatter functions here
7 | };
8 |
9 | return formatters;
10 | };
11 |
--------------------------------------------------------------------------------
/src/i18n/i18n-svelte.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 |
4 | import { initI18nSvelte } from 'typesafe-i18n/svelte';
5 | import type { Formatters, Locales, TranslationFunctions, Translations } from './i18n-types.js';
6 | import { loadedFormatters, loadedLocales } from './i18n-util.js';
7 |
8 | const { locale, LL, setLocale } = initI18nSvelte<
9 | Locales,
10 | Translations,
11 | TranslationFunctions,
12 | Formatters
13 | >(loadedLocales, loadedFormatters);
14 |
15 | export { locale, LL, setLocale };
16 |
17 | export default LL;
18 |
--------------------------------------------------------------------------------
/src/i18n/i18n-types.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 | import type {
4 | BaseTranslation as BaseTranslationType,
5 | LocalizedString,
6 | RequiredParams
7 | } from 'typesafe-i18n';
8 |
9 | export type BaseTranslation = BaseTranslationType;
10 | export type BaseLocale = 'en';
11 |
12 | export type Locales = 'de' | 'en' | 'it' | 'ru';
13 |
14 | export type Translation = RootTranslation;
15 |
16 | export type Translations = RootTranslation;
17 |
18 | type RootTranslation = {
19 | /**
20 | * This log was called from '{fileName}'
21 | * @param {string} fileName
22 | */
23 | log: RequiredParams<'fileName'>;
24 | site: {
25 | /**
26 | * Localize URL
27 | */
28 | name: string;
29 | };
30 | pageHome: {
31 | /**
32 | * Home page
33 | */
34 | title: string;
35 | /**
36 | * Welcome to the home page
37 | */
38 | welcome: string;
39 | /**
40 | * API calls that are not affected by the library
41 | */
42 | apiDescription: string;
43 | /**
44 | * {0} live spectator{{s}}
45 | * @param {string | number | boolean} 0
46 | */
47 | spectators: RequiredParams<'0'>;
48 | legend: {
49 | /**
50 | * Legend
51 | */
52 | title: string;
53 | /**
54 | * Correct link
55 | */
56 | correct: string;
57 | /**
58 | * Fallback link (leads to another locale)
59 | */
60 | fallback: string;
61 | /**
62 | * Correct link (only visible for supported locales)
63 | */
64 | vary: string;
65 | /**
66 | * Mismatched link, redirect
67 | */
68 | redirect: string;
69 | /**
70 | * Not available for this locale
71 | */
72 | error: string;
73 | };
74 | };
75 | pageAbout: {
76 | /**
77 | * About
78 | */
79 | title: string;
80 | /**
81 | * About us page says hello.
82 | */
83 | text: string;
84 | };
85 | pageEnglish: {
86 | /**
87 | * English-only page
88 | */
89 | title: string;
90 | /**
91 | * This page is only available in English.
92 | */
93 | text: string;
94 | };
95 | pageNews: {
96 | /**
97 | * News
98 | */
99 | title: string;
100 | };
101 | pageError: {
102 | /**
103 | * Page Not Found
104 | */
105 | title404: string;
106 | /**
107 | * It looks like you're offline
108 | */
109 | titleOffline: string;
110 | /**
111 | * Yikes!
112 | */
113 | titleOther: string;
114 | /**
115 | * Sorry, we weren't able to find the requested page.
116 | */
117 | message404: string;
118 | /**
119 | * Sorry, this page isn't available in your language.
120 | */
121 | messageNotTranslated: string;
122 | /**
123 | * Reload the page once you've found the internet.
124 | */
125 | messageOffline: string;
126 | /**
127 | * Please try reloading the page.
128 | */
129 | messageOther: string;
130 | /**
131 | * Return to home page
132 | */
133 | actionHome: string;
134 | /**
135 | * Show this page in English
136 | */
137 | actionBaseLocale: string;
138 | };
139 | };
140 |
141 | export type TranslationFunctions = {
142 | /**
143 | * This log was called from '{fileName}'
144 | */
145 | log: (arg: { fileName: string }) => LocalizedString;
146 | site: {
147 | /**
148 | * Localize URL
149 | */
150 | name: () => LocalizedString;
151 | };
152 | pageHome: {
153 | /**
154 | * Home page
155 | */
156 | title: () => LocalizedString;
157 | /**
158 | * Welcome to the home page
159 | */
160 | welcome: () => LocalizedString;
161 | /**
162 | * API calls that are not affected by the library
163 | */
164 | apiDescription: () => LocalizedString;
165 | /**
166 | * {0} live spectator{{s}}
167 | */
168 | spectators: (arg0: string | number | boolean) => LocalizedString;
169 | legend: {
170 | /**
171 | * Legend
172 | */
173 | title: () => LocalizedString;
174 | /**
175 | * Correct link
176 | */
177 | correct: () => LocalizedString;
178 | /**
179 | * Fallback link (leads to another locale)
180 | */
181 | fallback: () => LocalizedString;
182 | /**
183 | * Correct link (only visible for supported locales)
184 | */
185 | vary: () => LocalizedString;
186 | /**
187 | * Mismatched link, redirect
188 | */
189 | redirect: () => LocalizedString;
190 | /**
191 | * Not available for this locale
192 | */
193 | error: () => LocalizedString;
194 | };
195 | };
196 | pageAbout: {
197 | /**
198 | * About
199 | */
200 | title: () => LocalizedString;
201 | /**
202 | * About us page says hello.
203 | */
204 | text: () => LocalizedString;
205 | };
206 | pageEnglish: {
207 | /**
208 | * English-only page
209 | */
210 | title: () => LocalizedString;
211 | /**
212 | * This page is only available in English.
213 | */
214 | text: () => LocalizedString;
215 | };
216 | pageNews: {
217 | /**
218 | * News
219 | */
220 | title: () => LocalizedString;
221 | };
222 | pageError: {
223 | /**
224 | * Page Not Found
225 | */
226 | title404: () => LocalizedString;
227 | /**
228 | * It looks like you're offline
229 | */
230 | titleOffline: () => LocalizedString;
231 | /**
232 | * Yikes!
233 | */
234 | titleOther: () => LocalizedString;
235 | /**
236 | * Sorry, we weren't able to find the requested page.
237 | */
238 | message404: () => LocalizedString;
239 | /**
240 | * Sorry, this page isn't available in your language.
241 | */
242 | messageNotTranslated: () => LocalizedString;
243 | /**
244 | * Reload the page once you've found the internet.
245 | */
246 | messageOffline: () => LocalizedString;
247 | /**
248 | * Please try reloading the page.
249 | */
250 | messageOther: () => LocalizedString;
251 | /**
252 | * Return to home page
253 | */
254 | actionHome: () => LocalizedString;
255 | /**
256 | * Show this page in English
257 | */
258 | actionBaseLocale: () => LocalizedString;
259 | };
260 | };
261 |
262 | export type Formatters = {};
263 |
--------------------------------------------------------------------------------
/src/i18n/i18n-util.async.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 |
4 | import { initFormatters } from './formatters.js';
5 | import type { Locales, Translations } from './i18n-types.js';
6 | import { loadedFormatters, loadedLocales, locales } from './i18n-util.js';
7 |
8 | const localeTranslationLoaders = {
9 | de: () => import('./de/index.js'),
10 | en: () => import('./en/index.js'),
11 | it: () => import('./it/index.js'),
12 | ru: () => import('./ru/index.js')
13 | };
14 |
15 | const updateDictionary = (locale: Locales, dictionary: Partial): Translations =>
16 | (loadedLocales[locale] = { ...loadedLocales[locale], ...dictionary });
17 |
18 | export const importLocaleAsync = async (locale: Locales): Promise =>
19 | (await localeTranslationLoaders[locale]()).default as unknown as Translations;
20 |
21 | export const loadLocaleAsync = async (locale: Locales): Promise => {
22 | updateDictionary(locale, await importLocaleAsync(locale));
23 | loadFormatters(locale);
24 | };
25 |
26 | export const loadAllLocalesAsync = (): Promise => Promise.all(locales.map(loadLocaleAsync));
27 |
28 | export const loadFormatters = (locale: Locales): void =>
29 | void (loadedFormatters[locale] = initFormatters(locale));
30 |
--------------------------------------------------------------------------------
/src/i18n/i18n-util.sync.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 |
4 | import { initFormatters } from './formatters.js';
5 | import type { Locales, Translations } from './i18n-types.js';
6 | import { loadedFormatters, loadedLocales, locales } from './i18n-util.js';
7 |
8 | import de from './de/index.js';
9 | import en from './en/index.js';
10 | import it from './it/index.js';
11 | import ru from './ru/index.js';
12 |
13 | const localeTranslations = {
14 | de,
15 | en,
16 | it,
17 | ru
18 | };
19 |
20 | export const loadLocale = (locale: Locales): void => {
21 | if (loadedLocales[locale]) return;
22 |
23 | loadedLocales[locale] = localeTranslations[locale] as unknown as Translations;
24 | loadFormatters(locale);
25 | };
26 |
27 | export const loadAllLocales = (): void => locales.forEach(loadLocale);
28 |
29 | export const loadFormatters = (locale: Locales): void =>
30 | void (loadedFormatters[locale] = initFormatters(locale));
31 |
--------------------------------------------------------------------------------
/src/i18n/i18n-util.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 |
4 | import {
5 | i18n as initI18n,
6 | i18nObject as initI18nObject,
7 | i18nString as initI18nString
8 | } from 'typesafe-i18n';
9 | import type { LocaleDetector } from 'typesafe-i18n/detectors';
10 | import type { LocaleTranslationFunctions, TranslateByString } from 'typesafe-i18n';
11 | import { detectLocale as detectLocaleFn } from 'typesafe-i18n/detectors';
12 | import { initExtendDictionary } from 'typesafe-i18n/utils';
13 | import type { Formatters, Locales, Translations, TranslationFunctions } from './i18n-types.js';
14 |
15 | export const baseLocale: Locales = 'en';
16 |
17 | export const locales: Locales[] = ['de', 'en', 'it', 'ru'];
18 |
19 | export const isLocale = (locale: string): locale is Locales => locales.includes(locale as Locales);
20 |
21 | export const loadedLocales: Record = {} as Record;
22 |
23 | export const loadedFormatters: Record = {} as Record;
24 |
25 | export const extendDictionary = initExtendDictionary();
26 |
27 | export const i18nString = (locale: Locales): TranslateByString =>
28 | initI18nString(locale, loadedFormatters[locale]);
29 |
30 | export const i18nObject = (locale: Locales): TranslationFunctions =>
31 | initI18nObject(
32 | locale,
33 | loadedLocales[locale],
34 | loadedFormatters[locale]
35 | );
36 |
37 | export const i18n = (): LocaleTranslationFunctions =>
38 | initI18n(
39 | loadedLocales,
40 | loadedFormatters
41 | );
42 |
43 | export const detectLocale = (...detectors: LocaleDetector[]): Locales =>
44 | detectLocaleFn(baseLocale, locales, ...detectors);
45 |
--------------------------------------------------------------------------------
/src/i18n/it/index.ts:
--------------------------------------------------------------------------------
1 | import en from '$i18n/en/index.js';
2 | import type { Translation } from '../i18n-types.js';
3 |
4 | const it = {
5 | // Fallback
6 | ...(en as Translation),
7 |
8 | log: "Questa protocollazione è stata chiamata da '{fileName}'",
9 | site: {
10 | name: 'Localize URL'
11 | },
12 | pageHome: {
13 | title: 'Pagina iniziale',
14 | welcome: 'Benvenuti nella home page',
15 | apiDescription: 'Chiamate API che non sono interessate dalla libreria',
16 | spectators: '{0} {{spettatore|spettatori}} in diretta',
17 | legend: {
18 | title: 'Leggenda',
19 | correct: 'Collegamento corretto',
20 | fallback: "Collegamento di fallback (conduce a un'altra località)",
21 | vary: 'Collegamento corretto (visibile solo per le impostazioni locali supportate)',
22 | redirect: 'Collegamento non corrispondente, reindirizzamento',
23 | error: 'Non disponibile per questa lingua'
24 | }
25 | },
26 | pageAbout: {
27 | title: 'Chi siamo',
28 | text: 'La pagina Chi siamo saluta.'
29 | },
30 | pageEnglish: {
31 | title: 'Pagina solo in inglese',
32 | text: ''
33 | },
34 | pageNews: {
35 | title: 'Notizia'
36 | },
37 | pageError: {
38 | title404: 'Pagina non trovata',
39 | titleOffline: 'Sembra che tu sia offline',
40 | titleOther: 'Accidenti!',
41 | message404: 'Spiacenti, non siamo riusciti a trovare la pagina richiesta.',
42 | messageNotTranslated: 'Siamo spiacenti, questa pagina non è disponibile nella tua lingua.',
43 | messageOffline: 'Ricarica la pagina dopo aver trovato Internet.',
44 | messageOther: 'Prova a ricaricare la pagina.',
45 | actionHome: 'Ritorna alla pagina iniziale',
46 | actionBaseLocale: 'Mostra questa pagina in inglese'
47 | }
48 | } satisfies Translation;
49 |
50 | export default it;
51 |
--------------------------------------------------------------------------------
/src/i18n/ru/index.ts:
--------------------------------------------------------------------------------
1 | import en from '$i18n/en/index.js';
2 | import type { Translation } from '../i18n-types.js';
3 |
4 | const ru = {
5 | // Fallback
6 | ...(en as Translation),
7 |
8 | log: "Этот лог был вызван из '{fileName}'",
9 | site: {
10 | name: 'Localize URL'
11 | },
12 | pageHome: {
13 | title: 'Главная страница',
14 | welcome: 'Добро пожаловать на главную страницу',
15 | apiDescription: 'Вызовы API, на которые не влияет библиотека',
16 | spectators: '{0} зрител{{ей|ь|я|я|ей}} онлайн',
17 | legend: {
18 | title: 'Легенда',
19 | correct: 'Правильная ссылка',
20 | fallback: 'Запасная ссылка (ведет на другой язык)',
21 | vary: 'Правильная ссылка (видна только для поддерживаемых языков)',
22 | redirect: 'Неправильно составленная ссылка, перенаправление',
23 | error: 'Недоступно для этого языка'
24 | }
25 | },
26 | pageAbout: {
27 | title: 'О нас',
28 | text: 'Страница о нас говорит привет.'
29 | },
30 | pageEnglish: {
31 | title: 'Только английская версия',
32 | text: ''
33 | },
34 | pageNews: {
35 | title: 'Новости'
36 | },
37 | pageError: {
38 | title404: 'Страница не найдена',
39 | titleOffline: 'Похоже, вы не в сети',
40 | titleOther: 'Ой!',
41 | message404: 'К сожалению, мы не смогли найти запрошенную страницу.',
42 | messageNotTranslated: 'К сожалению, эта страница недоступна на вашем языке.',
43 | messageOffline: 'Перезагрузите страницу, как только ваше соединение восстановится.',
44 | messageOther: 'Пожалуйста, попробуйте перезагрузить страницу.',
45 | actionHome: 'Вернуться на главную страницу',
46 | actionBaseLocale: 'Показать эту страницу на английском языке'
47 | }
48 | } satisfies Translation;
49 |
50 | export default ru;
51 |
--------------------------------------------------------------------------------
/src/index.test.ts:
--------------------------------------------------------------------------------
1 | import { afterEach, describe, expect, it, vi } from 'vitest';
2 | import {
3 | PageCheckResult,
4 | buildAlternateLinks,
5 | checkPage,
6 | getLocaleFromUrl,
7 | getLocaleHomeHref,
8 | getPageParams,
9 | href,
10 | initLocalizeUrl,
11 | localizePage,
12 | localizeParam,
13 | matchParam,
14 | resetSettings,
15 | setPageParam,
16 | validatePage,
17 | wrapHref
18 | } from '$lib/index.js';
19 | import { HttpError, Redirect } from '@sveltejs/kit';
20 |
21 | const initDefault = () => {
22 | initLocalizeUrl({
23 | baseLocale: 'en',
24 | locales: ['en', 'ru']
25 | });
26 | };
27 |
28 | const initBasePrefix = () => {
29 | initLocalizeUrl({
30 | baseLocale: 'en',
31 | locales: ['en', 'ru'],
32 | addBaseLocaleToPath: true
33 | });
34 | };
35 |
36 | const initHosts = () => {
37 | initLocalizeUrl({
38 | baseLocale: 'en',
39 | locales: ['en', 'ru', 'it'],
40 | localeHosts: {
41 | en: 'foo.com',
42 | ru: 'foo.ru'
43 | }
44 | });
45 | };
46 |
47 | console.error = () => {
48 | // Suppress console.error messages
49 | };
50 | // But track when it's called
51 | const consoleError = vi.spyOn(console, 'error');
52 |
53 | describe('initLocalizeUrl', () => {
54 | afterEach(() => {
55 | vi.clearAllMocks();
56 | resetSettings();
57 | });
58 | it('with prefix except for the base locale', () => {
59 | initDefault();
60 | expect(getLocaleHomeHref('en', new URL('http://foo.com'))).toBe('http://foo.com/');
61 | expect(getLocaleHomeHref('ru', new URL('http://foo.com'))).toBe('http://foo.com/ru');
62 | });
63 | it('with prefix for every locale', () => {
64 | initBasePrefix();
65 | expect(getLocaleHomeHref('en', new URL('http://foo.com'))).toBe('http://foo.com/en');
66 | expect(getLocaleHomeHref('ru', new URL('http://foo.com'))).toBe('http://foo.com/ru');
67 | });
68 | it('with separate hosts per locale', () => {
69 | initHosts();
70 | expect(getLocaleHomeHref('en', new URL('http://foo.com'))).toBe('http://foo.com/');
71 | expect(getLocaleHomeHref('ru', new URL('http://foo.com'))).toBe('http://foo.ru/');
72 | expect(getLocaleHomeHref('it', new URL('http://foo.com'))).toBe('http://foo.com/it');
73 | });
74 | it('with separate hosts per locale, but without baseLocale host throws', () => {
75 | expect(() => {
76 | initLocalizeUrl({
77 | baseLocale: 'en',
78 | locales: ['en', 'ru'],
79 | localeHosts: {
80 | ru: 'foo.ru'
81 | }
82 | });
83 | }).toThrowError();
84 | });
85 | it('is processed only once', () => {
86 | initLocalizeUrl({
87 | baseLocale: 'en',
88 | locales: ['en', 'ru'],
89 | addBaseLocaleToPath: true
90 | });
91 | initLocalizeUrl({
92 | baseLocale: 'en',
93 | locales: ['en', 'ru'],
94 | addBaseLocaleToPath: false
95 | });
96 | expect(getLocaleHomeHref('en', new URL('http://foo.com/'))).toBe('http://foo.com/en');
97 | });
98 | });
99 |
100 | describe('getLocaleFromUrl', () => {
101 | afterEach(() => {
102 | vi.clearAllMocks();
103 | resetSettings();
104 | });
105 | it('from pathname prefix', () => {
106 | initDefault();
107 | expect(getLocaleFromUrl(new URL('http://foo.com/'))).toBe('en');
108 | expect(getLocaleFromUrl(new URL('http://foo.com/en'))).toBe('en');
109 | expect(getLocaleFromUrl(new URL('http://foo.com/ru'))).toBe('ru');
110 | expect(getLocaleFromUrl(new URL('http://foo.com/zz'))).toBe('en');
111 | });
112 | it('from pathname prefix or host', () => {
113 | initHosts();
114 | expect(getLocaleFromUrl(new URL('http://foo.com/'))).toBe('en');
115 | expect(getLocaleFromUrl(new URL('http://foo.com/en'))).toBe('en');
116 | expect(getLocaleFromUrl(new URL('http://foo.com/ru'))).toBe('ru');
117 | expect(getLocaleFromUrl(new URL('http://foo.ru/'))).toBe('ru');
118 | expect(getLocaleFromUrl(new URL('http://foo.ru/en'))).toBe('en');
119 | expect(getLocaleFromUrl(new URL('http://foo.com/it'))).toBe('it');
120 | });
121 | });
122 |
123 | describe('localizeParam', () => {
124 | afterEach(() => {
125 | vi.clearAllMocks();
126 | resetSettings();
127 | initDefault();
128 | });
129 | it('works', () => {
130 | const localizedParam = localizeParam(1, 'l_about', {
131 | en: 'about-us',
132 | ru: 'o-nas'
133 | });
134 | expect(matchParam('about-us', localizedParam)).toBeTruthy();
135 | expect(matchParam('o-nas', localizedParam)).toBeTruthy();
136 | expect(matchParam('about', localizedParam)).toBeFalsy();
137 | });
138 | });
139 |
140 | describe('localizePage', () => {
141 | afterEach(() => {
142 | vi.clearAllMocks();
143 | resetSettings();
144 | initDefault();
145 | });
146 | it('catches route params', () => {
147 | const LP = localizePage(
148 | new URL('http://foo.com/about/fixed/bar'),
149 | '/[[lang=lang]]/[l_about=l_about]/fixed/[[optional]]'
150 | );
151 | expect(LP._paramPositions).toMatchObject(
152 | new Map([
153 | ['l_about', 1],
154 | ['optional', 3]
155 | ])
156 | );
157 | });
158 | it('accepts custom params', () => {
159 | const LP = localizePage(
160 | new URL('http://foo.com/news/first-post'),
161 | '/[[lang=lang]]/[l_news=l_news]/[post]'
162 | );
163 | setPageParam(LP, 'post', {
164 | en: 'first-post',
165 | ru: 'pervyi-post'
166 | });
167 | const param = {
168 | name: 'post',
169 | position: 2,
170 | values: {
171 | en: 'first-post',
172 | ru: 'pervyi-post'
173 | }
174 | };
175 | expect(LP._customParams).toMatchObject(new Map([['post', param]]));
176 | expect(getPageParams(LP, true)).toMatchObject([param]);
177 | expect(consoleError).toHaveBeenCalledTimes(0);
178 | });
179 | it('prints an error when given unused custom params', () => {
180 | const LP = localizePage(new URL('http://foo.com/about'), '/[[lang=lang]]');
181 | setPageParam(LP, 'post', {
182 | en: 'first-post',
183 | ru: 'pervyi-post'
184 | });
185 | expect(consoleError).toHaveBeenCalledOnce();
186 | });
187 | });
188 |
189 | describe('href', () => {
190 | afterEach(() => {
191 | vi.clearAllMocks();
192 | resetSettings();
193 | });
194 | it('supports basic pathnames', () => {
195 | initDefault();
196 | const LP = localizePage(new URL('http://foo.com/'), '/[[lang=lang]]');
197 | expect(href(LP, 'ru', '/')).toBe('http://foo.com/ru');
198 | expect(consoleError).toHaveBeenCalledTimes(0);
199 | });
200 | it('supports localized params', () => {
201 | initDefault();
202 | localizeParam(1, 'l_about', {
203 | en: 'about-us',
204 | ru: 'o-nas'
205 | });
206 | const LP = localizePage(new URL('http://foo.com/'), '/[[lang=lang]]');
207 | expect(href(LP, 'ru', '/[l_about]')).toBe('http://foo.com/ru/o-nas');
208 | expect(consoleError).toHaveBeenCalledTimes(0);
209 | });
210 | it('supports custom params', () => {
211 | initDefault();
212 | localizeParam(1, 'l_news', {
213 | en: 'news',
214 | ru: 'novosti'
215 | });
216 | const LP = localizePage(
217 | new URL('http://foo.com/ru/novosti/pervyi-post'),
218 | '/[[lang=lang]]/[l_news=l_news]/[post]'
219 | );
220 | setPageParam(LP, 'post', {
221 | en: 'first-post',
222 | ru: 'pervyi-post'
223 | });
224 | expect(href(LP, 'en', '/[l_news]/[post]/edit')).toBe('http://foo.com/news/first-post/edit');
225 | expect(
226 | href(LP, 'en', {
227 | base: '/replaced/replaced/edit',
228 | params: ['l_news', 'post']
229 | })
230 | ).toBe('http://foo.com/news/first-post/edit');
231 | expect(consoleError).toHaveBeenCalledTimes(0);
232 | });
233 | it("prints an error when pathname param isn't registered", () => {
234 | initDefault();
235 | const LP = localizePage(new URL('http://foo.com/'), '/[[lang=lang]]');
236 | expect(href(LP, 'ru', '/[post]')).toBe('');
237 | expect(
238 | href(LP, 'ru', {
239 | base: '/ru/anything',
240 | params: ['l_none']
241 | })
242 | ).toBe('');
243 | expect(consoleError).toHaveBeenCalledTimes(2);
244 | });
245 | it('prints an error when pathname param is in the wrong position', () => {
246 | initDefault();
247 | localizeParam(1, 'l_about', {
248 | en: 'about-us',
249 | ru: 'o-nas'
250 | });
251 | const LP = localizePage(new URL('http://foo.com/'), '/[[lang=lang]]');
252 | expect(href(LP, 'ru', '/bar/[l_about]')).toBe('');
253 | expect(consoleError).toHaveBeenCalledOnce();
254 | });
255 | it('supports fallback', () => {
256 | initDefault();
257 | localizeParam(1, 'l_partial', {
258 | en: 'partial',
259 | de: 'teilweise'
260 | });
261 | const LP = localizePage(new URL('http://foo.com/'), '/[[lang=lang]]');
262 | expect(href(LP, 'ru', '/[l_partial]')).toBe('');
263 | expect(href(LP, 'ru', '/[l_partial]', true)).toBe('http://foo.com/partial');
264 | expect(href(LP, 'ru', '/[l_partial]', 'de')).toBe('http://foo.com/de/teilweise');
265 | expect(href(LP, 'ru', '/[l_partial]', ['it', 'de'])).toBe('http://foo.com/de/teilweise');
266 | expect(consoleError).toHaveBeenCalledTimes(0);
267 | });
268 | it('supports locale hosts', () => {
269 | initHosts();
270 | localizeParam(1, 'l_about', {
271 | en: 'about-us',
272 | ru: 'o-nas',
273 | it: 'chi-siamo'
274 | });
275 | const LP = localizePage(new URL('http://foo.com/'), '/[[lang=lang]]');
276 | expect(href(LP, 'en', '/[l_about]')).toBe('http://foo.com/about-us');
277 | expect(href(LP, 'ru', '/[l_about]')).toBe('http://foo.ru/o-nas');
278 | expect(href(LP, 'it', '/[l_about]')).toBe('http://foo.com/it/chi-siamo');
279 | expect(consoleError).toHaveBeenCalledTimes(0);
280 | });
281 | });
282 |
283 | describe('wrapHref', () => {
284 | afterEach(() => {
285 | vi.clearAllMocks();
286 | resetSettings();
287 | });
288 | it('works', () => {
289 | initDefault();
290 | localizeParam(1, 'l_about', {
291 | en: 'about-us'
292 | });
293 | const LP = localizePage(new URL('http://foo.com/'), '/[[lang=lang]]');
294 | expect(wrapHref(LP, 'en', '/[l_about]', 'test ')).toBe(
295 | 'test '
296 | );
297 | expect(wrapHref(LP, 'ru', '/[l_about]', 'test ')).toBe('');
298 | expect(consoleError).toHaveBeenCalledTimes(0);
299 | });
300 | });
301 |
302 | describe('buildAlternateLinks', () => {
303 | afterEach(() => {
304 | vi.clearAllMocks();
305 | resetSettings();
306 | });
307 | it('builds hreflang and switcher when page has no errors', () => {
308 | initDefault();
309 | localizeParam(1, 'l_about', {
310 | en: 'about-us',
311 | ru: 'o-nas'
312 | });
313 | const LP = localizePage(new URL('http://foo.com/ru/o-nas'), '/[[lang=lang]]/[l_about]');
314 | buildAlternateLinks(LP);
315 | expect(consoleError).toHaveBeenCalledTimes(0);
316 | const expected = new Map([
317 | ['en', 'http://foo.com/about-us'],
318 | ['ru', 'http://foo.com/ru/o-nas']
319 | ]);
320 | expect(LP.hreflang).toMatchObject(expected);
321 | expect(LP.switcher).toMatchObject(expected);
322 | });
323 | it('builds only switcher for pages that have an error', () => {
324 | initDefault();
325 | localizeParam(1, 'l_about', {
326 | en: 'about-us',
327 | ru: 'o-nas'
328 | });
329 | const LP = localizePage(new URL('http://foo.com/ru/o-nas'), '/[[lang=lang]]/[l_about]');
330 | buildAlternateLinks(LP, true);
331 | expect(LP.hreflang).toMatchObject(new Map());
332 | expect(LP.switcher).toMatchObject(
333 | new Map([
334 | ['en', 'http://foo.com/'],
335 | ['ru', 'http://foo.com/ru']
336 | ])
337 | );
338 | expect(consoleError).toHaveBeenCalledTimes(0);
339 | });
340 | it('builds partial hreflang and switcher with homepage fallback for partially localized params', () => {
341 | initDefault();
342 | localizeParam(1, 'l_about', {
343 | en: 'about-us'
344 | });
345 | const LP = localizePage(new URL('http://foo.com/ru/o-nas'), '/[[lang=lang]]/[l_about]');
346 | buildAlternateLinks(LP);
347 | expect(LP.hreflang).toMatchObject(new Map([['en', 'http://foo.com/about-us']]));
348 | expect(LP.switcher).toMatchObject(
349 | new Map([
350 | ['en', 'http://foo.com/about-us'],
351 | ['ru', 'http://foo.com/ru']
352 | ])
353 | );
354 | expect(consoleError).toHaveBeenCalledTimes(0);
355 | });
356 | });
357 |
358 | describe('checkPage', () => {
359 | afterEach(() => {
360 | vi.clearAllMocks();
361 | resetSettings();
362 | });
363 | it('handles correct URLs', () => {
364 | initDefault();
365 | localizeParam(1, 'l_about', {
366 | en: 'about-us',
367 | ru: 'o-nas'
368 | });
369 | const LP = localizePage(new URL('http://foo.com/ru/o-nas'), '/[[lang=lang]]/[l_about]');
370 | expect(checkPage(LP, 'ru')).toMatchObject([PageCheckResult.Success]);
371 | expect(consoleError).toHaveBeenCalledTimes(0);
372 | });
373 | it('handles mismatched URLs', () => {
374 | initDefault();
375 | localizeParam(1, 'l_about', {
376 | en: 'about-us',
377 | ru: 'o-nas'
378 | });
379 | const LP = localizePage(new URL('http://foo.com/ru/about-us'), '/[[lang=lang]]/[l_about]');
380 | expect(checkPage(LP, 'ru')).toMatchObject([
381 | PageCheckResult.Corrected,
382 | 'http://foo.com/ru/o-nas'
383 | ]);
384 | expect(consoleError).toHaveBeenCalledTimes(0);
385 | });
386 | it('handles not localizeable URLs', () => {
387 | initDefault();
388 | localizeParam(1, 'l_about', {
389 | en: 'about-us'
390 | });
391 | const LP = localizePage(new URL('http://foo.com/ru/about-us'), '/[[lang=lang]]/[l_about]');
392 | expect(checkPage(LP, 'ru')).toMatchObject([PageCheckResult.NotLocalized]);
393 | expect(consoleError).toHaveBeenCalledTimes(0);
394 | });
395 | it('handles URLs with search', () => {
396 | initDefault();
397 | localizeParam(1, 'l_about', {
398 | en: 'about-us',
399 | ru: 'o-nas'
400 | });
401 | let LP = localizePage(
402 | new URL('http://foo.com/ru/o-nas?foo=bar'),
403 | '/[[lang=lang]]/[l_about]'
404 | );
405 | expect(checkPage(LP, 'ru')).toMatchObject([PageCheckResult.Success]);
406 | LP = localizePage(new URL('http://foo.com/ru/about?foo=bar'), '/[[lang=lang]]/[l_about]');
407 | expect(checkPage(LP, 'ru')).toMatchObject([
408 | PageCheckResult.Corrected,
409 | 'http://foo.com/ru/o-nas?foo=bar'
410 | ]);
411 | expect(consoleError).toHaveBeenCalledTimes(0);
412 | });
413 | });
414 |
415 | describe('validatePage', () => {
416 | afterEach(() => {
417 | vi.clearAllMocks();
418 | resetSettings();
419 | });
420 | it('handles correct URLs', () => {
421 | initDefault();
422 | localizeParam(1, 'l_about', {
423 | en: 'about-us',
424 | ru: 'o-nas'
425 | });
426 | const LP = localizePage(new URL('http://foo.com/ru/o-nas'), '/[[lang=lang]]/[l_about]');
427 | validatePage(LP);
428 | expect(consoleError).toHaveBeenCalledTimes(0);
429 | });
430 | // it('handles mismatched URLs', () => {
431 | // initDefault();
432 | // localizeParam(1, 'l_about', {
433 | // en: 'about-us',
434 | // ru: 'o-nas'
435 | // });
436 | // const LP = localizePage(new URL('http://foo.com/ru/about-us'), '/[[lang=lang]]/[l_about]');
437 | // expect(consoleError).toHaveBeenCalledTimes(0);
438 | // expect(validatePage(LP)).toThrow(Redirect);
439 | // });
440 | // it('handles not localizeable URLs', () => {
441 | // initDefault();
442 | // localizeParam(1, 'l_about', {
443 | // en: 'about-us'
444 | // });
445 | // const LP = localizePage(new URL('http://foo.com/ru/about-us'), '/[[lang=lang]]/[l_about]');
446 | // expect(consoleError).toHaveBeenCalledTimes(0);
447 | // expect(validatePage(LP)).toThrow(HttpError);
448 | // });
449 | });
450 |
--------------------------------------------------------------------------------
/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | import { error, redirect } from '@sveltejs/kit';
2 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
3 | import type { HttpError, Redirect } from '@sveltejs/kit';
4 |
5 | export type LocalizeUrlSettings = {
6 | /**
7 | * Default locale.
8 | */
9 | baseLocale: string;
10 | /**
11 | * Enabled locales.
12 | */
13 | locales: string[];
14 | /**
15 | * If true, the correct pathname for `/page` is `/baseLocale/page`.
16 | */
17 | addBaseLocaleToPath?: boolean;
18 | /**
19 | * Locales matched by hosts. If specified, the correct path for `example.com/de/page` is `example.de/page`.
20 | */
21 | localeHosts?: Partial>;
22 | };
23 |
24 | const settings: LocalizeUrlSettings & {
25 | /**
26 | * Registered localized params.
27 | */
28 | paramRegistry: Map;
29 | isInitialized: boolean;
30 | } = {
31 | baseLocale: '',
32 | locales: [],
33 | paramRegistry: new Map(),
34 | isInitialized: false
35 | };
36 |
37 | /**
38 | * Initializes the library.
39 | * @param baseLocale Default locale.
40 | * @param locales Enabled locales.
41 | * @param addBaseLocaleToPath If true, the correct pathname for `/page` is `/baseLocale/page`.
42 | * @param localeHosts Locales matched by hosts. If specified, the correct path for
43 | * `example.com/de/page` is `example.de/page`.
44 | */
45 | export function initLocalizeUrl(newSettings: LocalizeUrlSettings) {
46 | if (settings.isInitialized) return;
47 |
48 | if (newSettings.localeHosts) {
49 | if (!(newSettings.baseLocale in newSettings.localeHosts)) {
50 | throw new Error(
51 | `Host for the base locale "${newSettings.baseLocale}" is not specified`
52 | );
53 | }
54 | newSettings.addBaseLocaleToPath = false;
55 | }
56 | Object.assign(settings, newSettings);
57 | settings.isInitialized = true;
58 | }
59 |
60 | /**
61 | * For testing only
62 | */
63 | export function resetSettings() {
64 | settings.baseLocale = '';
65 | settings.locales = [];
66 | settings.paramRegistry.clear();
67 | settings.isInitialized = false;
68 | delete settings.addBaseLocaleToPath;
69 | delete settings.localeHosts;
70 | }
71 |
72 | /** ==== Helpers ==== */
73 |
74 | const isLocale = (locale: string) => settings.locales.includes(locale);
75 |
76 | /**
77 | * Detects URL locale based on the pathname or the host (if `localeHosts` was specified during init).
78 | */
79 | export function getLocaleFromUrl(url: URL): string {
80 | const [, lang] = url.pathname.split('/');
81 | if (isLocale(lang)) return lang;
82 |
83 | if (settings.localeHosts) {
84 | for (const [locale, host] of Object.entries(settings.localeHosts)) {
85 | if (host === url.host) {
86 | return locale;
87 | }
88 | }
89 | }
90 | return settings.baseLocale;
91 | }
92 |
93 | /**
94 | * Builds a URL href for a home page in a specified locale.
95 | * @param currentUrl Current URL to use as a base.
96 | * @param locale Desired locale.
97 | * @param leaveSearch If true, search and hash won't be removed.
98 | */
99 | export function getLocaleHomeHref(locale: string, currentUrl: URL, leaveSearch = false): string {
100 | const url = new URL(currentUrl);
101 | url.pathname = '/';
102 | if (!leaveSearch) {
103 | url.search = '';
104 | url.hash = '';
105 | }
106 | if (settings.localeHosts) {
107 | const host = settings.localeHosts[locale];
108 | if (host) {
109 | // url leads to another domain
110 | url.host = host;
111 | return url.href;
112 | }
113 | }
114 | // add locale prefix
115 | if (settings.addBaseLocaleToPath || settings.baseLocale !== locale) {
116 | url.pathname = `/${locale}`;
117 | }
118 | return url.href;
119 | }
120 |
121 | /** ==== Param ==== */
122 |
123 | export type LocalizedParam = {
124 | /**
125 | * Position in the pathname.
126 | */
127 | position: number;
128 | /**
129 | * Param name.
130 | */
131 | name: string;
132 | /**
133 | * Locales matched by paths.
134 | */
135 | values: Partial>;
136 | };
137 |
138 | /**
139 | * Registers localized param.
140 | * @param position Param segment position in the URL starting with 1.
141 | * @param name Unique param name that matches router param name.
142 | * @param values Supported locales and their corresponding values.
143 | * @returns Localized param.
144 | * @example
145 | * ```typescript
146 | * // src/params/l_faq.ts - for URL: /[l_about]/[l_faq]
147 | * const localizedParam = localizeParam(2, 'l_faq', {
148 | * en: 'faq',
149 | * ru: 'voprosi-i-otveti'
150 | * })
151 | * ```
152 | */
153 | export function localizeParam(
154 | position: number,
155 | name: string,
156 | values: Partial>
157 | ): LocalizedParam {
158 | const result: LocalizedParam = {
159 | name,
160 | position,
161 | values
162 | };
163 | settings.paramRegistry.set(name, result);
164 | return result;
165 | }
166 |
167 | /**
168 | * Checks if the route param value matches any of the localized param values.
169 | * @example
170 | * ```typescript
171 | * export const match: ParamMatcher = (param) => matchParam(param, localizedParam)
172 | * ```
173 | */
174 | export function matchParam(routeParamValue: string, param: LocalizedParam): boolean {
175 | return Object.values(param.values).includes(routeParamValue);
176 | }
177 |
178 | /** ==== Page ==== */
179 |
180 | export type LocalizedPage = {
181 | /**
182 | * Localized URL hrefs by locale for ` ;
186 | /**
187 | * Localized URL hrefs by locale for a language switcher.
188 | * If a href doesn't exist for the locale, it will default to a home page href (`/de`).
189 | */
190 | switcher: Map;
191 | /**
192 | * Current page URL.
193 | */
194 | _url: URL;
195 | /**
196 | * Matched route id.
197 | */
198 | _routeId: string | null;
199 | /**
200 | * Route params and their positions in the pathname.
201 | */
202 | _paramPositions: Map;
203 | /**
204 | * Custom page-specific params like post slugs.
205 | */
206 | _customParams: Map;
207 | /**
208 | * Alternate hrefs need to be rebuilt.
209 | */
210 | _isDirty: boolean;
211 | /**
212 | * If the {@link checkPage} function marked that this page is not available for a requested locale.
213 | */
214 | _isNotAvailableForLocale: boolean;
215 | };
216 |
217 | /**
218 | * Builds new localized page object.
219 | * @param url Current URL.
220 | * @param routeId Matched route id.
221 | */
222 | export function localizePage(url: URL, routeId: string | null): LocalizedPage {
223 | // find matched route params and their positions
224 | const paramPositions = new Map();
225 | if (routeId) {
226 | const parts = routeId.split('/');
227 | for (let pos = 2; pos < parts.length; pos++) {
228 | const part = parts[pos];
229 | if (part[0] !== '[') continue;
230 |
231 | let name = part[1] === '[' ? part.slice(2, -2) : part.slice(1, -1);
232 | name = name.split('=')[0];
233 | paramPositions.set(name, pos - 1);
234 | }
235 | }
236 | return {
237 | hreflang: new Map(),
238 | switcher: new Map(),
239 | _url: new URL(url),
240 | _routeId: routeId,
241 | _paramPositions: paramPositions,
242 | _customParams: new Map(),
243 | _isDirty: true,
244 | _isNotAvailableForLocale: false
245 | };
246 | }
247 |
248 | /**
249 | * Set locales and matching values for dynamic params that depend on the server (like post slugs).
250 | * @param values Locales matched by values. Doesn't have to include all locales.
251 | * @example
252 | * ```typescript
253 | * // Route: /[l_news]/[category]/[post]. [category] and [post] are used to fetch an article from DB
254 | * setPageParam(localizedPage, 'category', post.category.slugs);
255 | * setPageParam(localizedPage, 'post', post.slugs);
256 | * ```
257 | */
258 | export function setPageParam(
259 | page: LocalizedPage,
260 | name: string,
261 | values: Partial>
262 | ) {
263 | const position = page._paramPositions.get(name);
264 | if (!position) {
265 | console.error(
266 | `svelte-localize-url: Param "${name}" isn't used at the route "${page._routeId}"`
267 | );
268 | return;
269 | }
270 |
271 | page._customParams.set(name, {
272 | position,
273 | name,
274 | values
275 | });
276 | page._isDirty = true;
277 | }
278 |
279 | /**
280 | * Retrieves page params (localized and optionally custom).
281 | * @param page Localized page.
282 | * @param includeCustom If true, includes custom params such as slugs.
283 | */
284 | export function getPageParams(page: LocalizedPage, includeCustom = false): LocalizedParam[] {
285 | const params: LocalizedParam[] = [];
286 | for (const [name] of page._paramPositions) {
287 | let param = settings.paramRegistry.get(name);
288 | if (!param && includeCustom) {
289 | param = page._customParams.get(name);
290 | }
291 | if (param) {
292 | params.push(param);
293 | }
294 | }
295 | return params;
296 | }
297 |
298 | /** ==== Paths ==== */
299 |
300 | /**
301 | * Attempts to create a new URL href for the desired locale.
302 | * @param page Localized page.
303 | * @param locale Desired locale.
304 | * @param pathname A new pathname to be localized. Can include localized parameters `[l_param]`.
305 | * @param fallbackLocales If specified, when one of the parameters doesn't support requested locale,
306 | * the function will try to generate a href for the fallback locale instead.
307 | * - `true` - use `baseLocale` as a fallback;
308 | * - `'locale'` - use one locale as a fallback;
309 | * - `['locale1', 'locale2', ]` - use multiple fallback locales.
310 | * @returns Localized href or an empty string if that is not possible.
311 | * @example
312 | * ```typescript
313 | * const pathFAQ = href(localizedPage, 'ru', '/[l_about]/[l_faq]')
314 | * const pathNewsPost = href(localizedPage, 'ru', '/[l_news]/[category]/[post]', ['en', 'de'])
315 | * ```
316 | */
317 | export function href(
318 | page: LocalizedPage,
319 | locale: string,
320 | pathname: string,
321 | fallbackLocales?: boolean | string | string[]
322 | ): string;
323 |
324 | /**
325 | * Attempts to transform a base pathname, replacing its parts according to the params.
326 | * @param page Localized page.
327 | * @param locale Desired locale.
328 | * @param transform Contents:
329 | * - `base` - An old pathname (shouldn't include any excplicitly stated `[l_param]` params).
330 | * - `params` - A list of localized params or their names that should be used.
331 | * @param fallbackLocales If specified, when one of the parameters doesn't support requested locale,
332 | * the function will try to generate a href for the fallback locale instead.
333 | * - `true` - use `baseLocale` as a fallback;
334 | * - `'locale'` - use one locale as a fallback;
335 | * - `['locale1', 'locale2', ]` - use multiple fallback locales.
336 | * @returns Transformed localized href or an empty string if that is not possible.
337 | * @example
338 | * ```typescript
339 | * const pathFAQ = href(localizedPage, 'ru', {
340 | * base: url.pathname,
341 | * params: ['l_about', 'l_faq']
342 | * })
343 | * ```
344 | */
345 | export function href(
346 | page: LocalizedPage,
347 | locale: string,
348 | transform: {
349 | base: string;
350 | params: (LocalizedParam | string)[];
351 | },
352 | fallbackLocales?: boolean | string | string[]
353 | ): string;
354 |
355 | export function href(
356 | page: LocalizedPage,
357 | locale: string,
358 | pathData:
359 | | string
360 | | {
361 | base: string;
362 | params: (LocalizedParam | string)[];
363 | },
364 | fallbackLocales?: boolean | string | string[]
365 | ): string;
366 |
367 | export function href(
368 | page: LocalizedPage,
369 | locale: string,
370 | pathData:
371 | | string
372 | | {
373 | base: string;
374 | params: (LocalizedParam | string)[];
375 | },
376 | fallbackLocale: boolean | string | string[] = false
377 | ): string {
378 | let parts: string[];
379 | let usedParams: (LocalizedParam | string)[];
380 | if (typeof pathData === 'string') {
381 | // new pathname
382 | usedParams = [];
383 | parts = pathData.split('/');
384 |
385 | // find params that are used in the pathname
386 | for (let i = 1; i < parts.length; i++) {
387 | const part = parts[i];
388 | if (part[0] !== '[') continue;
389 |
390 | const name = part.slice(1, -1);
391 | let param = settings.paramRegistry.get(name);
392 | if (!param) {
393 | param = page._customParams.get(name);
394 | }
395 | if (!param) {
396 | console.error(
397 | `svelte-localize-url: Param "${name}" that is inferred from the path "${pathData}"` +
398 | ` doesn't exist at the route "${page._routeId}"`
399 | );
400 | return '';
401 | }
402 | if (param.position !== i) {
403 | console.error(
404 | `svelte-localize-url: Param "${name}" that is inferred from the path "${pathData}"` +
405 | ` is in the wrong position ${i} (${param.position} expected) at the route "${page._routeId}"`
406 | );
407 | return '';
408 | }
409 |
410 | usedParams.push(param);
411 | }
412 | } else {
413 | // build on top of a base pathname
414 | parts = pathData.base.split('/');
415 | usedParams = pathData.params;
416 | }
417 |
418 | if (parts[1] === '' || isLocale(parts[1])) {
419 | // remove locale for now
420 | parts.splice(1, 1);
421 | }
422 |
423 | // replace parts of the original pathname
424 | for (const name of usedParams) {
425 | let param = typeof name === 'string' ? settings.paramRegistry.get(name) : name;
426 | if (!param) {
427 | param = page._customParams.get(name as string);
428 | }
429 | if (!param) {
430 | console.error(
431 | `svelte-localize-url: Param "${name}" doesn't exist at the route "${page._routeId}"`
432 | );
433 | return '';
434 | }
435 |
436 | const value = param.values[locale];
437 | if (value) {
438 | parts[param.position] = value;
439 | continue;
440 | }
441 |
442 | // no path for this locale
443 | if (fallbackLocale) {
444 | if (fallbackLocale === true) {
445 | return href(page, settings.baseLocale, pathData);
446 | }
447 |
448 | if (typeof fallbackLocale === 'string') {
449 | return href(page, fallbackLocale, pathData);
450 | }
451 |
452 | for (const fallback of fallbackLocale) {
453 | if (fallback === locale) continue;
454 |
455 | const fallbackHref = href(page, fallback, pathData);
456 | if (fallbackHref) {
457 | return fallbackHref;
458 | }
459 | }
460 | }
461 |
462 | return '';
463 | }
464 |
465 | // assemble final href
466 | let pathname = parts.join('/');
467 | // copy url without search and hash
468 | const url = new URL('/', page._url);
469 | if (settings.localeHosts) {
470 | let host = settings.localeHosts[locale];
471 | if (!host) {
472 | // host is not specified for a locale - use the base locale host but add the locale in the pathname
473 | host = settings.localeHosts[settings.baseLocale] as string;
474 | pathname = `/${locale}${pathname}`;
475 | }
476 | url.host = host;
477 | url.pathname = pathname;
478 | return url.href;
479 | }
480 |
481 | // all locales that are on the same host to the pathname
482 | if (settings.addBaseLocaleToPath || settings.baseLocale !== locale) {
483 | pathname = `/${locale}${pathname}`;
484 | }
485 | url.pathname = pathname;
486 | return url.href;
487 | }
488 |
489 | /**
490 | * A helper function that acts similarly to the {@link href} but instead returns a string that contains
491 | * the resulting href.
492 | * @param page Localized page.
493 | * @param locale Desired locale.
494 | * @param pathname A new pathname to be localized. Can include localized parameters `[l_param]`.
495 | * @param text A text that will be returned if the path is localized successfully.
496 | * Must contain a `%href%` piece that will be replaced with the localized href.
497 | * @param fallbackLocales If specified, when one of the parameters doesn't support requested locale,
498 | * the function will try to generate a href for the fallback locale instead.
499 | * - `true` - use `baseLocale` as a fallback;
500 | * - `'locale'` - use one locale as a fallback;
501 | * - `['locale1', 'locale2', ]` - use multiple fallback locales.
502 | * @example
503 | * ```svelte
504 | * {@html wrapHref(localizedPage, 'ru', '/[l_about]/[l_faq]', `${$LL.pageFAQ()} `)}
505 | * ```
506 | */
507 | export function wrapHref(
508 | page: LocalizedPage,
509 | locale: string,
510 | pathname: string,
511 | text: string,
512 | fallbackLocales: boolean | string | string[] = false
513 | ): string {
514 | const localizedPath = href(page, locale, pathname, fallbackLocales);
515 | if (!localizedPath) return '';
516 |
517 | return text.replace('%href%', localizedPath);
518 | }
519 |
520 | /**
521 | * Regenerates alternate links and returns localized page.
522 | * @param page Localized page.
523 | * @param pageError If there is a page error
524 | */
525 | export function buildAlternateLinks(
526 | page: LocalizedPage,
527 | pageError: App.Error | boolean | null = false
528 | ): LocalizedPage {
529 | if (!page._isDirty) return page;
530 | page._isDirty = false;
531 |
532 | // get localized params and custom slugs
533 | const params = getPageParams(page, true);
534 |
535 | // regenerate alternate links
536 | page.switcher.clear();
537 | page.hreflang.clear();
538 |
539 | if (page._isNotAvailableForLocale || !!pageError) {
540 | // only generate language switcher links
541 | for (const locale of settings.locales) {
542 | page.switcher.set(locale, getLocaleHomeHref(locale, page._url));
543 | }
544 | return page;
545 | }
546 |
547 | for (const locale of settings.locales) {
548 | const localizedPath = href(page, locale, {
549 | base: page._url.pathname,
550 | params
551 | });
552 | if (localizedPath) {
553 | page.hreflang.set(locale, localizedPath);
554 | // leave search and hash in switcher for better usability
555 | const switcherUrl = new URL(localizedPath);
556 | switcherUrl.search = page._url.search;
557 | // it's better to update hash dynamically in the language switcher component
558 | // switcherUrl.hash = page._url.hash;
559 | page.switcher.set(locale, switcherUrl.href);
560 | continue;
561 | }
562 | // no path for locale, point to the home page
563 | page.switcher.set(locale, getLocaleHomeHref(locale, page._url));
564 | }
565 |
566 | return page;
567 | }
568 |
569 | /** ==== Validation ==== */
570 |
571 | export enum PageCheckResult {
572 | Success = 0,
573 | Corrected = 1,
574 | NotLocalized = 2
575 | }
576 |
577 | /**
578 | * Checks if the page URL is correct for a given locale.
579 | * @param page Localized page.
580 | * @param locale Current locale.
581 | * @returns Check result, optionally followed by a correct path (if redirect is needed).
582 | */
583 | export function checkPage(
584 | page: LocalizedPage,
585 | locale: string
586 | ): [PageCheckResult.Corrected, string] | [PageCheckResult] {
587 | const correctHref = href(page, locale, {
588 | base: page._url.pathname,
589 | params: getPageParams(page, true)
590 | });
591 |
592 | if (!correctHref) {
593 | // not available for this locale
594 | page._isNotAvailableForLocale = true;
595 | return [PageCheckResult.NotLocalized];
596 | }
597 |
598 | const correctUrl = new URL(correctHref);
599 | if (correctUrl.host !== page._url.host || correctUrl.pathname !== page._url.pathname) {
600 | correctUrl.search = page._url.search;
601 | return [PageCheckResult.Corrected, correctUrl.href];
602 | }
603 |
604 | return [PageCheckResult.Success];
605 | }
606 |
607 | export type ValidatePageOptions = {
608 | /**
609 | * Default: 301. Which HTTP code to use when redirecting to a corrected localized URL.
610 | */
611 | redirectCode?: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308;
612 | /**
613 | * Allows to specify data that will be passed with the 404 error, like a
614 | * "This page isn't available in your language" message.
615 | */
616 | notFound?: string | App.Error;
617 | };
618 |
619 | /**
620 | * Validates the current page URL.
621 | * Throws a 404 error if there is no version of the page for the locale.
622 | * Redirects to a corrected URL if necessary.
623 | * @param currentUrl - Current URL from the `load()` function.
624 | * @param options.redirectCode Default: 301. Which HTTP code to use when redirecting to a corrected localized URL.
625 | * @param options.notFound Allows to specify data that will be passed with the 404 error, like a
626 | * "This page isn't available in your language" message.
627 | * @see {@link HttpError}, {@link Redirect}
628 | */
629 | export function validatePage(page: LocalizedPage, options?: ValidatePageOptions) {
630 | const locale = getLocaleFromUrl(page._url);
631 | const [status, correctPath] = checkPage(page, locale);
632 | if (status === PageCheckResult.Success) {
633 | return;
634 | }
635 |
636 | if (status === PageCheckResult.Corrected) {
637 | throw redirect(options?.redirectCode ?? 301, correctPath as string);
638 | }
639 |
640 | // not available for this locale
641 | throw error(404, options?.notFound);
642 | }
643 |
--------------------------------------------------------------------------------
/src/params/l_about.ts:
--------------------------------------------------------------------------------
1 | import { localizeParam, matchParam } from '$lib/index.js';
2 | import type { ParamMatcher } from '@sveltejs/kit';
3 |
4 | const localizedParam = localizeParam(1, 'l_about', {
5 | en: 'about',
6 | de: 'uber-uns',
7 | it: 'chi-samo',
8 | ru: 'o-nas'
9 | });
10 |
11 | export const match: ParamMatcher = (param) => matchParam(param, localizedParam);
12 |
--------------------------------------------------------------------------------
/src/params/l_english.ts:
--------------------------------------------------------------------------------
1 | import { localizeParam, matchParam } from '$lib/index.js';
2 | import type { ParamMatcher } from '@sveltejs/kit';
3 |
4 | const localizedParam = localizeParam(2, 'l_english', {
5 | en: 'english-only'
6 | });
7 |
8 | export const match: ParamMatcher = (param) => matchParam(param, localizedParam);
9 |
--------------------------------------------------------------------------------
/src/params/l_news.ts:
--------------------------------------------------------------------------------
1 | import { localizeParam, matchParam } from '$lib/index.js';
2 | import type { ParamMatcher } from '@sveltejs/kit';
3 |
4 | const localizedParam = localizeParam(1, 'l_news', {
5 | en: 'news',
6 | de: 'nachricht',
7 | it: 'notizia',
8 | ru: 'novosti'
9 | });
10 |
11 | export const match: ParamMatcher = (param) => matchParam(param, localizedParam);
12 |
--------------------------------------------------------------------------------
/src/params/lang.ts:
--------------------------------------------------------------------------------
1 | import { isLocale } from '$i18n/i18n-util.js';
2 | import type { ParamMatcher } from '@sveltejs/kit';
3 |
4 | // only accept valid languages as a segment in the URL
5 | export const match: ParamMatcher = (param) => isLocale(param);
6 |
--------------------------------------------------------------------------------
/src/routes/+error.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 | {#if $page.status === 404}
12 | {$LL.pageError.title404()}
13 |
14 | {#if !$page.error?.message || $page.error?.message === 'Not Found'}
15 |
16 | {$LL.pageError.message404()}
17 | {:else}
18 | {$page.error.message}
19 | {/if}
20 |
21 | {:else if !online}
22 | {$LL.pageError.titleOffline()}
23 | {$LL.pageError.messageOffline()}
24 | {:else}
25 | {$LL.pageError.titleOther()}
26 |
27 | {#if !$page.error?.message || $page.error?.message === 'Internal Error'}
28 |
29 | {$LL.pageError.messageOther()}
30 | {:else}
31 | {$page.error.message}
32 | {/if}
33 |
34 | {/if}
35 |
36 | {#if $page.status === 404 || online}
37 |
38 | {#if $page.error?.link}
39 |
40 | {$page.error.linkText}
41 |
42 | {/if}
43 |
44 | {$LL.pageError.actionHome()}
45 |
46 | {/if}
47 |
--------------------------------------------------------------------------------
/src/routes/+layout.server.ts:
--------------------------------------------------------------------------------
1 | import type { LayoutServerLoad } from './$types.js';
2 |
3 | export const load: LayoutServerLoad = ({ locals: { locale, LL } }) => {
4 | console.info(LL.log({ fileName: 'routes/+layout.server.ts' }));
5 |
6 | // pass locale information from "server-context" to "shared server + client context"
7 | return { locale };
8 | };
9 |
--------------------------------------------------------------------------------
/src/routes/+layout.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
30 | {$page.data.title || $LL.site.name()}
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/routes/+layout.ts:
--------------------------------------------------------------------------------
1 | import LL, { setLocale, locale as storeLocale } from '$i18n/i18n-svelte.js';
2 | import { loadLocaleAsync } from '$i18n/i18n-util.async.js';
3 | import { get } from 'svelte/store';
4 | import { initLocalizeUrl, localizePage } from '$lib/index.js';
5 | import { baseLocale, locales } from '$i18n/i18n-util.js';
6 | import { browser } from '$app/environment';
7 | import type { LayoutLoad } from './$types.js';
8 |
9 | export const load: LayoutLoad = async ({ url, route, data: { locale } }) => {
10 | // initialize Localize URL library for client (already initialized on server)
11 | initLocalizeUrl({
12 | baseLocale,
13 | locales
14 | });
15 |
16 | /**
17 | * Make sure that we're not overriding clientside typesafe-i18n locale when preloading pages on link hover.
18 | * An alternative solution is setting `data-sveltekit-preload-data` on the `body` tag to `tap` of `off`.
19 | */
20 | let loadLocale = true;
21 | if (browser) {
22 | const $storeLocale = get(storeLocale);
23 | if ($storeLocale !== undefined) {
24 | locale = $storeLocale;
25 | loadLocale = false;
26 | }
27 | }
28 |
29 | if (loadLocale) {
30 | // load dictionary into memory
31 | await loadLocaleAsync(locale);
32 | }
33 |
34 | // if you need to output a localized string in a `load` function,
35 | // you always need to call `setLocale` right before you access the `LL` store
36 | setLocale(locale);
37 | // get the translation functions value from the store
38 | const $LL = get(LL);
39 | console.info($LL.log({ fileName: 'routes/+layout.ts' }));
40 |
41 | /**
42 | * We need to create localized page exactly here at the top layer ('routes/+layout.ts'),
43 | * so even if during page validation a 404 will be thrown, layout and error page could still access it.
44 | */
45 | const LP = localizePage(url, route.id);
46 |
47 | // pass locale and localized page to the "rendering context"
48 | return { locale, LP };
49 | };
50 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/+layout.ts:
--------------------------------------------------------------------------------
1 | import { href, validatePage, getPageParams } from '$lib/index.js';
2 | import { get } from 'svelte/store';
3 | import LL, { setLocale } from '$i18n/i18n-svelte.js';
4 | import { baseLocale } from '$i18n/i18n-util.js';
5 | import type { LayoutLoad } from './$types.js';
6 |
7 | export const load: LayoutLoad = async ({ parent, url }) => {
8 | // wait for parent `+layout.ts` to load dictionary and pass locale information
9 | const { locale, LP } = await parent();
10 |
11 | // if you need to output a localized string in a `load` function,
12 | // you always need to call `setLocale` right before you access the `LL` store
13 | setLocale(locale);
14 | // get the translation functions value from the store
15 | const $LL = get(LL);
16 | console.info($LL.log({ fileName: 'routes/[[lang=lang]]/+layout.ts' }));
17 |
18 | /**
19 | * Create fallback path that will be suggested to a visitor if the requested page isn't available
20 | * for their locale (404).
21 | */
22 | const fallbackPath = href(LP, baseLocale, {
23 | base: url.pathname,
24 | params: getPageParams(LP)
25 | });
26 |
27 | /**
28 | * Localized page validation should happen exactly here in the `routes/[[lang=lang]]/+layout.ts` and NOT in the
29 | * `routes/+layout.ts`. There are 2 reasons for this:
30 | * 1. We shouldn't validate paths like `/api`.
31 | * 2. "If the error occurs inside a load function in `+layout(.server).js`, the closest error boundary in the tree
32 | * is an `+error.svelte` file above that layout (not next to it)." - https://kit.svelte.dev/docs/errors#responses
33 | * In other words, when a 404 is thrown here, the `routes/+error.svelte` layout will be used.
34 | * If we place validation in the `routes/+layout.ts`, there won't be an error layout to use, so SvelteKit will
35 | * use a default empty white page with a 404 code.
36 | */
37 | validatePage(LP, {
38 | notFound: {
39 | message: $LL.pageError.messageNotTranslated(),
40 | link: fallbackPath,
41 | linkText: $LL.pageError.actionBaseLocale()
42 | }
43 | });
44 |
45 | // pass locale and localized page to the "rendering context"
46 | return { locale, LP };
47 | };
48 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/+page.svelte:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 | {$LL.pageHome.welcome()}
27 |
28 |
29 |
30 |
{$LL.pageHome.legend.title()}
31 |
32 | {$LL.pageHome.legend.correct()}
33 | {$LL.pageHome.legend.fallback()}
34 | {$LL.pageHome.legend.vary()}
35 | {$LL.pageHome.legend.redirect()}
36 | {$LL.pageHome.legend.error()}
37 |
38 |
{$LL.pageHome.apiDescription()}
39 |
{$LL.pageHome.spectators(spectators)}
40 |
41 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/+page.ts:
--------------------------------------------------------------------------------
1 | import type { PageLoad } from './$types.js';
2 | import LL, { setLocale } from '$i18n/i18n-svelte.js';
3 | import { get } from 'svelte/store';
4 |
5 | export const load: PageLoad = async ({ parent }) => {
6 | // wait for `+layout.ts` to load dictionary and pass locale information
7 | const { locale } = await parent();
8 |
9 | // if you need to output a localized string in a `load` function,
10 | // you always need to call `setLocale` right before you access the `LL` store
11 | setLocale(locale);
12 | // get the translation functions value from the store
13 | const $LL = get(LL);
14 | console.info($LL.log({ fileName: 'routes/[[lang=lang]]/+page.ts' }));
15 |
16 | return {
17 | title: $LL.pageHome.title()
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_about=l_about]/+page.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | {$LL.pageAbout.title()}
13 |
14 |
15 | {$LL.pageAbout.text()}
16 |
17 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_about=l_about]/+page.ts:
--------------------------------------------------------------------------------
1 | import type { PageLoad } from './$types.js';
2 | import LL, { setLocale } from '$i18n/i18n-svelte.js';
3 | import { get } from 'svelte/store';
4 |
5 | export const load: PageLoad = async ({ parent }) => {
6 | // wait for `+layout.ts` to load dictionary and pass locale information
7 | const { locale } = await parent();
8 |
9 | // if you need to output a localized string in a `load` function,
10 | // you always need to call `setLocale` right before you access the `LL` store
11 | setLocale(locale);
12 | // get the translation functions value from the store
13 | const $LL = get(LL);
14 | console.info($LL.log({ fileName: 'routes/[[lang=lang]]/[l_about=l_about]/+page.ts' }));
15 |
16 | return {
17 | title: $LL.pageAbout.title()
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_about=l_about]/[l_english=l_english]/+page.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | {$LL.pageEnglish.title()}
13 |
14 |
15 | {$LL.pageEnglish.text()}
16 |
17 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_about=l_about]/[l_english=l_english]/+page.ts:
--------------------------------------------------------------------------------
1 | import type { PageLoad } from './$types.js';
2 | import LL, { setLocale } from '$i18n/i18n-svelte.js';
3 | import { get } from 'svelte/store';
4 |
5 | export const load: PageLoad = async ({ parent }) => {
6 | // wait for `+layout.ts` to load dictionary and pass locale information
7 | const { locale } = await parent();
8 |
9 | // if you need to output a localized string in a `load` function,
10 | // you always need to call `setLocale` right before you access the `LL` store
11 | setLocale(locale);
12 | // get the translation functions value from the store
13 | const $LL = get(LL);
14 | console.info(
15 | $LL.log({
16 | fileName: 'routes/[[lang=lang]]/[l_about=l_about]/[l_english=l_english]/+page.ts'
17 | })
18 | );
19 |
20 | return {
21 | title: $LL.pageEnglish.title()
22 | };
23 | };
24 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_news=l_news]/+page.server.ts:
--------------------------------------------------------------------------------
1 | import { getPostsByLocale } from '$utils/db.js';
2 | import type { PageServerLoad } from './$types.js';
3 |
4 | export const load: PageServerLoad = async ({ locals: { locale, LL } }) => {
5 | console.info(LL.log({ fileName: 'routes/[[lang=lang]]/[l_news=l_news]/+page.server.ts' }));
6 |
7 | return {
8 | posts: await getPostsByLocale(locale)
9 | };
10 | };
11 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_news=l_news]/+page.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 | {$LL.pageNews.title()}
16 |
17 |
18 | {#if data.posts}
19 |
20 | {#each data.posts as post}
21 |
26 | {post.title}
29 |
30 | {/each}
31 |
32 | {/if}
33 |
34 |
44 |
45 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_news=l_news]/+page.ts:
--------------------------------------------------------------------------------
1 | import type { PageLoad } from './$types.js';
2 | import LL, { setLocale } from '$i18n/i18n-svelte.js';
3 | import { get } from 'svelte/store';
4 |
5 | export const load: PageLoad = async ({ parent, data: { posts } }) => {
6 | // wait for `+layout.ts` to load dictionary and pass locale information
7 | const { locale } = await parent();
8 |
9 | // if you need to output a localized string in a `load` function,
10 | // you always need to call `setLocale` right before you access the `LL` store
11 | setLocale(locale);
12 | // get the translation functions value from the store
13 | const $LL = get(LL);
14 | console.info($LL.log({ fileName: 'routes/[[lang=lang]]/[l_about=l_about]/+page.ts' }));
15 |
16 | return {
17 | title: $LL.pageNews.title(),
18 | posts
19 | };
20 | };
21 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_news=l_news]/[post]/+page.server.ts:
--------------------------------------------------------------------------------
1 | import { getPostBySlug } from '$utils/db.js';
2 | import type { PageServerLoad } from './$types.js';
3 |
4 | export const load: PageServerLoad = async ({ params, locals: { LL } }) => {
5 | console.info(
6 | LL.log({ fileName: 'routes/[[lang=lang]]/[l_news=l_news]/[post]/+page.server.ts' })
7 | );
8 |
9 | return {
10 | post: await getPostBySlug(params.post)
11 | };
12 | };
13 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_news=l_news]/[post]/+page.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 | {data.post.title}
17 |
18 |
19 | {data.post.content}
20 |
21 |
--------------------------------------------------------------------------------
/src/routes/[[lang=lang]]/[l_news=l_news]/[post]/+page.ts:
--------------------------------------------------------------------------------
1 | import LL, { setLocale } from '$i18n/i18n-svelte.js';
2 | import { get } from 'svelte/store';
3 | import type { PageLoad } from './$types.js';
4 | import { error } from '@sveltejs/kit';
5 | import { getPageParams, href, setPageParam, validatePage } from '$lib/index.js';
6 | import { baseLocale } from '$i18n/i18n-util.js';
7 |
8 | export const load: PageLoad = async ({ url, parent, data: { post } }) => {
9 | // wait for `+layout.ts` to load dictionary and pass locale information
10 | const { locale, LP } = await parent();
11 |
12 | // if you need to output a localized string in a `load` function,
13 | // you always need to call `setLocale` right before you access the `LL` store
14 | setLocale(locale);
15 | // get the translation functions value from the store
16 | const $LL = get(LL);
17 | console.info($LL.log({ fileName: 'routes/[[lang=lang]]/[l_about=l_about]/[post]/+page.ts' }));
18 |
19 | if (!post) {
20 | throw error(404);
21 | }
22 |
23 | /**
24 | * This page depends on the slug param `post`. And in our case this slug is localized too.
25 | * Which is why we need to set a page param with the allowed values.
26 | */
27 | setPageParam(LP, 'post', post.slugs);
28 |
29 | /**
30 | * Create fallback path that will be suggested to a visitor if the requested post isn't available
31 | * for their locale (404).
32 | */
33 | const fallbackPath = href(LP, baseLocale, {
34 | base: url.pathname,
35 | params: getPageParams(LP, true)
36 | });
37 |
38 | /**
39 | * Since we added a new param we need to revalidate the page.
40 | * Just like before this may result in a redirect or a 404 page.
41 | */
42 | validatePage(LP, {
43 | notFound: {
44 | message: $LL.pageError.messageNotTranslated(),
45 | link: fallbackPath,
46 | linkText: $LL.pageError.actionBaseLocale()
47 | }
48 | });
49 |
50 | return {
51 | title: post.title,
52 | post
53 | };
54 | };
55 |
--------------------------------------------------------------------------------
/src/routes/api/spectators/+server.ts:
--------------------------------------------------------------------------------
1 | import { json } from '@sveltejs/kit';
2 | import type { RequestHandler } from './$types.js';
3 |
4 | export const GET: RequestHandler = async ({ url, locals: { LL } }) => {
5 | // no real data, just a simulation ;)
6 | const oldSpectators = Number(url.searchParams.get('oldSpectators') ?? '0');
7 | let spectators = oldSpectators * 2 + 1;
8 | if (spectators > 100_000) {
9 | spectators = 0;
10 | }
11 |
12 | console.info(LL.log({ fileName: 'routes/api/+server.ts' }));
13 |
14 | return json({ spectators });
15 | };
16 |
--------------------------------------------------------------------------------
/src/styles/global.scss:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | html {
6 | height: 100%;
7 | }
8 |
9 | body {
10 | margin: 0;
11 | padding: 0;
12 | font-family: Arial, Helvetica, sans-serif;
13 | background-color: #ff3e001a;
14 | overscroll-behavior: none;
15 | height: 100%;
16 | display: flex;
17 | flex-direction: column;
18 | }
19 |
20 | header {
21 | background-color: white;
22 | min-height: 100px;
23 | display: flex;
24 | justify-content: space-between;
25 | align-items: center;
26 | padding: 1rem 1.5rem;
27 | font-family: monospace;
28 | gap: 0.5rem 1.5rem;
29 | flex-shrink: 0;
30 |
31 | @media (max-width: 1024px) {
32 | & {
33 | flex-wrap: wrap;
34 | }
35 | }
36 |
37 | > a {
38 | flex-shrink: 0;
39 | text-decoration: none;
40 |
41 | h1 {
42 | font-size: 1.25rem;
43 | }
44 | }
45 |
46 | ul {
47 | list-style-type: none;
48 | display: flex;
49 | gap: 0.5rem;
50 | padding: 0;
51 |
52 | li > a {
53 | all: initial;
54 | cursor: pointer;
55 | padding: 0.5rem;
56 | color: #444;
57 |
58 | &.active {
59 | color: #ff3e00;
60 | border-bottom: 1px solid;
61 | }
62 | }
63 |
64 | &.menu {
65 | flex-wrap: wrap;
66 |
67 | li > a {
68 | background: #fdfdfd;
69 | display: block;
70 | border: 1px solid #ddd;
71 | }
72 |
73 | @media (max-width: 1024px) {
74 | & {
75 | order: 1;
76 | }
77 | }
78 |
79 | @media (max-width: 576px) {
80 | li {
81 | flex-basis: 100%;
82 | }
83 | }
84 | }
85 |
86 | &.switcher {
87 | flex-shrink: 0;
88 | }
89 | }
90 | }
91 |
92 | .center-list {
93 | margin: 0 auto 16px;
94 | display: table;
95 | text-align: left;
96 | line-height: 1.5;
97 | padding-left: 2rem;
98 |
99 | > li {
100 | margin-bottom: 0.5em;
101 | }
102 | }
103 |
104 | .link-hint:before {
105 | font-size: 14px;
106 | padding: 2px 5px;
107 | margin-right: 5px;
108 | border: 1px solid;
109 | }
110 | .link-hint--success:before {
111 | content: '200';
112 | background: #bbffb1;
113 | border-color: #3da027;
114 | }
115 | .link-hint--fallback:before {
116 | content: '200F';
117 | background: #b1f6ff;
118 | border-color: #2798a0;
119 | }
120 | .link-hint--vary:before {
121 | content: '200V';
122 | background: #e1b1ff;
123 | border-color: #7a27a0;
124 | }
125 | .link-hint--redirect:before {
126 | content: '301';
127 | background: #fdffb1;
128 | border-color: #a0a027;
129 | }
130 | .link-hint--error:before {
131 | content: '404';
132 | background: #ffbbb1;
133 | border-color: #a03d27;
134 | }
135 |
136 | h1 {
137 | color: #ff3e00;
138 | }
139 |
140 | h2 {
141 | margin: 2rem 0;
142 | text-align: center;
143 | }
144 |
145 | h3 {
146 | margin: 1.5rem 0;
147 | text-align: center;
148 | }
149 |
150 | main {
151 | padding: 1rem 1.5rem;
152 | overflow: hidden;
153 | color: #444;
154 | flex-shrink: 0;
155 | flex-grow: 1;
156 | }
157 |
158 | .content {
159 | text-align: center;
160 | }
161 |
162 | footer {
163 | background: #ffffff;
164 | padding: 1.5rem;
165 | margin-top: 1.5rem;
166 | flex-shrink: 0;
167 | text-align: center;
168 |
169 | a {
170 | text-decoration: none;
171 | color: #ff3e00;
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/src/utils/db.ts:
--------------------------------------------------------------------------------
1 | import type { Locales } from '$i18n/i18n-types.js';
2 |
3 | // Simulates DB
4 | const posts = [
5 | {
6 | id: 1,
7 | titles: {
8 | en: 'First post',
9 | de: 'Erster Beitrag',
10 | it: 'Primo post',
11 | ru: 'Первый пост'
12 | },
13 | slugs: {
14 | en: 'first-post',
15 | de: 'erster-beitrag',
16 | it: 'primo-post',
17 | ru: 'perviy-post'
18 | },
19 | contents: {
20 | en: 'First post says hello!',
21 | de: 'Erster Beitrag sagt Hallo!',
22 | it: 'Il primo post ti saluta!',
23 | ru: 'Первый пост говорит привет!'
24 | }
25 | },
26 | {
27 | id: 2,
28 | titles: {
29 | en: 'Second post',
30 | de: 'Zweiter Beitrag',
31 | it: 'Secondo post',
32 | ru: 'Второй пост'
33 | },
34 | slugs: {
35 | en: 'second-post',
36 | de: 'zweiter-beitrag',
37 | it: 'secondo-post',
38 | ru: 'vtoroy-post'
39 | },
40 | contents: {
41 | en: 'Second post says hello!',
42 | de: 'Zweiter Beitrag sagt Hallo!',
43 | it: 'Il secondo post ti saluta!',
44 | ru: 'Второй пост говорит привет!'
45 | }
46 | },
47 | {
48 | id: 3,
49 | titles: {
50 | en: 'English-only post'
51 | },
52 | slugs: {
53 | en: 'english-only-post'
54 | },
55 | contents: {
56 | en: 'English-only post says hello!'
57 | }
58 | }
59 | ];
60 |
61 | export type Post = {
62 | id: number;
63 | title: string;
64 | content: string;
65 | slugs: Partial>;
66 | locale: Locales;
67 | };
68 |
69 | export async function getPostsByLocale(locale: Locales): Promise {
70 | const results: Post[] = [];
71 | for (const post of posts) {
72 | if (!(locale in post.slugs)) continue;
73 |
74 | results.push({
75 | id: post.id,
76 | title: post.titles[locale] as string,
77 | content: post.contents[locale] as string,
78 | slugs: post.slugs,
79 | locale
80 | });
81 | }
82 |
83 | return results;
84 | }
85 |
86 | export async function getPostBySlug(slug: string): Promise {
87 | for (const post of posts) {
88 | for (const [locale, postSlug] of Object.entries(post.slugs)) {
89 | if (postSlug !== slug) continue;
90 |
91 | return {
92 | id: post.id,
93 | title: post.titles[locale as Locales] as string,
94 | content: post.contents[locale as Locales] as string,
95 | slugs: post.slugs,
96 | locale: locale as Locales
97 | };
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rinart73/sveltekit-localize-url/4007f0715f8e1234c1ce52e0f8f88a227b916a90/static/favicon.png
--------------------------------------------------------------------------------
/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from '@sveltejs/adapter-auto';
2 | import { vitePreprocess } from '@sveltejs/kit/vite';
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors
7 | // for more information about preprocessors
8 | preprocess: vitePreprocess(),
9 |
10 | kit: {
11 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
12 | // If your environment is not supported or you settled on a specific environment, switch out the adapter.
13 | // See https://kit.svelte.dev/docs/adapters for more information about adapters.
14 | adapter: adapter(),
15 | alias: {
16 | $i18n: 'src/i18n',
17 | $components: 'src/components',
18 | $utils: 'src/utils'
19 | }
20 | }
21 | };
22 |
23 | export default config;
24 |
--------------------------------------------------------------------------------
/tests/test.ts:
--------------------------------------------------------------------------------
1 | import { expect, test } from '@playwright/test';
2 |
3 | test('placeholder', async ({ page }) => {
4 | // await page.goto('/');
5 | // await expect(page.getByRole('heading', { name: 'Welcome to SvelteKit' })).toBeVisible();
6 | });
7 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "resolveJsonModule": true,
9 | "skipLibCheck": true,
10 | "sourceMap": true,
11 | "strict": true,
12 | "moduleResolution": "NodeNext"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from '@sveltejs/kit/vite';
2 | import { defineConfig } from 'vitest/config';
3 |
4 | export default defineConfig({
5 | plugins: [sveltekit()],
6 | test: {
7 | include: ['src/**/*.{test,spec}.{js,ts}']
8 | }
9 | });
10 |
--------------------------------------------------------------------------------