Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bfa12b61c | ||
|
|
79bd776ef9 | ||
|
|
222428ad47 | ||
|
|
4b3853dd22 | ||
|
|
9dd191902c | ||
|
|
3f524ad674 | ||
|
|
7e6376fcb7 | ||
|
|
6f35013faf | ||
|
|
e71acdaaa9 | ||
|
|
fd7c663282 | ||
|
|
89b2bbe9ac |
2
.env
2
.env
@@ -2,7 +2,7 @@ GENERATE_SOURCEMAP=false
|
|||||||
|
|
||||||
REACT_APP_NAME=KISS Translator
|
REACT_APP_NAME=KISS Translator
|
||||||
REACT_APP_NAME_CN=简约翻译
|
REACT_APP_NAME_CN=简约翻译
|
||||||
REACT_APP_VERSION=2.0.7
|
REACT_APP_VERSION=2.0.8
|
||||||
|
|
||||||
REACT_APP_HOMEPAGE=https://github.com/fishjar/kiss-translator
|
REACT_APP_HOMEPAGE=https://github.com/fishjar/kiss-translator
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# 自定义接口示例
|
# 自定义接口说明及示例
|
||||||
|
|
||||||
## 默认接口规范
|
## 默认接口规范
|
||||||
|
|
||||||
@@ -39,6 +39,30 @@ v2.0.4版后亦支持以下 Response 格式
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Prompt 相关
|
||||||
|
|
||||||
|
`Prompt` 可替换占位符:
|
||||||
|
|
||||||
|
```js
|
||||||
|
`{{from}}` // 原文语言名称
|
||||||
|
`{{to}}` // 目标语言名称
|
||||||
|
`{{fromLang}}` // 原文语言代码
|
||||||
|
`{{toLang}}` // 目标语言代码
|
||||||
|
`{{text}}` // 原文
|
||||||
|
`{{tone}}` // 风格
|
||||||
|
`{{title}}` // 页面标题
|
||||||
|
`{{description}}` // 页面描述
|
||||||
|
```
|
||||||
|
|
||||||
|
Hook 中 `Prompt` 类型说明:
|
||||||
|
|
||||||
|
```js
|
||||||
|
`systemPrompt` // 聚合翻译 System Prompt
|
||||||
|
`nobatchPrompt` // 非聚合翻译 System Prompt
|
||||||
|
`nobatchUserPrompt` // 非聚合翻译 User Prompt
|
||||||
|
`subtitlePrompt` // 字幕翻译 System Prompt
|
||||||
|
```
|
||||||
|
|
||||||
## 谷歌翻译接口
|
## 谷歌翻译接口
|
||||||
|
|
||||||
> 此接口不支持聚合
|
> 此接口不支持聚合
|
||||||
@@ -101,7 +125,10 @@ async (args) => {
|
|||||||
content: JSON.stringify({
|
content: JSON.stringify({
|
||||||
targetLanguage: args.toLang,
|
targetLanguage: args.toLang,
|
||||||
segments: args.texts.map((text, id) => ({ id, text })),
|
segments: args.texts.map((text, id) => ({ id, text })),
|
||||||
glossary: {},
|
title: "", // 可省略
|
||||||
|
description: "", // 可省略
|
||||||
|
glossary: {}, // 可省略
|
||||||
|
tone: "", // 可省略
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -134,7 +161,10 @@ async (args) => {
|
|||||||
content: JSON.stringify({
|
content: JSON.stringify({
|
||||||
targetLanguage: args.toLang,
|
targetLanguage: args.toLang,
|
||||||
segments: args.texts.map((text, id) => ({ id, text })),
|
segments: args.texts.map((text, id) => ({ id, text })),
|
||||||
glossary: {},
|
title: "", // 可省略
|
||||||
|
description: "", // 可省略
|
||||||
|
glossary: {}, // 可省略
|
||||||
|
tone: "", // 可省略
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -295,6 +325,7 @@ Hook参数里面的语言含义说明:
|
|||||||
["cs", "Czech - Čeština"],
|
["cs", "Czech - Čeština"],
|
||||||
["da", "Danish - Dansk"],
|
["da", "Danish - Dansk"],
|
||||||
["nl", "Dutch - Nederlands"],
|
["nl", "Dutch - Nederlands"],
|
||||||
|
["fa", "Persian - فارسی"],
|
||||||
["fi", "Finnish - Suomi"],
|
["fi", "Finnish - Suomi"],
|
||||||
["fr", "French - Français"],
|
["fr", "French - Français"],
|
||||||
["de", "German - Deutsch"],
|
["de", "German - Deutsch"],
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "kiss-translator",
|
"name": "kiss-translator",
|
||||||
"description": "A minimalist bilingual translation Extension & Greasemonkey Script",
|
"description": "A minimalist bilingual translation Extension & Greasemonkey Script",
|
||||||
"version": "2.0.7",
|
"version": "2.0.8",
|
||||||
"author": "Gabe<yugang2002@gmail.com>",
|
"author": "Gabe<yugang2002@gmail.com>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
310
pnpm-lock.yaml
generated
310
pnpm-lock.yaml
generated
@@ -87,10 +87,6 @@ importers:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
'@aashutoshrathi/word-wrap@1.2.6':
|
|
||||||
resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
|
|
||||||
'@alloc/quick-lru@5.2.0':
|
'@alloc/quick-lru@5.2.0':
|
||||||
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -109,6 +105,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==}
|
resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/code-frame@7.27.1':
|
||||||
|
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/compat-data@7.22.20':
|
'@babel/compat-data@7.22.20':
|
||||||
resolution: {integrity: sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==}
|
resolution: {integrity: sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -128,10 +128,18 @@ packages:
|
|||||||
resolution: {integrity: sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==}
|
resolution: {integrity: sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/generator@7.28.5':
|
||||||
|
resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/helper-annotate-as-pure@7.22.5':
|
'@babel/helper-annotate-as-pure@7.22.5':
|
||||||
resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
|
resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/helper-annotate-as-pure@7.27.3':
|
||||||
|
resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/helper-builder-binary-assignment-operator-visitor@7.22.15':
|
'@babel/helper-builder-binary-assignment-operator-visitor@7.22.15':
|
||||||
resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==}
|
resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -165,6 +173,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==}
|
resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/helper-globals@7.28.0':
|
||||||
|
resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/helper-hoist-variables@7.22.5':
|
'@babel/helper-hoist-variables@7.22.5':
|
||||||
resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
|
resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -181,6 +193,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==}
|
resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/helper-module-imports@7.27.1':
|
||||||
|
resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/helper-module-transforms@7.22.20':
|
'@babel/helper-module-transforms@7.22.20':
|
||||||
resolution: {integrity: sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==}
|
resolution: {integrity: sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -195,8 +211,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
|
resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/helper-plugin-utils@7.24.0':
|
'@babel/helper-plugin-utils@7.27.1':
|
||||||
resolution: {integrity: sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==}
|
resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/helper-remap-async-to-generator@7.22.20':
|
'@babel/helper-remap-async-to-generator@7.22.20':
|
||||||
@@ -231,10 +247,18 @@ packages:
|
|||||||
resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==}
|
resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/helper-string-parser@7.27.1':
|
||||||
|
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/helper-validator-identifier@7.22.20':
|
'@babel/helper-validator-identifier@7.22.20':
|
||||||
resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
|
resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/helper-validator-identifier@7.28.5':
|
||||||
|
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/helper-validator-option@7.22.15':
|
'@babel/helper-validator-option@7.22.15':
|
||||||
resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==}
|
resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -263,6 +287,11 @@ packages:
|
|||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
'@babel/parser@7.28.5':
|
||||||
|
resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
'@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.15':
|
'@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.15':
|
||||||
resolution: {integrity: sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==}
|
resolution: {integrity: sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -406,8 +435,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@babel/core': ^7.0.0-0
|
'@babel/core': ^7.0.0-0
|
||||||
|
|
||||||
'@babel/plugin-syntax-jsx@7.24.1':
|
'@babel/plugin-syntax-jsx@7.27.1':
|
||||||
resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==}
|
resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@babel/core': ^7.0.0-0
|
'@babel/core': ^7.0.0-0
|
||||||
@@ -852,10 +881,18 @@ packages:
|
|||||||
resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
|
resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/template@7.27.2':
|
||||||
|
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/traverse@7.22.20':
|
'@babel/traverse@7.22.20':
|
||||||
resolution: {integrity: sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==}
|
resolution: {integrity: sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/traverse@7.28.5':
|
||||||
|
resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/types@7.22.19':
|
'@babel/types@7.22.19':
|
||||||
resolution: {integrity: sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==}
|
resolution: {integrity: sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -864,6 +901,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==}
|
resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@babel/types@7.28.5':
|
||||||
|
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@bcoe/v8-coverage@0.2.3':
|
'@bcoe/v8-coverage@0.2.3':
|
||||||
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
|
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
|
||||||
|
|
||||||
@@ -1053,8 +1094,14 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
||||||
|
|
||||||
'@eslint-community/regexpp@4.10.0':
|
'@eslint-community/eslint-utils@4.9.0':
|
||||||
resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
|
resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
||||||
|
|
||||||
|
'@eslint-community/regexpp@4.12.2':
|
||||||
|
resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
|
||||||
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
||||||
|
|
||||||
'@eslint-community/regexpp@4.8.1':
|
'@eslint-community/regexpp@4.8.1':
|
||||||
@@ -1175,6 +1222,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==}
|
resolution: {integrity: sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==}
|
||||||
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
|
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
|
||||||
|
|
||||||
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
|
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
||||||
|
|
||||||
'@jridgewell/gen-mapping@0.3.3':
|
'@jridgewell/gen-mapping@0.3.3':
|
||||||
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
|
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
@@ -1183,6 +1233,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
|
resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
|
'@jridgewell/resolve-uri@3.1.2':
|
||||||
|
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
'@jridgewell/set-array@1.1.2':
|
'@jridgewell/set-array@1.1.2':
|
||||||
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
|
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
@@ -1193,9 +1247,15 @@ packages:
|
|||||||
'@jridgewell/sourcemap-codec@1.4.15':
|
'@jridgewell/sourcemap-codec@1.4.15':
|
||||||
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
|
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
|
||||||
|
|
||||||
|
'@jridgewell/sourcemap-codec@1.5.5':
|
||||||
|
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
||||||
|
|
||||||
'@jridgewell/trace-mapping@0.3.19':
|
'@jridgewell/trace-mapping@0.3.19':
|
||||||
resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==}
|
resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==}
|
||||||
|
|
||||||
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
|
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||||
|
|
||||||
'@leichtgewicht/ip-codec@2.0.4':
|
'@leichtgewicht/ip-codec@2.0.4':
|
||||||
resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==}
|
resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==}
|
||||||
|
|
||||||
@@ -1697,8 +1757,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
|
resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
|
||||||
'@ungap/structured-clone@1.2.0':
|
'@ungap/structured-clone@1.3.0':
|
||||||
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
|
||||||
|
|
||||||
'@webassemblyjs/ast@1.11.6':
|
'@webassemblyjs/ast@1.11.6':
|
||||||
resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==}
|
resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==}
|
||||||
@@ -1790,6 +1850,11 @@ packages:
|
|||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
acorn@8.15.0:
|
||||||
|
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
|
||||||
|
engines: {node: '>=0.4.0'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
address@1.2.2:
|
address@1.2.2:
|
||||||
resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==}
|
resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
@@ -2113,8 +2178,8 @@ packages:
|
|||||||
caniuse-api@3.0.0:
|
caniuse-api@3.0.0:
|
||||||
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
|
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
|
||||||
|
|
||||||
caniuse-lite@1.0.30001599:
|
caniuse-lite@1.0.30001754:
|
||||||
resolution: {integrity: sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==}
|
resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==}
|
||||||
|
|
||||||
case-sensitive-paths-webpack-plugin@2.4.0:
|
case-sensitive-paths-webpack-plugin@2.4.0:
|
||||||
resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==}
|
resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==}
|
||||||
@@ -2297,6 +2362,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
|
cross-spawn@7.0.6:
|
||||||
|
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
crypt@0.0.2:
|
crypt@0.0.2:
|
||||||
resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
|
resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
|
||||||
|
|
||||||
@@ -2463,6 +2532,15 @@ packages:
|
|||||||
supports-color:
|
supports-color:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
debug@4.4.3:
|
||||||
|
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
||||||
|
engines: {node: '>=6.0'}
|
||||||
|
peerDependencies:
|
||||||
|
supports-color: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
supports-color:
|
||||||
|
optional: true
|
||||||
|
|
||||||
decimal.js@10.4.3:
|
decimal.js@10.4.3:
|
||||||
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
|
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
|
||||||
|
|
||||||
@@ -2848,8 +2926,8 @@ packages:
|
|||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
esquery@1.5.0:
|
esquery@1.6.0:
|
||||||
resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
|
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
|
||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
|
|
||||||
esrecurse@4.3.0:
|
esrecurse@4.3.0:
|
||||||
@@ -2992,8 +3070,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
|
resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
|
||||||
engines: {node: ^10.12.0 || >=12.0.0}
|
engines: {node: ^10.12.0 || >=12.0.0}
|
||||||
|
|
||||||
flatted@3.3.1:
|
flatted@3.3.3:
|
||||||
resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
|
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
|
||||||
|
|
||||||
follow-redirects@1.15.3:
|
follow-redirects@1.15.3:
|
||||||
resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==}
|
resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==}
|
||||||
@@ -3297,8 +3375,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
|
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
ignore@5.3.1:
|
ignore@5.3.2:
|
||||||
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
|
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
immer@9.0.21:
|
immer@9.0.21:
|
||||||
@@ -3308,6 +3386,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
import-fresh@3.3.1:
|
||||||
|
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
import-local@3.1.0:
|
import-local@3.1.0:
|
||||||
resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
|
resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -3744,6 +3826,11 @@ packages:
|
|||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
jsesc@3.1.0:
|
||||||
|
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
json-buffer@3.0.1:
|
json-buffer@3.0.1:
|
||||||
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
|
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
|
||||||
|
|
||||||
@@ -4224,8 +4311,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==}
|
resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
|
||||||
optionator@0.9.3:
|
optionator@0.9.4:
|
||||||
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
|
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
|
||||||
p-limit@2.3.0:
|
p-limit@2.3.0:
|
||||||
@@ -4331,6 +4418,9 @@ packages:
|
|||||||
picocolors@1.0.0:
|
picocolors@1.0.0:
|
||||||
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
||||||
|
|
||||||
|
picocolors@1.1.1:
|
||||||
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||||
|
|
||||||
picomatch@2.3.1:
|
picomatch@2.3.1:
|
||||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||||
engines: {node: '>=8.6'}
|
engines: {node: '>=8.6'}
|
||||||
@@ -6021,8 +6111,6 @@ packages:
|
|||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
'@aashutoshrathi/word-wrap@1.2.6': {}
|
|
||||||
|
|
||||||
'@alloc/quick-lru@5.2.0': {}
|
'@alloc/quick-lru@5.2.0': {}
|
||||||
|
|
||||||
'@ampproject/remapping@2.2.1':
|
'@ampproject/remapping@2.2.1':
|
||||||
@@ -6042,6 +6130,12 @@ snapshots:
|
|||||||
'@babel/highlight': 7.22.20
|
'@babel/highlight': 7.22.20
|
||||||
chalk: 2.4.2
|
chalk: 2.4.2
|
||||||
|
|
||||||
|
'@babel/code-frame@7.27.1':
|
||||||
|
dependencies:
|
||||||
|
'@babel/helper-validator-identifier': 7.28.5
|
||||||
|
js-tokens: 4.0.0
|
||||||
|
picocolors: 1.1.1
|
||||||
|
|
||||||
'@babel/compat-data@7.22.20': {}
|
'@babel/compat-data@7.22.20': {}
|
||||||
|
|
||||||
'@babel/core@7.22.20':
|
'@babel/core@7.22.20':
|
||||||
@@ -6079,10 +6173,22 @@ snapshots:
|
|||||||
'@jridgewell/trace-mapping': 0.3.19
|
'@jridgewell/trace-mapping': 0.3.19
|
||||||
jsesc: 2.5.2
|
jsesc: 2.5.2
|
||||||
|
|
||||||
|
'@babel/generator@7.28.5':
|
||||||
|
dependencies:
|
||||||
|
'@babel/parser': 7.28.5
|
||||||
|
'@babel/types': 7.28.5
|
||||||
|
'@jridgewell/gen-mapping': 0.3.13
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
jsesc: 3.1.0
|
||||||
|
|
||||||
'@babel/helper-annotate-as-pure@7.22.5':
|
'@babel/helper-annotate-as-pure@7.22.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.22.19
|
'@babel/types': 7.22.19
|
||||||
|
|
||||||
|
'@babel/helper-annotate-as-pure@7.27.3':
|
||||||
|
dependencies:
|
||||||
|
'@babel/types': 7.28.5
|
||||||
|
|
||||||
'@babel/helper-builder-binary-assignment-operator-visitor@7.22.15':
|
'@babel/helper-builder-binary-assignment-operator-visitor@7.22.15':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.22.19
|
'@babel/types': 7.22.19
|
||||||
@@ -6133,6 +6239,8 @@ snapshots:
|
|||||||
'@babel/template': 7.22.15
|
'@babel/template': 7.22.15
|
||||||
'@babel/types': 7.22.19
|
'@babel/types': 7.22.19
|
||||||
|
|
||||||
|
'@babel/helper-globals@7.28.0': {}
|
||||||
|
|
||||||
'@babel/helper-hoist-variables@7.22.5':
|
'@babel/helper-hoist-variables@7.22.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.22.19
|
'@babel/types': 7.22.19
|
||||||
@@ -6149,6 +6257,13 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.24.0
|
'@babel/types': 7.24.0
|
||||||
|
|
||||||
|
'@babel/helper-module-imports@7.27.1':
|
||||||
|
dependencies:
|
||||||
|
'@babel/traverse': 7.28.5
|
||||||
|
'@babel/types': 7.28.5
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@babel/helper-module-transforms@7.22.20(@babel/core@7.22.20)':
|
'@babel/helper-module-transforms@7.22.20(@babel/core@7.22.20)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.22.20
|
'@babel/core': 7.22.20
|
||||||
@@ -6164,7 +6279,7 @@ snapshots:
|
|||||||
|
|
||||||
'@babel/helper-plugin-utils@7.22.5': {}
|
'@babel/helper-plugin-utils@7.22.5': {}
|
||||||
|
|
||||||
'@babel/helper-plugin-utils@7.24.0': {}
|
'@babel/helper-plugin-utils@7.27.1': {}
|
||||||
|
|
||||||
'@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.22.20)':
|
'@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.22.20)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6196,8 +6311,12 @@ snapshots:
|
|||||||
|
|
||||||
'@babel/helper-string-parser@7.24.1': {}
|
'@babel/helper-string-parser@7.24.1': {}
|
||||||
|
|
||||||
|
'@babel/helper-string-parser@7.27.1': {}
|
||||||
|
|
||||||
'@babel/helper-validator-identifier@7.22.20': {}
|
'@babel/helper-validator-identifier@7.22.20': {}
|
||||||
|
|
||||||
|
'@babel/helper-validator-identifier@7.28.5': {}
|
||||||
|
|
||||||
'@babel/helper-validator-option@7.22.15': {}
|
'@babel/helper-validator-option@7.22.15': {}
|
||||||
|
|
||||||
'@babel/helper-wrap-function@7.22.20':
|
'@babel/helper-wrap-function@7.22.20':
|
||||||
@@ -6234,6 +6353,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.22.19
|
'@babel/types': 7.22.19
|
||||||
|
|
||||||
|
'@babel/parser@7.28.5':
|
||||||
|
dependencies:
|
||||||
|
'@babel/types': 7.28.5
|
||||||
|
|
||||||
'@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.15(@babel/core@7.22.20)':
|
'@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.15(@babel/core@7.22.20)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.22.20
|
'@babel/core': 7.22.20
|
||||||
@@ -6341,7 +6464,7 @@ snapshots:
|
|||||||
'@babel/plugin-syntax-flow@7.24.1(@babel/core@7.22.20)':
|
'@babel/plugin-syntax-flow@7.24.1(@babel/core@7.22.20)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.22.20
|
'@babel/core': 7.22.20
|
||||||
'@babel/helper-plugin-utils': 7.24.0
|
'@babel/helper-plugin-utils': 7.27.1
|
||||||
|
|
||||||
'@babel/plugin-syntax-import-assertions@7.22.5(@babel/core@7.22.20)':
|
'@babel/plugin-syntax-import-assertions@7.22.5(@babel/core@7.22.20)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6368,10 +6491,10 @@ snapshots:
|
|||||||
'@babel/core': 7.22.20
|
'@babel/core': 7.22.20
|
||||||
'@babel/helper-plugin-utils': 7.22.5
|
'@babel/helper-plugin-utils': 7.22.5
|
||||||
|
|
||||||
'@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.22.20)':
|
'@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.22.20)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.22.20
|
'@babel/core': 7.22.20
|
||||||
'@babel/helper-plugin-utils': 7.24.0
|
'@babel/helper-plugin-utils': 7.27.1
|
||||||
|
|
||||||
'@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.20)':
|
'@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.20)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6689,11 +6812,13 @@ snapshots:
|
|||||||
'@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.22.20)':
|
'@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.22.20)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.22.20
|
'@babel/core': 7.22.20
|
||||||
'@babel/helper-annotate-as-pure': 7.22.5
|
'@babel/helper-annotate-as-pure': 7.27.3
|
||||||
'@babel/helper-module-imports': 7.24.3
|
'@babel/helper-module-imports': 7.27.1
|
||||||
'@babel/helper-plugin-utils': 7.24.0
|
'@babel/helper-plugin-utils': 7.27.1
|
||||||
'@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.22.20)
|
'@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.22.20)
|
||||||
'@babel/types': 7.24.0
|
'@babel/types': 7.28.5
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@babel/plugin-transform-react-pure-annotations@7.22.5(@babel/core@7.22.20)':
|
'@babel/plugin-transform-react-pure-annotations@7.22.5(@babel/core@7.22.20)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6918,6 +7043,12 @@ snapshots:
|
|||||||
'@babel/parser': 7.22.16
|
'@babel/parser': 7.22.16
|
||||||
'@babel/types': 7.22.19
|
'@babel/types': 7.22.19
|
||||||
|
|
||||||
|
'@babel/template@7.27.2':
|
||||||
|
dependencies:
|
||||||
|
'@babel/code-frame': 7.27.1
|
||||||
|
'@babel/parser': 7.28.5
|
||||||
|
'@babel/types': 7.28.5
|
||||||
|
|
||||||
'@babel/traverse@7.22.20':
|
'@babel/traverse@7.22.20':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.22.13
|
'@babel/code-frame': 7.22.13
|
||||||
@@ -6933,6 +7064,18 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@babel/traverse@7.28.5':
|
||||||
|
dependencies:
|
||||||
|
'@babel/code-frame': 7.27.1
|
||||||
|
'@babel/generator': 7.28.5
|
||||||
|
'@babel/helper-globals': 7.28.0
|
||||||
|
'@babel/parser': 7.28.5
|
||||||
|
'@babel/template': 7.27.2
|
||||||
|
'@babel/types': 7.28.5
|
||||||
|
debug: 4.4.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@babel/types@7.22.19':
|
'@babel/types@7.22.19':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/helper-string-parser': 7.22.5
|
'@babel/helper-string-parser': 7.22.5
|
||||||
@@ -6945,6 +7088,11 @@ snapshots:
|
|||||||
'@babel/helper-validator-identifier': 7.22.20
|
'@babel/helper-validator-identifier': 7.22.20
|
||||||
to-fast-properties: 2.0.0
|
to-fast-properties: 2.0.0
|
||||||
|
|
||||||
|
'@babel/types@7.28.5':
|
||||||
|
dependencies:
|
||||||
|
'@babel/helper-string-parser': 7.27.1
|
||||||
|
'@babel/helper-validator-identifier': 7.28.5
|
||||||
|
|
||||||
'@bcoe/v8-coverage@0.2.3': {}
|
'@bcoe/v8-coverage@0.2.3': {}
|
||||||
|
|
||||||
'@buttercup/fetch@0.1.2':
|
'@buttercup/fetch@0.1.2':
|
||||||
@@ -7163,18 +7311,23 @@ snapshots:
|
|||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-visitor-keys: 3.4.3
|
eslint-visitor-keys: 3.4.3
|
||||||
|
|
||||||
'@eslint-community/regexpp@4.10.0': {}
|
'@eslint-community/eslint-utils@4.9.0(eslint@8.57.0)':
|
||||||
|
dependencies:
|
||||||
|
eslint: 8.57.0
|
||||||
|
eslint-visitor-keys: 3.4.3
|
||||||
|
|
||||||
|
'@eslint-community/regexpp@4.12.2': {}
|
||||||
|
|
||||||
'@eslint-community/regexpp@4.8.1': {}
|
'@eslint-community/regexpp@4.8.1': {}
|
||||||
|
|
||||||
'@eslint/eslintrc@2.1.4':
|
'@eslint/eslintrc@2.1.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
debug: 4.3.4
|
debug: 4.4.3
|
||||||
espree: 9.6.1
|
espree: 9.6.1
|
||||||
globals: 13.24.0
|
globals: 13.24.0
|
||||||
ignore: 5.3.1
|
ignore: 5.3.2
|
||||||
import-fresh: 3.3.0
|
import-fresh: 3.3.1
|
||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
strip-json-comments: 3.1.1
|
strip-json-comments: 3.1.1
|
||||||
@@ -7203,7 +7356,7 @@ snapshots:
|
|||||||
'@humanwhocodes/config-array@0.11.14':
|
'@humanwhocodes/config-array@0.11.14':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@humanwhocodes/object-schema': 2.0.3
|
'@humanwhocodes/object-schema': 2.0.3
|
||||||
debug: 4.3.4
|
debug: 4.4.3
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -7399,6 +7552,11 @@ snapshots:
|
|||||||
'@types/yargs': 17.0.24
|
'@types/yargs': 17.0.24
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
|
|
||||||
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
|
||||||
'@jridgewell/gen-mapping@0.3.3':
|
'@jridgewell/gen-mapping@0.3.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/set-array': 1.1.2
|
'@jridgewell/set-array': 1.1.2
|
||||||
@@ -7407,6 +7565,8 @@ snapshots:
|
|||||||
|
|
||||||
'@jridgewell/resolve-uri@3.1.1': {}
|
'@jridgewell/resolve-uri@3.1.1': {}
|
||||||
|
|
||||||
|
'@jridgewell/resolve-uri@3.1.2': {}
|
||||||
|
|
||||||
'@jridgewell/set-array@1.1.2': {}
|
'@jridgewell/set-array@1.1.2': {}
|
||||||
|
|
||||||
'@jridgewell/source-map@0.3.5':
|
'@jridgewell/source-map@0.3.5':
|
||||||
@@ -7416,11 +7576,18 @@ snapshots:
|
|||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.4.15': {}
|
'@jridgewell/sourcemap-codec@1.4.15': {}
|
||||||
|
|
||||||
|
'@jridgewell/sourcemap-codec@1.5.5': {}
|
||||||
|
|
||||||
'@jridgewell/trace-mapping@0.3.19':
|
'@jridgewell/trace-mapping@0.3.19':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/resolve-uri': 3.1.1
|
'@jridgewell/resolve-uri': 3.1.1
|
||||||
'@jridgewell/sourcemap-codec': 1.4.15
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
|
|
||||||
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
'@leichtgewicht/ip-codec@2.0.4': {}
|
'@leichtgewicht/ip-codec@2.0.4': {}
|
||||||
|
|
||||||
'@mui/base@5.0.0-beta.40(@types/react@18.2.79)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
'@mui/base@5.0.0-beta.40(@types/react@18.2.79)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||||
@@ -7971,7 +8138,7 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 5.62.0
|
'@typescript-eslint/types': 5.62.0
|
||||||
eslint-visitor-keys: 3.4.3
|
eslint-visitor-keys: 3.4.3
|
||||||
|
|
||||||
'@ungap/structured-clone@1.2.0': {}
|
'@ungap/structured-clone@1.3.0': {}
|
||||||
|
|
||||||
'@webassemblyjs/ast@1.11.6':
|
'@webassemblyjs/ast@1.11.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8069,9 +8236,9 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.10.0
|
acorn: 8.10.0
|
||||||
|
|
||||||
acorn-jsx@5.3.2(acorn@8.11.3):
|
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.11.3
|
acorn: 8.15.0
|
||||||
|
|
||||||
acorn-walk@7.2.0: {}
|
acorn-walk@7.2.0: {}
|
||||||
|
|
||||||
@@ -8081,6 +8248,8 @@ snapshots:
|
|||||||
|
|
||||||
acorn@8.11.3: {}
|
acorn@8.11.3: {}
|
||||||
|
|
||||||
|
acorn@8.15.0: {}
|
||||||
|
|
||||||
address@1.2.2: {}
|
address@1.2.2: {}
|
||||||
|
|
||||||
adjust-sourcemap-loader@4.0.0:
|
adjust-sourcemap-loader@4.0.0:
|
||||||
@@ -8244,7 +8413,7 @@ snapshots:
|
|||||||
autoprefixer@10.4.16(postcss@8.4.30):
|
autoprefixer@10.4.16(postcss@8.4.30):
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist: 4.23.0
|
browserslist: 4.23.0
|
||||||
caniuse-lite: 1.0.30001599
|
caniuse-lite: 1.0.30001754
|
||||||
fraction.js: 4.3.6
|
fraction.js: 4.3.6
|
||||||
normalize-range: 0.1.2
|
normalize-range: 0.1.2
|
||||||
picocolors: 1.0.0
|
picocolors: 1.0.0
|
||||||
@@ -8444,7 +8613,7 @@ snapshots:
|
|||||||
|
|
||||||
browserslist@4.23.0:
|
browserslist@4.23.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
caniuse-lite: 1.0.30001599
|
caniuse-lite: 1.0.30001754
|
||||||
electron-to-chromium: 1.4.713
|
electron-to-chromium: 1.4.713
|
||||||
node-releases: 2.0.14
|
node-releases: 2.0.14
|
||||||
update-browserslist-db: 1.0.13(browserslist@4.23.0)
|
update-browserslist-db: 1.0.13(browserslist@4.23.0)
|
||||||
@@ -8484,11 +8653,11 @@ snapshots:
|
|||||||
caniuse-api@3.0.0:
|
caniuse-api@3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist: 4.23.0
|
browserslist: 4.23.0
|
||||||
caniuse-lite: 1.0.30001599
|
caniuse-lite: 1.0.30001754
|
||||||
lodash.memoize: 4.1.2
|
lodash.memoize: 4.1.2
|
||||||
lodash.uniq: 4.5.0
|
lodash.uniq: 4.5.0
|
||||||
|
|
||||||
caniuse-lite@1.0.30001599: {}
|
caniuse-lite@1.0.30001754: {}
|
||||||
|
|
||||||
case-sensitive-paths-webpack-plugin@2.4.0: {}
|
case-sensitive-paths-webpack-plugin@2.4.0: {}
|
||||||
|
|
||||||
@@ -8661,6 +8830,12 @@ snapshots:
|
|||||||
shebang-command: 2.0.0
|
shebang-command: 2.0.0
|
||||||
which: 2.0.2
|
which: 2.0.2
|
||||||
|
|
||||||
|
cross-spawn@7.0.6:
|
||||||
|
dependencies:
|
||||||
|
path-key: 3.1.1
|
||||||
|
shebang-command: 2.0.0
|
||||||
|
which: 2.0.2
|
||||||
|
|
||||||
crypt@0.0.2: {}
|
crypt@0.0.2: {}
|
||||||
|
|
||||||
crypto-random-string@2.0.0: {}
|
crypto-random-string@2.0.0: {}
|
||||||
@@ -8823,6 +8998,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.2
|
ms: 2.1.2
|
||||||
|
|
||||||
|
debug@4.4.3:
|
||||||
|
dependencies:
|
||||||
|
ms: 2.1.3
|
||||||
|
|
||||||
decimal.js@10.4.3: {}
|
decimal.js@10.4.3: {}
|
||||||
|
|
||||||
decode-named-character-reference@1.0.2:
|
decode-named-character-reference@1.0.2:
|
||||||
@@ -9270,24 +9449,24 @@ snapshots:
|
|||||||
|
|
||||||
eslint@8.57.0:
|
eslint@8.57.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
|
'@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0)
|
||||||
'@eslint-community/regexpp': 4.10.0
|
'@eslint-community/regexpp': 4.12.2
|
||||||
'@eslint/eslintrc': 2.1.4
|
'@eslint/eslintrc': 2.1.4
|
||||||
'@eslint/js': 8.57.0
|
'@eslint/js': 8.57.0
|
||||||
'@humanwhocodes/config-array': 0.11.14
|
'@humanwhocodes/config-array': 0.11.14
|
||||||
'@humanwhocodes/module-importer': 1.0.1
|
'@humanwhocodes/module-importer': 1.0.1
|
||||||
'@nodelib/fs.walk': 1.2.8
|
'@nodelib/fs.walk': 1.2.8
|
||||||
'@ungap/structured-clone': 1.2.0
|
'@ungap/structured-clone': 1.3.0
|
||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
cross-spawn: 7.0.3
|
cross-spawn: 7.0.6
|
||||||
debug: 4.3.4
|
debug: 4.4.3
|
||||||
doctrine: 3.0.0
|
doctrine: 3.0.0
|
||||||
escape-string-regexp: 4.0.0
|
escape-string-regexp: 4.0.0
|
||||||
eslint-scope: 7.2.2
|
eslint-scope: 7.2.2
|
||||||
eslint-visitor-keys: 3.4.3
|
eslint-visitor-keys: 3.4.3
|
||||||
espree: 9.6.1
|
espree: 9.6.1
|
||||||
esquery: 1.5.0
|
esquery: 1.6.0
|
||||||
esutils: 2.0.3
|
esutils: 2.0.3
|
||||||
fast-deep-equal: 3.1.3
|
fast-deep-equal: 3.1.3
|
||||||
file-entry-cache: 6.0.1
|
file-entry-cache: 6.0.1
|
||||||
@@ -9295,7 +9474,7 @@ snapshots:
|
|||||||
glob-parent: 6.0.2
|
glob-parent: 6.0.2
|
||||||
globals: 13.24.0
|
globals: 13.24.0
|
||||||
graphemer: 1.4.0
|
graphemer: 1.4.0
|
||||||
ignore: 5.3.1
|
ignore: 5.3.2
|
||||||
imurmurhash: 0.1.4
|
imurmurhash: 0.1.4
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
is-path-inside: 3.0.3
|
is-path-inside: 3.0.3
|
||||||
@@ -9305,7 +9484,7 @@ snapshots:
|
|||||||
lodash.merge: 4.6.2
|
lodash.merge: 4.6.2
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
optionator: 0.9.3
|
optionator: 0.9.4
|
||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
text-table: 0.2.0
|
text-table: 0.2.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -9313,15 +9492,15 @@ snapshots:
|
|||||||
|
|
||||||
espree@9.6.1:
|
espree@9.6.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.11.3
|
acorn: 8.15.0
|
||||||
acorn-jsx: 5.3.2(acorn@8.11.3)
|
acorn-jsx: 5.3.2(acorn@8.15.0)
|
||||||
eslint-visitor-keys: 3.4.3
|
eslint-visitor-keys: 3.4.3
|
||||||
|
|
||||||
esprima@1.2.2: {}
|
esprima@1.2.2: {}
|
||||||
|
|
||||||
esprima@4.0.1: {}
|
esprima@4.0.1: {}
|
||||||
|
|
||||||
esquery@1.5.0:
|
esquery@1.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
estraverse: 5.3.0
|
estraverse: 5.3.0
|
||||||
|
|
||||||
@@ -9508,11 +9687,11 @@ snapshots:
|
|||||||
|
|
||||||
flat-cache@3.2.0:
|
flat-cache@3.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
flatted: 3.3.1
|
flatted: 3.3.3
|
||||||
keyv: 4.5.4
|
keyv: 4.5.4
|
||||||
rimraf: 3.0.2
|
rimraf: 3.0.2
|
||||||
|
|
||||||
flatted@3.3.1: {}
|
flatted@3.3.3: {}
|
||||||
|
|
||||||
follow-redirects@1.15.3: {}
|
follow-redirects@1.15.3: {}
|
||||||
|
|
||||||
@@ -9838,7 +10017,7 @@ snapshots:
|
|||||||
|
|
||||||
ignore@5.2.4: {}
|
ignore@5.2.4: {}
|
||||||
|
|
||||||
ignore@5.3.1: {}
|
ignore@5.3.2: {}
|
||||||
|
|
||||||
immer@9.0.21: {}
|
immer@9.0.21: {}
|
||||||
|
|
||||||
@@ -9847,6 +10026,11 @@ snapshots:
|
|||||||
parent-module: 1.0.1
|
parent-module: 1.0.1
|
||||||
resolve-from: 4.0.0
|
resolve-from: 4.0.0
|
||||||
|
|
||||||
|
import-fresh@3.3.1:
|
||||||
|
dependencies:
|
||||||
|
parent-module: 1.0.1
|
||||||
|
resolve-from: 4.0.0
|
||||||
|
|
||||||
import-local@3.1.0:
|
import-local@3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
pkg-dir: 4.2.0
|
pkg-dir: 4.2.0
|
||||||
@@ -10527,6 +10711,8 @@ snapshots:
|
|||||||
|
|
||||||
jsesc@2.5.2: {}
|
jsesc@2.5.2: {}
|
||||||
|
|
||||||
|
jsesc@3.1.0: {}
|
||||||
|
|
||||||
json-buffer@3.0.1: {}
|
json-buffer@3.0.1: {}
|
||||||
|
|
||||||
json-parse-even-better-errors@2.3.1: {}
|
json-parse-even-better-errors@2.3.1: {}
|
||||||
@@ -11079,14 +11265,14 @@ snapshots:
|
|||||||
type-check: 0.3.2
|
type-check: 0.3.2
|
||||||
word-wrap: 1.2.5
|
word-wrap: 1.2.5
|
||||||
|
|
||||||
optionator@0.9.3:
|
optionator@0.9.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@aashutoshrathi/word-wrap': 1.2.6
|
|
||||||
deep-is: 0.1.4
|
deep-is: 0.1.4
|
||||||
fast-levenshtein: 2.0.6
|
fast-levenshtein: 2.0.6
|
||||||
levn: 0.4.1
|
levn: 0.4.1
|
||||||
prelude-ls: 1.2.1
|
prelude-ls: 1.2.1
|
||||||
type-check: 0.4.0
|
type-check: 0.4.0
|
||||||
|
word-wrap: 1.2.5
|
||||||
|
|
||||||
p-limit@2.3.0:
|
p-limit@2.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -11174,6 +11360,8 @@ snapshots:
|
|||||||
|
|
||||||
picocolors@1.0.0: {}
|
picocolors@1.0.0: {}
|
||||||
|
|
||||||
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
picomatch@2.3.1: {}
|
picomatch@2.3.1: {}
|
||||||
|
|
||||||
pify@2.3.0: {}
|
pify@2.3.0: {}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "__MSG_app_name__",
|
"name": "__MSG_app_name__",
|
||||||
"description": "__MSG_app_description__",
|
"description": "__MSG_app_description__",
|
||||||
"version": "2.0.7",
|
"version": "2.0.8",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"author": "Gabe<yugang2002@gmail.com>",
|
"author": "Gabe<yugang2002@gmail.com>",
|
||||||
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "__MSG_app_name__",
|
"name": "__MSG_app_name__",
|
||||||
"description": "__MSG_app_description__",
|
"description": "__MSG_app_description__",
|
||||||
"version": "2.0.7",
|
"version": "2.0.8",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"author": "Gabe<yugang2002@gmail.com>",
|
"author": "Gabe<yugang2002@gmail.com>",
|
||||||
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "__MSG_app_name__",
|
"name": "__MSG_app_name__",
|
||||||
"description": "__MSG_app_description__",
|
"description": "__MSG_app_description__",
|
||||||
"version": "2.0.7",
|
"version": "2.0.8",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"author": "Gabe<yugang2002@gmail.com>",
|
"author": "Gabe<yugang2002@gmail.com>",
|
||||||
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
"homepage_url": "https://github.com/fishjar/kiss-translator",
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ export const apiTranslate = async ({
|
|||||||
toLang,
|
toLang,
|
||||||
apiSetting = DEFAULT_API_SETTING,
|
apiSetting = DEFAULT_API_SETTING,
|
||||||
docInfo = {},
|
docInfo = {},
|
||||||
glossary = {},
|
glossary,
|
||||||
useCache = true,
|
useCache = true,
|
||||||
usePool = true,
|
usePool = true,
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ import {
|
|||||||
defaultSubtitlePrompt,
|
defaultSubtitlePrompt,
|
||||||
defaultNobatchPrompt,
|
defaultNobatchPrompt,
|
||||||
defaultNobatchUserPrompt,
|
defaultNobatchUserPrompt,
|
||||||
|
INPUT_PLACE_TONE,
|
||||||
|
INPUT_PLACE_TITLE,
|
||||||
|
INPUT_PLACE_DESCRIPTION,
|
||||||
|
INPUT_PLACE_TO_LANG,
|
||||||
|
INPUT_PLACE_FROM_LANG,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
import { msAuth } from "../libs/auth";
|
import { msAuth } from "../libs/auth";
|
||||||
import { genDeeplFree } from "./deepl";
|
import { genDeeplFree } from "./deepl";
|
||||||
@@ -62,36 +67,62 @@ const keyPick = (apiSlug, key = "", cacheMap) => {
|
|||||||
return keys[curIndex];
|
return keys[curIndex];
|
||||||
};
|
};
|
||||||
|
|
||||||
const genSystemPrompt = ({ systemPrompt, from, to }) =>
|
const genSystemPrompt = ({
|
||||||
|
systemPrompt,
|
||||||
|
tone,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
fromLang,
|
||||||
|
toLang,
|
||||||
|
texts,
|
||||||
|
docInfo: { title = "", description = "" } = {},
|
||||||
|
}) =>
|
||||||
systemPrompt
|
systemPrompt
|
||||||
|
.replaceAll(INPUT_PLACE_TITLE, title)
|
||||||
|
.replaceAll(INPUT_PLACE_DESCRIPTION, description)
|
||||||
|
.replaceAll(INPUT_PLACE_TONE, tone)
|
||||||
.replaceAll(INPUT_PLACE_FROM, from)
|
.replaceAll(INPUT_PLACE_FROM, from)
|
||||||
.replaceAll(INPUT_PLACE_TO, to);
|
.replaceAll(INPUT_PLACE_TO, to)
|
||||||
|
.replaceAll(INPUT_PLACE_FROM_LANG, fromLang)
|
||||||
|
.replaceAll(INPUT_PLACE_TO_LANG, toLang)
|
||||||
|
.replaceAll(INPUT_PLACE_TEXT, texts[0]);
|
||||||
|
|
||||||
const genUserPrompt = ({
|
const genUserPrompt = ({
|
||||||
nobatchUserPrompt,
|
nobatchUserPrompt,
|
||||||
useBatchFetch,
|
useBatchFetch,
|
||||||
tone,
|
tone,
|
||||||
glossary = {},
|
glossary,
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
|
fromLang,
|
||||||
toLang,
|
toLang,
|
||||||
texts,
|
texts,
|
||||||
docInfo,
|
docInfo: { title = "", description = "" } = {},
|
||||||
}) => {
|
}) => {
|
||||||
if (useBatchFetch) {
|
if (useBatchFetch) {
|
||||||
return JSON.stringify({
|
const promptObj = {
|
||||||
targetLanguage: toLang,
|
targetLanguage: toLang,
|
||||||
title: docInfo.title,
|
|
||||||
description: docInfo.description,
|
|
||||||
segments: texts.map((text, i) => ({ id: i, text })),
|
segments: texts.map((text, i) => ({ id: i, text })),
|
||||||
glossary,
|
};
|
||||||
tone,
|
|
||||||
});
|
title && (promptObj.title = title);
|
||||||
|
description && (promptObj.description = description);
|
||||||
|
glossary &&
|
||||||
|
Object.keys(glossary).length !== 0 &&
|
||||||
|
(promptObj.glossary = glossary);
|
||||||
|
tone && (promptObj.tone = tone);
|
||||||
|
|
||||||
|
return JSON.stringify(promptObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nobatchUserPrompt
|
return nobatchUserPrompt
|
||||||
|
.replaceAll(INPUT_PLACE_TITLE, title)
|
||||||
|
.replaceAll(INPUT_PLACE_DESCRIPTION, description)
|
||||||
|
.replaceAll(INPUT_PLACE_TONE, tone)
|
||||||
.replaceAll(INPUT_PLACE_FROM, from)
|
.replaceAll(INPUT_PLACE_FROM, from)
|
||||||
.replaceAll(INPUT_PLACE_TO, to)
|
.replaceAll(INPUT_PLACE_TO, to)
|
||||||
|
.replaceAll(INPUT_PLACE_FROM_LANG, fromLang)
|
||||||
|
.replaceAll(INPUT_PLACE_TO_LANG, toLang)
|
||||||
.replaceAll(INPUT_PLACE_TEXT, texts[0]);
|
.replaceAll(INPUT_PLACE_TEXT, texts[0]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -647,6 +678,7 @@ export const genTransReq = async ({ reqHook, ...args }) => {
|
|||||||
customHeader,
|
customHeader,
|
||||||
customBody,
|
customBody,
|
||||||
events,
|
events,
|
||||||
|
tone,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
if (API_SPE_TYPES.mulkeys.has(apiType)) {
|
if (API_SPE_TYPES.mulkeys.has(apiType)) {
|
||||||
@@ -658,12 +690,19 @@ export const genTransReq = async ({ reqHook, ...args }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (API_SPE_TYPES.ai.has(apiType)) {
|
if (API_SPE_TYPES.ai.has(apiType)) {
|
||||||
args.systemPrompt = genSystemPrompt({
|
args.systemPrompt = events
|
||||||
|
? systemPrompt
|
||||||
|
: genSystemPrompt({
|
||||||
systemPrompt: useBatchFetch ? systemPrompt : nobatchPrompt,
|
systemPrompt: useBatchFetch ? systemPrompt : nobatchPrompt,
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
|
fromLang,
|
||||||
|
toLang,
|
||||||
|
texts,
|
||||||
|
docInfo,
|
||||||
|
tone,
|
||||||
});
|
});
|
||||||
args.userPrompt = !!events
|
args.userPrompt = events
|
||||||
? JSON.stringify(events)
|
? JSON.stringify(events)
|
||||||
: genUserPrompt({
|
: genUserPrompt({
|
||||||
nobatchUserPrompt,
|
nobatchUserPrompt,
|
||||||
@@ -674,6 +713,7 @@ export const genTransReq = async ({ reqHook, ...args }) => {
|
|||||||
toLang,
|
toLang,
|
||||||
texts,
|
texts,
|
||||||
docInfo,
|
docInfo,
|
||||||
|
tone,
|
||||||
glossary,
|
glossary,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,12 @@ export const DEFAULT_CONTEXT_SIZE = 3; // 上下文会话数量
|
|||||||
export const INPUT_PLACE_URL = "{{url}}"; // 占位符
|
export const INPUT_PLACE_URL = "{{url}}"; // 占位符
|
||||||
export const INPUT_PLACE_FROM = "{{from}}"; // 占位符
|
export const INPUT_PLACE_FROM = "{{from}}"; // 占位符
|
||||||
export const INPUT_PLACE_TO = "{{to}}"; // 占位符
|
export const INPUT_PLACE_TO = "{{to}}"; // 占位符
|
||||||
|
export const INPUT_PLACE_FROM_LANG = "{{fromLang}}"; // 占位符
|
||||||
|
export const INPUT_PLACE_TO_LANG = "{{toLang}}"; // 占位符
|
||||||
export const INPUT_PLACE_TEXT = "{{text}}"; // 占位符
|
export const INPUT_PLACE_TEXT = "{{text}}"; // 占位符
|
||||||
|
export const INPUT_PLACE_TONE = "{{tone}}"; // 占位符
|
||||||
|
export const INPUT_PLACE_TITLE = "{{title}}"; // 占位符
|
||||||
|
export const INPUT_PLACE_DESCRIPTION = "{{description}}"; // 占位符
|
||||||
export const INPUT_PLACE_KEY = "{{key}}"; // 占位符
|
export const INPUT_PLACE_KEY = "{{key}}"; // 占位符
|
||||||
export const INPUT_PLACE_MODEL = "{{model}}"; // 占位符
|
export const INPUT_PLACE_MODEL = "{{model}}"; // 占位符
|
||||||
|
|
||||||
|
|||||||
@@ -804,9 +804,9 @@ export const I18N = {
|
|||||||
zh_TW: `注入 CSS`,
|
zh_TW: `注入 CSS`,
|
||||||
},
|
},
|
||||||
inject_css_helper: {
|
inject_css_helper: {
|
||||||
zh: `初始化时注入运行,一个页面仅运行一次。`,
|
zh: `预加载时注入,一个页面仅运行一次。`,
|
||||||
en: `Injected and run at initialization, and only run once per page.`,
|
en: `Injected during preload, runs only once per page.`,
|
||||||
zh_TW: `初始化時注入運行,一個頁面僅運行一次。`,
|
zh_TW: `預先載入時注入,一個頁面僅運行一次。`,
|
||||||
},
|
},
|
||||||
fixer_function: {
|
fixer_function: {
|
||||||
zh: `修复函数`,
|
zh: `修复函数`,
|
||||||
@@ -1674,9 +1674,14 @@ export const I18N = {
|
|||||||
zh_TW: `雙語顯示`,
|
zh_TW: `雙語顯示`,
|
||||||
},
|
},
|
||||||
is_skip_ad: {
|
is_skip_ad: {
|
||||||
zh: `是否快进广告`,
|
zh: `快进广告`,
|
||||||
en: `Should I fast forward to the ad?`,
|
en: `Skip AD`,
|
||||||
zh_TW: `是否快轉廣告`,
|
zh_TW: `快轉廣告`,
|
||||||
|
},
|
||||||
|
download_subtitles: {
|
||||||
|
zh: `下载字幕`,
|
||||||
|
en: `Download subtitles`,
|
||||||
|
zh_TW: `下载字幕`,
|
||||||
},
|
},
|
||||||
background_styles: {
|
background_styles: {
|
||||||
zh: `背景样式`,
|
zh: `背景样式`,
|
||||||
@@ -1753,6 +1758,36 @@ export const I18N = {
|
|||||||
en: `The subtitle data is ready, please click the KT button to load it`,
|
en: `The subtitle data is ready, please click the KT button to load it`,
|
||||||
zh_TW: `字幕資料已準備就緒,請點擊KT按鈕加載`,
|
zh_TW: `字幕資料已準備就緒,請點擊KT按鈕加載`,
|
||||||
},
|
},
|
||||||
|
starting_reprocess_events: {
|
||||||
|
zh: `重新处理字幕数据...`,
|
||||||
|
en: `Reprocess the subtitle data...`,
|
||||||
|
zh_TW: `重新处理字幕数据...`,
|
||||||
|
},
|
||||||
|
waitting_for_subtitle: {
|
||||||
|
zh: `请等待字幕数据`,
|
||||||
|
en: `Please wait for the subtitle data.`,
|
||||||
|
zh_TW: `请等待字幕数据`,
|
||||||
|
},
|
||||||
|
ai_processing_pls_wait: {
|
||||||
|
zh: `AI处理中,请稍等...`,
|
||||||
|
en: `AI processing in progress, please wait...`,
|
||||||
|
zh_TW: `AI处理中,请稍等...`,
|
||||||
|
},
|
||||||
|
processing_subtitles: {
|
||||||
|
zh: `字幕处理中...`,
|
||||||
|
en: `Subtitle processing...`,
|
||||||
|
zh_TW: `字幕处理中...`,
|
||||||
|
},
|
||||||
|
waiting_subtitles: {
|
||||||
|
zh: `等待字幕中`,
|
||||||
|
en: `Waiting for subtitles`,
|
||||||
|
zh_TW: `等待字幕中`,
|
||||||
|
},
|
||||||
|
subtitle_is_not_yet_ready: {
|
||||||
|
zh: `字幕数据尚未准备好`,
|
||||||
|
en: `Subtitle is not yet ready.`,
|
||||||
|
zh_TW: `字幕数据尚未准备好`,
|
||||||
|
},
|
||||||
log_level: {
|
log_level: {
|
||||||
zh: `日志级别`,
|
zh: `日志级别`,
|
||||||
en: `Log Level`,
|
en: `Log Level`,
|
||||||
@@ -1829,6 +1864,16 @@ export const I18N = {
|
|||||||
en: `Style Code`,
|
en: `Style Code`,
|
||||||
zh_TW: `樣式程式碼`,
|
zh_TW: `樣式程式碼`,
|
||||||
},
|
},
|
||||||
|
pre_trans_seconds: {
|
||||||
|
zh: `提前翻译时长 (10-36000s)`,
|
||||||
|
en: `Pre translation seconds (10-36000s)`,
|
||||||
|
zh_TW: `提前翻译时长 (10-36000s)`,
|
||||||
|
},
|
||||||
|
throttle_trans_interval: {
|
||||||
|
zh: `节流翻译间隔 (1-3600s)`,
|
||||||
|
en: `Throttling translation interval (1-3600s)`,
|
||||||
|
zh_TW: `节流翻译间隔 (1-3600s)`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const newI18n = (lang) => (key) => I18N[key]?.[lang] || "";
|
export const newI18n = (lang) => (key) => I18N[key]?.[lang] || "";
|
||||||
|
|||||||
@@ -33,3 +33,6 @@ export const EVENT_KISS = "event_kiss_translate";
|
|||||||
export const MSG_XHR_DATA_YOUTUBE = "KISS_XHR_DATA_YOUTUBE";
|
export const MSG_XHR_DATA_YOUTUBE = "KISS_XHR_DATA_YOUTUBE";
|
||||||
// export const MSG_GLOBAL_VAR_FETCH = "KISS_GLOBAL_VAR_FETCH";
|
// export const MSG_GLOBAL_VAR_FETCH = "KISS_GLOBAL_VAR_FETCH";
|
||||||
// export const MSG_GLOBAL_VAR_BACK = "KISS_GLOBAL_VAR_BACK";
|
// export const MSG_GLOBAL_VAR_BACK = "KISS_GLOBAL_VAR_BACK";
|
||||||
|
|
||||||
|
export const MSG_MENUS_PROGRESSED = "progressed";
|
||||||
|
export const MSG_MENUS_UPDATEFORM = "updateFormData";
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export const SHADOW_KEY = ">>>";
|
|||||||
export const DEFAULT_COLOR = "#209CEE"; // 默认高亮背景色/线条颜色
|
export const DEFAULT_COLOR = "#209CEE"; // 默认高亮背景色/线条颜色
|
||||||
|
|
||||||
export const DEFAULT_TRANS_TAG = "font";
|
export const DEFAULT_TRANS_TAG = "font";
|
||||||
export const DEFAULT_SELECT_STYLE =
|
// export const DEFAULT_SELECT_STYLE =
|
||||||
"-webkit-line-clamp: unset; max-height: none; height: auto;";
|
// "-webkit-line-clamp: unset; max-height: none; height: auto;";
|
||||||
|
|
||||||
export const OPT_TIMING_PAGESCROLL = "mk_pagescroll"; // 滚动加载翻译
|
export const OPT_TIMING_PAGESCROLL = "mk_pagescroll"; // 滚动加载翻译
|
||||||
export const OPT_TIMING_PAGEOPEN = "mk_pageopen"; // 直接翻译到底
|
export const OPT_TIMING_PAGEOPEN = "mk_pageopen"; // 直接翻译到底
|
||||||
@@ -108,11 +108,11 @@ export const GLOBLA_RULE = {
|
|||||||
textExtStyle: "", // 译文附加样式
|
textExtStyle: "", // 译文附加样式
|
||||||
termsStyle: "font-weight: bold;", // 专业术语样式
|
termsStyle: "font-weight: bold;", // 专业术语样式
|
||||||
highlightStyle: "color: red;", // 高亮词汇样式
|
highlightStyle: "color: red;", // 高亮词汇样式
|
||||||
selectStyle: DEFAULT_SELECT_STYLE, // 选择器节点样式
|
selectStyle: "", // 选择器节点样式
|
||||||
parentStyle: DEFAULT_SELECT_STYLE, // 选择器父节点样式
|
parentStyle: "", // 选择器父节点样式
|
||||||
grandStyle: DEFAULT_SELECT_STYLE, // 选择器祖节点样式
|
grandStyle: "", // 选择器祖节点样式
|
||||||
injectJs: "", // 注入JS
|
injectJs: "", // 注入JS
|
||||||
// injectCss: "", // 注入CSS(作废)
|
injectCss: "", // 注入CSS
|
||||||
transOnly: "false", // 是否仅显示译文
|
transOnly: "false", // 是否仅显示译文
|
||||||
// transTiming: OPT_TIMING_PAGESCROLL, // 翻译时机/鼠标悬停翻译 (暂时作废)
|
// transTiming: OPT_TIMING_PAGESCROLL, // 翻译时机/鼠标悬停翻译 (暂时作废)
|
||||||
transTag: DEFAULT_TRANS_TAG, // 译文元素标签
|
transTag: DEFAULT_TRANS_TAG, // 译文元素标签
|
||||||
@@ -165,6 +165,9 @@ const RULES_MAP = {
|
|||||||
"www.youtube.com": {
|
"www.youtube.com": {
|
||||||
rootsSelector: `ytd-page-manager`,
|
rootsSelector: `ytd-page-manager`,
|
||||||
ignoreSelector: `aside, button, footer, form, header, pre, mark, nav, #player, #container, .caption-window, .ytp-settings-menu`,
|
ignoreSelector: `aside, button, footer, form, header, pre, mark, nav, #player, #container, .caption-window, .ytp-settings-menu`,
|
||||||
|
selectStyle: `-webkit-line-clamp: unset; max-height: none; height: auto;`,
|
||||||
|
parentStyle: `-webkit-line-clamp: unset; max-height: none; height: auto;`,
|
||||||
|
grandStyle: `-webkit-line-clamp: unset; max-height: none; height: auto;`,
|
||||||
},
|
},
|
||||||
"web.telegram.org": {
|
"web.telegram.org": {
|
||||||
autoScan: `false`,
|
autoScan: `false`,
|
||||||
|
|||||||
@@ -112,6 +112,8 @@ export const DEFAULT_SUBTITLE_SETTING = {
|
|||||||
apiSlug: OPT_TRANS_MICROSOFT,
|
apiSlug: OPT_TRANS_MICROSOFT,
|
||||||
segSlug: "-", // AI智能断句
|
segSlug: "-", // AI智能断句
|
||||||
chunkLength: 1000, // AI处理切割长度
|
chunkLength: 1000, // AI处理切割长度
|
||||||
|
preTrans: 90, // 提前翻译时长
|
||||||
|
throttleTrans: 30, // 节流翻译间隔
|
||||||
// fromLang: "en",
|
// fromLang: "en",
|
||||||
toLang: "zh-CN",
|
toLang: "zh-CN",
|
||||||
isBilingual: true, // 是否双语显示
|
isBilingual: true, // 是否双语显示
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export const matchRule = async (href, { injectRules, subrulesList }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const rule = rules.find((r) =>
|
const rule = rules.find((r) =>
|
||||||
r.pattern.split(",").some((p) => isMatch(href, p.trim()))
|
r.pattern.split(/\n|,/).some((p) => isMatch(href, p.trim()))
|
||||||
);
|
);
|
||||||
const globalRule = {
|
const globalRule = {
|
||||||
...GLOBLA_RULE,
|
...GLOBLA_RULE,
|
||||||
@@ -58,7 +58,7 @@ export const matchRule = async (href, { injectRules, subrulesList }) => {
|
|||||||
"parentStyle",
|
"parentStyle",
|
||||||
"grandStyle",
|
"grandStyle",
|
||||||
"injectJs",
|
"injectJs",
|
||||||
// "injectCss",
|
"injectCss",
|
||||||
"transStartHook",
|
"transStartHook",
|
||||||
"transEndHook",
|
"transEndHook",
|
||||||
// "transRemoveHook",
|
// "transRemoveHook",
|
||||||
@@ -138,7 +138,7 @@ export const checkRules = (rules) => {
|
|||||||
parentStyle,
|
parentStyle,
|
||||||
grandStyle,
|
grandStyle,
|
||||||
injectJs,
|
injectJs,
|
||||||
// injectCss,
|
injectCss,
|
||||||
apiSlug,
|
apiSlug,
|
||||||
fromLang,
|
fromLang,
|
||||||
toLang,
|
toLang,
|
||||||
@@ -171,7 +171,7 @@ export const checkRules = (rules) => {
|
|||||||
parentStyle: type(parentStyle) === "string" ? parentStyle : "",
|
parentStyle: type(parentStyle) === "string" ? parentStyle : "",
|
||||||
grandStyle: type(grandStyle) === "string" ? grandStyle : "",
|
grandStyle: type(grandStyle) === "string" ? grandStyle : "",
|
||||||
injectJs: type(injectJs) === "string" ? injectJs : "",
|
injectJs: type(injectJs) === "string" ? injectJs : "",
|
||||||
// injectCss: type(injectCss) === "string" ? injectCss : "",
|
injectCss: type(injectCss) === "string" ? injectCss : "",
|
||||||
apiSlug:
|
apiSlug:
|
||||||
type(apiSlug) === "string" && apiSlug.trim() !== ""
|
type(apiSlug) === "string" && apiSlug.trim() !== ""
|
||||||
? apiSlug.trim()
|
? apiSlug.trim()
|
||||||
|
|||||||
@@ -15,7 +15,13 @@ export default class ShadowDomManager {
|
|||||||
_ReactComponent;
|
_ReactComponent;
|
||||||
_props;
|
_props;
|
||||||
|
|
||||||
constructor({ id, className = "", reactComponent, props = {} }) {
|
constructor({
|
||||||
|
id,
|
||||||
|
className = "",
|
||||||
|
reactComponent,
|
||||||
|
props = {},
|
||||||
|
rootElement = document.body,
|
||||||
|
}) {
|
||||||
if (!id || !reactComponent) {
|
if (!id || !reactComponent) {
|
||||||
throw new Error("ID and a React Component must be provided.");
|
throw new Error("ID and a React Component must be provided.");
|
||||||
}
|
}
|
||||||
@@ -23,6 +29,7 @@ export default class ShadowDomManager {
|
|||||||
this._className = className;
|
this._className = className;
|
||||||
this._ReactComponent = reactComponent;
|
this._ReactComponent = reactComponent;
|
||||||
this._props = props;
|
this._props = props;
|
||||||
|
this._rootElement = rootElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isVisible() {
|
get isVisible() {
|
||||||
@@ -93,7 +100,7 @@ export default class ShadowDomManager {
|
|||||||
host.className = this._className;
|
host.className = this._className;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.appendChild(host);
|
this._rootElement.appendChild(host);
|
||||||
this.#hostElement = host;
|
this.#hostElement = host;
|
||||||
const shadowContainer = host.attachShadow({ mode: "open" });
|
const shadowContainer = host.attachShadow({ mode: "open" });
|
||||||
const appRoot = document.createElement("div");
|
const appRoot = document.createElement("div");
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ export function createLogoSVG({
|
|||||||
const primaryColor = "#209CEE";
|
const primaryColor = "#209CEE";
|
||||||
const secondaryColor = "#E9F5FD";
|
const secondaryColor = "#E9F5FD";
|
||||||
|
|
||||||
const path1Fill = isSelected ? primaryColor : secondaryColor;
|
const path1Fill = isSelected ? secondaryColor : primaryColor;
|
||||||
const path2Fill = isSelected ? secondaryColor : primaryColor;
|
const path2Fill = isSelected ? primaryColor : secondaryColor;
|
||||||
|
|
||||||
const path1 = createSVGElement("path", {
|
const path1 = createSVGElement("path", {
|
||||||
d: "M0 0 C10.56 0 21.12 0 32 0 C32 10.56 32 21.12 32 32 C21.44 32 10.88 32 0 32 C0 21.44 0 10.88 0 0 Z ",
|
d: "M0 0 C10.56 0 21.12 0 32 0 C32 10.56 32 21.12 32 32 C21.44 32 10.88 32 0 32 C0 21.44 0 10.88 0 0 Z ",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
OPT_SPLIT_PARAGRAPH_PUNCTUATION,
|
OPT_SPLIT_PARAGRAPH_PUNCTUATION,
|
||||||
OPT_SPLIT_PARAGRAPH_DISABLE,
|
OPT_SPLIT_PARAGRAPH_DISABLE,
|
||||||
OPT_SPLIT_PARAGRAPH_TEXTLENGTH,
|
OPT_SPLIT_PARAGRAPH_TEXTLENGTH,
|
||||||
|
MSG_INJECT_CSS,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
import { interpreter } from "./interpreter";
|
import { interpreter } from "./interpreter";
|
||||||
import { clearFetchPool } from "./pool";
|
import { clearFetchPool } from "./pool";
|
||||||
@@ -26,6 +27,9 @@ import { shortcutRegister } from "./shortcut";
|
|||||||
import { tryDetectLang } from "./detect";
|
import { tryDetectLang } from "./detect";
|
||||||
import { trustedTypesHelper } from "./trustedTypes";
|
import { trustedTypesHelper } from "./trustedTypes";
|
||||||
import { injectJs, INJECTOR } from "../injectors";
|
import { injectJs, INJECTOR } from "../injectors";
|
||||||
|
import { injectInternalCss } from "./injector";
|
||||||
|
import { isExt } from "./client";
|
||||||
|
import { sendBgMsg } from "./msg";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Translator
|
* @class Translator
|
||||||
@@ -357,7 +361,7 @@ export class Translator {
|
|||||||
|
|
||||||
this.#eventName = genEventName();
|
this.#eventName = genEventName();
|
||||||
this.#docInfo = {
|
this.#docInfo = {
|
||||||
title: document.title,
|
title: truncateWords(document.title),
|
||||||
description: this.#getDocDescription(),
|
description: this.#getDocDescription(),
|
||||||
};
|
};
|
||||||
this.#combinedSkipsRegex = new RegExp(
|
this.#combinedSkipsRegex = new RegExp(
|
||||||
@@ -1624,7 +1628,14 @@ export class Translator {
|
|||||||
// injectCss && injectInternalCss(injectCss);
|
// injectCss && injectInternalCss(injectCss);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const { injectJs, toLang } = this.#rule;
|
const { injectJs, injectCss, toLang } = this.#rule;
|
||||||
|
|
||||||
|
if (isExt) {
|
||||||
|
injectCss && sendBgMsg(MSG_INJECT_CSS, injectCss);
|
||||||
|
} else {
|
||||||
|
injectCss && injectInternalCss(injectCss);
|
||||||
|
}
|
||||||
|
|
||||||
if (injectJs?.trim()) {
|
if (injectJs?.trim()) {
|
||||||
const apiSetting = { ...this.#apiSetting };
|
const apiSetting = { ...this.#apiSetting };
|
||||||
const docInfo = { ...this.#docInfo };
|
const docInfo = { ...this.#docInfo };
|
||||||
@@ -1688,7 +1699,7 @@ export class Translator {
|
|||||||
// 翻译页面标题
|
// 翻译页面标题
|
||||||
async #translateTitle() {
|
async #translateTitle() {
|
||||||
const title = document.title;
|
const title = document.title;
|
||||||
this.#docInfo.title = title;
|
this.#docInfo.title = truncateWords(title);
|
||||||
if (!title) return;
|
if (!title) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -409,3 +409,76 @@ export const randomBetween = (min, max, integer = true) => {
|
|||||||
const value = Math.random() * (max - min) + min;
|
const value = Math.random() * (max - min) + min;
|
||||||
return integer ? Math.floor(value) : value;
|
return integer ? Math.floor(value) : value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文件名自动获取 MIME 类型
|
||||||
|
* @param {*} filename
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function getMimeTypeFromFilename(filename) {
|
||||||
|
const defaultType = "application/octet-stream";
|
||||||
|
if (!filename || filename.indexOf(".") === -1) {
|
||||||
|
return defaultType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const extension = filename.split(".").pop().toLowerCase();
|
||||||
|
const mimeMap = {
|
||||||
|
// 文本
|
||||||
|
txt: "text/plain;charset=utf-8",
|
||||||
|
html: "text/html;charset=utf-8",
|
||||||
|
css: "text/css;charset=utf-8",
|
||||||
|
js: "text/javascript;charset=utf-8",
|
||||||
|
json: "application/json;charset=utf-8",
|
||||||
|
xml: "application/xml;charset=utf-8",
|
||||||
|
md: "text/markdown;charset=utf-8",
|
||||||
|
vtt: "text/vtt;charset=utf-8",
|
||||||
|
|
||||||
|
// 图像
|
||||||
|
png: "image/png",
|
||||||
|
jpg: "image/jpeg",
|
||||||
|
jpeg: "image/jpeg",
|
||||||
|
gif: "image/gif",
|
||||||
|
svg: "image/svg+xml",
|
||||||
|
webp: "image/webp",
|
||||||
|
ico: "image/x-icon",
|
||||||
|
|
||||||
|
// 音频/视频
|
||||||
|
mp3: "audio/mpeg",
|
||||||
|
mp4: "video/mp4",
|
||||||
|
webm: "video/webm",
|
||||||
|
wav: "audio/wav",
|
||||||
|
|
||||||
|
// 应用程序/文档
|
||||||
|
pdf: "application/pdf",
|
||||||
|
zip: "application/zip",
|
||||||
|
doc: "application/msword",
|
||||||
|
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
xls: "application/vnd.ms-excel",
|
||||||
|
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
|
};
|
||||||
|
|
||||||
|
// 默认值
|
||||||
|
return mimeMap[extension] || defaultType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载文件
|
||||||
|
* @param {*} str
|
||||||
|
* @param {*} filename
|
||||||
|
*/
|
||||||
|
export function downloadBlobFile(str, filename = "kiss-file.txt") {
|
||||||
|
const mimeType = getMimeTypeFromFilename(filename);
|
||||||
|
const blob = new Blob([str], { type: mimeType });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.style.display = "none";
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename || `kiss-file.txt`;
|
||||||
|
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ export class BilingualSubtitleManager {
|
|||||||
#captionWindowEl = null;
|
#captionWindowEl = null;
|
||||||
#paperEl = null;
|
#paperEl = null;
|
||||||
#currentSubtitleIndex = -1;
|
#currentSubtitleIndex = -1;
|
||||||
#preTranslateSeconds = 90;
|
// #preTranslateSeconds = 90;
|
||||||
#throttleSeconds = 30;
|
// #throttleSeconds = 30;
|
||||||
#setting = {};
|
#setting = {};
|
||||||
#isAdPlaying = false;
|
#isAdPlaying = false;
|
||||||
#throttledTriggerTranslations;
|
#throttledTriggerTranslations;
|
||||||
@@ -34,7 +34,7 @@ export class BilingualSubtitleManager {
|
|||||||
|
|
||||||
this.#throttledTriggerTranslations = throttle(
|
this.#throttledTriggerTranslations = throttle(
|
||||||
this.#triggerTranslations.bind(this),
|
this.#triggerTranslations.bind(this),
|
||||||
this.#throttleSeconds * 1000
|
(setting.throttleTrans ?? 30) * 1000
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +294,8 @@ export class BilingualSubtitleManager {
|
|||||||
* @param {number} currentTimeMs
|
* @param {number} currentTimeMs
|
||||||
*/
|
*/
|
||||||
#triggerTranslations(currentTimeMs) {
|
#triggerTranslations(currentTimeMs) {
|
||||||
const lookAheadMs = this.#preTranslateSeconds * 1000;
|
const { preTrans = 90 } = this.#setting;
|
||||||
|
const lookAheadMs = preTrans * 1000;
|
||||||
|
|
||||||
for (const sub of this.#formattedSubtitles) {
|
for (const sub of this.#formattedSubtitles) {
|
||||||
const isCurrent = sub.start <= currentTimeMs && sub.end >= currentTimeMs;
|
const isCurrent = sub.start <= currentTimeMs && sub.end >= currentTimeMs;
|
||||||
@@ -356,4 +357,8 @@ export class BilingualSubtitleManager {
|
|||||||
this.#currentSubtitleIndex = -1;
|
this.#currentSubtitleIndex = -1;
|
||||||
this.onTimeUpdate();
|
this.onTimeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSetting(obj) {
|
||||||
|
this.#setting = { ...this.#setting, ...obj };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
173
src/subtitle/Menus.js
Normal file
173
src/subtitle/Menus.js
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
|
import { MSG_MENUS_PROGRESSED, MSG_MENUS_UPDATEFORM } from "../config";
|
||||||
|
|
||||||
|
function Label({ children }) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
overflow: "hidden",
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MenuItem({ children, onClick, disabled = false }) {
|
||||||
|
const [hover, setHover] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: "0px 8px",
|
||||||
|
opacity: hover ? 1 : 0.8,
|
||||||
|
background: `rgba(255, 255, 255, ${hover ? 0.1 : 0})`,
|
||||||
|
cursor: disabled ? "default" : "pointer",
|
||||||
|
transition: "background 0.2s, opacity 0.2s",
|
||||||
|
borderRadius: 5,
|
||||||
|
}}
|
||||||
|
onMouseEnter={() => setHover(true)}
|
||||||
|
onMouseLeave={() => setHover(false)}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Switch({ label, name, value, onChange, disabled }) {
|
||||||
|
const handleClick = useCallback(() => {
|
||||||
|
if (disabled) return;
|
||||||
|
|
||||||
|
onChange({ name, value: !value });
|
||||||
|
}, [disabled, onChange, name, value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MenuItem onClick={handleClick} disabled={disabled}>
|
||||||
|
<Label>{label}</Label>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 40,
|
||||||
|
height: 24,
|
||||||
|
borderRadius: 12,
|
||||||
|
background: value ? "rgba(32,156,238,.8)" : "rgba(255,255,255,.3)",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
borderRadius: 10,
|
||||||
|
position: "absolute",
|
||||||
|
left: 2,
|
||||||
|
top: 2,
|
||||||
|
background: "rgba(255,255,255,.9)",
|
||||||
|
transform: `translateX(${value ? 16 : 0}px)`,
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Button({ label, onClick, disabled }) {
|
||||||
|
const handleClick = useCallback(() => {
|
||||||
|
if (disabled) return;
|
||||||
|
|
||||||
|
onClick();
|
||||||
|
}, [disabled, onClick]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MenuItem onClick={handleClick} disabled={disabled}>
|
||||||
|
<Label>{label}</Label>
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Menus({
|
||||||
|
i18n,
|
||||||
|
initData,
|
||||||
|
updateSetting,
|
||||||
|
downloadSubtitle,
|
||||||
|
hasSegApi,
|
||||||
|
eventName,
|
||||||
|
}) {
|
||||||
|
const [formData, setFormData] = useState(initData);
|
||||||
|
const [progressed, setProgressed] = useState(0);
|
||||||
|
|
||||||
|
const handleChange = useCallback(
|
||||||
|
({ name, value }) => {
|
||||||
|
setFormData((pre) => ({ ...pre, [name]: value }));
|
||||||
|
updateSetting({ name, value });
|
||||||
|
},
|
||||||
|
[updateSetting]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = (e) => {
|
||||||
|
const { action, data } = e.detail || {};
|
||||||
|
if (action === MSG_MENUS_PROGRESSED) {
|
||||||
|
setProgressed(data);
|
||||||
|
} else if (action === MSG_MENUS_UPDATEFORM) {
|
||||||
|
setFormData((pre) => ({ ...pre, ...data }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener(eventName, handler);
|
||||||
|
return () => window.removeEventListener(eventName, handler);
|
||||||
|
}, [eventName]);
|
||||||
|
|
||||||
|
const status = useMemo(() => {
|
||||||
|
if (progressed === 0) return i18n("waiting_subtitles");
|
||||||
|
if (progressed === 100) return i18n("download_subtitles");
|
||||||
|
return i18n("processing_subtitles");
|
||||||
|
}, [progressed, i18n]);
|
||||||
|
|
||||||
|
const { isAISegment, skipAd, isBilingual } = formData;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
left: 0,
|
||||||
|
bottom: 100,
|
||||||
|
background: "rgba(0,0,0,.6)",
|
||||||
|
width: 200,
|
||||||
|
lineHeight: "40px",
|
||||||
|
fontSize: 16,
|
||||||
|
padding: 8,
|
||||||
|
borderRadius: 5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
onChange={handleChange}
|
||||||
|
name="isAISegment"
|
||||||
|
value={isAISegment}
|
||||||
|
label={i18n("ai_segmentation")}
|
||||||
|
disabled={!hasSegApi}
|
||||||
|
/>
|
||||||
|
<Switch
|
||||||
|
onChange={handleChange}
|
||||||
|
name="isBilingual"
|
||||||
|
value={isBilingual}
|
||||||
|
label={i18n("is_bilingual_view")}
|
||||||
|
/>
|
||||||
|
<Switch
|
||||||
|
onChange={handleChange}
|
||||||
|
name="skipAd"
|
||||||
|
value={skipAd}
|
||||||
|
label={i18n("is_skip_ad")}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label={`${status} [${progressed}%] `}
|
||||||
|
onClick={downloadSubtitle}
|
||||||
|
disabled={progressed !== 100}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -6,34 +6,63 @@ import {
|
|||||||
APP_NAME,
|
APP_NAME,
|
||||||
OPT_LANGS_TO_CODE,
|
OPT_LANGS_TO_CODE,
|
||||||
OPT_TRANS_MICROSOFT,
|
OPT_TRANS_MICROSOFT,
|
||||||
|
MSG_MENUS_PROGRESSED,
|
||||||
|
MSG_MENUS_UPDATEFORM,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
import { sleep } from "../libs/utils.js";
|
import { sleep, genEventName, downloadBlobFile } from "../libs/utils.js";
|
||||||
import { createLogoSVG } from "../libs/svg.js";
|
import { createLogoSVG } from "../libs/svg.js";
|
||||||
import { randomBetween } from "../libs/utils.js";
|
import { randomBetween } from "../libs/utils.js";
|
||||||
import { newI18n } from "../config";
|
import { newI18n } from "../config";
|
||||||
|
import ShadowDomManager from "../libs/shadowDomManager.js";
|
||||||
|
import { Menus } from "./Menus.js";
|
||||||
|
import { buildBilingualVtt } from "./vtt.js";
|
||||||
|
|
||||||
const VIDEO_SELECT = "#container video";
|
const VIDEO_SELECT = "#container video";
|
||||||
const CONTORLS_SELECT = ".ytp-right-controls";
|
const CONTORLS_SELECT = ".ytp-right-controls";
|
||||||
const YT_CAPTION_SELECT = "#ytp-caption-window-container";
|
const YT_CAPTION_SELECT = "#ytp-caption-window-container";
|
||||||
const YT_AD_SELECT = ".video-ads";
|
const YT_AD_SELECT = ".video-ads";
|
||||||
|
const YT_SUBTITLE_BTN_SELECT = "button.ytp-subtitles-button";
|
||||||
|
|
||||||
class YouTubeCaptionProvider {
|
class YouTubeCaptionProvider {
|
||||||
#setting = {};
|
#setting = {};
|
||||||
#videoId = "";
|
|
||||||
#subtitles = [];
|
#subtitles = [];
|
||||||
|
#flatEvents = [];
|
||||||
|
#progressedNum = 0;
|
||||||
|
#fromLang = "auto";
|
||||||
|
|
||||||
|
#processingId = null;
|
||||||
|
|
||||||
#managerInstance = null;
|
#managerInstance = null;
|
||||||
#toggleButton = null;
|
#toggleButton = null;
|
||||||
#enabled = false;
|
#isMenuShow = false;
|
||||||
#ytControls = null;
|
|
||||||
#isBusy = false;
|
|
||||||
#fromLang = "auto";
|
|
||||||
#notificationEl = null;
|
#notificationEl = null;
|
||||||
#notificationTimeout = null;
|
#notificationTimeout = null;
|
||||||
#i18n = () => "";
|
#i18n = () => "";
|
||||||
|
#menuEventName = "kiss-event";
|
||||||
|
|
||||||
constructor(setting = {}) {
|
constructor(setting = {}) {
|
||||||
this.#setting = setting;
|
this.#setting = { ...setting, isAISegment: false };
|
||||||
this.#i18n = newI18n(setting.uiLang || "zh");
|
this.#i18n = newI18n(setting.uiLang || "zh");
|
||||||
|
this.#menuEventName = genEventName();
|
||||||
|
}
|
||||||
|
|
||||||
|
get #videoId() {
|
||||||
|
const docUrl = new URL(document.location.href);
|
||||||
|
return docUrl.searchParams.get("v");
|
||||||
|
}
|
||||||
|
|
||||||
|
get #videoEl() {
|
||||||
|
return document.querySelector(VIDEO_SELECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
set #progressed(num) {
|
||||||
|
this.#progressedNum = num;
|
||||||
|
this.#sendMenusMsg({ action: MSG_MENUS_PROGRESSED, data: num });
|
||||||
|
}
|
||||||
|
|
||||||
|
get #progressed() {
|
||||||
|
return this.#progressedNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
@@ -47,35 +76,47 @@ class YouTubeCaptionProvider {
|
|||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("yt-navigate-finish", () => {
|
window.addEventListener("yt-navigate-finish", () => {
|
||||||
setTimeout(() => {
|
logger.debug("Youtube Provider: yt-navigate-finish", this.#videoId);
|
||||||
if (this.#toggleButton) {
|
|
||||||
this.#toggleButton.style.opacity = "0.5";
|
|
||||||
}
|
|
||||||
this.#destroyManager();
|
this.#destroyManager();
|
||||||
this.#doubleClick();
|
|
||||||
}, 1000);
|
this.#subtitles = [];
|
||||||
|
this.#flatEvents = [];
|
||||||
|
this.#progressed = 0;
|
||||||
|
this.#fromLang = "auto";
|
||||||
|
this.#setting.isAISegment = false;
|
||||||
|
this.#sendMenusMsg({
|
||||||
|
action: MSG_MENUS_UPDATEFORM,
|
||||||
|
data: { isAISegment: false },
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.#waitForElement(CONTORLS_SELECT, (ytControls) =>
|
this.#waitForElement(CONTORLS_SELECT, (ytControls) => {
|
||||||
this.#injectToggleButton(ytControls)
|
const ytSubtitleBtn = ytControls.querySelector(YT_SUBTITLE_BTN_SELECT);
|
||||||
);
|
if (ytSubtitleBtn) {
|
||||||
|
ytSubtitleBtn.addEventListener("click", () => {
|
||||||
|
if (ytSubtitleBtn.getAttribute("aria-pressed") === "true") {
|
||||||
|
this.#startManager();
|
||||||
|
} else {
|
||||||
|
this.#destroyManager();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#injectToggleButton(ytControls);
|
||||||
|
});
|
||||||
|
|
||||||
this.#waitForElement(YT_AD_SELECT, (adContainer) => {
|
this.#waitForElement(YT_AD_SELECT, (adContainer) => {
|
||||||
this.#moAds(adContainer);
|
this.#moAds(adContainer);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get #videoEl() {
|
|
||||||
return document.querySelector(VIDEO_SELECT);
|
|
||||||
}
|
|
||||||
|
|
||||||
#moAds(adContainer) {
|
#moAds(adContainer) {
|
||||||
const { skipAd = false } = this.#setting;
|
|
||||||
|
|
||||||
const adLayoutSelector = ".ytp-ad-player-overlay-layout";
|
const adLayoutSelector = ".ytp-ad-player-overlay-layout";
|
||||||
const skipBtnSelector =
|
const skipBtnSelector =
|
||||||
".ytp-skip-ad-button, .ytp-ad-skip-button, .ytp-ad-skip-button-modern";
|
".ytp-skip-ad-button, .ytp-ad-skip-button, .ytp-ad-skip-button-modern";
|
||||||
const observer = new MutationObserver((mutations) => {
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
const { skipAd = false } = this.#setting;
|
||||||
for (const mutation of mutations) {
|
for (const mutation of mutations) {
|
||||||
if (mutation.type === "childList") {
|
if (mutation.type === "childList") {
|
||||||
const videoEl = this.#videoEl;
|
const videoEl = this.#videoEl;
|
||||||
@@ -149,60 +190,93 @@ class YouTubeCaptionProvider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async #doubleClick() {
|
updateSetting({ name, value }) {
|
||||||
const button = this.#ytControls?.querySelector(
|
if (this.#setting[name] === value) return;
|
||||||
"button.ytp-subtitles-button"
|
|
||||||
);
|
logger.debug("Youtube Provider: update setting", name, value);
|
||||||
if (button) {
|
this.#setting[name] = value;
|
||||||
await sleep(randomBetween(50, 100));
|
|
||||||
button.click();
|
if (name === "isBilingual") {
|
||||||
await sleep(randomBetween(500, 1000));
|
this.#managerInstance?.updateSetting({ [name]: value });
|
||||||
button.click();
|
} else if (name === "isAISegment") {
|
||||||
|
this.#reProcessEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
downloadSubtitle() {
|
||||||
|
if (!this.#subtitles.length || this.#progressed !== 100) {
|
||||||
|
logger.debug("Youtube Provider: The subtitle is not yet ready.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const vtt = buildBilingualVtt(this.#subtitles);
|
||||||
|
downloadBlobFile(
|
||||||
|
vtt,
|
||||||
|
`kiss-subtitles-${this.#videoId}_${Date.now()}.vtt`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
logger.info("Youtube Provider: download subtitles:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#sendMenusMsg({ action, data }) {
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent(this.#menuEventName, { detail: { action, data } })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#injectToggleButton(ytControls) {
|
#injectToggleButton(ytControls) {
|
||||||
this.#ytControls = ytControls;
|
|
||||||
|
|
||||||
const kissControls = document.createElement("div");
|
const kissControls = document.createElement("div");
|
||||||
kissControls.className = "notranslate kiss-subtitle-controls";
|
kissControls.className = "notranslate kiss-subtitle-controls";
|
||||||
Object.assign(kissControls.style, {
|
Object.assign(kissControls.style, {
|
||||||
height: "100%",
|
height: "100%",
|
||||||
|
position: "relative",
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggleButton = document.createElement("button");
|
const toggleButton = document.createElement("button");
|
||||||
toggleButton.className = "ytp-button kiss-subtitle-button";
|
toggleButton.className = "ytp-button kiss-subtitle-button";
|
||||||
toggleButton.title = APP_NAME;
|
toggleButton.title = APP_NAME;
|
||||||
Object.assign(toggleButton.style, {
|
|
||||||
color: "white",
|
|
||||||
opacity: "0.5",
|
|
||||||
});
|
|
||||||
|
|
||||||
toggleButton.appendChild(createLogoSVG());
|
toggleButton.appendChild(createLogoSVG());
|
||||||
kissControls.appendChild(toggleButton);
|
kissControls.appendChild(toggleButton);
|
||||||
|
|
||||||
toggleButton.onclick = () => {
|
const { segApiSetting, isAISegment, skipAd, isBilingual } = this.#setting;
|
||||||
if (this.#isBusy) {
|
const menu = new ShadowDomManager({
|
||||||
logger.info(`Youtube Provider: It's budy now...`);
|
id: "kiss-subtitle-menus",
|
||||||
this.#showNotification(this.#i18n("subtitle_data_processing"));
|
className: "notranslate",
|
||||||
}
|
reactComponent: Menus,
|
||||||
|
rootElement: kissControls,
|
||||||
|
props: {
|
||||||
|
i18n: this.#i18n,
|
||||||
|
updateSetting: this.updateSetting.bind(this),
|
||||||
|
downloadSubtitle: this.downloadSubtitle.bind(this),
|
||||||
|
hasSegApi: !!segApiSetting,
|
||||||
|
eventName: this.#menuEventName,
|
||||||
|
initData: {
|
||||||
|
isAISegment,
|
||||||
|
skipAd,
|
||||||
|
isBilingual,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!this.#enabled) {
|
toggleButton.onclick = () => {
|
||||||
logger.info(`Youtube Provider: Feature toggled ON.`);
|
if (!this.#isMenuShow) {
|
||||||
this.#enabled = true;
|
this.#isMenuShow = true;
|
||||||
this.#toggleButton?.replaceChildren(
|
this.#toggleButton?.replaceChildren(
|
||||||
createLogoSVG({ isSelected: true })
|
createLogoSVG({ isSelected: true })
|
||||||
);
|
);
|
||||||
this.#startManager();
|
menu.show();
|
||||||
} else {
|
} else {
|
||||||
logger.info(`Youtube Provider: Feature toggled OFF.`);
|
this.#isMenuShow = false;
|
||||||
this.#enabled = false;
|
|
||||||
this.#toggleButton?.replaceChildren(createLogoSVG());
|
this.#toggleButton?.replaceChildren(createLogoSVG());
|
||||||
this.#destroyManager();
|
menu.hide();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.#toggleButton = toggleButton;
|
this.#toggleButton = toggleButton;
|
||||||
this.#ytControls?.prepend(kissControls);
|
|
||||||
|
ytControls?.prepend(kissControls);
|
||||||
}
|
}
|
||||||
|
|
||||||
#isSameLang(lang1, lang2) {
|
#isSameLang(lang1, lang2) {
|
||||||
@@ -290,11 +364,6 @@ class YouTubeCaptionProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#getVideoId() {
|
|
||||||
const docUrl = new URL(document.location.href);
|
|
||||||
return docUrl.searchParams.get("v");
|
|
||||||
}
|
|
||||||
|
|
||||||
async #aiSegment({ videoId, fromLang, toLang, chunkEvents, segApiSetting }) {
|
async #aiSegment({ videoId, fromLang, toLang, chunkEvents, segApiSetting }) {
|
||||||
try {
|
try {
|
||||||
const events = chunkEvents.filter((item) => item.text);
|
const events = chunkEvents.filter((item) => item.text);
|
||||||
@@ -326,36 +395,38 @@ class YouTubeCaptionProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async #handleInterceptedRequest(url, responseText) {
|
async #handleInterceptedRequest(url, responseText) {
|
||||||
if (this.#isBusy) {
|
const videoId = this.#videoId;
|
||||||
logger.info("Youtube Provider is busy...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.#isBusy = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const videoId = this.#getVideoId();
|
|
||||||
if (!videoId) {
|
if (!videoId) {
|
||||||
logger.info("Youtube Provider: videoId not found.");
|
logger.debug("Youtube Provider: videoId not found.");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (videoId === this.#videoId) {
|
|
||||||
logger.info("Youtube Provider: videoId already processed.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const potUrl = new URL(url);
|
const potUrl = new URL(url);
|
||||||
if (videoId !== potUrl.searchParams.get("v")) {
|
if (videoId !== potUrl.searchParams.get("v")) {
|
||||||
logger.info("Youtube Provider: skip other timedtext.");
|
logger.debug("Youtube Provider: skip other timedtext:", videoId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { segApiSetting, toLang } = this.#setting;
|
if (this.#flatEvents.length) {
|
||||||
|
logger.debug("Youtube Provider: video was processed:", videoId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoId === this.#processingId) {
|
||||||
|
logger.debug("Youtube Provider: video is processing:", videoId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#processingId = videoId;
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.#showNotification(this.#i18n("starting_to_process_subtitle"));
|
||||||
|
|
||||||
|
const { toLang } = this.#setting;
|
||||||
const captionTracks = await this.#getCaptionTracks(videoId);
|
const captionTracks = await this.#getCaptionTracks(videoId);
|
||||||
const captionTrack = this.#findCaptionTrack(captionTracks);
|
const captionTrack = this.#findCaptionTrack(captionTracks);
|
||||||
if (!captionTrack) {
|
if (!captionTrack) {
|
||||||
logger.info("Youtube Provider: CaptionTrack not found.");
|
logger.debug("Youtube Provider: CaptionTrack not found:", videoId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +437,7 @@ class YouTubeCaptionProvider {
|
|||||||
responseText
|
responseText
|
||||||
);
|
);
|
||||||
if (!events?.length) {
|
if (!events?.length) {
|
||||||
logger.info("Youtube Provider: SubtitleEvents not got.");
|
logger.debug("Youtube Provider: events not got:", videoId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,33 +451,97 @@ class YouTubeCaptionProvider {
|
|||||||
`Youtube Provider: fromLang: ${fromLang}, toLang: ${toLang}`
|
`Youtube Provider: fromLang: ${fromLang}, toLang: ${toLang}`
|
||||||
);
|
);
|
||||||
if (this.#isSameLang(fromLang, toLang)) {
|
if (this.#isSameLang(fromLang, toLang)) {
|
||||||
logger.info("Youtube Provider: skip same lang", fromLang, toLang);
|
logger.debug("Youtube Provider: skip same lang", fromLang, toLang);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#showNotification(this.#i18n("starting_to_process_subtitle"));
|
const flatEvents = this.#genFlatEvents(events);
|
||||||
|
if (!flatEvents?.length) {
|
||||||
|
logger.debug("Youtube Provider: flatEvents not got:", videoId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const flatEvents = this.#flatEvents(events);
|
this.#flatEvents = flatEvents;
|
||||||
if (!flatEvents.length) return;
|
this.#fromLang = fromLang;
|
||||||
|
|
||||||
if (potUrl.searchParams.get("kind") === "asr" && segApiSetting) {
|
this.#processEvents({
|
||||||
logger.info("Youtube Provider: Starting AI ...");
|
videoId,
|
||||||
|
|
||||||
const eventChunks = this.#splitEventsIntoChunks(
|
|
||||||
flatEvents,
|
flatEvents,
|
||||||
segApiSetting.chunkLength
|
fromLang,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn("Youtube Provider: handle subtitle", error);
|
||||||
|
this.#showNotification(this.#i18n("subtitle_load_failed"));
|
||||||
|
} finally {
|
||||||
|
this.#processingId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async #processEvents({ videoId, flatEvents, fromLang }) {
|
||||||
|
try {
|
||||||
|
const [subtitles, progressed] = await this.#eventsToSubtitles({
|
||||||
|
videoId,
|
||||||
|
flatEvents,
|
||||||
|
fromLang,
|
||||||
|
});
|
||||||
|
if (!subtitles?.length) {
|
||||||
|
logger.debug(
|
||||||
|
"Youtube Provider: events to subtitles got empty",
|
||||||
|
videoId
|
||||||
);
|
);
|
||||||
const subtitlesFallback = () =>
|
return;
|
||||||
this.#formatSubtitles(flatEvents, fromLang);
|
}
|
||||||
|
|
||||||
|
if (videoId !== this.#videoId) {
|
||||||
|
logger.debug(
|
||||||
|
"Youtube Provider: videoId changed!",
|
||||||
|
videoId,
|
||||||
|
this.#videoId
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#subtitles = subtitles;
|
||||||
|
this.#progressed = progressed;
|
||||||
|
|
||||||
|
this.#startManager();
|
||||||
|
} catch (error) {
|
||||||
|
logger.info("Youtube Provider: process events", error);
|
||||||
|
this.#showNotification(this.#i18n("subtitle_load_failed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#reProcessEvents() {
|
||||||
|
const videoId = this.#videoId;
|
||||||
|
const flatEvents = this.#flatEvents;
|
||||||
|
const fromLang = this.#fromLang;
|
||||||
|
if (!videoId || !flatEvents.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#showNotification(this.#i18n("starting_reprocess_events"));
|
||||||
|
|
||||||
|
this.#destroyManager();
|
||||||
|
|
||||||
|
this.#processEvents({ videoId, flatEvents, fromLang });
|
||||||
|
}
|
||||||
|
|
||||||
|
async #eventsToSubtitles({ videoId, flatEvents, fromLang }) {
|
||||||
|
const { isAISegment, segApiSetting, chunkLength, toLang } = this.#setting;
|
||||||
|
const subtitlesFallback = () => [
|
||||||
|
this.#formatSubtitles(flatEvents, fromLang),
|
||||||
|
100,
|
||||||
|
];
|
||||||
|
|
||||||
|
// potUrl.searchParams.get("kind") === "asr"
|
||||||
|
if (isAISegment && segApiSetting) {
|
||||||
|
logger.info("Youtube Provider: Starting AI ...");
|
||||||
|
this.#showNotification(this.#i18n("ai_processing_pls_wait"));
|
||||||
|
|
||||||
|
const eventChunks = this.#splitEventsIntoChunks(flatEvents, chunkLength);
|
||||||
|
|
||||||
if (eventChunks.length === 0) {
|
if (eventChunks.length === 0) {
|
||||||
this.#onCaptionsReady({
|
return subtitlesFallback();
|
||||||
videoId,
|
|
||||||
subtitles: subtitlesFallback(),
|
|
||||||
fromLang,
|
|
||||||
isInitialLoad: true,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstChunkEvents = eventChunks[0];
|
const firstChunkEvents = eventChunks[0];
|
||||||
@@ -419,69 +554,28 @@ class YouTubeCaptionProvider {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!firstBatchSubtitles?.length) {
|
if (!firstBatchSubtitles?.length) {
|
||||||
this.#onCaptionsReady({
|
return subtitlesFallback();
|
||||||
videoId,
|
|
||||||
subtitles: subtitlesFallback(),
|
|
||||||
fromLang,
|
|
||||||
isInitialLoad: true,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#onCaptionsReady({
|
const chunkCount = eventChunks.length;
|
||||||
videoId,
|
if (chunkCount > 1) {
|
||||||
subtitles: firstBatchSubtitles,
|
|
||||||
fromLang,
|
|
||||||
isInitialLoad: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (eventChunks.length > 1) {
|
|
||||||
const remainingChunks = eventChunks.slice(1);
|
const remainingChunks = eventChunks.slice(1);
|
||||||
this.#processRemainingChunksAsync({
|
this.#processRemainingChunksAsync({
|
||||||
chunks: remainingChunks,
|
chunks: remainingChunks,
|
||||||
|
chunkCount,
|
||||||
videoId,
|
videoId,
|
||||||
fromLang,
|
fromLang,
|
||||||
toLang,
|
toLang,
|
||||||
segApiSetting,
|
segApiSetting,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
return [firstBatchSubtitles, 100 / eventChunks.length];
|
||||||
} else {
|
} else {
|
||||||
const subtitles = this.#formatSubtitles(flatEvents, fromLang);
|
return [firstBatchSubtitles, 100];
|
||||||
if (!subtitles?.length) {
|
|
||||||
logger.info("Youtube Provider: No subtitles after format.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#onCaptionsReady({
|
|
||||||
videoId,
|
|
||||||
subtitles,
|
|
||||||
fromLang,
|
|
||||||
isInitialLoad: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
logger.warn("Youtube Provider: unknow error", error);
|
|
||||||
this.#showNotification(this.#i18n("subtitle_load_failed"));
|
|
||||||
} finally {
|
|
||||||
this.#isBusy = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#onCaptionsReady({ videoId, subtitles, fromLang }) {
|
return subtitlesFallback();
|
||||||
this.#subtitles = subtitles;
|
|
||||||
this.#videoId = videoId;
|
|
||||||
this.#fromLang = fromLang;
|
|
||||||
|
|
||||||
if (this.#toggleButton) {
|
|
||||||
this.#toggleButton.style.opacity = subtitles.length ? "1" : "0.5";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#destroyManager();
|
|
||||||
if (this.#enabled) {
|
|
||||||
this.#startManager();
|
|
||||||
} else {
|
|
||||||
this.#showNotification(this.#i18n("subtitle_data_is_ready"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#startManager() {
|
#startManager() {
|
||||||
@@ -489,11 +583,8 @@ class YouTubeCaptionProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const videoId = this.#getVideoId();
|
if (!this.#subtitles.length) {
|
||||||
if (!this.#subtitles?.length || this.#videoId !== videoId) {
|
this.#showNotification(this.#i18n("waitting_for_subtitle"));
|
||||||
logger.info("Youtube Provider: No subtitles");
|
|
||||||
this.#showNotification(this.#i18n("try_get_subtitle_data"));
|
|
||||||
this.#doubleClick();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,7 +837,7 @@ class YouTubeCaptionProvider {
|
|||||||
return sentences;
|
return sentences;
|
||||||
}
|
}
|
||||||
|
|
||||||
#flatEvents(events = []) {
|
#genFlatEvents(events = []) {
|
||||||
const segments = [];
|
const segments = [];
|
||||||
let buffer = null;
|
let buffer = null;
|
||||||
|
|
||||||
@@ -829,6 +920,7 @@ class YouTubeCaptionProvider {
|
|||||||
|
|
||||||
async #processRemainingChunksAsync({
|
async #processRemainingChunksAsync({
|
||||||
chunks,
|
chunks,
|
||||||
|
chunkCount,
|
||||||
videoId,
|
videoId,
|
||||||
fromLang,
|
fromLang,
|
||||||
toLang,
|
toLang,
|
||||||
@@ -839,7 +931,7 @@ class YouTubeCaptionProvider {
|
|||||||
for (let i = 0; i < chunks.length; i++) {
|
for (let i = 0; i < chunks.length; i++) {
|
||||||
const chunkEvents = chunks[i];
|
const chunkEvents = chunks[i];
|
||||||
const chunkNum = i + 2;
|
const chunkNum = i + 2;
|
||||||
logger.info(
|
logger.debug(
|
||||||
`Youtube Provider: Processing subtitle chunk ${chunkNum}/${chunks.length + 1}: ${chunkEvents[0]?.start} --> ${chunkEvents[chunkEvents.length - 1]?.start}`
|
`Youtube Provider: Processing subtitle chunk ${chunkNum}/${chunks.length + 1}: ${chunkEvents[0]?.start} --> ${chunkEvents[chunkEvents.length - 1]?.start}`
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -857,7 +949,7 @@ class YouTubeCaptionProvider {
|
|||||||
if (aiSubtitles?.length > 0) {
|
if (aiSubtitles?.length > 0) {
|
||||||
subtitlesForThisChunk = aiSubtitles;
|
subtitlesForThisChunk = aiSubtitles;
|
||||||
} else {
|
} else {
|
||||||
logger.info(
|
logger.debug(
|
||||||
`Youtube Provider: AI segmentation for chunk ${chunkNum} returned no data.`
|
`Youtube Provider: AI segmentation for chunk ${chunkNum} returned no data.`
|
||||||
);
|
);
|
||||||
subtitlesForThisChunk = this.#formatSubtitles(chunkEvents, fromLang);
|
subtitlesForThisChunk = this.#formatSubtitles(chunkEvents, fromLang);
|
||||||
@@ -866,19 +958,29 @@ class YouTubeCaptionProvider {
|
|||||||
subtitlesForThisChunk = this.#formatSubtitles(chunkEvents, fromLang);
|
subtitlesForThisChunk = this.#formatSubtitles(chunkEvents, fromLang);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.#getVideoId() !== videoId) {
|
if (videoId !== this.#videoId) {
|
||||||
logger.info("Youtube Provider: videoId changed!");
|
logger.info(
|
||||||
|
"Youtube Provider: videoId changed!!",
|
||||||
|
videoId,
|
||||||
|
this.#videoId
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subtitlesForThisChunk.length > 0 && this.#managerInstance) {
|
if (subtitlesForThisChunk.length > 0) {
|
||||||
logger.info(
|
const progressed = (chunkNum * 100) / chunkCount;
|
||||||
`Youtube Provider: Appending ${subtitlesForThisChunk.length} subtitles from chunk ${chunkNum}.`
|
this.#subtitles.push(...subtitlesForThisChunk);
|
||||||
|
this.#progressed = progressed;
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
`Youtube Provider: Appending ${subtitlesForThisChunk.length} subtitles from chunk ${chunkNum} (${this.#progressed}%).`
|
||||||
);
|
);
|
||||||
this.#subtitles.push(subtitlesForThisChunk);
|
|
||||||
|
if (this.#managerInstance) {
|
||||||
this.#managerInstance.appendSubtitles(subtitlesForThisChunk);
|
this.#managerInstance.appendSubtitles(subtitlesForThisChunk);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info(`Youtube Provider: Chunk ${chunkNum} no subtitles.`);
|
logger.debug(`Youtube Provider: Chunk ${chunkNum} no subtitles.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
await sleep(randomBetween(500, 1000));
|
await sleep(randomBetween(500, 1000));
|
||||||
|
|||||||
@@ -54,6 +54,25 @@ function parseTimestampToMilliseconds(timestamp) {
|
|||||||
return (hours * 3600 + minutes * 60 + seconds) * 1000 + milliseconds;
|
return (hours * 3600 + minutes * 60 + seconds) * 1000 + milliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将毫秒数转换为VTT时间戳字符串 (HH:MM:SS.mmm).
|
||||||
|
*
|
||||||
|
* @param {number} ms - 总毫秒数.
|
||||||
|
* @returns {string} - 格式化的VTT时间戳 (HH:MM:SS.mmm).
|
||||||
|
*/
|
||||||
|
function formatMillisecondsToTimestamp(ms) {
|
||||||
|
const totalSeconds = Math.floor(ms / 1000);
|
||||||
|
const milliseconds = String(ms % 1000).padStart(3, "0");
|
||||||
|
|
||||||
|
const totalMinutes = Math.floor(totalSeconds / 60);
|
||||||
|
const seconds = String(totalSeconds % 60).padStart(2, "0");
|
||||||
|
|
||||||
|
const hours = String(Math.floor(totalMinutes / 60)).padStart(2, "0");
|
||||||
|
const minutes = String(totalMinutes % 60).padStart(2, "0");
|
||||||
|
|
||||||
|
return `${hours}:${minutes}:${seconds}.${milliseconds}`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析包含双语字幕的VTT文件内容。
|
* 解析包含双语字幕的VTT文件内容。
|
||||||
* @param {string} vttText - VTT文件的文本内容。
|
* @param {string} vttText - VTT文件的文本内容。
|
||||||
@@ -97,3 +116,31 @@ export function parseBilingualVtt(vttText) {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 parseBilingualVtt 生成的JSON数据转换回标准的VTT字幕字符串。
|
||||||
|
* @param {Array<Object>} cues - 字幕对象数组,
|
||||||
|
* @returns {string} - 格式化的VTT文件内容字符串。
|
||||||
|
*/
|
||||||
|
export function buildBilingualVtt(cues) {
|
||||||
|
if (!Array.isArray(cues)) {
|
||||||
|
return "WEBVTT";
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = "WEBVTT";
|
||||||
|
|
||||||
|
const cueBlocks = cues.map((cue, index) => {
|
||||||
|
const startTime = formatMillisecondsToTimestamp(cue.start);
|
||||||
|
const endTime = formatMillisecondsToTimestamp(cue.end);
|
||||||
|
|
||||||
|
const cueIndex = index + 1;
|
||||||
|
const timestampLine = `${startTime} --> ${endTime}`;
|
||||||
|
|
||||||
|
const textLine = cue.text || "";
|
||||||
|
const translationLine = cue.translation || "";
|
||||||
|
|
||||||
|
return `${cueIndex}\n${timestampLine}\n${textLine}\n${translationLine}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return [header, ...cueBlocks].join("\n\n");
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import FileDownloadIcon from "@mui/icons-material/FileDownload";
|
|||||||
import LoadingButton from "@mui/lab/LoadingButton";
|
import LoadingButton from "@mui/lab/LoadingButton";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { kissLog } from "../../libs/log";
|
import { kissLog } from "../../libs/log";
|
||||||
|
import { downloadBlobFile } from "../../libs/utils";
|
||||||
|
|
||||||
export default function DownloadButton({ handleData, text, fileName }) {
|
export default function DownloadButton({ handleData, text, fileName }) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -10,13 +11,7 @@ export default function DownloadButton({ handleData, text, fileName }) {
|
|||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const data = await handleData();
|
const data = await handleData();
|
||||||
const url = window.URL.createObjectURL(new Blob([data]));
|
downloadBlobFile(data, fileName);
|
||||||
const link = document.createElement("a");
|
|
||||||
link.href = url;
|
|
||||||
link.setAttribute("download", fileName || `${Date.now()}.json`);
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
link.remove();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
kissLog("download", err);
|
kissLog("download", err);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export default function ReusableAutocomplete({
|
|||||||
name: name,
|
name: name,
|
||||||
value: newValue,
|
value: newValue,
|
||||||
},
|
},
|
||||||
|
preventDefault: () => {},
|
||||||
};
|
};
|
||||||
onChange(syntheticEvent);
|
onChange(syntheticEvent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
|
|||||||
parentStyle = "",
|
parentStyle = "",
|
||||||
grandStyle = "",
|
grandStyle = "",
|
||||||
injectJs = "",
|
injectJs = "",
|
||||||
// injectCss = "",
|
injectCss = "",
|
||||||
apiSlug,
|
apiSlug,
|
||||||
fromLang,
|
fromLang,
|
||||||
toLang,
|
toLang,
|
||||||
@@ -651,7 +651,7 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
|
|||||||
maxRows={10}
|
maxRows={10}
|
||||||
/> */}
|
/> */}
|
||||||
|
|
||||||
{/* <TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
label={i18n("inject_css")}
|
label={i18n("inject_css")}
|
||||||
helperText={i18n("inject_css_helper")}
|
helperText={i18n("inject_css_helper")}
|
||||||
@@ -661,7 +661,7 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
maxRows={10}
|
maxRows={10}
|
||||||
multiline
|
multiline
|
||||||
/> */}
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
label={i18n("inject_js")}
|
label={i18n("inject_js")}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ export default function SubtitleSetting() {
|
|||||||
apiSlug,
|
apiSlug,
|
||||||
segSlug,
|
segSlug,
|
||||||
chunkLength,
|
chunkLength,
|
||||||
|
preTrans = 90,
|
||||||
|
throttleTrans = 30,
|
||||||
toLang,
|
toLang,
|
||||||
isBilingual,
|
isBilingual,
|
||||||
skipAd = false,
|
skipAd = false,
|
||||||
@@ -114,6 +116,32 @@ export default function SubtitleSetting() {
|
|||||||
max={20000}
|
max={20000}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={12} md={6} lg={3}>
|
||||||
|
<ValidationInput
|
||||||
|
fullWidth
|
||||||
|
size="small"
|
||||||
|
label={i18n("pre_trans_seconds")}
|
||||||
|
type="number"
|
||||||
|
name="preTrans"
|
||||||
|
value={preTrans}
|
||||||
|
onChange={handleChange}
|
||||||
|
min={10}
|
||||||
|
max={36000}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={12} md={6} lg={3}>
|
||||||
|
<ValidationInput
|
||||||
|
fullWidth
|
||||||
|
size="small"
|
||||||
|
label={i18n("throttle_trans_interval")}
|
||||||
|
type="number"
|
||||||
|
name="throttleTrans"
|
||||||
|
value={throttleTrans}
|
||||||
|
onChange={handleChange}
|
||||||
|
min={1}
|
||||||
|
max={3600}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
<Grid item xs={12} sm={12} md={6} lg={3}>
|
<Grid item xs={12} sm={12} md={6} lg={3}>
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
|
|||||||
Reference in New Issue
Block a user