├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── docs ├── bunny.mp4 ├── github.png ├── index.html └── npm.png ├── package-lock.json ├── package.json ├── rollup.config.js ├── rollup.preview.config.js ├── src-ts ├── stack-router.ts ├── transition-functions.ts ├── types.ts └── utils.ts ├── src ├── App.svelte ├── StackRouter.svelte ├── _routes.js ├── components │ └── Links.svelte ├── index.d.ts ├── index.js ├── pages │ ├── AsyncComponent.svelte │ ├── Guarded.svelte │ ├── Home.svelte │ ├── NotFound.svelte │ ├── Redirect.svelte │ ├── Resumable.svelte │ ├── Throwaway.svelte │ └── _Layout.svelte ├── preview.js ├── stores │ ├── async-component-loaded.js │ └── you-shall-pass.js └── style │ └── main.css └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | insert_final_newline = true 7 | indent_style = tab 8 | indent_size = 2 9 | 10 | [*.{yml,yaml}] 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | docs/ 2 | dist/ 3 | /*.js 4 | /*.mjs 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | es2020: true, 4 | node: true, 5 | }, 6 | extends: [ 7 | 'airbnb-base', 8 | 'plugin:@typescript-eslint/eslint-recommended', 9 | 'plugin:@typescript-eslint/recommended', 10 | ], 11 | parser: '@typescript-eslint/parser', 12 | parserOptions: { 13 | ecmaVersion: 11, 14 | sourceType: 'module', 15 | }, 16 | plugins: [ 17 | '@typescript-eslint', 18 | ], 19 | rules: { 20 | 'no-underscore-dangle': 'off', 21 | 'import/extensions': 'off', 22 | 'no-console': 'off', 23 | 'import/prefer-default-export': 'off', 24 | 'no-plusplus': 'off', 25 | '@typescript-eslint/no-empty-function': 'off', 26 | 'max-classes-per-file': 'off', 27 | 'camelcase': 'off', 28 | 'no-tabs': [ 29 | 'error', 30 | { 31 | allowIndentationTabs: true, 32 | }, 33 | ], 34 | indent: [ 35 | 'error', 36 | 'tab', 37 | { 38 | SwitchCase: 1, 39 | }, 40 | ], 41 | 'max-len': ['error', { ignoreComments: true, code: 160 }], 42 | '@typescript-eslint/no-unused-vars': [ 43 | 'error', 44 | { argsIgnorePattern: '^_' }, 45 | ], 46 | '@typescript-eslint/no-non-null-assertion': 'off', 47 | 'class-methods-use-this': 'off', 48 | '@typescript-eslint/no-explicit-any': 'off', 49 | '@typescript-eslint/ban-types': 'off', 50 | 'no-useless-constructor': 'off', 51 | 'import/no-extraneous-dependencies': 'off', 52 | 'no-shadow': 'off', 53 | 'no-use-before-define': [2, 'nofunc'], 54 | 'no-await-in-loop': 'off', 55 | 'no-param-reassign': 'off', 56 | 'no-restricted-syntax': 'off', 57 | 'no-inner-declarations': 'off', 58 | '@typescript-eslint/explicit-module-boundary-types': 'off' 59 | }, 60 | settings: { 61 | 'import/resolver': { 62 | node: { 63 | extensions: [ 64 | '.js', 65 | '.jsx', 66 | '.ts', 67 | '.tsx', 68 | ], 69 | }, 70 | }, 71 | }, 72 | }; 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /build 4 | /docs/build 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | node_modules 10 | 11 | # profiling files 12 | chrome-profiler-events*.json 13 | speed-measure-plugin*.json 14 | 15 | # IDEs and editors 16 | .idea 17 | .project 18 | .classpath 19 | .c9/ 20 | *.launch 21 | .settings/ 22 | *.sublime-workspace 23 | 24 | # IDE - VSCode 25 | .vscode/* 26 | !.vscode/settings.json 27 | !.vscode/tasks.json 28 | !.vscode/launch.json 29 | !.vscode/extensions.json 30 | .history/* 31 | 32 | # misc 33 | /.sass-cache 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | npm-debug.log 38 | yarn-error.log 39 | testem.log 40 | /typings 41 | 42 | # System Files 43 | .DS_Store 44 | Thumbs.db 45 | 46 | /src/stack-router.js 47 | /src/types.js 48 | /src/transition-functions.js 49 | /src/utils.js 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Carlo Dell'Acqua 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 | # svelte-stack-router 2 | 3 | Bridging the gap between Native Apps and WebApps. A Svelte Router that caches page components and will make your WebApp feel more native 4 | 5 | 6 | [NPM Package](https://www.npmjs.com/package/svelte-stack-router) 7 | 8 | `npm install svelte-stack-router` 9 | 10 | ## Working demo 11 | 12 | [svelte-stack-router demo](https://cdellacqua.github.io/svelte-stack-router/#/) 13 | 14 | The demo files can be found in [src/](https://github.com/cdellacqua/svelte-stack-router/blob/master/src/) 15 | 16 | ## Quick setup 17 | 18 | - install this package `npm install --save-dev svelte-stack-router` 19 | - open/create the component that will contain the StackRouter 20 | - define your routes as key-value pairs, like in the following example 21 | ```javascript 22 | const myRoutes = { 23 | "/": Home, 24 | "/my-page": PageComponent, 25 | "/my-other-page/:someString": OtherPageThatAcceptsAParameter, 26 | "/my-other-page2/:optionalParam?": OtherPageThatAcceptsAnOptionalParameter, 27 | "*": NotFound, 28 | }; 29 | ``` 30 | - import the StackRouter component 31 | - add `` somewhere in the HTML section 32 | 33 | Example: 34 | 35 | `App.svelte` 36 | ```svelte 37 | 47 | 48 | ``` 49 | 50 | ## How it works 51 | 52 | Page components are cached, this ensures that going back in the browser history resumes the complete previous state. 53 | 54 | In other words: **previously instantiated pages don't get destroyed by default, they just get paused and resumed to reduce re-renders and preserve their full state**. 55 | 56 | Note that **a cached page is uniquely identified by its route template** (i.e. the key in the `routes/myRoutes` objects in the examples above), *not by the component*. 57 | 58 | ## Enhanced lifecycle functions 59 | 60 | In addition to the `onMount` and `onDestroy` lifecycle functions provided by Svelte, this library offers `onPause`, `onResume`, `onBeforeLoad`, `onBeforeUnload`, `onAfterLoad` and `onAfterUnload`. 61 | 62 | All these new lifecycle functions accept synchronous and asynchronous callbacks. In case of asynchronous callbacks they are executed one by one in the same order they were registered. 63 | 64 | The complete lifecycle is (|| = semi-parallel execution, achieved with Promise.all): 65 | - create the page component if not in cache 66 | - before-unload previous component || before-load new component 67 | - pause previous component if resumable || resume new component if in cache || animate-transition 68 | - after-unload previous component || after-load new component 69 | - destroy previous component if not resumable 70 | 71 | All these additional lifecycle functions can be called by the Page component and by its children **during initialization**, this means they should be invoked directly in the script section of the Svelte component (e.g. not inside onMount or in reactive statements). 72 | 73 | If you have a component which shouldn't be paused or resumed by the StackRouter, you can call `setResumable(false)` 74 | 75 | Doing this will make your component disposable, so that it will be mounted and destroyed and never paused or resumed. 76 | 77 | ### Notes on StackRouter destruction 78 | 79 | When the `` components gets unmounted (e.g. if it is inside an `{#if ...}`), all the components that were previously cached by it 80 | will be destroyed. In particular, if the currently active component has registered any `onBeforeUnload`, `onPause` or `onAfterUnload` callbacks, those 81 | will get executed before the destruction of the component with a boolean parameter set to `true` to signal the urgency to clean up. 82 | 83 | ```svelte 84 | 93 | ``` 94 | 95 | ## Router events 96 | 97 | You can listen for the following events: 98 | - `on:navigation-start` emitted before unloading the old page and before loading the new page 99 | - `on:navigation-end` emitted after unloading the old page and after loading the new page 100 | - `on:forbidden` emitted when a route couldn't be reached because a guard returned a falsy value 101 | - ``` 102 | { 103 | message: 'access forbidden by guard', 104 | params: , 105 | location: 106 | } 107 | ``` 108 | - `on:error` emitted when a route couldn't be reached due to an error. The error can be one of the following (`<...>` indicates some value at runtime): 109 | - ``` 110 | { 111 | message: 'no route found', 112 | location: 113 | } 114 | ``` 115 | - ``` 116 | { 117 | message: 'unable to get component from provider', 118 | location: , 119 | err: 120 | } 121 | ``` 122 | - ``` 123 | { 124 | message: 'guard error', 125 | params: , 126 | location: , 127 | err: 128 | } 129 | ``` 130 | 131 | Example: 132 | ```svelte 133 | alert('navigation started')} /> 134 | ``` 135 | 136 | ## Navigation functions, links and stores 137 | 138 | ### Programmatic navigation 139 | The following functions enable programmatic navigation: 140 | - `push('/some-route')` 141 | - `pop()` or `pop({ some: 'return value' })` (see [Returning values](#returning-values)) 142 | - `replace('/a-route')` 143 | 144 | ### Links 145 | This library also provides a custom `use:link` action that you can add to your `` elements to create links. This action serves two purposes: 146 | - if you are using the router in "hash mode" (e.g. in a purely client-side rendering context), it lets you write paths without having to manually add the `#` prefix to all the `href`. For example `Example` (or `Example`) is automatically 147 | converted to `Example`. This is particularly helpful if you later decide to switch to "path mode" (see next point) 148 | - if you are using the router in "path mode" (e.g. in a server-side rendering context), it prevents the default browser navigation behavior and, on user click, pushes the new location using the History API of the browser 149 | 150 | ### Stores 151 | To easily access information about the current route, you can import the following stores: 152 | - `location`: reflects the relative URL, without the leading '#' if in hash mode 153 | - `pathname`: store derived from location that extracts the path section of the URL 154 | - `search`: store derived from location that extracts the query string (starting from '?' included) 155 | 156 | For example, if you are on a page like http://localhost:5000/#/home/some-page/?someParam=a%20string, the following comparisons will be true: 157 | - `$location === "/home/some-page/?someParam=a%20string"` 158 | - `$pathname === "/home/some-page/"` 159 | - `$search === "?someParam=a%20string"` 160 | 161 | 162 | These features have been heavily inspired by [svelte-spa-router](https://github.com/ItalyPaleAle/svelte-spa-router). 163 | 164 | ## Returning values 165 | 166 | When the `pop` function is called it can receive an optional parameter, which acts like a return value. 167 | 168 | This value will be passed on as an argument to all the callback functions that are registered in the `onResume` hook of the component that is about to be resumed, thus allowing two components to communicate with each other. 169 | 170 | For example: 171 | - suppose the user is on `/selection`, a page that presents them with a list of items and expects them to pick one. In the same page there is an `Add` button 172 | - the user clicks on the `Add` button, thus navigating to `/new`, a page with a form where they can POST a new item to the list 173 | - the user submits the form and, in the submit handler, `pop` is called with the `id` of the newly created entity 174 | - the user gets brought back to `/selection`, which, being resumable, can handle the return value in its `onResume` callback(s) and show the selection on the newly created entity 175 | 176 | For example: 177 | - Selection page 178 | ```svelte 179 | 184 | ``` 185 | - Add page 186 | ```svelte 187 | 195 | ``` 196 | You can look at an actual implementation in the live demo source code. 197 | 198 | 199 | ## Customizing behavior 200 | 201 | The `` component supports a variety of options: 202 | 203 | |name|type|description|default| 204 | |-|-|-|-| 205 | |defaultResumable|boolean|whether or not the default behavior should be to resume or recreate the components|true| 206 | |useHash|boolean|whether or not to prefix routes with '#' to implement a server-agnostic client side routing (e.g. no need to redirect 404 to index)|true| 207 | |restoreScroll|boolean|whether or not to restore the scroll position when navigating backwards|true| 208 | |transitionFn|TransitionFunction|a function that handles the transition between two pages|dive(300)| 209 | |routes|Record.|a key-value object associating a route path (e.g. '/a/route/path/:variable1?) to a SvelteComponent constructor|N/A - **required**| 210 | 211 | ## Advanced routing 212 | 213 | This router supports guards and asynchronously provided components (e.g. when using lazy loading). 214 | 215 | Guards are functions that can either return a `boolean` or a `Promise`. They are called sequentially and 216 | the first one to return (or resolve to) `false` causes a navigation error ("access forbidden by guard"). 217 | 218 | If a route has some parameters, the guard will receive them before the component. 219 | 220 | Guard type: 221 | ```typescript 222 | export type Guard = (paramsPreview?: Params) => boolean | Promise; 223 | ``` 224 | 225 | 226 | Here are some examples: 227 | - provide a component asynchronously: 228 | 229 | `App.svelte` 230 | ```svelte 231 | 240 | 241 | ``` 242 | - add guards to a route: 243 | 244 | `App.svelte` 245 | ```svelte 246 | 269 | 270 | ``` 271 | - add guards to a route with an async component provider: 272 | 273 | `App.svelte` 274 | ```svelte 275 | 291 | 292 | ``` 293 | 294 | ### TransitionFunction and available transitions 295 | 296 | This library provides 3 types of transitions between pages: 297 | - `dive(milliseconds)` transition with a dive effect 298 | - `slide(milliseconds)` transition with a slide effect 299 | - `noAnimation()` transition without any animation 300 | 301 | 302 | You can also implement a custom transition animation by implementing a transition function that reflect the following type definition: 303 | ```typescript 304 | /** 305 | * A function that handles the transition between two pages 306 | * @param {NavigationType} data.navigationType describes the navigation that occurred (e.g. backward, replace, forward, ...) 307 | * @param {HTMLElement} data.mountPointToLoad the mount point of the page that is being loaded 308 | * @param {HTMLElement} data.mountPointToUnload the mount point of the page that is being unloaded 309 | * @param {HTMLElement} data.routerMountPoint the router mount point, when this function is called it contains both the mountPointToLoad and the mountPointToUnload 310 | * @param {{x: number, y: number}} data.scroll if scroll restoration is enabled and the current component is being resumed, this object contains the x and y coordinates needed to bring the window scrollbars back to where they were when the component was paused 311 | * @return {Promise} a promise that resolves once the transition has finished 312 | */ 313 | export type TransitionFunction = (data: TransitionFunctionData) => Promise; 314 | ``` 315 | 316 | You can also generate a TransitionFunction using the helpers provided in transition-functions.js 317 | -------------------------------------------------------------------------------- /docs/bunny.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdellacqua/svelte-stack-router/03869dc2a44ccf8e2312d49b70698033ce0a2272/docs/bunny.mp4 -------------------------------------------------------------------------------- /docs/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdellacqua/svelte-stack-router/03869dc2a44ccf8e2312d49b70698033ce0a2272/docs/github.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | svelte-stack-router 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/npm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdellacqua/svelte-stack-router/03869dc2a44ccf8e2312d49b70698033ce0a2272/docs/npm.png -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-stack-router", 3 | "version": "2.4.6", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.12.11", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", 10 | "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.10.4" 14 | } 15 | }, 16 | "@babel/helper-validator-identifier": { 17 | "version": "7.14.0", 18 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", 19 | "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", 20 | "dev": true 21 | }, 22 | "@babel/highlight": { 23 | "version": "7.14.0", 24 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", 25 | "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", 26 | "dev": true, 27 | "requires": { 28 | "@babel/helper-validator-identifier": "^7.14.0", 29 | "chalk": "^2.0.0", 30 | "js-tokens": "^4.0.0" 31 | }, 32 | "dependencies": { 33 | "ansi-styles": { 34 | "version": "3.2.1", 35 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 36 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 37 | "dev": true, 38 | "requires": { 39 | "color-convert": "^1.9.0" 40 | } 41 | }, 42 | "chalk": { 43 | "version": "2.4.2", 44 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 45 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 46 | "dev": true, 47 | "requires": { 48 | "ansi-styles": "^3.2.1", 49 | "escape-string-regexp": "^1.0.5", 50 | "supports-color": "^5.3.0" 51 | } 52 | }, 53 | "color-convert": { 54 | "version": "1.9.3", 55 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 56 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 57 | "dev": true, 58 | "requires": { 59 | "color-name": "1.1.3" 60 | } 61 | }, 62 | "color-name": { 63 | "version": "1.1.3", 64 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 65 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 66 | "dev": true 67 | }, 68 | "escape-string-regexp": { 69 | "version": "1.0.5", 70 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 71 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 72 | "dev": true 73 | }, 74 | "has-flag": { 75 | "version": "3.0.0", 76 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 77 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 78 | "dev": true 79 | }, 80 | "supports-color": { 81 | "version": "5.5.0", 82 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 83 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 84 | "dev": true, 85 | "requires": { 86 | "has-flag": "^3.0.0" 87 | } 88 | } 89 | } 90 | }, 91 | "@eslint/eslintrc": { 92 | "version": "0.4.1", 93 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz", 94 | "integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==", 95 | "dev": true, 96 | "requires": { 97 | "ajv": "^6.12.4", 98 | "debug": "^4.1.1", 99 | "espree": "^7.3.0", 100 | "globals": "^12.1.0", 101 | "ignore": "^4.0.6", 102 | "import-fresh": "^3.2.1", 103 | "js-yaml": "^3.13.1", 104 | "minimatch": "^3.0.4", 105 | "strip-json-comments": "^3.1.1" 106 | }, 107 | "dependencies": { 108 | "globals": { 109 | "version": "12.4.0", 110 | "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", 111 | "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", 112 | "dev": true, 113 | "requires": { 114 | "type-fest": "^0.8.1" 115 | } 116 | }, 117 | "type-fest": { 118 | "version": "0.8.1", 119 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 120 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 121 | "dev": true 122 | } 123 | } 124 | }, 125 | "@nodelib/fs.scandir": { 126 | "version": "2.1.4", 127 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", 128 | "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", 129 | "dev": true, 130 | "requires": { 131 | "@nodelib/fs.stat": "2.0.4", 132 | "run-parallel": "^1.1.9" 133 | } 134 | }, 135 | "@nodelib/fs.stat": { 136 | "version": "2.0.4", 137 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", 138 | "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", 139 | "dev": true 140 | }, 141 | "@nodelib/fs.walk": { 142 | "version": "1.2.6", 143 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", 144 | "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", 145 | "dev": true, 146 | "requires": { 147 | "@nodelib/fs.scandir": "2.1.4", 148 | "fastq": "^1.6.0" 149 | } 150 | }, 151 | "@polka/url": { 152 | "version": "1.0.0-next.11", 153 | "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.11.tgz", 154 | "integrity": "sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA==", 155 | "dev": true 156 | }, 157 | "@rollup/plugin-commonjs": { 158 | "version": "16.0.0", 159 | "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz", 160 | "integrity": "sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw==", 161 | "dev": true, 162 | "requires": { 163 | "@rollup/pluginutils": "^3.1.0", 164 | "commondir": "^1.0.1", 165 | "estree-walker": "^2.0.1", 166 | "glob": "^7.1.6", 167 | "is-reference": "^1.2.1", 168 | "magic-string": "^0.25.7", 169 | "resolve": "^1.17.0" 170 | } 171 | }, 172 | "@rollup/plugin-node-resolve": { 173 | "version": "10.0.0", 174 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-10.0.0.tgz", 175 | "integrity": "sha512-sNijGta8fqzwA1VwUEtTvWCx2E7qC70NMsDh4ZG13byAXYigBNZMxALhKUSycBks5gupJdq0lFrKumFrRZ8H3A==", 176 | "dev": true, 177 | "requires": { 178 | "@rollup/pluginutils": "^3.1.0", 179 | "@types/resolve": "1.17.1", 180 | "builtin-modules": "^3.1.0", 181 | "deepmerge": "^4.2.2", 182 | "is-module": "^1.0.0", 183 | "resolve": "^1.17.0" 184 | } 185 | }, 186 | "@rollup/pluginutils": { 187 | "version": "3.1.0", 188 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", 189 | "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", 190 | "dev": true, 191 | "requires": { 192 | "@types/estree": "0.0.39", 193 | "estree-walker": "^1.0.1", 194 | "picomatch": "^2.2.2" 195 | }, 196 | "dependencies": { 197 | "estree-walker": { 198 | "version": "1.0.1", 199 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", 200 | "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", 201 | "dev": true 202 | } 203 | } 204 | }, 205 | "@tsconfig/svelte": { 206 | "version": "1.0.10", 207 | "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-1.0.10.tgz", 208 | "integrity": "sha512-EBrpH2iXXfaf/9z81koiDYkp2mlwW2XzFcAqn6qh7VKyP8zBvHHAQzNhY+W9vH5arAjmGAm5g8ElWq6YmXm3ig==", 209 | "dev": true 210 | }, 211 | "@types/estree": { 212 | "version": "0.0.39", 213 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", 214 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", 215 | "dev": true 216 | }, 217 | "@types/json-schema": { 218 | "version": "7.0.7", 219 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", 220 | "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", 221 | "dev": true 222 | }, 223 | "@types/json5": { 224 | "version": "0.0.29", 225 | "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", 226 | "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", 227 | "dev": true 228 | }, 229 | "@types/node": { 230 | "version": "14.0.23", 231 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.23.tgz", 232 | "integrity": "sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw==", 233 | "dev": true 234 | }, 235 | "@types/resolve": { 236 | "version": "1.17.1", 237 | "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", 238 | "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", 239 | "dev": true, 240 | "requires": { 241 | "@types/node": "*" 242 | } 243 | }, 244 | "@typescript-eslint/eslint-plugin": { 245 | "version": "4.25.0", 246 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.25.0.tgz", 247 | "integrity": "sha512-Qfs3dWkTMKkKwt78xp2O/KZQB8MPS1UQ5D3YW2s6LQWBE1074BE+Rym+b1pXZIX3M3fSvPUDaCvZLKV2ylVYYQ==", 248 | "dev": true, 249 | "requires": { 250 | "@typescript-eslint/experimental-utils": "4.25.0", 251 | "@typescript-eslint/scope-manager": "4.25.0", 252 | "debug": "^4.1.1", 253 | "functional-red-black-tree": "^1.0.1", 254 | "lodash": "^4.17.15", 255 | "regexpp": "^3.0.0", 256 | "semver": "^7.3.2", 257 | "tsutils": "^3.17.1" 258 | } 259 | }, 260 | "@typescript-eslint/experimental-utils": { 261 | "version": "4.25.0", 262 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.25.0.tgz", 263 | "integrity": "sha512-f0doRE76vq7NEEU0tw+ajv6CrmPelw5wLoaghEHkA2dNLFb3T/zJQqGPQ0OYt5XlZaS13MtnN+GTPCuUVg338w==", 264 | "dev": true, 265 | "requires": { 266 | "@types/json-schema": "^7.0.3", 267 | "@typescript-eslint/scope-manager": "4.25.0", 268 | "@typescript-eslint/types": "4.25.0", 269 | "@typescript-eslint/typescript-estree": "4.25.0", 270 | "eslint-scope": "^5.0.0", 271 | "eslint-utils": "^2.0.0" 272 | } 273 | }, 274 | "@typescript-eslint/parser": { 275 | "version": "4.25.0", 276 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.25.0.tgz", 277 | "integrity": "sha512-OZFa1SKyEJpAhDx8FcbWyX+vLwh7OEtzoo2iQaeWwxucyfbi0mT4DijbOSsTgPKzGHr6GrF2V5p/CEpUH/VBxg==", 278 | "dev": true, 279 | "requires": { 280 | "@typescript-eslint/scope-manager": "4.25.0", 281 | "@typescript-eslint/types": "4.25.0", 282 | "@typescript-eslint/typescript-estree": "4.25.0", 283 | "debug": "^4.1.1" 284 | } 285 | }, 286 | "@typescript-eslint/scope-manager": { 287 | "version": "4.25.0", 288 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.25.0.tgz", 289 | "integrity": "sha512-2NElKxMb/0rya+NJG1U71BuNnp1TBd1JgzYsldsdA83h/20Tvnf/HrwhiSlNmuq6Vqa0EzidsvkTArwoq+tH6w==", 290 | "dev": true, 291 | "requires": { 292 | "@typescript-eslint/types": "4.25.0", 293 | "@typescript-eslint/visitor-keys": "4.25.0" 294 | } 295 | }, 296 | "@typescript-eslint/types": { 297 | "version": "4.25.0", 298 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.25.0.tgz", 299 | "integrity": "sha512-+CNINNvl00OkW6wEsi32wU5MhHti2J25TJsJJqgQmJu3B3dYDBcmOxcE5w9cgoM13TrdE/5ND2HoEnBohasxRQ==", 300 | "dev": true 301 | }, 302 | "@typescript-eslint/typescript-estree": { 303 | "version": "4.25.0", 304 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.25.0.tgz", 305 | "integrity": "sha512-1B8U07TGNAFMxZbSpF6jqiDs1cVGO0izVkf18Q/SPcUAc9LhHxzvSowXDTvkHMWUVuPpagupaW63gB6ahTXVlg==", 306 | "dev": true, 307 | "requires": { 308 | "@typescript-eslint/types": "4.25.0", 309 | "@typescript-eslint/visitor-keys": "4.25.0", 310 | "debug": "^4.1.1", 311 | "globby": "^11.0.1", 312 | "is-glob": "^4.0.1", 313 | "semver": "^7.3.2", 314 | "tsutils": "^3.17.1" 315 | } 316 | }, 317 | "@typescript-eslint/visitor-keys": { 318 | "version": "4.25.0", 319 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.25.0.tgz", 320 | "integrity": "sha512-AmkqV9dDJVKP/TcZrbf6s6i1zYXt5Hl8qOLrRDTFfRNae4+LB8A4N3i+FLZPW85zIxRy39BgeWOfMS3HoH5ngg==", 321 | "dev": true, 322 | "requires": { 323 | "@typescript-eslint/types": "4.25.0", 324 | "eslint-visitor-keys": "^2.0.0" 325 | } 326 | }, 327 | "acorn": { 328 | "version": "7.4.1", 329 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 330 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", 331 | "dev": true 332 | }, 333 | "acorn-jsx": { 334 | "version": "5.3.1", 335 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", 336 | "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", 337 | "dev": true 338 | }, 339 | "ajv": { 340 | "version": "6.12.6", 341 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 342 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 343 | "dev": true, 344 | "requires": { 345 | "fast-deep-equal": "^3.1.1", 346 | "fast-json-stable-stringify": "^2.0.0", 347 | "json-schema-traverse": "^0.4.1", 348 | "uri-js": "^4.2.2" 349 | } 350 | }, 351 | "ansi-colors": { 352 | "version": "4.1.1", 353 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 354 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 355 | "dev": true 356 | }, 357 | "ansi-regex": { 358 | "version": "5.0.0", 359 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 360 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 361 | "dev": true 362 | }, 363 | "ansi-styles": { 364 | "version": "4.3.0", 365 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 366 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 367 | "dev": true, 368 | "requires": { 369 | "color-convert": "^2.0.1" 370 | } 371 | }, 372 | "anymatch": { 373 | "version": "3.1.1", 374 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 375 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 376 | "dev": true, 377 | "requires": { 378 | "normalize-path": "^3.0.0", 379 | "picomatch": "^2.0.4" 380 | } 381 | }, 382 | "argparse": { 383 | "version": "1.0.10", 384 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 385 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 386 | "dev": true, 387 | "requires": { 388 | "sprintf-js": "~1.0.2" 389 | } 390 | }, 391 | "array-includes": { 392 | "version": "3.1.3", 393 | "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", 394 | "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", 395 | "dev": true, 396 | "requires": { 397 | "call-bind": "^1.0.2", 398 | "define-properties": "^1.1.3", 399 | "es-abstract": "^1.18.0-next.2", 400 | "get-intrinsic": "^1.1.1", 401 | "is-string": "^1.0.5" 402 | } 403 | }, 404 | "array-union": { 405 | "version": "2.1.0", 406 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 407 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 408 | "dev": true 409 | }, 410 | "array.prototype.flat": { 411 | "version": "1.2.4", 412 | "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", 413 | "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", 414 | "dev": true, 415 | "requires": { 416 | "call-bind": "^1.0.0", 417 | "define-properties": "^1.1.3", 418 | "es-abstract": "^1.18.0-next.1" 419 | } 420 | }, 421 | "astral-regex": { 422 | "version": "2.0.0", 423 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", 424 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", 425 | "dev": true 426 | }, 427 | "async-limiter": { 428 | "version": "1.0.1", 429 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 430 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", 431 | "dev": true 432 | }, 433 | "balanced-match": { 434 | "version": "1.0.0", 435 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 436 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 437 | "dev": true 438 | }, 439 | "binary-extensions": { 440 | "version": "2.1.0", 441 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", 442 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", 443 | "dev": true 444 | }, 445 | "brace-expansion": { 446 | "version": "1.1.11", 447 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 448 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 449 | "dev": true, 450 | "requires": { 451 | "balanced-match": "^1.0.0", 452 | "concat-map": "0.0.1" 453 | } 454 | }, 455 | "braces": { 456 | "version": "3.0.2", 457 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 458 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 459 | "dev": true, 460 | "requires": { 461 | "fill-range": "^7.0.1" 462 | } 463 | }, 464 | "builtin-modules": { 465 | "version": "3.1.0", 466 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", 467 | "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", 468 | "dev": true 469 | }, 470 | "call-bind": { 471 | "version": "1.0.2", 472 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 473 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 474 | "dev": true, 475 | "requires": { 476 | "function-bind": "^1.1.1", 477 | "get-intrinsic": "^1.0.2" 478 | } 479 | }, 480 | "callsites": { 481 | "version": "3.1.0", 482 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 483 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 484 | "dev": true 485 | }, 486 | "chalk": { 487 | "version": "4.1.1", 488 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", 489 | "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", 490 | "dev": true, 491 | "requires": { 492 | "ansi-styles": "^4.1.0", 493 | "supports-color": "^7.1.0" 494 | } 495 | }, 496 | "chokidar": { 497 | "version": "3.4.3", 498 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", 499 | "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", 500 | "dev": true, 501 | "requires": { 502 | "anymatch": "~3.1.1", 503 | "braces": "~3.0.2", 504 | "fsevents": "~2.1.2", 505 | "glob-parent": "~5.1.0", 506 | "is-binary-path": "~2.1.0", 507 | "is-glob": "~4.0.1", 508 | "normalize-path": "~3.0.0", 509 | "readdirp": "~3.5.0" 510 | } 511 | }, 512 | "color-convert": { 513 | "version": "2.0.1", 514 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 515 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 516 | "dev": true, 517 | "requires": { 518 | "color-name": "~1.1.4" 519 | } 520 | }, 521 | "color-name": { 522 | "version": "1.1.4", 523 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 524 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 525 | "dev": true 526 | }, 527 | "commondir": { 528 | "version": "1.0.1", 529 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 530 | "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", 531 | "dev": true 532 | }, 533 | "concat-map": { 534 | "version": "0.0.1", 535 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 536 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 537 | "dev": true 538 | }, 539 | "confusing-browser-globals": { 540 | "version": "1.0.10", 541 | "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", 542 | "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", 543 | "dev": true 544 | }, 545 | "console-clear": { 546 | "version": "1.1.1", 547 | "resolved": "https://registry.npmjs.org/console-clear/-/console-clear-1.1.1.tgz", 548 | "integrity": "sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==", 549 | "dev": true 550 | }, 551 | "cross-spawn": { 552 | "version": "7.0.3", 553 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 554 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 555 | "dev": true, 556 | "requires": { 557 | "path-key": "^3.1.0", 558 | "shebang-command": "^2.0.0", 559 | "which": "^2.0.1" 560 | } 561 | }, 562 | "debug": { 563 | "version": "4.3.1", 564 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 565 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 566 | "dev": true, 567 | "requires": { 568 | "ms": "2.1.2" 569 | } 570 | }, 571 | "deep-is": { 572 | "version": "0.1.3", 573 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 574 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 575 | "dev": true 576 | }, 577 | "deepmerge": { 578 | "version": "4.2.2", 579 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", 580 | "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", 581 | "dev": true 582 | }, 583 | "define-properties": { 584 | "version": "1.1.3", 585 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 586 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 587 | "dev": true, 588 | "requires": { 589 | "object-keys": "^1.0.12" 590 | } 591 | }, 592 | "dir-glob": { 593 | "version": "3.0.1", 594 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 595 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 596 | "dev": true, 597 | "requires": { 598 | "path-type": "^4.0.0" 599 | } 600 | }, 601 | "doctrine": { 602 | "version": "3.0.0", 603 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 604 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 605 | "dev": true, 606 | "requires": { 607 | "esutils": "^2.0.2" 608 | } 609 | }, 610 | "emoji-regex": { 611 | "version": "8.0.0", 612 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 613 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 614 | "dev": true 615 | }, 616 | "enquirer": { 617 | "version": "2.3.6", 618 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", 619 | "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", 620 | "dev": true, 621 | "requires": { 622 | "ansi-colors": "^4.1.1" 623 | } 624 | }, 625 | "error-ex": { 626 | "version": "1.3.2", 627 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 628 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 629 | "dev": true, 630 | "requires": { 631 | "is-arrayish": "^0.2.1" 632 | } 633 | }, 634 | "es-abstract": { 635 | "version": "1.18.3", 636 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", 637 | "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", 638 | "dev": true, 639 | "requires": { 640 | "call-bind": "^1.0.2", 641 | "es-to-primitive": "^1.2.1", 642 | "function-bind": "^1.1.1", 643 | "get-intrinsic": "^1.1.1", 644 | "has": "^1.0.3", 645 | "has-symbols": "^1.0.2", 646 | "is-callable": "^1.2.3", 647 | "is-negative-zero": "^2.0.1", 648 | "is-regex": "^1.1.3", 649 | "is-string": "^1.0.6", 650 | "object-inspect": "^1.10.3", 651 | "object-keys": "^1.1.1", 652 | "object.assign": "^4.1.2", 653 | "string.prototype.trimend": "^1.0.4", 654 | "string.prototype.trimstart": "^1.0.4", 655 | "unbox-primitive": "^1.0.1" 656 | } 657 | }, 658 | "es-to-primitive": { 659 | "version": "1.2.1", 660 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 661 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 662 | "dev": true, 663 | "requires": { 664 | "is-callable": "^1.1.4", 665 | "is-date-object": "^1.0.1", 666 | "is-symbol": "^1.0.2" 667 | } 668 | }, 669 | "escape-string-regexp": { 670 | "version": "4.0.0", 671 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 672 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 673 | "dev": true 674 | }, 675 | "eslint": { 676 | "version": "7.27.0", 677 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.27.0.tgz", 678 | "integrity": "sha512-JZuR6La2ZF0UD384lcbnd0Cgg6QJjiCwhMD6eU4h/VGPcVGwawNNzKU41tgokGXnfjOOyI6QIffthhJTPzzuRA==", 679 | "dev": true, 680 | "requires": { 681 | "@babel/code-frame": "7.12.11", 682 | "@eslint/eslintrc": "^0.4.1", 683 | "ajv": "^6.10.0", 684 | "chalk": "^4.0.0", 685 | "cross-spawn": "^7.0.2", 686 | "debug": "^4.0.1", 687 | "doctrine": "^3.0.0", 688 | "enquirer": "^2.3.5", 689 | "escape-string-regexp": "^4.0.0", 690 | "eslint-scope": "^5.1.1", 691 | "eslint-utils": "^2.1.0", 692 | "eslint-visitor-keys": "^2.0.0", 693 | "espree": "^7.3.1", 694 | "esquery": "^1.4.0", 695 | "esutils": "^2.0.2", 696 | "fast-deep-equal": "^3.1.3", 697 | "file-entry-cache": "^6.0.1", 698 | "functional-red-black-tree": "^1.0.1", 699 | "glob-parent": "^5.0.0", 700 | "globals": "^13.6.0", 701 | "ignore": "^4.0.6", 702 | "import-fresh": "^3.0.0", 703 | "imurmurhash": "^0.1.4", 704 | "is-glob": "^4.0.0", 705 | "js-yaml": "^3.13.1", 706 | "json-stable-stringify-without-jsonify": "^1.0.1", 707 | "levn": "^0.4.1", 708 | "lodash.merge": "^4.6.2", 709 | "minimatch": "^3.0.4", 710 | "natural-compare": "^1.4.0", 711 | "optionator": "^0.9.1", 712 | "progress": "^2.0.0", 713 | "regexpp": "^3.1.0", 714 | "semver": "^7.2.1", 715 | "strip-ansi": "^6.0.0", 716 | "strip-json-comments": "^3.1.0", 717 | "table": "^6.0.9", 718 | "text-table": "^0.2.0", 719 | "v8-compile-cache": "^2.0.3" 720 | } 721 | }, 722 | "eslint-config-airbnb-base": { 723 | "version": "14.2.1", 724 | "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz", 725 | "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==", 726 | "dev": true, 727 | "requires": { 728 | "confusing-browser-globals": "^1.0.10", 729 | "object.assign": "^4.1.2", 730 | "object.entries": "^1.1.2" 731 | } 732 | }, 733 | "eslint-import-resolver-node": { 734 | "version": "0.3.4", 735 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", 736 | "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", 737 | "dev": true, 738 | "requires": { 739 | "debug": "^2.6.9", 740 | "resolve": "^1.13.1" 741 | }, 742 | "dependencies": { 743 | "debug": { 744 | "version": "2.6.9", 745 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 746 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 747 | "dev": true, 748 | "requires": { 749 | "ms": "2.0.0" 750 | } 751 | }, 752 | "ms": { 753 | "version": "2.0.0", 754 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 755 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 756 | "dev": true 757 | } 758 | } 759 | }, 760 | "eslint-module-utils": { 761 | "version": "2.6.1", 762 | "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", 763 | "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", 764 | "dev": true, 765 | "requires": { 766 | "debug": "^3.2.7", 767 | "pkg-dir": "^2.0.0" 768 | }, 769 | "dependencies": { 770 | "debug": { 771 | "version": "3.2.7", 772 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 773 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 774 | "dev": true, 775 | "requires": { 776 | "ms": "^2.1.1" 777 | } 778 | } 779 | } 780 | }, 781 | "eslint-plugin-import": { 782 | "version": "2.23.4", 783 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", 784 | "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", 785 | "dev": true, 786 | "requires": { 787 | "array-includes": "^3.1.3", 788 | "array.prototype.flat": "^1.2.4", 789 | "debug": "^2.6.9", 790 | "doctrine": "^2.1.0", 791 | "eslint-import-resolver-node": "^0.3.4", 792 | "eslint-module-utils": "^2.6.1", 793 | "find-up": "^2.0.0", 794 | "has": "^1.0.3", 795 | "is-core-module": "^2.4.0", 796 | "minimatch": "^3.0.4", 797 | "object.values": "^1.1.3", 798 | "pkg-up": "^2.0.0", 799 | "read-pkg-up": "^3.0.0", 800 | "resolve": "^1.20.0", 801 | "tsconfig-paths": "^3.9.0" 802 | }, 803 | "dependencies": { 804 | "debug": { 805 | "version": "2.6.9", 806 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 807 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 808 | "dev": true, 809 | "requires": { 810 | "ms": "2.0.0" 811 | } 812 | }, 813 | "doctrine": { 814 | "version": "2.1.0", 815 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 816 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 817 | "dev": true, 818 | "requires": { 819 | "esutils": "^2.0.2" 820 | } 821 | }, 822 | "ms": { 823 | "version": "2.0.0", 824 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 825 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 826 | "dev": true 827 | } 828 | } 829 | }, 830 | "eslint-scope": { 831 | "version": "5.1.1", 832 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 833 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 834 | "dev": true, 835 | "requires": { 836 | "esrecurse": "^4.3.0", 837 | "estraverse": "^4.1.1" 838 | } 839 | }, 840 | "eslint-utils": { 841 | "version": "2.1.0", 842 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", 843 | "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", 844 | "dev": true, 845 | "requires": { 846 | "eslint-visitor-keys": "^1.1.0" 847 | }, 848 | "dependencies": { 849 | "eslint-visitor-keys": { 850 | "version": "1.3.0", 851 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 852 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 853 | "dev": true 854 | } 855 | } 856 | }, 857 | "eslint-visitor-keys": { 858 | "version": "2.1.0", 859 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 860 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 861 | "dev": true 862 | }, 863 | "espree": { 864 | "version": "7.3.1", 865 | "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", 866 | "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", 867 | "dev": true, 868 | "requires": { 869 | "acorn": "^7.4.0", 870 | "acorn-jsx": "^5.3.1", 871 | "eslint-visitor-keys": "^1.3.0" 872 | }, 873 | "dependencies": { 874 | "eslint-visitor-keys": { 875 | "version": "1.3.0", 876 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 877 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 878 | "dev": true 879 | } 880 | } 881 | }, 882 | "esprima": { 883 | "version": "4.0.1", 884 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 885 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 886 | "dev": true 887 | }, 888 | "esquery": { 889 | "version": "1.4.0", 890 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 891 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 892 | "dev": true, 893 | "requires": { 894 | "estraverse": "^5.1.0" 895 | }, 896 | "dependencies": { 897 | "estraverse": { 898 | "version": "5.2.0", 899 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 900 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 901 | "dev": true 902 | } 903 | } 904 | }, 905 | "esrecurse": { 906 | "version": "4.3.0", 907 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 908 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 909 | "dev": true, 910 | "requires": { 911 | "estraverse": "^5.2.0" 912 | }, 913 | "dependencies": { 914 | "estraverse": { 915 | "version": "5.2.0", 916 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 917 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 918 | "dev": true 919 | } 920 | } 921 | }, 922 | "estraverse": { 923 | "version": "4.3.0", 924 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 925 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 926 | "dev": true 927 | }, 928 | "estree-walker": { 929 | "version": "2.0.1", 930 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.1.tgz", 931 | "integrity": "sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg==", 932 | "dev": true 933 | }, 934 | "esutils": { 935 | "version": "2.0.3", 936 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 937 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 938 | "dev": true 939 | }, 940 | "fast-deep-equal": { 941 | "version": "3.1.3", 942 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 943 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 944 | "dev": true 945 | }, 946 | "fast-glob": { 947 | "version": "3.2.5", 948 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", 949 | "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", 950 | "dev": true, 951 | "requires": { 952 | "@nodelib/fs.stat": "^2.0.2", 953 | "@nodelib/fs.walk": "^1.2.3", 954 | "glob-parent": "^5.1.0", 955 | "merge2": "^1.3.0", 956 | "micromatch": "^4.0.2", 957 | "picomatch": "^2.2.1" 958 | } 959 | }, 960 | "fast-json-stable-stringify": { 961 | "version": "2.1.0", 962 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 963 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 964 | "dev": true 965 | }, 966 | "fast-levenshtein": { 967 | "version": "2.0.6", 968 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 969 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 970 | "dev": true 971 | }, 972 | "fastq": { 973 | "version": "1.11.0", 974 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", 975 | "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", 976 | "dev": true, 977 | "requires": { 978 | "reusify": "^1.0.4" 979 | } 980 | }, 981 | "file-entry-cache": { 982 | "version": "6.0.1", 983 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 984 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 985 | "dev": true, 986 | "requires": { 987 | "flat-cache": "^3.0.4" 988 | } 989 | }, 990 | "fill-range": { 991 | "version": "7.0.1", 992 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 993 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 994 | "dev": true, 995 | "requires": { 996 | "to-regex-range": "^5.0.1" 997 | } 998 | }, 999 | "find-up": { 1000 | "version": "2.1.0", 1001 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 1002 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 1003 | "dev": true, 1004 | "requires": { 1005 | "locate-path": "^2.0.0" 1006 | } 1007 | }, 1008 | "flat-cache": { 1009 | "version": "3.0.4", 1010 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 1011 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 1012 | "dev": true, 1013 | "requires": { 1014 | "flatted": "^3.1.0", 1015 | "rimraf": "^3.0.2" 1016 | } 1017 | }, 1018 | "flatted": { 1019 | "version": "3.1.1", 1020 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", 1021 | "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", 1022 | "dev": true 1023 | }, 1024 | "fs.realpath": { 1025 | "version": "1.0.0", 1026 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1027 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 1028 | "dev": true 1029 | }, 1030 | "fsevents": { 1031 | "version": "2.1.3", 1032 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 1033 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 1034 | "dev": true, 1035 | "optional": true 1036 | }, 1037 | "function-bind": { 1038 | "version": "1.1.1", 1039 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1040 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 1041 | "dev": true 1042 | }, 1043 | "functional-red-black-tree": { 1044 | "version": "1.0.1", 1045 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1046 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 1047 | "dev": true 1048 | }, 1049 | "get-intrinsic": { 1050 | "version": "1.1.1", 1051 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 1052 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 1053 | "dev": true, 1054 | "requires": { 1055 | "function-bind": "^1.1.1", 1056 | "has": "^1.0.3", 1057 | "has-symbols": "^1.0.1" 1058 | } 1059 | }, 1060 | "get-port": { 1061 | "version": "3.2.0", 1062 | "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", 1063 | "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", 1064 | "dev": true 1065 | }, 1066 | "glob": { 1067 | "version": "7.1.6", 1068 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 1069 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 1070 | "dev": true, 1071 | "requires": { 1072 | "fs.realpath": "^1.0.0", 1073 | "inflight": "^1.0.4", 1074 | "inherits": "2", 1075 | "minimatch": "^3.0.4", 1076 | "once": "^1.3.0", 1077 | "path-is-absolute": "^1.0.0" 1078 | } 1079 | }, 1080 | "glob-parent": { 1081 | "version": "5.1.1", 1082 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 1083 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 1084 | "dev": true, 1085 | "requires": { 1086 | "is-glob": "^4.0.1" 1087 | } 1088 | }, 1089 | "globals": { 1090 | "version": "13.9.0", 1091 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", 1092 | "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", 1093 | "dev": true, 1094 | "requires": { 1095 | "type-fest": "^0.20.2" 1096 | } 1097 | }, 1098 | "globby": { 1099 | "version": "11.0.3", 1100 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", 1101 | "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", 1102 | "dev": true, 1103 | "requires": { 1104 | "array-union": "^2.1.0", 1105 | "dir-glob": "^3.0.1", 1106 | "fast-glob": "^3.1.1", 1107 | "ignore": "^5.1.4", 1108 | "merge2": "^1.3.0", 1109 | "slash": "^3.0.0" 1110 | }, 1111 | "dependencies": { 1112 | "ignore": { 1113 | "version": "5.1.8", 1114 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", 1115 | "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", 1116 | "dev": true 1117 | } 1118 | } 1119 | }, 1120 | "graceful-fs": { 1121 | "version": "4.2.6", 1122 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", 1123 | "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", 1124 | "dev": true 1125 | }, 1126 | "has": { 1127 | "version": "1.0.3", 1128 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1129 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1130 | "dev": true, 1131 | "requires": { 1132 | "function-bind": "^1.1.1" 1133 | } 1134 | }, 1135 | "has-bigints": { 1136 | "version": "1.0.1", 1137 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", 1138 | "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", 1139 | "dev": true 1140 | }, 1141 | "has-flag": { 1142 | "version": "4.0.0", 1143 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1144 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1145 | "dev": true 1146 | }, 1147 | "has-symbols": { 1148 | "version": "1.0.2", 1149 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", 1150 | "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", 1151 | "dev": true 1152 | }, 1153 | "hosted-git-info": { 1154 | "version": "2.8.9", 1155 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", 1156 | "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", 1157 | "dev": true 1158 | }, 1159 | "ignore": { 1160 | "version": "4.0.6", 1161 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 1162 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 1163 | "dev": true 1164 | }, 1165 | "import-fresh": { 1166 | "version": "3.3.0", 1167 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 1168 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1169 | "dev": true, 1170 | "requires": { 1171 | "parent-module": "^1.0.0", 1172 | "resolve-from": "^4.0.0" 1173 | } 1174 | }, 1175 | "imurmurhash": { 1176 | "version": "0.1.4", 1177 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1178 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1179 | "dev": true 1180 | }, 1181 | "inflight": { 1182 | "version": "1.0.6", 1183 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1184 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1185 | "dev": true, 1186 | "requires": { 1187 | "once": "^1.3.0", 1188 | "wrappy": "1" 1189 | } 1190 | }, 1191 | "inherits": { 1192 | "version": "2.0.4", 1193 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1194 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1195 | "dev": true 1196 | }, 1197 | "is-arrayish": { 1198 | "version": "0.2.1", 1199 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 1200 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 1201 | "dev": true 1202 | }, 1203 | "is-bigint": { 1204 | "version": "1.0.2", 1205 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", 1206 | "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", 1207 | "dev": true 1208 | }, 1209 | "is-binary-path": { 1210 | "version": "2.1.0", 1211 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1212 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1213 | "dev": true, 1214 | "requires": { 1215 | "binary-extensions": "^2.0.0" 1216 | } 1217 | }, 1218 | "is-boolean-object": { 1219 | "version": "1.1.1", 1220 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", 1221 | "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", 1222 | "dev": true, 1223 | "requires": { 1224 | "call-bind": "^1.0.2" 1225 | } 1226 | }, 1227 | "is-callable": { 1228 | "version": "1.2.3", 1229 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", 1230 | "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", 1231 | "dev": true 1232 | }, 1233 | "is-core-module": { 1234 | "version": "2.4.0", 1235 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", 1236 | "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", 1237 | "dev": true, 1238 | "requires": { 1239 | "has": "^1.0.3" 1240 | } 1241 | }, 1242 | "is-date-object": { 1243 | "version": "1.0.4", 1244 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", 1245 | "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", 1246 | "dev": true 1247 | }, 1248 | "is-extglob": { 1249 | "version": "2.1.1", 1250 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1251 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1252 | "dev": true 1253 | }, 1254 | "is-fullwidth-code-point": { 1255 | "version": "3.0.0", 1256 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1257 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1258 | "dev": true 1259 | }, 1260 | "is-glob": { 1261 | "version": "4.0.1", 1262 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 1263 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 1264 | "dev": true, 1265 | "requires": { 1266 | "is-extglob": "^2.1.1" 1267 | } 1268 | }, 1269 | "is-module": { 1270 | "version": "1.0.0", 1271 | "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", 1272 | "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", 1273 | "dev": true 1274 | }, 1275 | "is-negative-zero": { 1276 | "version": "2.0.1", 1277 | "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", 1278 | "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", 1279 | "dev": true 1280 | }, 1281 | "is-number": { 1282 | "version": "7.0.0", 1283 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1284 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1285 | "dev": true 1286 | }, 1287 | "is-number-object": { 1288 | "version": "1.0.5", 1289 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", 1290 | "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", 1291 | "dev": true 1292 | }, 1293 | "is-reference": { 1294 | "version": "1.2.1", 1295 | "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", 1296 | "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", 1297 | "dev": true, 1298 | "requires": { 1299 | "@types/estree": "*" 1300 | } 1301 | }, 1302 | "is-regex": { 1303 | "version": "1.1.3", 1304 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", 1305 | "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", 1306 | "dev": true, 1307 | "requires": { 1308 | "call-bind": "^1.0.2", 1309 | "has-symbols": "^1.0.2" 1310 | } 1311 | }, 1312 | "is-string": { 1313 | "version": "1.0.6", 1314 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", 1315 | "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", 1316 | "dev": true 1317 | }, 1318 | "is-symbol": { 1319 | "version": "1.0.4", 1320 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", 1321 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", 1322 | "dev": true, 1323 | "requires": { 1324 | "has-symbols": "^1.0.2" 1325 | } 1326 | }, 1327 | "isexe": { 1328 | "version": "2.0.0", 1329 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1330 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1331 | "dev": true 1332 | }, 1333 | "js-tokens": { 1334 | "version": "4.0.0", 1335 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1336 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1337 | "dev": true 1338 | }, 1339 | "js-yaml": { 1340 | "version": "3.14.1", 1341 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 1342 | "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 1343 | "dev": true, 1344 | "requires": { 1345 | "argparse": "^1.0.7", 1346 | "esprima": "^4.0.0" 1347 | } 1348 | }, 1349 | "json-parse-better-errors": { 1350 | "version": "1.0.2", 1351 | "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", 1352 | "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", 1353 | "dev": true 1354 | }, 1355 | "json-schema-traverse": { 1356 | "version": "0.4.1", 1357 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1358 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1359 | "dev": true 1360 | }, 1361 | "json-stable-stringify-without-jsonify": { 1362 | "version": "1.0.1", 1363 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1364 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1365 | "dev": true 1366 | }, 1367 | "json5": { 1368 | "version": "1.0.1", 1369 | "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", 1370 | "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", 1371 | "dev": true, 1372 | "requires": { 1373 | "minimist": "^1.2.0" 1374 | } 1375 | }, 1376 | "kleur": { 1377 | "version": "3.0.3", 1378 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", 1379 | "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", 1380 | "dev": true 1381 | }, 1382 | "levn": { 1383 | "version": "0.4.1", 1384 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1385 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1386 | "dev": true, 1387 | "requires": { 1388 | "prelude-ls": "^1.2.1", 1389 | "type-check": "~0.4.0" 1390 | } 1391 | }, 1392 | "livereload": { 1393 | "version": "0.9.1", 1394 | "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.1.tgz", 1395 | "integrity": "sha512-9g7sua11kkyZNo2hLRCG3LuZZwqexoyEyecSlV8cAsfAVVCZqLzVir6XDqmH0r+Vzgnd5LrdHDMyjtFnJQLAYw==", 1396 | "dev": true, 1397 | "requires": { 1398 | "chokidar": "^3.3.0", 1399 | "livereload-js": "^3.1.0", 1400 | "opts": ">= 1.2.0", 1401 | "ws": "^6.2.1" 1402 | }, 1403 | "dependencies": { 1404 | "ws": { 1405 | "version": "6.2.1", 1406 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", 1407 | "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", 1408 | "dev": true, 1409 | "requires": { 1410 | "async-limiter": "~1.0.0" 1411 | } 1412 | } 1413 | } 1414 | }, 1415 | "livereload-js": { 1416 | "version": "3.3.1", 1417 | "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.3.1.tgz", 1418 | "integrity": "sha512-CBu1gTEfzVhlOK1WASKAAJ9Qx1fHECTq0SUB67sfxwQssopTyvzqTlgl+c0h9pZ6V+Fzd2rc510ppuNusg9teQ==", 1419 | "dev": true 1420 | }, 1421 | "load-json-file": { 1422 | "version": "4.0.0", 1423 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", 1424 | "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", 1425 | "dev": true, 1426 | "requires": { 1427 | "graceful-fs": "^4.1.2", 1428 | "parse-json": "^4.0.0", 1429 | "pify": "^3.0.0", 1430 | "strip-bom": "^3.0.0" 1431 | } 1432 | }, 1433 | "local-access": { 1434 | "version": "1.0.1", 1435 | "resolved": "https://registry.npmjs.org/local-access/-/local-access-1.0.1.tgz", 1436 | "integrity": "sha512-ykt2pgN0aqIy6KQC1CqdWTWkmUwNgaOS6dcpHVjyBJONA+Xi7AtSB1vuxC/U/0tjIP3wcRudwQk1YYzUvzk2bA==", 1437 | "dev": true 1438 | }, 1439 | "locate-path": { 1440 | "version": "2.0.0", 1441 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 1442 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 1443 | "dev": true, 1444 | "requires": { 1445 | "p-locate": "^2.0.0", 1446 | "path-exists": "^3.0.0" 1447 | } 1448 | }, 1449 | "lodash": { 1450 | "version": "4.17.21", 1451 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1452 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 1453 | "dev": true 1454 | }, 1455 | "lodash.clonedeep": { 1456 | "version": "4.5.0", 1457 | "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", 1458 | "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", 1459 | "dev": true 1460 | }, 1461 | "lodash.merge": { 1462 | "version": "4.6.2", 1463 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1464 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1465 | "dev": true 1466 | }, 1467 | "lodash.truncate": { 1468 | "version": "4.4.2", 1469 | "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", 1470 | "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", 1471 | "dev": true 1472 | }, 1473 | "lru-cache": { 1474 | "version": "6.0.0", 1475 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1476 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1477 | "dev": true, 1478 | "requires": { 1479 | "yallist": "^4.0.0" 1480 | } 1481 | }, 1482 | "magic-string": { 1483 | "version": "0.25.7", 1484 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", 1485 | "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", 1486 | "dev": true, 1487 | "requires": { 1488 | "sourcemap-codec": "^1.4.4" 1489 | } 1490 | }, 1491 | "merge2": { 1492 | "version": "1.4.1", 1493 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1494 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1495 | "dev": true 1496 | }, 1497 | "micromatch": { 1498 | "version": "4.0.4", 1499 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", 1500 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", 1501 | "dev": true, 1502 | "requires": { 1503 | "braces": "^3.0.1", 1504 | "picomatch": "^2.2.3" 1505 | } 1506 | }, 1507 | "mime": { 1508 | "version": "2.4.6", 1509 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", 1510 | "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", 1511 | "dev": true 1512 | }, 1513 | "minimatch": { 1514 | "version": "3.0.4", 1515 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1516 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1517 | "dev": true, 1518 | "requires": { 1519 | "brace-expansion": "^1.1.7" 1520 | } 1521 | }, 1522 | "minimist": { 1523 | "version": "1.2.5", 1524 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1525 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1526 | "dev": true 1527 | }, 1528 | "mri": { 1529 | "version": "1.1.6", 1530 | "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", 1531 | "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", 1532 | "dev": true 1533 | }, 1534 | "ms": { 1535 | "version": "2.1.2", 1536 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1537 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1538 | "dev": true 1539 | }, 1540 | "natural-compare": { 1541 | "version": "1.4.0", 1542 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1543 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1544 | "dev": true 1545 | }, 1546 | "normalize-package-data": { 1547 | "version": "2.5.0", 1548 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 1549 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 1550 | "dev": true, 1551 | "requires": { 1552 | "hosted-git-info": "^2.1.4", 1553 | "resolve": "^1.10.0", 1554 | "semver": "2 || 3 || 4 || 5", 1555 | "validate-npm-package-license": "^3.0.1" 1556 | }, 1557 | "dependencies": { 1558 | "semver": { 1559 | "version": "5.7.1", 1560 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1561 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1562 | "dev": true 1563 | } 1564 | } 1565 | }, 1566 | "normalize-path": { 1567 | "version": "3.0.0", 1568 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1569 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1570 | "dev": true 1571 | }, 1572 | "object-inspect": { 1573 | "version": "1.10.3", 1574 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", 1575 | "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", 1576 | "dev": true 1577 | }, 1578 | "object-keys": { 1579 | "version": "1.1.1", 1580 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1581 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1582 | "dev": true 1583 | }, 1584 | "object.assign": { 1585 | "version": "4.1.2", 1586 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", 1587 | "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", 1588 | "dev": true, 1589 | "requires": { 1590 | "call-bind": "^1.0.0", 1591 | "define-properties": "^1.1.3", 1592 | "has-symbols": "^1.0.1", 1593 | "object-keys": "^1.1.1" 1594 | } 1595 | }, 1596 | "object.entries": { 1597 | "version": "1.1.4", 1598 | "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.4.tgz", 1599 | "integrity": "sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA==", 1600 | "dev": true, 1601 | "requires": { 1602 | "call-bind": "^1.0.2", 1603 | "define-properties": "^1.1.3", 1604 | "es-abstract": "^1.18.2" 1605 | } 1606 | }, 1607 | "object.values": { 1608 | "version": "1.1.4", 1609 | "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", 1610 | "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", 1611 | "dev": true, 1612 | "requires": { 1613 | "call-bind": "^1.0.2", 1614 | "define-properties": "^1.1.3", 1615 | "es-abstract": "^1.18.2" 1616 | } 1617 | }, 1618 | "once": { 1619 | "version": "1.4.0", 1620 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1621 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1622 | "dev": true, 1623 | "requires": { 1624 | "wrappy": "1" 1625 | } 1626 | }, 1627 | "optionator": { 1628 | "version": "0.9.1", 1629 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 1630 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 1631 | "dev": true, 1632 | "requires": { 1633 | "deep-is": "^0.1.3", 1634 | "fast-levenshtein": "^2.0.6", 1635 | "levn": "^0.4.1", 1636 | "prelude-ls": "^1.2.1", 1637 | "type-check": "^0.4.0", 1638 | "word-wrap": "^1.2.3" 1639 | } 1640 | }, 1641 | "opts": { 1642 | "version": "2.0.2", 1643 | "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz", 1644 | "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==", 1645 | "dev": true 1646 | }, 1647 | "p-limit": { 1648 | "version": "1.3.0", 1649 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", 1650 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", 1651 | "dev": true, 1652 | "requires": { 1653 | "p-try": "^1.0.0" 1654 | } 1655 | }, 1656 | "p-locate": { 1657 | "version": "2.0.0", 1658 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 1659 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 1660 | "dev": true, 1661 | "requires": { 1662 | "p-limit": "^1.1.0" 1663 | } 1664 | }, 1665 | "p-try": { 1666 | "version": "1.0.0", 1667 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", 1668 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", 1669 | "dev": true 1670 | }, 1671 | "parent-module": { 1672 | "version": "1.0.1", 1673 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1674 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1675 | "dev": true, 1676 | "requires": { 1677 | "callsites": "^3.0.0" 1678 | } 1679 | }, 1680 | "parse-json": { 1681 | "version": "4.0.0", 1682 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", 1683 | "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", 1684 | "dev": true, 1685 | "requires": { 1686 | "error-ex": "^1.3.1", 1687 | "json-parse-better-errors": "^1.0.1" 1688 | } 1689 | }, 1690 | "path-exists": { 1691 | "version": "3.0.0", 1692 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1693 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1694 | "dev": true 1695 | }, 1696 | "path-is-absolute": { 1697 | "version": "1.0.1", 1698 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1699 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1700 | "dev": true 1701 | }, 1702 | "path-key": { 1703 | "version": "3.1.1", 1704 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1705 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1706 | "dev": true 1707 | }, 1708 | "path-parse": { 1709 | "version": "1.0.6", 1710 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1711 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 1712 | "dev": true 1713 | }, 1714 | "path-type": { 1715 | "version": "4.0.0", 1716 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 1717 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 1718 | "dev": true 1719 | }, 1720 | "picomatch": { 1721 | "version": "2.3.0", 1722 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 1723 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 1724 | "dev": true 1725 | }, 1726 | "pify": { 1727 | "version": "3.0.0", 1728 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1729 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 1730 | "dev": true 1731 | }, 1732 | "pkg-dir": { 1733 | "version": "2.0.0", 1734 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", 1735 | "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", 1736 | "dev": true, 1737 | "requires": { 1738 | "find-up": "^2.1.0" 1739 | } 1740 | }, 1741 | "pkg-up": { 1742 | "version": "2.0.0", 1743 | "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", 1744 | "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", 1745 | "dev": true, 1746 | "requires": { 1747 | "find-up": "^2.1.0" 1748 | } 1749 | }, 1750 | "prelude-ls": { 1751 | "version": "1.2.1", 1752 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1753 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1754 | "dev": true 1755 | }, 1756 | "progress": { 1757 | "version": "2.0.3", 1758 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1759 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1760 | "dev": true 1761 | }, 1762 | "punycode": { 1763 | "version": "2.1.1", 1764 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1765 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1766 | "dev": true 1767 | }, 1768 | "queue-microtask": { 1769 | "version": "1.2.3", 1770 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1771 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1772 | "dev": true 1773 | }, 1774 | "read-pkg": { 1775 | "version": "3.0.0", 1776 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", 1777 | "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", 1778 | "dev": true, 1779 | "requires": { 1780 | "load-json-file": "^4.0.0", 1781 | "normalize-package-data": "^2.3.2", 1782 | "path-type": "^3.0.0" 1783 | }, 1784 | "dependencies": { 1785 | "path-type": { 1786 | "version": "3.0.0", 1787 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", 1788 | "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", 1789 | "dev": true, 1790 | "requires": { 1791 | "pify": "^3.0.0" 1792 | } 1793 | } 1794 | } 1795 | }, 1796 | "read-pkg-up": { 1797 | "version": "3.0.0", 1798 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", 1799 | "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", 1800 | "dev": true, 1801 | "requires": { 1802 | "find-up": "^2.0.0", 1803 | "read-pkg": "^3.0.0" 1804 | } 1805 | }, 1806 | "readdirp": { 1807 | "version": "3.5.0", 1808 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", 1809 | "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", 1810 | "dev": true, 1811 | "requires": { 1812 | "picomatch": "^2.2.1" 1813 | } 1814 | }, 1815 | "regexparam": { 1816 | "version": "1.3.0", 1817 | "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-1.3.0.tgz", 1818 | "integrity": "sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g==" 1819 | }, 1820 | "regexpp": { 1821 | "version": "3.1.0", 1822 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", 1823 | "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", 1824 | "dev": true 1825 | }, 1826 | "require-from-string": { 1827 | "version": "2.0.2", 1828 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 1829 | "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", 1830 | "dev": true 1831 | }, 1832 | "require-relative": { 1833 | "version": "0.8.7", 1834 | "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", 1835 | "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", 1836 | "dev": true 1837 | }, 1838 | "resolve": { 1839 | "version": "1.20.0", 1840 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 1841 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 1842 | "dev": true, 1843 | "requires": { 1844 | "is-core-module": "^2.2.0", 1845 | "path-parse": "^1.0.6" 1846 | } 1847 | }, 1848 | "resolve-from": { 1849 | "version": "4.0.0", 1850 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1851 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1852 | "dev": true 1853 | }, 1854 | "reusify": { 1855 | "version": "1.0.4", 1856 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1857 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1858 | "dev": true 1859 | }, 1860 | "rimraf": { 1861 | "version": "3.0.2", 1862 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1863 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1864 | "dev": true, 1865 | "requires": { 1866 | "glob": "^7.1.3" 1867 | } 1868 | }, 1869 | "rollup": { 1870 | "version": "2.32.1", 1871 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.32.1.tgz", 1872 | "integrity": "sha512-Op2vWTpvK7t6/Qnm1TTh7VjEZZkN8RWgf0DHbkKzQBwNf748YhXbozHVefqpPp/Fuyk/PQPAnYsBxAEtlMvpUw==", 1873 | "dev": true, 1874 | "requires": { 1875 | "fsevents": "~2.1.2" 1876 | } 1877 | }, 1878 | "rollup-plugin-css-only": { 1879 | "version": "3.1.0", 1880 | "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz", 1881 | "integrity": "sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==", 1882 | "dev": true, 1883 | "requires": { 1884 | "@rollup/pluginutils": "4" 1885 | }, 1886 | "dependencies": { 1887 | "@rollup/pluginutils": { 1888 | "version": "4.1.0", 1889 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.0.tgz", 1890 | "integrity": "sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==", 1891 | "dev": true, 1892 | "requires": { 1893 | "estree-walker": "^2.0.1", 1894 | "picomatch": "^2.2.2" 1895 | } 1896 | } 1897 | } 1898 | }, 1899 | "rollup-plugin-livereload": { 1900 | "version": "2.0.0", 1901 | "resolved": "https://registry.npmjs.org/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.0.tgz", 1902 | "integrity": "sha512-oC/8NqumGYuphkqrfszOHUUIwzKsaHBICw6QRwT5uD07gvePTS+HW+GFwu6f9K8W02CUuTvtIM9AWJrbj4wE1A==", 1903 | "dev": true, 1904 | "requires": { 1905 | "livereload": "^0.9.1" 1906 | } 1907 | }, 1908 | "rollup-plugin-svelte": { 1909 | "version": "7.1.0", 1910 | "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz", 1911 | "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==", 1912 | "dev": true, 1913 | "requires": { 1914 | "require-relative": "^0.8.7", 1915 | "rollup-pluginutils": "^2.8.2" 1916 | } 1917 | }, 1918 | "rollup-pluginutils": { 1919 | "version": "2.8.2", 1920 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", 1921 | "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", 1922 | "dev": true, 1923 | "requires": { 1924 | "estree-walker": "^0.6.1" 1925 | }, 1926 | "dependencies": { 1927 | "estree-walker": { 1928 | "version": "0.6.1", 1929 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", 1930 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", 1931 | "dev": true 1932 | } 1933 | } 1934 | }, 1935 | "run-parallel": { 1936 | "version": "1.2.0", 1937 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1938 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1939 | "dev": true, 1940 | "requires": { 1941 | "queue-microtask": "^1.2.2" 1942 | } 1943 | }, 1944 | "sade": { 1945 | "version": "1.7.4", 1946 | "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz", 1947 | "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==", 1948 | "dev": true, 1949 | "requires": { 1950 | "mri": "^1.1.0" 1951 | } 1952 | }, 1953 | "semiver": { 1954 | "version": "1.1.0", 1955 | "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", 1956 | "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==", 1957 | "dev": true 1958 | }, 1959 | "semver": { 1960 | "version": "7.3.5", 1961 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 1962 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 1963 | "dev": true, 1964 | "requires": { 1965 | "lru-cache": "^6.0.0" 1966 | } 1967 | }, 1968 | "shebang-command": { 1969 | "version": "2.0.0", 1970 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1971 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1972 | "dev": true, 1973 | "requires": { 1974 | "shebang-regex": "^3.0.0" 1975 | } 1976 | }, 1977 | "shebang-regex": { 1978 | "version": "3.0.0", 1979 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1980 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1981 | "dev": true 1982 | }, 1983 | "sirv": { 1984 | "version": "1.0.7", 1985 | "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.7.tgz", 1986 | "integrity": "sha512-QMT2OTD3CTr8de9VByPmvSEeyt6k8/Cxg0J2kQJ5HNhIWfhFg9ypcIWWzez9rPWnGj+WtJ7AZD/MdT/vdilV/A==", 1987 | "dev": true, 1988 | "requires": { 1989 | "@polka/url": "^1.0.0-next.9", 1990 | "mime": "^2.3.1", 1991 | "totalist": "^1.0.0" 1992 | } 1993 | }, 1994 | "sirv-cli": { 1995 | "version": "1.0.8", 1996 | "resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-1.0.8.tgz", 1997 | "integrity": "sha512-bJI+kkzQvMKfAOfgLzv09kWsdymLm39LgKmGjacB19GHIAQLCvXXg8e8HzcofTjDZlA8zVv4dQjU9SWkNzkJhw==", 1998 | "dev": true, 1999 | "requires": { 2000 | "console-clear": "^1.1.0", 2001 | "get-port": "^3.2.0", 2002 | "kleur": "^3.0.0", 2003 | "local-access": "^1.0.1", 2004 | "sade": "^1.6.0", 2005 | "semiver": "^1.0.0", 2006 | "sirv": "^1.0.7", 2007 | "tinydate": "^1.0.0" 2008 | } 2009 | }, 2010 | "slash": { 2011 | "version": "3.0.0", 2012 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 2013 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2014 | "dev": true 2015 | }, 2016 | "slice-ansi": { 2017 | "version": "4.0.0", 2018 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", 2019 | "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", 2020 | "dev": true, 2021 | "requires": { 2022 | "ansi-styles": "^4.0.0", 2023 | "astral-regex": "^2.0.0", 2024 | "is-fullwidth-code-point": "^3.0.0" 2025 | } 2026 | }, 2027 | "sourcemap-codec": { 2028 | "version": "1.4.8", 2029 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 2030 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 2031 | "dev": true 2032 | }, 2033 | "spdx-correct": { 2034 | "version": "3.1.1", 2035 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", 2036 | "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", 2037 | "dev": true, 2038 | "requires": { 2039 | "spdx-expression-parse": "^3.0.0", 2040 | "spdx-license-ids": "^3.0.0" 2041 | } 2042 | }, 2043 | "spdx-exceptions": { 2044 | "version": "2.3.0", 2045 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", 2046 | "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", 2047 | "dev": true 2048 | }, 2049 | "spdx-expression-parse": { 2050 | "version": "3.0.1", 2051 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", 2052 | "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", 2053 | "dev": true, 2054 | "requires": { 2055 | "spdx-exceptions": "^2.1.0", 2056 | "spdx-license-ids": "^3.0.0" 2057 | } 2058 | }, 2059 | "spdx-license-ids": { 2060 | "version": "3.0.9", 2061 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", 2062 | "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", 2063 | "dev": true 2064 | }, 2065 | "sprintf-js": { 2066 | "version": "1.0.3", 2067 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2068 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2069 | "dev": true 2070 | }, 2071 | "string-width": { 2072 | "version": "4.2.2", 2073 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 2074 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 2075 | "dev": true, 2076 | "requires": { 2077 | "emoji-regex": "^8.0.0", 2078 | "is-fullwidth-code-point": "^3.0.0", 2079 | "strip-ansi": "^6.0.0" 2080 | } 2081 | }, 2082 | "string.prototype.trimend": { 2083 | "version": "1.0.4", 2084 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", 2085 | "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", 2086 | "dev": true, 2087 | "requires": { 2088 | "call-bind": "^1.0.2", 2089 | "define-properties": "^1.1.3" 2090 | } 2091 | }, 2092 | "string.prototype.trimstart": { 2093 | "version": "1.0.4", 2094 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", 2095 | "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", 2096 | "dev": true, 2097 | "requires": { 2098 | "call-bind": "^1.0.2", 2099 | "define-properties": "^1.1.3" 2100 | } 2101 | }, 2102 | "strip-ansi": { 2103 | "version": "6.0.0", 2104 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2105 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2106 | "dev": true, 2107 | "requires": { 2108 | "ansi-regex": "^5.0.0" 2109 | } 2110 | }, 2111 | "strip-bom": { 2112 | "version": "3.0.0", 2113 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 2114 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 2115 | "dev": true 2116 | }, 2117 | "strip-json-comments": { 2118 | "version": "3.1.1", 2119 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2120 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2121 | "dev": true 2122 | }, 2123 | "supports-color": { 2124 | "version": "7.2.0", 2125 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2126 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2127 | "dev": true, 2128 | "requires": { 2129 | "has-flag": "^4.0.0" 2130 | } 2131 | }, 2132 | "svelte": { 2133 | "version": "3.38.2", 2134 | "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.38.2.tgz", 2135 | "integrity": "sha512-q5Dq0/QHh4BLJyEVWGe7Cej5NWs040LWjMbicBGZ+3qpFWJ1YObRmUDZKbbovddLC9WW7THTj3kYbTOFmU9fbg==", 2136 | "dev": true 2137 | }, 2138 | "table": { 2139 | "version": "6.7.1", 2140 | "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", 2141 | "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", 2142 | "dev": true, 2143 | "requires": { 2144 | "ajv": "^8.0.1", 2145 | "lodash.clonedeep": "^4.5.0", 2146 | "lodash.truncate": "^4.4.2", 2147 | "slice-ansi": "^4.0.0", 2148 | "string-width": "^4.2.0", 2149 | "strip-ansi": "^6.0.0" 2150 | }, 2151 | "dependencies": { 2152 | "ajv": { 2153 | "version": "8.5.0", 2154 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz", 2155 | "integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==", 2156 | "dev": true, 2157 | "requires": { 2158 | "fast-deep-equal": "^3.1.1", 2159 | "json-schema-traverse": "^1.0.0", 2160 | "require-from-string": "^2.0.2", 2161 | "uri-js": "^4.2.2" 2162 | } 2163 | }, 2164 | "json-schema-traverse": { 2165 | "version": "1.0.0", 2166 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", 2167 | "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", 2168 | "dev": true 2169 | } 2170 | } 2171 | }, 2172 | "text-table": { 2173 | "version": "0.2.0", 2174 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2175 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2176 | "dev": true 2177 | }, 2178 | "tinydate": { 2179 | "version": "1.3.0", 2180 | "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz", 2181 | "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==", 2182 | "dev": true 2183 | }, 2184 | "to-regex-range": { 2185 | "version": "5.0.1", 2186 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2187 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2188 | "dev": true, 2189 | "requires": { 2190 | "is-number": "^7.0.0" 2191 | } 2192 | }, 2193 | "totalist": { 2194 | "version": "1.1.0", 2195 | "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", 2196 | "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", 2197 | "dev": true 2198 | }, 2199 | "tsconfig-paths": { 2200 | "version": "3.9.0", 2201 | "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", 2202 | "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", 2203 | "dev": true, 2204 | "requires": { 2205 | "@types/json5": "^0.0.29", 2206 | "json5": "^1.0.1", 2207 | "minimist": "^1.2.0", 2208 | "strip-bom": "^3.0.0" 2209 | } 2210 | }, 2211 | "tslib": { 2212 | "version": "2.0.3", 2213 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", 2214 | "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", 2215 | "dev": true 2216 | }, 2217 | "tsutils": { 2218 | "version": "3.21.0", 2219 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", 2220 | "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", 2221 | "dev": true, 2222 | "requires": { 2223 | "tslib": "^1.8.1" 2224 | }, 2225 | "dependencies": { 2226 | "tslib": { 2227 | "version": "1.14.1", 2228 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 2229 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 2230 | "dev": true 2231 | } 2232 | } 2233 | }, 2234 | "type-check": { 2235 | "version": "0.4.0", 2236 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2237 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2238 | "dev": true, 2239 | "requires": { 2240 | "prelude-ls": "^1.2.1" 2241 | } 2242 | }, 2243 | "type-fest": { 2244 | "version": "0.20.2", 2245 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 2246 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2247 | "dev": true 2248 | }, 2249 | "typescript": { 2250 | "version": "4.1.2", 2251 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz", 2252 | "integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==", 2253 | "dev": true 2254 | }, 2255 | "unbox-primitive": { 2256 | "version": "1.0.1", 2257 | "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", 2258 | "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", 2259 | "dev": true, 2260 | "requires": { 2261 | "function-bind": "^1.1.1", 2262 | "has-bigints": "^1.0.1", 2263 | "has-symbols": "^1.0.2", 2264 | "which-boxed-primitive": "^1.0.2" 2265 | } 2266 | }, 2267 | "uri-js": { 2268 | "version": "4.4.1", 2269 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2270 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2271 | "dev": true, 2272 | "requires": { 2273 | "punycode": "^2.1.0" 2274 | } 2275 | }, 2276 | "v8-compile-cache": { 2277 | "version": "2.3.0", 2278 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 2279 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 2280 | "dev": true 2281 | }, 2282 | "validate-npm-package-license": { 2283 | "version": "3.0.4", 2284 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 2285 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 2286 | "dev": true, 2287 | "requires": { 2288 | "spdx-correct": "^3.0.0", 2289 | "spdx-expression-parse": "^3.0.0" 2290 | } 2291 | }, 2292 | "which": { 2293 | "version": "2.0.2", 2294 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2295 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2296 | "dev": true, 2297 | "requires": { 2298 | "isexe": "^2.0.0" 2299 | } 2300 | }, 2301 | "which-boxed-primitive": { 2302 | "version": "1.0.2", 2303 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", 2304 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", 2305 | "dev": true, 2306 | "requires": { 2307 | "is-bigint": "^1.0.1", 2308 | "is-boolean-object": "^1.1.0", 2309 | "is-number-object": "^1.0.4", 2310 | "is-string": "^1.0.5", 2311 | "is-symbol": "^1.0.3" 2312 | } 2313 | }, 2314 | "word-wrap": { 2315 | "version": "1.2.3", 2316 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2317 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 2318 | "dev": true 2319 | }, 2320 | "wrappy": { 2321 | "version": "1.0.2", 2322 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2323 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2324 | "dev": true 2325 | }, 2326 | "yallist": { 2327 | "version": "4.0.0", 2328 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2329 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2330 | "dev": true 2331 | } 2332 | } 2333 | } 2334 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-stack-router", 3 | "version": "2.4.6", 4 | "description": "Bridging the gap between Native Apps and WebApps. A Svelte Router that caches page components and will make your WebApp feel more native", 5 | "main": "dist/index.cjs", 6 | "module": "dist/index.js", 7 | "svelte": "src/index.js", 8 | "types": "dist/index.d.ts", 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1", 11 | "build": "tsc && rimraf dist && rollup -c && tsc -d --emitDeclarationOnly --declarationDir dist && cp src/index.d.ts dist/index.d.ts", 12 | "prepublishOnly": "npm run build", 13 | "start": "sirv docs --host", 14 | "dev": "npm run build && rollup --config rollup.preview.config.js -w", 15 | "build:preview": "npm run build && rollup --config rollup.preview.config.js" 16 | }, 17 | "keywords": [ 18 | "spa", 19 | "router", 20 | "stack", 21 | "svelte", 22 | "cache" 23 | ], 24 | "repository": { 25 | "type": "git", 26 | "url": "git+https://github.com/cdellacqua/svelte-stack-router.git" 27 | }, 28 | "bugs": { 29 | "url": "https://github.com/cdellacqua/svelte-stack-router/issues" 30 | }, 31 | "homepage": "https://github.com/cdellacqua/svelte-stack-router", 32 | "files": [ 33 | "src/index.js", 34 | "src/stack-router.js", 35 | "src/transition-functions.js", 36 | "src/types.js", 37 | "src/utils.js", 38 | "src/StackRouter.svelte", 39 | "dist" 40 | ], 41 | "exports": { 42 | ".": { 43 | "import": "./dist/index.js", 44 | "require": "./dist/index.cjs" 45 | }, 46 | "./package.json": "./package.json" 47 | }, 48 | "author": "Carlo Dell'Acqua", 49 | "license": "MIT", 50 | "devDependencies": { 51 | "@rollup/plugin-commonjs": "^16.0.0", 52 | "@rollup/plugin-node-resolve": "^10.0.0", 53 | "@tsconfig/svelte": "^1.0.10", 54 | "@typescript-eslint/eslint-plugin": "^4.25.0", 55 | "@typescript-eslint/parser": "^4.25.0", 56 | "eslint": "^7.27.0", 57 | "eslint-config-airbnb-base": "^14.2.1", 58 | "eslint-plugin-import": "^2.23.4", 59 | "rimraf": "^3.0.2", 60 | "rollup": "^2.3.4", 61 | "rollup-plugin-css-only": "^3.1.0", 62 | "rollup-plugin-livereload": "^2.0.0", 63 | "rollup-plugin-svelte": "^7.1.0", 64 | "sirv-cli": "^1.0.8", 65 | "svelte": "^3.37.0", 66 | "tslib": "^2.0.3", 67 | "typescript": "^4.1.2" 68 | }, 69 | "dependencies": { 70 | "regexparam": "^1.3.0" 71 | }, 72 | "peerDependencies": { 73 | "svelte": "^3.38.2" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import resolve from '@rollup/plugin-node-resolve'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | import pkg from './package.json'; 5 | import css from 'rollup-plugin-css-only'; 6 | 7 | const production = !process.env.ROLLUP_WATCH; 8 | 9 | const external = [ 10 | ...Object.keys(pkg.devDependencies || {}), 11 | ...Object.keys(pkg.peerDependencies || {}), 12 | ...Object.keys(pkg.dependencies || {}) 13 | ]; 14 | 15 | export default { 16 | input: 'src/index.js', 17 | output: [ 18 | { file: pkg.main, format: 'cjs' }, 19 | { file: pkg.module, format: 'es' } 20 | ], 21 | external, 22 | plugins: [ 23 | svelte({ 24 | compilerOptions: { 25 | dev: !production, 26 | }, 27 | }), 28 | css({ output: 'bundle.css' }), 29 | 30 | // If you have external dependencies installed from 31 | // npm, you'll most likely need these plugins. In 32 | // some cases you'll need additional configuration - 33 | // consult the documentation for details: 34 | // https://github.com/rollup/plugins/tree/master/packages/commonjs 35 | resolve({ 36 | browser: true, 37 | dedupe: ['svelte'], 38 | }), 39 | commonjs({ 40 | include: 'node_modules/**', 41 | }) 42 | ], 43 | }; 44 | -------------------------------------------------------------------------------- /rollup.preview.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import resolve from '@rollup/plugin-node-resolve'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | import pkg from './package.json'; 5 | import livereload from 'rollup-plugin-livereload'; 6 | import css from 'rollup-plugin-css-only'; 7 | 8 | const name = pkg.name 9 | .replace(/^(@\S+\/)?(svelte-)?(\S+)/, '$3') 10 | .replace(/^\w/, m => m.toUpperCase()) 11 | .replace(/-\w/g, m => m[1].toUpperCase()); 12 | 13 | const production = !process.env.ROLLUP_WATCH; 14 | 15 | function serve() { 16 | let server; 17 | 18 | function toExit() { 19 | if (server) server.kill(0); 20 | } 21 | 22 | return { 23 | writeBundle() { 24 | if (server) return; 25 | server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { 26 | stdio: ['ignore', 'inherit', 'inherit'], 27 | shell: true 28 | }); 29 | 30 | process.on('SIGTERM', toExit); 31 | process.on('exit', toExit); 32 | } 33 | }; 34 | } 35 | 36 | 37 | export default [{ 38 | input: 'src/preview.js', 39 | output: { 40 | sourcemap: true, 41 | format: 'iife', 42 | name, 43 | file: 'docs/build/bundle.js' 44 | }, 45 | plugins: [ 46 | svelte({ 47 | compilerOptions: { 48 | dev: !production, 49 | }, 50 | }), 51 | css({ output: 'bundle.css' }), 52 | 53 | // If you have external dependencies installed from 54 | // npm, you'll most likely need these plugins. In 55 | // some cases you'll need additional configuration - 56 | // consult the documentation for details: 57 | // https://github.com/rollup/plugins/tree/master/packages/commonjs 58 | resolve({ 59 | browser: true, 60 | dedupe: ['svelte'] 61 | }), 62 | commonjs(), 63 | 64 | // In dev mode, call `npm run start` once 65 | // the bundle has been generated 66 | !production && serve(), 67 | 68 | // Watch the `docs` directory and refresh the 69 | // browser on changes when not in production 70 | !production && livereload('docs'), 71 | ], 72 | watch: { 73 | clearScreen: false 74 | } 75 | }]; 76 | -------------------------------------------------------------------------------- /src-ts/stack-router.ts: -------------------------------------------------------------------------------- 1 | import regexparam from 'regexparam'; 2 | import { SvelteComponent, tick } from 'svelte'; 3 | import { noop } from 'svelte/internal'; 4 | import { 5 | readable, derived, writable, get, 6 | } from 'svelte/store'; 7 | import { noAnimation } from './transition-functions'; 8 | import { 9 | CacheEntry, 10 | ComponentConfig, 11 | Config, 12 | HistoryItem, 13 | HistoryState, 14 | NavigationType, 15 | LoadableEntryAction, 16 | UnloadableEntryAction, 17 | Routes, 18 | Params, 19 | StackRouterEvent, 20 | StackRouterEventType, 21 | RouteDescriptor, 22 | SvelteComponentConstructor, 23 | } from './types'; 24 | import { dispatchCustomEvent, sleep } from './utils'; 25 | 26 | const config: Config = { 27 | defaultResumable: true, 28 | useHash: true, 29 | restoreScroll: true, 30 | routes: {}, 31 | mountPoint: null, 32 | transitionFn: noAnimation(), 33 | dispatch: null, 34 | }; 35 | 36 | const internalCache = writable([]); 37 | /** Current component cache readable store */ 38 | export const cache = derived(internalCache, (x) => x); 39 | 40 | /* LOCATION */ 41 | function getLocation(): string { 42 | if (config.useHash) { 43 | const hashIndex = window.location.href.indexOf('#/'); 44 | const location = hashIndex > -1 ? window.location.href.substring(hashIndex + 1) : '/'; 45 | return location; 46 | } 47 | const relativeUrl = (window.location.pathname || '/') + window.location.search; 48 | return relativeUrl; 49 | } 50 | 51 | // Used in the `pop` function to prevent a double trigger of the PopStateEvent 52 | let ignorePopStateEvent = false; 53 | 54 | const _location = writable(getLocation(), (set) => { 55 | let previousLocation: string | null = null; 56 | const handlePopState = async () => { 57 | if (ignorePopStateEvent) { 58 | return; 59 | } 60 | const newLocation = getLocation(); 61 | if (previousLocation !== newLocation) { 62 | previousLocation = newLocation; 63 | set(newLocation); 64 | } 65 | }; 66 | window.addEventListener('popstate', handlePopState); 67 | return function stop() { 68 | window.removeEventListener('popstate', handlePopState); 69 | }; 70 | }); 71 | 72 | /** 73 | * Readable store representing the current location 74 | */ 75 | export const location = derived(_location, ($_location) => $_location); 76 | 77 | /* PATHNAME */ 78 | function getPathname(location: string): string { 79 | const queryStringPosition = location.indexOf('?'); 80 | if (queryStringPosition !== -1) { 81 | return location.substring(0, queryStringPosition); 82 | } 83 | return location; 84 | } 85 | /** 86 | * Readable store that contains the pathname part of the location 87 | */ 88 | export const pathname = derived(location, getPathname); 89 | 90 | /* SEARCH */ 91 | function getSearch(location: string): string { 92 | const queryStringPosition = location.indexOf('?'); 93 | if (queryStringPosition !== -1) { 94 | return location.substring(queryStringPosition); 95 | } 96 | return ''; 97 | } 98 | /** 99 | * Readable store that contains the search part of the location 100 | */ 101 | export const search = derived(location, getSearch); 102 | 103 | /* UTILS */ 104 | let lastHistoryTimestamp: number; 105 | async function waitForHistoryState(callback: () => void): Promise { 106 | const historyState = window.history.state; 107 | 108 | callback(); 109 | 110 | // Wait for history.state to pick the current state (without this sleep history.state points to the previous state) 111 | // See https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event 112 | let limit = 100; 113 | while (historyState === window.history.state && limit) { 114 | await sleep(2); 115 | limit--; 116 | } 117 | if (historyState === window.history.state) { 118 | console.warn('unable to detect history change'); 119 | } 120 | } 121 | 122 | function buildParams(pathname: string, routeKey: string): Params | undefined { 123 | const { pattern, keys } = regexparam(routeKey); 124 | const matches = pattern.exec(pathname) || []; 125 | const params = keys.reduce((params, _, index) => { 126 | params[keys[index]] = matches[index + 1] === undefined ? null : decodeURIComponent(matches[index + 1]); 127 | return params; 128 | }, {} as Params); 129 | return Object.keys(params).length === 0 ? undefined : params; 130 | } 131 | 132 | /* EVENT-BASED EXECUTION */ 133 | const eventQueue: StackRouterEvent[] = []; 134 | function enqueueEvent(event: StackRouterEvent): void { 135 | eventQueue.push(event); 136 | consumeQueue(); 137 | } 138 | 139 | let consumingQueue = false; 140 | async function consumeQueue(): Promise { 141 | if (consumingQueue) { 142 | return; 143 | } 144 | consumingQueue = true; 145 | while (eventQueue.length > 0) { 146 | const item = eventQueue.shift()!; 147 | switch (item.type) { 148 | case StackRouterEventType.Navigate: 149 | await handleHistoryChange(item.payload); 150 | break; 151 | case StackRouterEventType.Mount: 152 | await mount(item.payload); 153 | break; 154 | case StackRouterEventType.Destroy: 155 | await destroy(); 156 | break; 157 | case StackRouterEventType.UpdateConfig: 158 | await updateConfig(item.payload); 159 | break; 160 | // no default 161 | } 162 | } 163 | consumingQueue = false; 164 | } 165 | 166 | /* INIT & DESTROY */ 167 | let locationSubscription = noop; 168 | 169 | export function handleUpdateConfig(initConfig: Partial> & { routes: Routes }): void { 170 | enqueueEvent({ 171 | type: StackRouterEventType.UpdateConfig, 172 | payload: initConfig, 173 | }); 174 | } 175 | 176 | function updateConfig(initConfig: Partial> & { routes: Routes }): void { 177 | const previousUseHash = config.useHash; 178 | 179 | (Object.keys(initConfig) as (keyof Omit)[]) 180 | .forEach((key) => { 181 | if (initConfig[key] !== undefined) { 182 | config[key] = initConfig[key] as any; 183 | } 184 | }); 185 | 186 | if (previousUseHash !== config.useHash) { 187 | const currentLocation = getLocation(); 188 | if (get(_location) !== currentLocation) { 189 | _location.set(currentLocation); 190 | } 191 | } 192 | 193 | if ('scrollRestoration' in window.history) { 194 | window.history.scrollRestoration = config.restoreScroll ? 'manual' : 'auto'; 195 | } 196 | } 197 | 198 | export function handleStackRouterComponentMount(initConfig: Partial & { routes: Routes, mountPoint: HTMLDivElement }): void { 199 | enqueueEvent({ 200 | type: StackRouterEventType.Mount, 201 | payload: initConfig, 202 | }); 203 | } 204 | 205 | function mount(initConfig: Partial & { routes: Routes, mountPoint: HTMLDivElement }) { 206 | updateConfig(initConfig); 207 | 208 | const firstRun = true; 209 | let previousState: HistoryState | null = null; 210 | 211 | locationSubscription = location 212 | .subscribe( 213 | async ($location) => { 214 | // Wait for history.state to pick the current state (without this sleep history.state can point to the previous state) 215 | // See https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event 216 | let currentState = window.history.state; 217 | if (!firstRun && currentState !== undefined) { 218 | let limit = 100; 219 | while (previousState === currentState && limit) { 220 | await sleep(2); 221 | limit--; 222 | currentState = window.history.state; 223 | } 224 | if (previousState === currentState) { 225 | console.warn('unable to detect history change'); 226 | } 227 | } 228 | enqueueEvent({ 229 | type: StackRouterEventType.Navigate, 230 | payload: { 231 | location: $location, 232 | state: currentState, 233 | }, 234 | }); 235 | previousState = currentState; 236 | }, 237 | ); 238 | } 239 | 240 | export function handleStackRouterComponentDestroy(): void { 241 | enqueueEvent({ 242 | type: StackRouterEventType.Destroy, 243 | }); 244 | } 245 | 246 | async function destroy() { 247 | locationSubscription(); 248 | const currentCache = get(internalCache); 249 | for (const entry of currentCache) { 250 | // eslint-disable-next-line no-use-before-define 251 | if (entry === activeCacheEntry) { 252 | if (entry.entryConfig.onBeforeUnload && entry.entryConfig.onBeforeUnload.length > 0) { 253 | for (const callback of entry.entryConfig.onBeforeUnload) { 254 | await callback(true); 255 | } 256 | } 257 | if (entry.entryConfig.resumable && entry.entryConfig.onPause && entry.entryConfig.onPause.length > 0) { 258 | for (const callback of entry.entryConfig.onPause) { 259 | await callback(true); 260 | } 261 | } 262 | if (entry.entryConfig.onAfterUnload && entry.entryConfig.onAfterUnload.length > 0) { 263 | for (const callback of entry.entryConfig.onAfterUnload) { 264 | await callback(true); 265 | } 266 | } 267 | } 268 | entry.componentInstance.$destroy(); 269 | } 270 | // eslint-disable-next-line no-use-before-define 271 | activeCacheEntry = null; 272 | internalCache.set([]); 273 | locationSubscription = noop; 274 | config.mountPoint = null; 275 | config.dispatch = null; 276 | } 277 | 278 | let editableEntryConfig: ComponentConfig | null = null; 279 | async function prepareCacheEntryToActivate(cache: CacheEntry[], pathname: string): Promise { 280 | const routeKeys = Object.keys(config.routes); 281 | const routeKey = routeKeys.find((routeKey) => { 282 | const { pattern } = regexparam(routeKey); 283 | return pattern.test(pathname); 284 | }); 285 | if (routeKey === undefined || routeKey === null) { 286 | return { 287 | message: 'no route found', 288 | }; 289 | } 290 | const params = buildParams(pathname, routeKey); 291 | 292 | const routeDescriptor = typeof config.routes[routeKey] === 'object' ? (config.routes[routeKey] as RouteDescriptor) : ({} as RouteDescriptor); 293 | 294 | // Check guards before updating params 295 | const guards = routeDescriptor.guards 296 | || (routeDescriptor.guard && [routeDescriptor.guard!]) 297 | || []; 298 | for (const guard of guards) { 299 | try { 300 | if (!await guard(params)) { 301 | return { 302 | message: 'access forbidden by guard', 303 | params, 304 | }; 305 | } 306 | } catch (err) { 307 | return { 308 | message: 'guard error', 309 | params, 310 | err, 311 | }; 312 | } 313 | } 314 | 315 | const resumableEntry = cache.find( 316 | (s) => s.routeMatch === routeKey, 317 | ); 318 | 319 | let entry: CacheEntry | undefined; 320 | if (resumableEntry) { 321 | editableEntryConfig = resumableEntry.entryConfig; 322 | entry = resumableEntry; 323 | 324 | if (resumableEntry.pathname !== pathname) { 325 | resumableEntry.componentInstance.$set({ params }); 326 | resumableEntry.pathname = pathname; 327 | } 328 | } else { 329 | const mountPoint = document.createElement('div'); 330 | 331 | editableEntryConfig = { 332 | resumable: config.defaultResumable, 333 | }; 334 | 335 | let component: SvelteComponentConstructor; 336 | 337 | if (typeof config.routes[routeKey] !== 'object') { 338 | component = config.routes[routeKey] as SvelteComponentConstructor; 339 | } else if (routeDescriptor.component) { 340 | component = routeDescriptor.component; 341 | } else if (routeDescriptor.componentProvider) { 342 | try { 343 | const resolved = await routeDescriptor.componentProvider(); 344 | component = (resolved as unknown as { default: SvelteComponentConstructor }).default || resolved; 345 | 346 | // Cache the promise result so that it will be available in the future 347 | // without having to call the provider again 348 | routeDescriptor.component = component; 349 | } catch (err) { 350 | return { 351 | message: 'unable to get component from provider', 352 | err, 353 | }; 354 | } 355 | } else { 356 | return { 357 | message: 'unable to get a component constructor', 358 | err: new Error('unable to get a component constructor'), 359 | }; 360 | } 361 | 362 | entry = { 363 | component, 364 | // eslint-disable-next-line new-cap 365 | componentInstance: new component({ target: mountPoint, props: { params } }), 366 | mountPoint, 367 | pathname, 368 | routeMatch: routeKey, 369 | entryConfig: editableEntryConfig, 370 | }; 371 | } 372 | 373 | await tick(); 374 | 375 | editableEntryConfig = null; 376 | 377 | return entry; 378 | } 379 | 380 | let activeCacheEntry: CacheEntry | null = null; 381 | async function handleHistoryChange(historyItem: HistoryItem): Promise { 382 | const currentCache: CacheEntry[] = get(internalCache); 383 | 384 | const isNewHistoryItem = !historyItem.state; 385 | if (isNewHistoryItem) { 386 | historyItem.state = { 387 | timestamp: new Date().getTime(), 388 | }; 389 | await waitForHistoryState(() => window.history.replaceState(historyItem.state, '', (config.useHash ? '#' : '') + historyItem.location)); 390 | } 391 | 392 | const pageToLoadResult = await prepareCacheEntryToActivate(currentCache, getPathname(historyItem.location)); 393 | if ('message' in pageToLoadResult) { 394 | switch (pageToLoadResult.message) { 395 | case 'access forbidden by guard': 396 | config.dispatch?.('forbidden', { 397 | ...pageToLoadResult, 398 | location: historyItem.location, 399 | }); 400 | break; 401 | default: 402 | config.dispatch?.('error', { 403 | ...pageToLoadResult, 404 | location: historyItem.location, 405 | }); 406 | break; 407 | } 408 | return; 409 | } 410 | const pageToLoad: CacheEntry = pageToLoadResult; 411 | const pageToUnload = activeCacheEntry; 412 | const newTopIndexInCurrentStack = currentCache.findIndex((s) => s.routeMatch === pageToLoad.routeMatch); 413 | 414 | let pageToLoadAction = LoadableEntryAction.NoOp; 415 | let pageToUnloadAction = UnloadableEntryAction.NoOp; 416 | let navigationType: NavigationType = NavigationType.GoForwardNewState; 417 | 418 | if (!pageToUnload) { 419 | pageToLoadAction = LoadableEntryAction.New; 420 | } else { 421 | if (pageToUnload.routeMatch !== pageToLoad.routeMatch) { 422 | if (newTopIndexInCurrentStack !== -1) { 423 | pageToLoadAction = LoadableEntryAction.Resume; 424 | } else { 425 | pageToLoadAction = LoadableEntryAction.New; 426 | } 427 | if (pageToUnload.entryConfig.resumable) { 428 | pageToUnloadAction = UnloadableEntryAction.Pause; 429 | } else { 430 | pageToUnloadAction = UnloadableEntryAction.Destroy; 431 | } 432 | } 433 | 434 | if (isNewHistoryItem) { 435 | navigationType = NavigationType.GoForwardNewState; 436 | } else if (historyItem.state.timestamp > lastHistoryTimestamp) { 437 | navigationType = NavigationType.GoForwardResumeState; 438 | } else if (historyItem.state.timestamp < lastHistoryTimestamp) { 439 | navigationType = NavigationType.GoBackward; 440 | } else { 441 | navigationType = NavigationType.Replace; 442 | } 443 | } 444 | 445 | config.dispatch?.('navigation-start', { 446 | location: historyItem.location, 447 | navigationType, 448 | pageToLoad, 449 | pageToUnload, 450 | pageToLoadAction, 451 | pageToUnloadAction, 452 | }); 453 | 454 | // BEFORE TRANSITION 455 | async function beforeUnload() { 456 | if ( 457 | pageToUnload 458 | && pageToUnloadAction !== UnloadableEntryAction.NoOp 459 | && pageToUnload.entryConfig.onBeforeUnload 460 | && pageToUnload.entryConfig.onBeforeUnload.length > 0 461 | ) { 462 | for (const callback of pageToUnload.entryConfig.onBeforeUnload) { 463 | await callback(); 464 | } 465 | } 466 | } 467 | 468 | async function beforeLoad() { 469 | if ( 470 | pageToLoad 471 | && pageToLoadAction !== LoadableEntryAction.NoOp 472 | && pageToLoad.entryConfig.onBeforeLoad 473 | && pageToLoad.entryConfig.onBeforeLoad.length > 0 474 | ) { 475 | for (const callback of pageToLoad.entryConfig.onBeforeLoad) { 476 | await callback(); 477 | } 478 | } 479 | } 480 | 481 | await Promise.all([beforeUnload(), beforeLoad()]); 482 | 483 | // DURING TRANSITION 484 | async function pause() { 485 | if ( 486 | pageToUnload 487 | && pageToUnloadAction === UnloadableEntryAction.Pause 488 | && pageToUnload.entryConfig.onPause 489 | && pageToUnload.entryConfig.onPause.length > 0 490 | ) { 491 | for (const callback of pageToUnload.entryConfig.onPause) { 492 | await callback(); 493 | } 494 | } 495 | } 496 | 497 | async function resume() { 498 | if (pageToLoad && pageToLoadAction === LoadableEntryAction.Resume) { 499 | const { returnValue } = historyItem.state || {}; 500 | await waitForHistoryState(() => { 501 | // Remove returnValue and scroll 502 | window.history.replaceState( 503 | { 504 | timestamp: historyItem.state.timestamp, 505 | } as HistoryState, 506 | '', 507 | (config.useHash ? '#' : '') + historyItem.location, 508 | ); 509 | }); 510 | if (pageToLoad.entryConfig.onResume && pageToLoad.entryConfig.onResume.length > 0) { 511 | for (const callback of pageToLoad.entryConfig.onResume) { 512 | await callback(returnValue); 513 | } 514 | } 515 | } 516 | } 517 | 518 | const oldTopMountPoint = pageToUnload ? pageToUnload.mountPoint : null; 519 | const newTopMountPoint = pageToLoad.mountPoint; 520 | 521 | if (oldTopMountPoint !== newTopMountPoint) { 522 | async function transition() { 523 | if (config.mountPoint) { 524 | if (!newTopMountPoint.parentElement) { 525 | config.mountPoint.appendChild(newTopMountPoint); 526 | } 527 | 528 | await config.transitionFn({ 529 | navigationType, 530 | routerMountPoint: config.mountPoint, 531 | mountPointToLoad: newTopMountPoint, 532 | mountPointToUnload: oldTopMountPoint, 533 | scroll: historyItem.state.scroll || { x: 0, y: 0 }, 534 | }); 535 | 536 | if (oldTopMountPoint) { 537 | config.mountPoint.removeChild(oldTopMountPoint); 538 | } 539 | } 540 | } 541 | 542 | await Promise.all([ 543 | transition(), 544 | pause(), 545 | resume(), 546 | ]); 547 | } 548 | 549 | // AFTER TRANSITION 550 | async function afterLoad() { 551 | if ( 552 | pageToLoad 553 | && pageToLoadAction !== LoadableEntryAction.NoOp 554 | && pageToLoad.entryConfig.onAfterLoad 555 | && pageToLoad.entryConfig.onAfterLoad.length > 0 556 | ) { 557 | for (const callback of pageToLoad.entryConfig.onAfterLoad) { 558 | await callback(); 559 | } 560 | } 561 | } 562 | 563 | async function afterUnload() { 564 | if ( 565 | pageToUnload 566 | && pageToUnloadAction !== UnloadableEntryAction.NoOp 567 | && pageToUnload.entryConfig.onAfterUnload 568 | && pageToUnload.entryConfig.onAfterUnload.length > 0 569 | ) { 570 | for (const callback of pageToUnload.entryConfig.onAfterUnload) { 571 | await callback(); 572 | } 573 | } 574 | } 575 | 576 | await Promise.all([afterLoad(), afterUnload()]); 577 | 578 | if (pageToLoadAction === LoadableEntryAction.New) { 579 | currentCache.push(pageToLoad); 580 | } 581 | if (pageToUnload && pageToUnloadAction === UnloadableEntryAction.Destroy) { 582 | pageToUnload.componentInstance.$destroy(); 583 | currentCache.splice(currentCache.indexOf(pageToUnload), 1); 584 | } 585 | internalCache.set(currentCache); 586 | activeCacheEntry = pageToLoad; 587 | 588 | lastHistoryTimestamp = historyItem.state.timestamp; 589 | 590 | config.dispatch?.('navigation-end', { 591 | location: historyItem.location, 592 | navigationType, 593 | pageToLoad, 594 | pageToUnload, 595 | pageToLoadAction, 596 | pageToUnloadAction, 597 | }); 598 | } 599 | 600 | /* API FUNCTIONS */ 601 | /** 602 | * Replaces the current history location and state 603 | * If the new location equals the current one, this function won't modify the browser history 604 | * @param location new location 605 | * @param state new history state 606 | */ 607 | export async function replace(location: string, state?: HistoryState): Promise { 608 | if (location === getLocation()) { 609 | return; 610 | } 611 | await waitForHistoryState(() => { 612 | window.history.replaceState({ 613 | ...(state || {}), 614 | timestamp: lastHistoryTimestamp, 615 | }, 616 | '', 617 | (config.useHash ? '#' : '') + location); 618 | }); 619 | 620 | dispatchCustomEvent(window as any, 'popstate'); 621 | } 622 | 623 | /** 624 | * Navigates to a new location 625 | * If scroll restoration is enabled, the current window scroll position is persisted before leaving the current location 626 | * If the new location equals the current one, this function won't modify the browser history 627 | * @param location new location 628 | */ 629 | export async function push(location: string): Promise { 630 | if (location === getLocation()) { 631 | return; 632 | } 633 | 634 | if (config.restoreScroll) { 635 | await waitForHistoryState(() => { 636 | window.history.replaceState({ 637 | timestamp: window.history.state ? window.history.state.timestamp : new Date().getTime(), 638 | scroll: { 639 | x: window.scrollX, 640 | y: window.scrollY, 641 | }, 642 | }, '', (config.useHash ? '#' : '') + getLocation()); 643 | }); 644 | } 645 | 646 | await waitForHistoryState(() => { 647 | window.history.pushState( 648 | undefined, 649 | '', 650 | (config.useHash ? '#' : '') + location, 651 | ); 652 | }); 653 | 654 | dispatchCustomEvent(window as any, 'popstate'); 655 | } 656 | 657 | /** 658 | * Navigates back 659 | * @param returnValue a serializable object that will be returned to the component associated with the previous location if resumable 660 | */ 661 | export async function pop(returnValue?: any): Promise { 662 | ignorePopStateEvent = true; 663 | await waitForHistoryState(() => window.history.back()); 664 | await waitForHistoryState(() => { 665 | window.history.replaceState( 666 | { 667 | ...window.history.state || {}, 668 | returnValue, 669 | }, 670 | '', 671 | (config.useHash ? '#' : '') + getLocation(), 672 | ); 673 | }); 674 | ignorePopStateEvent = false; 675 | dispatchCustomEvent(window as any, 'popstate'); 676 | } 677 | 678 | /** 679 | * Svelte action that can be associated with an HTMLAnchorElement (``) to automatically prefix '#' when using client side navigation only 680 | * @param node the HTML anchor tag 681 | * @param href the href attribute of the anchor tag 682 | * @returns an object containing the callback Svelte will use to trigger updates 683 | */ 684 | export function link(node: HTMLAnchorElement, href?: string): { update: (args: any) => void } { 685 | if (!node || !node.tagName || node.tagName.toLowerCase() !== 'a') { 686 | throw new Error('not a tag'); 687 | } 688 | 689 | async function pushState(e: MouseEvent) { 690 | if (!e.ctrlKey) { 691 | e.preventDefault(); 692 | // for an unknown reason, pushing the state blocks any on:click handler attached in a Svelte file. 693 | // This sleep lets the event propagate and schedules the push call after the bubbling has finished 694 | await sleep(1); 695 | push(config.useHash ? node.getAttribute('href')!.substring(1) : node.getAttribute('href')!); 696 | } 697 | } 698 | 699 | node.addEventListener('click', pushState); 700 | 701 | function hashHref(node: HTMLElement, href: string) { 702 | if (!href || href.length < 1 || href.charAt(0) !== '/') { 703 | throw new Error(`invalid href ${href}`); 704 | } 705 | 706 | node.setAttribute('href', `${config.useHash ? '#' : ''}${href}`); 707 | } 708 | 709 | hashHref(node, href || node.getAttribute('href')!); 710 | 711 | return { 712 | update(href: string) { 713 | hashHref(node, href); 714 | }, 715 | }; 716 | } 717 | 718 | /* COMPONENT LIFECYCLE */ 719 | const lifecycleErrorText = 'lifecycle functions can only be' 720 | + ' called while initializing or before preparing a component to resume (i.e. with a reactive statement on "params")'; 721 | 722 | /** 723 | * Attaches a callback to the resume lifecycle phase. 724 | * Lifecycle summary (|| = semi-parallel execution, achieved with Promise.all): 725 | * - create the page component if not in cache 726 | * - before-unload previous component || before-load new component 727 | * - pause previous component if resumable || resume new component if in cache || animate-transition 728 | * - after-unload previous component || after-load new component 729 | * - destroy previous component if not resumable 730 | * @param callback function that will be called when the component is resumed 731 | */ 732 | export function onResume(callback: (returnValue?: any) => any): void { 733 | if (!editableEntryConfig) { 734 | throw new Error(lifecycleErrorText); 735 | } 736 | if (!editableEntryConfig.onResume) { 737 | editableEntryConfig.onResume = []; 738 | } 739 | editableEntryConfig.onResume.push(callback); 740 | } 741 | 742 | /** 743 | * Attaches a callback to the pause lifecycle phase. 744 | * Lifecycle summary (|| = semi-parallel execution, achieved with Promise.all): 745 | * - create the page component if not in cache 746 | * - before-unload previous component || before-load new component 747 | * - pause previous component if resumable || resume new component if in cache || animate-transition 748 | * - after-unload previous component || after-load new component 749 | * - destroy previous component if not resumable 750 | * @param callback function that will be called when the component is paused 751 | */ 752 | export function onPause(callback: () => any): void { 753 | if (!editableEntryConfig) { 754 | throw new Error(lifecycleErrorText); 755 | } 756 | if (!editableEntryConfig.onPause) { 757 | editableEntryConfig.onPause = []; 758 | } 759 | editableEntryConfig.onPause.push(callback); 760 | } 761 | 762 | /** 763 | * Attaches a callback to the before-unload lifecycle phase. 764 | * Lifecycle summary (|| = semi-parallel execution, achieved with Promise.all): 765 | * - create the page component if not in cache 766 | * - before-unload previous component || before-load new component 767 | * - pause previous component if resumable || resume new component if in cache || animate-transition 768 | * - after-unload previous component || after-load new component 769 | * - destroy previous component if not resumable 770 | * @param callback function that will be called when the component is being prepared for unloading 771 | */ 772 | export function onBeforeUnload(callback: () => any): void { 773 | if (!editableEntryConfig) { 774 | throw new Error(lifecycleErrorText); 775 | } 776 | if (!editableEntryConfig.onBeforeUnload) { 777 | editableEntryConfig.onBeforeUnload = []; 778 | } 779 | editableEntryConfig.onBeforeUnload.push(callback); 780 | } 781 | 782 | /** 783 | * Lifecycle summary (|| = semi-parallel execution, achieved with Promise.all): 784 | * - create the page component if not in cache 785 | * - before-unload previous component || before-load new component 786 | * - pause previous component if resumable || resume new component if in cache || animate-transition 787 | * - after-unload previous component || after-load new component 788 | * - destroy previous component if not resumable 789 | * @param callback function that will be called when the component has finished loading 790 | */ 791 | export function onAfterLoad(callback: () => any): void { 792 | if (!editableEntryConfig) { 793 | throw new Error(lifecycleErrorText); 794 | } 795 | if (!editableEntryConfig.onAfterLoad) { 796 | editableEntryConfig.onAfterLoad = []; 797 | } 798 | editableEntryConfig.onAfterLoad.push(callback); 799 | } 800 | 801 | /** 802 | * Attaches a callback to the after-unload lifecycle phase. 803 | * Lifecycle summary (|| = semi-parallel execution, achieved with Promise.all): 804 | * - create the page component if not in cache 805 | * - before-unload previous component || before-load new component 806 | * - pause previous component if resumable || resume new component if in cache || animate-transition 807 | * - after-unload previous component || after-load new component 808 | * - destroy previous component if not resumable 809 | * @param callback function that will be called when the component has finished unloading 810 | */ 811 | export function onAfterUnload(callback: () => any): void { 812 | if (!editableEntryConfig) { 813 | throw new Error(lifecycleErrorText); 814 | } 815 | if (!editableEntryConfig.onAfterUnload) { 816 | editableEntryConfig.onAfterUnload = []; 817 | } 818 | editableEntryConfig.onAfterUnload.push(callback); 819 | } 820 | 821 | /** 822 | * Attaches a callback to the before-load lifecycle phase. 823 | * Lifecycle summary (|| = semi-parallel execution, achieved with Promise.all): 824 | * - create the page component if not in cache 825 | * - before-unload previous component || before-load new component 826 | * - pause previous component if resumable || resume new component if in cache || animate-transition 827 | * - after-unload previous component || after-load new component 828 | * - destroy previous component if not resumable 829 | * @param callback function that will be called when the component is being prepared for loading 830 | */ 831 | export function onBeforeLoad(callback: () => any): void { 832 | if (!editableEntryConfig) { 833 | throw new Error(lifecycleErrorText); 834 | } 835 | if (!editableEntryConfig.onBeforeLoad) { 836 | editableEntryConfig.onBeforeLoad = []; 837 | } 838 | editableEntryConfig.onBeforeLoad.push(callback); 839 | } 840 | 841 | /** 842 | * Determines whether the component will be paused or destroyed 843 | * @param resumable whether the component should be paused and resumed or completely destroyed and recreated 844 | */ 845 | export function setResumable(resumable: boolean): void { 846 | if (!editableEntryConfig) { 847 | throw new Error(lifecycleErrorText); 848 | } 849 | editableEntryConfig.resumable = resumable; 850 | } 851 | -------------------------------------------------------------------------------- /src-ts/transition-functions.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-properties */ 2 | import { NavigationType, TransitionFunction, TransitionFunctionData } from './types'; 3 | import { animationFrame, sleep } from './utils'; 4 | 5 | function makeStyleTag(content: string): HTMLStyleElement { 6 | const styleTag = document.createElement('style'); 7 | styleTag.innerHTML = content; 8 | return styleTag; 9 | } 10 | 11 | export function commonTransitionGenerator( 12 | duration: number, 13 | styleGenerators: ( 14 | (loadClass: string, unloadClass: string, routerClass: string, transitionFunctionData: TransitionFunctionData) => HTMLStyleElement 15 | )[], 16 | ): TransitionFunction { 17 | return async (transitionFunctionData) => { 18 | const timestamp = new Date().getTime(); 19 | const unloadClass = `unload-${timestamp}`; 20 | const loadClass = `load-${timestamp}`; 21 | const routerClass = `router-${timestamp}`; 22 | 23 | const { 24 | mountPointToUnload, mountPointToLoad, scroll, routerMountPoint, 25 | } = transitionFunctionData; 26 | 27 | mountPointToUnload?.classList.add(unloadClass); 28 | mountPointToLoad.classList.add(loadClass); 29 | routerMountPoint.classList.add(routerClass); 30 | 31 | const styleNodes = new Array(styleGenerators.length); 32 | for (let i = 0; i < styleGenerators.length; i++) { 33 | const styleNode = styleGenerators[i](loadClass, unloadClass, routerClass, transitionFunctionData); 34 | styleNodes[i] = styleNode; 35 | document.head.appendChild(styleNode); 36 | await animationFrame(); 37 | await animationFrame(); 38 | await animationFrame(); 39 | } 40 | 41 | let preventAutoScroll = false; 42 | const scrollListener = () => { preventAutoScroll = true; }; 43 | window.addEventListener('scroll', scrollListener); 44 | await sleep(duration); 45 | window.removeEventListener('scroll', scrollListener); 46 | 47 | if (!preventAutoScroll) { 48 | window.scrollTo(scroll.x, scroll.y); 49 | if (window.getComputedStyle(document.documentElement).scrollBehavior === 'smooth') { 50 | // At the moment of writing this comment there is no official/simple way to wait for the 51 | // window.scrollTo method to complete the animation 52 | // Hack: loop for a maximum of 500ms checking if the scroll position is close enough to the target scroll 53 | const threshold = 5; 54 | for (let i = 0; i < 50; i++) { 55 | if ( 56 | Math.sqrt( 57 | Math.pow(window.scrollX - scroll.x, 2) 58 | + Math.pow(window.scrollY - scroll.y, 2), 59 | ) < threshold 60 | ) { 61 | break; 62 | } 63 | await sleep(10); 64 | } 65 | } 66 | } 67 | 68 | for (const styleNode of styleNodes) { 69 | document.head.removeChild(styleNode); 70 | } 71 | 72 | mountPointToUnload?.classList.remove(unloadClass); 73 | mountPointToLoad.classList.remove(loadClass); 74 | routerMountPoint.classList.remove(routerClass); 75 | }; 76 | } 77 | 78 | export function slide(duration: number): TransitionFunction { 79 | return commonTransitionGenerator( 80 | duration, 81 | [ 82 | (loadClass, unloadClass, routerClass, { 83 | navigationType, 84 | }) => makeStyleTag(` 85 | html { 86 | scroll-behavior: smooth; 87 | } 88 | .${loadClass} { 89 | position: absolute; 90 | z-index: 2; 91 | left: 0; 92 | top: 0; 93 | right: 0; 94 | opacity: 0; 95 | transform: translateX(${navigationType === NavigationType.GoBackward ? '-' : ''}50%); 96 | } 97 | .${unloadClass} { 98 | position: relative; 99 | z-index: 1; 100 | opacity: 1; 101 | transform: translateX(0%); 102 | } 103 | .${routerClass} { 104 | position: relative; 105 | overflow: hidden; 106 | } 107 | `), 108 | (_1, _2, routerClass, { 109 | mountPointToLoad, 110 | mountPointToUnload, 111 | }) => makeStyleTag(` 112 | .${routerClass} { 113 | min-height: ${Math.max(mountPointToLoad.offsetHeight, mountPointToUnload?.offsetHeight || 0)}px; 114 | min-width: ${Math.max(mountPointToLoad.offsetWidth, mountPointToUnload?.offsetWidth || 0)}px; 115 | } 116 | `), 117 | (loadClass, unloadClass, _, { navigationType }) => makeStyleTag(` 118 | .${loadClass} { 119 | transition: transform ${duration}ms, opacity ${Math.floor(duration / 2)}ms linear ${Math.floor(duration / 2)}ms; 120 | opacity: 1; 121 | transform: translateX(0%); 122 | } 123 | .${unloadClass} { 124 | transition: transform ${duration}ms, opacity ${Math.floor(duration / 2)}ms linear; 125 | opacity: 0; 126 | transform: translateX(${navigationType === NavigationType.GoBackward ? '' : '-'}50%); 127 | } 128 | `), 129 | ], 130 | ); 131 | } 132 | 133 | export function dive(duration: number): TransitionFunction { 134 | return commonTransitionGenerator( 135 | duration, 136 | [ 137 | (loadClass, unloadClass, routerClass, { navigationType }) => makeStyleTag(` 138 | html { 139 | scroll-behavior: smooth; 140 | } 141 | .${loadClass} { 142 | position: absolute; 143 | z-index: 2; 144 | left: 0; 145 | top: 0; 146 | right: 0; 147 | opacity: 0; 148 | transform: translateZ(${navigationType === NavigationType.GoBackward ? '' : '-'}150px); 149 | } 150 | .${unloadClass} { 151 | position: relative; 152 | z-index: 1; 153 | opacity: 1; 154 | transform: translateZ(0px); 155 | } 156 | .${routerClass} { 157 | perspective: 1200px; 158 | perspective-origin: top center; 159 | position: relative; 160 | overflow: hidden; 161 | } 162 | `), 163 | (_1, _2, routerClass, { 164 | mountPointToLoad, 165 | mountPointToUnload, 166 | }) => makeStyleTag(` 167 | .${routerClass} { 168 | min-height: ${Math.max(mountPointToLoad.offsetHeight, mountPointToUnload?.offsetHeight || 0)}px; 169 | min-width: ${Math.max(mountPointToLoad.offsetWidth, mountPointToUnload?.offsetWidth || 0)}px; 170 | } 171 | `), 172 | (loadClass, unloadClass, _, { navigationType }) => makeStyleTag(` 173 | .${loadClass} { 174 | transition: transform ${duration}ms, opacity ${Math.floor(duration / 2)}ms linear ${Math.floor(duration / 2)}ms; 175 | opacity: 1; 176 | transform: translateZ(0px); 177 | } 178 | .${unloadClass} { 179 | transition: transform ${duration}ms, opacity ${Math.floor(duration / 2)}ms linear; 180 | opacity: 0; 181 | transform: translateZ(${navigationType === NavigationType.GoBackward ? '-' : ''}150px); 182 | } 183 | `), 184 | ], 185 | ); 186 | } 187 | 188 | export function noAnimation(): TransitionFunction { 189 | return ({ scroll }) => { 190 | window.scrollTo(scroll.x, scroll.y); 191 | return Promise.resolve(); 192 | }; 193 | } 194 | -------------------------------------------------------------------------------- /src-ts/types.ts: -------------------------------------------------------------------------------- 1 | import { SvelteComponent } from 'svelte'; 2 | 3 | export type SvelteComponentConstructor = new (options: { target: HTMLElement, props: Record }) => SvelteComponent; 4 | 5 | export interface HistoryState { 6 | timestamp: number, 7 | returnValue?: any, 8 | scroll?: { 9 | x: number, 10 | y: number, 11 | } 12 | } 13 | 14 | export interface HistoryItem { 15 | location: string, 16 | state: HistoryState, 17 | } 18 | 19 | export enum LoadableEntryAction { 20 | NoOp, 21 | New, 22 | Resume, 23 | } 24 | 25 | export enum UnloadableEntryAction { 26 | NoOp, 27 | Destroy, 28 | Pause, 29 | } 30 | 31 | export enum NavigationType { 32 | GoForwardNewState, 33 | GoForwardResumeState, 34 | GoBackward, 35 | Replace, 36 | } 37 | 38 | export interface TransitionFunctionData { 39 | navigationType: NavigationType, 40 | routerMountPoint: HTMLElement, 41 | mountPointToLoad: HTMLElement, 42 | mountPointToUnload: HTMLElement | null, 43 | scroll: { 44 | x: number, 45 | y: number, 46 | }, 47 | } 48 | 49 | /** 50 | * A function that handles the transition between two pages 51 | * @param {NavigationType} data.navigationType describes the navigation that occurred (e.g. backward, replace, forward, ...) 52 | * @param {HTMLElement} data.mountPointToLoad the mount point of the page that is being loaded 53 | * @param {HTMLElement} data.mountPointToUnload the mount point of the page that is being unloaded 54 | * @param {HTMLElement} data.routerMountPoint the router mount point, when this function is called it contains both the mountPointToLoad and the mountPointToUnload 55 | * @param {{x: number, y: number}|undefined} data.scroll if scroll restoration is enabled and the current component is being resumed, this object contains the x and y coordinates needed to bring the window scrollbars back to where they were when the component was paused 56 | * @return {Promise} a promise that resolves once the transition has finished 57 | */ 58 | export type TransitionFunction = (data: TransitionFunctionData) => Promise; 59 | 60 | export type Params = Record; 61 | 62 | export type Guard = (params?: Params) => boolean | Promise; 63 | 64 | export interface RouteDescriptor { 65 | guard?: Guard, 66 | guards?: Guard[], 67 | component?: SvelteComponentConstructor, 68 | componentProvider?: () => Promise 71 | } 72 | 73 | export type Routes = Record; 74 | 75 | export interface Config { 76 | /** Whether or not the default behavior should be to resume or recreate the components */ 77 | defaultResumable: boolean, 78 | /** Whether or not to prefix routes with '#' to implement a server-agnostic client side routing (e.g. no need to redirect 404 to index) */ 79 | useHash: boolean, 80 | /** Whether or not to restore the scroll position when navigating backwards */ 81 | restoreScroll: boolean, 82 | /** A key-value object associating a route path (e.g. '/a/route/path/:variable1?) to a SvelteComponent constructor */ 83 | routes: Routes, 84 | /** Reference to the HTML element that will wrap all the page components */ 85 | mountPoint: null | HTMLElement, 86 | /** A function that handles the transition between two pages */ 87 | transitionFn: TransitionFunction, 88 | /** The Svelte dispatcher of the current instance of the StackRouter */ 89 | dispatch: ((eventName: string, eventData?: Record) => void) | null, 90 | } 91 | 92 | export enum StackRouterEventType { 93 | Navigate, 94 | Mount, 95 | Destroy, 96 | UpdateConfig, 97 | } 98 | 99 | export type StackRouterEvent = { 100 | type: StackRouterEventType.Mount, 101 | payload: Partial & { routes: Routes, mountPoint: HTMLDivElement }, 102 | } | { 103 | type: StackRouterEventType.Destroy, 104 | } | { 105 | type: StackRouterEventType.Navigate, 106 | payload: HistoryItem, 107 | } | { 108 | type: StackRouterEventType.UpdateConfig, 109 | payload: Partial> & { routes: Routes }, 110 | }; 111 | 112 | export interface ComponentConfig { 113 | onResume?: ((returnValue?: any) => any)[], 114 | onPause?: ((force?: boolean) => any)[], 115 | onBeforeUnload?: ((force?: boolean) => any)[], 116 | onAfterLoad?: (() => any)[], 117 | onBeforeLoad?: (() => any)[], 118 | onAfterUnload?: ((force?: boolean) => any)[], 119 | resumable: boolean, 120 | } 121 | 122 | export interface CacheEntry { 123 | component: SvelteComponentConstructor, 124 | componentInstance: SvelteComponent, 125 | pathname: string, 126 | routeMatch: string, 127 | entryConfig: ComponentConfig, 128 | mountPoint: HTMLDivElement, 129 | } 130 | -------------------------------------------------------------------------------- /src-ts/utils.ts: -------------------------------------------------------------------------------- 1 | export function noop() { } 2 | 3 | export function animationFrame() { 4 | return new Promise((res) => requestAnimationFrame(() => res())); 5 | } 6 | 7 | export function sleep(ms: number) { 8 | return new Promise((res) => setTimeout(() => res(), ms)); 9 | } 10 | 11 | export function dispatchCustomEvent(element: HTMLElement, eventName: string) { 12 | element.dispatchEvent(new CustomEvent(eventName, { 13 | bubbles: true, 14 | cancelable: true, 15 | })); 16 | } 17 | -------------------------------------------------------------------------------- /src/App.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/StackRouter.svelte: -------------------------------------------------------------------------------- 1 | 52 | 53 |
54 | -------------------------------------------------------------------------------- /src/_routes.js: -------------------------------------------------------------------------------- 1 | import { get } from 'svelte/store'; 2 | import Home from './pages/Home.svelte'; 3 | import Resumable from './pages/Resumable.svelte'; 4 | import Throwaway from './pages/Throwaway.svelte'; 5 | import Redirect from './pages/Redirect.svelte'; 6 | import NotFound from './pages/NotFound.svelte'; 7 | import Guarded from './pages/Guarded.svelte'; 8 | import AsyncComponent from './pages/AsyncComponent.svelte'; 9 | import youShallPass from './stores/you-shall-pass'; 10 | 11 | export default { 12 | '/': Home, 13 | '/resumable/:aVariable?': Resumable, 14 | '/throwaway': Throwaway, 15 | '/guarded': { 16 | component: Guarded, 17 | guard: () => get(youShallPass), 18 | }, 19 | '/async': { 20 | componentProvider: () => new Promise( 21 | (resolve, reject) => setTimeout( 22 | // Simulate lazy loading 23 | () => resolve(AsyncComponent), 24 | 25 | // Simulate a network error 26 | // The promise can fail. In that case the router will emit an appropriate "error" event 27 | // with the details and the original error returned by the failed promise 28 | // () => reject(new Error('oh no!')), 29 | 1000, 30 | ), 31 | ), 32 | }, 33 | '/redirect': Redirect, 34 | '*': NotFound, 35 | }; 36 | -------------------------------------------------------------------------------- /src/components/Links.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 28 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/named */ 2 | import type { 3 | NavigationType, TransitionFunction, CacheEntry, PageToUnloadAction, PageToLoadAction, Routes, Params 4 | } from './types'; 5 | 6 | export * from './stack-router'; 7 | export * from './transition-functions'; 8 | export * from './types'; 9 | export * from './utils'; 10 | export class SvelteComponent { 11 | $$prop_def: {}; 12 | 13 | $$slot_def: {}; 14 | 15 | $on(event: string, handler: (e: CustomEvent) => any): () => void; 16 | } 17 | export class StackRouter extends SvelteComponent { 18 | $$prop_def: { 19 | /** Whether or not the default behavior should be to resume or recreate the components */ 20 | defaultResumable?: boolean, 21 | /** Whether or not to prefix routes with '#' to implement a server-agnostic client side routing (e.g. no need to redirect 404 to index) */ 22 | useHash?: boolean, 23 | /** Whether or not to restore the scroll position when navigating backwards */ 24 | restoreScroll?: boolean, 25 | /** A key-value object associating a route path (e.g. '/a/route/path/:variable1?) to a SvelteComponent constructor */ 26 | routes: Routes, 27 | /** A function that handles the transition between two pages */ 28 | transitionFn?: TransitionFunction, 29 | } 30 | 31 | /** Triggered on errors such as "no route found" */ 32 | $on(event: 'error', handler: (e: CustomEvent<{ 33 | message: string, 34 | location: string, 35 | }>) => any): () => void; 36 | 37 | /** Triggered before unloading the old page and before loading the new page */ 38 | $on(event: 'navigation-start', handler: (e: CustomEvent<{ 39 | location: string, 40 | navigationType: NavigationType, 41 | pageToLoad: CacheEntry, 42 | pageToUnload: CacheEntry | null, 43 | pageToLoadAction: PageToLoadAction, 44 | pageToUnloadAction: PageToUnloadAction, 45 | }>) => any): () => void; 46 | 47 | /** Triggered after unloading the old page and after loading the new page */ 48 | $on(event: 'navigation-end', handler: (e: CustomEvent<{ 49 | location: string, 50 | navigationType: NavigationType, 51 | pageToLoad: CacheEntry, 52 | pageToUnload: CacheEntry | null, 53 | pageToLoadAction: PageToLoadAction, 54 | pageToUnloadAction: PageToUnloadAction, 55 | }>) => any): () => void; 56 | 57 | /** Triggered when a route couldn't be reached because a guard returned a falsy value */ 58 | $on(event: 'forbidden', handler: (e: CustomEvent<{ 59 | message: string, 60 | params?: Params, 61 | location: string 62 | }>) => any): () => void; 63 | } 64 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export * from './stack-router'; 2 | export * from './transition-functions'; 3 | export * from './types'; 4 | export * from './utils'; 5 | export { default as StackRouter } from './StackRouter.svelte'; 6 | -------------------------------------------------------------------------------- /src/pages/AsyncComponent.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 |

I'm an asynchronously loaded component

12 |
13 |
14 | I'll take some time to get loaded the first time, but if you come back I'll be 15 | ready, even if I'm not resumable! 16 |
17 | -------------------------------------------------------------------------------- /src/pages/Guarded.svelte: -------------------------------------------------------------------------------- 1 |
2 |

I'm a guarded component

3 |
4 |
5 | You shall be able to reach me only if you checked "Enable guarded route" first 6 |
7 | -------------------------------------------------------------------------------- /src/pages/Home.svelte: -------------------------------------------------------------------------------- 1 |
2 |

Welcome to svelte-stack-router

3 |
4 |
5 |

A fast, app-like router that caches components

6 |
7 |
8 |

9 | Less re-renders, full state preservation and cool animations! 10 |

11 |
12 | 20 | -------------------------------------------------------------------------------- /src/pages/NotFound.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 |

Not found

8 |
9 | Redirect 10 | -------------------------------------------------------------------------------- /src/pages/Redirect.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | I'm temporary... just wait a sec... 10 | -------------------------------------------------------------------------------- /src/pages/Resumable.svelte: -------------------------------------------------------------------------------- 1 | 90 | 91 |
92 |

I'm a resumable component

93 |
94 |
95 | 101 |
102 |
107 | {#if params.aVariable} 108 |

113 | I have a param! "{params.aVariable}" 114 |

115 | {/if} 116 |
117 |
118 |

119 | This component will get cached. As a result the following video 120 | will be paused and resumed every time you visit this page 121 |

122 |
124 |
Events so far:
125 |
126 |
    127 | {#each events as event} 128 |
  • 129 | {event} 130 |
  • 131 | {/each} 132 |
133 |
134 | -------------------------------------------------------------------------------- /src/pages/Throwaway.svelte: -------------------------------------------------------------------------------- 1 | 48 | 49 |
50 |

I'm a non-resumable component

51 |
52 |
53 |

54 | This component won't get cached. As a result the following video 55 | will restart every time you visit this page 56 |

57 |
59 |
Events so far:
60 |
61 |
    62 | {#each events as event} 63 |
  • 64 | {event} 65 |
  • 66 | {/each} 67 |
68 |
69 | -------------------------------------------------------------------------------- /src/pages/_Layout.svelte: -------------------------------------------------------------------------------- 1 | 25 | 26 |
27 |
28 |

Location pathname: {$pathname}

29 |
30 |
31 | 39 |
40 |
41 | 45 |
46 |
47 | 51 |
52 | 53 | {#if !unmount} 54 | 62 | {:else} 63 |
64 | StackRouter unmounted, all cached components have been destroyed 65 |
66 | {/if} 67 |
68 | -------------------------------------------------------------------------------- /src/preview.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | props: {}, 6 | }); 7 | 8 | export default app; 9 | -------------------------------------------------------------------------------- /src/stores/async-component-loaded.js: -------------------------------------------------------------------------------- 1 | import { writable } from 'svelte/store'; 2 | 3 | export default writable(false); 4 | -------------------------------------------------------------------------------- /src/stores/you-shall-pass.js: -------------------------------------------------------------------------------- 1 | import { writable } from 'svelte/store'; 2 | 3 | export default writable(false); 4 | -------------------------------------------------------------------------------- /src/style/main.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | text-align: center; 6 | } 7 | 8 | body { 9 | color: white; 10 | background-color: #1c1c1c; 11 | } 12 | 13 | a { 14 | text-decoration: none; 15 | padding: 0.5em 1em; 16 | margin: 0.5em 1em; 17 | color: gray; 18 | background-color: lavender; 19 | display: inline-block; 20 | font-size: 1em; 21 | } 22 | 23 | button { 24 | border: none; 25 | background-color: antiquewhite; 26 | color: gray; 27 | font-size: 1em; 28 | padding: 0.5em 1em; 29 | margin: 0.5em 1em; 30 | } 31 | 32 | h1, h2 { 33 | display: inline-block; 34 | margin: 0; 35 | text-align: center; 36 | position: relative; 37 | padding-bottom: 20px; 38 | } 39 | 40 | h1::after { 41 | content: ' '; 42 | display: block; 43 | position: absolute; 44 | left: 5%; 45 | right: 5%; 46 | margin-top: 10px; 47 | height: 1px; 48 | background-color: gray; 49 | } 50 | 51 | select { 52 | background-color: #4c4c4c; 53 | border: none; 54 | padding: 0.5em 1em; 55 | margin: 0.5em 1em; 56 | color: white; 57 | font-size: 1em; 58 | } 59 | 60 | img.text { 61 | height: 1em; 62 | width: auto; 63 | vertical-align: middle; 64 | } 65 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "es2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 6 | "module": "es2020", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 7 | // "lib": [], /* Specify library files to be included in the compilation. */ 8 | // "allowJs": true, /* Allow javascript files to be compiled. */ 9 | // "checkJs": true, /* Report errors in .js files. */ 10 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 11 | "declaration": false, /* Generates corresponding '.d.ts' file. */ 12 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 13 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 14 | // "outFile": "./", /* Concatenate and emit output to single file. */ 15 | "outDir": "./src", /* Redirect output structure to the directory. */ 16 | "rootDir": "./src-ts", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 17 | // "composite": true, /* Enable project compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true, /* Enable all strict type-checking options. */ 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 52 | 53 | /* Source Map Options */ 54 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 55 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 56 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 57 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 58 | 59 | /* Experimental Options */ 60 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 61 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 62 | 63 | /* Advanced Options */ 64 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 65 | }, 66 | "include": [ 67 | "src-ts" 68 | ], 69 | "exclude": [ 70 | "src" 71 | ] 72 | } 73 | --------------------------------------------------------------------------------