├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── README.md ├── docs ├── API.md ├── COMPONENTS.md ├── POLYFILLS.md └── logos │ ├── microsoft.png │ └── speechly.png ├── package.json ├── pnpm-lock.yaml ├── postcss.config.cjs ├── src ├── app.css ├── app.d.ts ├── app.html ├── global.d.ts ├── hooks.ts ├── lib │ ├── NativeSpeechRecognition.ts │ ├── RecognitionManager.ts │ ├── SpeechRecognition.ts │ ├── components │ │ ├── Button.svelte │ │ ├── Listen.svelte │ │ └── Stop.svelte │ ├── constants.ts │ ├── index.ts │ ├── isAndroid.ts │ ├── reducers.ts │ ├── stores.ts │ ├── types.ts │ └── utils.ts └── routes │ ├── Dictaphones.svelte │ ├── _Dictaphone │ ├── Dictaphone.svelte │ ├── DictaphoneWidgetA.svelte │ └── DictaphoneWidgetB.svelte │ ├── __layout.svelte │ ├── components │ ├── Dictaphones.svelte │ ├── _Dictaphone │ │ ├── Dictaphone.svelte │ │ ├── DictaphoneWidgetA.svelte │ │ └── DictaphoneWidgetB.svelte │ └── index.svelte │ └── index.svelte ├── static ├── favicon.png └── robots.txt ├── svelte.config.js ├── tailwind.config.cjs └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | package.json 12 | pnpm-lock.yaml 13 | package-lock.json 14 | yarn.lock 15 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript') 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true 19 | }, 20 | rules: { 21 | "prefer-rest-params": "off", 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | .vercel 10 | .output 11 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | package.json 12 | pnpm-lock.yaml 13 | package-lock.json 14 | yarn.lock 15 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "files.autoSave": "onFocusChange", 4 | "[svelte]": { 5 | "editor.defaultFormatter": "svelte.svelte-vscode", 6 | "editor.codeActionsOnSave": [ 7 | "source.fixAll", 8 | "source.sortImports" 9 | ] 10 | }, 11 | "typescript.tsserver.experimental.enableProjectDiagnostics": true, 12 | "editor.quickSuggestions": { 13 | "strings": true 14 | }, 15 | "eslint.validate": [ 16 | "javascript", 17 | "javascriptreact", 18 | "svelte" 19 | ] 20 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-speech-recognition 2 | [![npm](https://img.shields.io/npm/v/svelte-speech-recognition?style=flat-square)](https://www.npmjs.com/package/svelte-speech-recognition) 3 | [![npm](https://img.shields.io/npm/dt/svelte-speech-recognition?style=flat-square)](https://www.npmjs.com/package/svelte-speech-recognition) 4 | [![Netlify](https://img.shields.io/netlify/e1d87723-3ac6-4e8a-8d60-b30a5e977bad?style=flat-square)](https://svelte-speech-recognition.netlify.app/) 5 | [![GitHub last commit](https://img.shields.io/github/last-commit/jhubbardsf/svelte-speech-recognition?style=flat-square)](https://github.com/jhubbardsf/svelte-speech-recognition) 6 | 7 | 8 | A Svelte library that converts speech from the microphone to text and makes it available to your Svelte components. Originally based off the [react-speech-recognition](https://github.com/JamesBrill/react-speech-recognition) library. 9 | 10 | NOTE: This is a WIP and still in alpha. There's still a bit of work to do before v1. That being said it's functional and any testing would be appreciated. 11 | 12 | ## How it works 13 | `useSpeechRecognition` is a Svelte hook that gives a component access to a transcript of speech picked up from the user's microphone. 14 | 15 | `SpeechRecognition` manages the global state of the Web Speech API, exposing functions to turn the microphone on and off. 16 | 17 | Under the hood, 18 | it uses [Web Speech API](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition). Note that browser support for this API is currently limited, with Chrome having the best experience - see [supported browsers](#supported-browsers) for more information. 19 | 20 | ## Useful links 21 | 22 | * [Basic example](#basic-example) 23 | * [Why you should use a polyfill with this library](#why-you-should-use-a-polyfill-with-this-library) 24 | * [Cross-browser example](#cross-browser-example) 25 | * [Svelte-Components](docs/COMPONENTS.md) 26 | * [Polyfills](docs/POLYFILLS.md) 27 | * [API docs](docs/API.md) 28 | 29 | ## Installation 30 | 31 | To install: 32 | 33 | `npm install --save-dev svelte-speech-recognition` 34 | 35 | To import in your Svelte code: 36 | 37 | `import SpeechRecognition, { useSpeechRecognition } from 'svelte-speech-recognition/SpeechRecognition'` 38 | 39 | ## Basic example 40 | 41 | The most basic example of a component using this hook would be: 42 | 43 | ```sv 44 | 54 | 55 | This is the final transcript: 56 | {$transcriptStore.finalTranscript} 57 | 58 | This is the interim transcript: 59 | {$transcriptStore.interimTranscript} 60 | ``` 61 | 62 | You can see more examples in the example Svelte app attached to this repo. See [Developing](#developing). 63 | 64 | ## Why you should use a polyfill with this library 65 | 66 | By default, speech recognition is not supported in all browsers, with the best native experience being available on desktop Chrome. To avoid the limitations of native browser speech recognition, it's recommended that you combine `svelte-speech-recognition` with a [speech recognition polyfill](docs/POLYFILLS.md). Why? Here's a comparison with and without polyfills: 67 | * ✅ With a polyfill, your web app will be voice-enabled on all modern browsers (except Internet Explorer) 68 | * ❌ Without a polyfill, your web app will only be voice-enabled on the browsers listed [here](#supported-browsers) 69 | * ✅ With a polyfill, your web app will have a consistent voice experience across browsers 70 | * ❌ Without a polyfill, different native implementations will produce different transcriptions, have different levels of accuracy, and have different formatting styles 71 | * ✅ With a polyfill, you control who is processing your users' voice data 72 | * ❌ Without a polyfill, your users' voice data will be sent to big tech companies like Google or Apple to be transcribed 73 | * ✅ With a polyfill, `svelte-speech-recognition` will be suitable for use in commercial applications 74 | * ❌ Without a polyfill, `svelte-speech-recognition` will still be fine for personal projects or use cases where cross-browser support is not needed 75 | 76 | `svelte-speech-recognition` currently supports polyfills for the following cloud providers: 77 | 78 |
79 | 80 | Speechly 81 | 82 | 83 | 84 | Microsoft Azure Cognitive Services 85 | 86 |
87 | 88 | ## Cross-browser example 89 | 90 | You can find the full guide for setting up a polyfill [here](docs/POLYFILLS.md). Alternatively, here is a quick (and free) example using Speechly: 91 | * Install `@speechly/speech-recognition-polyfill` in your web app 92 | * You will need a Speechly app ID. To get one of these, sign up for free with Speechly and follow [the guide here](https://docs.speechly.com/quick-start/stt-only/) 93 | * Here's a component for a push-to-talk button. The basic example above would also work fine. 94 | ```sv 95 | 112 | 113 | {#if (!browserSupportsSpeechRecognition)} 114 | Browser doesn't support speech recognition 115 | {:else} 116 |
117 |

Microphone: {listening ? 'on' : 'off'}

118 | 124 |

{$transcriptStore.finalTranscript}

125 |
126 | {/if} 127 | ``` 128 | 129 | ## Detecting browser support for Web Speech API 130 | 131 | If you choose not to use a polyfill, this library still fails gracefully on browsers that don't support speech recognition. It is recommended that you render some fallback content if it is not supported by the user's browser: 132 | 133 | ```sv 134 | {#if (!browserSupportsSpeechRecognition)} 135 | // Render some fallback content 136 | {/if} 137 | ``` 138 | 139 | ### Supported browsers 140 | 141 | Without a polyfill, the Web Speech API is largely only supported by Google browsers. As of May 2022, the following browsers support the Web Speech API: 142 | 143 | * Chrome (desktop) 144 | * Safari 145 | * Microsoft Edge 146 | * Chrome (Android): a word of warning about this platform, which is that there can be an annoying beeping sound when turning the microphone on. This is part of the Android OS and cannot be controlled from the browser 147 | * Android webview 148 | * Samsung Internet 149 | 150 | For all other browsers, you can render fallback content using the `SpeechRecognition.browserSupportsSpeechRecognition` function described above. Alternatively, as mentioned before, you can integrate a [polyfill](docs/POLYFILLS.md). 151 | 152 | ## Detecting when the user denies access to the microphone 153 | 154 | Even if the browser supports the Web Speech API, the user still has to give permission for their microphone to be used before transcription can begin. They are asked for permission when `svelte-speech-recognition` first tries to start listening. At this point, you can detect when the user denies access via the `isMicrophoneAvailable` state. When this becomes `false`, it's advised that you disable voice-driven features and indicate that microphone access is needed for them to work. 155 | 156 | ```sv 157 | {#if (!isMicrophoneAvailable)} 158 | // Render some fallback content 159 | {/if} 160 | ``` 161 | 162 | ## Controlling the microphone 163 | 164 | Before consuming the transcript, you should be familiar with `SpeechRecognition`, which gives you control over the microphone. The state of the microphone is global, so any functions you call on this object will affect _all_ components using `useSpeechRecognition`. 165 | 166 | ### Turning the microphone on 167 | 168 | To start listening to speech, call the `startListening` function. 169 | 170 | ```sv 171 | SpeechRecognition.startListening() 172 | ``` 173 | 174 | This is an asynchronous function, so it will need to be awaited if you want to do something after the microphone has been turned on. 175 | 176 | ### Turning the microphone off 177 | 178 | To turn the microphone off, but still finish processing any speech in progress, call `stopListening`. 179 | 180 | ```sv 181 | SpeechRecognition.stopListening() 182 | ``` 183 | 184 | To turn the microphone off, and cancel the processing of any speech in progress, call `abortListening`. 185 | 186 | ```sv 187 | SpeechRecognition.abortListening() 188 | ``` 189 | 190 | ## Consuming the microphone transcript 191 | 192 | To make the microphone transcript available as a Svelte store in your component. It has the interimTranscript and finalTranscript object, simply add: 193 | 194 | ```sv 195 | const { transcriptStore } = useSpeechRecognition() 196 | ``` 197 | 198 | ## Resetting the microphone transcript 199 | 200 | To set the transcript to an empty string, you can call the `resetTranscript` function provided by `useSpeechRecognition`. Note that this is local to your component and does not affect any other components using Speech Recognition. 201 | 202 | ```sv 203 | const { resetTranscript } = useSpeechRecognition() 204 | ``` 205 | 206 | ## Commands 207 | 208 | To respond when the user says a particular phrase, you can pass in a list of commands to the `useSpeechRecognition` hook. Each command is an object with the following properties: 209 | - `command`: This is a string or `RegExp` representing the phrase you want to listen for. If you want to use the same callback for multiple commands, you can also pass in an array here, with each value being a string or `RegExp` 210 | - `callback`: The function that is executed when the command is spoken. The last argument that this function receives will always be an object containing the following properties: 211 | - `command`: The command phrase that was matched. This can be useful when you provide an array of command phrases for the same callback and need to know which one triggered it 212 | - `resetTranscript`: A function that sets the transcript to an empty string 213 | - `matchInterim`: Boolean that determines whether "interim" results should be matched against the command. This will make your component respond faster to commands, but also makes false positives more likely - i.e. the command may be detected when it is not spoken. This is `false` by default and should only be set for simple commands. 214 | - `isFuzzyMatch`: Boolean that determines whether the comparison between speech and `command` is based on similarity rather than an exact match. Fuzzy matching is useful for commands that are easy to mispronounce or be misinterpreted by the Speech Recognition engine (e.g. names of places, sports teams, restaurant menu items). It is intended for commands that are string literals without special characters. If `command` is a string with special characters or a `RegExp`, it will be converted to a string without special characters when fuzzy matching. The similarity that is needed to match the command can be configured with `fuzzyMatchingThreshold`. `isFuzzyMatch` is `false` by default. When it is set to `true`, it will pass four arguments to `callback`: 215 | - The value of `command` (with any special characters removed) 216 | - The speech that matched `command` 217 | - The similarity between `command` and the speech 218 | - The object mentioned in the `callback` description above 219 | - `fuzzyMatchingThreshold`: If the similarity of speech to `command` is higher than this value when `isFuzzyMatch` is turned on, the `callback` will be invoked. You should set this only if `isFuzzyMatch` is `true`. It takes values between `0` (will match anything) and `1` (needs an exact match). The default value is `0.8`. 220 | - `bestMatchOnly`: Boolean that, when `isFuzzyMatch` is `true`, determines whether the callback should only be triggered by the command phrase that _best_ matches the speech, rather than being triggered by all matching fuzzy command phrases. This is useful for fuzzy commands with multiple command phrases assigned to the same callback function - you may only want the callback to be triggered once for each spoken command. You should set this only if `isFuzzyMatch` is `true`. The default value is `false`. 221 | 222 | ### Command symbols 223 | 224 | To make commands easier to write, the following symbols are supported: 225 | - Splats: this is just a `*` and will match multi-word text: 226 | - Example: `'I would like to order *'` 227 | - The words that match the splat will be passed into the callback, one argument per splat 228 | - Named variables: this is written `:` and will match a single word: 229 | - Example: `'I am :height metres tall'` 230 | - The one word that matches the named variable will be passed into the callback 231 | - Optional words: this is a phrase wrapped in parentheses `(` and `)`, and is not required to match the command: 232 | - Example: `'Pass the salt (please)'` 233 | - The above example would match both `'Pass the salt'` and `'Pass the salt please'` 234 | 235 | ### Example with commands 236 | ```sv 237 | 284 | 285 | {#if browserSupportsSpeechRecognition} 286 |
287 |

{message}

288 |

{$transcriptStore.finalTranscript}

289 |
290 | {:else} 291 |

Browser does not support speech recognition.

292 | {/if} 293 | ``` -------------------------------------------------------------------------------- /docs/API.md: -------------------------------------------------------------------------------- 1 | # API docs 2 | 3 | ## Interface 4 | 5 | * [useSpeechRecognition](#useSpeechRecognition) 6 | * [SpeechRecognition](#SpeechRecognition) 7 | 8 | ## useSpeechRecognition 9 | 10 | Hook for consuming speech recorded by the microphone. Import with: 11 | 12 | ```sv 13 | import { useSpeechRecognition } from 'svelte-speech-recognition/SpeechRecognition' 14 | ``` 15 | 16 | ### Input props 17 | 18 | These are passed as an object argument to `useSpeechRecognition`: 19 | 20 | ```sv 21 | useSpeechRecognition({ transcribing, clearTranscriptOnListen, commands }) 22 | ``` 23 | 24 | #### transcribing [Writable] 25 | 26 | Writable svelte store. Is this component collecting a transcript or not? This is independent of the global `listening` state of the microphone. `true` by default. 27 | 28 | #### clearTranscriptOnListen [Writable] 29 | 30 | Writable svelte store. Does this component clear its transcript when the microphone is turned on? Has no effect when continuous listening is enabled. `true` by default. 31 | 32 | #### commands [list] 33 | 34 | See [Commands](../README.md#Commands). 35 | 36 | ### Output state 37 | 38 | These are returned from `useSpeechRecognition`: 39 | 40 | ```sv 41 | const { 42 | transcriptStore, 43 | interimTranscript 44 | finalTranscript, 45 | clearTranscriptOnListen, 46 | resetTranscript, 47 | listening, 48 | browserSupportsSpeechRecognition, 49 | isMicrophoneAvailable, 50 | } = useSpeechRecognition() 51 | ``` 52 | 53 | #### transcriptStore [Readable<{ interimTranscript: string, finalTranscript: string[] }>] 54 | 55 | Transcription store with a finalTranscript and interimTranscript object. 56 | 57 | #### resetTranscript [() => void] 58 | 59 | Sets `transcriptStore.finalTranscript` to empty array & `transcriptStore.interimTranscript` to an empty string. 60 | 61 | #### listening [Readable] 62 | 63 | Svelte store that is updated when the Web Speech API is listening to speech from the microphone. 64 | 65 | #### transcriptStore.interimTranscript [string] 66 | 67 | Transcription of speech that the Web Speech API is still processing (i.e. it's still deciding what has just been spoken). 68 | 69 | For the current words being spoken, the interim transcript reflects each successive guess made by the transcription algorithm. When the browser’s confidence in its guess is maximized, it is added to the final transcript. 70 | 71 | The difference between interim and final transcripts can be illustrated by an example over four iterations of the transcription algorithm: 72 | 73 | | Final transcript | Interim transcript | 74 | | ------------------- | ------------------ | 75 | | 'Hello, I am' | 'jam' | 76 | | 'Hello, I am' | 'jams' | 77 | | 'Hello, I am' | 'James' | 78 | | 'Hello, I am James' | '' | 79 | 80 | #### transcriptStore.finalTranscript [string] 81 | 82 | Transcription of speech that the Web Speech API has finished processing. 83 | 84 | #### browserSupportsSpeechRecognition [bool] 85 | 86 | The Web Speech API is not supported on all browsers, so it is recommended that you render some fallback content if it is not supported by the user's browser: 87 | 88 | ```sv 89 | {#if (!browserSupportsSpeechRecognition)} 90 | // Render some fallback content 91 | {/if} 92 | ``` 93 | 94 | #### browserSupportsContinuousListening [bool] 95 | 96 | Continuous listening is not supported on all browsers, so it is recommended that you apply some fallback behaviour if your web app uses continuous listening and is running on a browser that doesn't support it: 97 | 98 | ```sv 99 | {#if (browserSupportsContinuousListening)} 100 | SpeechRecognition.startListening({ continuous: true }) 101 | {:else} 102 | // Fallback behaviour 103 | {/if} 104 | ``` 105 | 106 | #### isMicrophoneAvailable [bool] 107 | 108 | The user has to give permission for their microphone to be used before transcription can begin. They are asked for permission when `svelte-speech-recognition` first tries to start listening. This state will become `false` if they deny access. In this case, it's advised that you disable voice-driven features and indicate that microphone access is needed for them to work. 109 | 110 | ```sv 111 | {#if (!isMicrophoneAvailable)} 112 | // Render some fallback content 113 | {/if} 114 | ``` 115 | 116 | ## SpeechRecognition 117 | 118 | Object providing functions to manage the global state of the microphone. Import with: 119 | 120 | ```sv 121 | import SpeechRecognition from 'svelte-speech-recognition/SpeechRecognition' 122 | ``` 123 | 124 | ### Functions 125 | 126 | #### startListening (async) 127 | 128 | Start listening to speech. 129 | 130 | ```sv 131 | SpeechRecognition.startListening() 132 | ``` 133 | 134 | This is an asynchronous function, so it will need to be awaited if you want to do something after the microphone has been turned on. 135 | 136 | It can be called with an options argument. For example: 137 | 138 | ```sv 139 | SpeechRecognition.startListening({ 140 | continuous: true, 141 | language: 'zh-CN' 142 | }) 143 | ``` 144 | 145 | The following options are available: 146 | 147 | ##### continuous [bool] 148 | 149 | By default, the microphone will stop listening when the user stops speaking (`continuous: false`). This reflects the approach taken by "press to talk" buttons on modern devices. 150 | 151 | If you want to listen continuously, set the `continuous` property to `true` when calling `startListening`. The microphone will continue to listen, even after the user has stopped speaking. 152 | 153 | ```sv 154 | SpeechRecognition.startListening({ continuous: true }) 155 | ``` 156 | 157 | #### language [string] 158 | 159 | To listen for a specific language, you can pass a language tag (e.g. `'zh-CN'` for Chinese) when calling `startListening`. 160 | 161 | ```sv 162 | SpeechRecognition.startListening({ language: 'zh-CN' }) 163 | ``` 164 | 165 | Some known supported languages (based on [this Stack Overflow post](http://stackoverflow.com/a/14302134/338039)): 166 | 167 | * Afrikaans `af` 168 | * Basque `eu` 169 | * Bulgarian `bg` 170 | * Catalan `ca` 171 | * Arabic (Egypt) `ar-EG` 172 | * Arabic (Jordan) `ar-JO` 173 | * Arabic (Kuwait) `ar-KW` 174 | * Arabic (Lebanon) `ar-LB` 175 | * Arabic (Qatar) `ar-QA` 176 | * Arabic (UAE) `ar-AE` 177 | * Arabic (Morocco) `ar-MA` 178 | * Arabic (Iraq) `ar-IQ` 179 | * Arabic (Algeria) `ar-DZ` 180 | * Arabic (Bahrain) `ar-BH` 181 | * Arabic (Lybia) `ar-LY` 182 | * Arabic (Oman) `ar-OM` 183 | * Arabic (Saudi Arabia) `ar-SA` 184 | * Arabic (Tunisia) `ar-TN` 185 | * Arabic (Yemen) `ar-YE` 186 | * Czech `cs` 187 | * Dutch `nl-NL` 188 | * English (Australia) `en-AU` 189 | * English (Canada) `en-CA` 190 | * English (India) `en-IN` 191 | * English (New Zealand) `en-NZ` 192 | * English (South Africa) `en-ZA` 193 | * English(UK) `en-GB` 194 | * English(US) `en-US` 195 | * Finnish `fi` 196 | * French `fr-FR` 197 | * Galician `gl` 198 | * German `de-DE` 199 | * Greek `el-GR` 200 | * Hebrew `he` 201 | * Hungarian `hu` 202 | * Icelandic `is` 203 | * Italian `it-IT` 204 | * Indonesian `id` 205 | * Japanese `ja` 206 | * Korean `ko` 207 | * Latin `la` 208 | * Mandarin Chinese `zh-CN` 209 | * Taiwanese `zh-TW` 210 | * Cantonese `zh-HK` 211 | * Malaysian `ms-MY` 212 | * Norwegian `no-NO` 213 | * Polish `pl` 214 | * Pig Latin `xx-piglatin` 215 | * Portuguese `pt-PT` 216 | * Portuguese (Brasil) `pt-br` 217 | * Romanian `ro-RO` 218 | * Russian `ru` 219 | * Serbian `sr-SP` 220 | * Slovak `sk` 221 | * Spanish (Argentina) `es-AR` 222 | * Spanish (Bolivia) `es-BO` 223 | * Spanish (Chile) `es-CL` 224 | * Spanish (Colombia) `es-CO` 225 | * Spanish (Costa Rica) `es-CR` 226 | * Spanish (Dominican Republic) `es-DO` 227 | * Spanish (Ecuador) `es-EC` 228 | * Spanish (El Salvador) `es-SV` 229 | * Spanish (Guatemala) `es-GT` 230 | * Spanish (Honduras) `es-HN` 231 | * Spanish (Mexico) `es-MX` 232 | * Spanish (Nicaragua) `es-NI` 233 | * Spanish (Panama) `es-PA` 234 | * Spanish (Paraguay) `es-PY` 235 | * Spanish (Peru) `es-PE` 236 | * Spanish (Puerto Rico) `es-PR` 237 | * Spanish (Spain) `es-ES` 238 | * Spanish (US) `es-US` 239 | * Spanish (Uruguay) `es-UY` 240 | * Spanish (Venezuela) `es-VE` 241 | * Swedish `sv-SE` 242 | * Turkish `tr` 243 | * Zulu `zu` 244 | 245 | #### stopListening (async) 246 | 247 | Turn the microphone off, but still finish processing any speech in progress. 248 | 249 | ```sv 250 | SpeechRecognition.stopListening() 251 | ``` 252 | 253 | This is an asynchronous function, so it will need to be awaited if you want to do something after the microphone has been turned off. 254 | 255 | #### abortListening (async) 256 | 257 | Turn the microphone off, and cancel the processing of any speech in progress. 258 | 259 | ```sv 260 | SpeechRecognition.abortListening() 261 | ``` 262 | 263 | This is an asynchronous function, so it will need to be awaited if you want to do something after the microphone has been turned off. 264 | 265 | #### getRecognition 266 | 267 | This returns the underlying [object](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition) used by Web Speech API. 268 | 269 | #### applyPolyfill 270 | 271 | Replace the native Speech Recognition engine (if there is one) with a custom implementation of the [W3C SpeechRecognition specification](https://wicg.github.io/speech-api/#speechreco-section). If there is a Speech Recognition implementation already listening to the microphone, this will be turned off. See [Polyfills](./POLYFILLS.md) for more information on how to use this. 272 | 273 | ```sv 274 | SpeechRecognition.applyPolyfill(SpeechRecognitionPolyfill) 275 | ``` -------------------------------------------------------------------------------- /docs/COMPONENTS.md: -------------------------------------------------------------------------------- 1 | # Svelte Components 2 | 3 | Below are the listen of Svelte components, their props, and what they can do. For code examples please look in [src/routes/components/Dictaphones.svelte](../src/routes/components/Dictaphones.svelte). Components come with a default button for testing but have a slot you can customize. 4 | 5 | - [Svelte Components](#svelte-components) 6 | - [Example w/ Ponyfill](#example-w-ponyfill) 7 | - [Listen](#listen) 8 | - [Stop](#stop) 9 | 10 | --- 11 | 12 | ## Example w/ Ponyfill 13 | 14 | ```sv 15 | 31 | 32 |
33 | {#if showFirstWidget} 34 | 35 | {/if} 36 | 37 | 38 |
39 | 40 | 41 | 47 |
48 | 49 |
50 | 51 | 52 | 53 |
54 | ``` 55 | 56 | --- 57 | ## Listen 58 | Props: 59 | * `language: string` Speech Recognition API language (support types [here](./API.md#language)) 60 | * `continuous: boolean` Whether it will listen continuously or for one phrase 61 | * `SpeechRecognition` Instance of SpeechRecognition object 62 | * `buttonText: string` String you can customize for default button text 63 | 64 | Use: 65 | 66 | When the user clicks on this component the Speech Recognition API will start listening for text/commands. 67 | 68 | --- 69 | 70 | ## Stop 71 | Props: 72 | * `SpeechRecognition` Instance of SpeechRecognition object 73 | 74 | Use: 75 | 76 | When the clicks on this component the Speech Recognition API will stop. 77 | 78 | -------------------------------------------------------------------------------- /docs/POLYFILLS.md: -------------------------------------------------------------------------------- 1 | # Polyfills 2 | 3 | If you want `svelte-speech-recognition` to work on more browsers than just Chrome, you can integrate a polyfill. This is a piece of code that fills in some missing feature in browsers that don't support it. 4 | 5 | Under the hood, Web Speech API in Chrome uses Google's speech recognition servers. To replicate this functionality elsewhere, you will need to host your own speech recognition service and implement the Web Speech API using that service. That implementation, which is essentially a polyfill, can then be plugged into `svelte-speech-recognition`. You can write that polyfill yourself, but it's recommended you use one someone else has already made. 6 | 7 | # Basic usage 8 | 9 | The `SpeechRecognition` class exported by `svelte-speech-recognition` has the method `applyPolyfill`. This can take an implementation of the [W3C SpeechRecognition specification](https://wicg.github.io/speech-api/#speechreco-section). From then on, that implementation will used by `svelte-speech-recognition` to transcribe speech picked up by the microphone. 10 | 11 | ```sv 12 | SpeechRecognition.applyPolyfill(SpeechRecognitionPolyfill) 13 | ``` 14 | 15 | Note that this type of polyfill that does not pollute the global scope is known as a "ponyfill" - the distinction is explained [here](https://ponyfoo.com/articles/polyfills-or-ponyfills). `svelte-speech-recognition` will also pick up traditional polyfills - just make sure you import them before `svelte-speech-recognition`. 16 | 17 | ## Usage recommendations 18 | * Call this as early as possible to minimise periods where fallback content, which you should render while the polyfill is loading, is rendered. Also note that if there is a Speech Recognition implementation already listening to the microphone, this will be turned off when the polyfill is applied, so make sure the polyfill is applied before rendering any buttons to start listening 19 | * After `applyPolyfill` has been called, `browserSupportsSpeechRecognition` will be `true` on _most_ browsers, but there are still exceptions. Browsers like Internet Explorer do not support the APIs needed for polyfills - in these cases where `browserSupportsSpeechRecognition` is `false`, you should still have some suitable fallback content 20 | * Do not rely on polyfills being perfect implementations of the Speech Recognition specification - make sure you have tested them in different browsers and are aware of their individual limitations 21 | 22 | # Polyfill libraries 23 | 24 | Rather than roll your own, you should use a ready-made polyfill for a cloud provider's speech recognition service. `svelte-speech-recognition` currently supports polyfills for the following cloud providers: 25 | 26 | ## Speechly 27 | 28 | 29 | Speechly 30 | 31 | 32 | [Speechly](https://www.speechly.com/) specialises in enabling developers to create voice-driven UIs and provides a speech recognition API with a generous free tier to get you started. Their web speech recognition polyfill was developed with `react-speech-recognition` (the original fork for this library) in mind so is a great choice to combine with this library. 33 | 34 | * Polyfill repo: [speech-recognition-polyfill](https://github.com/speechly/speech-recognition-polyfill) 35 | * Polyfill author: [speechly](https://github.com/speechly) 36 | * Requirements: 37 | * Install `@speechly/speech-recognition-polyfill` in your web app 38 | * You will need a Speechly app ID. To get one of these, sign up with Speechly and follow [the guide here](https://docs.speechly.com/quick-start/stt-only/) 39 | 40 | Here is a basic example combining `speech-recognition-polyfill` and `svelte-speech-recognition` to get you started. This code worked with version 1.0.0 of the polyfill in May 2021 - if it has become outdated due to changes in the polyfill or in Speechly, please raise a GitHub issue or PR to get this updated. 41 | 42 | ```sv 43 | 59 | 60 | {#if (!browserSupportsSpeechRecognition)} 61 | Browser doesn't support speech recognition 62 | {:else} 63 |
64 |

Microphone: {listening ? 'on' : 'off'}

65 | 71 |

{$transcriptStore.finalTranscript}

72 |
73 | {/if} 74 | ``` 75 | 76 | ### Limitations 77 | * The `lang` property is currently unsupported, defaulting to English transcription. In `svelte-speech-recognition`, this means that the `language` property in `startListening` cannot be used to change languages when using this polyfill. New languages will be coming soon! 78 | * Transcripts are generated in uppercase letters without punctuation. If needed, you can transform them using [toLowerCase()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase) 79 | 80 |
81 |
82 | 83 | ## Microsoft Azure Cognitive Services 84 | 85 | 86 | Microsoft Azure Cognitive Services 87 | 88 | 89 | This is Microsoft's offering for speech recognition (among many other features). The free trial gives you $200 of credit to get started. It's pretty easy to set up - see the [documentation](https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/). 90 | 91 | * Polyfill repo: [web-speech-cognitive-services](https://github.com/compulim/web-speech-cognitive-services) 92 | * Polyfill author: [compulim](https://github.com/compulim) 93 | * Requirements: 94 | * Install `web-speech-cognitive-services` and `microsoft-cognitiveservices-speech-sdk` in your web app for this polyfill to function 95 | * You will need two things to configure this polyfill: the name of the Azure region your Speech Service is deployed in, plus a subscription key (or better still, an authorization token). [This doc](https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/overview#find-keys-and-region) explains how to find those 96 | 97 | Here is a basic example combining `web-speech-cognitive-services` and `svelte-speech-recognition` to get you started (do not use this in production; for a production-friendly version, read on below). This code worked with version 7.1.0 of the polyfill in February 2021 - if it has become outdated due to changes in the polyfill or in Azure Cognitive Services, please raise a GitHub issue or PR to get this updated. 98 | 99 | ```sv 100 | 122 | 123 | {#if (!browserSupportsSpeechRecognition)} 124 | Browser doesn't support speech recognition 125 | {:else} 126 |
127 |

Microphone: {listening ? 'on' : 'off'}

128 | 134 |

{$transcriptStore.finalTranscript}

135 |
136 | {/if} 137 | ``` 138 | 139 | ### Usage in production 140 | 141 | Your subscription key is a secret that you should not be leaking to your users in production. In other words, it should never be downloaded to your users' browsers. A more secure approach that's recommended by Microsoft is to exchange your subscription key for an authorization token, which has a limited lifetime. You should get this token on your backend and pass this to your Svelte app. Microsoft give guidance on how to do this [here](https://docs.microsoft.com/en-us/azure/cognitive-services/authentication?tabs=powershell). 142 | 143 | Once your Svelte app has the authorization token, it should be passed into the polyfill creator instead of the subscription key like this: 144 | ```sv 145 | const { SpeechRecognition: AzureSpeechRecognition } = createSpeechServicesPonyfill({ 146 | credentials: { 147 | region: REGION, 148 | authorizationToken: AUTHORIZATION_TOKEN, 149 | } 150 | }); 151 | ``` 152 | 153 | ### Limitations 154 | * There is currently a [bug](https://github.com/compulim/web-speech-cognitive-services/issues/166) in this polyfill's `stop` method when using continuous listening. If you are using `continuous: true`, use `abortListening` to stop the transcription. Otherwise, you can use `stopListening`. 155 | * On Safari and Firefox, an error will be thrown if calling `startListening` to switch to a different language without first calling `stopListening`. It's recommended that you stick to one language and, if you do need to change languages, call `stopListening` first 156 | * If you don't specify a language, Azure will return a 400 response. When calling `startListening`, you will need to explicitly provide one of the language codes defined [here](https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/language-support). For English, use `en-GB` or `en-US` 157 | * Currently untested on iOS (let me know if it works!) 158 | 159 |
160 |
161 | 162 | ## AWS Transcribe 163 | 164 | There is no polyfill for [AWS Transcribe](https://aws.amazon.com/transcribe/) in the ecosystem yet, though a promising project can be found [here](https://github.com/ceuk/speech-recognition-aws-polyfill). 165 | 166 | # Providing your own polyfill 167 | 168 | If you want to roll your own implementation of the Speech Recognition API, follow the [W3C SpeechRecognition specification](https://wicg.github.io/speech-api/#speechreco-section). You should implement at least the following for `svelte-speech-recognition` to work: 169 | * `continuous` (property) 170 | * `lang` (property) 171 | * `interimResults` (property) 172 | * `onresult` (property). On the events received, the following properties are used: 173 | * `event.resultIndex` 174 | * `event.results[i].isFinal` 175 | * `event.results[i][0].transcript` 176 | * `event.results[i][0].confidence` 177 | * `onend` (property) 178 | * `onerror` (property) 179 | * `start` (method) 180 | * `stop` (method) 181 | * `abort` (method) 182 | -------------------------------------------------------------------------------- /docs/logos/microsoft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhubbardsf/svelte-speech-recognition/6e0d028d1b8cd1e81cdeafb8179a59f9c9800015/docs/logos/microsoft.png -------------------------------------------------------------------------------- /docs/logos/speechly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhubbardsf/svelte-speech-recognition/6e0d028d1b8cd1e81cdeafb8179a59f9c9800015/docs/logos/speechly.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-speech-recognition", 3 | "version": "0.0.7", 4 | "author": "Josh Hubbard (https://joshuahubbard.dev/)", 5 | "description": "A Svelte wrapper for the Sortable.js library", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/jhubbardsf/svelte-speech-recognition.git" 9 | }, 10 | "publishConfig": { 11 | "access": "public" 12 | }, 13 | "scripts": { 14 | "dev": "svelte-kit dev", 15 | "build": "svelte-kit build", 16 | "package": "svelte-kit package", 17 | "preview": "svelte-kit preview", 18 | "prepare": "svelte-kit sync", 19 | "check": "svelte-check --tsconfig ./tsconfig.json", 20 | "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", 21 | "lint": "prettier --check --plugin-search-dir=. . && eslint .", 22 | "format": "prettier --write --plugin-search-dir=. .", 23 | "debugger": "NODE_OPTIONS=\"--inspect\" svelte-kit dev" 24 | }, 25 | "devDependencies": { 26 | "@speechly/speech-recognition-polyfill": "^1.1.0", 27 | "@sveltejs/adapter-auto": "next", 28 | "@sveltejs/kit": "next", 29 | "@types/cookie": "^0.4.1", 30 | "@typescript-eslint/eslint-plugin": "^5.10.1", 31 | "@typescript-eslint/parser": "^5.10.1", 32 | "eslint": "^8.12.0", 33 | "eslint-config-prettier": "^8.3.0", 34 | "eslint-plugin-svelte3": "^4.0.0", 35 | "prettier": "^2.5.1", 36 | "prettier-plugin-svelte": "^2.5.0", 37 | "svelte": "^3.46.0", 38 | "svelte-check": "^2.2.6", 39 | "svelte-preprocess": "^4.10.5", 40 | "svelte2tsx": "^0.5.10", 41 | "tslib": "^2.3.1", 42 | "typescript": "~4.6.2", 43 | "postcss": "^8.4.12", 44 | "postcss-load-config": "^3.1.4", 45 | "autoprefixer": "^10.4.4", 46 | "tailwindcss": "^3.0.23" 47 | }, 48 | "type": "module", 49 | "keywords": [ 50 | "svelte", 51 | "svelte-kit", 52 | "speech-recognition" 53 | ], 54 | "license": "MIT" 55 | } -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.4 2 | 3 | specifiers: 4 | '@speechly/speech-recognition-polyfill': ^1.1.0 5 | '@sveltejs/adapter-auto': next 6 | '@sveltejs/kit': next 7 | '@types/cookie': ^0.4.1 8 | '@typescript-eslint/eslint-plugin': ^5.10.1 9 | '@typescript-eslint/parser': ^5.10.1 10 | autoprefixer: ^10.4.4 11 | eslint: ^8.12.0 12 | eslint-config-prettier: ^8.3.0 13 | eslint-plugin-svelte3: ^4.0.0 14 | postcss: ^8.4.12 15 | postcss-load-config: ^3.1.4 16 | prettier: ^2.5.1 17 | prettier-plugin-svelte: ^2.5.0 18 | svelte: ^3.46.0 19 | svelte-check: ^2.2.6 20 | svelte-preprocess: ^4.10.5 21 | svelte2tsx: ^0.5.10 22 | tailwindcss: ^3.0.23 23 | tslib: ^2.3.1 24 | typescript: ~4.6.2 25 | 26 | devDependencies: 27 | '@speechly/speech-recognition-polyfill': 1.1.0 28 | '@sveltejs/adapter-auto': 1.0.0-next.48 29 | '@sveltejs/kit': 1.0.0-next.344_svelte@3.48.0 30 | '@types/cookie': 0.4.1 31 | '@typescript-eslint/eslint-plugin': 5.25.0_jorowkvdqu6pwramweg5le7ncu 32 | '@typescript-eslint/parser': 5.25.0_utdtartgf6fqqgkivzeynh76la 33 | autoprefixer: 10.4.7_postcss@8.4.14 34 | eslint: 8.16.0 35 | eslint-config-prettier: 8.5.0_eslint@8.16.0 36 | eslint-plugin-svelte3: 4.0.0_vypdqzeyqutkgs6qzc7qod4c64 37 | postcss: 8.4.14 38 | postcss-load-config: 3.1.4_postcss@8.4.14 39 | prettier: 2.6.2 40 | prettier-plugin-svelte: 2.7.0_kkjbqzpydplecjtkxrgomroeru 41 | svelte: 3.48.0 42 | svelte-check: 2.7.1_bwfybwdzwmlevsatlte2x4gwcy 43 | svelte-preprocess: 4.10.6_kwmypdju4ysizxi7azib3bf22y 44 | svelte2tsx: 0.5.10_wwvk7nlptlrqo2czohjtk6eiqm 45 | tailwindcss: 3.0.24 46 | tslib: 2.4.0 47 | typescript: 4.6.4 48 | 49 | packages: 50 | 51 | /@eslint/eslintrc/1.3.0: 52 | resolution: {integrity: sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==} 53 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 54 | dependencies: 55 | ajv: 6.12.6 56 | debug: 4.3.4 57 | espree: 9.3.2 58 | globals: 13.15.0 59 | ignore: 5.2.0 60 | import-fresh: 3.3.0 61 | js-yaml: 4.1.0 62 | minimatch: 3.1.2 63 | strip-json-comments: 3.1.1 64 | transitivePeerDependencies: 65 | - supports-color 66 | dev: true 67 | 68 | /@humanwhocodes/config-array/0.9.5: 69 | resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} 70 | engines: {node: '>=10.10.0'} 71 | dependencies: 72 | '@humanwhocodes/object-schema': 1.2.1 73 | debug: 4.3.4 74 | minimatch: 3.1.2 75 | transitivePeerDependencies: 76 | - supports-color 77 | dev: true 78 | 79 | /@humanwhocodes/object-schema/1.2.1: 80 | resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} 81 | dev: true 82 | 83 | /@iarna/toml/2.2.5: 84 | resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} 85 | dev: true 86 | 87 | /@jridgewell/resolve-uri/3.0.7: 88 | resolution: {integrity: sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==} 89 | engines: {node: '>=6.0.0'} 90 | dev: true 91 | 92 | /@jridgewell/sourcemap-codec/1.4.13: 93 | resolution: {integrity: sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==} 94 | dev: true 95 | 96 | /@jridgewell/trace-mapping/0.3.13: 97 | resolution: {integrity: sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==} 98 | dependencies: 99 | '@jridgewell/resolve-uri': 3.0.7 100 | '@jridgewell/sourcemap-codec': 1.4.13 101 | dev: true 102 | 103 | /@mapbox/node-pre-gyp/1.0.9: 104 | resolution: {integrity: sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==} 105 | hasBin: true 106 | dependencies: 107 | detect-libc: 2.0.1 108 | https-proxy-agent: 5.0.1 109 | make-dir: 3.1.0 110 | node-fetch: 2.6.7 111 | nopt: 5.0.0 112 | npmlog: 5.0.1 113 | rimraf: 3.0.2 114 | semver: 7.3.7 115 | tar: 6.1.11 116 | transitivePeerDependencies: 117 | - encoding 118 | - supports-color 119 | dev: true 120 | 121 | /@nodelib/fs.scandir/2.1.5: 122 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 123 | engines: {node: '>= 8'} 124 | dependencies: 125 | '@nodelib/fs.stat': 2.0.5 126 | run-parallel: 1.2.0 127 | dev: true 128 | 129 | /@nodelib/fs.stat/2.0.5: 130 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 131 | engines: {node: '>= 8'} 132 | dev: true 133 | 134 | /@nodelib/fs.walk/1.2.8: 135 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 136 | engines: {node: '>= 8'} 137 | dependencies: 138 | '@nodelib/fs.scandir': 2.1.5 139 | fastq: 1.13.0 140 | dev: true 141 | 142 | /@rollup/pluginutils/4.2.1: 143 | resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} 144 | engines: {node: '>= 8.0.0'} 145 | dependencies: 146 | estree-walker: 2.0.2 147 | picomatch: 2.3.1 148 | dev: true 149 | 150 | /@speechly/browser-client/1.5.0: 151 | resolution: {integrity: sha512-sAhLuwV1YMoMoe3mY8WgT3C4+89FimBj0oAPMAtxl7PdWWWAAvWRqB1n9MzTaDzGN3mvu9tSkqrS+DHWU4jw4A==} 152 | dependencies: 153 | base-64: 0.1.0 154 | uuid: 8.3.2 155 | dev: true 156 | 157 | /@speechly/speech-recognition-polyfill/1.1.0: 158 | resolution: {integrity: sha512-GFzyDcqn0y0bOlo3Z8bq+lwR1GxLk3pta2hrXs6z20rV0mXxlvQDOEY3SGq1IgfvInL7CILVINCFUopl5oGozg==} 159 | dependencies: 160 | '@speechly/browser-client': 1.5.0 161 | dev: true 162 | 163 | /@sveltejs/adapter-auto/1.0.0-next.48: 164 | resolution: {integrity: sha512-DZsMi31t5AsKYafmRGcgKcuGZRz4EN4sQ0UacPN85K3+9Xh7WadfHwWMfFFLIvCUMLE3jqZw+RErnZxUDZ1EGA==} 165 | dependencies: 166 | '@sveltejs/adapter-cloudflare': 1.0.0-next.21 167 | '@sveltejs/adapter-netlify': 1.0.0-next.62 168 | '@sveltejs/adapter-vercel': 1.0.0-next.56 169 | transitivePeerDependencies: 170 | - encoding 171 | - supports-color 172 | dev: true 173 | 174 | /@sveltejs/adapter-cloudflare/1.0.0-next.21: 175 | resolution: {integrity: sha512-bPD62sGuCfo20jCz01ihd5ArxyiCu7iogQrQQK+higbz6OR1q34VnXCuNg/vHuDp+6kegLvRTRD0Qe22WVOZbw==} 176 | dependencies: 177 | esbuild: 0.14.39 178 | worktop: 0.8.0-next.14 179 | dev: true 180 | 181 | /@sveltejs/adapter-netlify/1.0.0-next.62: 182 | resolution: {integrity: sha512-oX5Q0I57eI2bvd5FYtRFArevcY90Aza0OywtmuO/USoE4f+Z96idktaKOdyMhjlIQkc2GTablJSA88UIycwwMA==} 183 | dependencies: 184 | '@iarna/toml': 2.2.5 185 | esbuild: 0.14.39 186 | set-cookie-parser: 2.4.8 187 | tiny-glob: 0.2.9 188 | dev: true 189 | 190 | /@sveltejs/adapter-vercel/1.0.0-next.56: 191 | resolution: {integrity: sha512-DZj4wLwMb3xIzxue5oGrtr86xrBq/SwK28NuA7Txblg2wSRE9hhrTUQ0ERlP6V/qdXZ9ZE58Rq8L8/6Vt7tqPA==} 192 | dependencies: 193 | '@vercel/nft': 0.19.1 194 | esbuild: 0.14.39 195 | transitivePeerDependencies: 196 | - encoding 197 | - supports-color 198 | dev: true 199 | 200 | /@sveltejs/kit/1.0.0-next.344_svelte@3.48.0: 201 | resolution: {integrity: sha512-IKFyB/ErD1E6/Gl/AKA2EvOPmu6jdHDIoDYStL0PP12ZASOKTPNfSgusPHMNOTV+qyJKwo8JdOTWwLuFmZLq8A==} 202 | engines: {node: '>=16.7'} 203 | hasBin: true 204 | peerDependencies: 205 | svelte: ^3.44.0 206 | dependencies: 207 | '@sveltejs/vite-plugin-svelte': 1.0.0-next.44_svelte@3.48.0+vite@2.9.9 208 | chokidar: 3.5.3 209 | sade: 1.8.1 210 | svelte: 3.48.0 211 | vite: 2.9.9 212 | transitivePeerDependencies: 213 | - diff-match-patch 214 | - less 215 | - sass 216 | - stylus 217 | - supports-color 218 | dev: true 219 | 220 | /@sveltejs/vite-plugin-svelte/1.0.0-next.44_svelte@3.48.0+vite@2.9.9: 221 | resolution: {integrity: sha512-n+sssEWbzykPS447FmnNyU5GxEhrBPDVd0lxNZnxRGz9P6651LjjwAnISKr3CKgT9v8IybP8VD0n2i5XzbqExg==} 222 | engines: {node: ^14.13.1 || >= 16} 223 | peerDependencies: 224 | diff-match-patch: ^1.0.5 225 | svelte: ^3.44.0 226 | vite: ^2.9.0 227 | peerDependenciesMeta: 228 | diff-match-patch: 229 | optional: true 230 | dependencies: 231 | '@rollup/pluginutils': 4.2.1 232 | debug: 4.3.4 233 | deepmerge: 4.2.2 234 | kleur: 4.1.4 235 | magic-string: 0.26.2 236 | svelte: 3.48.0 237 | svelte-hmr: 0.14.11_svelte@3.48.0 238 | vite: 2.9.9 239 | transitivePeerDependencies: 240 | - supports-color 241 | dev: true 242 | 243 | /@types/cookie/0.4.1: 244 | resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} 245 | dev: true 246 | 247 | /@types/json-schema/7.0.11: 248 | resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} 249 | dev: true 250 | 251 | /@types/node/17.0.35: 252 | resolution: {integrity: sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==} 253 | dev: true 254 | 255 | /@types/pug/2.0.6: 256 | resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==} 257 | dev: true 258 | 259 | /@types/sass/1.43.1: 260 | resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} 261 | dependencies: 262 | '@types/node': 17.0.35 263 | dev: true 264 | 265 | /@typescript-eslint/eslint-plugin/5.25.0_jorowkvdqu6pwramweg5le7ncu: 266 | resolution: {integrity: sha512-icYrFnUzvm+LhW0QeJNKkezBu6tJs9p/53dpPLFH8zoM9w1tfaKzVurkPotEpAqQ8Vf8uaFyL5jHd0Vs6Z0ZQg==} 267 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 268 | peerDependencies: 269 | '@typescript-eslint/parser': ^5.0.0 270 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 271 | typescript: '*' 272 | peerDependenciesMeta: 273 | typescript: 274 | optional: true 275 | dependencies: 276 | '@typescript-eslint/parser': 5.25.0_utdtartgf6fqqgkivzeynh76la 277 | '@typescript-eslint/scope-manager': 5.25.0 278 | '@typescript-eslint/type-utils': 5.25.0_utdtartgf6fqqgkivzeynh76la 279 | '@typescript-eslint/utils': 5.25.0_utdtartgf6fqqgkivzeynh76la 280 | debug: 4.3.4 281 | eslint: 8.16.0 282 | functional-red-black-tree: 1.0.1 283 | ignore: 5.2.0 284 | regexpp: 3.2.0 285 | semver: 7.3.7 286 | tsutils: 3.21.0_typescript@4.6.4 287 | typescript: 4.6.4 288 | transitivePeerDependencies: 289 | - supports-color 290 | dev: true 291 | 292 | /@typescript-eslint/parser/5.25.0_utdtartgf6fqqgkivzeynh76la: 293 | resolution: {integrity: sha512-r3hwrOWYbNKP1nTcIw/aZoH+8bBnh/Lh1iDHoFpyG4DnCpvEdctrSl6LOo19fZbzypjQMHdajolxs6VpYoChgA==} 294 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 295 | peerDependencies: 296 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 297 | typescript: '*' 298 | peerDependenciesMeta: 299 | typescript: 300 | optional: true 301 | dependencies: 302 | '@typescript-eslint/scope-manager': 5.25.0 303 | '@typescript-eslint/types': 5.25.0 304 | '@typescript-eslint/typescript-estree': 5.25.0_typescript@4.6.4 305 | debug: 4.3.4 306 | eslint: 8.16.0 307 | typescript: 4.6.4 308 | transitivePeerDependencies: 309 | - supports-color 310 | dev: true 311 | 312 | /@typescript-eslint/scope-manager/5.25.0: 313 | resolution: {integrity: sha512-p4SKTFWj+2VpreUZ5xMQsBMDdQ9XdRvODKXN4EksyBjFp2YvQdLkyHqOffakYZPuWJUDNu3jVXtHALDyTv3cww==} 314 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 315 | dependencies: 316 | '@typescript-eslint/types': 5.25.0 317 | '@typescript-eslint/visitor-keys': 5.25.0 318 | dev: true 319 | 320 | /@typescript-eslint/type-utils/5.25.0_utdtartgf6fqqgkivzeynh76la: 321 | resolution: {integrity: sha512-B6nb3GK3Gv1Rsb2pqalebe/RyQoyG/WDy9yhj8EE0Ikds4Xa8RR28nHz+wlt4tMZk5bnAr0f3oC8TuDAd5CPrw==} 322 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 323 | peerDependencies: 324 | eslint: '*' 325 | typescript: '*' 326 | peerDependenciesMeta: 327 | typescript: 328 | optional: true 329 | dependencies: 330 | '@typescript-eslint/utils': 5.25.0_utdtartgf6fqqgkivzeynh76la 331 | debug: 4.3.4 332 | eslint: 8.16.0 333 | tsutils: 3.21.0_typescript@4.6.4 334 | typescript: 4.6.4 335 | transitivePeerDependencies: 336 | - supports-color 337 | dev: true 338 | 339 | /@typescript-eslint/types/5.25.0: 340 | resolution: {integrity: sha512-7fWqfxr0KNHj75PFqlGX24gWjdV/FDBABXL5dyvBOWHpACGyveok8Uj4ipPX/1fGU63fBkzSIycEje4XsOxUFA==} 341 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 342 | dev: true 343 | 344 | /@typescript-eslint/typescript-estree/5.25.0_typescript@4.6.4: 345 | resolution: {integrity: sha512-MrPODKDych/oWs/71LCnuO7NyR681HuBly2uLnX3r5i4ME7q/yBqC4hW33kmxtuauLTM0OuBOhhkFaxCCOjEEw==} 346 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 347 | peerDependencies: 348 | typescript: '*' 349 | peerDependenciesMeta: 350 | typescript: 351 | optional: true 352 | dependencies: 353 | '@typescript-eslint/types': 5.25.0 354 | '@typescript-eslint/visitor-keys': 5.25.0 355 | debug: 4.3.4 356 | globby: 11.1.0 357 | is-glob: 4.0.3 358 | semver: 7.3.7 359 | tsutils: 3.21.0_typescript@4.6.4 360 | typescript: 4.6.4 361 | transitivePeerDependencies: 362 | - supports-color 363 | dev: true 364 | 365 | /@typescript-eslint/utils/5.25.0_utdtartgf6fqqgkivzeynh76la: 366 | resolution: {integrity: sha512-qNC9bhnz/n9Kba3yI6HQgQdBLuxDoMgdjzdhSInZh6NaDnFpTUlwNGxplUFWfY260Ya0TRPvkg9dd57qxrJI9g==} 367 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 368 | peerDependencies: 369 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 370 | dependencies: 371 | '@types/json-schema': 7.0.11 372 | '@typescript-eslint/scope-manager': 5.25.0 373 | '@typescript-eslint/types': 5.25.0 374 | '@typescript-eslint/typescript-estree': 5.25.0_typescript@4.6.4 375 | eslint: 8.16.0 376 | eslint-scope: 5.1.1 377 | eslint-utils: 3.0.0_eslint@8.16.0 378 | transitivePeerDependencies: 379 | - supports-color 380 | - typescript 381 | dev: true 382 | 383 | /@typescript-eslint/visitor-keys/5.25.0: 384 | resolution: {integrity: sha512-yd26vFgMsC4h2dgX4+LR+GeicSKIfUvZREFLf3DDjZPtqgLx5AJZr6TetMNwFP9hcKreTTeztQYBTNbNoOycwA==} 385 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 386 | dependencies: 387 | '@typescript-eslint/types': 5.25.0 388 | eslint-visitor-keys: 3.3.0 389 | dev: true 390 | 391 | /@vercel/nft/0.19.1: 392 | resolution: {integrity: sha512-klR5oN7S3WJsZz0r6Xsq7o8YlFEyU3/00VmlpZzIPVFzKfbcEjXo/sVR5lQBUqNKuOzhcbxaFtzW9aOyHjmPYA==} 393 | hasBin: true 394 | dependencies: 395 | '@mapbox/node-pre-gyp': 1.0.9 396 | acorn: 8.7.1 397 | bindings: 1.5.0 398 | estree-walker: 2.0.2 399 | glob: 7.2.3 400 | graceful-fs: 4.2.10 401 | micromatch: 4.0.5 402 | node-gyp-build: 4.4.0 403 | node-pre-gyp: 0.13.0 404 | resolve-from: 5.0.0 405 | rollup-pluginutils: 2.8.2 406 | transitivePeerDependencies: 407 | - encoding 408 | - supports-color 409 | dev: true 410 | 411 | /abbrev/1.1.1: 412 | resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} 413 | dev: true 414 | 415 | /acorn-jsx/5.3.2_acorn@8.7.1: 416 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 417 | peerDependencies: 418 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 419 | dependencies: 420 | acorn: 8.7.1 421 | dev: true 422 | 423 | /acorn-node/1.8.2: 424 | resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==} 425 | dependencies: 426 | acorn: 7.4.1 427 | acorn-walk: 7.2.0 428 | xtend: 4.0.2 429 | dev: true 430 | 431 | /acorn-walk/7.2.0: 432 | resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} 433 | engines: {node: '>=0.4.0'} 434 | dev: true 435 | 436 | /acorn/7.4.1: 437 | resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} 438 | engines: {node: '>=0.4.0'} 439 | hasBin: true 440 | dev: true 441 | 442 | /acorn/8.7.1: 443 | resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==} 444 | engines: {node: '>=0.4.0'} 445 | hasBin: true 446 | dev: true 447 | 448 | /agent-base/6.0.2: 449 | resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} 450 | engines: {node: '>= 6.0.0'} 451 | dependencies: 452 | debug: 4.3.4 453 | transitivePeerDependencies: 454 | - supports-color 455 | dev: true 456 | 457 | /ajv/6.12.6: 458 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 459 | dependencies: 460 | fast-deep-equal: 3.1.3 461 | fast-json-stable-stringify: 2.1.0 462 | json-schema-traverse: 0.4.1 463 | uri-js: 4.4.1 464 | dev: true 465 | 466 | /ansi-regex/2.1.1: 467 | resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} 468 | engines: {node: '>=0.10.0'} 469 | dev: true 470 | 471 | /ansi-regex/5.0.1: 472 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 473 | engines: {node: '>=8'} 474 | dev: true 475 | 476 | /ansi-styles/4.3.0: 477 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 478 | engines: {node: '>=8'} 479 | dependencies: 480 | color-convert: 2.0.1 481 | dev: true 482 | 483 | /anymatch/3.1.2: 484 | resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} 485 | engines: {node: '>= 8'} 486 | dependencies: 487 | normalize-path: 3.0.0 488 | picomatch: 2.3.1 489 | dev: true 490 | 491 | /aproba/1.2.0: 492 | resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} 493 | dev: true 494 | 495 | /aproba/2.0.0: 496 | resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} 497 | dev: true 498 | 499 | /are-we-there-yet/1.1.7: 500 | resolution: {integrity: sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==} 501 | dependencies: 502 | delegates: 1.0.0 503 | readable-stream: 2.3.7 504 | dev: true 505 | 506 | /are-we-there-yet/2.0.0: 507 | resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} 508 | engines: {node: '>=10'} 509 | dependencies: 510 | delegates: 1.0.0 511 | readable-stream: 3.6.0 512 | dev: true 513 | 514 | /arg/5.0.1: 515 | resolution: {integrity: sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==} 516 | dev: true 517 | 518 | /argparse/2.0.1: 519 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 520 | dev: true 521 | 522 | /array-union/2.1.0: 523 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 524 | engines: {node: '>=8'} 525 | dev: true 526 | 527 | /autoprefixer/10.4.7_postcss@8.4.14: 528 | resolution: {integrity: sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==} 529 | engines: {node: ^10 || ^12 || >=14} 530 | hasBin: true 531 | peerDependencies: 532 | postcss: ^8.1.0 533 | dependencies: 534 | browserslist: 4.20.3 535 | caniuse-lite: 1.0.30001342 536 | fraction.js: 4.2.0 537 | normalize-range: 0.1.2 538 | picocolors: 1.0.0 539 | postcss: 8.4.14 540 | postcss-value-parser: 4.2.0 541 | dev: true 542 | 543 | /balanced-match/1.0.2: 544 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 545 | dev: true 546 | 547 | /base-64/0.1.0: 548 | resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==} 549 | dev: true 550 | 551 | /binary-extensions/2.2.0: 552 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 553 | engines: {node: '>=8'} 554 | dev: true 555 | 556 | /bindings/1.5.0: 557 | resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} 558 | dependencies: 559 | file-uri-to-path: 1.0.0 560 | dev: true 561 | 562 | /brace-expansion/1.1.11: 563 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 564 | dependencies: 565 | balanced-match: 1.0.2 566 | concat-map: 0.0.1 567 | dev: true 568 | 569 | /braces/3.0.2: 570 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 571 | engines: {node: '>=8'} 572 | dependencies: 573 | fill-range: 7.0.1 574 | dev: true 575 | 576 | /browserslist/4.20.3: 577 | resolution: {integrity: sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==} 578 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 579 | hasBin: true 580 | dependencies: 581 | caniuse-lite: 1.0.30001342 582 | electron-to-chromium: 1.4.138 583 | escalade: 3.1.1 584 | node-releases: 2.0.5 585 | picocolors: 1.0.0 586 | dev: true 587 | 588 | /buffer-crc32/0.2.13: 589 | resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} 590 | dev: true 591 | 592 | /callsites/3.1.0: 593 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 594 | engines: {node: '>=6'} 595 | dev: true 596 | 597 | /camelcase-css/2.0.1: 598 | resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} 599 | engines: {node: '>= 6'} 600 | dev: true 601 | 602 | /caniuse-lite/1.0.30001342: 603 | resolution: {integrity: sha512-bn6sOCu7L7jcbBbyNhLg0qzXdJ/PMbybZTH/BA6Roet9wxYRm6Tr9D0s0uhLkOZ6MSG+QU6txUgdpr3MXIVqjA==} 604 | dev: true 605 | 606 | /chalk/4.1.2: 607 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 608 | engines: {node: '>=10'} 609 | dependencies: 610 | ansi-styles: 4.3.0 611 | supports-color: 7.2.0 612 | dev: true 613 | 614 | /chokidar/3.5.3: 615 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} 616 | engines: {node: '>= 8.10.0'} 617 | dependencies: 618 | anymatch: 3.1.2 619 | braces: 3.0.2 620 | glob-parent: 5.1.2 621 | is-binary-path: 2.1.0 622 | is-glob: 4.0.3 623 | normalize-path: 3.0.0 624 | readdirp: 3.6.0 625 | optionalDependencies: 626 | fsevents: 2.3.2 627 | dev: true 628 | 629 | /chownr/1.1.4: 630 | resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} 631 | dev: true 632 | 633 | /chownr/2.0.0: 634 | resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} 635 | engines: {node: '>=10'} 636 | dev: true 637 | 638 | /code-point-at/1.1.0: 639 | resolution: {integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=} 640 | engines: {node: '>=0.10.0'} 641 | dev: true 642 | 643 | /color-convert/2.0.1: 644 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 645 | engines: {node: '>=7.0.0'} 646 | dependencies: 647 | color-name: 1.1.4 648 | dev: true 649 | 650 | /color-name/1.1.4: 651 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 652 | dev: true 653 | 654 | /color-support/1.1.3: 655 | resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} 656 | hasBin: true 657 | dev: true 658 | 659 | /concat-map/0.0.1: 660 | resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} 661 | dev: true 662 | 663 | /console-control-strings/1.1.0: 664 | resolution: {integrity: sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=} 665 | dev: true 666 | 667 | /core-util-is/1.0.3: 668 | resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} 669 | dev: true 670 | 671 | /cross-spawn/7.0.3: 672 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 673 | engines: {node: '>= 8'} 674 | dependencies: 675 | path-key: 3.1.1 676 | shebang-command: 2.0.0 677 | which: 2.0.2 678 | dev: true 679 | 680 | /cssesc/3.0.0: 681 | resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} 682 | engines: {node: '>=4'} 683 | hasBin: true 684 | dev: true 685 | 686 | /debug/3.2.7: 687 | resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} 688 | peerDependencies: 689 | supports-color: '*' 690 | peerDependenciesMeta: 691 | supports-color: 692 | optional: true 693 | dependencies: 694 | ms: 2.1.2 695 | dev: true 696 | 697 | /debug/4.3.4: 698 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 699 | engines: {node: '>=6.0'} 700 | peerDependencies: 701 | supports-color: '*' 702 | peerDependenciesMeta: 703 | supports-color: 704 | optional: true 705 | dependencies: 706 | ms: 2.1.2 707 | dev: true 708 | 709 | /dedent-js/1.0.1: 710 | resolution: {integrity: sha1-vuX7fJ5yfYXf+iRZDRDsGrElUwU=} 711 | dev: true 712 | 713 | /deep-extend/0.6.0: 714 | resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} 715 | engines: {node: '>=4.0.0'} 716 | dev: true 717 | 718 | /deep-is/0.1.4: 719 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 720 | dev: true 721 | 722 | /deepmerge/4.2.2: 723 | resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} 724 | engines: {node: '>=0.10.0'} 725 | dev: true 726 | 727 | /defined/1.0.0: 728 | resolution: {integrity: sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=} 729 | dev: true 730 | 731 | /delegates/1.0.0: 732 | resolution: {integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=} 733 | dev: true 734 | 735 | /detect-indent/6.1.0: 736 | resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} 737 | engines: {node: '>=8'} 738 | dev: true 739 | 740 | /detect-libc/1.0.3: 741 | resolution: {integrity: sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=} 742 | engines: {node: '>=0.10'} 743 | hasBin: true 744 | dev: true 745 | 746 | /detect-libc/2.0.1: 747 | resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==} 748 | engines: {node: '>=8'} 749 | dev: true 750 | 751 | /detective/5.2.0: 752 | resolution: {integrity: sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==} 753 | engines: {node: '>=0.8.0'} 754 | hasBin: true 755 | dependencies: 756 | acorn-node: 1.8.2 757 | defined: 1.0.0 758 | minimist: 1.2.6 759 | dev: true 760 | 761 | /didyoumean/1.2.2: 762 | resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} 763 | dev: true 764 | 765 | /dir-glob/3.0.1: 766 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 767 | engines: {node: '>=8'} 768 | dependencies: 769 | path-type: 4.0.0 770 | dev: true 771 | 772 | /dlv/1.1.3: 773 | resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} 774 | dev: true 775 | 776 | /doctrine/3.0.0: 777 | resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} 778 | engines: {node: '>=6.0.0'} 779 | dependencies: 780 | esutils: 2.0.3 781 | dev: true 782 | 783 | /electron-to-chromium/1.4.138: 784 | resolution: {integrity: sha512-IOyp2Seq3w4QLln+yZWcMF3VXhhduz4bwg9gfI+CnP5TkzwNXQ8FCZuwwPsnes73AfWdf5J2n2OXdUwDUspDPQ==} 785 | dev: true 786 | 787 | /emoji-regex/8.0.0: 788 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 789 | dev: true 790 | 791 | /es6-promise/3.3.1: 792 | resolution: {integrity: sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=} 793 | dev: true 794 | 795 | /esbuild-android-64/0.14.39: 796 | resolution: {integrity: sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ==} 797 | engines: {node: '>=12'} 798 | cpu: [x64] 799 | os: [android] 800 | requiresBuild: true 801 | dev: true 802 | optional: true 803 | 804 | /esbuild-android-arm64/0.14.39: 805 | resolution: {integrity: sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA==} 806 | engines: {node: '>=12'} 807 | cpu: [arm64] 808 | os: [android] 809 | requiresBuild: true 810 | dev: true 811 | optional: true 812 | 813 | /esbuild-darwin-64/0.14.39: 814 | resolution: {integrity: sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g==} 815 | engines: {node: '>=12'} 816 | cpu: [x64] 817 | os: [darwin] 818 | requiresBuild: true 819 | dev: true 820 | optional: true 821 | 822 | /esbuild-darwin-arm64/0.14.39: 823 | resolution: {integrity: sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw==} 824 | engines: {node: '>=12'} 825 | cpu: [arm64] 826 | os: [darwin] 827 | requiresBuild: true 828 | dev: true 829 | optional: true 830 | 831 | /esbuild-freebsd-64/0.14.39: 832 | resolution: {integrity: sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ==} 833 | engines: {node: '>=12'} 834 | cpu: [x64] 835 | os: [freebsd] 836 | requiresBuild: true 837 | dev: true 838 | optional: true 839 | 840 | /esbuild-freebsd-arm64/0.14.39: 841 | resolution: {integrity: sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg==} 842 | engines: {node: '>=12'} 843 | cpu: [arm64] 844 | os: [freebsd] 845 | requiresBuild: true 846 | dev: true 847 | optional: true 848 | 849 | /esbuild-linux-32/0.14.39: 850 | resolution: {integrity: sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg==} 851 | engines: {node: '>=12'} 852 | cpu: [ia32] 853 | os: [linux] 854 | requiresBuild: true 855 | dev: true 856 | optional: true 857 | 858 | /esbuild-linux-64/0.14.39: 859 | resolution: {integrity: sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ==} 860 | engines: {node: '>=12'} 861 | cpu: [x64] 862 | os: [linux] 863 | requiresBuild: true 864 | dev: true 865 | optional: true 866 | 867 | /esbuild-linux-arm/0.14.39: 868 | resolution: {integrity: sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ==} 869 | engines: {node: '>=12'} 870 | cpu: [arm] 871 | os: [linux] 872 | requiresBuild: true 873 | dev: true 874 | optional: true 875 | 876 | /esbuild-linux-arm64/0.14.39: 877 | resolution: {integrity: sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ==} 878 | engines: {node: '>=12'} 879 | cpu: [arm64] 880 | os: [linux] 881 | requiresBuild: true 882 | dev: true 883 | optional: true 884 | 885 | /esbuild-linux-mips64le/0.14.39: 886 | resolution: {integrity: sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw==} 887 | engines: {node: '>=12'} 888 | cpu: [mips64el] 889 | os: [linux] 890 | requiresBuild: true 891 | dev: true 892 | optional: true 893 | 894 | /esbuild-linux-ppc64le/0.14.39: 895 | resolution: {integrity: sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ==} 896 | engines: {node: '>=12'} 897 | cpu: [ppc64] 898 | os: [linux] 899 | requiresBuild: true 900 | dev: true 901 | optional: true 902 | 903 | /esbuild-linux-riscv64/0.14.39: 904 | resolution: {integrity: sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA==} 905 | engines: {node: '>=12'} 906 | cpu: [riscv64] 907 | os: [linux] 908 | requiresBuild: true 909 | dev: true 910 | optional: true 911 | 912 | /esbuild-linux-s390x/0.14.39: 913 | resolution: {integrity: sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA==} 914 | engines: {node: '>=12'} 915 | cpu: [s390x] 916 | os: [linux] 917 | requiresBuild: true 918 | dev: true 919 | optional: true 920 | 921 | /esbuild-netbsd-64/0.14.39: 922 | resolution: {integrity: sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA==} 923 | engines: {node: '>=12'} 924 | cpu: [x64] 925 | os: [netbsd] 926 | requiresBuild: true 927 | dev: true 928 | optional: true 929 | 930 | /esbuild-openbsd-64/0.14.39: 931 | resolution: {integrity: sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA==} 932 | engines: {node: '>=12'} 933 | cpu: [x64] 934 | os: [openbsd] 935 | requiresBuild: true 936 | dev: true 937 | optional: true 938 | 939 | /esbuild-sunos-64/0.14.39: 940 | resolution: {integrity: sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg==} 941 | engines: {node: '>=12'} 942 | cpu: [x64] 943 | os: [sunos] 944 | requiresBuild: true 945 | dev: true 946 | optional: true 947 | 948 | /esbuild-windows-32/0.14.39: 949 | resolution: {integrity: sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q==} 950 | engines: {node: '>=12'} 951 | cpu: [ia32] 952 | os: [win32] 953 | requiresBuild: true 954 | dev: true 955 | optional: true 956 | 957 | /esbuild-windows-64/0.14.39: 958 | resolution: {integrity: sha512-E2wm+5FwCcLpKsBHRw28bSYQw0Ikxb7zIMxw3OPAkiaQhLVr3dnVO8DofmbWhhf6b97bWzg37iSZ45ZDpLw7Ow==} 959 | engines: {node: '>=12'} 960 | cpu: [x64] 961 | os: [win32] 962 | requiresBuild: true 963 | dev: true 964 | optional: true 965 | 966 | /esbuild-windows-arm64/0.14.39: 967 | resolution: {integrity: sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA==} 968 | engines: {node: '>=12'} 969 | cpu: [arm64] 970 | os: [win32] 971 | requiresBuild: true 972 | dev: true 973 | optional: true 974 | 975 | /esbuild/0.14.39: 976 | resolution: {integrity: sha512-2kKujuzvRWYtwvNjYDY444LQIA3TyJhJIX3Yo4+qkFlDDtGlSicWgeHVJqMUP/2sSfH10PGwfsj+O2ro1m10xQ==} 977 | engines: {node: '>=12'} 978 | hasBin: true 979 | requiresBuild: true 980 | optionalDependencies: 981 | esbuild-android-64: 0.14.39 982 | esbuild-android-arm64: 0.14.39 983 | esbuild-darwin-64: 0.14.39 984 | esbuild-darwin-arm64: 0.14.39 985 | esbuild-freebsd-64: 0.14.39 986 | esbuild-freebsd-arm64: 0.14.39 987 | esbuild-linux-32: 0.14.39 988 | esbuild-linux-64: 0.14.39 989 | esbuild-linux-arm: 0.14.39 990 | esbuild-linux-arm64: 0.14.39 991 | esbuild-linux-mips64le: 0.14.39 992 | esbuild-linux-ppc64le: 0.14.39 993 | esbuild-linux-riscv64: 0.14.39 994 | esbuild-linux-s390x: 0.14.39 995 | esbuild-netbsd-64: 0.14.39 996 | esbuild-openbsd-64: 0.14.39 997 | esbuild-sunos-64: 0.14.39 998 | esbuild-windows-32: 0.14.39 999 | esbuild-windows-64: 0.14.39 1000 | esbuild-windows-arm64: 0.14.39 1001 | dev: true 1002 | 1003 | /escalade/3.1.1: 1004 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 1005 | engines: {node: '>=6'} 1006 | dev: true 1007 | 1008 | /escape-string-regexp/4.0.0: 1009 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 1010 | engines: {node: '>=10'} 1011 | dev: true 1012 | 1013 | /eslint-config-prettier/8.5.0_eslint@8.16.0: 1014 | resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} 1015 | hasBin: true 1016 | peerDependencies: 1017 | eslint: '>=7.0.0' 1018 | dependencies: 1019 | eslint: 8.16.0 1020 | dev: true 1021 | 1022 | /eslint-plugin-svelte3/4.0.0_vypdqzeyqutkgs6qzc7qod4c64: 1023 | resolution: {integrity: sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==} 1024 | peerDependencies: 1025 | eslint: '>=8.0.0' 1026 | svelte: ^3.2.0 1027 | dependencies: 1028 | eslint: 8.16.0 1029 | svelte: 3.48.0 1030 | dev: true 1031 | 1032 | /eslint-scope/5.1.1: 1033 | resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} 1034 | engines: {node: '>=8.0.0'} 1035 | dependencies: 1036 | esrecurse: 4.3.0 1037 | estraverse: 4.3.0 1038 | dev: true 1039 | 1040 | /eslint-scope/7.1.1: 1041 | resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} 1042 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1043 | dependencies: 1044 | esrecurse: 4.3.0 1045 | estraverse: 5.3.0 1046 | dev: true 1047 | 1048 | /eslint-utils/3.0.0_eslint@8.16.0: 1049 | resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} 1050 | engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} 1051 | peerDependencies: 1052 | eslint: '>=5' 1053 | dependencies: 1054 | eslint: 8.16.0 1055 | eslint-visitor-keys: 2.1.0 1056 | dev: true 1057 | 1058 | /eslint-visitor-keys/2.1.0: 1059 | resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} 1060 | engines: {node: '>=10'} 1061 | dev: true 1062 | 1063 | /eslint-visitor-keys/3.3.0: 1064 | resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} 1065 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1066 | dev: true 1067 | 1068 | /eslint/8.16.0: 1069 | resolution: {integrity: sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==} 1070 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1071 | hasBin: true 1072 | dependencies: 1073 | '@eslint/eslintrc': 1.3.0 1074 | '@humanwhocodes/config-array': 0.9.5 1075 | ajv: 6.12.6 1076 | chalk: 4.1.2 1077 | cross-spawn: 7.0.3 1078 | debug: 4.3.4 1079 | doctrine: 3.0.0 1080 | escape-string-regexp: 4.0.0 1081 | eslint-scope: 7.1.1 1082 | eslint-utils: 3.0.0_eslint@8.16.0 1083 | eslint-visitor-keys: 3.3.0 1084 | espree: 9.3.2 1085 | esquery: 1.4.0 1086 | esutils: 2.0.3 1087 | fast-deep-equal: 3.1.3 1088 | file-entry-cache: 6.0.1 1089 | functional-red-black-tree: 1.0.1 1090 | glob-parent: 6.0.2 1091 | globals: 13.15.0 1092 | ignore: 5.2.0 1093 | import-fresh: 3.3.0 1094 | imurmurhash: 0.1.4 1095 | is-glob: 4.0.3 1096 | js-yaml: 4.1.0 1097 | json-stable-stringify-without-jsonify: 1.0.1 1098 | levn: 0.4.1 1099 | lodash.merge: 4.6.2 1100 | minimatch: 3.1.2 1101 | natural-compare: 1.4.0 1102 | optionator: 0.9.1 1103 | regexpp: 3.2.0 1104 | strip-ansi: 6.0.1 1105 | strip-json-comments: 3.1.1 1106 | text-table: 0.2.0 1107 | v8-compile-cache: 2.3.0 1108 | transitivePeerDependencies: 1109 | - supports-color 1110 | dev: true 1111 | 1112 | /espree/9.3.2: 1113 | resolution: {integrity: sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==} 1114 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1115 | dependencies: 1116 | acorn: 8.7.1 1117 | acorn-jsx: 5.3.2_acorn@8.7.1 1118 | eslint-visitor-keys: 3.3.0 1119 | dev: true 1120 | 1121 | /esquery/1.4.0: 1122 | resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} 1123 | engines: {node: '>=0.10'} 1124 | dependencies: 1125 | estraverse: 5.3.0 1126 | dev: true 1127 | 1128 | /esrecurse/4.3.0: 1129 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 1130 | engines: {node: '>=4.0'} 1131 | dependencies: 1132 | estraverse: 5.3.0 1133 | dev: true 1134 | 1135 | /estraverse/4.3.0: 1136 | resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} 1137 | engines: {node: '>=4.0'} 1138 | dev: true 1139 | 1140 | /estraverse/5.3.0: 1141 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 1142 | engines: {node: '>=4.0'} 1143 | dev: true 1144 | 1145 | /estree-walker/0.6.1: 1146 | resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} 1147 | dev: true 1148 | 1149 | /estree-walker/2.0.2: 1150 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 1151 | dev: true 1152 | 1153 | /esutils/2.0.3: 1154 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 1155 | engines: {node: '>=0.10.0'} 1156 | dev: true 1157 | 1158 | /fast-deep-equal/3.1.3: 1159 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 1160 | dev: true 1161 | 1162 | /fast-glob/3.2.11: 1163 | resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} 1164 | engines: {node: '>=8.6.0'} 1165 | dependencies: 1166 | '@nodelib/fs.stat': 2.0.5 1167 | '@nodelib/fs.walk': 1.2.8 1168 | glob-parent: 5.1.2 1169 | merge2: 1.4.1 1170 | micromatch: 4.0.5 1171 | dev: true 1172 | 1173 | /fast-json-stable-stringify/2.1.0: 1174 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 1175 | dev: true 1176 | 1177 | /fast-levenshtein/2.0.6: 1178 | resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} 1179 | dev: true 1180 | 1181 | /fastq/1.13.0: 1182 | resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} 1183 | dependencies: 1184 | reusify: 1.0.4 1185 | dev: true 1186 | 1187 | /file-entry-cache/6.0.1: 1188 | resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} 1189 | engines: {node: ^10.12.0 || >=12.0.0} 1190 | dependencies: 1191 | flat-cache: 3.0.4 1192 | dev: true 1193 | 1194 | /file-uri-to-path/1.0.0: 1195 | resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} 1196 | dev: true 1197 | 1198 | /fill-range/7.0.1: 1199 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 1200 | engines: {node: '>=8'} 1201 | dependencies: 1202 | to-regex-range: 5.0.1 1203 | dev: true 1204 | 1205 | /flat-cache/3.0.4: 1206 | resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} 1207 | engines: {node: ^10.12.0 || >=12.0.0} 1208 | dependencies: 1209 | flatted: 3.2.5 1210 | rimraf: 3.0.2 1211 | dev: true 1212 | 1213 | /flatted/3.2.5: 1214 | resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} 1215 | dev: true 1216 | 1217 | /fraction.js/4.2.0: 1218 | resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} 1219 | dev: true 1220 | 1221 | /fs-minipass/1.2.7: 1222 | resolution: {integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==} 1223 | dependencies: 1224 | minipass: 2.9.0 1225 | dev: true 1226 | 1227 | /fs-minipass/2.1.0: 1228 | resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} 1229 | engines: {node: '>= 8'} 1230 | dependencies: 1231 | minipass: 3.1.6 1232 | dev: true 1233 | 1234 | /fs.realpath/1.0.0: 1235 | resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} 1236 | dev: true 1237 | 1238 | /fsevents/2.3.2: 1239 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 1240 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1241 | os: [darwin] 1242 | requiresBuild: true 1243 | dev: true 1244 | optional: true 1245 | 1246 | /function-bind/1.1.1: 1247 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 1248 | dev: true 1249 | 1250 | /functional-red-black-tree/1.0.1: 1251 | resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} 1252 | dev: true 1253 | 1254 | /gauge/2.7.4: 1255 | resolution: {integrity: sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=} 1256 | dependencies: 1257 | aproba: 1.2.0 1258 | console-control-strings: 1.1.0 1259 | has-unicode: 2.0.1 1260 | object-assign: 4.1.1 1261 | signal-exit: 3.0.7 1262 | string-width: 1.0.2 1263 | strip-ansi: 3.0.1 1264 | wide-align: 1.1.5 1265 | dev: true 1266 | 1267 | /gauge/3.0.2: 1268 | resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} 1269 | engines: {node: '>=10'} 1270 | dependencies: 1271 | aproba: 2.0.0 1272 | color-support: 1.1.3 1273 | console-control-strings: 1.1.0 1274 | has-unicode: 2.0.1 1275 | object-assign: 4.1.1 1276 | signal-exit: 3.0.7 1277 | string-width: 4.2.3 1278 | strip-ansi: 6.0.1 1279 | wide-align: 1.1.5 1280 | dev: true 1281 | 1282 | /glob-parent/5.1.2: 1283 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1284 | engines: {node: '>= 6'} 1285 | dependencies: 1286 | is-glob: 4.0.3 1287 | dev: true 1288 | 1289 | /glob-parent/6.0.2: 1290 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 1291 | engines: {node: '>=10.13.0'} 1292 | dependencies: 1293 | is-glob: 4.0.3 1294 | dev: true 1295 | 1296 | /glob/7.2.3: 1297 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 1298 | dependencies: 1299 | fs.realpath: 1.0.0 1300 | inflight: 1.0.6 1301 | inherits: 2.0.4 1302 | minimatch: 3.1.2 1303 | once: 1.4.0 1304 | path-is-absolute: 1.0.1 1305 | dev: true 1306 | 1307 | /globals/13.15.0: 1308 | resolution: {integrity: sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==} 1309 | engines: {node: '>=8'} 1310 | dependencies: 1311 | type-fest: 0.20.2 1312 | dev: true 1313 | 1314 | /globalyzer/0.1.0: 1315 | resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} 1316 | dev: true 1317 | 1318 | /globby/11.1.0: 1319 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 1320 | engines: {node: '>=10'} 1321 | dependencies: 1322 | array-union: 2.1.0 1323 | dir-glob: 3.0.1 1324 | fast-glob: 3.2.11 1325 | ignore: 5.2.0 1326 | merge2: 1.4.1 1327 | slash: 3.0.0 1328 | dev: true 1329 | 1330 | /globrex/0.1.2: 1331 | resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} 1332 | dev: true 1333 | 1334 | /graceful-fs/4.2.10: 1335 | resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} 1336 | dev: true 1337 | 1338 | /has-flag/4.0.0: 1339 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1340 | engines: {node: '>=8'} 1341 | dev: true 1342 | 1343 | /has-unicode/2.0.1: 1344 | resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=} 1345 | dev: true 1346 | 1347 | /has/1.0.3: 1348 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 1349 | engines: {node: '>= 0.4.0'} 1350 | dependencies: 1351 | function-bind: 1.1.1 1352 | dev: true 1353 | 1354 | /https-proxy-agent/5.0.1: 1355 | resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} 1356 | engines: {node: '>= 6'} 1357 | dependencies: 1358 | agent-base: 6.0.2 1359 | debug: 4.3.4 1360 | transitivePeerDependencies: 1361 | - supports-color 1362 | dev: true 1363 | 1364 | /iconv-lite/0.4.24: 1365 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 1366 | engines: {node: '>=0.10.0'} 1367 | dependencies: 1368 | safer-buffer: 2.1.2 1369 | dev: true 1370 | 1371 | /ignore-walk/3.0.4: 1372 | resolution: {integrity: sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==} 1373 | dependencies: 1374 | minimatch: 3.1.2 1375 | dev: true 1376 | 1377 | /ignore/5.2.0: 1378 | resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} 1379 | engines: {node: '>= 4'} 1380 | dev: true 1381 | 1382 | /import-fresh/3.3.0: 1383 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} 1384 | engines: {node: '>=6'} 1385 | dependencies: 1386 | parent-module: 1.0.1 1387 | resolve-from: 4.0.0 1388 | dev: true 1389 | 1390 | /imurmurhash/0.1.4: 1391 | resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=} 1392 | engines: {node: '>=0.8.19'} 1393 | dev: true 1394 | 1395 | /inflight/1.0.6: 1396 | resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} 1397 | dependencies: 1398 | once: 1.4.0 1399 | wrappy: 1.0.2 1400 | dev: true 1401 | 1402 | /inherits/2.0.4: 1403 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 1404 | dev: true 1405 | 1406 | /ini/1.3.8: 1407 | resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} 1408 | dev: true 1409 | 1410 | /is-binary-path/2.1.0: 1411 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 1412 | engines: {node: '>=8'} 1413 | dependencies: 1414 | binary-extensions: 2.2.0 1415 | dev: true 1416 | 1417 | /is-core-module/2.9.0: 1418 | resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} 1419 | dependencies: 1420 | has: 1.0.3 1421 | dev: true 1422 | 1423 | /is-extglob/2.1.1: 1424 | resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} 1425 | engines: {node: '>=0.10.0'} 1426 | dev: true 1427 | 1428 | /is-fullwidth-code-point/1.0.0: 1429 | resolution: {integrity: sha1-754xOG8DGn8NZDr4L95QxFfvAMs=} 1430 | engines: {node: '>=0.10.0'} 1431 | dependencies: 1432 | number-is-nan: 1.0.1 1433 | dev: true 1434 | 1435 | /is-fullwidth-code-point/3.0.0: 1436 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1437 | engines: {node: '>=8'} 1438 | dev: true 1439 | 1440 | /is-glob/4.0.3: 1441 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1442 | engines: {node: '>=0.10.0'} 1443 | dependencies: 1444 | is-extglob: 2.1.1 1445 | dev: true 1446 | 1447 | /is-number/7.0.0: 1448 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1449 | engines: {node: '>=0.12.0'} 1450 | dev: true 1451 | 1452 | /isarray/1.0.0: 1453 | resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=} 1454 | dev: true 1455 | 1456 | /isexe/2.0.0: 1457 | resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} 1458 | dev: true 1459 | 1460 | /js-yaml/4.1.0: 1461 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1462 | hasBin: true 1463 | dependencies: 1464 | argparse: 2.0.1 1465 | dev: true 1466 | 1467 | /json-schema-traverse/0.4.1: 1468 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 1469 | dev: true 1470 | 1471 | /json-stable-stringify-without-jsonify/1.0.1: 1472 | resolution: {integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=} 1473 | dev: true 1474 | 1475 | /kleur/4.1.4: 1476 | resolution: {integrity: sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==} 1477 | engines: {node: '>=6'} 1478 | dev: true 1479 | 1480 | /levn/0.4.1: 1481 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 1482 | engines: {node: '>= 0.8.0'} 1483 | dependencies: 1484 | prelude-ls: 1.2.1 1485 | type-check: 0.4.0 1486 | dev: true 1487 | 1488 | /lilconfig/2.0.5: 1489 | resolution: {integrity: sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==} 1490 | engines: {node: '>=10'} 1491 | dev: true 1492 | 1493 | /lodash.merge/4.6.2: 1494 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 1495 | dev: true 1496 | 1497 | /lower-case/2.0.2: 1498 | resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} 1499 | dependencies: 1500 | tslib: 2.4.0 1501 | dev: true 1502 | 1503 | /lru-cache/6.0.0: 1504 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 1505 | engines: {node: '>=10'} 1506 | dependencies: 1507 | yallist: 4.0.0 1508 | dev: true 1509 | 1510 | /magic-string/0.25.9: 1511 | resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} 1512 | dependencies: 1513 | sourcemap-codec: 1.4.8 1514 | dev: true 1515 | 1516 | /magic-string/0.26.2: 1517 | resolution: {integrity: sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==} 1518 | engines: {node: '>=12'} 1519 | dependencies: 1520 | sourcemap-codec: 1.4.8 1521 | dev: true 1522 | 1523 | /make-dir/3.1.0: 1524 | resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} 1525 | engines: {node: '>=8'} 1526 | dependencies: 1527 | semver: 6.3.0 1528 | dev: true 1529 | 1530 | /merge2/1.4.1: 1531 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1532 | engines: {node: '>= 8'} 1533 | dev: true 1534 | 1535 | /micromatch/4.0.5: 1536 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 1537 | engines: {node: '>=8.6'} 1538 | dependencies: 1539 | braces: 3.0.2 1540 | picomatch: 2.3.1 1541 | dev: true 1542 | 1543 | /min-indent/1.0.1: 1544 | resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} 1545 | engines: {node: '>=4'} 1546 | dev: true 1547 | 1548 | /minimatch/3.1.2: 1549 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1550 | dependencies: 1551 | brace-expansion: 1.1.11 1552 | dev: true 1553 | 1554 | /minimist/1.2.6: 1555 | resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} 1556 | dev: true 1557 | 1558 | /minipass/2.9.0: 1559 | resolution: {integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==} 1560 | dependencies: 1561 | safe-buffer: 5.2.1 1562 | yallist: 3.1.1 1563 | dev: true 1564 | 1565 | /minipass/3.1.6: 1566 | resolution: {integrity: sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==} 1567 | engines: {node: '>=8'} 1568 | dependencies: 1569 | yallist: 4.0.0 1570 | dev: true 1571 | 1572 | /minizlib/1.3.3: 1573 | resolution: {integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==} 1574 | dependencies: 1575 | minipass: 2.9.0 1576 | dev: true 1577 | 1578 | /minizlib/2.1.2: 1579 | resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} 1580 | engines: {node: '>= 8'} 1581 | dependencies: 1582 | minipass: 3.1.6 1583 | yallist: 4.0.0 1584 | dev: true 1585 | 1586 | /mkdirp/0.5.6: 1587 | resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} 1588 | hasBin: true 1589 | dependencies: 1590 | minimist: 1.2.6 1591 | dev: true 1592 | 1593 | /mkdirp/1.0.4: 1594 | resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} 1595 | engines: {node: '>=10'} 1596 | hasBin: true 1597 | dev: true 1598 | 1599 | /mri/1.2.0: 1600 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 1601 | engines: {node: '>=4'} 1602 | dev: true 1603 | 1604 | /mrmime/1.0.0: 1605 | resolution: {integrity: sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==} 1606 | engines: {node: '>=10'} 1607 | dev: true 1608 | 1609 | /ms/2.1.2: 1610 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1611 | dev: true 1612 | 1613 | /nanoid/3.3.4: 1614 | resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} 1615 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1616 | hasBin: true 1617 | dev: true 1618 | 1619 | /natural-compare/1.4.0: 1620 | resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} 1621 | dev: true 1622 | 1623 | /needle/2.9.1: 1624 | resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} 1625 | engines: {node: '>= 4.4.x'} 1626 | hasBin: true 1627 | dependencies: 1628 | debug: 3.2.7 1629 | iconv-lite: 0.4.24 1630 | sax: 1.2.4 1631 | transitivePeerDependencies: 1632 | - supports-color 1633 | dev: true 1634 | 1635 | /no-case/3.0.4: 1636 | resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} 1637 | dependencies: 1638 | lower-case: 2.0.2 1639 | tslib: 2.4.0 1640 | dev: true 1641 | 1642 | /node-fetch/2.6.7: 1643 | resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} 1644 | engines: {node: 4.x || >=6.0.0} 1645 | peerDependencies: 1646 | encoding: ^0.1.0 1647 | peerDependenciesMeta: 1648 | encoding: 1649 | optional: true 1650 | dependencies: 1651 | whatwg-url: 5.0.0 1652 | dev: true 1653 | 1654 | /node-gyp-build/4.4.0: 1655 | resolution: {integrity: sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==} 1656 | hasBin: true 1657 | dev: true 1658 | 1659 | /node-pre-gyp/0.13.0: 1660 | resolution: {integrity: sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==} 1661 | deprecated: 'Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future' 1662 | hasBin: true 1663 | dependencies: 1664 | detect-libc: 1.0.3 1665 | mkdirp: 0.5.6 1666 | needle: 2.9.1 1667 | nopt: 4.0.3 1668 | npm-packlist: 1.4.8 1669 | npmlog: 4.1.2 1670 | rc: 1.2.8 1671 | rimraf: 2.7.1 1672 | semver: 5.7.1 1673 | tar: 4.4.19 1674 | transitivePeerDependencies: 1675 | - supports-color 1676 | dev: true 1677 | 1678 | /node-releases/2.0.5: 1679 | resolution: {integrity: sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==} 1680 | dev: true 1681 | 1682 | /nopt/4.0.3: 1683 | resolution: {integrity: sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==} 1684 | hasBin: true 1685 | dependencies: 1686 | abbrev: 1.1.1 1687 | osenv: 0.1.5 1688 | dev: true 1689 | 1690 | /nopt/5.0.0: 1691 | resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} 1692 | engines: {node: '>=6'} 1693 | hasBin: true 1694 | dependencies: 1695 | abbrev: 1.1.1 1696 | dev: true 1697 | 1698 | /normalize-path/3.0.0: 1699 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 1700 | engines: {node: '>=0.10.0'} 1701 | dev: true 1702 | 1703 | /normalize-range/0.1.2: 1704 | resolution: {integrity: sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=} 1705 | engines: {node: '>=0.10.0'} 1706 | dev: true 1707 | 1708 | /npm-bundled/1.1.2: 1709 | resolution: {integrity: sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==} 1710 | dependencies: 1711 | npm-normalize-package-bin: 1.0.1 1712 | dev: true 1713 | 1714 | /npm-normalize-package-bin/1.0.1: 1715 | resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} 1716 | dev: true 1717 | 1718 | /npm-packlist/1.4.8: 1719 | resolution: {integrity: sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==} 1720 | dependencies: 1721 | ignore-walk: 3.0.4 1722 | npm-bundled: 1.1.2 1723 | npm-normalize-package-bin: 1.0.1 1724 | dev: true 1725 | 1726 | /npmlog/4.1.2: 1727 | resolution: {integrity: sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==} 1728 | dependencies: 1729 | are-we-there-yet: 1.1.7 1730 | console-control-strings: 1.1.0 1731 | gauge: 2.7.4 1732 | set-blocking: 2.0.0 1733 | dev: true 1734 | 1735 | /npmlog/5.0.1: 1736 | resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} 1737 | dependencies: 1738 | are-we-there-yet: 2.0.0 1739 | console-control-strings: 1.1.0 1740 | gauge: 3.0.2 1741 | set-blocking: 2.0.0 1742 | dev: true 1743 | 1744 | /number-is-nan/1.0.1: 1745 | resolution: {integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=} 1746 | engines: {node: '>=0.10.0'} 1747 | dev: true 1748 | 1749 | /object-assign/4.1.1: 1750 | resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} 1751 | engines: {node: '>=0.10.0'} 1752 | dev: true 1753 | 1754 | /object-hash/3.0.0: 1755 | resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} 1756 | engines: {node: '>= 6'} 1757 | dev: true 1758 | 1759 | /once/1.4.0: 1760 | resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} 1761 | dependencies: 1762 | wrappy: 1.0.2 1763 | dev: true 1764 | 1765 | /optionator/0.9.1: 1766 | resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} 1767 | engines: {node: '>= 0.8.0'} 1768 | dependencies: 1769 | deep-is: 0.1.4 1770 | fast-levenshtein: 2.0.6 1771 | levn: 0.4.1 1772 | prelude-ls: 1.2.1 1773 | type-check: 0.4.0 1774 | word-wrap: 1.2.3 1775 | dev: true 1776 | 1777 | /os-homedir/1.0.2: 1778 | resolution: {integrity: sha1-/7xJiDNuDoM94MFox+8VISGqf7M=} 1779 | engines: {node: '>=0.10.0'} 1780 | dev: true 1781 | 1782 | /os-tmpdir/1.0.2: 1783 | resolution: {integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=} 1784 | engines: {node: '>=0.10.0'} 1785 | dev: true 1786 | 1787 | /osenv/0.1.5: 1788 | resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==} 1789 | dependencies: 1790 | os-homedir: 1.0.2 1791 | os-tmpdir: 1.0.2 1792 | dev: true 1793 | 1794 | /parent-module/1.0.1: 1795 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1796 | engines: {node: '>=6'} 1797 | dependencies: 1798 | callsites: 3.1.0 1799 | dev: true 1800 | 1801 | /pascal-case/3.1.2: 1802 | resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} 1803 | dependencies: 1804 | no-case: 3.0.4 1805 | tslib: 2.4.0 1806 | dev: true 1807 | 1808 | /path-is-absolute/1.0.1: 1809 | resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} 1810 | engines: {node: '>=0.10.0'} 1811 | dev: true 1812 | 1813 | /path-key/3.1.1: 1814 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1815 | engines: {node: '>=8'} 1816 | dev: true 1817 | 1818 | /path-parse/1.0.7: 1819 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1820 | dev: true 1821 | 1822 | /path-type/4.0.0: 1823 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1824 | engines: {node: '>=8'} 1825 | dev: true 1826 | 1827 | /picocolors/1.0.0: 1828 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 1829 | dev: true 1830 | 1831 | /picomatch/2.3.1: 1832 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1833 | engines: {node: '>=8.6'} 1834 | dev: true 1835 | 1836 | /postcss-js/4.0.0_postcss@8.4.14: 1837 | resolution: {integrity: sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==} 1838 | engines: {node: ^12 || ^14 || >= 16} 1839 | peerDependencies: 1840 | postcss: ^8.3.3 1841 | dependencies: 1842 | camelcase-css: 2.0.1 1843 | postcss: 8.4.14 1844 | dev: true 1845 | 1846 | /postcss-load-config/3.1.4_postcss@8.4.14: 1847 | resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} 1848 | engines: {node: '>= 10'} 1849 | peerDependencies: 1850 | postcss: '>=8.0.9' 1851 | ts-node: '>=9.0.0' 1852 | peerDependenciesMeta: 1853 | postcss: 1854 | optional: true 1855 | ts-node: 1856 | optional: true 1857 | dependencies: 1858 | lilconfig: 2.0.5 1859 | postcss: 8.4.14 1860 | yaml: 1.10.2 1861 | dev: true 1862 | 1863 | /postcss-nested/5.0.6_postcss@8.4.14: 1864 | resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==} 1865 | engines: {node: '>=12.0'} 1866 | peerDependencies: 1867 | postcss: ^8.2.14 1868 | dependencies: 1869 | postcss: 8.4.14 1870 | postcss-selector-parser: 6.0.10 1871 | dev: true 1872 | 1873 | /postcss-selector-parser/6.0.10: 1874 | resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} 1875 | engines: {node: '>=4'} 1876 | dependencies: 1877 | cssesc: 3.0.0 1878 | util-deprecate: 1.0.2 1879 | dev: true 1880 | 1881 | /postcss-value-parser/4.2.0: 1882 | resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} 1883 | dev: true 1884 | 1885 | /postcss/8.4.14: 1886 | resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} 1887 | engines: {node: ^10 || ^12 || >=14} 1888 | dependencies: 1889 | nanoid: 3.3.4 1890 | picocolors: 1.0.0 1891 | source-map-js: 1.0.2 1892 | dev: true 1893 | 1894 | /prelude-ls/1.2.1: 1895 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1896 | engines: {node: '>= 0.8.0'} 1897 | dev: true 1898 | 1899 | /prettier-plugin-svelte/2.7.0_kkjbqzpydplecjtkxrgomroeru: 1900 | resolution: {integrity: sha512-fQhhZICprZot2IqEyoiUYLTRdumULGRvw0o4dzl5jt0jfzVWdGqeYW27QTWAeXhoupEZJULmNoH3ueJwUWFLIA==} 1901 | peerDependencies: 1902 | prettier: ^1.16.4 || ^2.0.0 1903 | svelte: ^3.2.0 1904 | dependencies: 1905 | prettier: 2.6.2 1906 | svelte: 3.48.0 1907 | dev: true 1908 | 1909 | /prettier/2.6.2: 1910 | resolution: {integrity: sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==} 1911 | engines: {node: '>=10.13.0'} 1912 | hasBin: true 1913 | dev: true 1914 | 1915 | /process-nextick-args/2.0.1: 1916 | resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} 1917 | dev: true 1918 | 1919 | /punycode/2.1.1: 1920 | resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} 1921 | engines: {node: '>=6'} 1922 | dev: true 1923 | 1924 | /queue-microtask/1.2.3: 1925 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1926 | dev: true 1927 | 1928 | /quick-lru/5.1.1: 1929 | resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} 1930 | engines: {node: '>=10'} 1931 | dev: true 1932 | 1933 | /rc/1.2.8: 1934 | resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} 1935 | hasBin: true 1936 | dependencies: 1937 | deep-extend: 0.6.0 1938 | ini: 1.3.8 1939 | minimist: 1.2.6 1940 | strip-json-comments: 2.0.1 1941 | dev: true 1942 | 1943 | /readable-stream/2.3.7: 1944 | resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} 1945 | dependencies: 1946 | core-util-is: 1.0.3 1947 | inherits: 2.0.4 1948 | isarray: 1.0.0 1949 | process-nextick-args: 2.0.1 1950 | safe-buffer: 5.1.2 1951 | string_decoder: 1.1.1 1952 | util-deprecate: 1.0.2 1953 | dev: true 1954 | 1955 | /readable-stream/3.6.0: 1956 | resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} 1957 | engines: {node: '>= 6'} 1958 | dependencies: 1959 | inherits: 2.0.4 1960 | string_decoder: 1.3.0 1961 | util-deprecate: 1.0.2 1962 | dev: true 1963 | 1964 | /readdirp/3.6.0: 1965 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1966 | engines: {node: '>=8.10.0'} 1967 | dependencies: 1968 | picomatch: 2.3.1 1969 | dev: true 1970 | 1971 | /regexparam/2.0.0: 1972 | resolution: {integrity: sha512-gJKwd2MVPWHAIFLsaYDZfyKzHNS4o7E/v8YmNf44vmeV2e4YfVoDToTOKTvE7ab68cRJ++kLuEXJBaEeJVt5ow==} 1973 | engines: {node: '>=8'} 1974 | dev: true 1975 | 1976 | /regexpp/3.2.0: 1977 | resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} 1978 | engines: {node: '>=8'} 1979 | dev: true 1980 | 1981 | /resolve-from/4.0.0: 1982 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1983 | engines: {node: '>=4'} 1984 | dev: true 1985 | 1986 | /resolve-from/5.0.0: 1987 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 1988 | engines: {node: '>=8'} 1989 | dev: true 1990 | 1991 | /resolve/1.22.0: 1992 | resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} 1993 | hasBin: true 1994 | dependencies: 1995 | is-core-module: 2.9.0 1996 | path-parse: 1.0.7 1997 | supports-preserve-symlinks-flag: 1.0.0 1998 | dev: true 1999 | 2000 | /reusify/1.0.4: 2001 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 2002 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 2003 | dev: true 2004 | 2005 | /rimraf/2.7.1: 2006 | resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} 2007 | hasBin: true 2008 | dependencies: 2009 | glob: 7.2.3 2010 | dev: true 2011 | 2012 | /rimraf/3.0.2: 2013 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 2014 | hasBin: true 2015 | dependencies: 2016 | glob: 7.2.3 2017 | dev: true 2018 | 2019 | /rollup-pluginutils/2.8.2: 2020 | resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} 2021 | dependencies: 2022 | estree-walker: 0.6.1 2023 | dev: true 2024 | 2025 | /rollup/2.74.1: 2026 | resolution: {integrity: sha512-K2zW7kV8Voua5eGkbnBtWYfMIhYhT9Pel2uhBk2WO5eMee161nPze/XRfvEQPFYz7KgrCCnmh2Wy0AMFLGGmMA==} 2027 | engines: {node: '>=10.0.0'} 2028 | hasBin: true 2029 | optionalDependencies: 2030 | fsevents: 2.3.2 2031 | dev: true 2032 | 2033 | /run-parallel/1.2.0: 2034 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 2035 | dependencies: 2036 | queue-microtask: 1.2.3 2037 | dev: true 2038 | 2039 | /sade/1.8.1: 2040 | resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} 2041 | engines: {node: '>=6'} 2042 | dependencies: 2043 | mri: 1.2.0 2044 | dev: true 2045 | 2046 | /safe-buffer/5.1.2: 2047 | resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 2048 | dev: true 2049 | 2050 | /safe-buffer/5.2.1: 2051 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 2052 | dev: true 2053 | 2054 | /safer-buffer/2.1.2: 2055 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 2056 | dev: true 2057 | 2058 | /sander/0.5.1: 2059 | resolution: {integrity: sha1-dB4kXiMfB8r7b98PEzrfohalAq0=} 2060 | dependencies: 2061 | es6-promise: 3.3.1 2062 | graceful-fs: 4.2.10 2063 | mkdirp: 0.5.6 2064 | rimraf: 2.7.1 2065 | dev: true 2066 | 2067 | /sax/1.2.4: 2068 | resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} 2069 | dev: true 2070 | 2071 | /semver/5.7.1: 2072 | resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} 2073 | hasBin: true 2074 | dev: true 2075 | 2076 | /semver/6.3.0: 2077 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} 2078 | hasBin: true 2079 | dev: true 2080 | 2081 | /semver/7.3.7: 2082 | resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} 2083 | engines: {node: '>=10'} 2084 | hasBin: true 2085 | dependencies: 2086 | lru-cache: 6.0.0 2087 | dev: true 2088 | 2089 | /set-blocking/2.0.0: 2090 | resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} 2091 | dev: true 2092 | 2093 | /set-cookie-parser/2.4.8: 2094 | resolution: {integrity: sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==} 2095 | dev: true 2096 | 2097 | /shebang-command/2.0.0: 2098 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 2099 | engines: {node: '>=8'} 2100 | dependencies: 2101 | shebang-regex: 3.0.0 2102 | dev: true 2103 | 2104 | /shebang-regex/3.0.0: 2105 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 2106 | engines: {node: '>=8'} 2107 | dev: true 2108 | 2109 | /signal-exit/3.0.7: 2110 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 2111 | dev: true 2112 | 2113 | /slash/3.0.0: 2114 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 2115 | engines: {node: '>=8'} 2116 | dev: true 2117 | 2118 | /sorcery/0.10.0: 2119 | resolution: {integrity: sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=} 2120 | hasBin: true 2121 | dependencies: 2122 | buffer-crc32: 0.2.13 2123 | minimist: 1.2.6 2124 | sander: 0.5.1 2125 | sourcemap-codec: 1.4.8 2126 | dev: true 2127 | 2128 | /source-map-js/1.0.2: 2129 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 2130 | engines: {node: '>=0.10.0'} 2131 | dev: true 2132 | 2133 | /sourcemap-codec/1.4.8: 2134 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} 2135 | dev: true 2136 | 2137 | /string-width/1.0.2: 2138 | resolution: {integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=} 2139 | engines: {node: '>=0.10.0'} 2140 | dependencies: 2141 | code-point-at: 1.1.0 2142 | is-fullwidth-code-point: 1.0.0 2143 | strip-ansi: 3.0.1 2144 | dev: true 2145 | 2146 | /string-width/4.2.3: 2147 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 2148 | engines: {node: '>=8'} 2149 | dependencies: 2150 | emoji-regex: 8.0.0 2151 | is-fullwidth-code-point: 3.0.0 2152 | strip-ansi: 6.0.1 2153 | dev: true 2154 | 2155 | /string_decoder/1.1.1: 2156 | resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} 2157 | dependencies: 2158 | safe-buffer: 5.1.2 2159 | dev: true 2160 | 2161 | /string_decoder/1.3.0: 2162 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 2163 | dependencies: 2164 | safe-buffer: 5.2.1 2165 | dev: true 2166 | 2167 | /strip-ansi/3.0.1: 2168 | resolution: {integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=} 2169 | engines: {node: '>=0.10.0'} 2170 | dependencies: 2171 | ansi-regex: 2.1.1 2172 | dev: true 2173 | 2174 | /strip-ansi/6.0.1: 2175 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 2176 | engines: {node: '>=8'} 2177 | dependencies: 2178 | ansi-regex: 5.0.1 2179 | dev: true 2180 | 2181 | /strip-indent/3.0.0: 2182 | resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} 2183 | engines: {node: '>=8'} 2184 | dependencies: 2185 | min-indent: 1.0.1 2186 | dev: true 2187 | 2188 | /strip-json-comments/2.0.1: 2189 | resolution: {integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo=} 2190 | engines: {node: '>=0.10.0'} 2191 | dev: true 2192 | 2193 | /strip-json-comments/3.1.1: 2194 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 2195 | engines: {node: '>=8'} 2196 | dev: true 2197 | 2198 | /supports-color/7.2.0: 2199 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 2200 | engines: {node: '>=8'} 2201 | dependencies: 2202 | has-flag: 4.0.0 2203 | dev: true 2204 | 2205 | /supports-preserve-symlinks-flag/1.0.0: 2206 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 2207 | engines: {node: '>= 0.4'} 2208 | dev: true 2209 | 2210 | /svelte-check/2.7.1_bwfybwdzwmlevsatlte2x4gwcy: 2211 | resolution: {integrity: sha512-vHVu2+SQ6ibt77iTQaq2oiOjBgGL48qqcg0ZdEOsP5pPOjgeyR9QbnaEdzdBs9nsVYBc/42haKtzb2uFqS8GVw==} 2212 | hasBin: true 2213 | peerDependencies: 2214 | svelte: ^3.24.0 2215 | dependencies: 2216 | '@jridgewell/trace-mapping': 0.3.13 2217 | chokidar: 3.5.3 2218 | fast-glob: 3.2.11 2219 | import-fresh: 3.3.0 2220 | picocolors: 1.0.0 2221 | sade: 1.8.1 2222 | svelte: 3.48.0 2223 | svelte-preprocess: 4.10.6_kwmypdju4ysizxi7azib3bf22y 2224 | typescript: 4.6.4 2225 | transitivePeerDependencies: 2226 | - '@babel/core' 2227 | - coffeescript 2228 | - less 2229 | - node-sass 2230 | - postcss 2231 | - postcss-load-config 2232 | - pug 2233 | - sass 2234 | - stylus 2235 | - sugarss 2236 | dev: true 2237 | 2238 | /svelte-hmr/0.14.11_svelte@3.48.0: 2239 | resolution: {integrity: sha512-R9CVfX6DXxW1Kn45Jtmx+yUe+sPhrbYSUp7TkzbW0jI5fVPn6lsNG9NEs5dFg5qRhFNAoVdRw5qQDLALNKhwbQ==} 2240 | engines: {node: ^12.20 || ^14.13.1 || >= 16} 2241 | peerDependencies: 2242 | svelte: '>=3.19.0' 2243 | dependencies: 2244 | svelte: 3.48.0 2245 | dev: true 2246 | 2247 | /svelte-preprocess/4.10.6_kwmypdju4ysizxi7azib3bf22y: 2248 | resolution: {integrity: sha512-I2SV1w/AveMvgIQlUF/ZOO3PYVnhxfcpNyGt8pxpUVhPfyfL/CZBkkw/KPfuFix5FJ9TnnNYMhACK3DtSaYVVQ==} 2249 | engines: {node: '>= 9.11.2'} 2250 | requiresBuild: true 2251 | peerDependencies: 2252 | '@babel/core': ^7.10.2 2253 | coffeescript: ^2.5.1 2254 | less: ^3.11.3 || ^4.0.0 2255 | node-sass: '*' 2256 | postcss: ^7 || ^8 2257 | postcss-load-config: ^2.1.0 || ^3.0.0 2258 | pug: ^3.0.0 2259 | sass: ^1.26.8 2260 | stylus: ^0.55.0 2261 | sugarss: ^2.0.0 2262 | svelte: ^3.23.0 2263 | typescript: ^3.9.5 || ^4.0.0 2264 | peerDependenciesMeta: 2265 | '@babel/core': 2266 | optional: true 2267 | coffeescript: 2268 | optional: true 2269 | less: 2270 | optional: true 2271 | node-sass: 2272 | optional: true 2273 | postcss: 2274 | optional: true 2275 | postcss-load-config: 2276 | optional: true 2277 | pug: 2278 | optional: true 2279 | sass: 2280 | optional: true 2281 | stylus: 2282 | optional: true 2283 | sugarss: 2284 | optional: true 2285 | typescript: 2286 | optional: true 2287 | dependencies: 2288 | '@types/pug': 2.0.6 2289 | '@types/sass': 1.43.1 2290 | detect-indent: 6.1.0 2291 | magic-string: 0.25.9 2292 | postcss: 8.4.14 2293 | postcss-load-config: 3.1.4_postcss@8.4.14 2294 | sorcery: 0.10.0 2295 | strip-indent: 3.0.0 2296 | svelte: 3.48.0 2297 | typescript: 4.6.4 2298 | dev: true 2299 | 2300 | /svelte/3.48.0: 2301 | resolution: {integrity: sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ==} 2302 | engines: {node: '>= 8'} 2303 | dev: true 2304 | 2305 | /svelte2tsx/0.5.10_wwvk7nlptlrqo2czohjtk6eiqm: 2306 | resolution: {integrity: sha512-nokQ0HTTWMcNX6tLrDLiOmJCuqjKZU9nCZ6/mVuCL3nusXdbp+9nv69VG2pCy7uQC66kV4Ls+j0WfvvJuGVnkg==} 2307 | peerDependencies: 2308 | svelte: ^3.24 2309 | typescript: ^4.1.2 2310 | dependencies: 2311 | dedent-js: 1.0.1 2312 | pascal-case: 3.1.2 2313 | svelte: 3.48.0 2314 | typescript: 4.6.4 2315 | dev: true 2316 | 2317 | /tailwindcss/3.0.24: 2318 | resolution: {integrity: sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==} 2319 | engines: {node: '>=12.13.0'} 2320 | hasBin: true 2321 | dependencies: 2322 | arg: 5.0.1 2323 | chokidar: 3.5.3 2324 | color-name: 1.1.4 2325 | detective: 5.2.0 2326 | didyoumean: 1.2.2 2327 | dlv: 1.1.3 2328 | fast-glob: 3.2.11 2329 | glob-parent: 6.0.2 2330 | is-glob: 4.0.3 2331 | lilconfig: 2.0.5 2332 | normalize-path: 3.0.0 2333 | object-hash: 3.0.0 2334 | picocolors: 1.0.0 2335 | postcss: 8.4.14 2336 | postcss-js: 4.0.0_postcss@8.4.14 2337 | postcss-load-config: 3.1.4_postcss@8.4.14 2338 | postcss-nested: 5.0.6_postcss@8.4.14 2339 | postcss-selector-parser: 6.0.10 2340 | postcss-value-parser: 4.2.0 2341 | quick-lru: 5.1.1 2342 | resolve: 1.22.0 2343 | transitivePeerDependencies: 2344 | - ts-node 2345 | dev: true 2346 | 2347 | /tar/4.4.19: 2348 | resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==} 2349 | engines: {node: '>=4.5'} 2350 | dependencies: 2351 | chownr: 1.1.4 2352 | fs-minipass: 1.2.7 2353 | minipass: 2.9.0 2354 | minizlib: 1.3.3 2355 | mkdirp: 0.5.6 2356 | safe-buffer: 5.2.1 2357 | yallist: 3.1.1 2358 | dev: true 2359 | 2360 | /tar/6.1.11: 2361 | resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} 2362 | engines: {node: '>= 10'} 2363 | dependencies: 2364 | chownr: 2.0.0 2365 | fs-minipass: 2.1.0 2366 | minipass: 3.1.6 2367 | minizlib: 2.1.2 2368 | mkdirp: 1.0.4 2369 | yallist: 4.0.0 2370 | dev: true 2371 | 2372 | /text-table/0.2.0: 2373 | resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} 2374 | dev: true 2375 | 2376 | /tiny-glob/0.2.9: 2377 | resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} 2378 | dependencies: 2379 | globalyzer: 0.1.0 2380 | globrex: 0.1.2 2381 | dev: true 2382 | 2383 | /to-regex-range/5.0.1: 2384 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 2385 | engines: {node: '>=8.0'} 2386 | dependencies: 2387 | is-number: 7.0.0 2388 | dev: true 2389 | 2390 | /tr46/0.0.3: 2391 | resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=} 2392 | dev: true 2393 | 2394 | /tslib/1.14.1: 2395 | resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} 2396 | dev: true 2397 | 2398 | /tslib/2.4.0: 2399 | resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} 2400 | dev: true 2401 | 2402 | /tsutils/3.21.0_typescript@4.6.4: 2403 | resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} 2404 | engines: {node: '>= 6'} 2405 | peerDependencies: 2406 | typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' 2407 | dependencies: 2408 | tslib: 1.14.1 2409 | typescript: 4.6.4 2410 | dev: true 2411 | 2412 | /type-check/0.4.0: 2413 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 2414 | engines: {node: '>= 0.8.0'} 2415 | dependencies: 2416 | prelude-ls: 1.2.1 2417 | dev: true 2418 | 2419 | /type-fest/0.20.2: 2420 | resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} 2421 | engines: {node: '>=10'} 2422 | dev: true 2423 | 2424 | /typescript/4.6.4: 2425 | resolution: {integrity: sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==} 2426 | engines: {node: '>=4.2.0'} 2427 | hasBin: true 2428 | dev: true 2429 | 2430 | /uri-js/4.4.1: 2431 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 2432 | dependencies: 2433 | punycode: 2.1.1 2434 | dev: true 2435 | 2436 | /util-deprecate/1.0.2: 2437 | resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} 2438 | dev: true 2439 | 2440 | /uuid/8.3.2: 2441 | resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} 2442 | hasBin: true 2443 | dev: true 2444 | 2445 | /v8-compile-cache/2.3.0: 2446 | resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} 2447 | dev: true 2448 | 2449 | /vite/2.9.9: 2450 | resolution: {integrity: sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==} 2451 | engines: {node: '>=12.2.0'} 2452 | hasBin: true 2453 | peerDependencies: 2454 | less: '*' 2455 | sass: '*' 2456 | stylus: '*' 2457 | peerDependenciesMeta: 2458 | less: 2459 | optional: true 2460 | sass: 2461 | optional: true 2462 | stylus: 2463 | optional: true 2464 | dependencies: 2465 | esbuild: 0.14.39 2466 | postcss: 8.4.14 2467 | resolve: 1.22.0 2468 | rollup: 2.74.1 2469 | optionalDependencies: 2470 | fsevents: 2.3.2 2471 | dev: true 2472 | 2473 | /webidl-conversions/3.0.1: 2474 | resolution: {integrity: sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=} 2475 | dev: true 2476 | 2477 | /whatwg-url/5.0.0: 2478 | resolution: {integrity: sha1-lmRU6HZUYuN2RNNib2dCzotwll0=} 2479 | dependencies: 2480 | tr46: 0.0.3 2481 | webidl-conversions: 3.0.1 2482 | dev: true 2483 | 2484 | /which/2.0.2: 2485 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 2486 | engines: {node: '>= 8'} 2487 | hasBin: true 2488 | dependencies: 2489 | isexe: 2.0.0 2490 | dev: true 2491 | 2492 | /wide-align/1.1.5: 2493 | resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} 2494 | dependencies: 2495 | string-width: 4.2.3 2496 | dev: true 2497 | 2498 | /word-wrap/1.2.3: 2499 | resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} 2500 | engines: {node: '>=0.10.0'} 2501 | dev: true 2502 | 2503 | /worktop/0.8.0-next.14: 2504 | resolution: {integrity: sha512-RZgqHu1w/JcUdWOE/BUEAzarrUUHh39eWkLdX8XpA6MfgLJF6X5Vl26CV7/wcm4O/UpZvHMGJUtB9eYTqDjc9g==} 2505 | engines: {node: '>=12'} 2506 | dependencies: 2507 | mrmime: 1.0.0 2508 | regexparam: 2.0.0 2509 | dev: true 2510 | 2511 | /wrappy/1.0.2: 2512 | resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} 2513 | dev: true 2514 | 2515 | /xtend/4.0.2: 2516 | resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} 2517 | engines: {node: '>=0.4'} 2518 | dev: true 2519 | 2520 | /yallist/3.1.1: 2521 | resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} 2522 | dev: true 2523 | 2524 | /yallist/4.0.0: 2525 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 2526 | dev: true 2527 | 2528 | /yaml/1.10.2: 2529 | resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} 2530 | engines: {node: '>= 6'} 2531 | dev: true 2532 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const tailwindcss = require('tailwindcss'); 2 | const autoprefixer = require('autoprefixer'); 3 | 4 | const config = { 5 | plugins: [ 6 | //Some plugins, like tailwindcss/nesting, need to run before Tailwind, 7 | tailwindcss(), 8 | //But others, like autoprefixer, need to run after, 9 | autoprefixer 10 | ] 11 | }; 12 | 13 | module.exports = config; 14 | -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | /* Write your global styles here, in PostCSS syntax */ 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | -------------------------------------------------------------------------------- /src/app.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // See https://kit.svelte.dev/docs/types#app 4 | // for information about these interfaces 5 | declare namespace App { 6 | interface Locals { 7 | userid: string; 8 | } 9 | 10 | // interface Platform {} 11 | 12 | // interface Session {} 13 | 14 | // interface Stuff {} 15 | } 16 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | %sveltekit.head% 9 | 10 | 11 | 12 |
%sveltekit.body%
13 | 14 | 15 | -------------------------------------------------------------------------------- /src/global.d.ts: -------------------------------------------------------------------------------- 1 | import type { SpeechRecognitionClass } from "$lib/types"; 2 | 3 | declare global { 4 | interface Window { 5 | SpeechRecognition: SpeechRecognitionClass; 6 | webkitSpeechRecognition: SpeechRecognitionClass; 7 | webkitAudioContext: AudioContext; 8 | } 9 | 10 | interface Navigator { 11 | brave?: () => void; 12 | } 13 | } -------------------------------------------------------------------------------- /src/hooks.ts: -------------------------------------------------------------------------------- 1 | import type { Handle } from '@sveltejs/kit'; 2 | 3 | export const handle: Handle = async ({ event, resolve }) => { 4 | const response = await resolve(event); 5 | 6 | return response; 7 | }; 8 | -------------------------------------------------------------------------------- /src/lib/NativeSpeechRecognition.ts: -------------------------------------------------------------------------------- 1 | import { browser } from "$app/env"; 2 | import type { SpeechRecognitionClass } from "@speechly/speech-recognition-polyfill"; 3 | 4 | const NativeSpeechRecognition = !browser ? null : (navigator.brave ? null : window.SpeechRecognition || window.webkitSpeechRecognition); 5 | const isNative = (SpeechRecognition: SpeechRecognitionClass) => SpeechRecognition === NativeSpeechRecognition; 6 | const browserSupportsSpeechRecognition = !!NativeSpeechRecognition; 7 | 8 | export { NativeSpeechRecognition, isNative, browserSupportsSpeechRecognition } -------------------------------------------------------------------------------- /src/lib/RecognitionManager.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | /* eslint-disable @typescript-eslint/no-empty-function */ 3 | import isAndroid from './isAndroid' 4 | import { isNative } from './NativeSpeechRecognition' 5 | import { get, writable, type Writable } from 'svelte/store'; 6 | import { debounce, concatTranscripts, browserSupportsPolyfills } from '$lib/utils' 7 | import type { SpeechRecognitionClass, SpeechRecognition, SpeechRecognitionErrorEvent } from '@speechly/speech-recognition-polyfill'; 8 | 9 | 10 | export default class RecognitionManager { 11 | recognition: SpeechRecognition | null; 12 | pauseAfterDisconnect: boolean; 13 | interimTranscript: string; 14 | finalTranscript: string; 15 | listening: Writable; 16 | isMicrophoneAvailable: boolean; 17 | subscribers: any; 18 | onStopListening: any; 19 | previousResultWasFinalOnly: boolean; 20 | constructor(SpeechRecognition: SpeechRecognitionClass) { 21 | console.log('SpeechRecognition Constructor'); 22 | this.recognition = null 23 | this.pauseAfterDisconnect = false 24 | this.interimTranscript = '' 25 | this.finalTranscript = '' 26 | this.listening = writable(false) 27 | this.isMicrophoneAvailable = true 28 | this.subscribers = {} 29 | this.onStopListening = () => { } 30 | this.previousResultWasFinalOnly = false 31 | 32 | this.resetTranscript = this.resetTranscript.bind(this) 33 | this.startListening = this.startListening.bind(this) 34 | this.stopListening = this.stopListening.bind(this) 35 | this.abortListening = this.abortListening.bind(this) 36 | this.setSpeechRecognition = this.setSpeechRecognition.bind(this) 37 | this.disableRecognition = this.disableRecognition.bind(this) 38 | 39 | this.setSpeechRecognition(SpeechRecognition) 40 | 41 | if (isAndroid()) { 42 | this.updateFinalTranscript = debounce(this.updateFinalTranscript, 250, true) 43 | } 44 | } 45 | 46 | setSpeechRecognition(SpeechRecognition: SpeechRecognitionClass) { 47 | console.log('setSpeechRecognition'); 48 | const browserSupportsRecogniser = !!SpeechRecognition && ( 49 | isNative(SpeechRecognition) || browserSupportsPolyfills() 50 | ) 51 | if (browserSupportsRecogniser) { 52 | this.disableRecognition() 53 | this.recognition = new SpeechRecognition() 54 | this.recognition.continuous = false 55 | this.recognition.interimResults = true 56 | this.recognition.onresult = this.updateTranscript.bind(this) 57 | this.recognition.onend = this.onRecognitionDisconnect.bind(this) 58 | this.recognition.onerror = this.onError.bind(this) 59 | } 60 | // this.emitBrowserSupportsSpeechRecognitionChange(browserSupportsRecogniser) 61 | } 62 | 63 | subscribe(id: number, callbacks: any) { 64 | console.log('subscribe: ', { id, callbacks }); 65 | this.subscribers[id] = callbacks 66 | } 67 | 68 | unsubscribe(id: number) { 69 | console.log('unsubscribe'); 70 | delete this.subscribers[id] 71 | } 72 | 73 | emitListeningChange(listening: boolean) { 74 | console.log('emitListeningChange'); 75 | this.listening.set(listening) 76 | Object.keys(this.subscribers).forEach((id) => { 77 | const { onListeningChange } = this.subscribers[id] 78 | onListeningChange(listening) 79 | }) 80 | } 81 | 82 | emitMicrophoneAvailabilityChange(isMicrophoneAvailable: boolean) { 83 | console.log('emitMicrophoneAvailabilityChange'); 84 | this.isMicrophoneAvailable = isMicrophoneAvailable 85 | Object.keys(this.subscribers).forEach((id) => { 86 | const { onMicrophoneAvailabilityChange } = this.subscribers[id] 87 | onMicrophoneAvailabilityChange(isMicrophoneAvailable) 88 | }) 89 | } 90 | 91 | emitTranscriptChange(interimTranscript: string, finalTranscript: string) { 92 | console.log('emitTranscriptChange: ', { interimTranscript, finalTranscript }); 93 | Object.keys(this.subscribers).forEach((id) => { 94 | const { onTranscriptChange } = this.subscribers[id] 95 | onTranscriptChange(interimTranscript, finalTranscript) 96 | }) 97 | } 98 | 99 | emitClearTranscript() { 100 | console.log('emitClearTranscript'); 101 | Object.keys(this.subscribers).forEach((id) => { 102 | const { onClearTranscript } = this.subscribers[id] 103 | onClearTranscript() 104 | }) 105 | } 106 | 107 | disconnect(disconnectType: 'ABORT' | 'RESET' | 'STOP') { 108 | console.log('disconnect'); 109 | if (this.recognition && get(this.listening)) { 110 | switch (disconnectType) { 111 | case 'ABORT': 112 | this.pauseAfterDisconnect = true 113 | this.abort() 114 | break 115 | case 'RESET': 116 | console.log('RESET SWITCH'); 117 | this.pauseAfterDisconnect = false 118 | this.abort() 119 | break 120 | case 'STOP': 121 | default: 122 | this.pauseAfterDisconnect = true 123 | this.stop() 124 | } 125 | } 126 | } 127 | 128 | disableRecognition() { 129 | console.log('disableRecognition'); 130 | if (this.recognition) { 131 | this.recognition.onresult = () => { } 132 | this.recognition.onend = () => { } 133 | this.recognition.onerror = () => { } 134 | if (get(this.listening)) { 135 | this.stopListening() 136 | } 137 | } 138 | } 139 | 140 | onError(event: SpeechRecognitionErrorEvent) { 141 | console.log('onError'); 142 | if (event && event.error && event.error === 'not-allowed') { 143 | this.emitMicrophoneAvailabilityChange(false) 144 | this.disableRecognition() 145 | } 146 | } 147 | 148 | onRecognitionDisconnect() { 149 | console.log('onRecognitionDisconnect'); 150 | this.onStopListening() 151 | this.listening.set(false) 152 | if (this.pauseAfterDisconnect) { 153 | this.emitListeningChange(false) 154 | } else if (this.recognition) { 155 | if (this.recognition.continuous) { 156 | this.startListening({ continuous: this.recognition.continuous }) 157 | } else { 158 | this.emitListeningChange(false) 159 | } 160 | } 161 | this.pauseAfterDisconnect = false 162 | } 163 | 164 | updateTranscript({ results, resultIndex }: { results: any, resultIndex: number }) { 165 | console.log('updateTranscript'); 166 | const currentIndex = resultIndex === undefined ? results.length - 1 : resultIndex 167 | this.interimTranscript = '' 168 | this.finalTranscript = '' 169 | for (let i = currentIndex; i < results.length; ++i) { 170 | if (results[i].isFinal && (!isAndroid() || results[i][0].confidence > 0)) { 171 | this.updateFinalTranscript(results[i][0].transcript) 172 | } else { 173 | this.interimTranscript = concatTranscripts( 174 | this.interimTranscript, 175 | results[i][0].transcript 176 | ) 177 | } 178 | } 179 | let isDuplicateResult = false 180 | if (this.interimTranscript === '' && this.finalTranscript !== '') { 181 | if (this.previousResultWasFinalOnly) { 182 | isDuplicateResult = true 183 | } 184 | this.previousResultWasFinalOnly = true 185 | } else { 186 | this.previousResultWasFinalOnly = false 187 | } 188 | if (!isDuplicateResult) { 189 | this.emitTranscriptChange(this.interimTranscript, this.finalTranscript) 190 | } 191 | } 192 | 193 | updateFinalTranscript(newFinalTranscript: string) { 194 | console.log('updateFinalTranscript'); 195 | this.finalTranscript = concatTranscripts( 196 | this.finalTranscript, 197 | newFinalTranscript 198 | ) 199 | } 200 | 201 | resetTranscript() { 202 | console.log('resetTranscript') 203 | this.disconnect('RESET') 204 | } 205 | 206 | async startListening({ continuous = false, language = 'en' } = {}) { 207 | console.log('startListening'); 208 | if (!this.recognition) { 209 | return 210 | } 211 | 212 | const isContinuousChanged = continuous !== this.recognition.continuous 213 | // @ts-expect-error I believe this is a bug because Speechly doesn't have .lang. 214 | const isLanguageChanged = language && language !== this.recognition.lang 215 | if (isContinuousChanged || isLanguageChanged) { 216 | if (get(this.listening)) { 217 | await this.stopListening() 218 | } 219 | this.recognition.continuous = isContinuousChanged ? continuous : this.recognition.continuous 220 | // @ts-expect-error I believe this is a bug because Speechly doesn't have .lang. 221 | this.recognition.lang = isLanguageChanged ? language : this.recognition.lang 222 | } 223 | if (!get(this.listening)) { 224 | if (!this.recognition.continuous) { 225 | this.resetTranscript() 226 | this.emitClearTranscript() 227 | } 228 | try { 229 | await this.start() 230 | this.emitListeningChange(true) 231 | } catch (e) { 232 | // DOMExceptions indicate a redundant microphone start - safe to swallow 233 | if (!(e instanceof DOMException)) { 234 | this.emitMicrophoneAvailabilityChange(false) 235 | } 236 | } 237 | } 238 | } 239 | 240 | async abortListening() { 241 | console.log('abortListening'); 242 | this.disconnect('ABORT') 243 | this.emitListeningChange(false) 244 | await new Promise(resolve => { 245 | this.onStopListening = resolve 246 | }) 247 | } 248 | 249 | async stopListening() { 250 | console.log('stopListening'); 251 | this.disconnect('STOP') 252 | this.emitListeningChange(false) 253 | await new Promise(resolve => { 254 | this.onStopListening = resolve 255 | }) 256 | } 257 | 258 | getRecognition() { 259 | console.log('getRecognition'); 260 | return this.recognition 261 | } 262 | 263 | async start() { 264 | console.log('Start'); 265 | if (this.recognition && !get(this.listening)) { 266 | await this.recognition.start() 267 | this.listening.set(true) 268 | } 269 | } 270 | 271 | stop() { 272 | console.log('Stop'); 273 | if (this.recognition && get(this.listening)) { 274 | this.recognition.stop() 275 | this.listening.set(false) 276 | } 277 | } 278 | 279 | abort() { 280 | console.log('Abort'); 281 | if (this.recognition && get(this.listening)) { 282 | this.recognition.abort() 283 | this.listening.set(false) 284 | } 285 | } 286 | } -------------------------------------------------------------------------------- /src/lib/SpeechRecognition.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | import { 3 | commandToRegExp, 4 | compareTwoStringsUsingDiceCoefficient, 5 | browserSupportsPolyfills 6 | } from './utils' 7 | import { browser } from '$app/env'; 8 | import isAndroid from './isAndroid'; 9 | import RecognitionManager from './RecognitionManager' 10 | import { derived, get, writable, type Writable } from 'svelte/store'; 11 | import { NativeSpeechRecognition } from './NativeSpeechRecognition' 12 | import type { SpeechRecognitionClass, SpeechRecognition as PolyfillSpeechRecognitionType } from '@speechly/speech-recognition-polyfill'; 13 | 14 | 15 | let _browserSupportsSpeechRecognition = !!NativeSpeechRecognition 16 | let _browserSupportsContinuousListening = _browserSupportsSpeechRecognition && !isAndroid() 17 | let recognitionManager: RecognitionManager; 18 | 19 | type TranscriptStore = { interimTranscript: string, finalTranscript: string[] }; 20 | const useSpeechRecognition = ({ 21 | transcribing = true, 22 | clearTranscriptOnListen = true, 23 | commands = [] 24 | } = {}) => { 25 | const recognitionManager = SpeechRecognition.getRecognitionManager(); 26 | 27 | // Stores to be used in Svelte files 28 | const transcribingStore = writable(transcribing); 29 | const transcriptStore: Writable = writable({ interimTranscript: '', finalTranscript: [] }); 30 | const clearTranscriptOnListenStore = writable(clearTranscriptOnListen); 31 | const listeningReadable = derived(recognitionManager.listening, $listening => $listening); 32 | 33 | // Maybe keep, interimTranscript and finalTranscript in separate stores to match react-speech-recognition 34 | const interimTranscript = derived(transcriptStore, $transcript => $transcript.interimTranscript); 35 | const finalTranscript = derived(transcriptStore, $transcript => $transcript.finalTranscript); 36 | 37 | const browserSupportsSpeechRecognition = !browser ? true : _browserSupportsSpeechRecognition; 38 | const browserSupportsContinuousListening = _browserSupportsContinuousListening; 39 | let isMicrophoneAvailable = recognitionManager.isMicrophoneAvailable 40 | 41 | const clearTranscript = () => { 42 | transcriptStore.set({ interimTranscript: '', finalTranscript: [] }) 43 | }; 44 | 45 | const resetTranscript = () => { 46 | console.log('Hit reset transcript.'); 47 | recognitionManager.resetTranscript() 48 | clearTranscript() 49 | }; 50 | 51 | const testFuzzyMatch = (command: any, input: string, fuzzyMatchingThreshold: number) => { 52 | console.log("testFuzzyMatch: ", { command, input, fuzzyMatchingThreshold }); 53 | const commandToString = (typeof command === 'object') ? command.toString() : command 54 | const commandWithoutSpecials = commandToString 55 | .replace(/[&/\\#,+()!$~%.'":*?<>{}]/g, '') 56 | .replace(/ +/g, ' ') 57 | .trim() 58 | const howSimilar = compareTwoStringsUsingDiceCoefficient(commandWithoutSpecials, input) 59 | if (howSimilar >= fuzzyMatchingThreshold) { 60 | return { 61 | command, 62 | commandWithoutSpecials, 63 | howSimilar, 64 | isFuzzyMatch: true 65 | } 66 | } 67 | return null 68 | } 69 | 70 | const testMatch = (command: any, input: string) => { 71 | const pattern = commandToRegExp(command) 72 | const result = pattern.exec(input) 73 | if (result) { 74 | return { 75 | command, 76 | parameters: result.slice(1) 77 | } 78 | } 79 | return null 80 | } 81 | 82 | const matchCommands = (newInterimTranscript: string, newFinalTranscript: string) => { 83 | commands.forEach(({ 84 | command, 85 | callback, 86 | matchInterim = false, 87 | isFuzzyMatch = false, 88 | fuzzyMatchingThreshold = 0.8, 89 | bestMatchOnly = false 90 | }) => { 91 | const input = !newFinalTranscript && matchInterim 92 | ? newInterimTranscript.trim() 93 | : newFinalTranscript.trim() 94 | const subcommands = Array.isArray(command) ? command : [command] 95 | const results = subcommands.map(subcommand => { 96 | if (isFuzzyMatch) { 97 | return testFuzzyMatch(subcommand, input, fuzzyMatchingThreshold) 98 | } 99 | return testMatch(subcommand, input) 100 | }).filter(x => x) 101 | if (isFuzzyMatch && bestMatchOnly && results.length >= 2) { 102 | //@ts-expect-error Fix later 103 | results.sort((a, b) => b.howSimilar - a.howSimilar) 104 | const command = results[0]?.command; 105 | //@ts-expect-error Fix later 106 | const commandWithoutSpecials = results[0]?.commandWithoutSpecials; 107 | //@ts-expect-error Fix later 108 | const howSimilar = results[0]?.howSimilar; 109 | 110 | callback(commandWithoutSpecials, input, howSimilar, { command, resetTranscript }) 111 | } else { 112 | results.forEach(result => { 113 | //@ts-expect-error Fix later 114 | if (result.isFuzzyMatch) { 115 | //@ts-expect-error Fix later 116 | const { command, commandWithoutSpecials, howSimilar } = result 117 | callback(commandWithoutSpecials, input, howSimilar, { command, resetTranscript }) 118 | } else { 119 | //@ts-expect-error Fix later 120 | const { command, parameters } = result 121 | callback(...parameters, { command, resetTranscript }) 122 | } 123 | }) 124 | } 125 | }) 126 | } 127 | 128 | const handleTranscriptChange = (newInterimTranscript: string, newFinalTranscript: string) => { // Handle this with a svelte store 129 | console.log("handleTranscriptChange: ", { newInterimTranscript, newFinalTranscript }); 130 | const isTranscribing = get(transcribingStore); 131 | if (isTranscribing) { 132 | transcriptStore.update(n => { 133 | 134 | n.interimTranscript = newInterimTranscript; 135 | if (newFinalTranscript) 136 | n.finalTranscript = [...n.finalTranscript, newFinalTranscript]; 137 | 138 | return n; 139 | }) 140 | } 141 | matchCommands(newInterimTranscript, newFinalTranscript) 142 | } 143 | 144 | const handleClearTranscript = () => { 145 | console.log("handleClearTranscript"); 146 | const clearTranscriptOnListenValue = get(clearTranscriptOnListenStore); 147 | if (clearTranscriptOnListenValue) { 148 | clearTranscript() 149 | } 150 | } 151 | 152 | // Old use effect block 153 | const id = SpeechRecognition.counter 154 | SpeechRecognition.counter += 1 155 | 156 | const callbacks = { 157 | onListeningChange: (newListening: boolean) => recognitionManager.listening.set(newListening), 158 | onMicrophoneAvailabilityChange: (newMicrophoneAvailability: boolean) => isMicrophoneAvailable = newMicrophoneAvailability, 159 | onTranscriptChange: handleTranscriptChange, 160 | onClearTranscript: handleClearTranscript, 161 | } 162 | recognitionManager.subscribe(id, callbacks) 163 | // Old use effect block 164 | 165 | return { 166 | transcribing: transcribingStore, 167 | clearTranscriptOnListen: clearTranscriptOnListenStore, 168 | listening: listeningReadable, 169 | isMicrophoneAvailable, 170 | resetTranscript, 171 | browserSupportsSpeechRecognition, 172 | browserSupportsContinuousListening, 173 | transcriptStore, 174 | interimTranscript, 175 | finalTranscript, 176 | } 177 | } 178 | 179 | export type startListeningInput = { continuous?: boolean, language?: string }; 180 | export interface SpeechRecognitionType { 181 | counter: number, 182 | applyPolyfill: (input: SpeechRecognitionClass) => void, 183 | getRecognitionManager: () => RecognitionManager, 184 | getRecognition: () => PolyfillSpeechRecognitionType | null, 185 | startListening: (input: startListeningInput) => void, 186 | stopListening: () => void, 187 | abortListening: () => void, 188 | browserSupportsSpeechRecognition: () => boolean, 189 | browserSupportsContinuousListening: () => boolean, 190 | } 191 | const SpeechRecognition: SpeechRecognitionType = { 192 | counter: 0, 193 | applyPolyfill: (PolyfillSpeechRecognition: SpeechRecognitionClass) => { 194 | console.log("applyPolyfill"); 195 | if (recognitionManager) { 196 | recognitionManager.setSpeechRecognition(PolyfillSpeechRecognition) 197 | } else { 198 | recognitionManager = new RecognitionManager(PolyfillSpeechRecognition) 199 | } 200 | const browserSupportsPolyfill = !!PolyfillSpeechRecognition && browserSupportsPolyfills() 201 | _browserSupportsSpeechRecognition = browserSupportsPolyfill 202 | _browserSupportsContinuousListening = browserSupportsPolyfill 203 | }, 204 | getRecognitionManager: () => { 205 | console.log("getRecognitionManager"); 206 | if (!recognitionManager) { 207 | recognitionManager = new RecognitionManager(NativeSpeechRecognition) 208 | } 209 | return recognitionManager 210 | }, 211 | getRecognition: () => { 212 | console.log("getRecognition"); 213 | const recognitionManager = SpeechRecognition.getRecognitionManager() 214 | return recognitionManager.getRecognition() 215 | }, 216 | startListening: async ({ continuous = false, language = 'en-US' } = {}) => { 217 | console.log("startListening: ", { continuous, language }); 218 | const recognitionManager = SpeechRecognition.getRecognitionManager() 219 | await recognitionManager.startListening({ continuous, language }) 220 | }, 221 | stopListening: async () => { 222 | console.log("Stop listening"); 223 | const recognitionManager = SpeechRecognition.getRecognitionManager() 224 | await recognitionManager.stopListening() 225 | }, 226 | abortListening: async () => { 227 | console.log("Abort listening"); 228 | const recognitionManager = SpeechRecognition.getRecognitionManager() 229 | await recognitionManager.abortListening() 230 | }, 231 | browserSupportsSpeechRecognition: () => _browserSupportsSpeechRecognition, 232 | browserSupportsContinuousListening: () => _browserSupportsContinuousListening 233 | } 234 | 235 | export { useSpeechRecognition } 236 | export default SpeechRecognition -------------------------------------------------------------------------------- /src/lib/components/Button.svelte: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/lib/components/Listen.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 | 15 | 18 | 19 |
20 | -------------------------------------------------------------------------------- /src/lib/components/Stop.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 | 15 | 16 | 17 |
18 | -------------------------------------------------------------------------------- /src/lib/constants.ts: -------------------------------------------------------------------------------- 1 | export const CLEAR_TRANSCRIPT = 'CLEAR_TRANSCRIPT' 2 | export const APPEND_TRANSCRIPT = 'APPEND_TRANSCRIPT' -------------------------------------------------------------------------------- /src/lib/index.ts: -------------------------------------------------------------------------------- 1 | export { default as SpeechRecognition, useSpeechRecognition } from './SpeechRecognition'; -------------------------------------------------------------------------------- /src/lib/isAndroid.ts: -------------------------------------------------------------------------------- 1 | export default () => /(android)/i.test(typeof navigator !== 'undefined' ? navigator.userAgent : '') -------------------------------------------------------------------------------- /src/lib/reducers.ts: -------------------------------------------------------------------------------- 1 | // import { CLEAR_TRANSCRIPT, APPEND_TRANSCRIPT } from './constants' 2 | // import type { TranscriptAction, TranscriptState } from './types' 3 | // import { concatTranscripts } from './utils' 4 | 5 | // const transcriptReducer = (state: TranscriptState, action: TranscriptAction) => { 6 | // switch (action.type) { 7 | // case CLEAR_TRANSCRIPT: 8 | // return { 9 | // interimTranscript: '', 10 | // finalTranscript: '' 11 | // } 12 | // case APPEND_TRANSCRIPT: 13 | // if (!action.payload) action.payload = { interimTranscript: '', finalTranscript: '' } 14 | 15 | // return { 16 | // interimTranscript: action.payload.interimTranscript, 17 | // finalTranscript: concatTranscripts(state.finalTranscript, action.payload.finalTranscript) 18 | // } 19 | // default: 20 | // throw new Error() 21 | // } 22 | // } 23 | 24 | // export { transcriptReducer } 25 | 26 | export { }; -------------------------------------------------------------------------------- /src/lib/stores.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | import { writable, type Subscriber, type Unsubscriber } from 'svelte/store'; 3 | import type { TranscriptAction, TranscriptState } from './types'; 4 | 5 | type Reducer = (state: TranscriptState, action: TranscriptAction) => TranscriptState; 6 | type Dispatch = (action: TranscriptAction) => void; 7 | type Subscribe = { subscribe: (this: void, run: Subscriber) => Unsubscriber }; 8 | export function reducible(state: TranscriptState, reducer: Reducer): [Subscribe, Dispatch] { 9 | const { update, subscribe } = writable(state); 10 | 11 | function dispatch(action: TranscriptAction) { 12 | update(state => reducer(state, action)); 13 | } 14 | 15 | return [{ subscribe }, dispatch]; 16 | } -------------------------------------------------------------------------------- /src/lib/types.ts: -------------------------------------------------------------------------------- 1 | import type { CLEAR_TRANSCRIPT, APPEND_TRANSCRIPT } from './constants' 2 | 3 | type TranscriptAction = { type: typeof CLEAR_TRANSCRIPT | typeof APPEND_TRANSCRIPT, payload?: TranscriptState } 4 | type TranscriptState = { interimTranscript: string, finalTranscript: string } 5 | type Command = { 6 | command: string | string[]; 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | callback: any, 9 | matchInterim?: boolean; 10 | isFuzzyMatch?: boolean; 11 | fuzzyMatchingThreshold?: number; 12 | bestMatchOnly?: boolean; 13 | } 14 | 15 | export type { TranscriptAction, TranscriptState, Command }; -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | /* eslint-disable @typescript-eslint/no-this-alias */ 3 | const debounce = (func: { (newFinalTranscript: string): void; apply?: any }, wait: number | undefined, immediate: boolean, ...rest: undefined[]) => { 4 | let timeout: NodeJS.Timeout | undefined 5 | return () => { 6 | const context = this 7 | const args = [func, wait, immediate, ...rest]; 8 | const later = function () { 9 | timeout = undefined 10 | if (!immediate) func.apply(context, args) 11 | } 12 | const callNow = immediate && !timeout 13 | clearTimeout(timeout) 14 | timeout = setTimeout(later, wait) 15 | if (callNow) func.apply(context, args) 16 | } 17 | } 18 | 19 | const concatTranscripts = (...transcriptParts: string[]) => { 20 | return transcriptParts.map(t => t.trim()).join(' ').trim() 21 | } 22 | 23 | // The command matching code is a modified version of Backbone.Router by Jeremy Ashkenas, under the MIT license. 24 | const optionalParam = /\s*\((.*?)\)\s*/g 25 | const optionalRegex = /(\(\?:[^)]+\))\?/g 26 | const namedParam = /(\(\?)?:\w+/g 27 | const splatParam = /\*/g 28 | const escapeRegExp = /[-{}[\]+?.,\\^$|#]/g 29 | const commandToRegExp = (command: any) => { 30 | if (command instanceof RegExp) { 31 | return new RegExp(command.source, 'i') 32 | } 33 | command = command 34 | .replace(escapeRegExp, '\\$&') 35 | .replace(optionalParam, '(?:$1)?') 36 | .replace(namedParam, (match: any, optional: any) => { 37 | return optional ? match : '([^\\s]+)' 38 | }) 39 | .replace(splatParam, '(.*?)') 40 | .replace(optionalRegex, '\\s*$1?\\s*') 41 | return new RegExp('^' + command + '$', 'i') 42 | } 43 | 44 | // this is from https://github.com/aceakash/string-similarity 45 | const compareTwoStringsUsingDiceCoefficient = (first: string, second: string) => { 46 | first = first.replace(/\s+/g, '').toLowerCase() 47 | second = second.replace(/\s+/g, '').toLowerCase() 48 | 49 | if (!first.length && !second.length) return 1 // if both are empty strings 50 | if (!first.length || !second.length) return 0 // if only one is empty string 51 | if (first === second) return 1 // identical 52 | if (first.length === 1 && second.length === 1) return 0 // both are 1-letter strings 53 | if (first.length < 2 || second.length < 2) return 0 // if either is a 1-letter string 54 | 55 | const firstBigrams = new Map() 56 | for (let i = 0; i < first.length - 1; i++) { 57 | const bigram = first.substring(i, i + 2) 58 | const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) + 1 : 1 59 | 60 | firstBigrams.set(bigram, count) 61 | } 62 | 63 | let intersectionSize = 0 64 | for (let i = 0; i < second.length - 1; i++) { 65 | const bigram = second.substring(i, i + 2) 66 | const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) : 0 67 | 68 | if (count > 0) { 69 | firstBigrams.set(bigram, count - 1) 70 | intersectionSize++ 71 | } 72 | } 73 | 74 | return (2.0 * intersectionSize) / (first.length + second.length - 2) 75 | } 76 | 77 | const browserSupportsPolyfills = () => { 78 | return typeof window !== 'undefined' && 79 | window.navigator !== undefined && 80 | window.navigator.mediaDevices !== undefined && 81 | window.navigator.mediaDevices.getUserMedia !== undefined && 82 | (window.AudioContext !== undefined || window.webkitAudioContext !== undefined) 83 | } 84 | 85 | export { 86 | debounce, 87 | concatTranscripts, 88 | commandToRegExp, 89 | compareTwoStringsUsingDiceCoefficient, 90 | browserSupportsPolyfills 91 | } -------------------------------------------------------------------------------- /src/routes/Dictaphones.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 |
29 | {#if showFirstWidget} 30 | 31 | {/if} 32 | 33 |
34 | 35 | 36 | 37 | 38 | 39 |
40 | 41 |
42 |

Commands to Try

43 |

44 | Some commands to try saying: "YOUR_NAME is my name.", "The weather is CONDITION today.", "My 45 | top sports are TEAM and TEAM", "clear". Look in 46 | src/routes/_Dictaphone/DictaphoneWidgetA.svelte and 47 | src/routes/_Dictaphone/DictaphoneWidgetb.svelte to see more commands and how they work. 48 |

49 |
50 |
51 | 52 | 64 | -------------------------------------------------------------------------------- /src/routes/_Dictaphone/Dictaphone.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | {#if browserSupportsSpeechRecognition} 29 | {#if !isMicrophoneAvailable} 30 | Please allow access to the microphone 31 | {/if} 32 | 33 |
34 |
35 | listening: {$listening ? 'on' : 'off'} 36 | transcribing: {$transcribing ? 'on' : 'off'} 37 | clearTranscriptOnListen: {$clearTranscriptOnListen ? 'on' : 'off'} 38 |
39 | 40 | 41 | 42 | Interim: {$interimTranscript} 43 | Final: {$finalTranscript} 44 |
45 | {:else} 46 | No browser support 47 | {/if} 48 | 49 | 58 | -------------------------------------------------------------------------------- /src/routes/_Dictaphone/DictaphoneWidgetA.svelte: -------------------------------------------------------------------------------- 1 | 47 | 48 |
49 |

Dictaphone A

50 |
51 | Bot Response: {message} 52 |
53 | 54 |
55 | 56 |
57 |
58 | 59 | 71 | -------------------------------------------------------------------------------- /src/routes/_Dictaphone/DictaphoneWidgetB.svelte: -------------------------------------------------------------------------------- 1 | 28 | 29 |
30 |

Dictaphone B

31 |
32 | Bot Response: {message} 33 |
34 | 35 |
36 | 37 |
38 |
39 | 40 | 50 | -------------------------------------------------------------------------------- /src/routes/__layout.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Svelte Speech Recognition 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/routes/components/Dictaphones.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 |
19 | {#if showFirstWidget} 20 | 21 | {/if} 22 | 23 | 24 |
25 | 26 | 27 | 33 |
34 | 35 |
36 | 37 | 38 | 39 |
40 | 41 |
42 |

Commands to Try

43 |

44 | Some commands to try saying: "YOUR_NAME is my name.", "The weather is CONDITION today.", "My 45 | top sports are TEAM and TEAM", "clear". Look in 46 | src/routes/_Dictaphone/DictaphoneWidgetA.svelte and 47 | src/routes/_Dictaphone/DictaphoneWidgetb.svelte to see more commands and how they work. 48 |

49 |
50 |
51 | -------------------------------------------------------------------------------- /src/routes/components/_Dictaphone/Dictaphone.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | {#if browserSupportsSpeechRecognition} 29 | {#if !isMicrophoneAvailable} 30 | Please allow access to the microphone 31 | {/if} 32 | 33 |
34 |
35 | listening: {$listening ? 'on' : 'off'} 36 | transcribing: {$transcribing ? 'on' : 'off'} 37 | clearTranscriptOnListen: {$clearTranscriptOnListen ? 'on' : 'off'} 38 |
39 | 40 | 41 | 42 | Interim: {$interimTranscript} 43 | Final: {$finalTranscript} 44 |
45 | {:else} 46 | No browser support 47 | {/if} 48 | 49 | 57 | -------------------------------------------------------------------------------- /src/routes/components/_Dictaphone/DictaphoneWidgetA.svelte: -------------------------------------------------------------------------------- 1 | 47 | 48 |
49 |

Dictaphone A

50 |
51 | Bot Response: {message} 52 |
53 | 54 |
55 | 56 |
57 |
58 | 59 | 71 | -------------------------------------------------------------------------------- /src/routes/components/_Dictaphone/DictaphoneWidgetB.svelte: -------------------------------------------------------------------------------- 1 | 28 | 29 |
30 |

Dictaphone B

31 |
32 | Bot Response: {message} 33 |
34 | 35 |
36 | 37 |
38 |
39 | 40 | 50 | -------------------------------------------------------------------------------- /src/routes/components/index.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/index.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhubbardsf/svelte-speech-recognition/6e0d028d1b8cd1e81cdeafb8179a59f9c9800015/static/favicon.png -------------------------------------------------------------------------------- /static/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto'; 2 | import preprocess from 'svelte-preprocess'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://github.com/sveltejs/svelte-preprocess 7 | // for more information about preprocessors 8 | preprocess: [ 9 | preprocess({ 10 | postcss: true 11 | }) 12 | ], 13 | 14 | kit: { 15 | adapter: adapter(), 16 | // vite: { 17 | // esbuild: { 18 | // drop: ['console', 'debugger'] 19 | // }, 20 | // }, 21 | // Override http methods in the Todo forms 22 | methodOverride: { 23 | allowed: ['PATCH', 'DELETE'] 24 | } 25 | } 26 | }; 27 | 28 | export default config; 29 | -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | content: ['./src/**/*.{html,js,svelte,ts}'], 3 | 4 | theme: { 5 | extend: {} 6 | }, 7 | 8 | plugins: [] 9 | }; 10 | 11 | module.exports = config; 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | } 13 | } --------------------------------------------------------------------------------