├── .editorconfig
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .prettierrc.json
├── .vscode
└── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── pnpm-lock.yaml
├── src
└── index.ts
├── tests
└── index.test.ts
├── tsconfig.json
└── vitest.config.ts
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{md,markdown}]
2 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - develop
5 | - master
6 |
7 | name: Test Coveralls
8 |
9 | jobs:
10 |
11 | build:
12 | name: Build
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: pnpm/action-setup@v2
16 | with:
17 | version: 8.6.1
18 |
19 | - uses: actions/checkout@v1
20 |
21 | - name: Use Node.js 18.x
22 | uses: actions/setup-node@v1
23 | with:
24 | node-version: 18.x
25 |
26 | - name: pnpm install, make test-coverage
27 | run: |
28 | pnpm install
29 | pnpm run test
30 |
31 | - name: Coveralls
32 | uses: coverallsapp/github-action@master
33 | with:
34 | github-token: ${{ secrets.GITHUB_TOKEN }}
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /node_modules
3 | /coverage
4 | /dist
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 2,
4 | "semi": false,
5 | "singleQuote": true
6 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "markdown.extension.toc.levels": "1..3"
3 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 3.0.0 - BREAKING CHANGES
4 |
5 | - Refactoring to facilitate iterative construction of the corpus (multiple `.addData()` instead of a one-time `buildCorpus()`), and export/import of corpus internal data.
6 |
7 | ## 2.1.0
8 |
9 | - Add an optionnal `prng` parameter at generation to use a specific Pseudo Random Number Generator
10 |
11 | ## 2.0.4
12 |
13 | - Dependencies update
14 |
15 | ## 2.0.0
16 |
17 | - **Refactoring with breaking changes**
18 | - The constructor and generator take two different options objects
19 | - Most of generator options are gone, except `filter` and `maxTries`
20 | - Tests have been rewritten with jest, in TypeScript
21 |
22 | ## 1.5.0
23 |
24 | - Code rewritten in TypeScript. You can now `import MarkovGenerator from 'markov-strings'`
25 |
26 | ## 1.4.0
27 |
28 | - New `filter()` method, thanks @flpvsk
29 |
30 | ## 1.3.4 - 1.3.5
31 |
32 | - Dependencies update
33 |
34 | ## 1.3.3
35 |
36 | - Updated README. Version bump for npm
37 |
38 | ## 1.3.2
39 |
40 | - Fixed an infinite loop bug
41 | - Performance improvement
42 |
43 | ## 1.3.1
44 |
45 | - Updated README example
46 | - Removed a useless line
47 |
48 | ## 1.3.0
49 |
50 | - New feature: the generator now accepts arrays of objects, and tells the user which objects were used to build a sentence
51 | - Fixed all unit tests
52 | - Added a changelog
53 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Simon Cambier
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/scambier/markov-strings)
2 | [](https://coveralls.io/github/scambier/markov-strings?branch=master)
3 | [](https://badge.fury.io/js/markov-strings)
4 |
5 |
6 | ---
7 | ! This is the readme for markov-strings **3.x.x.** - The docs for the older **2.x.x** are [here](https://github.com/scambier/markov-strings/tree/v2) !
8 |
9 | ---
10 |
11 | # Markov-strings
12 |
13 | A simplistic Markov chain text generator.
14 | Give it an array of strings, and it will output a randomly generated string.
15 |
16 | A rust port of this library is available [here](https://github.com/scambier/markov-strings-rust).
17 |
18 | This module was created for the Mastodon bot [@BelgicaNews](https://botsin.space/@BelgicaNews).
19 |
20 | - [Markov-strings](#markov-strings)
21 | - [Prerequisites](#prerequisites)
22 | - [Installing](#installing)
23 | - [Usage](#usage)
24 | - [API](#api)
25 | - [`new Markov([options])`](#new-markovoptions)
26 | - [`.addData(data)`](#adddatadata)
27 | - [`.generate([options])`](#generateoptions)
28 | - [`.export()` and `.import(data)`](#export-and-importdata)
29 | - [Unit tests](#unit-tests)
30 | - [Changelog](#changelog)
31 | - [Running the tests](#running-the-tests)
32 |
33 | ## Prerequisites
34 |
35 | Built and tested with NodeJS 18
36 |
37 | ## Installing
38 |
39 | `npm install --save markov-strings`
40 |
41 | ## Usage
42 |
43 | ```js
44 | import Markov from 'markov-strings'
45 | // Not recommended: you can use `require()` if needed, instead of `import`
46 | // const Markov = require('markov-strings').default
47 |
48 | // Build the Markov generator
49 | const markov = new Markov({ stateSize: 2 })
50 |
51 | // Add data for the generator
52 | const data = [/* insert a few hundreds/thousands sentences here */]
53 | markov.addData(data)
54 |
55 | const options = {
56 | maxTries: 20, // Give up if I don't have a sentence after 20 tries (default is 10)
57 |
58 | // If you want to get seeded results, you can provide an external PRNG.
59 | prng: Math.random, // Default value if left empty
60 |
61 | // You'll often need to manually filter raw results to get something that fits your needs.
62 | filter: (result) => {
63 | return result.string.split(' ').length >= 5 && // At least 5 words
64 | result.string.endsWith('.') // End sentences with a dot.
65 | }
66 | }
67 |
68 | // Generate a sentence
69 | const result = markov.generate(options)
70 | console.log(result)
71 | /*
72 | {
73 | string: 'lorem ipsum dolor sit amet etc.',
74 | score: 42,
75 | tries: 5,
76 | refs: [ an array of objects ]
77 | }
78 | */
79 | ```
80 |
81 | Markov-strings is built in TypeScript, and exports several types to help you. Take a look at [the source](https://github.com/scambier/markov-strings/blob/master/src/index.ts) to see how it works.
82 |
83 | ## API
84 |
85 | ### `new Markov([options])`
86 |
87 | Create a generator instance.
88 |
89 | #### options
90 |
91 | ```js
92 | {
93 | stateSize: number
94 | }
95 | ```
96 |
97 | The `stateSize` is the number of words for each "link" of the generated sentence. `1` will output gibberish sentences without much sense. `2` is a sensible default for most cases. `3` and more can create good sentences if you have a corpus that allows it.
98 |
99 | ### `.addData(data)`
100 |
101 | To function correctly, the Markov generator needs its internal data to be correctly structured. `.addData(data)` allows you add raw data, that is automatically formatted to fit the internal structure.
102 |
103 | You can call `.addData(data)` as often as you need, **with new data each time (!)**. Multiple calls of `.addData()` with the same data is not recommended, because it will skew the random generation of results.
104 |
105 | #### data
106 |
107 | ```js
108 | string[] | Array<{ string: string }>
109 | ```
110 |
111 | `data` is an array of strings (sentences), or an array of objects. If you wish to use objects, each one must have a `string` attribute. The bigger the array, the better and more varied the results.
112 |
113 | Examples:
114 |
115 | ```js
116 | [ 'lorem ipsum', 'dolor sit amet' ]
117 | ```
118 |
119 | or
120 |
121 | ```js
122 | [
123 | { string: 'lorem ipsum', attr: 'value' },
124 | { string: 'dolor sit amet', attr: 'other value' }
125 | ]
126 | ```
127 |
128 | The additionnal data passed with objects will be returned in the `refs` array of the generated sentence.
129 |
130 | ### `.generate([options])`
131 |
132 | Returns an object of type `MarkovResult`:
133 |
134 | ```ts
135 | {
136 | string: string, // The resulting sentence
137 | score: number, // A relative "score" based on the number of possible permutations. Higher is "better", but the actual value depends on your corpus
138 | refs: Array<{ string: string }>, // The array of references used to build the sentence
139 | tries: number // The number of tries it took to output this result
140 | }
141 | ```
142 |
143 | The `refs` array will contain all objects that have been used to build the sentence. May be useful to fetch meta data or make stats.
144 |
145 | #### options
146 |
147 | ```ts
148 | {
149 | maxTries: number // The max number of tentatives before giving up (default is 10)
150 | prng: Math.random, // An external Pseudo Random Number Generator if you want to get seeded results
151 | filter: (result: MarkovResult) => boolean // A callback to filter results (see example above)
152 | }
153 | ```
154 |
155 | ### `.export()` and `.import(data)`
156 |
157 | You can export and import the markov built corpus. The exported data is a serializable object, and must be deserialized before being re-imported.
158 |
159 | [Example use-case](https://github.com/scambier/markov-strings/issues/9)
160 |
161 | ## Running the tests
162 |
163 | `npm test`
164 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "markov-strings",
3 | "version": "3.0.2",
4 | "description": "A Markov string generator",
5 | "main": "dist/index.js",
6 | "files": [
7 | "dist"
8 | ],
9 | "scripts": {
10 | "dev": "tsc --watch",
11 | "build": "tsc",
12 | "test": "vitest run --coverage"
13 | },
14 | "engines": {
15 | "node": ">=8.0.0"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/scambier/markov-strings"
20 | },
21 | "keywords": [
22 | "markov",
23 | "string",
24 | "chain",
25 | "procedural",
26 | "generation",
27 | "text"
28 | ],
29 | "author": "scambier",
30 | "license": "MIT",
31 | "devDependencies": {
32 | "@types/lodash": "^4.17.13",
33 | "@types/lodash-es": "^4.17.12",
34 | "@types/node": "^22.10.4",
35 | "@vitest/coverage-v8": "2.1.8",
36 | "coveralls": "^3.1.1",
37 | "prettier": "^3.4.2",
38 | "typescript": "^5.7.2",
39 | "vitest": "^2.1.8"
40 | },
41 | "dependencies": {
42 | "lodash-es": "^4.17.21"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | dependencies:
11 | lodash-es:
12 | specifier: ^4.17.21
13 | version: 4.17.21
14 | devDependencies:
15 | '@types/lodash':
16 | specifier: ^4.17.13
17 | version: 4.17.13
18 | '@types/lodash-es':
19 | specifier: ^4.17.12
20 | version: 4.17.12
21 | '@types/node':
22 | specifier: ^22.10.4
23 | version: 22.10.4
24 | '@vitest/coverage-v8':
25 | specifier: 2.1.8
26 | version: 2.1.8(vitest@2.1.8(@types/node@22.10.4))
27 | coveralls:
28 | specifier: ^3.1.1
29 | version: 3.1.1
30 | prettier:
31 | specifier: ^3.4.2
32 | version: 3.4.2
33 | typescript:
34 | specifier: ^5.7.2
35 | version: 5.7.2
36 | vitest:
37 | specifier: ^2.1.8
38 | version: 2.1.8(@types/node@22.10.4)
39 |
40 | packages:
41 |
42 | '@ampproject/remapping@2.3.0':
43 | resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
44 | engines: {node: '>=6.0.0'}
45 |
46 | '@babel/helper-string-parser@7.25.9':
47 | resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
48 | engines: {node: '>=6.9.0'}
49 |
50 | '@babel/helper-validator-identifier@7.25.9':
51 | resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
52 | engines: {node: '>=6.9.0'}
53 |
54 | '@babel/parser@7.26.3':
55 | resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==}
56 | engines: {node: '>=6.0.0'}
57 | hasBin: true
58 |
59 | '@babel/types@7.26.3':
60 | resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==}
61 | engines: {node: '>=6.9.0'}
62 |
63 | '@bcoe/v8-coverage@0.2.3':
64 | resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
65 |
66 | '@esbuild/aix-ppc64@0.21.5':
67 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
68 | engines: {node: '>=12'}
69 | cpu: [ppc64]
70 | os: [aix]
71 |
72 | '@esbuild/android-arm64@0.21.5':
73 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
74 | engines: {node: '>=12'}
75 | cpu: [arm64]
76 | os: [android]
77 |
78 | '@esbuild/android-arm@0.21.5':
79 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
80 | engines: {node: '>=12'}
81 | cpu: [arm]
82 | os: [android]
83 |
84 | '@esbuild/android-x64@0.21.5':
85 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
86 | engines: {node: '>=12'}
87 | cpu: [x64]
88 | os: [android]
89 |
90 | '@esbuild/darwin-arm64@0.21.5':
91 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
92 | engines: {node: '>=12'}
93 | cpu: [arm64]
94 | os: [darwin]
95 |
96 | '@esbuild/darwin-x64@0.21.5':
97 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
98 | engines: {node: '>=12'}
99 | cpu: [x64]
100 | os: [darwin]
101 |
102 | '@esbuild/freebsd-arm64@0.21.5':
103 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
104 | engines: {node: '>=12'}
105 | cpu: [arm64]
106 | os: [freebsd]
107 |
108 | '@esbuild/freebsd-x64@0.21.5':
109 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
110 | engines: {node: '>=12'}
111 | cpu: [x64]
112 | os: [freebsd]
113 |
114 | '@esbuild/linux-arm64@0.21.5':
115 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
116 | engines: {node: '>=12'}
117 | cpu: [arm64]
118 | os: [linux]
119 |
120 | '@esbuild/linux-arm@0.21.5':
121 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
122 | engines: {node: '>=12'}
123 | cpu: [arm]
124 | os: [linux]
125 |
126 | '@esbuild/linux-ia32@0.21.5':
127 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
128 | engines: {node: '>=12'}
129 | cpu: [ia32]
130 | os: [linux]
131 |
132 | '@esbuild/linux-loong64@0.21.5':
133 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
134 | engines: {node: '>=12'}
135 | cpu: [loong64]
136 | os: [linux]
137 |
138 | '@esbuild/linux-mips64el@0.21.5':
139 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
140 | engines: {node: '>=12'}
141 | cpu: [mips64el]
142 | os: [linux]
143 |
144 | '@esbuild/linux-ppc64@0.21.5':
145 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
146 | engines: {node: '>=12'}
147 | cpu: [ppc64]
148 | os: [linux]
149 |
150 | '@esbuild/linux-riscv64@0.21.5':
151 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
152 | engines: {node: '>=12'}
153 | cpu: [riscv64]
154 | os: [linux]
155 |
156 | '@esbuild/linux-s390x@0.21.5':
157 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
158 | engines: {node: '>=12'}
159 | cpu: [s390x]
160 | os: [linux]
161 |
162 | '@esbuild/linux-x64@0.21.5':
163 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
164 | engines: {node: '>=12'}
165 | cpu: [x64]
166 | os: [linux]
167 |
168 | '@esbuild/netbsd-x64@0.21.5':
169 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
170 | engines: {node: '>=12'}
171 | cpu: [x64]
172 | os: [netbsd]
173 |
174 | '@esbuild/openbsd-x64@0.21.5':
175 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
176 | engines: {node: '>=12'}
177 | cpu: [x64]
178 | os: [openbsd]
179 |
180 | '@esbuild/sunos-x64@0.21.5':
181 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
182 | engines: {node: '>=12'}
183 | cpu: [x64]
184 | os: [sunos]
185 |
186 | '@esbuild/win32-arm64@0.21.5':
187 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
188 | engines: {node: '>=12'}
189 | cpu: [arm64]
190 | os: [win32]
191 |
192 | '@esbuild/win32-ia32@0.21.5':
193 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
194 | engines: {node: '>=12'}
195 | cpu: [ia32]
196 | os: [win32]
197 |
198 | '@esbuild/win32-x64@0.21.5':
199 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
200 | engines: {node: '>=12'}
201 | cpu: [x64]
202 | os: [win32]
203 |
204 | '@isaacs/cliui@8.0.2':
205 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
206 | engines: {node: '>=12'}
207 |
208 | '@istanbuljs/schema@0.1.3':
209 | resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
210 | engines: {node: '>=8'}
211 |
212 | '@jridgewell/gen-mapping@0.3.8':
213 | resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
214 | engines: {node: '>=6.0.0'}
215 |
216 | '@jridgewell/resolve-uri@3.1.2':
217 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
218 | engines: {node: '>=6.0.0'}
219 |
220 | '@jridgewell/set-array@1.2.1':
221 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
222 | engines: {node: '>=6.0.0'}
223 |
224 | '@jridgewell/sourcemap-codec@1.5.0':
225 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
226 |
227 | '@jridgewell/trace-mapping@0.3.25':
228 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
229 |
230 | '@pkgjs/parseargs@0.11.0':
231 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
232 | engines: {node: '>=14'}
233 |
234 | '@rollup/rollup-android-arm-eabi@4.29.1':
235 | resolution: {integrity: sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==}
236 | cpu: [arm]
237 | os: [android]
238 |
239 | '@rollup/rollup-android-arm64@4.29.1':
240 | resolution: {integrity: sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==}
241 | cpu: [arm64]
242 | os: [android]
243 |
244 | '@rollup/rollup-darwin-arm64@4.29.1':
245 | resolution: {integrity: sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==}
246 | cpu: [arm64]
247 | os: [darwin]
248 |
249 | '@rollup/rollup-darwin-x64@4.29.1':
250 | resolution: {integrity: sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==}
251 | cpu: [x64]
252 | os: [darwin]
253 |
254 | '@rollup/rollup-freebsd-arm64@4.29.1':
255 | resolution: {integrity: sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==}
256 | cpu: [arm64]
257 | os: [freebsd]
258 |
259 | '@rollup/rollup-freebsd-x64@4.29.1':
260 | resolution: {integrity: sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==}
261 | cpu: [x64]
262 | os: [freebsd]
263 |
264 | '@rollup/rollup-linux-arm-gnueabihf@4.29.1':
265 | resolution: {integrity: sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==}
266 | cpu: [arm]
267 | os: [linux]
268 |
269 | '@rollup/rollup-linux-arm-musleabihf@4.29.1':
270 | resolution: {integrity: sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==}
271 | cpu: [arm]
272 | os: [linux]
273 |
274 | '@rollup/rollup-linux-arm64-gnu@4.29.1':
275 | resolution: {integrity: sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==}
276 | cpu: [arm64]
277 | os: [linux]
278 |
279 | '@rollup/rollup-linux-arm64-musl@4.29.1':
280 | resolution: {integrity: sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==}
281 | cpu: [arm64]
282 | os: [linux]
283 |
284 | '@rollup/rollup-linux-loongarch64-gnu@4.29.1':
285 | resolution: {integrity: sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==}
286 | cpu: [loong64]
287 | os: [linux]
288 |
289 | '@rollup/rollup-linux-powerpc64le-gnu@4.29.1':
290 | resolution: {integrity: sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==}
291 | cpu: [ppc64]
292 | os: [linux]
293 |
294 | '@rollup/rollup-linux-riscv64-gnu@4.29.1':
295 | resolution: {integrity: sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==}
296 | cpu: [riscv64]
297 | os: [linux]
298 |
299 | '@rollup/rollup-linux-s390x-gnu@4.29.1':
300 | resolution: {integrity: sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==}
301 | cpu: [s390x]
302 | os: [linux]
303 |
304 | '@rollup/rollup-linux-x64-gnu@4.29.1':
305 | resolution: {integrity: sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==}
306 | cpu: [x64]
307 | os: [linux]
308 |
309 | '@rollup/rollup-linux-x64-musl@4.29.1':
310 | resolution: {integrity: sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==}
311 | cpu: [x64]
312 | os: [linux]
313 |
314 | '@rollup/rollup-win32-arm64-msvc@4.29.1':
315 | resolution: {integrity: sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==}
316 | cpu: [arm64]
317 | os: [win32]
318 |
319 | '@rollup/rollup-win32-ia32-msvc@4.29.1':
320 | resolution: {integrity: sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==}
321 | cpu: [ia32]
322 | os: [win32]
323 |
324 | '@rollup/rollup-win32-x64-msvc@4.29.1':
325 | resolution: {integrity: sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==}
326 | cpu: [x64]
327 | os: [win32]
328 |
329 | '@types/estree@1.0.6':
330 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
331 |
332 | '@types/lodash-es@4.17.12':
333 | resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
334 |
335 | '@types/lodash@4.17.13':
336 | resolution: {integrity: sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==}
337 |
338 | '@types/node@22.10.4':
339 | resolution: {integrity: sha512-99l6wv4HEzBQhvaU/UGoeBoCK61SCROQaCCGyQSgX2tEQ3rKkNZ2S7CEWnS/4s1LV+8ODdK21UeyR1fHP2mXug==}
340 |
341 | '@vitest/coverage-v8@2.1.8':
342 | resolution: {integrity: sha512-2Y7BPlKH18mAZYAW1tYByudlCYrQyl5RGvnnDYJKW5tCiO5qg3KSAy3XAxcxKz900a0ZXxWtKrMuZLe3lKBpJw==}
343 | peerDependencies:
344 | '@vitest/browser': 2.1.8
345 | vitest: 2.1.8
346 | peerDependenciesMeta:
347 | '@vitest/browser':
348 | optional: true
349 |
350 | '@vitest/expect@2.1.8':
351 | resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==}
352 |
353 | '@vitest/mocker@2.1.8':
354 | resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==}
355 | peerDependencies:
356 | msw: ^2.4.9
357 | vite: ^5.0.0
358 | peerDependenciesMeta:
359 | msw:
360 | optional: true
361 | vite:
362 | optional: true
363 |
364 | '@vitest/pretty-format@2.1.8':
365 | resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==}
366 |
367 | '@vitest/runner@2.1.8':
368 | resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==}
369 |
370 | '@vitest/snapshot@2.1.8':
371 | resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==}
372 |
373 | '@vitest/spy@2.1.8':
374 | resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==}
375 |
376 | '@vitest/utils@2.1.8':
377 | resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==}
378 |
379 | ajv@6.12.6:
380 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
381 |
382 | ansi-regex@5.0.1:
383 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
384 | engines: {node: '>=8'}
385 |
386 | ansi-regex@6.1.0:
387 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
388 | engines: {node: '>=12'}
389 |
390 | ansi-styles@4.3.0:
391 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
392 | engines: {node: '>=8'}
393 |
394 | ansi-styles@6.2.1:
395 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
396 | engines: {node: '>=12'}
397 |
398 | argparse@1.0.10:
399 | resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
400 |
401 | asn1@0.2.6:
402 | resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
403 |
404 | assert-plus@1.0.0:
405 | resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
406 | engines: {node: '>=0.8'}
407 |
408 | assertion-error@2.0.1:
409 | resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
410 | engines: {node: '>=12'}
411 |
412 | asynckit@0.4.0:
413 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
414 |
415 | aws-sign2@0.7.0:
416 | resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==}
417 |
418 | aws4@1.13.2:
419 | resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==}
420 |
421 | balanced-match@1.0.2:
422 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
423 |
424 | bcrypt-pbkdf@1.0.2:
425 | resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
426 |
427 | brace-expansion@2.0.1:
428 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
429 |
430 | cac@6.7.14:
431 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
432 | engines: {node: '>=8'}
433 |
434 | caseless@0.12.0:
435 | resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
436 |
437 | chai@5.1.2:
438 | resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==}
439 | engines: {node: '>=12'}
440 |
441 | check-error@2.1.1:
442 | resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
443 | engines: {node: '>= 16'}
444 |
445 | color-convert@2.0.1:
446 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
447 | engines: {node: '>=7.0.0'}
448 |
449 | color-name@1.1.4:
450 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
451 |
452 | combined-stream@1.0.8:
453 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
454 | engines: {node: '>= 0.8'}
455 |
456 | core-util-is@1.0.2:
457 | resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
458 |
459 | coveralls@3.1.1:
460 | resolution: {integrity: sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==}
461 | engines: {node: '>=6'}
462 | hasBin: true
463 |
464 | cross-spawn@7.0.6:
465 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
466 | engines: {node: '>= 8'}
467 |
468 | dashdash@1.14.1:
469 | resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
470 | engines: {node: '>=0.10'}
471 |
472 | debug@4.4.0:
473 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
474 | engines: {node: '>=6.0'}
475 | peerDependencies:
476 | supports-color: '*'
477 | peerDependenciesMeta:
478 | supports-color:
479 | optional: true
480 |
481 | deep-eql@5.0.2:
482 | resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
483 | engines: {node: '>=6'}
484 |
485 | delayed-stream@1.0.0:
486 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
487 | engines: {node: '>=0.4.0'}
488 |
489 | eastasianwidth@0.2.0:
490 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
491 |
492 | ecc-jsbn@0.1.2:
493 | resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
494 |
495 | emoji-regex@8.0.0:
496 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
497 |
498 | emoji-regex@9.2.2:
499 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
500 |
501 | es-module-lexer@1.6.0:
502 | resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==}
503 |
504 | esbuild@0.21.5:
505 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
506 | engines: {node: '>=12'}
507 | hasBin: true
508 |
509 | esprima@4.0.1:
510 | resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
511 | engines: {node: '>=4'}
512 | hasBin: true
513 |
514 | estree-walker@3.0.3:
515 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
516 |
517 | expect-type@1.1.0:
518 | resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==}
519 | engines: {node: '>=12.0.0'}
520 |
521 | extend@3.0.2:
522 | resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
523 |
524 | extsprintf@1.3.0:
525 | resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==}
526 | engines: {'0': node >=0.6.0}
527 |
528 | fast-deep-equal@3.1.3:
529 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
530 |
531 | fast-json-stable-stringify@2.1.0:
532 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
533 |
534 | foreground-child@3.3.0:
535 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
536 | engines: {node: '>=14'}
537 |
538 | forever-agent@0.6.1:
539 | resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
540 |
541 | form-data@2.3.3:
542 | resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==}
543 | engines: {node: '>= 0.12'}
544 |
545 | fsevents@2.3.3:
546 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
547 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
548 | os: [darwin]
549 |
550 | getpass@0.1.7:
551 | resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
552 |
553 | glob@10.4.5:
554 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
555 | hasBin: true
556 |
557 | har-schema@2.0.0:
558 | resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==}
559 | engines: {node: '>=4'}
560 |
561 | har-validator@5.1.5:
562 | resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==}
563 | engines: {node: '>=6'}
564 | deprecated: this library is no longer supported
565 |
566 | has-flag@4.0.0:
567 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
568 | engines: {node: '>=8'}
569 |
570 | html-escaper@2.0.2:
571 | resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
572 |
573 | http-signature@1.2.0:
574 | resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==}
575 | engines: {node: '>=0.8', npm: '>=1.3.7'}
576 |
577 | is-fullwidth-code-point@3.0.0:
578 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
579 | engines: {node: '>=8'}
580 |
581 | is-typedarray@1.0.0:
582 | resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
583 |
584 | isexe@2.0.0:
585 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
586 |
587 | isstream@0.1.2:
588 | resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==}
589 |
590 | istanbul-lib-coverage@3.2.2:
591 | resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
592 | engines: {node: '>=8'}
593 |
594 | istanbul-lib-report@3.0.1:
595 | resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
596 | engines: {node: '>=10'}
597 |
598 | istanbul-lib-source-maps@5.0.6:
599 | resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==}
600 | engines: {node: '>=10'}
601 |
602 | istanbul-reports@3.1.7:
603 | resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
604 | engines: {node: '>=8'}
605 |
606 | jackspeak@3.4.3:
607 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
608 |
609 | js-yaml@3.14.1:
610 | resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
611 | hasBin: true
612 |
613 | jsbn@0.1.1:
614 | resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
615 |
616 | json-schema-traverse@0.4.1:
617 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
618 |
619 | json-schema@0.4.0:
620 | resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
621 |
622 | json-stringify-safe@5.0.1:
623 | resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
624 |
625 | jsprim@1.4.2:
626 | resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
627 | engines: {node: '>=0.6.0'}
628 |
629 | lcov-parse@1.0.0:
630 | resolution: {integrity: sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==}
631 | hasBin: true
632 |
633 | lodash-es@4.17.21:
634 | resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
635 |
636 | log-driver@1.2.7:
637 | resolution: {integrity: sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==}
638 | engines: {node: '>=0.8.6'}
639 |
640 | loupe@3.1.2:
641 | resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==}
642 |
643 | lru-cache@10.4.3:
644 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
645 |
646 | magic-string@0.30.17:
647 | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
648 |
649 | magicast@0.3.5:
650 | resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
651 |
652 | make-dir@4.0.0:
653 | resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
654 | engines: {node: '>=10'}
655 |
656 | mime-db@1.52.0:
657 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
658 | engines: {node: '>= 0.6'}
659 |
660 | mime-types@2.1.35:
661 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
662 | engines: {node: '>= 0.6'}
663 |
664 | minimatch@9.0.5:
665 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
666 | engines: {node: '>=16 || 14 >=14.17'}
667 |
668 | minimist@1.2.8:
669 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
670 |
671 | minipass@7.1.2:
672 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
673 | engines: {node: '>=16 || 14 >=14.17'}
674 |
675 | ms@2.1.3:
676 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
677 |
678 | nanoid@3.3.8:
679 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
680 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
681 | hasBin: true
682 |
683 | oauth-sign@0.9.0:
684 | resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==}
685 |
686 | package-json-from-dist@1.0.1:
687 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
688 |
689 | path-key@3.1.1:
690 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
691 | engines: {node: '>=8'}
692 |
693 | path-scurry@1.11.1:
694 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
695 | engines: {node: '>=16 || 14 >=14.18'}
696 |
697 | pathe@1.1.2:
698 | resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
699 |
700 | pathval@2.0.0:
701 | resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
702 | engines: {node: '>= 14.16'}
703 |
704 | performance-now@2.1.0:
705 | resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
706 |
707 | picocolors@1.1.1:
708 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
709 |
710 | postcss@8.4.49:
711 | resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
712 | engines: {node: ^10 || ^12 || >=14}
713 |
714 | prettier@3.4.2:
715 | resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==}
716 | engines: {node: '>=14'}
717 | hasBin: true
718 |
719 | psl@1.15.0:
720 | resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
721 |
722 | punycode@2.3.1:
723 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
724 | engines: {node: '>=6'}
725 |
726 | qs@6.5.3:
727 | resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==}
728 | engines: {node: '>=0.6'}
729 |
730 | request@2.88.2:
731 | resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
732 | engines: {node: '>= 6'}
733 | deprecated: request has been deprecated, see https://github.com/request/request/issues/3142
734 |
735 | rollup@4.29.1:
736 | resolution: {integrity: sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==}
737 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
738 | hasBin: true
739 |
740 | safe-buffer@5.2.1:
741 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
742 |
743 | safer-buffer@2.1.2:
744 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
745 |
746 | semver@7.6.3:
747 | resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
748 | engines: {node: '>=10'}
749 | hasBin: true
750 |
751 | shebang-command@2.0.0:
752 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
753 | engines: {node: '>=8'}
754 |
755 | shebang-regex@3.0.0:
756 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
757 | engines: {node: '>=8'}
758 |
759 | siginfo@2.0.0:
760 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
761 |
762 | signal-exit@4.1.0:
763 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
764 | engines: {node: '>=14'}
765 |
766 | source-map-js@1.2.1:
767 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
768 | engines: {node: '>=0.10.0'}
769 |
770 | sprintf-js@1.0.3:
771 | resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
772 |
773 | sshpk@1.18.0:
774 | resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==}
775 | engines: {node: '>=0.10.0'}
776 | hasBin: true
777 |
778 | stackback@0.0.2:
779 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
780 |
781 | std-env@3.8.0:
782 | resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==}
783 |
784 | string-width@4.2.3:
785 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
786 | engines: {node: '>=8'}
787 |
788 | string-width@5.1.2:
789 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
790 | engines: {node: '>=12'}
791 |
792 | strip-ansi@6.0.1:
793 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
794 | engines: {node: '>=8'}
795 |
796 | strip-ansi@7.1.0:
797 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
798 | engines: {node: '>=12'}
799 |
800 | supports-color@7.2.0:
801 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
802 | engines: {node: '>=8'}
803 |
804 | test-exclude@7.0.1:
805 | resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
806 | engines: {node: '>=18'}
807 |
808 | tinybench@2.9.0:
809 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
810 |
811 | tinyexec@0.3.2:
812 | resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
813 |
814 | tinypool@1.0.2:
815 | resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==}
816 | engines: {node: ^18.0.0 || >=20.0.0}
817 |
818 | tinyrainbow@1.2.0:
819 | resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
820 | engines: {node: '>=14.0.0'}
821 |
822 | tinyspy@3.0.2:
823 | resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
824 | engines: {node: '>=14.0.0'}
825 |
826 | tough-cookie@2.5.0:
827 | resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==}
828 | engines: {node: '>=0.8'}
829 |
830 | tunnel-agent@0.6.0:
831 | resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
832 |
833 | tweetnacl@0.14.5:
834 | resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
835 |
836 | typescript@5.7.2:
837 | resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==}
838 | engines: {node: '>=14.17'}
839 | hasBin: true
840 |
841 | undici-types@6.20.0:
842 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
843 |
844 | uri-js@4.4.1:
845 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
846 |
847 | uuid@3.4.0:
848 | resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
849 | deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
850 | hasBin: true
851 |
852 | verror@1.10.0:
853 | resolution: {integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=}
854 | engines: {'0': node >=0.6.0}
855 |
856 | vite-node@2.1.8:
857 | resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==}
858 | engines: {node: ^18.0.0 || >=20.0.0}
859 | hasBin: true
860 |
861 | vite@5.4.11:
862 | resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==}
863 | engines: {node: ^18.0.0 || >=20.0.0}
864 | hasBin: true
865 | peerDependencies:
866 | '@types/node': ^18.0.0 || >=20.0.0
867 | less: '*'
868 | lightningcss: ^1.21.0
869 | sass: '*'
870 | sass-embedded: '*'
871 | stylus: '*'
872 | sugarss: '*'
873 | terser: ^5.4.0
874 | peerDependenciesMeta:
875 | '@types/node':
876 | optional: true
877 | less:
878 | optional: true
879 | lightningcss:
880 | optional: true
881 | sass:
882 | optional: true
883 | sass-embedded:
884 | optional: true
885 | stylus:
886 | optional: true
887 | sugarss:
888 | optional: true
889 | terser:
890 | optional: true
891 |
892 | vitest@2.1.8:
893 | resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==}
894 | engines: {node: ^18.0.0 || >=20.0.0}
895 | hasBin: true
896 | peerDependencies:
897 | '@edge-runtime/vm': '*'
898 | '@types/node': ^18.0.0 || >=20.0.0
899 | '@vitest/browser': 2.1.8
900 | '@vitest/ui': 2.1.8
901 | happy-dom: '*'
902 | jsdom: '*'
903 | peerDependenciesMeta:
904 | '@edge-runtime/vm':
905 | optional: true
906 | '@types/node':
907 | optional: true
908 | '@vitest/browser':
909 | optional: true
910 | '@vitest/ui':
911 | optional: true
912 | happy-dom:
913 | optional: true
914 | jsdom:
915 | optional: true
916 |
917 | which@2.0.2:
918 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
919 | engines: {node: '>= 8'}
920 | hasBin: true
921 |
922 | why-is-node-running@2.3.0:
923 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
924 | engines: {node: '>=8'}
925 | hasBin: true
926 |
927 | wrap-ansi@7.0.0:
928 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
929 | engines: {node: '>=10'}
930 |
931 | wrap-ansi@8.1.0:
932 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
933 | engines: {node: '>=12'}
934 |
935 | snapshots:
936 |
937 | '@ampproject/remapping@2.3.0':
938 | dependencies:
939 | '@jridgewell/gen-mapping': 0.3.8
940 | '@jridgewell/trace-mapping': 0.3.25
941 |
942 | '@babel/helper-string-parser@7.25.9': {}
943 |
944 | '@babel/helper-validator-identifier@7.25.9': {}
945 |
946 | '@babel/parser@7.26.3':
947 | dependencies:
948 | '@babel/types': 7.26.3
949 |
950 | '@babel/types@7.26.3':
951 | dependencies:
952 | '@babel/helper-string-parser': 7.25.9
953 | '@babel/helper-validator-identifier': 7.25.9
954 |
955 | '@bcoe/v8-coverage@0.2.3': {}
956 |
957 | '@esbuild/aix-ppc64@0.21.5':
958 | optional: true
959 |
960 | '@esbuild/android-arm64@0.21.5':
961 | optional: true
962 |
963 | '@esbuild/android-arm@0.21.5':
964 | optional: true
965 |
966 | '@esbuild/android-x64@0.21.5':
967 | optional: true
968 |
969 | '@esbuild/darwin-arm64@0.21.5':
970 | optional: true
971 |
972 | '@esbuild/darwin-x64@0.21.5':
973 | optional: true
974 |
975 | '@esbuild/freebsd-arm64@0.21.5':
976 | optional: true
977 |
978 | '@esbuild/freebsd-x64@0.21.5':
979 | optional: true
980 |
981 | '@esbuild/linux-arm64@0.21.5':
982 | optional: true
983 |
984 | '@esbuild/linux-arm@0.21.5':
985 | optional: true
986 |
987 | '@esbuild/linux-ia32@0.21.5':
988 | optional: true
989 |
990 | '@esbuild/linux-loong64@0.21.5':
991 | optional: true
992 |
993 | '@esbuild/linux-mips64el@0.21.5':
994 | optional: true
995 |
996 | '@esbuild/linux-ppc64@0.21.5':
997 | optional: true
998 |
999 | '@esbuild/linux-riscv64@0.21.5':
1000 | optional: true
1001 |
1002 | '@esbuild/linux-s390x@0.21.5':
1003 | optional: true
1004 |
1005 | '@esbuild/linux-x64@0.21.5':
1006 | optional: true
1007 |
1008 | '@esbuild/netbsd-x64@0.21.5':
1009 | optional: true
1010 |
1011 | '@esbuild/openbsd-x64@0.21.5':
1012 | optional: true
1013 |
1014 | '@esbuild/sunos-x64@0.21.5':
1015 | optional: true
1016 |
1017 | '@esbuild/win32-arm64@0.21.5':
1018 | optional: true
1019 |
1020 | '@esbuild/win32-ia32@0.21.5':
1021 | optional: true
1022 |
1023 | '@esbuild/win32-x64@0.21.5':
1024 | optional: true
1025 |
1026 | '@isaacs/cliui@8.0.2':
1027 | dependencies:
1028 | string-width: 5.1.2
1029 | string-width-cjs: string-width@4.2.3
1030 | strip-ansi: 7.1.0
1031 | strip-ansi-cjs: strip-ansi@6.0.1
1032 | wrap-ansi: 8.1.0
1033 | wrap-ansi-cjs: wrap-ansi@7.0.0
1034 |
1035 | '@istanbuljs/schema@0.1.3': {}
1036 |
1037 | '@jridgewell/gen-mapping@0.3.8':
1038 | dependencies:
1039 | '@jridgewell/set-array': 1.2.1
1040 | '@jridgewell/sourcemap-codec': 1.5.0
1041 | '@jridgewell/trace-mapping': 0.3.25
1042 |
1043 | '@jridgewell/resolve-uri@3.1.2': {}
1044 |
1045 | '@jridgewell/set-array@1.2.1': {}
1046 |
1047 | '@jridgewell/sourcemap-codec@1.5.0': {}
1048 |
1049 | '@jridgewell/trace-mapping@0.3.25':
1050 | dependencies:
1051 | '@jridgewell/resolve-uri': 3.1.2
1052 | '@jridgewell/sourcemap-codec': 1.5.0
1053 |
1054 | '@pkgjs/parseargs@0.11.0':
1055 | optional: true
1056 |
1057 | '@rollup/rollup-android-arm-eabi@4.29.1':
1058 | optional: true
1059 |
1060 | '@rollup/rollup-android-arm64@4.29.1':
1061 | optional: true
1062 |
1063 | '@rollup/rollup-darwin-arm64@4.29.1':
1064 | optional: true
1065 |
1066 | '@rollup/rollup-darwin-x64@4.29.1':
1067 | optional: true
1068 |
1069 | '@rollup/rollup-freebsd-arm64@4.29.1':
1070 | optional: true
1071 |
1072 | '@rollup/rollup-freebsd-x64@4.29.1':
1073 | optional: true
1074 |
1075 | '@rollup/rollup-linux-arm-gnueabihf@4.29.1':
1076 | optional: true
1077 |
1078 | '@rollup/rollup-linux-arm-musleabihf@4.29.1':
1079 | optional: true
1080 |
1081 | '@rollup/rollup-linux-arm64-gnu@4.29.1':
1082 | optional: true
1083 |
1084 | '@rollup/rollup-linux-arm64-musl@4.29.1':
1085 | optional: true
1086 |
1087 | '@rollup/rollup-linux-loongarch64-gnu@4.29.1':
1088 | optional: true
1089 |
1090 | '@rollup/rollup-linux-powerpc64le-gnu@4.29.1':
1091 | optional: true
1092 |
1093 | '@rollup/rollup-linux-riscv64-gnu@4.29.1':
1094 | optional: true
1095 |
1096 | '@rollup/rollup-linux-s390x-gnu@4.29.1':
1097 | optional: true
1098 |
1099 | '@rollup/rollup-linux-x64-gnu@4.29.1':
1100 | optional: true
1101 |
1102 | '@rollup/rollup-linux-x64-musl@4.29.1':
1103 | optional: true
1104 |
1105 | '@rollup/rollup-win32-arm64-msvc@4.29.1':
1106 | optional: true
1107 |
1108 | '@rollup/rollup-win32-ia32-msvc@4.29.1':
1109 | optional: true
1110 |
1111 | '@rollup/rollup-win32-x64-msvc@4.29.1':
1112 | optional: true
1113 |
1114 | '@types/estree@1.0.6': {}
1115 |
1116 | '@types/lodash-es@4.17.12':
1117 | dependencies:
1118 | '@types/lodash': 4.17.13
1119 |
1120 | '@types/lodash@4.17.13': {}
1121 |
1122 | '@types/node@22.10.4':
1123 | dependencies:
1124 | undici-types: 6.20.0
1125 |
1126 | '@vitest/coverage-v8@2.1.8(vitest@2.1.8(@types/node@22.10.4))':
1127 | dependencies:
1128 | '@ampproject/remapping': 2.3.0
1129 | '@bcoe/v8-coverage': 0.2.3
1130 | debug: 4.4.0
1131 | istanbul-lib-coverage: 3.2.2
1132 | istanbul-lib-report: 3.0.1
1133 | istanbul-lib-source-maps: 5.0.6
1134 | istanbul-reports: 3.1.7
1135 | magic-string: 0.30.17
1136 | magicast: 0.3.5
1137 | std-env: 3.8.0
1138 | test-exclude: 7.0.1
1139 | tinyrainbow: 1.2.0
1140 | vitest: 2.1.8(@types/node@22.10.4)
1141 | transitivePeerDependencies:
1142 | - supports-color
1143 |
1144 | '@vitest/expect@2.1.8':
1145 | dependencies:
1146 | '@vitest/spy': 2.1.8
1147 | '@vitest/utils': 2.1.8
1148 | chai: 5.1.2
1149 | tinyrainbow: 1.2.0
1150 |
1151 | '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.4))':
1152 | dependencies:
1153 | '@vitest/spy': 2.1.8
1154 | estree-walker: 3.0.3
1155 | magic-string: 0.30.17
1156 | optionalDependencies:
1157 | vite: 5.4.11(@types/node@22.10.4)
1158 |
1159 | '@vitest/pretty-format@2.1.8':
1160 | dependencies:
1161 | tinyrainbow: 1.2.0
1162 |
1163 | '@vitest/runner@2.1.8':
1164 | dependencies:
1165 | '@vitest/utils': 2.1.8
1166 | pathe: 1.1.2
1167 |
1168 | '@vitest/snapshot@2.1.8':
1169 | dependencies:
1170 | '@vitest/pretty-format': 2.1.8
1171 | magic-string: 0.30.17
1172 | pathe: 1.1.2
1173 |
1174 | '@vitest/spy@2.1.8':
1175 | dependencies:
1176 | tinyspy: 3.0.2
1177 |
1178 | '@vitest/utils@2.1.8':
1179 | dependencies:
1180 | '@vitest/pretty-format': 2.1.8
1181 | loupe: 3.1.2
1182 | tinyrainbow: 1.2.0
1183 |
1184 | ajv@6.12.6:
1185 | dependencies:
1186 | fast-deep-equal: 3.1.3
1187 | fast-json-stable-stringify: 2.1.0
1188 | json-schema-traverse: 0.4.1
1189 | uri-js: 4.4.1
1190 |
1191 | ansi-regex@5.0.1: {}
1192 |
1193 | ansi-regex@6.1.0: {}
1194 |
1195 | ansi-styles@4.3.0:
1196 | dependencies:
1197 | color-convert: 2.0.1
1198 |
1199 | ansi-styles@6.2.1: {}
1200 |
1201 | argparse@1.0.10:
1202 | dependencies:
1203 | sprintf-js: 1.0.3
1204 |
1205 | asn1@0.2.6:
1206 | dependencies:
1207 | safer-buffer: 2.1.2
1208 |
1209 | assert-plus@1.0.0: {}
1210 |
1211 | assertion-error@2.0.1: {}
1212 |
1213 | asynckit@0.4.0: {}
1214 |
1215 | aws-sign2@0.7.0: {}
1216 |
1217 | aws4@1.13.2: {}
1218 |
1219 | balanced-match@1.0.2: {}
1220 |
1221 | bcrypt-pbkdf@1.0.2:
1222 | dependencies:
1223 | tweetnacl: 0.14.5
1224 |
1225 | brace-expansion@2.0.1:
1226 | dependencies:
1227 | balanced-match: 1.0.2
1228 |
1229 | cac@6.7.14: {}
1230 |
1231 | caseless@0.12.0: {}
1232 |
1233 | chai@5.1.2:
1234 | dependencies:
1235 | assertion-error: 2.0.1
1236 | check-error: 2.1.1
1237 | deep-eql: 5.0.2
1238 | loupe: 3.1.2
1239 | pathval: 2.0.0
1240 |
1241 | check-error@2.1.1: {}
1242 |
1243 | color-convert@2.0.1:
1244 | dependencies:
1245 | color-name: 1.1.4
1246 |
1247 | color-name@1.1.4: {}
1248 |
1249 | combined-stream@1.0.8:
1250 | dependencies:
1251 | delayed-stream: 1.0.0
1252 |
1253 | core-util-is@1.0.2: {}
1254 |
1255 | coveralls@3.1.1:
1256 | dependencies:
1257 | js-yaml: 3.14.1
1258 | lcov-parse: 1.0.0
1259 | log-driver: 1.2.7
1260 | minimist: 1.2.8
1261 | request: 2.88.2
1262 |
1263 | cross-spawn@7.0.6:
1264 | dependencies:
1265 | path-key: 3.1.1
1266 | shebang-command: 2.0.0
1267 | which: 2.0.2
1268 |
1269 | dashdash@1.14.1:
1270 | dependencies:
1271 | assert-plus: 1.0.0
1272 |
1273 | debug@4.4.0:
1274 | dependencies:
1275 | ms: 2.1.3
1276 |
1277 | deep-eql@5.0.2: {}
1278 |
1279 | delayed-stream@1.0.0: {}
1280 |
1281 | eastasianwidth@0.2.0: {}
1282 |
1283 | ecc-jsbn@0.1.2:
1284 | dependencies:
1285 | jsbn: 0.1.1
1286 | safer-buffer: 2.1.2
1287 |
1288 | emoji-regex@8.0.0: {}
1289 |
1290 | emoji-regex@9.2.2: {}
1291 |
1292 | es-module-lexer@1.6.0: {}
1293 |
1294 | esbuild@0.21.5:
1295 | optionalDependencies:
1296 | '@esbuild/aix-ppc64': 0.21.5
1297 | '@esbuild/android-arm': 0.21.5
1298 | '@esbuild/android-arm64': 0.21.5
1299 | '@esbuild/android-x64': 0.21.5
1300 | '@esbuild/darwin-arm64': 0.21.5
1301 | '@esbuild/darwin-x64': 0.21.5
1302 | '@esbuild/freebsd-arm64': 0.21.5
1303 | '@esbuild/freebsd-x64': 0.21.5
1304 | '@esbuild/linux-arm': 0.21.5
1305 | '@esbuild/linux-arm64': 0.21.5
1306 | '@esbuild/linux-ia32': 0.21.5
1307 | '@esbuild/linux-loong64': 0.21.5
1308 | '@esbuild/linux-mips64el': 0.21.5
1309 | '@esbuild/linux-ppc64': 0.21.5
1310 | '@esbuild/linux-riscv64': 0.21.5
1311 | '@esbuild/linux-s390x': 0.21.5
1312 | '@esbuild/linux-x64': 0.21.5
1313 | '@esbuild/netbsd-x64': 0.21.5
1314 | '@esbuild/openbsd-x64': 0.21.5
1315 | '@esbuild/sunos-x64': 0.21.5
1316 | '@esbuild/win32-arm64': 0.21.5
1317 | '@esbuild/win32-ia32': 0.21.5
1318 | '@esbuild/win32-x64': 0.21.5
1319 |
1320 | esprima@4.0.1: {}
1321 |
1322 | estree-walker@3.0.3:
1323 | dependencies:
1324 | '@types/estree': 1.0.6
1325 |
1326 | expect-type@1.1.0: {}
1327 |
1328 | extend@3.0.2: {}
1329 |
1330 | extsprintf@1.3.0: {}
1331 |
1332 | fast-deep-equal@3.1.3: {}
1333 |
1334 | fast-json-stable-stringify@2.1.0: {}
1335 |
1336 | foreground-child@3.3.0:
1337 | dependencies:
1338 | cross-spawn: 7.0.6
1339 | signal-exit: 4.1.0
1340 |
1341 | forever-agent@0.6.1: {}
1342 |
1343 | form-data@2.3.3:
1344 | dependencies:
1345 | asynckit: 0.4.0
1346 | combined-stream: 1.0.8
1347 | mime-types: 2.1.35
1348 |
1349 | fsevents@2.3.3:
1350 | optional: true
1351 |
1352 | getpass@0.1.7:
1353 | dependencies:
1354 | assert-plus: 1.0.0
1355 |
1356 | glob@10.4.5:
1357 | dependencies:
1358 | foreground-child: 3.3.0
1359 | jackspeak: 3.4.3
1360 | minimatch: 9.0.5
1361 | minipass: 7.1.2
1362 | package-json-from-dist: 1.0.1
1363 | path-scurry: 1.11.1
1364 |
1365 | har-schema@2.0.0: {}
1366 |
1367 | har-validator@5.1.5:
1368 | dependencies:
1369 | ajv: 6.12.6
1370 | har-schema: 2.0.0
1371 |
1372 | has-flag@4.0.0: {}
1373 |
1374 | html-escaper@2.0.2: {}
1375 |
1376 | http-signature@1.2.0:
1377 | dependencies:
1378 | assert-plus: 1.0.0
1379 | jsprim: 1.4.2
1380 | sshpk: 1.18.0
1381 |
1382 | is-fullwidth-code-point@3.0.0: {}
1383 |
1384 | is-typedarray@1.0.0: {}
1385 |
1386 | isexe@2.0.0: {}
1387 |
1388 | isstream@0.1.2: {}
1389 |
1390 | istanbul-lib-coverage@3.2.2: {}
1391 |
1392 | istanbul-lib-report@3.0.1:
1393 | dependencies:
1394 | istanbul-lib-coverage: 3.2.2
1395 | make-dir: 4.0.0
1396 | supports-color: 7.2.0
1397 |
1398 | istanbul-lib-source-maps@5.0.6:
1399 | dependencies:
1400 | '@jridgewell/trace-mapping': 0.3.25
1401 | debug: 4.4.0
1402 | istanbul-lib-coverage: 3.2.2
1403 | transitivePeerDependencies:
1404 | - supports-color
1405 |
1406 | istanbul-reports@3.1.7:
1407 | dependencies:
1408 | html-escaper: 2.0.2
1409 | istanbul-lib-report: 3.0.1
1410 |
1411 | jackspeak@3.4.3:
1412 | dependencies:
1413 | '@isaacs/cliui': 8.0.2
1414 | optionalDependencies:
1415 | '@pkgjs/parseargs': 0.11.0
1416 |
1417 | js-yaml@3.14.1:
1418 | dependencies:
1419 | argparse: 1.0.10
1420 | esprima: 4.0.1
1421 |
1422 | jsbn@0.1.1: {}
1423 |
1424 | json-schema-traverse@0.4.1: {}
1425 |
1426 | json-schema@0.4.0: {}
1427 |
1428 | json-stringify-safe@5.0.1: {}
1429 |
1430 | jsprim@1.4.2:
1431 | dependencies:
1432 | assert-plus: 1.0.0
1433 | extsprintf: 1.3.0
1434 | json-schema: 0.4.0
1435 | verror: 1.10.0
1436 |
1437 | lcov-parse@1.0.0: {}
1438 |
1439 | lodash-es@4.17.21: {}
1440 |
1441 | log-driver@1.2.7: {}
1442 |
1443 | loupe@3.1.2: {}
1444 |
1445 | lru-cache@10.4.3: {}
1446 |
1447 | magic-string@0.30.17:
1448 | dependencies:
1449 | '@jridgewell/sourcemap-codec': 1.5.0
1450 |
1451 | magicast@0.3.5:
1452 | dependencies:
1453 | '@babel/parser': 7.26.3
1454 | '@babel/types': 7.26.3
1455 | source-map-js: 1.2.1
1456 |
1457 | make-dir@4.0.0:
1458 | dependencies:
1459 | semver: 7.6.3
1460 |
1461 | mime-db@1.52.0: {}
1462 |
1463 | mime-types@2.1.35:
1464 | dependencies:
1465 | mime-db: 1.52.0
1466 |
1467 | minimatch@9.0.5:
1468 | dependencies:
1469 | brace-expansion: 2.0.1
1470 |
1471 | minimist@1.2.8: {}
1472 |
1473 | minipass@7.1.2: {}
1474 |
1475 | ms@2.1.3: {}
1476 |
1477 | nanoid@3.3.8: {}
1478 |
1479 | oauth-sign@0.9.0: {}
1480 |
1481 | package-json-from-dist@1.0.1: {}
1482 |
1483 | path-key@3.1.1: {}
1484 |
1485 | path-scurry@1.11.1:
1486 | dependencies:
1487 | lru-cache: 10.4.3
1488 | minipass: 7.1.2
1489 |
1490 | pathe@1.1.2: {}
1491 |
1492 | pathval@2.0.0: {}
1493 |
1494 | performance-now@2.1.0: {}
1495 |
1496 | picocolors@1.1.1: {}
1497 |
1498 | postcss@8.4.49:
1499 | dependencies:
1500 | nanoid: 3.3.8
1501 | picocolors: 1.1.1
1502 | source-map-js: 1.2.1
1503 |
1504 | prettier@3.4.2: {}
1505 |
1506 | psl@1.15.0:
1507 | dependencies:
1508 | punycode: 2.3.1
1509 |
1510 | punycode@2.3.1: {}
1511 |
1512 | qs@6.5.3: {}
1513 |
1514 | request@2.88.2:
1515 | dependencies:
1516 | aws-sign2: 0.7.0
1517 | aws4: 1.13.2
1518 | caseless: 0.12.0
1519 | combined-stream: 1.0.8
1520 | extend: 3.0.2
1521 | forever-agent: 0.6.1
1522 | form-data: 2.3.3
1523 | har-validator: 5.1.5
1524 | http-signature: 1.2.0
1525 | is-typedarray: 1.0.0
1526 | isstream: 0.1.2
1527 | json-stringify-safe: 5.0.1
1528 | mime-types: 2.1.35
1529 | oauth-sign: 0.9.0
1530 | performance-now: 2.1.0
1531 | qs: 6.5.3
1532 | safe-buffer: 5.2.1
1533 | tough-cookie: 2.5.0
1534 | tunnel-agent: 0.6.0
1535 | uuid: 3.4.0
1536 |
1537 | rollup@4.29.1:
1538 | dependencies:
1539 | '@types/estree': 1.0.6
1540 | optionalDependencies:
1541 | '@rollup/rollup-android-arm-eabi': 4.29.1
1542 | '@rollup/rollup-android-arm64': 4.29.1
1543 | '@rollup/rollup-darwin-arm64': 4.29.1
1544 | '@rollup/rollup-darwin-x64': 4.29.1
1545 | '@rollup/rollup-freebsd-arm64': 4.29.1
1546 | '@rollup/rollup-freebsd-x64': 4.29.1
1547 | '@rollup/rollup-linux-arm-gnueabihf': 4.29.1
1548 | '@rollup/rollup-linux-arm-musleabihf': 4.29.1
1549 | '@rollup/rollup-linux-arm64-gnu': 4.29.1
1550 | '@rollup/rollup-linux-arm64-musl': 4.29.1
1551 | '@rollup/rollup-linux-loongarch64-gnu': 4.29.1
1552 | '@rollup/rollup-linux-powerpc64le-gnu': 4.29.1
1553 | '@rollup/rollup-linux-riscv64-gnu': 4.29.1
1554 | '@rollup/rollup-linux-s390x-gnu': 4.29.1
1555 | '@rollup/rollup-linux-x64-gnu': 4.29.1
1556 | '@rollup/rollup-linux-x64-musl': 4.29.1
1557 | '@rollup/rollup-win32-arm64-msvc': 4.29.1
1558 | '@rollup/rollup-win32-ia32-msvc': 4.29.1
1559 | '@rollup/rollup-win32-x64-msvc': 4.29.1
1560 | fsevents: 2.3.3
1561 |
1562 | safe-buffer@5.2.1: {}
1563 |
1564 | safer-buffer@2.1.2: {}
1565 |
1566 | semver@7.6.3: {}
1567 |
1568 | shebang-command@2.0.0:
1569 | dependencies:
1570 | shebang-regex: 3.0.0
1571 |
1572 | shebang-regex@3.0.0: {}
1573 |
1574 | siginfo@2.0.0: {}
1575 |
1576 | signal-exit@4.1.0: {}
1577 |
1578 | source-map-js@1.2.1: {}
1579 |
1580 | sprintf-js@1.0.3: {}
1581 |
1582 | sshpk@1.18.0:
1583 | dependencies:
1584 | asn1: 0.2.6
1585 | assert-plus: 1.0.0
1586 | bcrypt-pbkdf: 1.0.2
1587 | dashdash: 1.14.1
1588 | ecc-jsbn: 0.1.2
1589 | getpass: 0.1.7
1590 | jsbn: 0.1.1
1591 | safer-buffer: 2.1.2
1592 | tweetnacl: 0.14.5
1593 |
1594 | stackback@0.0.2: {}
1595 |
1596 | std-env@3.8.0: {}
1597 |
1598 | string-width@4.2.3:
1599 | dependencies:
1600 | emoji-regex: 8.0.0
1601 | is-fullwidth-code-point: 3.0.0
1602 | strip-ansi: 6.0.1
1603 |
1604 | string-width@5.1.2:
1605 | dependencies:
1606 | eastasianwidth: 0.2.0
1607 | emoji-regex: 9.2.2
1608 | strip-ansi: 7.1.0
1609 |
1610 | strip-ansi@6.0.1:
1611 | dependencies:
1612 | ansi-regex: 5.0.1
1613 |
1614 | strip-ansi@7.1.0:
1615 | dependencies:
1616 | ansi-regex: 6.1.0
1617 |
1618 | supports-color@7.2.0:
1619 | dependencies:
1620 | has-flag: 4.0.0
1621 |
1622 | test-exclude@7.0.1:
1623 | dependencies:
1624 | '@istanbuljs/schema': 0.1.3
1625 | glob: 10.4.5
1626 | minimatch: 9.0.5
1627 |
1628 | tinybench@2.9.0: {}
1629 |
1630 | tinyexec@0.3.2: {}
1631 |
1632 | tinypool@1.0.2: {}
1633 |
1634 | tinyrainbow@1.2.0: {}
1635 |
1636 | tinyspy@3.0.2: {}
1637 |
1638 | tough-cookie@2.5.0:
1639 | dependencies:
1640 | psl: 1.15.0
1641 | punycode: 2.3.1
1642 |
1643 | tunnel-agent@0.6.0:
1644 | dependencies:
1645 | safe-buffer: 5.2.1
1646 |
1647 | tweetnacl@0.14.5: {}
1648 |
1649 | typescript@5.7.2: {}
1650 |
1651 | undici-types@6.20.0: {}
1652 |
1653 | uri-js@4.4.1:
1654 | dependencies:
1655 | punycode: 2.3.1
1656 |
1657 | uuid@3.4.0: {}
1658 |
1659 | verror@1.10.0:
1660 | dependencies:
1661 | assert-plus: 1.0.0
1662 | core-util-is: 1.0.2
1663 | extsprintf: 1.3.0
1664 |
1665 | vite-node@2.1.8(@types/node@22.10.4):
1666 | dependencies:
1667 | cac: 6.7.14
1668 | debug: 4.4.0
1669 | es-module-lexer: 1.6.0
1670 | pathe: 1.1.2
1671 | vite: 5.4.11(@types/node@22.10.4)
1672 | transitivePeerDependencies:
1673 | - '@types/node'
1674 | - less
1675 | - lightningcss
1676 | - sass
1677 | - sass-embedded
1678 | - stylus
1679 | - sugarss
1680 | - supports-color
1681 | - terser
1682 |
1683 | vite@5.4.11(@types/node@22.10.4):
1684 | dependencies:
1685 | esbuild: 0.21.5
1686 | postcss: 8.4.49
1687 | rollup: 4.29.1
1688 | optionalDependencies:
1689 | '@types/node': 22.10.4
1690 | fsevents: 2.3.3
1691 |
1692 | vitest@2.1.8(@types/node@22.10.4):
1693 | dependencies:
1694 | '@vitest/expect': 2.1.8
1695 | '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.4))
1696 | '@vitest/pretty-format': 2.1.8
1697 | '@vitest/runner': 2.1.8
1698 | '@vitest/snapshot': 2.1.8
1699 | '@vitest/spy': 2.1.8
1700 | '@vitest/utils': 2.1.8
1701 | chai: 5.1.2
1702 | debug: 4.4.0
1703 | expect-type: 1.1.0
1704 | magic-string: 0.30.17
1705 | pathe: 1.1.2
1706 | std-env: 3.8.0
1707 | tinybench: 2.9.0
1708 | tinyexec: 0.3.2
1709 | tinypool: 1.0.2
1710 | tinyrainbow: 1.2.0
1711 | vite: 5.4.11(@types/node@22.10.4)
1712 | vite-node: 2.1.8(@types/node@22.10.4)
1713 | why-is-node-running: 2.3.0
1714 | optionalDependencies:
1715 | '@types/node': 22.10.4
1716 | transitivePeerDependencies:
1717 | - less
1718 | - lightningcss
1719 | - msw
1720 | - sass
1721 | - sass-embedded
1722 | - stylus
1723 | - sugarss
1724 | - supports-color
1725 | - terser
1726 |
1727 | which@2.0.2:
1728 | dependencies:
1729 | isexe: 2.0.0
1730 |
1731 | why-is-node-running@2.3.0:
1732 | dependencies:
1733 | siginfo: 2.0.0
1734 | stackback: 0.0.2
1735 |
1736 | wrap-ansi@7.0.0:
1737 | dependencies:
1738 | ansi-styles: 4.3.0
1739 | string-width: 4.2.3
1740 | strip-ansi: 6.0.1
1741 |
1742 | wrap-ansi@8.1.0:
1743 | dependencies:
1744 | ansi-styles: 6.2.1
1745 | string-width: 5.1.2
1746 | strip-ansi: 7.1.0
1747 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | cloneDeep,
3 | flatten,
4 | includes,
5 | isEmpty,
6 | isString,
7 | slice,
8 | some,
9 | uniqBy,
10 | assignIn
11 | } from 'lodash-es'
12 |
13 | export type MarkovInputData = { string: string }[]
14 |
15 | export type MarkovGenerateOptions = {
16 | maxTries?: number
17 | prng?: () => number
18 | filter?: (result: MarkovResult) => boolean
19 | }
20 |
21 | /**
22 | * Data to build the Markov instance
23 | */
24 | export type MarkovConstructorOptions = {
25 | stateSize?: number
26 | }
27 |
28 | /**
29 | * While `stateSize` is optional as a constructor parameter,
30 | * it must exist as a member
31 | */
32 | export type MarkovDataMembers = {
33 | stateSize: number
34 | }
35 |
36 | export type MarkovResult = {
37 | string: string
38 | score: number
39 | refs: MarkovInputData
40 | tries: number
41 | }
42 |
43 | export type MarkovFragment = {
44 | words: string
45 | refs: MarkovInputData
46 | }
47 |
48 | export type Corpus = { [key: string]: MarkovFragment[] }
49 |
50 | export type MarkovImportExport = {
51 | corpus: Corpus
52 | startWords: MarkovFragment[]
53 | endWords: MarkovFragment[]
54 | options: MarkovDataMembers
55 | }
56 |
57 | function sampleWithPRNG(
58 | array: T[],
59 | prng: () => number = Math.random
60 | ): T | undefined {
61 | const length = array == null ? 0 : array.length
62 | return length ? array[Math.floor(prng() * length)] : undefined
63 | }
64 |
65 | export default class Markov {
66 | public data: MarkovInputData
67 | public options: MarkovDataMembers
68 |
69 | public startWords: MarkovFragment[] = []
70 | public endWords: MarkovFragment[] = []
71 | public corpus: Corpus = {}
72 |
73 | private defaultOptions: MarkovDataMembers = {
74 | stateSize: 2,
75 | }
76 |
77 | /**
78 | * Creates an instance of Markov generator.
79 | *
80 | * @param {MarkovConstructorOptions} [options={}]
81 | * @memberof Markov
82 | */
83 | constructor(options: MarkovConstructorOptions = {}) {
84 | this.data = []
85 |
86 | // Save options
87 | this.options = this.defaultOptions
88 | assignIn(this.options, options)
89 | }
90 |
91 | /**
92 | * Imports a corpus. This overwrites existing data.
93 | *
94 | * @param data
95 | */
96 | public import(data: MarkovImportExport): void {
97 | this.options = cloneDeep(data.options)
98 | this.corpus = cloneDeep(data.corpus)
99 | this.startWords = cloneDeep(data.startWords)
100 | this.endWords = cloneDeep(data.endWords)
101 | }
102 |
103 | /**
104 | * Exports structed data used to generate sentence.
105 | */
106 | public export(): MarkovImportExport {
107 | return cloneDeep({
108 | options: this.options,
109 | corpus: this.corpus,
110 | startWords: this.startWords,
111 | endWords: this.endWords,
112 | })
113 | }
114 |
115 | public addData(rawData: MarkovInputData | string[]) {
116 | // Format data if necessary
117 | let input: MarkovInputData = []
118 | if (isString(rawData[0])) {
119 | input = (rawData as string[]).map((s) => ({ string: s }))
120 | } else if (rawData[0].hasOwnProperty('string')) {
121 | input = rawData as MarkovInputData
122 | } else {
123 | throw new Error('Objects in your corpus must have a "string" property')
124 | }
125 |
126 | this.buildCorpus(input)
127 |
128 | this.data = this.data.concat(input)
129 | }
130 |
131 | /**
132 | * Builds the corpus. You must call this before generating sentences.
133 | *
134 | * @memberof Markov
135 | */
136 | private buildCorpus(data: MarkovInputData): void {
137 | const options = this.options
138 |
139 | // Loop through all sentences
140 | data.forEach((item) => {
141 | const line = item.string
142 | const words = line.split(' ')
143 | const stateSize = options.stateSize // Default value of 2 is set in the constructor
144 |
145 | //#region Start words
146 | // "Start words" is the list of words that can start a generated chain.
147 |
148 | const start = slice(words, 0, stateSize).join(' ')
149 | const oldStartObj = this.startWords.find((o) => o.words === start)
150 |
151 | // If we already have identical startWords
152 | if (oldStartObj) {
153 | // If the current item is not present in the references, add it
154 | if (!includes(oldStartObj.refs, item)) {
155 | oldStartObj.refs.push(item)
156 | }
157 | } else {
158 | // Add the startWords (and reference) to the list
159 | this.startWords.push({ words: start, refs: [item] })
160 | }
161 |
162 | //#endregion Start words
163 |
164 | //#region End words
165 | // "End words" is the list of words that can end a generated chain.
166 |
167 | const end = slice(words, words.length - stateSize, words.length).join(' ')
168 | const oldEndObj = this.endWords.find((o) => o.words === end)
169 | if (oldEndObj) {
170 | if (!includes(oldEndObj.refs, item)) {
171 | oldEndObj.refs.push(item)
172 | }
173 | } else {
174 | this.endWords.push({ words: end, refs: [item] })
175 | }
176 |
177 | //#endregion End words
178 |
179 | //#region Corpus generation
180 |
181 | // We loop through all words in the sentence to build "blocks" of `stateSize`
182 | // e.g. for a stateSize of 2, "lorem ipsum dolor sit amet" will have the following blocks:
183 | // "lorem ipsum", "ipsum dolor", "dolor sit", and "sit amet"
184 | for (let i = 0; i < words.length - 1; i++) {
185 | const curr = slice(words, i, i + stateSize).join(' ')
186 | const next = slice(words, i + stateSize, i + stateSize * 2).join(' ')
187 | if (!next || next.split(' ').length !== options.stateSize) {
188 | continue
189 | }
190 |
191 | // Check if the corpus already has a corresponding "curr" block
192 | if (this.corpus.hasOwnProperty(curr)) {
193 | const oldObj = this.corpus[curr].find((o) => o.words === next)
194 | if (oldObj) {
195 | // If the corpus already has the chain "curr -> next",
196 | // just add the current reference for this block
197 | oldObj.refs.push(item)
198 | } else {
199 | // Add the new "next" block in the list of possible paths for "curr"
200 | this.corpus[curr].push({ words: next, refs: [item] })
201 | }
202 | } else {
203 | // Add the "curr" block and link it with the "next" one
204 | this.corpus[curr] = [{ words: next, refs: [item] }]
205 | }
206 | }
207 |
208 | //#endregion Corpus generation
209 | })
210 | }
211 |
212 | /**
213 | * Generates a result, that contains a string and its references
214 | *
215 | * @param {MarkovGenerateOptions} [options={}]
216 | * @returns {MarkovResult}
217 | * @memberof Markov
218 | */
219 | public generate(options: MarkovGenerateOptions = {}): MarkovResult {
220 | if (isEmpty(this.corpus)) {
221 | throw new Error(
222 | 'Corpus is empty. There is either no data, or the data is not sufficient to create markov chains.'
223 | )
224 | }
225 |
226 | const corpus = cloneDeep(this.corpus)
227 | const maxTries = options.maxTries ? options.maxTries : 10
228 | const prng = options.prng ? options.prng : Math.random
229 |
230 | let tries: number
231 |
232 | // We loop through fragments to create a complete sentence
233 | for (tries = 1; tries <= maxTries; tries++) {
234 | let ended = false
235 |
236 | // Create an array of MarkovCorpusItems
237 | // The first item is a random startWords element
238 | const arr = [sampleWithPRNG(this.startWords, prng)!]
239 |
240 | let score = 0
241 |
242 | // loop to build a complete sentence
243 | for (let innerTries = 0; innerTries < maxTries; innerTries++) {
244 | const block = arr[arr.length - 1] // last value in array
245 | const state = sampleWithPRNG(corpus[block.words], prng) // Find a following item in the corpus
246 |
247 | // If a state cannot be found, the sentence can't be completed
248 | if (!state) {
249 | break
250 | }
251 |
252 | // add new state to list
253 | arr.push(state)
254 |
255 | // increment score
256 | score += corpus[block.words].length - 1 // increment score
257 |
258 | // is sentence finished?
259 | if (some(this.endWords, { words: state.words })) {
260 | ended = true
261 | break
262 | }
263 | }
264 |
265 | const sentence = arr
266 | .map((o) => o.words)
267 | .join(' ')
268 | .trim()
269 |
270 | const result = {
271 | string: sentence,
272 | score,
273 | refs: uniqBy(flatten(arr.map((o) => o.refs)), 'string'),
274 | tries,
275 | }
276 |
277 | // sentence is not ended or incorrect
278 | if (
279 | !ended ||
280 | (typeof options.filter === 'function' && !options.filter(result))
281 | ) {
282 | continue
283 | }
284 |
285 | return result
286 | }
287 | throw new Error(
288 | `Failed to build a sentence after ${tries - 1
289 | } tries. Possible solutions: try a less restrictive filter(), give more raw data to the corpus builder, or increase the number of maximum tries.`
290 | )
291 | }
292 | }
293 |
--------------------------------------------------------------------------------
/tests/index.test.ts:
--------------------------------------------------------------------------------
1 | import { map, some } from 'lodash-es'
2 | import Markov, { MarkovResult } from '../src'
3 | import { describe, expect, it, beforeEach, vi } from 'vitest'
4 |
5 | const data = [
6 | 'Lorem ipsum dolor sit amet',
7 | 'Lorem ipsum duplicate start words',
8 | 'Consectetur adipiscing elit',
9 | 'Quisque tempor, erat vel lacinia imperdiet',
10 | 'Justo nisi fringilla dui',
11 | 'Egestas bibendum eros nisi ut lacus',
12 | "fringilla dui avait annoncé une rupture avec le erat vel: il n'en est rien…",
13 | 'Fusce tincidunt tempor, erat vel lacinia vel ex pharetra pretium lacinia imperdiet'
14 | ]
15 |
16 | describe('Markov class', () => {
17 | describe('Constructor', () => {
18 |
19 | it('should have a default stateSize', () => {
20 | const markov = new Markov()
21 | expect(markov.options.stateSize).toBe(2)
22 | })
23 |
24 | it('should save a different stateSize', () => {
25 | const markov = new Markov({ stateSize: 3 })
26 | expect(markov.options.stateSize).toBe(3)
27 | })
28 | })
29 |
30 | describe('Adding data', () => {
31 | it('should build synchronously', () => {
32 | const markov = new Markov()
33 | expect(markov.corpus).toEqual({})
34 | markov.addData(data)
35 | expect(markov.corpus).not.toEqual({})
36 | })
37 |
38 |
39 | it('should throw an error if the data structure is invalid', () => {
40 | const markov = new Markov()
41 | expect(() => {
42 | // @ts-ignore
43 | markov.addData([{}])
44 | }).toThrowError()
45 | })
46 |
47 | it('should accept objects', () => {
48 | const markov = new Markov()
49 | markov.addData(data.map(o => ({ string: o })))
50 | expect(markov.corpus).not.toEqual({})
51 | })
52 |
53 | })
54 |
55 | describe('After adding data', () => {
56 | let markov: Markov
57 | beforeEach(() => {
58 | markov = new Markov()
59 | markov.addData(data)
60 | })
61 |
62 | describe('The startWords array', () => {
63 | it('should contain the right values', () => {
64 | const start = markov.startWords
65 | expect(some(start, { words: 'Lorem ipsum' })).toBeTruthy()
66 | expect(some(start, { words: 'Consectetur adipiscing' })).toBeTruthy()
67 | expect(some(start, { words: 'Quisque tempor,' })).toBeTruthy()
68 | expect(some(start, { words: 'Justo nisi' })).toBeTruthy()
69 | expect(some(start, { words: 'Egestas bibendum' })).toBeTruthy()
70 | expect(some(start, { words: 'fringilla dui' })).toBeTruthy()
71 | expect(some(start, { words: 'Fusce tincidunt' })).toBeTruthy()
72 | })
73 |
74 | it('should have the right length', () => {
75 | expect(markov.startWords).toHaveLength(7)
76 | })
77 | })
78 |
79 | describe('The endWords array', () => {
80 | it('should have the right length', () => {
81 | expect(markov.endWords).toHaveLength(7)
82 | })
83 |
84 | it('should contain the right values', () => {
85 | const end = markov.endWords
86 | expect(some(end, { words: 'sit amet' })).toBeTruthy()
87 | expect(some(end, { words: 'start words' })).toBeTruthy()
88 | expect(some(end, { words: 'adipiscing elit' })).toBeTruthy()
89 | expect(some(end, { words: 'fringilla dui' })).toBeTruthy()
90 | expect(some(end, { words: 'ut lacus' })).toBeTruthy()
91 | expect(some(end, { words: 'est rien…' })).toBeTruthy()
92 | })
93 | })
94 |
95 | describe('The corpus itself', () => {
96 | it('should have the right values for the right keys', () => {
97 | const corpus = markov.corpus
98 | expect(some(corpus['Lorem ipsum'], { words: 'dolor sit' })).toBeTruthy()
99 | expect(
100 | some(corpus['Lorem ipsum'], { words: 'duplicate start' })
101 | ).toBeTruthy()
102 | expect(
103 | some(corpus['tempor, erat'], { words: 'vel lacinia' })
104 | ).toBeTruthy()
105 | })
106 | })
107 |
108 | describe('Export data', () => {
109 | it('should clone the original corpus values', () => {
110 | const exported = markov.export()
111 |
112 | expect(exported.corpus).toEqual(markov.corpus)
113 | expect(exported.corpus).not.toBe(markov.corpus)
114 |
115 | expect(exported.startWords).not.toBe(markov.startWords)
116 | expect(exported.startWords).toEqual(markov.startWords)
117 |
118 | expect(exported.endWords).not.toBe(markov.endWords)
119 | expect(exported.endWords).toEqual(markov.endWords)
120 |
121 | expect(exported.options).toEqual(markov.options)
122 | expect(exported.options).not.toBe(markov.options)
123 | })
124 | })
125 |
126 | describe('Import data', () => {
127 | it('should overwrite original values', () => {
128 | const exported = markov.export()
129 | const newMarkov = new Markov()
130 |
131 | // Make sure that the corpus is empty
132 | expect(newMarkov.corpus).toEqual({})
133 |
134 | newMarkov.import(exported)
135 |
136 | expect(newMarkov.corpus).toEqual(exported.corpus)
137 | expect(newMarkov.corpus).not.toBe(exported.corpus)
138 |
139 | expect(newMarkov.startWords).toEqual(exported.startWords)
140 | expect(newMarkov.startWords).not.toBe(exported.startWords)
141 |
142 | expect(newMarkov.endWords).toEqual(exported.endWords)
143 | expect(newMarkov.endWords).not.toBe(exported.endWords)
144 |
145 | expect(newMarkov.options).toEqual(exported.options)
146 | expect(newMarkov.options).not.toBe(exported.options)
147 | })
148 | })
149 | })
150 |
151 | describe('The sentence generator', () => {
152 | let markov: Markov
153 | beforeEach(() => {
154 | markov = new Markov()
155 | markov.addData(data)
156 | })
157 |
158 | it('should throw an error if the corpus is not built', () => {
159 | markov = new Markov()
160 | expect(() => {
161 | markov.generate()
162 | }).toThrowError('Corpus is empty. There is either no data, or the data is not sufficient to create markov chains.')
163 | })
164 |
165 | it('should return a result if under the tries limit', () => {
166 | expect.assertions(10)
167 |
168 | for (let i = 0; i < 10; i++) {
169 | const sentence = markov.generate({ maxTries: 20 })
170 | expect(sentence.tries).toBeLessThanOrEqual(20)
171 | }
172 | })
173 |
174 | it('should call the `filter` callback', () => {
175 | const filter = vi.fn(x => true)
176 | markov.generate({ filter })
177 | expect(filter).toHaveBeenCalled()
178 | })
179 |
180 | it('should throw an error after 10 tries, by default', () => {
181 | expect(() => {
182 | markov.generate({
183 | filter(result: MarkovResult): boolean {
184 | return false
185 | }
186 | })
187 | }).toThrowError('10')
188 | })
189 |
190 | it('should end with a value from endWords', async () => {
191 | expect.assertions(10)
192 |
193 | for (let i = 0; i < 10; i++) {
194 | const result = markov.generate()
195 | const arr = result.string.split(' ')
196 | const end = arr.slice(arr.length - 2, arr.length)
197 | expect(map(markov.endWords, 'words')).toContain(end.join(' '))
198 | }
199 | })
200 |
201 | it(`should pass the result object to 'filter(result)'`, async () => {
202 | expect.assertions(6)
203 |
204 | const options = {
205 | minWords: 5,
206 | maxTries: 10,
207 | filter: (result: MarkovResult): boolean => {
208 | expect(Object.keys(result)).toHaveLength(4)
209 | expect(result).toHaveProperty('string')
210 | expect(result).toHaveProperty('score')
211 | expect(result).toHaveProperty('refs')
212 | expect(Array.isArray(result.refs)).toBeTruthy()
213 | expect(result).toHaveProperty('tries')
214 | return true
215 | }
216 | }
217 | markov.generate(options)
218 | })
219 |
220 | })
221 | })
222 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": true,
3 | "include": [
4 | "src/**/*"
5 | ],
6 | "compilerOptions": {
7 | /* Basic Options */
8 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
9 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
10 | // "lib": [], /* Specify library files to be included in the compilation. */
11 | // "allowJs": true, /* Allow javascript files to be compiled. */
12 | // "checkJs": true, /* Report errors in .js files. */
13 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
14 | "declaration": true, /* Generates corresponding '.d.ts' file. */
15 | "declarationDir": "./dist",
16 | // "sourceMap": true, /* Generates corresponding '.map' file. */
17 | // "outFile": "./", /* Concatenate and emit output to single file. */
18 | "outDir": "./dist", /* Redirect output structure to the directory. */
19 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
20 | // "removeComments": true, /* Do not emit comments to output. */
21 | // "noEmit": true, /* Do not emit outputs. */
22 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
23 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
24 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
25 |
26 | /* Strict Type-Checking Options */
27 | "strict": true, /* Enable all strict type-checking options. */
28 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
29 | // "strictNullChecks": true, /* Enable strict null checks. */
30 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */
31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
34 |
35 | /* Additional Checks */
36 | // "noUnusedLocals": true, /* Report errors on unused locals. */
37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
40 |
41 | /* Module Resolution Options */
42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
46 | // "typeRoots": [], /* List of folders to include type definitions from. */
47 | // "types": [], /* Type declaration files to be included in compilation. */
48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
49 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
51 |
52 | /* Source Map Options */
53 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
54 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */
55 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
56 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
57 |
58 | /* Experimental Options */
59 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
60 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
61 | }
62 | }
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config'
2 |
3 | export default defineConfig({
4 | test: {
5 | coverage: {
6 | reporter: ['lcov'],
7 | },
8 | },
9 | })
--------------------------------------------------------------------------------