├── .github └── workflows │ └── release.yml ├── .gitignore ├── README.md ├── package.json ├── pnpm-lock.yaml ├── screenshot.webp ├── src ├── App.css ├── App.tsx ├── api.ts ├── main.tsx ├── types │ ├── api.ts │ └── reply.ts ├── utils.ts └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | push: 8 | tags: 9 | - 'v*' 10 | 11 | jobs: 12 | release: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | 19 | - uses: actions/setup-node@v4 20 | with: 21 | node-version: lts/* 22 | 23 | - run: npx changelogithub 24 | env: 25 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bilibili Comment Search 2 | 3 | 让 Bilibili 支持评论搜索。 4 | 5 | [在 Greasyfork 上安装脚本](https://greasyfork.org/zh-CN/scripts/467863-bilibili-comment-search) 6 | 7 | ![screenshot](./screenshot.webp) 8 | 9 | ## 工作原理 10 | 11 | 脚本会在 Bilibili 视频页的评论区添加“搜索评论”按钮,用户点击时,将打开对话框并获取所有评论。在对话框中,用户可以输入关键词并按下 Enter 来搜索特定评论。评论获取完成后,包含关键字的评论会显示在对话框中。 12 | 13 | ## 限制 14 | 15 | 为了提高性能并避免达到请求速率的限制,目前仅会加载 20 页评论,即 20 \* 20 条评论,以及每条评论的最多 3 条子评论。 16 | 17 | ## License 18 | 19 | MIT 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "userscript-bilibili-comment-search", 3 | "private": true, 4 | "version": "0.2.0", 5 | "description": "Add comment searching support in Bilibili.", 6 | "type": "module", 7 | "packageManager": "pnpm@8.6.0", 8 | "author": "pacexy ", 9 | "license": "MIT", 10 | "homepage": "https://github.com/pacexy/userscript-bilibili-comment-search#readme", 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/pacexy/userscript-bilibili-comment-search.git" 14 | }, 15 | "bugs": "https://github.com/pacexy/userscript-bilibili-comment-search/issues", 16 | "scripts": { 17 | "dev": "vite", 18 | "build": "tsc && vite build", 19 | "preview": "vite preview", 20 | "release": "bumpp package.json" 21 | }, 22 | "dependencies": { 23 | "react": "^18.2.0", 24 | "react-dom": "^18.2.0", 25 | "react-highlight-words": "^0.20.0" 26 | }, 27 | "devDependencies": { 28 | "@types/react": "^18.2.8", 29 | "@types/react-dom": "^18.2.4", 30 | "@types/react-highlight-words": "^0.16.4", 31 | "@vitejs/plugin-react": "^4.0.0", 32 | "bumpp": "9.1.0", 33 | "typescript": "^5.1.3", 34 | "vite": "^4.3.9", 35 | "vite-plugin-monkey": "^3.2.2" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.1' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | react: 9 | specifier: ^18.2.0 10 | version: 18.2.0 11 | react-dom: 12 | specifier: ^18.2.0 13 | version: 18.2.0(react@18.2.0) 14 | react-highlight-words: 15 | specifier: ^0.20.0 16 | version: 0.20.0(react@18.2.0) 17 | 18 | devDependencies: 19 | '@types/react': 20 | specifier: ^18.2.8 21 | version: 18.2.8 22 | '@types/react-dom': 23 | specifier: ^18.2.4 24 | version: 18.2.4 25 | '@types/react-highlight-words': 26 | specifier: ^0.16.4 27 | version: 0.16.4 28 | '@vitejs/plugin-react': 29 | specifier: ^4.0.0 30 | version: 4.0.0(vite@4.3.9) 31 | bumpp: 32 | specifier: 9.1.0 33 | version: 9.1.0 34 | typescript: 35 | specifier: ^5.1.3 36 | version: 5.1.3 37 | vite: 38 | specifier: ^4.3.9 39 | version: 4.3.9 40 | vite-plugin-monkey: 41 | specifier: ^3.2.2 42 | version: 3.2.2(vite@4.3.9) 43 | 44 | packages: 45 | 46 | /@ampproject/remapping@2.2.1: 47 | resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} 48 | engines: {node: '>=6.0.0'} 49 | dependencies: 50 | '@jridgewell/gen-mapping': 0.3.3 51 | '@jridgewell/trace-mapping': 0.3.18 52 | dev: true 53 | 54 | /@babel/code-frame@7.21.4: 55 | resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} 56 | engines: {node: '>=6.9.0'} 57 | dependencies: 58 | '@babel/highlight': 7.18.6 59 | dev: true 60 | 61 | /@babel/compat-data@7.22.3: 62 | resolution: {integrity: sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==} 63 | engines: {node: '>=6.9.0'} 64 | dev: true 65 | 66 | /@babel/core@7.22.1: 67 | resolution: {integrity: sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==} 68 | engines: {node: '>=6.9.0'} 69 | dependencies: 70 | '@ampproject/remapping': 2.2.1 71 | '@babel/code-frame': 7.21.4 72 | '@babel/generator': 7.22.3 73 | '@babel/helper-compilation-targets': 7.22.1(@babel/core@7.22.1) 74 | '@babel/helper-module-transforms': 7.22.1 75 | '@babel/helpers': 7.22.3 76 | '@babel/parser': 7.22.4 77 | '@babel/template': 7.21.9 78 | '@babel/traverse': 7.22.4 79 | '@babel/types': 7.22.4 80 | convert-source-map: 1.9.0 81 | debug: 4.3.4 82 | gensync: 1.0.0-beta.2 83 | json5: 2.2.3 84 | semver: 6.3.0 85 | transitivePeerDependencies: 86 | - supports-color 87 | dev: true 88 | 89 | /@babel/generator@7.22.3: 90 | resolution: {integrity: sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==} 91 | engines: {node: '>=6.9.0'} 92 | dependencies: 93 | '@babel/types': 7.22.4 94 | '@jridgewell/gen-mapping': 0.3.3 95 | '@jridgewell/trace-mapping': 0.3.18 96 | jsesc: 2.5.2 97 | dev: true 98 | 99 | /@babel/helper-compilation-targets@7.22.1(@babel/core@7.22.1): 100 | resolution: {integrity: sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ==} 101 | engines: {node: '>=6.9.0'} 102 | peerDependencies: 103 | '@babel/core': ^7.0.0 104 | dependencies: 105 | '@babel/compat-data': 7.22.3 106 | '@babel/core': 7.22.1 107 | '@babel/helper-validator-option': 7.21.0 108 | browserslist: 4.21.7 109 | lru-cache: 5.1.1 110 | semver: 6.3.0 111 | dev: true 112 | 113 | /@babel/helper-environment-visitor@7.22.1: 114 | resolution: {integrity: sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==} 115 | engines: {node: '>=6.9.0'} 116 | dev: true 117 | 118 | /@babel/helper-function-name@7.21.0: 119 | resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} 120 | engines: {node: '>=6.9.0'} 121 | dependencies: 122 | '@babel/template': 7.21.9 123 | '@babel/types': 7.22.4 124 | dev: true 125 | 126 | /@babel/helper-hoist-variables@7.18.6: 127 | resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} 128 | engines: {node: '>=6.9.0'} 129 | dependencies: 130 | '@babel/types': 7.22.4 131 | dev: true 132 | 133 | /@babel/helper-module-imports@7.21.4: 134 | resolution: {integrity: sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==} 135 | engines: {node: '>=6.9.0'} 136 | dependencies: 137 | '@babel/types': 7.22.4 138 | dev: true 139 | 140 | /@babel/helper-module-transforms@7.22.1: 141 | resolution: {integrity: sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==} 142 | engines: {node: '>=6.9.0'} 143 | dependencies: 144 | '@babel/helper-environment-visitor': 7.22.1 145 | '@babel/helper-module-imports': 7.21.4 146 | '@babel/helper-simple-access': 7.21.5 147 | '@babel/helper-split-export-declaration': 7.18.6 148 | '@babel/helper-validator-identifier': 7.19.1 149 | '@babel/template': 7.21.9 150 | '@babel/traverse': 7.22.4 151 | '@babel/types': 7.22.4 152 | transitivePeerDependencies: 153 | - supports-color 154 | dev: true 155 | 156 | /@babel/helper-plugin-utils@7.21.5: 157 | resolution: {integrity: sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==} 158 | engines: {node: '>=6.9.0'} 159 | dev: true 160 | 161 | /@babel/helper-simple-access@7.21.5: 162 | resolution: {integrity: sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==} 163 | engines: {node: '>=6.9.0'} 164 | dependencies: 165 | '@babel/types': 7.22.4 166 | dev: true 167 | 168 | /@babel/helper-split-export-declaration@7.18.6: 169 | resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} 170 | engines: {node: '>=6.9.0'} 171 | dependencies: 172 | '@babel/types': 7.22.4 173 | dev: true 174 | 175 | /@babel/helper-string-parser@7.21.5: 176 | resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==} 177 | engines: {node: '>=6.9.0'} 178 | dev: true 179 | 180 | /@babel/helper-validator-identifier@7.19.1: 181 | resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} 182 | engines: {node: '>=6.9.0'} 183 | dev: true 184 | 185 | /@babel/helper-validator-option@7.21.0: 186 | resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} 187 | engines: {node: '>=6.9.0'} 188 | dev: true 189 | 190 | /@babel/helpers@7.22.3: 191 | resolution: {integrity: sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==} 192 | engines: {node: '>=6.9.0'} 193 | dependencies: 194 | '@babel/template': 7.21.9 195 | '@babel/traverse': 7.22.4 196 | '@babel/types': 7.22.4 197 | transitivePeerDependencies: 198 | - supports-color 199 | dev: true 200 | 201 | /@babel/highlight@7.18.6: 202 | resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} 203 | engines: {node: '>=6.9.0'} 204 | dependencies: 205 | '@babel/helper-validator-identifier': 7.19.1 206 | chalk: 2.4.2 207 | js-tokens: 4.0.0 208 | dev: true 209 | 210 | /@babel/parser@7.22.4: 211 | resolution: {integrity: sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==} 212 | engines: {node: '>=6.0.0'} 213 | hasBin: true 214 | dependencies: 215 | '@babel/types': 7.22.4 216 | dev: true 217 | 218 | /@babel/plugin-transform-react-jsx-self@7.21.0(@babel/core@7.22.1): 219 | resolution: {integrity: sha512-f/Eq+79JEu+KUANFks9UZCcvydOOGMgF7jBrcwjHa5jTZD8JivnhCJYvmlhR/WTXBWonDExPoW0eO/CR4QJirA==} 220 | engines: {node: '>=6.9.0'} 221 | peerDependencies: 222 | '@babel/core': ^7.0.0-0 223 | dependencies: 224 | '@babel/core': 7.22.1 225 | '@babel/helper-plugin-utils': 7.21.5 226 | dev: true 227 | 228 | /@babel/plugin-transform-react-jsx-source@7.19.6(@babel/core@7.22.1): 229 | resolution: {integrity: sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ==} 230 | engines: {node: '>=6.9.0'} 231 | peerDependencies: 232 | '@babel/core': ^7.0.0-0 233 | dependencies: 234 | '@babel/core': 7.22.1 235 | '@babel/helper-plugin-utils': 7.21.5 236 | dev: true 237 | 238 | /@babel/template@7.21.9: 239 | resolution: {integrity: sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==} 240 | engines: {node: '>=6.9.0'} 241 | dependencies: 242 | '@babel/code-frame': 7.21.4 243 | '@babel/parser': 7.22.4 244 | '@babel/types': 7.22.4 245 | dev: true 246 | 247 | /@babel/traverse@7.22.4: 248 | resolution: {integrity: sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ==} 249 | engines: {node: '>=6.9.0'} 250 | dependencies: 251 | '@babel/code-frame': 7.21.4 252 | '@babel/generator': 7.22.3 253 | '@babel/helper-environment-visitor': 7.22.1 254 | '@babel/helper-function-name': 7.21.0 255 | '@babel/helper-hoist-variables': 7.18.6 256 | '@babel/helper-split-export-declaration': 7.18.6 257 | '@babel/parser': 7.22.4 258 | '@babel/types': 7.22.4 259 | debug: 4.3.4 260 | globals: 11.12.0 261 | transitivePeerDependencies: 262 | - supports-color 263 | dev: true 264 | 265 | /@babel/types@7.22.4: 266 | resolution: {integrity: sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA==} 267 | engines: {node: '>=6.9.0'} 268 | dependencies: 269 | '@babel/helper-string-parser': 7.21.5 270 | '@babel/helper-validator-identifier': 7.19.1 271 | to-fast-properties: 2.0.0 272 | dev: true 273 | 274 | /@esbuild/android-arm64@0.17.19: 275 | resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} 276 | engines: {node: '>=12'} 277 | cpu: [arm64] 278 | os: [android] 279 | requiresBuild: true 280 | dev: true 281 | optional: true 282 | 283 | /@esbuild/android-arm@0.17.19: 284 | resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} 285 | engines: {node: '>=12'} 286 | cpu: [arm] 287 | os: [android] 288 | requiresBuild: true 289 | dev: true 290 | optional: true 291 | 292 | /@esbuild/android-x64@0.17.19: 293 | resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} 294 | engines: {node: '>=12'} 295 | cpu: [x64] 296 | os: [android] 297 | requiresBuild: true 298 | dev: true 299 | optional: true 300 | 301 | /@esbuild/darwin-arm64@0.17.19: 302 | resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} 303 | engines: {node: '>=12'} 304 | cpu: [arm64] 305 | os: [darwin] 306 | requiresBuild: true 307 | dev: true 308 | optional: true 309 | 310 | /@esbuild/darwin-x64@0.17.19: 311 | resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} 312 | engines: {node: '>=12'} 313 | cpu: [x64] 314 | os: [darwin] 315 | requiresBuild: true 316 | dev: true 317 | optional: true 318 | 319 | /@esbuild/freebsd-arm64@0.17.19: 320 | resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} 321 | engines: {node: '>=12'} 322 | cpu: [arm64] 323 | os: [freebsd] 324 | requiresBuild: true 325 | dev: true 326 | optional: true 327 | 328 | /@esbuild/freebsd-x64@0.17.19: 329 | resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} 330 | engines: {node: '>=12'} 331 | cpu: [x64] 332 | os: [freebsd] 333 | requiresBuild: true 334 | dev: true 335 | optional: true 336 | 337 | /@esbuild/linux-arm64@0.17.19: 338 | resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} 339 | engines: {node: '>=12'} 340 | cpu: [arm64] 341 | os: [linux] 342 | requiresBuild: true 343 | dev: true 344 | optional: true 345 | 346 | /@esbuild/linux-arm@0.17.19: 347 | resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} 348 | engines: {node: '>=12'} 349 | cpu: [arm] 350 | os: [linux] 351 | requiresBuild: true 352 | dev: true 353 | optional: true 354 | 355 | /@esbuild/linux-ia32@0.17.19: 356 | resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} 357 | engines: {node: '>=12'} 358 | cpu: [ia32] 359 | os: [linux] 360 | requiresBuild: true 361 | dev: true 362 | optional: true 363 | 364 | /@esbuild/linux-loong64@0.17.19: 365 | resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} 366 | engines: {node: '>=12'} 367 | cpu: [loong64] 368 | os: [linux] 369 | requiresBuild: true 370 | dev: true 371 | optional: true 372 | 373 | /@esbuild/linux-mips64el@0.17.19: 374 | resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} 375 | engines: {node: '>=12'} 376 | cpu: [mips64el] 377 | os: [linux] 378 | requiresBuild: true 379 | dev: true 380 | optional: true 381 | 382 | /@esbuild/linux-ppc64@0.17.19: 383 | resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} 384 | engines: {node: '>=12'} 385 | cpu: [ppc64] 386 | os: [linux] 387 | requiresBuild: true 388 | dev: true 389 | optional: true 390 | 391 | /@esbuild/linux-riscv64@0.17.19: 392 | resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} 393 | engines: {node: '>=12'} 394 | cpu: [riscv64] 395 | os: [linux] 396 | requiresBuild: true 397 | dev: true 398 | optional: true 399 | 400 | /@esbuild/linux-s390x@0.17.19: 401 | resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} 402 | engines: {node: '>=12'} 403 | cpu: [s390x] 404 | os: [linux] 405 | requiresBuild: true 406 | dev: true 407 | optional: true 408 | 409 | /@esbuild/linux-x64@0.17.19: 410 | resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} 411 | engines: {node: '>=12'} 412 | cpu: [x64] 413 | os: [linux] 414 | requiresBuild: true 415 | dev: true 416 | optional: true 417 | 418 | /@esbuild/netbsd-x64@0.17.19: 419 | resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} 420 | engines: {node: '>=12'} 421 | cpu: [x64] 422 | os: [netbsd] 423 | requiresBuild: true 424 | dev: true 425 | optional: true 426 | 427 | /@esbuild/openbsd-x64@0.17.19: 428 | resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} 429 | engines: {node: '>=12'} 430 | cpu: [x64] 431 | os: [openbsd] 432 | requiresBuild: true 433 | dev: true 434 | optional: true 435 | 436 | /@esbuild/sunos-x64@0.17.19: 437 | resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} 438 | engines: {node: '>=12'} 439 | cpu: [x64] 440 | os: [sunos] 441 | requiresBuild: true 442 | dev: true 443 | optional: true 444 | 445 | /@esbuild/win32-arm64@0.17.19: 446 | resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} 447 | engines: {node: '>=12'} 448 | cpu: [arm64] 449 | os: [win32] 450 | requiresBuild: true 451 | dev: true 452 | optional: true 453 | 454 | /@esbuild/win32-ia32@0.17.19: 455 | resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} 456 | engines: {node: '>=12'} 457 | cpu: [ia32] 458 | os: [win32] 459 | requiresBuild: true 460 | dev: true 461 | optional: true 462 | 463 | /@esbuild/win32-x64@0.17.19: 464 | resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} 465 | engines: {node: '>=12'} 466 | cpu: [x64] 467 | os: [win32] 468 | requiresBuild: true 469 | dev: true 470 | optional: true 471 | 472 | /@jridgewell/gen-mapping@0.3.3: 473 | resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} 474 | engines: {node: '>=6.0.0'} 475 | dependencies: 476 | '@jridgewell/set-array': 1.1.2 477 | '@jridgewell/sourcemap-codec': 1.4.15 478 | '@jridgewell/trace-mapping': 0.3.18 479 | dev: true 480 | 481 | /@jridgewell/resolve-uri@3.1.0: 482 | resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} 483 | engines: {node: '>=6.0.0'} 484 | dev: true 485 | 486 | /@jridgewell/set-array@1.1.2: 487 | resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} 488 | engines: {node: '>=6.0.0'} 489 | dev: true 490 | 491 | /@jridgewell/sourcemap-codec@1.4.14: 492 | resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} 493 | dev: true 494 | 495 | /@jridgewell/sourcemap-codec@1.4.15: 496 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 497 | dev: true 498 | 499 | /@jridgewell/trace-mapping@0.3.18: 500 | resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} 501 | dependencies: 502 | '@jridgewell/resolve-uri': 3.1.0 503 | '@jridgewell/sourcemap-codec': 1.4.14 504 | dev: true 505 | 506 | /@jsdevtools/ez-spawn@3.0.4: 507 | resolution: {integrity: sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==} 508 | engines: {node: '>=10'} 509 | dependencies: 510 | call-me-maybe: 1.0.2 511 | cross-spawn: 7.0.3 512 | string-argv: 0.3.2 513 | type-detect: 4.0.8 514 | dev: true 515 | 516 | /@nodelib/fs.scandir@2.1.5: 517 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 518 | engines: {node: '>= 8'} 519 | dependencies: 520 | '@nodelib/fs.stat': 2.0.5 521 | run-parallel: 1.2.0 522 | dev: true 523 | 524 | /@nodelib/fs.stat@2.0.5: 525 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 526 | engines: {node: '>= 8'} 527 | dev: true 528 | 529 | /@nodelib/fs.walk@1.2.8: 530 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 531 | engines: {node: '>= 8'} 532 | dependencies: 533 | '@nodelib/fs.scandir': 2.1.5 534 | fastq: 1.15.0 535 | dev: true 536 | 537 | /@types/prop-types@15.7.5: 538 | resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} 539 | dev: true 540 | 541 | /@types/react-dom@18.2.4: 542 | resolution: {integrity: sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw==} 543 | dependencies: 544 | '@types/react': 18.2.8 545 | dev: true 546 | 547 | /@types/react-highlight-words@0.16.4: 548 | resolution: {integrity: sha512-KITBX3xzheQLu2s3bUgLmRE7ekmhc52zRjRTwkKayQARh30L4fjEGzGm7ULK9TuX2LgxWWavZqyQGDGjAHbL3w==} 549 | dependencies: 550 | '@types/react': 18.2.8 551 | dev: true 552 | 553 | /@types/react@18.2.8: 554 | resolution: {integrity: sha512-lTyWUNrd8ntVkqycEEplasWy2OxNlShj3zqS0LuB1ENUGis5HodmhM7DtCoUGbxj3VW/WsGA0DUhpG6XrM7gPA==} 555 | dependencies: 556 | '@types/prop-types': 15.7.5 557 | '@types/scheduler': 0.16.3 558 | csstype: 3.1.2 559 | dev: true 560 | 561 | /@types/scheduler@0.16.3: 562 | resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} 563 | dev: true 564 | 565 | /@vitejs/plugin-react@4.0.0(vite@4.3.9): 566 | resolution: {integrity: sha512-HX0XzMjL3hhOYm+0s95pb0Z7F8O81G7joUHgfDd/9J/ZZf5k4xX6QAMFkKsHFxaHlf6X7GD7+XuaZ66ULiJuhQ==} 567 | engines: {node: ^14.18.0 || >=16.0.0} 568 | peerDependencies: 569 | vite: ^4.2.0 570 | dependencies: 571 | '@babel/core': 7.22.1 572 | '@babel/plugin-transform-react-jsx-self': 7.21.0(@babel/core@7.22.1) 573 | '@babel/plugin-transform-react-jsx-source': 7.19.6(@babel/core@7.22.1) 574 | react-refresh: 0.14.0 575 | vite: 4.3.9 576 | transitivePeerDependencies: 577 | - supports-color 578 | dev: true 579 | 580 | /acorn-walk@8.2.0: 581 | resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} 582 | engines: {node: '>=0.4.0'} 583 | dev: true 584 | 585 | /acorn@8.8.2: 586 | resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} 587 | engines: {node: '>=0.4.0'} 588 | hasBin: true 589 | dev: true 590 | 591 | /address@1.2.2: 592 | resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} 593 | engines: {node: '>= 10.0.0'} 594 | dev: true 595 | 596 | /agent-base@6.0.2: 597 | resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} 598 | engines: {node: '>= 6.0.0'} 599 | dependencies: 600 | debug: 4.3.4 601 | transitivePeerDependencies: 602 | - supports-color 603 | dev: true 604 | 605 | /ansi-styles@3.2.1: 606 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} 607 | engines: {node: '>=4'} 608 | dependencies: 609 | color-convert: 1.9.3 610 | dev: true 611 | 612 | /anymatch@3.1.3: 613 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 614 | engines: {node: '>= 8'} 615 | dependencies: 616 | normalize-path: 3.0.0 617 | picomatch: 2.3.1 618 | dev: true 619 | 620 | /binary-extensions@2.2.0: 621 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 622 | engines: {node: '>=8'} 623 | dev: true 624 | 625 | /braces@3.0.2: 626 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 627 | engines: {node: '>=8'} 628 | dependencies: 629 | fill-range: 7.0.1 630 | dev: true 631 | 632 | /browserslist@4.21.7: 633 | resolution: {integrity: sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA==} 634 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 635 | hasBin: true 636 | dependencies: 637 | caniuse-lite: 1.0.30001492 638 | electron-to-chromium: 1.4.416 639 | node-releases: 2.0.12 640 | update-browserslist-db: 1.0.11(browserslist@4.21.7) 641 | dev: true 642 | 643 | /bumpp@9.1.0: 644 | resolution: {integrity: sha512-m3+YD8uoa0VttG+RV4oKr3lK60gkUn1yPDaBTFwT7xrdJUsy7Jm0VYgx457HI3VPAOX8szLmy1x2y1QcvB+M8Q==} 645 | engines: {node: '>=10'} 646 | hasBin: true 647 | dependencies: 648 | '@jsdevtools/ez-spawn': 3.0.4 649 | c12: 1.4.1 650 | cac: 6.7.14 651 | fast-glob: 3.2.12 652 | prompts: 2.4.2 653 | semver: 7.5.1 654 | transitivePeerDependencies: 655 | - supports-color 656 | dev: true 657 | 658 | /c12@1.4.1: 659 | resolution: {integrity: sha512-0x7pWfLZpZsgtyotXtuepJc0rZYE0Aw8PwNAXs0jSG9zq6Sl5xmbWnFqfmRY01ieZLHNbvneSFm9/x88CvzAuw==} 660 | dependencies: 661 | chokidar: 3.5.3 662 | defu: 6.1.2 663 | dotenv: 16.1.3 664 | giget: 1.1.2 665 | jiti: 1.18.2 666 | mlly: 1.3.0 667 | ohash: 1.1.2 668 | pathe: 1.1.1 669 | perfect-debounce: 0.1.3 670 | pkg-types: 1.0.3 671 | rc9: 2.1.0 672 | transitivePeerDependencies: 673 | - supports-color 674 | dev: true 675 | 676 | /cac@6.7.14: 677 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 678 | engines: {node: '>=8'} 679 | dev: true 680 | 681 | /call-me-maybe@1.0.2: 682 | resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} 683 | dev: true 684 | 685 | /caniuse-lite@1.0.30001492: 686 | resolution: {integrity: sha512-2efF8SAZwgAX1FJr87KWhvuJxnGJKOnctQa8xLOskAXNXq8oiuqgl6u1kk3fFpsp3GgvzlRjiK1sl63hNtFADw==} 687 | dev: true 688 | 689 | /chalk@2.4.2: 690 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} 691 | engines: {node: '>=4'} 692 | dependencies: 693 | ansi-styles: 3.2.1 694 | escape-string-regexp: 1.0.5 695 | supports-color: 5.5.0 696 | dev: true 697 | 698 | /chokidar@3.5.3: 699 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} 700 | engines: {node: '>= 8.10.0'} 701 | dependencies: 702 | anymatch: 3.1.3 703 | braces: 3.0.2 704 | glob-parent: 5.1.2 705 | is-binary-path: 2.1.0 706 | is-glob: 4.0.3 707 | normalize-path: 3.0.0 708 | readdirp: 3.6.0 709 | optionalDependencies: 710 | fsevents: 2.3.2 711 | dev: true 712 | 713 | /chownr@2.0.0: 714 | resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} 715 | engines: {node: '>=10'} 716 | dev: true 717 | 718 | /color-convert@1.9.3: 719 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 720 | dependencies: 721 | color-name: 1.1.3 722 | dev: true 723 | 724 | /color-name@1.1.3: 725 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} 726 | dev: true 727 | 728 | /colorette@2.0.20: 729 | resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} 730 | dev: true 731 | 732 | /convert-source-map@1.9.0: 733 | resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} 734 | dev: true 735 | 736 | /cross-spawn@7.0.3: 737 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 738 | engines: {node: '>= 8'} 739 | dependencies: 740 | path-key: 3.1.1 741 | shebang-command: 2.0.0 742 | which: 2.0.2 743 | dev: true 744 | 745 | /csstype@3.1.2: 746 | resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} 747 | dev: true 748 | 749 | /debug@4.3.4: 750 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 751 | engines: {node: '>=6.0'} 752 | peerDependencies: 753 | supports-color: '*' 754 | peerDependenciesMeta: 755 | supports-color: 756 | optional: true 757 | dependencies: 758 | ms: 2.1.2 759 | dev: true 760 | 761 | /define-lazy-prop@2.0.0: 762 | resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} 763 | engines: {node: '>=8'} 764 | dev: true 765 | 766 | /defu@6.1.2: 767 | resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==} 768 | dev: true 769 | 770 | /destr@1.2.2: 771 | resolution: {integrity: sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA==} 772 | dev: true 773 | 774 | /detect-port@1.5.1: 775 | resolution: {integrity: sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==} 776 | hasBin: true 777 | dependencies: 778 | address: 1.2.2 779 | debug: 4.3.4 780 | transitivePeerDependencies: 781 | - supports-color 782 | dev: true 783 | 784 | /dom-serializer@2.0.0: 785 | resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} 786 | dependencies: 787 | domelementtype: 2.3.0 788 | domhandler: 5.0.3 789 | entities: 4.5.0 790 | dev: true 791 | 792 | /domelementtype@2.3.0: 793 | resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} 794 | dev: true 795 | 796 | /domhandler@5.0.3: 797 | resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} 798 | engines: {node: '>= 4'} 799 | dependencies: 800 | domelementtype: 2.3.0 801 | dev: true 802 | 803 | /domutils@3.1.0: 804 | resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} 805 | dependencies: 806 | dom-serializer: 2.0.0 807 | domelementtype: 2.3.0 808 | domhandler: 5.0.3 809 | dev: true 810 | 811 | /dotenv@16.1.3: 812 | resolution: {integrity: sha512-FYssxsmCTtKL72fGBSvb1K9dRz0/VZeWqFme/vSb7r7323x4CRaHu4LvQ5JG3+s6yt2YPbBrkpiEODktfyjI9A==} 813 | engines: {node: '>=12'} 814 | dev: true 815 | 816 | /electron-to-chromium@1.4.416: 817 | resolution: {integrity: sha512-AUYh0XDTb2vrj0rj82jb3P9hHSyzQNdTPYWZIhPdCOui7/vpme7+HTE07BE5jwuqg/34TZ8ktlRz6GImJ4IXjA==} 818 | dev: true 819 | 820 | /entities@4.5.0: 821 | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 822 | engines: {node: '>=0.12'} 823 | dev: true 824 | 825 | /esbuild@0.17.19: 826 | resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} 827 | engines: {node: '>=12'} 828 | hasBin: true 829 | requiresBuild: true 830 | optionalDependencies: 831 | '@esbuild/android-arm': 0.17.19 832 | '@esbuild/android-arm64': 0.17.19 833 | '@esbuild/android-x64': 0.17.19 834 | '@esbuild/darwin-arm64': 0.17.19 835 | '@esbuild/darwin-x64': 0.17.19 836 | '@esbuild/freebsd-arm64': 0.17.19 837 | '@esbuild/freebsd-x64': 0.17.19 838 | '@esbuild/linux-arm': 0.17.19 839 | '@esbuild/linux-arm64': 0.17.19 840 | '@esbuild/linux-ia32': 0.17.19 841 | '@esbuild/linux-loong64': 0.17.19 842 | '@esbuild/linux-mips64el': 0.17.19 843 | '@esbuild/linux-ppc64': 0.17.19 844 | '@esbuild/linux-riscv64': 0.17.19 845 | '@esbuild/linux-s390x': 0.17.19 846 | '@esbuild/linux-x64': 0.17.19 847 | '@esbuild/netbsd-x64': 0.17.19 848 | '@esbuild/openbsd-x64': 0.17.19 849 | '@esbuild/sunos-x64': 0.17.19 850 | '@esbuild/win32-arm64': 0.17.19 851 | '@esbuild/win32-ia32': 0.17.19 852 | '@esbuild/win32-x64': 0.17.19 853 | dev: true 854 | 855 | /escalade@3.1.1: 856 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 857 | engines: {node: '>=6'} 858 | dev: true 859 | 860 | /escape-string-regexp@1.0.5: 861 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} 862 | engines: {node: '>=0.8.0'} 863 | dev: true 864 | 865 | /fast-glob@3.2.12: 866 | resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} 867 | engines: {node: '>=8.6.0'} 868 | dependencies: 869 | '@nodelib/fs.stat': 2.0.5 870 | '@nodelib/fs.walk': 1.2.8 871 | glob-parent: 5.1.2 872 | merge2: 1.4.1 873 | micromatch: 4.0.5 874 | dev: true 875 | 876 | /fastq@1.15.0: 877 | resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} 878 | dependencies: 879 | reusify: 1.0.4 880 | dev: true 881 | 882 | /fill-range@7.0.1: 883 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 884 | engines: {node: '>=8'} 885 | dependencies: 886 | to-regex-range: 5.0.1 887 | dev: true 888 | 889 | /flat@5.0.2: 890 | resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} 891 | hasBin: true 892 | dev: true 893 | 894 | /fs-minipass@2.1.0: 895 | resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} 896 | engines: {node: '>= 8'} 897 | dependencies: 898 | minipass: 3.3.6 899 | dev: true 900 | 901 | /fsevents@2.3.2: 902 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 903 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 904 | os: [darwin] 905 | requiresBuild: true 906 | dev: true 907 | optional: true 908 | 909 | /gensync@1.0.0-beta.2: 910 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 911 | engines: {node: '>=6.9.0'} 912 | dev: true 913 | 914 | /giget@1.1.2: 915 | resolution: {integrity: sha512-HsLoS07HiQ5oqvObOI+Qb2tyZH4Gj5nYGfF9qQcZNrPw+uEFhdXtgJr01aO2pWadGHucajYDLxxbtQkm97ON2A==} 916 | hasBin: true 917 | dependencies: 918 | colorette: 2.0.20 919 | defu: 6.1.2 920 | https-proxy-agent: 5.0.1 921 | mri: 1.2.0 922 | node-fetch-native: 1.1.1 923 | pathe: 1.1.1 924 | tar: 6.1.15 925 | transitivePeerDependencies: 926 | - supports-color 927 | dev: true 928 | 929 | /glob-parent@5.1.2: 930 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 931 | engines: {node: '>= 6'} 932 | dependencies: 933 | is-glob: 4.0.3 934 | dev: true 935 | 936 | /globals@11.12.0: 937 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} 938 | engines: {node: '>=4'} 939 | dev: true 940 | 941 | /has-flag@3.0.0: 942 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} 943 | engines: {node: '>=4'} 944 | dev: true 945 | 946 | /highlight-words-core@1.2.2: 947 | resolution: {integrity: sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg==} 948 | dev: false 949 | 950 | /htmlparser2@8.0.2: 951 | resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} 952 | dependencies: 953 | domelementtype: 2.3.0 954 | domhandler: 5.0.3 955 | domutils: 3.1.0 956 | entities: 4.5.0 957 | dev: true 958 | 959 | /https-proxy-agent@5.0.1: 960 | resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} 961 | engines: {node: '>= 6'} 962 | dependencies: 963 | agent-base: 6.0.2 964 | debug: 4.3.4 965 | transitivePeerDependencies: 966 | - supports-color 967 | dev: true 968 | 969 | /is-binary-path@2.1.0: 970 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 971 | engines: {node: '>=8'} 972 | dependencies: 973 | binary-extensions: 2.2.0 974 | dev: true 975 | 976 | /is-docker@2.2.1: 977 | resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} 978 | engines: {node: '>=8'} 979 | hasBin: true 980 | dev: true 981 | 982 | /is-extglob@2.1.1: 983 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 984 | engines: {node: '>=0.10.0'} 985 | dev: true 986 | 987 | /is-glob@4.0.3: 988 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 989 | engines: {node: '>=0.10.0'} 990 | dependencies: 991 | is-extglob: 2.1.1 992 | dev: true 993 | 994 | /is-number@7.0.0: 995 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 996 | engines: {node: '>=0.12.0'} 997 | dev: true 998 | 999 | /is-wsl@2.2.0: 1000 | resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} 1001 | engines: {node: '>=8'} 1002 | dependencies: 1003 | is-docker: 2.2.1 1004 | dev: true 1005 | 1006 | /isexe@2.0.0: 1007 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1008 | dev: true 1009 | 1010 | /jiti@1.18.2: 1011 | resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==} 1012 | hasBin: true 1013 | dev: true 1014 | 1015 | /js-tokens@4.0.0: 1016 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1017 | 1018 | /jsesc@2.5.2: 1019 | resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} 1020 | engines: {node: '>=4'} 1021 | hasBin: true 1022 | dev: true 1023 | 1024 | /json5@2.2.3: 1025 | resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} 1026 | engines: {node: '>=6'} 1027 | hasBin: true 1028 | dev: true 1029 | 1030 | /jsonc-parser@3.2.0: 1031 | resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} 1032 | dev: true 1033 | 1034 | /kleur@3.0.3: 1035 | resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} 1036 | engines: {node: '>=6'} 1037 | dev: true 1038 | 1039 | /loose-envify@1.4.0: 1040 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 1041 | hasBin: true 1042 | dependencies: 1043 | js-tokens: 4.0.0 1044 | dev: false 1045 | 1046 | /lru-cache@5.1.1: 1047 | resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} 1048 | dependencies: 1049 | yallist: 3.1.1 1050 | dev: true 1051 | 1052 | /lru-cache@6.0.0: 1053 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 1054 | engines: {node: '>=10'} 1055 | dependencies: 1056 | yallist: 4.0.0 1057 | dev: true 1058 | 1059 | /magic-string@0.30.0: 1060 | resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} 1061 | engines: {node: '>=12'} 1062 | dependencies: 1063 | '@jridgewell/sourcemap-codec': 1.4.15 1064 | dev: true 1065 | 1066 | /memoize-one@4.0.3: 1067 | resolution: {integrity: sha512-QmpUu4KqDmX0plH4u+tf0riMc1KHE1+lw95cMrLlXQAFOx/xnBtwhZ52XJxd9X2O6kwKBqX32kmhbhlobD0cuw==} 1068 | dev: false 1069 | 1070 | /merge2@1.4.1: 1071 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1072 | engines: {node: '>= 8'} 1073 | dev: true 1074 | 1075 | /micromatch@4.0.5: 1076 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 1077 | engines: {node: '>=8.6'} 1078 | dependencies: 1079 | braces: 3.0.2 1080 | picomatch: 2.3.1 1081 | dev: true 1082 | 1083 | /minipass@3.3.6: 1084 | resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} 1085 | engines: {node: '>=8'} 1086 | dependencies: 1087 | yallist: 4.0.0 1088 | dev: true 1089 | 1090 | /minipass@5.0.0: 1091 | resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} 1092 | engines: {node: '>=8'} 1093 | dev: true 1094 | 1095 | /minizlib@2.1.2: 1096 | resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} 1097 | engines: {node: '>= 8'} 1098 | dependencies: 1099 | minipass: 3.3.6 1100 | yallist: 4.0.0 1101 | dev: true 1102 | 1103 | /mkdirp@1.0.4: 1104 | resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} 1105 | engines: {node: '>=10'} 1106 | hasBin: true 1107 | dev: true 1108 | 1109 | /mlly@1.3.0: 1110 | resolution: {integrity: sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==} 1111 | dependencies: 1112 | acorn: 8.8.2 1113 | pathe: 1.1.1 1114 | pkg-types: 1.0.3 1115 | ufo: 1.1.2 1116 | dev: true 1117 | 1118 | /mri@1.2.0: 1119 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 1120 | engines: {node: '>=4'} 1121 | dev: true 1122 | 1123 | /mrmime@1.0.1: 1124 | resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} 1125 | engines: {node: '>=10'} 1126 | dev: true 1127 | 1128 | /ms@2.1.2: 1129 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1130 | dev: true 1131 | 1132 | /nanoid@3.3.6: 1133 | resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} 1134 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1135 | hasBin: true 1136 | dev: true 1137 | 1138 | /node-fetch-native@1.1.1: 1139 | resolution: {integrity: sha512-9VvspTSUp2Sxbl+9vbZTlFGq9lHwE8GDVVekxx6YsNd1YH59sb3Ba8v3Y3cD8PkLNcileGGcA21PFjVl0jzDaw==} 1140 | dev: true 1141 | 1142 | /node-releases@2.0.12: 1143 | resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} 1144 | dev: true 1145 | 1146 | /normalize-path@3.0.0: 1147 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 1148 | engines: {node: '>=0.10.0'} 1149 | dev: true 1150 | 1151 | /object-assign@4.1.1: 1152 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1153 | engines: {node: '>=0.10.0'} 1154 | dev: false 1155 | 1156 | /ohash@1.1.2: 1157 | resolution: {integrity: sha512-9CIOSq5945rI045GFtcO3uudyOkYVY1nyfFxVQp+9BRgslr8jPNiSSrsFGg/BNTUFOLqx0P5tng6G32brIPw0w==} 1158 | dev: true 1159 | 1160 | /open@8.4.2: 1161 | resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} 1162 | engines: {node: '>=12'} 1163 | dependencies: 1164 | define-lazy-prop: 2.0.0 1165 | is-docker: 2.2.1 1166 | is-wsl: 2.2.0 1167 | dev: true 1168 | 1169 | /path-key@3.1.1: 1170 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1171 | engines: {node: '>=8'} 1172 | dev: true 1173 | 1174 | /pathe@1.1.1: 1175 | resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} 1176 | dev: true 1177 | 1178 | /perfect-debounce@0.1.3: 1179 | resolution: {integrity: sha512-NOT9AcKiDGpnV/HBhI22Str++XWcErO/bALvHCuhv33owZW/CjH8KAFLZDCmu3727sihe0wTxpDhyGc6M8qacQ==} 1180 | dev: true 1181 | 1182 | /picocolors@1.0.0: 1183 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 1184 | dev: true 1185 | 1186 | /picomatch@2.3.1: 1187 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1188 | engines: {node: '>=8.6'} 1189 | dev: true 1190 | 1191 | /pkg-types@1.0.3: 1192 | resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} 1193 | dependencies: 1194 | jsonc-parser: 3.2.0 1195 | mlly: 1.3.0 1196 | pathe: 1.1.1 1197 | dev: true 1198 | 1199 | /postcss@8.4.24: 1200 | resolution: {integrity: sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==} 1201 | engines: {node: ^10 || ^12 || >=14} 1202 | dependencies: 1203 | nanoid: 3.3.6 1204 | picocolors: 1.0.0 1205 | source-map-js: 1.0.2 1206 | dev: true 1207 | 1208 | /prompts@2.4.2: 1209 | resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} 1210 | engines: {node: '>= 6'} 1211 | dependencies: 1212 | kleur: 3.0.3 1213 | sisteransi: 1.0.5 1214 | dev: true 1215 | 1216 | /prop-types@15.8.1: 1217 | resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} 1218 | dependencies: 1219 | loose-envify: 1.4.0 1220 | object-assign: 4.1.1 1221 | react-is: 16.13.1 1222 | dev: false 1223 | 1224 | /queue-microtask@1.2.3: 1225 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1226 | dev: true 1227 | 1228 | /rc9@2.1.0: 1229 | resolution: {integrity: sha512-ROO9bv8PPqngWKoiUZU3JDQ4sugpdRs9DfwHnzDSxK25XtQn6BEHL6EOd/OtKuDT2qodrtNR+0WkPT6l0jxH5Q==} 1230 | dependencies: 1231 | defu: 6.1.2 1232 | destr: 1.2.2 1233 | flat: 5.0.2 1234 | dev: true 1235 | 1236 | /react-dom@18.2.0(react@18.2.0): 1237 | resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} 1238 | peerDependencies: 1239 | react: ^18.2.0 1240 | dependencies: 1241 | loose-envify: 1.4.0 1242 | react: 18.2.0 1243 | scheduler: 0.23.0 1244 | dev: false 1245 | 1246 | /react-highlight-words@0.20.0(react@18.2.0): 1247 | resolution: {integrity: sha512-asCxy+jCehDVhusNmCBoxDf2mm1AJ//D+EzDx1m5K7EqsMBIHdZ5G4LdwbSEXqZq1Ros0G0UySWmAtntSph7XA==} 1248 | peerDependencies: 1249 | react: ^0.14.0 || ^15.0.0 || ^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0 1250 | dependencies: 1251 | highlight-words-core: 1.2.2 1252 | memoize-one: 4.0.3 1253 | prop-types: 15.8.1 1254 | react: 18.2.0 1255 | dev: false 1256 | 1257 | /react-is@16.13.1: 1258 | resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} 1259 | dev: false 1260 | 1261 | /react-refresh@0.14.0: 1262 | resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} 1263 | engines: {node: '>=0.10.0'} 1264 | dev: true 1265 | 1266 | /react@18.2.0: 1267 | resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} 1268 | engines: {node: '>=0.10.0'} 1269 | dependencies: 1270 | loose-envify: 1.4.0 1271 | dev: false 1272 | 1273 | /readdirp@3.6.0: 1274 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1275 | engines: {node: '>=8.10.0'} 1276 | dependencies: 1277 | picomatch: 2.3.1 1278 | dev: true 1279 | 1280 | /reusify@1.0.4: 1281 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1282 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1283 | dev: true 1284 | 1285 | /rollup@3.23.0: 1286 | resolution: {integrity: sha512-h31UlwEi7FHihLe1zbk+3Q7z1k/84rb9BSwmBSr/XjOCEaBJ2YyedQDuM0t/kfOS0IxM+vk1/zI9XxYj9V+NJQ==} 1287 | engines: {node: '>=14.18.0', npm: '>=8.0.0'} 1288 | hasBin: true 1289 | optionalDependencies: 1290 | fsevents: 2.3.2 1291 | dev: true 1292 | 1293 | /run-parallel@1.2.0: 1294 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1295 | dependencies: 1296 | queue-microtask: 1.2.3 1297 | dev: true 1298 | 1299 | /scheduler@0.23.0: 1300 | resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} 1301 | dependencies: 1302 | loose-envify: 1.4.0 1303 | dev: false 1304 | 1305 | /semver@6.3.0: 1306 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} 1307 | hasBin: true 1308 | dev: true 1309 | 1310 | /semver@7.5.1: 1311 | resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==} 1312 | engines: {node: '>=10'} 1313 | hasBin: true 1314 | dependencies: 1315 | lru-cache: 6.0.0 1316 | dev: true 1317 | 1318 | /shebang-command@2.0.0: 1319 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1320 | engines: {node: '>=8'} 1321 | dependencies: 1322 | shebang-regex: 3.0.0 1323 | dev: true 1324 | 1325 | /shebang-regex@3.0.0: 1326 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1327 | engines: {node: '>=8'} 1328 | dev: true 1329 | 1330 | /sisteransi@1.0.5: 1331 | resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} 1332 | dev: true 1333 | 1334 | /source-map-js@1.0.2: 1335 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 1336 | engines: {node: '>=0.10.0'} 1337 | dev: true 1338 | 1339 | /string-argv@0.3.2: 1340 | resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} 1341 | engines: {node: '>=0.6.19'} 1342 | dev: true 1343 | 1344 | /supports-color@5.5.0: 1345 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 1346 | engines: {node: '>=4'} 1347 | dependencies: 1348 | has-flag: 3.0.0 1349 | dev: true 1350 | 1351 | /systemjs@6.14.1: 1352 | resolution: {integrity: sha512-8ftwWd+XnQtZ/aGbatrN4QFNGrKJzmbtixW+ODpci7pyoTajg4sonPP8aFLESAcuVxaC1FyDESt+SpfFCH9rZQ==} 1353 | dev: true 1354 | 1355 | /tar@6.1.15: 1356 | resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==} 1357 | engines: {node: '>=10'} 1358 | dependencies: 1359 | chownr: 2.0.0 1360 | fs-minipass: 2.1.0 1361 | minipass: 5.0.0 1362 | minizlib: 2.1.2 1363 | mkdirp: 1.0.4 1364 | yallist: 4.0.0 1365 | dev: true 1366 | 1367 | /to-fast-properties@2.0.0: 1368 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 1369 | engines: {node: '>=4'} 1370 | dev: true 1371 | 1372 | /to-regex-range@5.0.1: 1373 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1374 | engines: {node: '>=8.0'} 1375 | dependencies: 1376 | is-number: 7.0.0 1377 | dev: true 1378 | 1379 | /type-detect@4.0.8: 1380 | resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} 1381 | engines: {node: '>=4'} 1382 | dev: true 1383 | 1384 | /typescript@5.1.3: 1385 | resolution: {integrity: sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==} 1386 | engines: {node: '>=14.17'} 1387 | hasBin: true 1388 | dev: true 1389 | 1390 | /ufo@1.1.2: 1391 | resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} 1392 | dev: true 1393 | 1394 | /update-browserslist-db@1.0.11(browserslist@4.21.7): 1395 | resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} 1396 | hasBin: true 1397 | peerDependencies: 1398 | browserslist: '>= 4.21.0' 1399 | dependencies: 1400 | browserslist: 4.21.7 1401 | escalade: 3.1.1 1402 | picocolors: 1.0.0 1403 | dev: true 1404 | 1405 | /vite-plugin-monkey@3.2.2(vite@4.3.9): 1406 | resolution: {integrity: sha512-h4pcTAVelBG3AYyMMAZu8tKLVo6Oeycul5MHkNOuvSusMq7Cm08q/VMG7eDZlFw1/Vww2Z6O242F1rGCQ1iHAQ==} 1407 | engines: {node: ^14.18 || >= 16, pnpm: '>=6'} 1408 | peerDependencies: 1409 | vite: '>=3.0.0' 1410 | peerDependenciesMeta: 1411 | vite: 1412 | optional: true 1413 | dependencies: 1414 | acorn-walk: 8.2.0 1415 | cross-spawn: 7.0.3 1416 | detect-port: 1.5.1 1417 | htmlparser2: 8.0.2 1418 | magic-string: 0.30.0 1419 | mrmime: 1.0.1 1420 | open: 8.4.2 1421 | picocolors: 1.0.0 1422 | systemjs: 6.14.1 1423 | vite: 4.3.9 1424 | transitivePeerDependencies: 1425 | - supports-color 1426 | dev: true 1427 | 1428 | /vite@4.3.9: 1429 | resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} 1430 | engines: {node: ^14.18.0 || >=16.0.0} 1431 | hasBin: true 1432 | peerDependencies: 1433 | '@types/node': '>= 14' 1434 | less: '*' 1435 | sass: '*' 1436 | stylus: '*' 1437 | sugarss: '*' 1438 | terser: ^5.4.0 1439 | peerDependenciesMeta: 1440 | '@types/node': 1441 | optional: true 1442 | less: 1443 | optional: true 1444 | sass: 1445 | optional: true 1446 | stylus: 1447 | optional: true 1448 | sugarss: 1449 | optional: true 1450 | terser: 1451 | optional: true 1452 | dependencies: 1453 | esbuild: 0.17.19 1454 | postcss: 8.4.24 1455 | rollup: 3.23.0 1456 | optionalDependencies: 1457 | fsevents: 2.3.2 1458 | dev: true 1459 | 1460 | /which@2.0.2: 1461 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1462 | engines: {node: '>= 8'} 1463 | hasBin: true 1464 | dependencies: 1465 | isexe: 2.0.0 1466 | dev: true 1467 | 1468 | /yallist@3.1.1: 1469 | resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} 1470 | dev: true 1471 | 1472 | /yallist@4.0.0: 1473 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 1474 | dev: true 1475 | -------------------------------------------------------------------------------- /screenshot.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pacexy/userscript-bilibili-comment-search/256188effc917beae2f08a438f910e0b76eae5d6/screenshot.webp -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | #comment-search-root { 2 | float: right; 3 | } 4 | 5 | #comment-search-root button { 6 | margin-left: auto; 7 | border: none; 8 | padding: 4px 8px; 9 | border-radius: 4px; 10 | } 11 | 12 | #comment-search-root dialog[open] { 13 | display: block; 14 | } 15 | 16 | #comment-search-root dialog { 17 | display: none; 18 | width: 800px; 19 | margin: auto; 20 | padding: 1em; 21 | border-radius: 8px; 22 | border: none; 23 | outline: none; 24 | overflow: hidden; 25 | } 26 | #comment-search-root dialog .header { 27 | display: flex; 28 | align-items: center; 29 | } 30 | 31 | #comment-search-root dialog .header h1 { 32 | font-size: 15px; 33 | color: var(--text1); 34 | } 35 | 36 | #comment-search-root dialog .header h1 span { 37 | color: var(--text3); 38 | } 39 | 40 | #comment-search-root dialog input { 41 | padding: 5px 10px; 42 | border: 1px solid var(--Ga1); 43 | border-radius: 4px; 44 | background-color: var(--bg3); 45 | color: var(--text1); 46 | outline: none; 47 | width: 100%; 48 | margin-top: 20px; 49 | } 50 | 51 | #comment-search-root dialog .note { 52 | color: var(--text3); 53 | margin: 10px 0; 54 | } 55 | 56 | #comment-search-root dialog .comment-tree { 57 | height: 500px; 58 | overflow: auto; 59 | overscroll-behavior: contain; 60 | } 61 | 62 | #comment-search-root .comment-item { 63 | display: flex; 64 | } 65 | 66 | #comment-search-root .comment-item-avatar { 67 | border-radius: 50%; 68 | background-color: var(--Ga1); 69 | margin-right: 10px; 70 | flex-shrink: 0; 71 | } 72 | 73 | #comment-search-root .comment-item-content { 74 | } 75 | 76 | #comment-search-root .comment-item-username { 77 | font-size: 12px; 78 | font-weight: bold; 79 | margin-bottom: 4px; 80 | color: #61666d; 81 | margin-right: 12px; 82 | } 83 | 84 | #comment-search-root .comment-item-message { 85 | font-size: 14px; 86 | color: var(--text1); 87 | } 88 | 89 | #comment-search-root .comment-item-highlight { 90 | background-color: #f8eec2; 91 | } 92 | 93 | #comment-search-root .comment-item-time { 94 | color: var(--text3); 95 | margin-top: 4px; 96 | } 97 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useRef, useState } from 'react' 2 | import Highlighter from 'react-highlight-words' 3 | import { PAGE_LIMIT, fetchComments } from './api' 4 | import { Reply } from './types/reply' 5 | import { extractVideoId, formatDateTime } from './utils' 6 | import { version } from '../package.json' 7 | 8 | import './App.css' 9 | 10 | let keyword = '' 11 | 12 | export default function App() { 13 | const dialogRef = useRef(null) 14 | const inputRef = useRef(null) 15 | const [comments, setComments] = useState() 16 | const promiseRef = useRef | null>(null) 17 | 18 | return ( 19 | <> 20 | { 23 | const rect = e.currentTarget.getBoundingClientRect() 24 | if ( 25 | e.clientY < rect.top || 26 | e.clientY > rect.bottom || 27 | e.clientX < rect.left || 28 | e.clientX > rect.right 29 | ) { 30 | e.currentTarget.close() 31 | } 32 | }} 33 | > 34 |
35 |

36 | Bilibili Comment Search {''} 37 | v{version} 38 |

39 | 40 |
41 | { 45 | if (e.key === 'Enter' && promiseRef.current) { 46 | e.preventDefault() 47 | keyword = e.currentTarget.value 48 | promiseRef.current 49 | .then((allComments) => { 50 | const comments = searchComments(allComments) 51 | setComments(comments) 52 | }) 53 | .catch((e) => { 54 | console.error(e) 55 | }) 56 | } 57 | }} 58 | /> 59 |
60 | Note: 由于性能和 Rate Limit 的原因,目前仅会加载 {PAGE_LIMIT}{' '} 61 | 页评论,即 {PAGE_LIMIT} * 20 条评论,及其至多 3 条子评论。 62 |
63 |
64 | 65 |
66 |
67 | 77 | 78 | ) 79 | } 80 | 81 | interface CommentProps { 82 | comments?: Reply[] | null 83 | sub?: boolean 84 | } 85 | const CommentTree: React.FC = ({ comments, sub = false }) => { 86 | if (!comments) return null 87 | return ( 88 |
    89 | {comments 90 | .sort((c1, c2) => c1.ctime - c2.ctime) 91 | .map((comment) => ( 92 |
  • 99 | 107 |
    116 | 117 | {comment.member.uname} 118 | 119 | 126 |
    127 | {formatDateTime(comment.ctime)} 128 |
    129 | 130 |
    131 |
  • 132 | ))} 133 |
134 | ) 135 | } 136 | 137 | function searchComments(allComments: Reply[]) { 138 | return allComments.filter((comment) => { 139 | return ( 140 | comment.content.message.includes(keyword) || 141 | comment.replies?.some((reply) => reply.content.message.includes(keyword)) 142 | ) 143 | }) 144 | } 145 | -------------------------------------------------------------------------------- /src/api.ts: -------------------------------------------------------------------------------- 1 | import { CommentDetailsResponse, CommentSort, CommentType } from './types/api' 2 | import { Reply } from './types/reply' 3 | import { debug } from './utils' 4 | 5 | // for performance and rate limit, we only fetch the first 20 pages 6 | export const PAGE_LIMIT = 20 7 | const replies: Reply[] = [] 8 | 9 | export async function fetchComments(videoId: string) { 10 | if (replies.length > 0) { 11 | return replies 12 | } 13 | 14 | const pageSize = 20 15 | let page = 1 16 | 17 | while (true) { 18 | const params = new URLSearchParams({ 19 | type: CommentType.VIDEO.toString(), 20 | oid: videoId, 21 | sort: CommentSort.TIME.toString(), 22 | pn: page.toString(), 23 | ps: pageSize.toString(), 24 | }) 25 | 26 | debug(`fetch comments: page ${page}`) 27 | const response = await fetch( 28 | `https://api.bilibili.com/x/v2/reply?${params}`, 29 | { credentials: 'include' } 30 | ) 31 | 32 | const data: CommentDetailsResponse = await response.json() 33 | 34 | if (data.code !== 0) { 35 | throw new Error(`Failed to fetch comments: ${data.message}`) 36 | } 37 | 38 | if (!data.data) { 39 | throw new Error(`Failed to fetch comments: ${data.message}`) 40 | } 41 | 42 | replies.push(...(data.data.replies ?? [])) 43 | 44 | if ( 45 | page * pageSize >= 46 | Math.min(PAGE_LIMIT * pageSize, data.data.page.count) 47 | ) { 48 | break 49 | } 50 | 51 | page++ 52 | } 53 | 54 | return replies 55 | } 56 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App' 4 | import { assertEl, debug } from './utils' 5 | 6 | function run() { 7 | debug('run') 8 | const id = 'comment-search-root' 9 | let root = document.querySelector(`#${id}`) 10 | if (root) { 11 | debug('root exists') 12 | return 13 | } 14 | 15 | const container = assertEl(document.querySelector('#commentapp')) 16 | root = document.createElement('div') 17 | root.id = id 18 | container.prepend(root) 19 | 20 | debug('render') 21 | ReactDOM.createRoot(root).render( 22 | 23 | 24 | 25 | ) 26 | } 27 | 28 | window.addEventListener('load', () => { 29 | const timer = setInterval(() => { 30 | try { 31 | run() 32 | clearInterval(timer) 33 | } catch (error) { 34 | // ignore 35 | } 36 | }, 500) 37 | }) 38 | -------------------------------------------------------------------------------- /src/types/api.ts: -------------------------------------------------------------------------------- 1 | import { Reply } from './reply' 2 | 3 | interface Page { 4 | /** 5 | * 当前页码 6 | */ 7 | num: number 8 | /** 9 | * 每页项数 10 | */ 11 | size: number 12 | /** 13 | * 根评论条数 14 | */ 15 | count: number 16 | /** 17 | * 总计评论条数 18 | */ 19 | acount: number 20 | } 21 | 22 | interface Config { 23 | /** 24 | * 是否显示管理置顶 25 | */ 26 | showadmin: number 27 | /** 28 | * (?) 29 | */ 30 | showentry: number 31 | /** 32 | * 是否显示楼层号 33 | */ 34 | showfloor: number 35 | /** 36 | * 是否显示话题 37 | */ 38 | showtopic: number 39 | /** 40 | * 是否显示“UP 觉得很赞”标志 41 | */ 42 | show_up_flag: boolean 43 | /** 44 | * 是否只读评论区 45 | */ 46 | read_only: boolean 47 | /** 48 | * 是否显示删除记录 49 | */ 50 | show_del_log: boolean 51 | } 52 | 53 | interface Hot { 54 | // Define properties for each hot comment item 55 | } 56 | 57 | interface Top { 58 | // Define properties for the top comment item 59 | } 60 | 61 | interface Notice { 62 | /** 63 | * 公告正文 64 | */ 65 | content: string 66 | /** 67 | * 公告 id 68 | */ 69 | id: number 70 | /** 71 | * 公告页面链接 url 72 | */ 73 | link: string 74 | /** 75 | * 公告标题 76 | */ 77 | title: string 78 | } 79 | 80 | interface Folder { 81 | /** 82 | * 评论区是否存在折叠评论 83 | */ 84 | has_folded: boolean 85 | /** 86 | * 是否折叠? 87 | */ 88 | is_folded: boolean 89 | /** 90 | * 相关规则页面 url 91 | */ 92 | rule: string 93 | } 94 | 95 | interface Control { 96 | /** 97 | * 是否禁止新增评论 98 | * 用户涉及合约争议,锁定该用户所有稿件、动态的评论区,不允许新增评论,root_input_text和child_input_text值为“当前评论区不可新增评论” 99 | */ 100 | input_disable: boolean 101 | /** 102 | * 评论框文字 103 | */ 104 | root_input_text: string 105 | /** 106 | * 评论框文字 107 | */ 108 | child_input_text: string 109 | /** 110 | * 空评论区文字 111 | */ 112 | bg_text: string 113 | /** 114 | * 评论是否筛选后可见 115 | * false:无需筛选 116 | * true:需要筛选 117 | */ 118 | web_selection: boolean 119 | /** 120 | * 答题页面链接文字 121 | */ 122 | answer_guide_text: string 123 | /** 124 | * 答题页面图标 url 125 | */ 126 | answer_guide_icon_url: string 127 | /** 128 | * 答题页面 ios url 129 | */ 130 | answer_guide_ios_url: string 131 | /** 132 | * 答题页面安卓 url 133 | */ 134 | answer_guide_android_url: string 135 | } 136 | 137 | interface CommentSection { 138 | /** 139 | * 页信息 140 | */ 141 | page: Page 142 | /** 143 | * 评论区显示控制 144 | */ 145 | config: Config 146 | /** 147 | * 评论列表 148 | */ 149 | replies: Reply[] | null 150 | /** 151 | * 热评列表 152 | */ 153 | hots: Hot[] | null 154 | /** 155 | * 置顶评论 156 | */ 157 | upper: { 158 | /** 159 | * UP 主 mid 160 | */ 161 | mid: number 162 | /** 163 | * 置顶条目 164 | */ 165 | top: Top | null 166 | } 167 | /** 168 | * (?) 169 | */ 170 | top: null 171 | /** 172 | * 评论区公告信息 173 | */ 174 | notice: Notice | null 175 | /** 176 | * 投票评论? 177 | */ 178 | vote: number | null 179 | /** 180 | * (?) 181 | */ 182 | blacklist: number 183 | /** 184 | * (?) 185 | */ 186 | assist: number 187 | /** 188 | * 评论区类型id 189 | */ 190 | mode: number 191 | /** 192 | * 评论区支持的类型id 193 | */ 194 | support_mode: number[] 195 | /** 196 | * 折叠相关信息 197 | */ 198 | folder: Folder 199 | /** 200 | * (?) 201 | */ 202 | lottery_card: null 203 | /** 204 | * 显示bvid? 205 | */ 206 | show_bvid: boolean 207 | /** 208 | * 评论区输入属性 209 | */ 210 | control: Control 211 | } 212 | 213 | export interface CommentDetailsResponse { 214 | /** 215 | * 返回值 216 | * 0:成功 217 | * -400:请求错误 218 | * -404:无此项 219 | * 12002:评论区已关闭 220 | * 12009:评论主体的type不合法 221 | */ 222 | code: number 223 | /** 224 | * 错误信息 225 | * 默认为0 226 | */ 227 | message: string 228 | /** 229 | * 1 230 | */ 231 | ttl: number 232 | /** 233 | * 数据本体 234 | * 正确时:obj 235 | * 错误时:null 236 | */ 237 | data: CommentSection | null 238 | } 239 | 240 | /** 241 | * Enum representing the different types of comments. 242 | */ 243 | export enum CommentType { 244 | VIDEO = 1, // Video稿件 245 | TOPIC = 2, // 话题 246 | ACTIVITY = 4, // 活动 247 | SHORT_VIDEO = 5, // 小视频 248 | BAN_INFO = 6, // 小黑屋封禁信息 249 | NOTICE = 7, // 公告信息 250 | LIVE_ACTIVITY = 8, // 直播活动 251 | ACTIVITY_ARTICLE = 9, // 活动稿件 252 | LIVE_NOTICE = 10, // 直播公告 253 | ALBUM = 11, // 相簿(图片动态) 254 | COLUMN = 12, // 专栏 255 | TICKET = 13, // 票务 256 | AUDIO = 14, // 音频 257 | JURY = 15, // 风纪委员会 258 | REVIEW = 16, // 点评 259 | DYNAMIC = 17, // 动态(纯文字动态&分享) 260 | PLAYLIST = 18, // 播单 261 | MUSIC_PLAYLIST = 19, // 音乐播单 262 | COMIC_1 = 20, // 漫画 263 | COMIC_2 = 21, // 漫画 264 | COMIC_3 = 22, // 漫画 265 | COURSE = 33, // 课程 266 | } 267 | 268 | export enum CommentSort { 269 | /** 270 | * 按时间 271 | */ 272 | TIME = 0, 273 | /** 274 | * 按点赞数 275 | */ 276 | LIKES = 1, 277 | /** 278 | * 按回复数 279 | */ 280 | REPLIES = 2, 281 | } 282 | 283 | interface CommentRequestParams { 284 | /** 285 | * APP 登录 Token 286 | * APP 方式必要 287 | */ 288 | access_key?: string 289 | /** 290 | * 评论区类型代码 291 | * 类型代码见表 292 | */ 293 | type: CommentType 294 | /** 295 | * 目标评论区 id 296 | */ 297 | oid: number 298 | /** 299 | * 排序方式 300 | * 默认为0 301 | * 0:按时间 302 | * 1:按点赞数 303 | * 2:按回复数 304 | */ 305 | sort?: CommentSort 306 | /** 307 | * 是否不显示热评 308 | * 默认为0 309 | * 1:不显示 310 | * 0:显示 311 | */ 312 | nohot?: number 313 | /** 314 | * 每页项数 315 | * 默认为20 316 | * 定义域:1-20 317 | */ 318 | ps?: number 319 | /** 320 | * 页码 321 | * 默认为1 322 | */ 323 | pn?: number 324 | } 325 | -------------------------------------------------------------------------------- /src/types/reply.ts: -------------------------------------------------------------------------------- 1 | export interface Reply { 2 | rpid: number 3 | oid: number 4 | type: number 5 | mid: number 6 | root: number 7 | parent: number 8 | dialog: number 9 | count: number 10 | rcount: number 11 | state: number 12 | fansgrade: number 13 | attr: number 14 | ctime: number 15 | rpid_str: string 16 | root_str: string 17 | parent_str: string 18 | like: number 19 | action: number 20 | member: Member 21 | content: Content 22 | replies: Reply[] | null 23 | assist: number 24 | up_action: UpAction 25 | invisible: boolean 26 | reply_control: ReplyControl 27 | folder: Folder 28 | dynamic_id_str: string 29 | } 30 | 31 | interface Member { 32 | mid: string 33 | uname: string 34 | sex: string 35 | sign: string 36 | avatar: string 37 | rank: string 38 | face_nft_new: number 39 | is_senior_member: number 40 | senior: Senior 41 | level_info: LevelInfo 42 | pendant: Pendant 43 | nameplate: Nameplate 44 | official_verify: OfficialVerify 45 | vip: Vip 46 | fans_detail: any 47 | user_sailing: any 48 | is_contractor: boolean 49 | contract_desc: string 50 | nft_interaction: any 51 | avatar_item: AvatarItem 52 | } 53 | 54 | interface Senior {} 55 | 56 | interface LevelInfo { 57 | current_level: number 58 | current_min: number 59 | current_exp: number 60 | next_exp: number 61 | } 62 | 63 | interface Pendant { 64 | pid: number 65 | name: string 66 | image: string 67 | expire: number 68 | image_enhance: string 69 | image_enhance_frame: string 70 | } 71 | 72 | interface Nameplate { 73 | nid: number 74 | name: string 75 | image: string 76 | image_small: string 77 | level: string 78 | condition: string 79 | } 80 | 81 | interface OfficialVerify { 82 | type: number 83 | desc: string 84 | } 85 | 86 | interface Vip { 87 | vipType: number 88 | vipDueDate: number 89 | dueRemark: string 90 | accessStatus: number 91 | vipStatus: number 92 | vipStatusWarn: string 93 | themeType: number 94 | label: Label 95 | avatar_subscript: number 96 | nickname_color: string 97 | } 98 | 99 | interface Label { 100 | path: string 101 | text: string 102 | label_theme: string 103 | text_color: string 104 | bg_style: number 105 | bg_color: string 106 | border_color: string 107 | use_img_label: boolean 108 | img_label_uri_hans: string 109 | img_label_uri_hant: string 110 | img_label_uri_hans_static: string 111 | img_label_uri_hant_static: string 112 | } 113 | 114 | interface AvatarItem { 115 | container_size: ContainerSize 116 | fallback_layers: FallbackLayers 117 | mid: string 118 | } 119 | 120 | interface ContainerSize { 121 | width: number 122 | height: number 123 | } 124 | 125 | interface FallbackLayers { 126 | layers: Layer[] 127 | is_critical_group: boolean 128 | } 129 | 130 | interface Layer { 131 | visible: boolean 132 | general_spec: GeneralSpec 133 | layer_config: LayerConfig 134 | resource: Resource 135 | } 136 | 137 | interface GeneralSpec { 138 | pos_spec: PosSpec 139 | size_spec: SizeSpec 140 | render_spec: RenderSpec 141 | } 142 | 143 | interface PosSpec { 144 | coordinate_pos: number 145 | axis_x: number 146 | axis_y: number 147 | } 148 | 149 | interface SizeSpec { 150 | width: number 151 | height: number 152 | } 153 | 154 | interface RenderSpec { 155 | opacity: number 156 | } 157 | 158 | interface LayerConfig { 159 | tags: Tags 160 | is_critical?: boolean 161 | layer_mask?: LayerMask 162 | } 163 | 164 | interface Tags { 165 | AVATAR_LAYER?: AvatarLayer 166 | ICON_LAYER?: IconLayer 167 | } 168 | 169 | interface AvatarLayer {} 170 | 171 | interface IconLayer {} 172 | 173 | interface LayerMask { 174 | general_spec: GeneralSpec 175 | mask_src: MaskSrc 176 | } 177 | 178 | interface MaskSrc { 179 | src_type: number 180 | draw: Draw 181 | } 182 | 183 | interface Draw { 184 | draw_type: number 185 | fill_mode: number 186 | color_config: ColorConfig 187 | } 188 | 189 | interface ColorConfig { 190 | day: Day 191 | } 192 | 193 | interface Day { 194 | argb: string 195 | } 196 | 197 | interface Resource { 198 | res_type: number 199 | res_image?: ResImage 200 | res_native_draw?: ResNativeDraw 201 | } 202 | 203 | interface ResImage { 204 | image_src: ImageSrc 205 | } 206 | 207 | interface ImageSrc { 208 | src_type: number 209 | local?: number 210 | placeholder?: number 211 | remote?: Remote 212 | } 213 | 214 | interface Remote { 215 | url: string 216 | bfs_style: string 217 | } 218 | 219 | interface ResNativeDraw { 220 | draw_src: DrawSrc 221 | } 222 | 223 | interface DrawSrc { 224 | src_type: number 225 | draw: Draw 226 | } 227 | 228 | interface Night { 229 | argb: string 230 | } 231 | 232 | interface Content { 233 | message: string 234 | members: any[] 235 | emote: Emote 236 | jump_url: JumpUrl 237 | max_line: number 238 | } 239 | 240 | interface Emote { 241 | '[吃瓜]': GeneratedType 242 | } 243 | 244 | interface GeneratedType { 245 | id: number 246 | package_id: number 247 | state: number 248 | type: number 249 | attr: number 250 | text: string 251 | url: string 252 | meta: Meta 253 | mtime: number 254 | jump_title: string 255 | } 256 | 257 | interface Meta { 258 | size: number 259 | } 260 | 261 | interface JumpUrl { 262 | rul: Rul 263 | } 264 | 265 | interface Rul { 266 | title: string 267 | state: number 268 | prefix_icon: string 269 | app_url_schema: string 270 | app_name: string 271 | app_package_name: string 272 | click_report: string 273 | is_half_screen: boolean 274 | exposure_report: string 275 | extra: Extra 276 | underline: boolean 277 | match_once: boolean 278 | pc_url: string 279 | icon_position: number 280 | } 281 | 282 | interface Extra { 283 | goods_show_type: number 284 | is_word_search: boolean 285 | goods_cm_control: number 286 | goods_click_report: string 287 | goods_exposure_report: string 288 | } 289 | 290 | interface UpAction { 291 | like: boolean 292 | reply: boolean 293 | } 294 | 295 | interface ReplyControl { 296 | max_line: number 297 | time_desc: string 298 | } 299 | 300 | interface Folder { 301 | has_folded: boolean 302 | is_folded: boolean 303 | rule: string 304 | } 305 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { name } from '../package.json' 2 | 3 | export function assertEl(el: T | null) { 4 | if (!el) { 5 | throw new Error('Element not found') 6 | } 7 | return el 8 | } 9 | 10 | export function debug(message: any) { 11 | console.log(`[${name}] ${message}`) 12 | } 13 | 14 | export function extractVideoId(url: string) { 15 | const match = url.match(/\/video\/(BV\w+)\//) 16 | if (!match) { 17 | throw new Error(`Failed to extract video id from url: ${url}`) 18 | } 19 | return match[1] 20 | } 21 | 22 | export function formatDateTime(ts: number) { 23 | const date = new Date(ts * 1000) 24 | return date.toLocaleString('zh-CN', { 25 | year: 'numeric', 26 | month: '2-digit', 27 | day: '2-digit', 28 | hour: '2-digit', 29 | minute: '2-digit', 30 | hour12: false, 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | //// 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import monkey, { cdn } from 'vite-plugin-monkey' 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [ 8 | react(), 9 | monkey({ 10 | entry: 'src/main.tsx', 11 | userscript: { 12 | name: { 13 | '': 'Bilibili 评论搜索', 14 | en: 'Bilibili Comment Search', 15 | zh: 'Bilibili 评论搜索', 16 | }, 17 | description: { 18 | '': '让 Bilibili 支持评论搜索。', 19 | en: 'Add comment searching support in Bilibili.', 20 | zh: '让 Bilibili 支持评论搜索。', 21 | }, 22 | icon: 'https://www.bilibili.com/favicon.ico', 23 | namespace: 'npm/vite-plugin-monkey', 24 | match: [ 25 | '*://www.bilibili.com/video/av*', 26 | '*://www.bilibili.com/bangumi/play/ep*', 27 | '*://www.bilibili.com/bangumi/play/ss*', 28 | '*://www.bilibili.com/video/BV*', 29 | ], 30 | }, 31 | build: { 32 | externalGlobals: { 33 | react: cdn.jsdelivr('React', 'umd/react.production.min.js'), 34 | 'react-dom': cdn.jsdelivr( 35 | 'ReactDOM', 36 | 'umd/react-dom.production.min.js' 37 | ), 38 | }, 39 | }, 40 | }), 41 | ], 42 | }) 43 | --------------------------------------------------------------------------------