├── .github ├── ISSUE_TEMPLATE │ ├── ---bug.md │ └── ---feature.md └── workflows │ └── release.yml ├── .gitignore ├── .prettierrc.json ├── CHANGELOG.md ├── LICENSE ├── LICENSE.txt ├── README.md ├── easy-image-uploader.zip ├── manifest.json ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── deleter.ts ├── helper.ts ├── lang │ ├── README.md │ ├── helpers.ts │ └── locale │ │ ├── ar.ts │ │ ├── cz.ts │ │ ├── da.ts │ │ ├── de.ts │ │ ├── en-gb.ts │ │ ├── en.ts │ │ ├── es.ts │ │ ├── fr.ts │ │ ├── hi.ts │ │ ├── id.ts │ │ ├── it.ts │ │ ├── ja.ts │ │ ├── ko.ts │ │ ├── nl.ts │ │ ├── no.ts │ │ ├── pl.ts │ │ ├── pt-br.ts │ │ ├── pt.ts │ │ ├── ro.ts │ │ ├── ru.ts │ │ ├── tr.ts │ │ ├── zh-cn.ts │ │ └── zh-tw.ts ├── main.ts ├── setting.ts ├── uploader.ts └── utils.ts ├── tsconfig.json ├── versions.json └── workspace.code-workspace /.github/ISSUE_TEMPLATE/---bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 缺陷反馈 3 | about: Obsidian Image Uploader 不正确行为。 4 | title: "[Bug] " 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **扩展是否为最新版本** 11 | 12 | - [ ] 是 13 | 14 | 15 | **描述问题** 16 | 17 | 18 | 19 | **复现步骤** 20 | 21 | 22 | 23 | **期待的正常行为** 24 | 25 | 26 | 27 | **截图** 28 | 29 | 30 | 31 | **额外信息** 32 | 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/---feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 功能建议 3 | about: 请求实现新功能或改进已有功能。 4 | title: "[Feature] " 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **请描述目前使用Obsidian Image Uploader 遇到什么不便** 11 | 12 | 13 | 14 | 15 | **理想情况下,Obsidian Image Uploader 应该怎么做** 16 | 17 | 18 | 19 | 20 | **额外信息** 21 | 22 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # name: Build plugin 2 | 3 | # on: 4 | # push: 5 | # tags: 6 | # - "*" 7 | 8 | # env: 9 | # PLUGIN_NAME: dist 10 | 11 | # jobs: 12 | # build: 13 | # runs-on: ubuntu-latest 14 | 15 | # steps: 16 | # - uses: actions/checkout@v2 17 | # - name: Setup Node.js 18 | # uses: actions/setup-node@v2 19 | # with: 20 | # node-version: "14" 21 | # - name: Build 22 | # id: build 23 | # run: | 24 | # npm install 25 | # npm run build 26 | # mkdir ${{ env.PLUGIN_NAME }} 27 | # cp main.js manifest.json ${{ env.PLUGIN_NAME }} 28 | # zip -r ${{ env.PLUGIN_NAME }}.zip ${{ env.PLUGIN_NAME }} 29 | # ls 30 | # echo "::set-output name=tag_name::$(git tag --sort version:refname | tail -n 1)" 31 | # - name: Create Release 32 | # id: create_release 33 | # uses: actions/create-release@v1 34 | # env: 35 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | # with: 37 | # tag_name: ${{ github.ref }} 38 | # release_name: ${{ github.ref }} 39 | # draft: false 40 | # prerelease: false 41 | # - name: Upload zip file 42 | # id: upload-zip 43 | # uses: actions/upload-release-asset@v1 44 | # env: 45 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | # with: 47 | # upload_url: ${{ steps.create_release.outputs.upload_url }} 48 | # asset_path: ./${{ env.PLUGIN_NAME }}.zip 49 | # asset_name: ${{ env.PLUGIN_NAME }}-${{ steps.build.outputs.tag_name }}.zip 50 | # asset_content_type: application/zip 51 | # - name: Upload main.js 52 | # id: upload-main 53 | # uses: actions/upload-release-asset@v1 54 | # env: 55 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 56 | # with: 57 | # upload_url: ${{ steps.create_release.outputs.upload_url }} 58 | # asset_path: ./main.js 59 | # asset_name: main.js 60 | # asset_content_type: text/javascript 61 | # - name: Upload manifest.json 62 | # id: upload-manifest 63 | # uses: actions/upload-release-asset@v1 64 | # env: 65 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 66 | # with: 67 | # upload_url: ${{ steps.create_release.outputs.upload_url }} 68 | # asset_path: ./manifest.json 69 | # asset_name: manifest.json 70 | # asset_content_type: application/json 71 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Intellij 2 | *.iml 3 | .idea 4 | 5 | # npm 6 | node_modules 7 | 8 | # build 9 | *.js.map 10 | main.js 11 | 12 | # ignore 13 | data.json 14 | 15 | .DS_Store 16 | dist 17 | easy-image-uploader -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": false, 7 | "arrowParens": "avoid" 8 | } 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.0.0 2 | 3 | 支持 Blog MetaWeblog API 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Kirill Gavrilov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | 3 | Version 2.0, January 2004 4 | 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 16 | 17 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 18 | 19 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 20 | 21 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 22 | 23 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 24 | 25 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 26 | 27 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 28 | 29 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 30 | 31 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 32 | 33 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 34 | 35 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 36 | 37 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 38 | 39 | You must cause any modified files to carry prominent notices stating that You changed the files; and 40 | 41 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 42 | 43 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 44 | 45 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 46 | 47 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 48 | 49 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 50 | 51 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 52 | 53 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 54 | 55 | END OF TERMS AND CONDITIONS 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Obsidian Image Uploader 2 | 3 | 这是一个支持 Blog MetaWeblog API、PicGo、PicGo-Core 上传图片到图床的工具。 4 | 5 | 什么是 Blog MetaWeblog API 呢?简单来说,就是直接将图片上传到博客网站的服务器,例如上传到博客园,开源中国。**薅博客网站的羊毛,把博客网站当成免费并且优质的图床。** 6 | 7 | 你不需要新建 Github 库,不需要买腾讯云/阿里云/七牛云 OSS,不需要域名,不需要备案,不需要买 CDN !就可以拥有性能良好的图床。 8 | 9 | **有任何问题可联系作者**:[![Bilibili](https://img.shields.io/badge/-B站-808080?)](https://space.bilibili.com/96271327) [![TikTok](https://img.shields.io/badge/-抖音-808080?)](https://img2023.cnblogs.com/blog/2740513/202308/2740513-20230805232943210-456006284.jpg) [![公众号](https://img.shields.io/badge/-公众号-808080?logo=Weibo)](https://img2023.cnblogs.com/blog/2740513/202308/2740513-20230805222711650-1692038416.jpg) [![微信](https://img.shields.io/badge/-微信-808080)](https://img2023.cnblogs.com/blog/2740513/202308/2740513-20230805222553308-968510341.jpg) 10 | 11 | # 开始 12 | 13 | ## 下载安装 14 | 15 | 本插件暂未发布到 Obsidian 插件市场,你可以点击链接 [obsidian-image-uploader.zip](./obsidian-image-uploader.zip) 下载插件,解压后放到 {Your Obsidain Vault}/.obsidian/plugins 目录下即可。 16 | 17 | ## 基于 Blog MetaWeblog API(推荐) 18 | 19 | 以博客园为例:打开博客园设置,开启 MetaWebblog,获取登录用户名,登录令牌,图片上传的接口地址(BlogURL),用户 ID(就是接口地址最后一段,图片中就是 sancijun) 20 | 21 | ![image.png](https://img2023.cnblogs.com/blog/2740513/202308/2740513-20230805155248341-460300794.jpg) 22 | 23 | 打开 Obsidian 插件,设置插件参数: 24 | 25 | ![image.png](https://img2023.cnblogs.com/blog/2740513/202308/2740513-20230805160020170-452969692.png) 26 | 27 | 设置完成之后复制粘贴,右键上传,批量上传图片到博客网站,Markdown 文档中自动替换成上传后的图片链接。 28 | 29 | ## 基于 PicGo 30 | 31 | 1. 安装 PicGo 工具,并进行配置,配置参考[官网](https://github.com/Molunerfinn/PicGo) 32 | 2. 开启 PicGo 的 Server 服务,并记住端口号 33 | 3. 安装插件 34 | 4. 打开插件配置项,设置为http://127.0.0.1:{{PicGo设置的端口号}}/upload(例如:http://127.0.0.1:36677/upload) 35 | 5. 接下来试试看能否上传成功 36 | 37 | # 特性 38 | 39 | ## 剪切板上传 40 | 41 | 本插件支持黏贴剪切板的图片的时候直接上传,目前支持复制系统内图像直接上传。 42 | 支持通过设置 `frontmatter` 来控制单个文件的上传,默认值为 `true`,控制关闭请将该值设置为 `false` 43 | 44 | 支持 ".png", ".jpg", ".jpeg", ".bmp", ".gif", ".svg", ".tiff" 45 | 46 | 该功能在 PicGo 2.3.0-beta7 版本中无法使用,请更换其他版本 47 | 48 | ```yaml 49 | --- 50 | image-auto-upload: true 51 | --- 52 | ``` 53 | 54 | ## 批量上传一个文件中的所有图像文件 55 | 56 | 输入 `ctrl+P` 呼出面板,输入 `upload all images`,点击回车,就会自动开始上传。 57 | 58 | 路径解析优先级,会依次按照优先级查找: 59 | 60 | 1. 绝对路径,指基于库的绝对路径 61 | 2. 相对路径,以./或../开头 62 | 3. 尽可能简短的形式 63 | 64 | ## 批量下载网络图片到本地 65 | 66 | 输入 `ctrl+P` 呼出面板,输入 `download all images`,点击回车,就会自动开始下载。只在 win 进行过测试 67 | 68 | ## 支持右键菜单上传图片 69 | 70 | 目前已支持标准 md 以及 wiki 格式。支持相对路径以及绝对路径,需要进行正确设置,不然会引发奇怪的问题 71 | 72 | ## 支持拖拽上传 73 | 74 | 仅在使用 picGo 客户端时生效 75 | 76 | ## 支持 Picgo-Core 77 | 78 | 目前已经全功能支持 79 | 80 | ### 安装 81 | 82 | [官方文档:全局安装](https://picgo.github.io/PicGo-Core-Doc/zh/guide/getting-started.html#%E5%85%A8%E5%B1%80%E5%AE%89%E8%A3%85) 83 | 84 | ### PicGo-Core 配置 85 | 86 | [官方文档:配置](https://picgo.github.io/PicGo-Core-Doc/zh/guide/config.html#%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6) 87 | 88 | ### 插件配置 89 | 90 | `Default uploader` 选择 `PicGo-Core` 91 | 设置路径,默认为空,使用环境变量 92 | 也可以设置自定义路径 93 | 94 | # TODO 95 | 96 | - [ ] 支持添加水印 97 | - [ ] 支持同时使用 Blog MetaWeblog API + PicGo 作为备份 98 | 99 | # 联系作者 100 | 101 | ![联系作者](https://img2022.cnblogs.com/blog/2740513/202207/2740513-20220713233831988-965905513.png) 102 | 103 | # 致谢 104 | 105 | 本插件是基于 [renmu123/obsidian-image-auto-upload-plugin](https://github.com/renmu123/obsidian-image-auto-upload-plugin) 开发,非常感谢 renmu123/obsidian-image-auto-upload-plugin。 106 | -------------------------------------------------------------------------------- /easy-image-uploader.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sancijun/obsidian-image-uploader/c65ed1659cf134c0d6692359af0bfa0ae282bda1/easy-image-uploader.zip -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "easy-image-uploader", 3 | "name": "Easy Image Uploader", 4 | "version": "1.0.1", 5 | "minAppVersion": "0.10.7", 6 | "description": "简单好用的图床工具,支持直接将图片上传到博客网站、GitHub、Gitee、腾讯云,或者搭配 PicGo/PicGo-Core 使用。", 7 | "author": "三此君", 8 | "authorUrl": "https://github.com/sancijun/obsidian-image-uploader", 9 | "isDesktopOnly": true 10 | } 11 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easy-image-uploader", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "easy-image-uploader", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "cos-js-sdk-v5": "^1.4.20", 13 | "file-base64": "^1.0.0", 14 | "fix-path": "^4.0.0", 15 | "gm": "^1.25.0", 16 | "image-type": "^5.2.0", 17 | "xml2js": "^0.6.2" 18 | }, 19 | "devDependencies": { 20 | "@rollup/plugin-commonjs": "^25.0.4", 21 | "@rollup/plugin-json": "^6.0.0", 22 | "@rollup/plugin-node-resolve": "^15.0.2", 23 | "@rollup/plugin-typescript": "^11.1.0", 24 | "@types/electron": "^1.6.10", 25 | "@types/gm": "^1.25.1", 26 | "@types/node": "^14.14.2", 27 | "@types/xml2js": "^0.4.11", 28 | "obsidian": "^1.2.8", 29 | "rollup": "^3.29.0", 30 | "rollup-plugin-commonjs": "^10.1.0", 31 | "rollup-plugin-copy": "^3.4.0", 32 | "rollup-plugin-zip": "^1.0.3", 33 | "tslib": "^2.5.0", 34 | "typescript": "^5.0.4" 35 | } 36 | }, 37 | "node_modules/@codemirror/state": { 38 | "version": "6.2.1", 39 | "resolved": "https://npm.shopee.io/@codemirror%2fstate/-/state-6.2.1.tgz", 40 | "integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==", 41 | "dev": true, 42 | "license": "MIT", 43 | "peer": true 44 | }, 45 | "node_modules/@codemirror/view": { 46 | "version": "6.19.0", 47 | "resolved": "https://npm.shopee.io/@codemirror%2fview/-/view-6.19.0.tgz", 48 | "integrity": "sha512-XqNIfW/3GaaF+T7Q1jBcRLCPm1NbrR2DBxrXacSt1FG+rNsdsNn3/azAfgpUoJ7yy4xgd8xTPa3AlL+y0lMizQ==", 49 | "dev": true, 50 | "license": "MIT", 51 | "peer": true, 52 | "dependencies": { 53 | "@codemirror/state": "^6.1.4", 54 | "style-mod": "^4.1.0", 55 | "w3c-keyname": "^2.2.4" 56 | } 57 | }, 58 | "node_modules/@electron/get": { 59 | "version": "2.0.2", 60 | "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz", 61 | "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==", 62 | "dev": true, 63 | "license": "MIT", 64 | "dependencies": { 65 | "debug": "^4.1.1", 66 | "env-paths": "^2.2.0", 67 | "fs-extra": "^8.1.0", 68 | "got": "^11.8.5", 69 | "progress": "^2.0.3", 70 | "semver": "^6.2.0", 71 | "sumchecker": "^3.0.1" 72 | }, 73 | "engines": { 74 | "node": ">=12" 75 | }, 76 | "optionalDependencies": { 77 | "global-agent": "^3.0.0" 78 | } 79 | }, 80 | "node_modules/@jridgewell/sourcemap-codec": { 81 | "version": "1.4.15", 82 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 83 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 84 | "dev": true, 85 | "license": "MIT" 86 | }, 87 | "node_modules/@nodelib/fs.scandir": { 88 | "version": "2.1.5", 89 | "resolved": "https://npm.shopee.io/@nodelib%2ffs.scandir/-/fs.scandir-2.1.5.tgz", 90 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 91 | "dev": true, 92 | "license": "MIT", 93 | "dependencies": { 94 | "@nodelib/fs.stat": "2.0.5", 95 | "run-parallel": "^1.1.9" 96 | }, 97 | "engines": { 98 | "node": ">= 8" 99 | } 100 | }, 101 | "node_modules/@nodelib/fs.stat": { 102 | "version": "2.0.5", 103 | "resolved": "https://npm.shopee.io/@nodelib%2ffs.stat/-/fs.stat-2.0.5.tgz", 104 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 105 | "dev": true, 106 | "license": "MIT", 107 | "engines": { 108 | "node": ">= 8" 109 | } 110 | }, 111 | "node_modules/@nodelib/fs.walk": { 112 | "version": "1.2.8", 113 | "resolved": "https://npm.shopee.io/@nodelib%2ffs.walk/-/fs.walk-1.2.8.tgz", 114 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 115 | "dev": true, 116 | "license": "MIT", 117 | "dependencies": { 118 | "@nodelib/fs.scandir": "2.1.5", 119 | "fastq": "^1.6.0" 120 | }, 121 | "engines": { 122 | "node": ">= 8" 123 | } 124 | }, 125 | "node_modules/@rollup/plugin-commonjs": { 126 | "version": "25.0.4", 127 | "resolved": "https://npm.shopee.io/@rollup%2fplugin-commonjs/-/plugin-commonjs-25.0.4.tgz", 128 | "integrity": "sha512-L92Vz9WUZXDnlQQl3EwbypJR4+DM2EbsO+/KOcEkP4Mc6Ct453EeDB2uH9lgRwj4w5yflgNpq9pHOiY8aoUXBQ==", 129 | "dev": true, 130 | "license": "MIT", 131 | "dependencies": { 132 | "@rollup/pluginutils": "^5.0.1", 133 | "commondir": "^1.0.1", 134 | "estree-walker": "^2.0.2", 135 | "glob": "^8.0.3", 136 | "is-reference": "1.2.1", 137 | "magic-string": "^0.27.0" 138 | }, 139 | "engines": { 140 | "node": ">=14.0.0" 141 | }, 142 | "peerDependencies": { 143 | "rollup": "^2.68.0||^3.0.0" 144 | }, 145 | "peerDependenciesMeta": { 146 | "rollup": { 147 | "optional": true 148 | } 149 | } 150 | }, 151 | "node_modules/@rollup/plugin-json": { 152 | "version": "6.0.0", 153 | "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.0.0.tgz", 154 | "integrity": "sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==", 155 | "dev": true, 156 | "license": "MIT", 157 | "dependencies": { 158 | "@rollup/pluginutils": "^5.0.1" 159 | }, 160 | "engines": { 161 | "node": ">=14.0.0" 162 | }, 163 | "peerDependencies": { 164 | "rollup": "^1.20.0||^2.0.0||^3.0.0" 165 | }, 166 | "peerDependenciesMeta": { 167 | "rollup": { 168 | "optional": true 169 | } 170 | } 171 | }, 172 | "node_modules/@rollup/plugin-node-resolve": { 173 | "version": "15.2.1", 174 | "resolved": "https://npm.shopee.io/@rollup%2fplugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz", 175 | "integrity": "sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==", 176 | "dev": true, 177 | "license": "MIT", 178 | "dependencies": { 179 | "@rollup/pluginutils": "^5.0.1", 180 | "@types/resolve": "1.20.2", 181 | "deepmerge": "^4.2.2", 182 | "is-builtin-module": "^3.2.1", 183 | "is-module": "^1.0.0", 184 | "resolve": "^1.22.1" 185 | }, 186 | "engines": { 187 | "node": ">=14.0.0" 188 | }, 189 | "peerDependencies": { 190 | "rollup": "^2.78.0||^3.0.0" 191 | }, 192 | "peerDependenciesMeta": { 193 | "rollup": { 194 | "optional": true 195 | } 196 | } 197 | }, 198 | "node_modules/@rollup/plugin-typescript": { 199 | "version": "11.1.0", 200 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.0.tgz", 201 | "integrity": "sha512-86flrfE+bSHB69znnTV6kVjkncs2LBMhcTCyxWgRxLyfXfQrxg4UwlAqENnjrrxnSNS/XKCDJCl8EkdFJVHOxw==", 202 | "dev": true, 203 | "license": "MIT", 204 | "dependencies": { 205 | "@rollup/pluginutils": "^5.0.1", 206 | "resolve": "^1.22.1" 207 | }, 208 | "engines": { 209 | "node": ">=14.0.0" 210 | }, 211 | "peerDependencies": { 212 | "rollup": "^2.14.0||^3.0.0", 213 | "tslib": "*", 214 | "typescript": ">=3.7.0" 215 | }, 216 | "peerDependenciesMeta": { 217 | "rollup": { 218 | "optional": true 219 | }, 220 | "tslib": { 221 | "optional": true 222 | } 223 | } 224 | }, 225 | "node_modules/@rollup/pluginutils": { 226 | "version": "5.0.2", 227 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", 228 | "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", 229 | "dev": true, 230 | "license": "MIT", 231 | "dependencies": { 232 | "@types/estree": "^1.0.0", 233 | "estree-walker": "^2.0.2", 234 | "picomatch": "^2.3.1" 235 | }, 236 | "engines": { 237 | "node": ">=14.0.0" 238 | }, 239 | "peerDependencies": { 240 | "rollup": "^1.20.0||^2.0.0||^3.0.0" 241 | }, 242 | "peerDependenciesMeta": { 243 | "rollup": { 244 | "optional": true 245 | } 246 | } 247 | }, 248 | "node_modules/@sindresorhus/is": { 249 | "version": "4.6.0", 250 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", 251 | "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", 252 | "dev": true, 253 | "license": "MIT", 254 | "engines": { 255 | "node": ">=10" 256 | }, 257 | "funding": { 258 | "url": "https://github.com/sindresorhus/is?sponsor=1" 259 | } 260 | }, 261 | "node_modules/@szmarczak/http-timer": { 262 | "version": "4.0.6", 263 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", 264 | "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", 265 | "dev": true, 266 | "license": "MIT", 267 | "dependencies": { 268 | "defer-to-connect": "^2.0.0" 269 | }, 270 | "engines": { 271 | "node": ">=10" 272 | } 273 | }, 274 | "node_modules/@tokenizer/token": { 275 | "version": "0.3.0", 276 | "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", 277 | "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", 278 | "license": "MIT" 279 | }, 280 | "node_modules/@types/cacheable-request": { 281 | "version": "6.0.3", 282 | "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", 283 | "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", 284 | "dev": true, 285 | "license": "MIT", 286 | "dependencies": { 287 | "@types/http-cache-semantics": "*", 288 | "@types/keyv": "^3.1.4", 289 | "@types/node": "*", 290 | "@types/responselike": "^1.0.0" 291 | } 292 | }, 293 | "node_modules/@types/codemirror": { 294 | "version": "0.0.108", 295 | "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz", 296 | "integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==", 297 | "dev": true, 298 | "license": "MIT", 299 | "dependencies": { 300 | "@types/tern": "*" 301 | } 302 | }, 303 | "node_modules/@types/electron": { 304 | "version": "1.6.10", 305 | "resolved": "https://registry.npmjs.org/@types/electron/-/electron-1.6.10.tgz", 306 | "integrity": "sha512-MOCVyzIwkBEloreoCVrTV108vSf8fFIJPsGruLCoAoBZdxtnJUqKA4lNonf/2u1twSjAspPEfmEheC+TLm/cMw==", 307 | "deprecated": "This is a stub types definition for electron (https://github.com/electron/electron). electron provides its own type definitions, so you don't need @types/electron installed!", 308 | "dev": true, 309 | "license": "MIT", 310 | "dependencies": { 311 | "electron": "*" 312 | } 313 | }, 314 | "node_modules/@types/estree": { 315 | "version": "1.0.1", 316 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", 317 | "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", 318 | "dev": true, 319 | "license": "MIT" 320 | }, 321 | "node_modules/@types/fs-extra": { 322 | "version": "8.1.2", 323 | "resolved": "https://npm.shopee.io/@types%2ffs-extra/-/fs-extra-8.1.2.tgz", 324 | "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==", 325 | "dev": true, 326 | "license": "MIT", 327 | "dependencies": { 328 | "@types/node": "*" 329 | } 330 | }, 331 | "node_modules/@types/glob": { 332 | "version": "7.2.0", 333 | "resolved": "https://npm.shopee.io/@types%2fglob/-/glob-7.2.0.tgz", 334 | "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", 335 | "dev": true, 336 | "license": "MIT", 337 | "dependencies": { 338 | "@types/minimatch": "*", 339 | "@types/node": "*" 340 | } 341 | }, 342 | "node_modules/@types/gm": { 343 | "version": "1.25.1", 344 | "resolved": "https://npm.shopee.io/@types%2fgm/-/gm-1.25.1.tgz", 345 | "integrity": "sha512-WLqlPvjot5jxpt1AFxaWm0fgWZUBGXOPJC3ZrQgRpvpHYjwYbvr/4GwRzd0mXFfxzX+TrvXaow+/WbmWFHomlQ==", 346 | "dev": true, 347 | "license": "MIT", 348 | "dependencies": { 349 | "@types/node": "*" 350 | } 351 | }, 352 | "node_modules/@types/http-cache-semantics": { 353 | "version": "4.0.1", 354 | "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", 355 | "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", 356 | "dev": true, 357 | "license": "MIT" 358 | }, 359 | "node_modules/@types/keyv": { 360 | "version": "3.1.4", 361 | "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", 362 | "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", 363 | "dev": true, 364 | "license": "MIT", 365 | "dependencies": { 366 | "@types/node": "*" 367 | } 368 | }, 369 | "node_modules/@types/minimatch": { 370 | "version": "5.1.2", 371 | "resolved": "https://npm.shopee.io/@types%2fminimatch/-/minimatch-5.1.2.tgz", 372 | "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", 373 | "dev": true, 374 | "license": "MIT" 375 | }, 376 | "node_modules/@types/node": { 377 | "version": "14.18.46", 378 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.46.tgz", 379 | "integrity": "sha512-n4yVT5FuY5NCcGHCosQSGvvCT74HhowymPN2OEcsHPw6U1NuxV9dvxWbrM2dnBukWjdMYzig1WfIkWdTTQJqng==", 380 | "dev": true, 381 | "license": "MIT" 382 | }, 383 | "node_modules/@types/resolve": { 384 | "version": "1.20.2", 385 | "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", 386 | "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", 387 | "dev": true, 388 | "license": "MIT" 389 | }, 390 | "node_modules/@types/responselike": { 391 | "version": "1.0.0", 392 | "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", 393 | "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", 394 | "dev": true, 395 | "license": "MIT", 396 | "dependencies": { 397 | "@types/node": "*" 398 | } 399 | }, 400 | "node_modules/@types/tern": { 401 | "version": "0.23.4", 402 | "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz", 403 | "integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==", 404 | "dev": true, 405 | "license": "MIT", 406 | "dependencies": { 407 | "@types/estree": "*" 408 | } 409 | }, 410 | "node_modules/@types/xml2js": { 411 | "version": "0.4.11", 412 | "resolved": "https://npm.shopee.io/@types%2fxml2js/-/xml2js-0.4.11.tgz", 413 | "integrity": "sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==", 414 | "dev": true, 415 | "license": "MIT", 416 | "dependencies": { 417 | "@types/node": "*" 418 | } 419 | }, 420 | "node_modules/@types/yauzl": { 421 | "version": "2.10.0", 422 | "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", 423 | "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", 424 | "dev": true, 425 | "license": "MIT", 426 | "optional": true, 427 | "dependencies": { 428 | "@types/node": "*" 429 | } 430 | }, 431 | "node_modules/@xmldom/xmldom": { 432 | "version": "0.8.10", 433 | "resolved": "https://npm.shopee.io/@xmldom%2fxmldom/-/xmldom-0.8.10.tgz", 434 | "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", 435 | "license": "MIT", 436 | "engines": { 437 | "node": ">=10.0.0" 438 | } 439 | }, 440 | "node_modules/ansi-regex": { 441 | "version": "6.0.1", 442 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 443 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 444 | "license": "MIT", 445 | "engines": { 446 | "node": ">=12" 447 | }, 448 | "funding": { 449 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 450 | } 451 | }, 452 | "node_modules/array-parallel": { 453 | "version": "0.1.3", 454 | "resolved": "https://npm.shopee.io/array-parallel/-/array-parallel-0.1.3.tgz", 455 | "integrity": "sha1-j3hTCJJu1apHjEfmTRszS2wMlH0=", 456 | "license": "MIT" 457 | }, 458 | "node_modules/array-series": { 459 | "version": "0.1.5", 460 | "resolved": "https://npm.shopee.io/array-series/-/array-series-0.1.5.tgz", 461 | "integrity": "sha1-3103v8XC7wdV4qpPkv6ufUtaly8=", 462 | "license": "MIT" 463 | }, 464 | "node_modules/array-union": { 465 | "version": "2.1.0", 466 | "resolved": "https://npm.shopee.io/array-union/-/array-union-2.1.0.tgz", 467 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 468 | "dev": true, 469 | "license": "MIT", 470 | "engines": { 471 | "node": ">=8" 472 | } 473 | }, 474 | "node_modules/balanced-match": { 475 | "version": "1.0.2", 476 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 477 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 478 | "dev": true, 479 | "license": "MIT" 480 | }, 481 | "node_modules/boolean": { 482 | "version": "3.2.0", 483 | "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", 484 | "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", 485 | "dev": true, 486 | "license": "MIT", 487 | "optional": true 488 | }, 489 | "node_modules/brace-expansion": { 490 | "version": "2.0.1", 491 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 492 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 493 | "dev": true, 494 | "license": "MIT", 495 | "dependencies": { 496 | "balanced-match": "^1.0.0" 497 | } 498 | }, 499 | "node_modules/braces": { 500 | "version": "3.0.2", 501 | "resolved": "https://npm.shopee.io/braces/-/braces-3.0.2.tgz", 502 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 503 | "dev": true, 504 | "license": "MIT", 505 | "dependencies": { 506 | "fill-range": "^7.0.1" 507 | }, 508 | "engines": { 509 | "node": ">=8" 510 | } 511 | }, 512 | "node_modules/buffer-crc32": { 513 | "version": "0.2.13", 514 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 515 | "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", 516 | "dev": true, 517 | "license": "MIT", 518 | "engines": { 519 | "node": "*" 520 | } 521 | }, 522 | "node_modules/builtin-modules": { 523 | "version": "3.3.0", 524 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", 525 | "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", 526 | "dev": true, 527 | "license": "MIT", 528 | "engines": { 529 | "node": ">=6" 530 | }, 531 | "funding": { 532 | "url": "https://github.com/sponsors/sindresorhus" 533 | } 534 | }, 535 | "node_modules/cacheable-lookup": { 536 | "version": "5.0.4", 537 | "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", 538 | "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", 539 | "dev": true, 540 | "license": "MIT", 541 | "engines": { 542 | "node": ">=10.6.0" 543 | } 544 | }, 545 | "node_modules/cacheable-request": { 546 | "version": "7.0.2", 547 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", 548 | "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", 549 | "dev": true, 550 | "license": "MIT", 551 | "dependencies": { 552 | "clone-response": "^1.0.2", 553 | "get-stream": "^5.1.0", 554 | "http-cache-semantics": "^4.0.0", 555 | "keyv": "^4.0.0", 556 | "lowercase-keys": "^2.0.0", 557 | "normalize-url": "^6.0.1", 558 | "responselike": "^2.0.0" 559 | }, 560 | "engines": { 561 | "node": ">=8" 562 | } 563 | }, 564 | "node_modules/clone-response": { 565 | "version": "1.0.3", 566 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", 567 | "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", 568 | "dev": true, 569 | "license": "MIT", 570 | "dependencies": { 571 | "mimic-response": "^1.0.0" 572 | }, 573 | "funding": { 574 | "url": "https://github.com/sponsors/sindresorhus" 575 | } 576 | }, 577 | "node_modules/colorette": { 578 | "version": "1.4.0", 579 | "resolved": "https://npm.shopee.io/colorette/-/colorette-1.4.0.tgz", 580 | "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", 581 | "dev": true, 582 | "license": "MIT" 583 | }, 584 | "node_modules/commondir": { 585 | "version": "1.0.1", 586 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 587 | "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", 588 | "dev": true, 589 | "license": "MIT" 590 | }, 591 | "node_modules/concat-map": { 592 | "version": "0.0.1", 593 | "resolved": "https://npm.shopee.io/concat-map/-/concat-map-0.0.1.tgz", 594 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 595 | "dev": true, 596 | "license": "MIT" 597 | }, 598 | "node_modules/core-util-is": { 599 | "version": "1.0.3", 600 | "resolved": "https://npm.shopee.io/core-util-is/-/core-util-is-1.0.3.tgz", 601 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 602 | "license": "MIT" 603 | }, 604 | "node_modules/cos-js-sdk-v5": { 605 | "version": "1.4.20", 606 | "resolved": "https://npm.shopee.io/cos-js-sdk-v5/-/cos-js-sdk-v5-1.4.20.tgz", 607 | "integrity": "sha512-cGpmVoKN3iYBtWo8Lwp059fOrT4yyb/+I6fVS++Zyop/ZFJswDRkjnrASViwYd8N+hi3qWVAa6ruvvBsLutEwg==", 608 | "license": "ISC", 609 | "dependencies": { 610 | "@xmldom/xmldom": "^0.8.6" 611 | } 612 | }, 613 | "node_modules/cross-spawn": { 614 | "version": "7.0.3", 615 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 616 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 617 | "license": "MIT", 618 | "dependencies": { 619 | "path-key": "^3.1.0", 620 | "shebang-command": "^2.0.0", 621 | "which": "^2.0.1" 622 | }, 623 | "engines": { 624 | "node": ">= 8" 625 | } 626 | }, 627 | "node_modules/debug": { 628 | "version": "4.3.4", 629 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 630 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 631 | "dev": true, 632 | "license": "MIT", 633 | "dependencies": { 634 | "ms": "2.1.2" 635 | }, 636 | "engines": { 637 | "node": ">=6.0" 638 | }, 639 | "peerDependenciesMeta": { 640 | "supports-color": { 641 | "optional": true 642 | } 643 | } 644 | }, 645 | "node_modules/decompress-response": { 646 | "version": "6.0.0", 647 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", 648 | "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", 649 | "dev": true, 650 | "license": "MIT", 651 | "dependencies": { 652 | "mimic-response": "^3.1.0" 653 | }, 654 | "engines": { 655 | "node": ">=10" 656 | }, 657 | "funding": { 658 | "url": "https://github.com/sponsors/sindresorhus" 659 | } 660 | }, 661 | "node_modules/decompress-response/node_modules/mimic-response": { 662 | "version": "3.1.0", 663 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", 664 | "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", 665 | "dev": true, 666 | "license": "MIT", 667 | "engines": { 668 | "node": ">=10" 669 | }, 670 | "funding": { 671 | "url": "https://github.com/sponsors/sindresorhus" 672 | } 673 | }, 674 | "node_modules/deepmerge": { 675 | "version": "4.3.1", 676 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", 677 | "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", 678 | "dev": true, 679 | "license": "MIT", 680 | "engines": { 681 | "node": ">=0.10.0" 682 | } 683 | }, 684 | "node_modules/default-shell": { 685 | "version": "2.2.0", 686 | "resolved": "https://registry.npmjs.org/default-shell/-/default-shell-2.2.0.tgz", 687 | "integrity": "sha512-sPpMZcVhRQ0nEMDtuMJ+RtCxt7iHPAMBU+I4tAlo5dU1sjRpNax0crj6nR3qKpvVnckaQ9U38enXcwW9nZJeCw==", 688 | "license": "MIT", 689 | "engines": { 690 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 691 | }, 692 | "funding": { 693 | "url": "https://github.com/sponsors/sindresorhus" 694 | } 695 | }, 696 | "node_modules/defer-to-connect": { 697 | "version": "2.0.1", 698 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", 699 | "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", 700 | "dev": true, 701 | "license": "MIT", 702 | "engines": { 703 | "node": ">=10" 704 | } 705 | }, 706 | "node_modules/define-properties": { 707 | "version": "1.2.0", 708 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", 709 | "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", 710 | "dev": true, 711 | "license": "MIT", 712 | "optional": true, 713 | "dependencies": { 714 | "has-property-descriptors": "^1.0.0", 715 | "object-keys": "^1.1.1" 716 | }, 717 | "engines": { 718 | "node": ">= 0.4" 719 | }, 720 | "funding": { 721 | "url": "https://github.com/sponsors/ljharb" 722 | } 723 | }, 724 | "node_modules/detect-node": { 725 | "version": "2.1.0", 726 | "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", 727 | "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", 728 | "dev": true, 729 | "license": "MIT", 730 | "optional": true 731 | }, 732 | "node_modules/dir-glob": { 733 | "version": "3.0.1", 734 | "resolved": "https://npm.shopee.io/dir-glob/-/dir-glob-3.0.1.tgz", 735 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 736 | "dev": true, 737 | "license": "MIT", 738 | "dependencies": { 739 | "path-type": "^4.0.0" 740 | }, 741 | "engines": { 742 | "node": ">=8" 743 | } 744 | }, 745 | "node_modules/electron": { 746 | "version": "24.3.0", 747 | "resolved": "https://registry.npmjs.org/electron/-/electron-24.3.0.tgz", 748 | "integrity": "sha512-M7PpfpOzGdLeZPr2xhxXuvJeoXPEHMH40Rtv8BCGleRPolwna9BepAGc0H0F+Uz5kGKOv3xcm99fTurvXUH0nw==", 749 | "dev": true, 750 | "hasInstallScript": true, 751 | "license": "MIT", 752 | "dependencies": { 753 | "@electron/get": "^2.0.0", 754 | "@types/node": "^18.11.18", 755 | "extract-zip": "^2.0.1" 756 | }, 757 | "bin": { 758 | "electron": "cli.js" 759 | }, 760 | "engines": { 761 | "node": ">= 12.20.55" 762 | } 763 | }, 764 | "node_modules/electron/node_modules/@types/node": { 765 | "version": "18.16.7", 766 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.7.tgz", 767 | "integrity": "sha512-MFg7ua/bRtnA1hYE3pVyWxGd/r7aMqjNOdHvlSsXV3n8iaeGKkOaPzpJh6/ovf4bEXWcojkeMJpTsq3mzXW4IQ==", 768 | "dev": true, 769 | "license": "MIT" 770 | }, 771 | "node_modules/end-of-stream": { 772 | "version": "1.4.4", 773 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 774 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 775 | "dev": true, 776 | "license": "MIT", 777 | "dependencies": { 778 | "once": "^1.4.0" 779 | } 780 | }, 781 | "node_modules/env-paths": { 782 | "version": "2.2.1", 783 | "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", 784 | "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", 785 | "dev": true, 786 | "license": "MIT", 787 | "engines": { 788 | "node": ">=6" 789 | } 790 | }, 791 | "node_modules/es6-error": { 792 | "version": "4.1.1", 793 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 794 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 795 | "dev": true, 796 | "license": "MIT", 797 | "optional": true 798 | }, 799 | "node_modules/escape-string-regexp": { 800 | "version": "4.0.0", 801 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 802 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 803 | "dev": true, 804 | "license": "MIT", 805 | "optional": true, 806 | "engines": { 807 | "node": ">=10" 808 | }, 809 | "funding": { 810 | "url": "https://github.com/sponsors/sindresorhus" 811 | } 812 | }, 813 | "node_modules/estree-walker": { 814 | "version": "2.0.2", 815 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 816 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 817 | "dev": true, 818 | "license": "MIT" 819 | }, 820 | "node_modules/execa": { 821 | "version": "5.1.1", 822 | "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", 823 | "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", 824 | "license": "MIT", 825 | "dependencies": { 826 | "cross-spawn": "^7.0.3", 827 | "get-stream": "^6.0.0", 828 | "human-signals": "^2.1.0", 829 | "is-stream": "^2.0.0", 830 | "merge-stream": "^2.0.0", 831 | "npm-run-path": "^4.0.1", 832 | "onetime": "^5.1.2", 833 | "signal-exit": "^3.0.3", 834 | "strip-final-newline": "^2.0.0" 835 | }, 836 | "engines": { 837 | "node": ">=10" 838 | }, 839 | "funding": { 840 | "url": "https://github.com/sindresorhus/execa?sponsor=1" 841 | } 842 | }, 843 | "node_modules/execa/node_modules/get-stream": { 844 | "version": "6.0.1", 845 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", 846 | "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", 847 | "license": "MIT", 848 | "engines": { 849 | "node": ">=10" 850 | }, 851 | "funding": { 852 | "url": "https://github.com/sponsors/sindresorhus" 853 | } 854 | }, 855 | "node_modules/extract-zip": { 856 | "version": "2.0.1", 857 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", 858 | "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", 859 | "dev": true, 860 | "license": "BSD-2-Clause", 861 | "dependencies": { 862 | "debug": "^4.1.1", 863 | "get-stream": "^5.1.0", 864 | "yauzl": "^2.10.0" 865 | }, 866 | "bin": { 867 | "extract-zip": "cli.js" 868 | }, 869 | "engines": { 870 | "node": ">= 10.17.0" 871 | }, 872 | "optionalDependencies": { 873 | "@types/yauzl": "^2.9.1" 874 | } 875 | }, 876 | "node_modules/fast-glob": { 877 | "version": "3.3.1", 878 | "resolved": "https://npm.shopee.io/fast-glob/-/fast-glob-3.3.1.tgz", 879 | "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", 880 | "dev": true, 881 | "license": "MIT", 882 | "dependencies": { 883 | "@nodelib/fs.stat": "^2.0.2", 884 | "@nodelib/fs.walk": "^1.2.3", 885 | "glob-parent": "^5.1.2", 886 | "merge2": "^1.3.0", 887 | "micromatch": "^4.0.4" 888 | }, 889 | "engines": { 890 | "node": ">=8.6.0" 891 | } 892 | }, 893 | "node_modules/fastq": { 894 | "version": "1.15.0", 895 | "resolved": "https://npm.shopee.io/fastq/-/fastq-1.15.0.tgz", 896 | "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", 897 | "dev": true, 898 | "license": "ISC", 899 | "dependencies": { 900 | "reusify": "^1.0.4" 901 | } 902 | }, 903 | "node_modules/fd-slicer": { 904 | "version": "1.1.0", 905 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 906 | "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", 907 | "dev": true, 908 | "license": "MIT", 909 | "dependencies": { 910 | "pend": "~1.2.0" 911 | } 912 | }, 913 | "node_modules/file-base64": { 914 | "version": "1.0.0", 915 | "resolved": "https://npm.shopee.io/file-base64/-/file-base64-1.0.0.tgz", 916 | "integrity": "sha512-JOHtxfZUKANW2NRJeKTgPcudTN14fcD9crVKTmQsBtZrkUPEMoF5/rp8VOuYQGuapWKpLJv+XC8jnyMO3HTrjg==", 917 | "license": "MIT", 918 | "dependencies": { 919 | "into-stream": "^2.0.0" 920 | } 921 | }, 922 | "node_modules/file-type": { 923 | "version": "18.5.0", 924 | "resolved": "https://npm.shopee.io/file-type/-/file-type-18.5.0.tgz", 925 | "integrity": "sha512-yvpl5U868+V6PqXHMmsESpg6unQ5GfnPssl4dxdJudBrr9qy7Fddt7EVX1VLlddFfe8Gj9N7goCZH22FXuSQXQ==", 926 | "license": "MIT", 927 | "dependencies": { 928 | "readable-web-to-node-stream": "^3.0.2", 929 | "strtok3": "^7.0.0", 930 | "token-types": "^5.0.1" 931 | }, 932 | "engines": { 933 | "node": ">=14.16" 934 | }, 935 | "funding": { 936 | "url": "https://github.com/sindresorhus/file-type?sponsor=1" 937 | } 938 | }, 939 | "node_modules/fill-range": { 940 | "version": "7.0.1", 941 | "resolved": "https://npm.shopee.io/fill-range/-/fill-range-7.0.1.tgz", 942 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 943 | "dev": true, 944 | "license": "MIT", 945 | "dependencies": { 946 | "to-regex-range": "^5.0.1" 947 | }, 948 | "engines": { 949 | "node": ">=8" 950 | } 951 | }, 952 | "node_modules/fix-path": { 953 | "version": "4.0.0", 954 | "resolved": "https://registry.npmjs.org/fix-path/-/fix-path-4.0.0.tgz", 955 | "integrity": "sha512-g31GX207Tt+psI53ZSaB1egprYbEN0ZYl90aKcO22A2LmCNnFsSq3b5YpoKp3E/QEiWByTXGJOkFQG4S07Bc1A==", 956 | "license": "MIT", 957 | "dependencies": { 958 | "shell-path": "^3.0.0" 959 | }, 960 | "engines": { 961 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 962 | }, 963 | "funding": { 964 | "url": "https://github.com/sponsors/sindresorhus" 965 | } 966 | }, 967 | "node_modules/from2": { 968 | "version": "2.3.0", 969 | "resolved": "https://npm.shopee.io/from2/-/from2-2.3.0.tgz", 970 | "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", 971 | "license": "MIT", 972 | "dependencies": { 973 | "inherits": "^2.0.1", 974 | "readable-stream": "^2.0.0" 975 | } 976 | }, 977 | "node_modules/from2/node_modules/readable-stream": { 978 | "version": "2.3.8", 979 | "resolved": "https://npm.shopee.io/readable-stream/-/readable-stream-2.3.8.tgz", 980 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", 981 | "license": "MIT", 982 | "dependencies": { 983 | "core-util-is": "~1.0.0", 984 | "inherits": "~2.0.3", 985 | "isarray": "~1.0.0", 986 | "process-nextick-args": "~2.0.0", 987 | "safe-buffer": "~5.1.1", 988 | "string_decoder": "~1.1.1", 989 | "util-deprecate": "~1.0.1" 990 | } 991 | }, 992 | "node_modules/from2/node_modules/safe-buffer": { 993 | "version": "5.1.2", 994 | "resolved": "https://npm.shopee.io/safe-buffer/-/safe-buffer-5.1.2.tgz", 995 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 996 | "license": "MIT" 997 | }, 998 | "node_modules/from2/node_modules/string_decoder": { 999 | "version": "1.1.1", 1000 | "resolved": "https://npm.shopee.io/string_decoder/-/string_decoder-1.1.1.tgz", 1001 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1002 | "license": "MIT", 1003 | "dependencies": { 1004 | "safe-buffer": "~5.1.0" 1005 | } 1006 | }, 1007 | "node_modules/fs-extra": { 1008 | "version": "8.1.0", 1009 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 1010 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 1011 | "dev": true, 1012 | "license": "MIT", 1013 | "dependencies": { 1014 | "graceful-fs": "^4.2.0", 1015 | "jsonfile": "^4.0.0", 1016 | "universalify": "^0.1.0" 1017 | }, 1018 | "engines": { 1019 | "node": ">=6 <7 || >=8" 1020 | } 1021 | }, 1022 | "node_modules/fs.realpath": { 1023 | "version": "1.0.0", 1024 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1025 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 1026 | "dev": true, 1027 | "license": "ISC" 1028 | }, 1029 | "node_modules/fsevents": { 1030 | "version": "2.3.2", 1031 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 1032 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 1033 | "dev": true, 1034 | "hasInstallScript": true, 1035 | "license": "MIT", 1036 | "optional": true, 1037 | "os": [ 1038 | "darwin" 1039 | ], 1040 | "engines": { 1041 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1042 | } 1043 | }, 1044 | "node_modules/function-bind": { 1045 | "version": "1.1.1", 1046 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1047 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 1048 | "dev": true, 1049 | "license": "MIT" 1050 | }, 1051 | "node_modules/get-intrinsic": { 1052 | "version": "1.2.0", 1053 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 1054 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 1055 | "dev": true, 1056 | "license": "MIT", 1057 | "optional": true, 1058 | "dependencies": { 1059 | "function-bind": "^1.1.1", 1060 | "has": "^1.0.3", 1061 | "has-symbols": "^1.0.3" 1062 | }, 1063 | "funding": { 1064 | "url": "https://github.com/sponsors/ljharb" 1065 | } 1066 | }, 1067 | "node_modules/get-stream": { 1068 | "version": "5.2.0", 1069 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 1070 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 1071 | "dev": true, 1072 | "license": "MIT", 1073 | "dependencies": { 1074 | "pump": "^3.0.0" 1075 | }, 1076 | "engines": { 1077 | "node": ">=8" 1078 | }, 1079 | "funding": { 1080 | "url": "https://github.com/sponsors/sindresorhus" 1081 | } 1082 | }, 1083 | "node_modules/glob": { 1084 | "version": "8.1.0", 1085 | "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", 1086 | "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", 1087 | "dev": true, 1088 | "license": "ISC", 1089 | "dependencies": { 1090 | "fs.realpath": "^1.0.0", 1091 | "inflight": "^1.0.4", 1092 | "inherits": "2", 1093 | "minimatch": "^5.0.1", 1094 | "once": "^1.3.0" 1095 | }, 1096 | "engines": { 1097 | "node": ">=12" 1098 | }, 1099 | "funding": { 1100 | "url": "https://github.com/sponsors/isaacs" 1101 | } 1102 | }, 1103 | "node_modules/glob-parent": { 1104 | "version": "5.1.2", 1105 | "resolved": "https://npm.shopee.io/glob-parent/-/glob-parent-5.1.2.tgz", 1106 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1107 | "dev": true, 1108 | "license": "ISC", 1109 | "dependencies": { 1110 | "is-glob": "^4.0.1" 1111 | }, 1112 | "engines": { 1113 | "node": ">= 6" 1114 | } 1115 | }, 1116 | "node_modules/global-agent": { 1117 | "version": "3.0.0", 1118 | "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", 1119 | "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", 1120 | "dev": true, 1121 | "license": "BSD-3-Clause", 1122 | "optional": true, 1123 | "dependencies": { 1124 | "boolean": "^3.0.1", 1125 | "es6-error": "^4.1.1", 1126 | "matcher": "^3.0.0", 1127 | "roarr": "^2.15.3", 1128 | "semver": "^7.3.2", 1129 | "serialize-error": "^7.0.1" 1130 | }, 1131 | "engines": { 1132 | "node": ">=10.0" 1133 | } 1134 | }, 1135 | "node_modules/global-agent/node_modules/semver": { 1136 | "version": "7.5.0", 1137 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", 1138 | "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", 1139 | "dev": true, 1140 | "license": "ISC", 1141 | "optional": true, 1142 | "dependencies": { 1143 | "lru-cache": "^6.0.0" 1144 | }, 1145 | "bin": { 1146 | "semver": "bin/semver.js" 1147 | }, 1148 | "engines": { 1149 | "node": ">=10" 1150 | } 1151 | }, 1152 | "node_modules/globalthis": { 1153 | "version": "1.0.3", 1154 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", 1155 | "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", 1156 | "dev": true, 1157 | "license": "MIT", 1158 | "optional": true, 1159 | "dependencies": { 1160 | "define-properties": "^1.1.3" 1161 | }, 1162 | "engines": { 1163 | "node": ">= 0.4" 1164 | }, 1165 | "funding": { 1166 | "url": "https://github.com/sponsors/ljharb" 1167 | } 1168 | }, 1169 | "node_modules/globby": { 1170 | "version": "10.0.1", 1171 | "resolved": "https://npm.shopee.io/globby/-/globby-10.0.1.tgz", 1172 | "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", 1173 | "dev": true, 1174 | "license": "MIT", 1175 | "dependencies": { 1176 | "@types/glob": "^7.1.1", 1177 | "array-union": "^2.1.0", 1178 | "dir-glob": "^3.0.1", 1179 | "fast-glob": "^3.0.3", 1180 | "glob": "^7.1.3", 1181 | "ignore": "^5.1.1", 1182 | "merge2": "^1.2.3", 1183 | "slash": "^3.0.0" 1184 | }, 1185 | "engines": { 1186 | "node": ">=8" 1187 | } 1188 | }, 1189 | "node_modules/globby/node_modules/brace-expansion": { 1190 | "version": "1.1.11", 1191 | "resolved": "https://npm.shopee.io/brace-expansion/-/brace-expansion-1.1.11.tgz", 1192 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1193 | "dev": true, 1194 | "license": "MIT", 1195 | "dependencies": { 1196 | "balanced-match": "^1.0.0", 1197 | "concat-map": "0.0.1" 1198 | } 1199 | }, 1200 | "node_modules/globby/node_modules/glob": { 1201 | "version": "7.2.3", 1202 | "resolved": "https://npm.shopee.io/glob/-/glob-7.2.3.tgz", 1203 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 1204 | "dev": true, 1205 | "license": "ISC", 1206 | "dependencies": { 1207 | "fs.realpath": "^1.0.0", 1208 | "inflight": "^1.0.4", 1209 | "inherits": "2", 1210 | "minimatch": "^3.1.1", 1211 | "once": "^1.3.0", 1212 | "path-is-absolute": "^1.0.0" 1213 | }, 1214 | "engines": { 1215 | "node": "*" 1216 | }, 1217 | "funding": { 1218 | "url": "https://github.com/sponsors/isaacs" 1219 | } 1220 | }, 1221 | "node_modules/globby/node_modules/minimatch": { 1222 | "version": "3.1.2", 1223 | "resolved": "https://npm.shopee.io/minimatch/-/minimatch-3.1.2.tgz", 1224 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1225 | "dev": true, 1226 | "license": "ISC", 1227 | "dependencies": { 1228 | "brace-expansion": "^1.1.7" 1229 | }, 1230 | "engines": { 1231 | "node": "*" 1232 | } 1233 | }, 1234 | "node_modules/gm": { 1235 | "version": "1.25.0", 1236 | "resolved": "https://npm.shopee.io/gm/-/gm-1.25.0.tgz", 1237 | "integrity": "sha512-4kKdWXTtgQ4biIo7hZA396HT062nDVVHPjQcurNZ3o/voYN+o5FUC5kOwuORbpExp3XbTJ3SU7iRipiIhQtovw==", 1238 | "license": "MIT", 1239 | "dependencies": { 1240 | "array-parallel": "~0.1.3", 1241 | "array-series": "~0.1.5", 1242 | "cross-spawn": "^4.0.0", 1243 | "debug": "^3.1.0" 1244 | }, 1245 | "engines": { 1246 | "node": ">=14" 1247 | } 1248 | }, 1249 | "node_modules/gm/node_modules/cross-spawn": { 1250 | "version": "4.0.2", 1251 | "resolved": "https://npm.shopee.io/cross-spawn/-/cross-spawn-4.0.2.tgz", 1252 | "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", 1253 | "license": "MIT", 1254 | "dependencies": { 1255 | "lru-cache": "^4.0.1", 1256 | "which": "^1.2.9" 1257 | } 1258 | }, 1259 | "node_modules/gm/node_modules/debug": { 1260 | "version": "3.2.7", 1261 | "resolved": "https://npm.shopee.io/debug/-/debug-3.2.7.tgz", 1262 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 1263 | "license": "MIT", 1264 | "dependencies": { 1265 | "ms": "^2.1.1" 1266 | } 1267 | }, 1268 | "node_modules/gm/node_modules/lru-cache": { 1269 | "version": "4.1.5", 1270 | "resolved": "https://npm.shopee.io/lru-cache/-/lru-cache-4.1.5.tgz", 1271 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 1272 | "license": "ISC", 1273 | "dependencies": { 1274 | "pseudomap": "^1.0.2", 1275 | "yallist": "^2.1.2" 1276 | } 1277 | }, 1278 | "node_modules/gm/node_modules/which": { 1279 | "version": "1.3.1", 1280 | "resolved": "https://npm.shopee.io/which/-/which-1.3.1.tgz", 1281 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1282 | "license": "ISC", 1283 | "dependencies": { 1284 | "isexe": "^2.0.0" 1285 | }, 1286 | "bin": { 1287 | "which": "bin/which" 1288 | } 1289 | }, 1290 | "node_modules/gm/node_modules/yallist": { 1291 | "version": "2.1.2", 1292 | "resolved": "https://npm.shopee.io/yallist/-/yallist-2.1.2.tgz", 1293 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", 1294 | "license": "ISC" 1295 | }, 1296 | "node_modules/got": { 1297 | "version": "11.8.6", 1298 | "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", 1299 | "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", 1300 | "dev": true, 1301 | "license": "MIT", 1302 | "dependencies": { 1303 | "@sindresorhus/is": "^4.0.0", 1304 | "@szmarczak/http-timer": "^4.0.5", 1305 | "@types/cacheable-request": "^6.0.1", 1306 | "@types/responselike": "^1.0.0", 1307 | "cacheable-lookup": "^5.0.3", 1308 | "cacheable-request": "^7.0.2", 1309 | "decompress-response": "^6.0.0", 1310 | "http2-wrapper": "^1.0.0-beta.5.2", 1311 | "lowercase-keys": "^2.0.0", 1312 | "p-cancelable": "^2.0.0", 1313 | "responselike": "^2.0.0" 1314 | }, 1315 | "engines": { 1316 | "node": ">=10.19.0" 1317 | }, 1318 | "funding": { 1319 | "url": "https://github.com/sindresorhus/got?sponsor=1" 1320 | } 1321 | }, 1322 | "node_modules/graceful-fs": { 1323 | "version": "4.2.11", 1324 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1325 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 1326 | "dev": true, 1327 | "license": "ISC" 1328 | }, 1329 | "node_modules/has": { 1330 | "version": "1.0.3", 1331 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1332 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1333 | "dev": true, 1334 | "license": "MIT", 1335 | "dependencies": { 1336 | "function-bind": "^1.1.1" 1337 | }, 1338 | "engines": { 1339 | "node": ">= 0.4.0" 1340 | } 1341 | }, 1342 | "node_modules/has-property-descriptors": { 1343 | "version": "1.0.0", 1344 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", 1345 | "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", 1346 | "dev": true, 1347 | "license": "MIT", 1348 | "optional": true, 1349 | "dependencies": { 1350 | "get-intrinsic": "^1.1.1" 1351 | }, 1352 | "funding": { 1353 | "url": "https://github.com/sponsors/ljharb" 1354 | } 1355 | }, 1356 | "node_modules/has-symbols": { 1357 | "version": "1.0.3", 1358 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 1359 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 1360 | "dev": true, 1361 | "license": "MIT", 1362 | "optional": true, 1363 | "engines": { 1364 | "node": ">= 0.4" 1365 | }, 1366 | "funding": { 1367 | "url": "https://github.com/sponsors/ljharb" 1368 | } 1369 | }, 1370 | "node_modules/http-cache-semantics": { 1371 | "version": "4.1.1", 1372 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", 1373 | "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", 1374 | "dev": true, 1375 | "license": "BSD-2-Clause" 1376 | }, 1377 | "node_modules/http2-wrapper": { 1378 | "version": "1.0.3", 1379 | "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", 1380 | "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", 1381 | "dev": true, 1382 | "license": "MIT", 1383 | "dependencies": { 1384 | "quick-lru": "^5.1.1", 1385 | "resolve-alpn": "^1.0.0" 1386 | }, 1387 | "engines": { 1388 | "node": ">=10.19.0" 1389 | } 1390 | }, 1391 | "node_modules/human-signals": { 1392 | "version": "2.1.0", 1393 | "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", 1394 | "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", 1395 | "license": "Apache-2.0", 1396 | "engines": { 1397 | "node": ">=10.17.0" 1398 | } 1399 | }, 1400 | "node_modules/ieee754": { 1401 | "version": "1.2.1", 1402 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 1403 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 1404 | "funding": [ 1405 | { 1406 | "type": "github", 1407 | "url": "https://github.com/sponsors/feross" 1408 | }, 1409 | { 1410 | "type": "patreon", 1411 | "url": "https://www.patreon.com/feross" 1412 | }, 1413 | { 1414 | "type": "consulting", 1415 | "url": "https://feross.org/support" 1416 | } 1417 | ], 1418 | "license": "BSD-3-Clause" 1419 | }, 1420 | "node_modules/ignore": { 1421 | "version": "5.2.4", 1422 | "resolved": "https://npm.shopee.io/ignore/-/ignore-5.2.4.tgz", 1423 | "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", 1424 | "dev": true, 1425 | "license": "MIT", 1426 | "engines": { 1427 | "node": ">= 4" 1428 | } 1429 | }, 1430 | "node_modules/image-type": { 1431 | "version": "5.2.0", 1432 | "resolved": "https://npm.shopee.io/image-type/-/image-type-5.2.0.tgz", 1433 | "integrity": "sha512-f0+6qHeGfyEh1HhFGPUWZb+Dqqm6raKeeAR6Opt01wBBIQL32/1wpZkPQm8gcliB/Ws6oiX2ofFYXB57+CV0iQ==", 1434 | "license": "MIT", 1435 | "dependencies": { 1436 | "file-type": "^18.1.0" 1437 | }, 1438 | "engines": { 1439 | "node": ">=14.16" 1440 | }, 1441 | "funding": { 1442 | "url": "https://github.com/sponsors/sindresorhus" 1443 | } 1444 | }, 1445 | "node_modules/inflight": { 1446 | "version": "1.0.6", 1447 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1448 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1449 | "dev": true, 1450 | "license": "ISC", 1451 | "dependencies": { 1452 | "once": "^1.3.0", 1453 | "wrappy": "1" 1454 | } 1455 | }, 1456 | "node_modules/inherits": { 1457 | "version": "2.0.4", 1458 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1459 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1460 | "license": "ISC" 1461 | }, 1462 | "node_modules/into-stream": { 1463 | "version": "2.0.1", 1464 | "resolved": "https://npm.shopee.io/into-stream/-/into-stream-2.0.1.tgz", 1465 | "integrity": "sha1-25sANpRFPq4JHYpchMwRUHt4HTE=", 1466 | "license": "MIT", 1467 | "dependencies": { 1468 | "from2": "^2.1.1" 1469 | }, 1470 | "engines": { 1471 | "node": ">=0.10.0" 1472 | } 1473 | }, 1474 | "node_modules/is-builtin-module": { 1475 | "version": "3.2.1", 1476 | "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", 1477 | "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", 1478 | "dev": true, 1479 | "license": "MIT", 1480 | "dependencies": { 1481 | "builtin-modules": "^3.3.0" 1482 | }, 1483 | "engines": { 1484 | "node": ">=6" 1485 | }, 1486 | "funding": { 1487 | "url": "https://github.com/sponsors/sindresorhus" 1488 | } 1489 | }, 1490 | "node_modules/is-core-module": { 1491 | "version": "2.12.0", 1492 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", 1493 | "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", 1494 | "dev": true, 1495 | "license": "MIT", 1496 | "dependencies": { 1497 | "has": "^1.0.3" 1498 | }, 1499 | "funding": { 1500 | "url": "https://github.com/sponsors/ljharb" 1501 | } 1502 | }, 1503 | "node_modules/is-extglob": { 1504 | "version": "2.1.1", 1505 | "resolved": "https://npm.shopee.io/is-extglob/-/is-extglob-2.1.1.tgz", 1506 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1507 | "dev": true, 1508 | "license": "MIT", 1509 | "engines": { 1510 | "node": ">=0.10.0" 1511 | } 1512 | }, 1513 | "node_modules/is-glob": { 1514 | "version": "4.0.3", 1515 | "resolved": "https://npm.shopee.io/is-glob/-/is-glob-4.0.3.tgz", 1516 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1517 | "dev": true, 1518 | "license": "MIT", 1519 | "dependencies": { 1520 | "is-extglob": "^2.1.1" 1521 | }, 1522 | "engines": { 1523 | "node": ">=0.10.0" 1524 | } 1525 | }, 1526 | "node_modules/is-module": { 1527 | "version": "1.0.0", 1528 | "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", 1529 | "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", 1530 | "dev": true, 1531 | "license": "MIT" 1532 | }, 1533 | "node_modules/is-number": { 1534 | "version": "7.0.0", 1535 | "resolved": "https://npm.shopee.io/is-number/-/is-number-7.0.0.tgz", 1536 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1537 | "dev": true, 1538 | "license": "MIT", 1539 | "engines": { 1540 | "node": ">=0.12.0" 1541 | } 1542 | }, 1543 | "node_modules/is-plain-object": { 1544 | "version": "3.0.1", 1545 | "resolved": "https://npm.shopee.io/is-plain-object/-/is-plain-object-3.0.1.tgz", 1546 | "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", 1547 | "dev": true, 1548 | "license": "MIT", 1549 | "engines": { 1550 | "node": ">=0.10.0" 1551 | } 1552 | }, 1553 | "node_modules/is-reference": { 1554 | "version": "1.2.1", 1555 | "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", 1556 | "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", 1557 | "dev": true, 1558 | "license": "MIT", 1559 | "dependencies": { 1560 | "@types/estree": "*" 1561 | } 1562 | }, 1563 | "node_modules/is-stream": { 1564 | "version": "2.0.1", 1565 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", 1566 | "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", 1567 | "license": "MIT", 1568 | "engines": { 1569 | "node": ">=8" 1570 | }, 1571 | "funding": { 1572 | "url": "https://github.com/sponsors/sindresorhus" 1573 | } 1574 | }, 1575 | "node_modules/isarray": { 1576 | "version": "1.0.0", 1577 | "resolved": "https://npm.shopee.io/isarray/-/isarray-1.0.0.tgz", 1578 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 1579 | "license": "MIT" 1580 | }, 1581 | "node_modules/isexe": { 1582 | "version": "2.0.0", 1583 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1584 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1585 | "license": "ISC" 1586 | }, 1587 | "node_modules/json-buffer": { 1588 | "version": "3.0.1", 1589 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 1590 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", 1591 | "dev": true, 1592 | "license": "MIT" 1593 | }, 1594 | "node_modules/json-stringify-safe": { 1595 | "version": "5.0.1", 1596 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1597 | "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", 1598 | "dev": true, 1599 | "license": "ISC", 1600 | "optional": true 1601 | }, 1602 | "node_modules/jsonfile": { 1603 | "version": "4.0.0", 1604 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 1605 | "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", 1606 | "dev": true, 1607 | "license": "MIT", 1608 | "optionalDependencies": { 1609 | "graceful-fs": "^4.1.6" 1610 | } 1611 | }, 1612 | "node_modules/keyv": { 1613 | "version": "4.5.2", 1614 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", 1615 | "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", 1616 | "dev": true, 1617 | "license": "MIT", 1618 | "dependencies": { 1619 | "json-buffer": "3.0.1" 1620 | } 1621 | }, 1622 | "node_modules/lowercase-keys": { 1623 | "version": "2.0.0", 1624 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 1625 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 1626 | "dev": true, 1627 | "license": "MIT", 1628 | "engines": { 1629 | "node": ">=8" 1630 | } 1631 | }, 1632 | "node_modules/lru-cache": { 1633 | "version": "6.0.0", 1634 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1635 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1636 | "dev": true, 1637 | "license": "ISC", 1638 | "optional": true, 1639 | "dependencies": { 1640 | "yallist": "^4.0.0" 1641 | }, 1642 | "engines": { 1643 | "node": ">=10" 1644 | } 1645 | }, 1646 | "node_modules/magic-string": { 1647 | "version": "0.27.0", 1648 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", 1649 | "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", 1650 | "dev": true, 1651 | "license": "MIT", 1652 | "dependencies": { 1653 | "@jridgewell/sourcemap-codec": "^1.4.13" 1654 | }, 1655 | "engines": { 1656 | "node": ">=12" 1657 | } 1658 | }, 1659 | "node_modules/matcher": { 1660 | "version": "3.0.0", 1661 | "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", 1662 | "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", 1663 | "dev": true, 1664 | "license": "MIT", 1665 | "optional": true, 1666 | "dependencies": { 1667 | "escape-string-regexp": "^4.0.0" 1668 | }, 1669 | "engines": { 1670 | "node": ">=10" 1671 | } 1672 | }, 1673 | "node_modules/merge-stream": { 1674 | "version": "2.0.0", 1675 | "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", 1676 | "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", 1677 | "license": "MIT" 1678 | }, 1679 | "node_modules/merge2": { 1680 | "version": "1.4.1", 1681 | "resolved": "https://npm.shopee.io/merge2/-/merge2-1.4.1.tgz", 1682 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1683 | "dev": true, 1684 | "license": "MIT", 1685 | "engines": { 1686 | "node": ">= 8" 1687 | } 1688 | }, 1689 | "node_modules/micromatch": { 1690 | "version": "4.0.5", 1691 | "resolved": "https://npm.shopee.io/micromatch/-/micromatch-4.0.5.tgz", 1692 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", 1693 | "dev": true, 1694 | "license": "MIT", 1695 | "dependencies": { 1696 | "braces": "^3.0.2", 1697 | "picomatch": "^2.3.1" 1698 | }, 1699 | "engines": { 1700 | "node": ">=8.6" 1701 | } 1702 | }, 1703 | "node_modules/mimic-fn": { 1704 | "version": "2.1.0", 1705 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 1706 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 1707 | "license": "MIT", 1708 | "engines": { 1709 | "node": ">=6" 1710 | } 1711 | }, 1712 | "node_modules/mimic-response": { 1713 | "version": "1.0.1", 1714 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 1715 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 1716 | "dev": true, 1717 | "license": "MIT", 1718 | "engines": { 1719 | "node": ">=4" 1720 | } 1721 | }, 1722 | "node_modules/minimatch": { 1723 | "version": "5.1.6", 1724 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", 1725 | "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", 1726 | "dev": true, 1727 | "license": "ISC", 1728 | "dependencies": { 1729 | "brace-expansion": "^2.0.1" 1730 | }, 1731 | "engines": { 1732 | "node": ">=10" 1733 | } 1734 | }, 1735 | "node_modules/moment": { 1736 | "version": "2.29.4", 1737 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", 1738 | "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", 1739 | "dev": true, 1740 | "license": "MIT", 1741 | "engines": { 1742 | "node": "*" 1743 | } 1744 | }, 1745 | "node_modules/ms": { 1746 | "version": "2.1.2", 1747 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1748 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1749 | "license": "MIT" 1750 | }, 1751 | "node_modules/normalize-url": { 1752 | "version": "6.1.0", 1753 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", 1754 | "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", 1755 | "dev": true, 1756 | "license": "MIT", 1757 | "engines": { 1758 | "node": ">=10" 1759 | }, 1760 | "funding": { 1761 | "url": "https://github.com/sponsors/sindresorhus" 1762 | } 1763 | }, 1764 | "node_modules/npm-run-path": { 1765 | "version": "4.0.1", 1766 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", 1767 | "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", 1768 | "license": "MIT", 1769 | "dependencies": { 1770 | "path-key": "^3.0.0" 1771 | }, 1772 | "engines": { 1773 | "node": ">=8" 1774 | } 1775 | }, 1776 | "node_modules/object-keys": { 1777 | "version": "1.1.1", 1778 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1779 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1780 | "dev": true, 1781 | "license": "MIT", 1782 | "optional": true, 1783 | "engines": { 1784 | "node": ">= 0.4" 1785 | } 1786 | }, 1787 | "node_modules/obsidian": { 1788 | "version": "1.2.8", 1789 | "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.2.8.tgz", 1790 | "integrity": "sha512-HrC+feA8o0tXspj4lEAqxb1btwLwHD2oHXSwbbN+CdRHURqbCkuIDLld+nkuyJ1w1c9uvVDRVk8BoeOnWheOrQ==", 1791 | "dev": true, 1792 | "license": "MIT", 1793 | "dependencies": { 1794 | "@types/codemirror": "0.0.108", 1795 | "moment": "2.29.4" 1796 | }, 1797 | "peerDependencies": { 1798 | "@codemirror/state": "^6.0.0", 1799 | "@codemirror/view": "^6.0.0" 1800 | } 1801 | }, 1802 | "node_modules/once": { 1803 | "version": "1.4.0", 1804 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1805 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1806 | "dev": true, 1807 | "license": "ISC", 1808 | "dependencies": { 1809 | "wrappy": "1" 1810 | } 1811 | }, 1812 | "node_modules/onetime": { 1813 | "version": "5.1.2", 1814 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 1815 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 1816 | "license": "MIT", 1817 | "dependencies": { 1818 | "mimic-fn": "^2.1.0" 1819 | }, 1820 | "engines": { 1821 | "node": ">=6" 1822 | }, 1823 | "funding": { 1824 | "url": "https://github.com/sponsors/sindresorhus" 1825 | } 1826 | }, 1827 | "node_modules/p-cancelable": { 1828 | "version": "2.1.1", 1829 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", 1830 | "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", 1831 | "dev": true, 1832 | "license": "MIT", 1833 | "engines": { 1834 | "node": ">=8" 1835 | } 1836 | }, 1837 | "node_modules/path-is-absolute": { 1838 | "version": "1.0.1", 1839 | "resolved": "https://npm.shopee.io/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1840 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1841 | "dev": true, 1842 | "license": "MIT", 1843 | "engines": { 1844 | "node": ">=0.10.0" 1845 | } 1846 | }, 1847 | "node_modules/path-key": { 1848 | "version": "3.1.1", 1849 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1850 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1851 | "license": "MIT", 1852 | "engines": { 1853 | "node": ">=8" 1854 | } 1855 | }, 1856 | "node_modules/path-parse": { 1857 | "version": "1.0.7", 1858 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1859 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1860 | "dev": true, 1861 | "license": "MIT" 1862 | }, 1863 | "node_modules/path-type": { 1864 | "version": "4.0.0", 1865 | "resolved": "https://npm.shopee.io/path-type/-/path-type-4.0.0.tgz", 1866 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 1867 | "dev": true, 1868 | "license": "MIT", 1869 | "engines": { 1870 | "node": ">=8" 1871 | } 1872 | }, 1873 | "node_modules/peek-readable": { 1874 | "version": "5.0.0", 1875 | "resolved": "https://npm.shopee.io/peek-readable/-/peek-readable-5.0.0.tgz", 1876 | "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", 1877 | "license": "MIT", 1878 | "engines": { 1879 | "node": ">=14.16" 1880 | }, 1881 | "funding": { 1882 | "type": "github", 1883 | "url": "https://github.com/sponsors/Borewit" 1884 | } 1885 | }, 1886 | "node_modules/pend": { 1887 | "version": "1.2.0", 1888 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 1889 | "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", 1890 | "dev": true, 1891 | "license": "MIT" 1892 | }, 1893 | "node_modules/picomatch": { 1894 | "version": "2.3.1", 1895 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1896 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1897 | "dev": true, 1898 | "license": "MIT", 1899 | "engines": { 1900 | "node": ">=8.6" 1901 | }, 1902 | "funding": { 1903 | "url": "https://github.com/sponsors/jonschlinkert" 1904 | } 1905 | }, 1906 | "node_modules/process-nextick-args": { 1907 | "version": "2.0.1", 1908 | "resolved": "https://npm.shopee.io/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1909 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 1910 | "license": "MIT" 1911 | }, 1912 | "node_modules/progress": { 1913 | "version": "2.0.3", 1914 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1915 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1916 | "dev": true, 1917 | "license": "MIT", 1918 | "engines": { 1919 | "node": ">=0.4.0" 1920 | } 1921 | }, 1922 | "node_modules/pseudomap": { 1923 | "version": "1.0.2", 1924 | "resolved": "https://npm.shopee.io/pseudomap/-/pseudomap-1.0.2.tgz", 1925 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", 1926 | "license": "ISC" 1927 | }, 1928 | "node_modules/pump": { 1929 | "version": "3.0.0", 1930 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1931 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1932 | "dev": true, 1933 | "license": "MIT", 1934 | "dependencies": { 1935 | "end-of-stream": "^1.1.0", 1936 | "once": "^1.3.1" 1937 | } 1938 | }, 1939 | "node_modules/queue-microtask": { 1940 | "version": "1.2.3", 1941 | "resolved": "https://npm.shopee.io/queue-microtask/-/queue-microtask-1.2.3.tgz", 1942 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1943 | "dev": true, 1944 | "funding": [ 1945 | { 1946 | "type": "github", 1947 | "url": "https://github.com/sponsors/feross" 1948 | }, 1949 | { 1950 | "type": "patreon", 1951 | "url": "https://www.patreon.com/feross" 1952 | }, 1953 | { 1954 | "type": "consulting", 1955 | "url": "https://feross.org/support" 1956 | } 1957 | ], 1958 | "license": "MIT" 1959 | }, 1960 | "node_modules/quick-lru": { 1961 | "version": "5.1.1", 1962 | "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", 1963 | "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", 1964 | "dev": true, 1965 | "license": "MIT", 1966 | "engines": { 1967 | "node": ">=10" 1968 | }, 1969 | "funding": { 1970 | "url": "https://github.com/sponsors/sindresorhus" 1971 | } 1972 | }, 1973 | "node_modules/readable-stream": { 1974 | "version": "3.6.2", 1975 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1976 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1977 | "license": "MIT", 1978 | "dependencies": { 1979 | "inherits": "^2.0.3", 1980 | "string_decoder": "^1.1.1", 1981 | "util-deprecate": "^1.0.1" 1982 | }, 1983 | "engines": { 1984 | "node": ">= 6" 1985 | } 1986 | }, 1987 | "node_modules/readable-web-to-node-stream": { 1988 | "version": "3.0.2", 1989 | "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", 1990 | "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", 1991 | "license": "MIT", 1992 | "dependencies": { 1993 | "readable-stream": "^3.6.0" 1994 | }, 1995 | "engines": { 1996 | "node": ">=8" 1997 | }, 1998 | "funding": { 1999 | "type": "github", 2000 | "url": "https://github.com/sponsors/Borewit" 2001 | } 2002 | }, 2003 | "node_modules/resolve": { 2004 | "version": "1.22.2", 2005 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", 2006 | "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", 2007 | "dev": true, 2008 | "license": "MIT", 2009 | "dependencies": { 2010 | "is-core-module": "^2.11.0", 2011 | "path-parse": "^1.0.7", 2012 | "supports-preserve-symlinks-flag": "^1.0.0" 2013 | }, 2014 | "bin": { 2015 | "resolve": "bin/resolve" 2016 | }, 2017 | "funding": { 2018 | "url": "https://github.com/sponsors/ljharb" 2019 | } 2020 | }, 2021 | "node_modules/resolve-alpn": { 2022 | "version": "1.2.1", 2023 | "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", 2024 | "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", 2025 | "dev": true, 2026 | "license": "MIT" 2027 | }, 2028 | "node_modules/responselike": { 2029 | "version": "2.0.1", 2030 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", 2031 | "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", 2032 | "dev": true, 2033 | "license": "MIT", 2034 | "dependencies": { 2035 | "lowercase-keys": "^2.0.0" 2036 | }, 2037 | "funding": { 2038 | "url": "https://github.com/sponsors/sindresorhus" 2039 | } 2040 | }, 2041 | "node_modules/reusify": { 2042 | "version": "1.0.4", 2043 | "resolved": "https://npm.shopee.io/reusify/-/reusify-1.0.4.tgz", 2044 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 2045 | "dev": true, 2046 | "license": "MIT", 2047 | "engines": { 2048 | "iojs": ">=1.0.0", 2049 | "node": ">=0.10.0" 2050 | } 2051 | }, 2052 | "node_modules/roarr": { 2053 | "version": "2.15.4", 2054 | "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", 2055 | "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", 2056 | "dev": true, 2057 | "license": "BSD-3-Clause", 2058 | "optional": true, 2059 | "dependencies": { 2060 | "boolean": "^3.0.1", 2061 | "detect-node": "^2.0.4", 2062 | "globalthis": "^1.0.1", 2063 | "json-stringify-safe": "^5.0.1", 2064 | "semver-compare": "^1.0.0", 2065 | "sprintf-js": "^1.1.2" 2066 | }, 2067 | "engines": { 2068 | "node": ">=8.0" 2069 | } 2070 | }, 2071 | "node_modules/rollup": { 2072 | "version": "3.29.1", 2073 | "resolved": "https://npm.shopee.io/rollup/-/rollup-3.29.1.tgz", 2074 | "integrity": "sha512-c+ebvQz0VIH4KhhCpDsI+Bik0eT8ZFEVZEYw0cGMVqIP8zc+gnwl7iXCamTw7vzv2MeuZFZfdx5JJIq+ehzDlg==", 2075 | "dev": true, 2076 | "license": "MIT", 2077 | "bin": { 2078 | "rollup": "dist/bin/rollup" 2079 | }, 2080 | "engines": { 2081 | "node": ">=14.18.0", 2082 | "npm": ">=8.0.0" 2083 | }, 2084 | "optionalDependencies": { 2085 | "fsevents": "~2.3.2" 2086 | } 2087 | }, 2088 | "node_modules/rollup-plugin-commonjs": { 2089 | "version": "10.1.0", 2090 | "resolved": "https://npm.shopee.io/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", 2091 | "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", 2092 | "dev": true, 2093 | "license": "MIT", 2094 | "dependencies": { 2095 | "estree-walker": "^0.6.1", 2096 | "is-reference": "^1.1.2", 2097 | "magic-string": "^0.25.2", 2098 | "resolve": "^1.11.0", 2099 | "rollup-pluginutils": "^2.8.1" 2100 | }, 2101 | "peerDependencies": { 2102 | "rollup": ">=1.12.0" 2103 | } 2104 | }, 2105 | "node_modules/rollup-plugin-commonjs/node_modules/estree-walker": { 2106 | "version": "0.6.1", 2107 | "resolved": "https://npm.shopee.io/estree-walker/-/estree-walker-0.6.1.tgz", 2108 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", 2109 | "dev": true, 2110 | "license": "MIT" 2111 | }, 2112 | "node_modules/rollup-plugin-commonjs/node_modules/magic-string": { 2113 | "version": "0.25.9", 2114 | "resolved": "https://npm.shopee.io/magic-string/-/magic-string-0.25.9.tgz", 2115 | "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", 2116 | "dev": true, 2117 | "license": "MIT", 2118 | "dependencies": { 2119 | "sourcemap-codec": "^1.4.8" 2120 | } 2121 | }, 2122 | "node_modules/rollup-plugin-copy": { 2123 | "version": "3.4.0", 2124 | "resolved": "https://npm.shopee.io/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz", 2125 | "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==", 2126 | "dev": true, 2127 | "license": "MIT", 2128 | "dependencies": { 2129 | "@types/fs-extra": "^8.0.1", 2130 | "colorette": "^1.1.0", 2131 | "fs-extra": "^8.1.0", 2132 | "globby": "10.0.1", 2133 | "is-plain-object": "^3.0.0" 2134 | }, 2135 | "engines": { 2136 | "node": ">=8.3" 2137 | } 2138 | }, 2139 | "node_modules/rollup-plugin-zip": { 2140 | "version": "1.0.3", 2141 | "resolved": "https://npm.shopee.io/rollup-plugin-zip/-/rollup-plugin-zip-1.0.3.tgz", 2142 | "integrity": "sha512-HTF9I4VjJnDVXd37P/POZPi8p5Luq4mP7A3Lbaxk3wPxRg8DXbxLHDlWxP9X3I1wYYgbT+xHuw8WEwb8RKwpQw==", 2143 | "dev": true, 2144 | "license": "MIT", 2145 | "dependencies": { 2146 | "yazl": "^2.5.1" 2147 | }, 2148 | "peerDependencies": { 2149 | "rollup": ">=2.0.2" 2150 | } 2151 | }, 2152 | "node_modules/rollup-pluginutils": { 2153 | "version": "2.8.2", 2154 | "resolved": "https://npm.shopee.io/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", 2155 | "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", 2156 | "dev": true, 2157 | "license": "MIT", 2158 | "dependencies": { 2159 | "estree-walker": "^0.6.1" 2160 | } 2161 | }, 2162 | "node_modules/rollup-pluginutils/node_modules/estree-walker": { 2163 | "version": "0.6.1", 2164 | "resolved": "https://npm.shopee.io/estree-walker/-/estree-walker-0.6.1.tgz", 2165 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", 2166 | "dev": true, 2167 | "license": "MIT" 2168 | }, 2169 | "node_modules/run-parallel": { 2170 | "version": "1.2.0", 2171 | "resolved": "https://npm.shopee.io/run-parallel/-/run-parallel-1.2.0.tgz", 2172 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 2173 | "dev": true, 2174 | "funding": [ 2175 | { 2176 | "type": "github", 2177 | "url": "https://github.com/sponsors/feross" 2178 | }, 2179 | { 2180 | "type": "patreon", 2181 | "url": "https://www.patreon.com/feross" 2182 | }, 2183 | { 2184 | "type": "consulting", 2185 | "url": "https://feross.org/support" 2186 | } 2187 | ], 2188 | "license": "MIT", 2189 | "dependencies": { 2190 | "queue-microtask": "^1.2.2" 2191 | } 2192 | }, 2193 | "node_modules/safe-buffer": { 2194 | "version": "5.2.1", 2195 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2196 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 2197 | "funding": [ 2198 | { 2199 | "type": "github", 2200 | "url": "https://github.com/sponsors/feross" 2201 | }, 2202 | { 2203 | "type": "patreon", 2204 | "url": "https://www.patreon.com/feross" 2205 | }, 2206 | { 2207 | "type": "consulting", 2208 | "url": "https://feross.org/support" 2209 | } 2210 | ], 2211 | "license": "MIT" 2212 | }, 2213 | "node_modules/sax": { 2214 | "version": "1.2.4", 2215 | "resolved": "https://npm.shopee.io/sax/-/sax-1.2.4.tgz", 2216 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", 2217 | "license": "ISC" 2218 | }, 2219 | "node_modules/semver": { 2220 | "version": "6.3.0", 2221 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 2222 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 2223 | "dev": true, 2224 | "license": "ISC", 2225 | "bin": { 2226 | "semver": "bin/semver.js" 2227 | } 2228 | }, 2229 | "node_modules/semver-compare": { 2230 | "version": "1.0.0", 2231 | "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", 2232 | "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", 2233 | "dev": true, 2234 | "license": "MIT", 2235 | "optional": true 2236 | }, 2237 | "node_modules/serialize-error": { 2238 | "version": "7.0.1", 2239 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", 2240 | "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", 2241 | "dev": true, 2242 | "license": "MIT", 2243 | "optional": true, 2244 | "dependencies": { 2245 | "type-fest": "^0.13.1" 2246 | }, 2247 | "engines": { 2248 | "node": ">=10" 2249 | }, 2250 | "funding": { 2251 | "url": "https://github.com/sponsors/sindresorhus" 2252 | } 2253 | }, 2254 | "node_modules/shebang-command": { 2255 | "version": "2.0.0", 2256 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2257 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2258 | "license": "MIT", 2259 | "dependencies": { 2260 | "shebang-regex": "^3.0.0" 2261 | }, 2262 | "engines": { 2263 | "node": ">=8" 2264 | } 2265 | }, 2266 | "node_modules/shebang-regex": { 2267 | "version": "3.0.0", 2268 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2269 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2270 | "license": "MIT", 2271 | "engines": { 2272 | "node": ">=8" 2273 | } 2274 | }, 2275 | "node_modules/shell-env": { 2276 | "version": "4.0.1", 2277 | "resolved": "https://registry.npmjs.org/shell-env/-/shell-env-4.0.1.tgz", 2278 | "integrity": "sha512-w3oeZ9qg/P6Lu6qqwavvMnB/bwfsz67gPB3WXmLd/n6zuh7TWQZtGa3iMEdmua0kj8rivkwl+vUjgLWlqZOMPw==", 2279 | "license": "MIT", 2280 | "dependencies": { 2281 | "default-shell": "^2.0.0", 2282 | "execa": "^5.1.1", 2283 | "strip-ansi": "^7.0.1" 2284 | }, 2285 | "engines": { 2286 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 2287 | }, 2288 | "funding": { 2289 | "url": "https://github.com/sponsors/sindresorhus" 2290 | } 2291 | }, 2292 | "node_modules/shell-path": { 2293 | "version": "3.0.0", 2294 | "resolved": "https://registry.npmjs.org/shell-path/-/shell-path-3.0.0.tgz", 2295 | "integrity": "sha512-HNIZ+W/3P0JuVTV03xjGqYKt3e3h0/Z4AH8TQWeth1LBtCusSjICgkdNdb3VZr6mI7ijE2AiFFpgkVMNKsALeQ==", 2296 | "license": "MIT", 2297 | "dependencies": { 2298 | "shell-env": "^4.0.0" 2299 | }, 2300 | "engines": { 2301 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 2302 | }, 2303 | "funding": { 2304 | "url": "https://github.com/sponsors/sindresorhus" 2305 | } 2306 | }, 2307 | "node_modules/signal-exit": { 2308 | "version": "3.0.7", 2309 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 2310 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", 2311 | "license": "ISC" 2312 | }, 2313 | "node_modules/slash": { 2314 | "version": "3.0.0", 2315 | "resolved": "https://npm.shopee.io/slash/-/slash-3.0.0.tgz", 2316 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2317 | "dev": true, 2318 | "license": "MIT", 2319 | "engines": { 2320 | "node": ">=8" 2321 | } 2322 | }, 2323 | "node_modules/sourcemap-codec": { 2324 | "version": "1.4.8", 2325 | "resolved": "https://npm.shopee.io/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 2326 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 2327 | "dev": true, 2328 | "license": "MIT" 2329 | }, 2330 | "node_modules/sprintf-js": { 2331 | "version": "1.1.2", 2332 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", 2333 | "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", 2334 | "dev": true, 2335 | "license": "BSD-3-Clause", 2336 | "optional": true 2337 | }, 2338 | "node_modules/string_decoder": { 2339 | "version": "1.3.0", 2340 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 2341 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 2342 | "license": "MIT", 2343 | "dependencies": { 2344 | "safe-buffer": "~5.2.0" 2345 | } 2346 | }, 2347 | "node_modules/strip-ansi": { 2348 | "version": "7.0.1", 2349 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", 2350 | "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", 2351 | "license": "MIT", 2352 | "dependencies": { 2353 | "ansi-regex": "^6.0.1" 2354 | }, 2355 | "engines": { 2356 | "node": ">=12" 2357 | }, 2358 | "funding": { 2359 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 2360 | } 2361 | }, 2362 | "node_modules/strip-final-newline": { 2363 | "version": "2.0.0", 2364 | "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", 2365 | "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", 2366 | "license": "MIT", 2367 | "engines": { 2368 | "node": ">=6" 2369 | } 2370 | }, 2371 | "node_modules/strtok3": { 2372 | "version": "7.0.0", 2373 | "resolved": "https://npm.shopee.io/strtok3/-/strtok3-7.0.0.tgz", 2374 | "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", 2375 | "license": "MIT", 2376 | "dependencies": { 2377 | "@tokenizer/token": "^0.3.0", 2378 | "peek-readable": "^5.0.0" 2379 | }, 2380 | "engines": { 2381 | "node": ">=14.16" 2382 | }, 2383 | "funding": { 2384 | "type": "github", 2385 | "url": "https://github.com/sponsors/Borewit" 2386 | } 2387 | }, 2388 | "node_modules/style-mod": { 2389 | "version": "4.1.0", 2390 | "resolved": "https://npm.shopee.io/style-mod/-/style-mod-4.1.0.tgz", 2391 | "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==", 2392 | "dev": true, 2393 | "license": "MIT", 2394 | "peer": true 2395 | }, 2396 | "node_modules/sumchecker": { 2397 | "version": "3.0.1", 2398 | "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", 2399 | "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", 2400 | "dev": true, 2401 | "license": "Apache-2.0", 2402 | "dependencies": { 2403 | "debug": "^4.1.0" 2404 | }, 2405 | "engines": { 2406 | "node": ">= 8.0" 2407 | } 2408 | }, 2409 | "node_modules/supports-preserve-symlinks-flag": { 2410 | "version": "1.0.0", 2411 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 2412 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 2413 | "dev": true, 2414 | "license": "MIT", 2415 | "engines": { 2416 | "node": ">= 0.4" 2417 | }, 2418 | "funding": { 2419 | "url": "https://github.com/sponsors/ljharb" 2420 | } 2421 | }, 2422 | "node_modules/to-regex-range": { 2423 | "version": "5.0.1", 2424 | "resolved": "https://npm.shopee.io/to-regex-range/-/to-regex-range-5.0.1.tgz", 2425 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2426 | "dev": true, 2427 | "license": "MIT", 2428 | "dependencies": { 2429 | "is-number": "^7.0.0" 2430 | }, 2431 | "engines": { 2432 | "node": ">=8.0" 2433 | } 2434 | }, 2435 | "node_modules/token-types": { 2436 | "version": "5.0.1", 2437 | "resolved": "https://npm.shopee.io/token-types/-/token-types-5.0.1.tgz", 2438 | "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", 2439 | "license": "MIT", 2440 | "dependencies": { 2441 | "@tokenizer/token": "^0.3.0", 2442 | "ieee754": "^1.2.1" 2443 | }, 2444 | "engines": { 2445 | "node": ">=14.16" 2446 | }, 2447 | "funding": { 2448 | "type": "github", 2449 | "url": "https://github.com/sponsors/Borewit" 2450 | } 2451 | }, 2452 | "node_modules/tslib": { 2453 | "version": "2.5.0", 2454 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", 2455 | "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", 2456 | "dev": true, 2457 | "license": "0BSD" 2458 | }, 2459 | "node_modules/type-fest": { 2460 | "version": "0.13.1", 2461 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", 2462 | "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", 2463 | "dev": true, 2464 | "license": "(MIT OR CC0-1.0)", 2465 | "optional": true, 2466 | "engines": { 2467 | "node": ">=10" 2468 | }, 2469 | "funding": { 2470 | "url": "https://github.com/sponsors/sindresorhus" 2471 | } 2472 | }, 2473 | "node_modules/typescript": { 2474 | "version": "5.0.4", 2475 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", 2476 | "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", 2477 | "dev": true, 2478 | "license": "Apache-2.0", 2479 | "bin": { 2480 | "tsc": "bin/tsc", 2481 | "tsserver": "bin/tsserver" 2482 | }, 2483 | "engines": { 2484 | "node": ">=12.20" 2485 | } 2486 | }, 2487 | "node_modules/universalify": { 2488 | "version": "0.1.2", 2489 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 2490 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 2491 | "dev": true, 2492 | "license": "MIT", 2493 | "engines": { 2494 | "node": ">= 4.0.0" 2495 | } 2496 | }, 2497 | "node_modules/util-deprecate": { 2498 | "version": "1.0.2", 2499 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2500 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 2501 | "license": "MIT" 2502 | }, 2503 | "node_modules/w3c-keyname": { 2504 | "version": "2.2.8", 2505 | "resolved": "https://npm.shopee.io/w3c-keyname/-/w3c-keyname-2.2.8.tgz", 2506 | "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", 2507 | "dev": true, 2508 | "license": "MIT", 2509 | "peer": true 2510 | }, 2511 | "node_modules/which": { 2512 | "version": "2.0.2", 2513 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2514 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2515 | "license": "ISC", 2516 | "dependencies": { 2517 | "isexe": "^2.0.0" 2518 | }, 2519 | "bin": { 2520 | "node-which": "bin/node-which" 2521 | }, 2522 | "engines": { 2523 | "node": ">= 8" 2524 | } 2525 | }, 2526 | "node_modules/wrappy": { 2527 | "version": "1.0.2", 2528 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2529 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2530 | "dev": true, 2531 | "license": "ISC" 2532 | }, 2533 | "node_modules/xml2js": { 2534 | "version": "0.6.2", 2535 | "resolved": "https://npm.shopee.io/xml2js/-/xml2js-0.6.2.tgz", 2536 | "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", 2537 | "license": "MIT", 2538 | "dependencies": { 2539 | "sax": ">=0.6.0", 2540 | "xmlbuilder": "~11.0.0" 2541 | }, 2542 | "engines": { 2543 | "node": ">=4.0.0" 2544 | } 2545 | }, 2546 | "node_modules/xmlbuilder": { 2547 | "version": "11.0.1", 2548 | "resolved": "https://npm.shopee.io/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 2549 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", 2550 | "license": "MIT", 2551 | "engines": { 2552 | "node": ">=4.0" 2553 | } 2554 | }, 2555 | "node_modules/yallist": { 2556 | "version": "4.0.0", 2557 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2558 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2559 | "dev": true, 2560 | "license": "ISC", 2561 | "optional": true 2562 | }, 2563 | "node_modules/yauzl": { 2564 | "version": "2.10.0", 2565 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 2566 | "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", 2567 | "dev": true, 2568 | "license": "MIT", 2569 | "dependencies": { 2570 | "buffer-crc32": "~0.2.3", 2571 | "fd-slicer": "~1.1.0" 2572 | } 2573 | }, 2574 | "node_modules/yazl": { 2575 | "version": "2.5.1", 2576 | "resolved": "https://npm.shopee.io/yazl/-/yazl-2.5.1.tgz", 2577 | "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", 2578 | "dev": true, 2579 | "license": "MIT", 2580 | "dependencies": { 2581 | "buffer-crc32": "~0.2.3" 2582 | } 2583 | } 2584 | } 2585 | } 2586 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easy-image-uploader", 3 | "version": "1.0.1", 4 | "type": "module", 5 | "description": "自动将图片直接上传到博客网站获取对应图片链接,或者基于 PicGo 自动上传到图床。", 6 | "main": "main.js", 7 | "scripts": { 8 | "dev": "rollup --config rollup.config.js -w", 9 | "build": "rollup --config rollup.config.js && zip -rj easy-image-uploader.zip easy-image-uploader" 10 | }, 11 | "keywords": [ 12 | "obsidian.md", 13 | "picgo", 14 | "image", 15 | "blog" 16 | ], 17 | "author": "三此君", 18 | "license": "MIT", 19 | "devDependencies": { 20 | "@rollup/plugin-commonjs": "^25.0.4", 21 | "@rollup/plugin-json": "^6.0.0", 22 | "@rollup/plugin-node-resolve": "^15.0.2", 23 | "@rollup/plugin-typescript": "^11.1.0", 24 | "@types/electron": "^1.6.10", 25 | "@types/gm": "^1.25.1", 26 | "@types/node": "^14.14.2", 27 | "@types/xml2js": "^0.4.11", 28 | "obsidian": "^1.2.8", 29 | "rollup": "^3.29.0", 30 | "rollup-plugin-commonjs": "^10.1.0", 31 | "rollup-plugin-copy": "^3.4.0", 32 | "rollup-plugin-zip": "^1.0.3", 33 | "tslib": "^2.5.0", 34 | "typescript": "^5.0.4" 35 | }, 36 | "dependencies": { 37 | "cos-js-sdk-v5": "^1.4.20", 38 | "file-base64": "^1.0.0", 39 | "fix-path": "^4.0.0", 40 | "image-type": "^5.2.0", 41 | "xml2js": "^0.6.2" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from "@rollup/plugin-typescript"; 2 | import { nodeResolve } from "@rollup/plugin-node-resolve"; 3 | import commonjs from "@rollup/plugin-commonjs"; 4 | import json from "@rollup/plugin-json"; 5 | import copy from "rollup-plugin-copy"; 6 | 7 | export default { 8 | input: "src/main.ts", 9 | output: { 10 | dir: "./easy-image-uploader", 11 | sourcemap: "inline", 12 | format: "cjs", 13 | exports: "default", 14 | }, 15 | external: ["obsidian", "electron"], 16 | plugins: [ 17 | typescript(), 18 | nodeResolve({ browser: false }), 19 | commonjs(), 20 | json(), 21 | copy({ 22 | targets: [ 23 | { src: "manifest.json", dest: "easy-image-uploader" } 24 | ], 25 | hook: "buildStart", 26 | }), 27 | ], 28 | }; 29 | -------------------------------------------------------------------------------- /src/deleter.ts: -------------------------------------------------------------------------------- 1 | import { IStringKeyMap } from "./utils"; 2 | import { App, requestUrl } from "obsidian"; 3 | import imageAutoUploadPlugin from "./main"; 4 | 5 | export class PicGoDeleter { 6 | plugin: imageAutoUploadPlugin; 7 | 8 | constructor(plugin: imageAutoUploadPlugin) { 9 | this.plugin = plugin; 10 | } 11 | 12 | async deleteImage(configMap: IStringKeyMap[]) { 13 | const response = await requestUrl({ 14 | url: this.plugin.settings.deleteServer, 15 | method: "POST", 16 | headers: { "Content-Type": "application/json" }, 17 | body: JSON.stringify({ 18 | list: configMap, 19 | }), 20 | }); 21 | const data = response.json; 22 | return data; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/helper.ts: -------------------------------------------------------------------------------- 1 | import { MarkdownView, App } from "obsidian"; 2 | import { parse } from "path"; 3 | 4 | interface Image { 5 | path: string; 6 | name: string; 7 | source: string; 8 | } 9 | // ![](./dsa/aa.png) local image should has ext 10 | // ![](https://dasdasda) internet image should not has ext 11 | // MARK [[./dsa/aa.png]] 12 | const REGEX_FILE = /\!\[(.*?)\]\((\S+\.\w+)\)|\!\[(.*?)\]\((https?:\/\/.*?)\)/g; 13 | const REGEX_WIKI_FILE = /\!\[\[(.*?)(\s*?\|.*?)?\]\]/g; 14 | export default class Helper { 15 | app: App; 16 | 17 | constructor(app: App) { 18 | this.app = app; 19 | } 20 | getFrontmatterValue(key: string, defaultValue: any = undefined) { 21 | const file = this.app.workspace.getActiveFile(); 22 | if (!file) { 23 | return undefined; 24 | } 25 | const path = file.path; 26 | const cache = this.app.metadataCache.getCache(path); 27 | 28 | let value = defaultValue; 29 | if (cache?.frontmatter && cache.frontmatter.hasOwnProperty(key)) { 30 | value = cache.frontmatter[key]; 31 | } 32 | return value; 33 | } 34 | 35 | getEditor() { 36 | const mdView = this.app.workspace.getActiveViewOfType(MarkdownView); 37 | if (mdView) { 38 | return mdView.editor; 39 | } else { 40 | return null; 41 | } 42 | } 43 | getValue() { 44 | const editor = this.getEditor(); 45 | return editor.getValue(); 46 | } 47 | 48 | setValue(value: string) { 49 | const editor = this.getEditor(); 50 | const { left, top } = editor.getScrollInfo(); 51 | const position = editor.getCursor(); 52 | 53 | editor.setValue(value); 54 | editor.scrollTo(left, top); 55 | editor.setCursor(position); 56 | } 57 | 58 | // get all file urls, include local and internet 59 | getAllFiles(): Image[] { 60 | const editor = this.getEditor(); 61 | let value = editor.getValue(); 62 | return this.getImageLink(value); 63 | } 64 | getImageLink(value: string): Image[] { 65 | const matches = value.matchAll(REGEX_FILE); 66 | const WikiMatches = value.matchAll(REGEX_WIKI_FILE); 67 | 68 | let fileArray: Image[] = []; 69 | 70 | for (const match of matches) { 71 | const source = match[0]; 72 | 73 | let name = match[1]; 74 | let path = match[2]; 75 | if (name === undefined) { 76 | name = match[3]; 77 | } 78 | if (path === undefined) { 79 | path = match[4]; 80 | } 81 | 82 | fileArray.push({ 83 | path: path, 84 | name: name, 85 | source: source, 86 | }); 87 | } 88 | 89 | for (const match of WikiMatches) { 90 | let name = parse(match[1]).name; 91 | const path = match[1]; 92 | const source = match[0]; 93 | if (match[2]) { 94 | name = `${name}${match[2]}`; 95 | } 96 | fileArray.push({ 97 | path: path, 98 | name: name, 99 | source: source, 100 | }); 101 | } 102 | console.log(fileArray); 103 | 104 | return fileArray; 105 | } 106 | 107 | hasBlackDomain(src: string, blackDomains: string) { 108 | if (blackDomains.trim() === "") { 109 | return false; 110 | } 111 | const blackDomainList = blackDomains.split(",").filter(item => item !== ""); 112 | let url = new URL(src); 113 | const domain = url.hostname; 114 | 115 | return blackDomainList.some(blackDomain => domain.includes(blackDomain)); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/lang/README.md: -------------------------------------------------------------------------------- 1 | ## Localization 2 | 3 | The plugin has full localization support, and will attempt to load the current Obsidian locale. If one does not exist, it will fall back to English. 4 | 5 | ### Adding a new Locale 6 | 7 | New locales can be added by creating a pull request. Two things should be done in this pull request: 8 | 9 | 1. Create the locale in the `locales` folder by copying the `en.ts` file. This file should be given a name matching the string returned by `moment.locale()`. 10 | 2. Create the translation by editing the value of each property. 11 | 3. Add the import in `locales.ts`. 12 | 4. Add the language to the `localeMap` variable. 13 | 14 | -------------------------------------------------------------------------------- /src/lang/helpers.ts: -------------------------------------------------------------------------------- 1 | import { moment } from 'obsidian'; 2 | 3 | import ar from './locale/ar'; 4 | import cz from './locale/cz'; 5 | import da from './locale/da'; 6 | import de from './locale/de'; 7 | import en from './locale/en'; 8 | import enGB from './locale/en-gb'; 9 | import es from './locale/es'; 10 | import fr from './locale/fr'; 11 | import hi from './locale/hi'; 12 | import id from './locale/id'; 13 | import it from './locale/it'; 14 | import ja from './locale/ja'; 15 | import ko from './locale/ko'; 16 | import nl from './locale/nl'; 17 | import no from './locale/no'; 18 | import pl from './locale/pl'; 19 | import pt from './locale/pt'; 20 | import ptBR from './locale/pt-br'; 21 | import ro from './locale/ro'; 22 | import ru from './locale/ru'; 23 | import tr from './locale/tr'; 24 | import zhCN from './locale/zh-cn'; 25 | import zhTW from './locale/zh-tw'; 26 | 27 | const localeMap: { [k: string]: Partial } = { 28 | ar, 29 | cs: cz, 30 | da, 31 | de, 32 | en, 33 | 'en-gb': enGB, 34 | es, 35 | fr, 36 | hi, 37 | id, 38 | it, 39 | ja, 40 | ko, 41 | nl, 42 | nn: no, 43 | pl, 44 | pt, 45 | 'pt-br': ptBR, 46 | ro, 47 | ru, 48 | tr, 49 | 'zh-cn': zhCN, 50 | 'zh-tw': zhTW, 51 | }; 52 | 53 | const locale = localeMap[moment.locale()]; 54 | 55 | export function t(str: keyof typeof en): string { 56 | return (locale && locale[str]) || en[str]; 57 | } 58 | -------------------------------------------------------------------------------- /src/lang/locale/ar.ts: -------------------------------------------------------------------------------- 1 | // العربية 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/cz.ts: -------------------------------------------------------------------------------- 1 | // čeština 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/da.ts: -------------------------------------------------------------------------------- 1 | // Dansk 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/de.ts: -------------------------------------------------------------------------------- 1 | // Deutsch 2 | 3 | export default {}; -------------------------------------------------------------------------------- /src/lang/locale/en-gb.ts: -------------------------------------------------------------------------------- 1 | // British English 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/en.ts: -------------------------------------------------------------------------------- 1 | // English 2 | 3 | export default { 4 | // setting.ts 5 | "Plugin Settings": "Plugin Settings", 6 | "Auto pasted upload": "Auto pasted upload", 7 | "If you set this value true, when you paste image, it will be auto uploaded(you should set the picGo server rightly)": 8 | "If you set this value true, when you paste image, it will be auto uploaded", 9 | "Default uploader": "Default uploader", 10 | "PicGo server": "PicGo server", 11 | "Please input PicGo server": "Please input PicGo server", 12 | "PicGo delete server": 13 | "PicGo server delete route(you need to use PicList app)", 14 | "PicList desc": "Search PicList on Github to download and install", 15 | "Please input PicGo delete server": "Please input PicGo delete server", 16 | "Delete image using PicList": "Delete image using PicList", 17 | "PicGo-Core path": "PicGo-Core path", 18 | "Delete successfully": "Delete successfully", 19 | "Delete failed": "Delete failed", 20 | "Image size suffix": "Image size suffix", 21 | "Image size suffix Description": "like |300 for resize image in ob.", 22 | "Please input image size suffix": "Please input image size suffix", 23 | "Error, could not delete": "Error, could not delete", 24 | "Please input PicGo-Core path, default using environment variables": 25 | "Please input PicGo-Core path, default using environment variables", 26 | "Work on network": "Work on network", 27 | "Work on network Description": 28 | "Allow upload network image by 'Upload all' command.\n Or when you paste, md standard image link in your clipboard will be auto upload.", 29 | fixPath: "fixPath", 30 | fixPathWarning: 31 | "This option is used to fix PicGo-core upload failures on Linux and Mac. It modifies the PATH variable within Obsidian. If Obsidian encounters any bugs, turn off the option, try again! ", 32 | "Upload when clipboard has image and text together": 33 | "Upload when clipboard has image and text together", 34 | "When you copy, some application like Excel will image and text to clipboard, you can upload or not.": 35 | "When you copy, some application like Excel will image and text to clipboard, you can upload or not.", 36 | "Network Domain Black List": "Network Domain Black List", 37 | "Network Domain Black List Description": 38 | "Image in the domain list will not be upload,use comma separated", 39 | "Delete source file after you upload file": 40 | "Delete source file after you upload file", 41 | "Delete source file in ob assets after you upload file.": 42 | "Delete source file in ob assets after you upload file.", 43 | "Image desc": "Image desc", 44 | reserve: "default", 45 | "remove all": "none", 46 | "remove default": "remove image.png", 47 | "Blog URL":"Blog URL", 48 | "Blog ID": "Blog ID", 49 | "Blog User Name": "Blog User Name", 50 | "Blog Token": "Blog Token", 51 | "Please input blog url": "Please input blog url", 52 | "Please input blog ID": "Please input blog ID", 53 | "Please input blog user name": "Please input blog user name", 54 | "Please input blog token": "Please input blog token", 55 | "Repository": "Repository", 56 | "Please input your repository": "Please input your repository", 57 | "Branch": "Branch", 58 | "Please input your branch": "Please input your branch", 59 | "Token": "Token", 60 | "Please input your token": "Please input your token", 61 | "Path": "Path", 62 | "Please input your path": "Please input your path", 63 | "Custom URL": "Custom URL", 64 | "Please input custom URL": "Please input custom URL", 65 | "Rename": "Rename", 66 | "Rename Desc": "Whether to rename the image with a timestamp", 67 | "Secret ID": "Secret ID", 68 | "Please input your secret ID": "Please input your secret ID", 69 | "Secret Key": "Secret Key", 70 | "Please input your secret key": "Please input your secret key", 71 | "Region": "Region", 72 | "Please input your region": "Please input your region", 73 | "Bucket": "Bucket", 74 | "Please input your bucket name": "Please input your bucket name" 75 | }; 76 | -------------------------------------------------------------------------------- /src/lang/locale/es.ts: -------------------------------------------------------------------------------- 1 | // Español 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/fr.ts: -------------------------------------------------------------------------------- 1 | // français 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/hi.ts: -------------------------------------------------------------------------------- 1 | // हिन्दी 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/id.ts: -------------------------------------------------------------------------------- 1 | // Bahasa Indonesia 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/it.ts: -------------------------------------------------------------------------------- 1 | // Italiano 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/ja.ts: -------------------------------------------------------------------------------- 1 | // 日本語 2 | 3 | export default {}; -------------------------------------------------------------------------------- /src/lang/locale/ko.ts: -------------------------------------------------------------------------------- 1 | // 한국어 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/nl.ts: -------------------------------------------------------------------------------- 1 | // Nederlands 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/no.ts: -------------------------------------------------------------------------------- 1 | // Norsk 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/pl.ts: -------------------------------------------------------------------------------- 1 | // język polski 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/pt-br.ts: -------------------------------------------------------------------------------- 1 | // Português do Brasil 2 | // Brazilian Portuguese 3 | 4 | export default {}; -------------------------------------------------------------------------------- /src/lang/locale/pt.ts: -------------------------------------------------------------------------------- 1 | // Português 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/ro.ts: -------------------------------------------------------------------------------- 1 | // Română 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/ru.ts: -------------------------------------------------------------------------------- 1 | // русский 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/tr.ts: -------------------------------------------------------------------------------- 1 | // Türkçe 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/lang/locale/zh-cn.ts: -------------------------------------------------------------------------------- 1 | // 简体中文 2 | 3 | export default { 4 | // setting.ts 5 | "Plugin Settings": "插件设置", 6 | "Auto pasted upload": "剪切板自动上传", 7 | "If you set this value true, when you paste image, it will be auto uploaded(you should set the picGo server rightly)": 8 | "启用该选项后,粘贴图片时会自动上传", 9 | "Default uploader": "默认上传器", 10 | "PicGo server": "PicGo server", 11 | "Please input PicGo server": "请输入 PicGo server", 12 | "PicGo delete server": "PicGo server 删除接口(请使用PicList来启用此功能)", 13 | "PicList desc": "PicList是PicGo二次开发版,请Github搜索PicList下载", 14 | "Please input PicGo delete server": "请输入 PicGo server 删除接口", 15 | "Delete image using PicList": "使用 PicList 删除图片", 16 | "PicGo-Core path": "PicGo-Core 路径", 17 | "Delete successfully": "删除成功", 18 | "Delete failed": "删除失败", 19 | "Error, could not delete": "错误,无法删除", 20 | "Image size suffix": "图片大小后缀", 21 | "Image size suffix Description": "比如:|300 用于调整图片大小", 22 | "Please input image size suffix": "请输入图片大小后缀", 23 | "Please input PicGo-Core path, default using environment variables": 24 | "请输入 PicGo-Core path,默认使用环境变量", 25 | "Work on network": "应用网络图片", 26 | "Work on network Description": 27 | "当你上传所有图片时,也会上传网络图片。以及当你进行黏贴时,剪切板中的标准 md 图片会被上传", 28 | fixPath: "修正PATH变量", 29 | fixPathWarning: 30 | "此选项用于修复Linux和Mac上 PicGo-Core 上传失败的问题。它会修改 Obsidian 内的 PATH 变量,如果 Obsidian 遇到任何BUG,先关闭这个选项试试!", 31 | "Upload when clipboard has image and text together": 32 | "当剪切板同时拥有文本和图片剪切板数据时是否上传图片", 33 | "When you copy, some application like Excel will image and text to clipboard, you can upload or not.": 34 | "当你复制时,某些应用例如 Excel 会在剪切板同时文本和图像数据,确认是否上传。", 35 | "Network Domain Black List": "网络图片域名黑名单", 36 | "Network Domain Black List Description": 37 | "黑名单域名中的图片将不会被上传,用英文逗号分割", 38 | "Delete source file after you upload file": "上传文件后移除源文件", 39 | "Delete source file in ob assets after you upload file.": 40 | "上传文件后移除在ob附件文件夹中的文件", 41 | "Image desc": "图片描述", 42 | reserve: "默认", 43 | "remove all": "无", 44 | "remove default": "移除image.png", 45 | "Blog URL":"Blog URL", 46 | "Blog ID": "Blog UserId", 47 | "Blog User Name": "博客用户名", 48 | "Blog Token": "博客登录令牌", 49 | "Please input blog url": "请输入 blog url", 50 | "Please input blog ID": "请输入 blog user id", 51 | "Please input blog user name": "请输入用户名", 52 | "Please input blog token": "请输入登录令牌(部署密码)", 53 | "Repository": "仓库", 54 | "Please input your repository": "请输入仓库名,例如:sancijun/images", 55 | "Branch": "分支", 56 | "Please input your branch": "请输入分支名,默认为 master", 57 | "Token": "令牌", 58 | "Please input your token": "请输入个人令牌", 59 | "Path": "路径", 60 | "Please input your path": "请求输入图片存储路径", 61 | "Custom URL": "自定义域名", 62 | "Please input custom URL": "请输入自定义域名", 63 | "Rename": "重命名", 64 | "Rename Desc": "是否使用当前时间戳重命名文件", 65 | "Secret ID": "Secret ID", 66 | "Please input your secret ID": "请输入 Secret ID", 67 | "Secret Key": "Secret Key", 68 | "Please input your secret key": "请输入 Secret Key", 69 | "Region": "Region", 70 | "Please input your region": "请输入 Region", 71 | "Bucket": "Bucket", 72 | "Please input your bucket name": "请输入 Bucket Name" 73 | }; 74 | -------------------------------------------------------------------------------- /src/lang/locale/zh-tw.ts: -------------------------------------------------------------------------------- 1 | // 繁體中文 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MarkdownView, 3 | Plugin, 4 | FileSystemAdapter, 5 | Editor, 6 | Menu, 7 | MenuItem, 8 | TFile, 9 | normalizePath, 10 | Notice, 11 | addIcon, 12 | requestUrl, 13 | MarkdownFileInfo, 14 | } from "obsidian"; 15 | 16 | import { resolve, relative, join, parse, posix, basename, dirname } from "path"; 17 | import { existsSync, mkdirSync, writeFileSync, unlink } from "fs"; 18 | 19 | import fixPath from "fix-path"; 20 | import imageType from "image-type"; 21 | 22 | import { 23 | isAssetTypeAnImage, 24 | isAnImage, 25 | getUrlAsset, 26 | arrayToObject, 27 | } from "./utils"; 28 | import { PicGoUploader, PicGoCoreUploader, BlogUploader, GithubUploader, GiteeUploader, TencentCosUploader } from "./uploader"; 29 | import { PicGoDeleter } from "./deleter"; 30 | import Helper from "./helper"; 31 | import { t } from "./lang/helpers"; 32 | 33 | import { SettingTab, PluginSettings, DEFAULT_SETTINGS } from "./setting"; 34 | 35 | interface Image { 36 | path: string; 37 | name: string; 38 | source: string; 39 | } 40 | 41 | export default class imageAutoUploadPlugin extends Plugin { 42 | settings: PluginSettings; 43 | helper: Helper; 44 | editor: Editor; 45 | picGoUploader: PicGoUploader; 46 | picGoDeleter: PicGoDeleter; 47 | picGoCoreUploader: PicGoCoreUploader; 48 | blogUploader: BlogUploader; 49 | githubUploader: GithubUploader; 50 | giteeUploader: GiteeUploader; 51 | tencentCosUploader: TencentCosUploader; 52 | uploader: PicGoUploader | PicGoCoreUploader | BlogUploader | GithubUploader | GiteeUploader | TencentCosUploader; 53 | 54 | async loadSettings() { 55 | this.settings = Object.assign(DEFAULT_SETTINGS, await this.loadData()); 56 | } 57 | 58 | async saveSettings() { 59 | await this.saveData(this.settings); 60 | } 61 | 62 | onunload() {} 63 | 64 | async onload() { 65 | await this.loadSettings(); 66 | 67 | this.helper = new Helper(this.app); 68 | this.picGoUploader = new PicGoUploader(this.settings, this); 69 | this.picGoDeleter = new PicGoDeleter(this); 70 | this.picGoCoreUploader = new PicGoCoreUploader(this.settings, this); 71 | this.blogUploader = new BlogUploader(this.settings, this); 72 | this.githubUploader = new GithubUploader(this.settings, this); 73 | this.giteeUploader = new GiteeUploader(this.settings, this); 74 | this.tencentCosUploader = new TencentCosUploader(this.settings, this); 75 | 76 | if (this.settings.uploader === "PicGo") { 77 | this.uploader = this.picGoUploader; 78 | } else if (this.settings.uploader === "PicGo-Core") { 79 | this.uploader = this.picGoCoreUploader; 80 | if (this.settings.fixPath) { 81 | fixPath(); 82 | } 83 | } else if(this.settings.uploader === "Blog") { 84 | this.uploader = this.blogUploader; 85 | } else if(this.settings.uploader === "GitHub") { 86 | this.uploader = this.githubUploader; 87 | } else if(this.settings.uploader === "Gitee") { 88 | this.uploader = this.giteeUploader; 89 | } else if(this.settings.uploader === "Tencent") { 90 | this.uploader = this.tencentCosUploader; 91 | } else { 92 | new Notice("unknown uploader"); 93 | } 94 | 95 | addIcon( 96 | "upload", 97 | ` 98 | 99 | ` 100 | ); 101 | 102 | this.addSettingTab(new SettingTab(this.app, this)); 103 | 104 | this.addCommand({ 105 | id: "Upload all images", 106 | name: "Upload all images", 107 | checkCallback: (checking: boolean) => { 108 | let leaf = this.app.workspace.activeLeaf; 109 | if (leaf) { 110 | if (!checking) { 111 | this.uploadAllFile(); 112 | } 113 | return true; 114 | } 115 | return false; 116 | }, 117 | }); 118 | this.addCommand({ 119 | id: "Download all images", 120 | name: "Download all images", 121 | checkCallback: (checking: boolean) => { 122 | let leaf = this.app.workspace.activeLeaf; 123 | if (leaf) { 124 | if (!checking) { 125 | this.downloadAllImageFiles(); 126 | } 127 | return true; 128 | } 129 | return false; 130 | }, 131 | }); 132 | 133 | this.setupPasteHandler(); 134 | this.registerFileMenu(); 135 | 136 | this.registerSelection(); 137 | } 138 | 139 | registerSelection() { 140 | this.registerEvent( 141 | this.app.workspace.on( 142 | "editor-menu", 143 | (menu: Menu, editor: Editor, info: MarkdownView | MarkdownFileInfo) => { 144 | if (this.app.workspace.getLeavesOfType("markdown").length === 0) { 145 | return; 146 | } 147 | const selection = editor.getSelection(); 148 | if (selection) { 149 | const markdownRegex = /!\[.*\]\((.*)\)/g; 150 | const markdownMatch = markdownRegex.exec(selection); 151 | if (markdownMatch && markdownMatch.length > 1) { 152 | const markdownUrl = markdownMatch[1]; 153 | if ( 154 | this.settings.uploadedImages.find( 155 | (item: { imgUrl: string }) => item.imgUrl === markdownUrl 156 | ) 157 | ) { 158 | this.addMenu(menu, markdownUrl, editor); 159 | } 160 | } 161 | } 162 | } 163 | ) 164 | ); 165 | } 166 | 167 | addMenu = (menu: Menu, imgPath: string, editor: Editor) => { 168 | menu.addItem((item: MenuItem) => 169 | item 170 | .setIcon("trash-2") 171 | .setTitle(t("Delete image using PicList")) 172 | .onClick(async () => { 173 | try { 174 | const selectedItem = this.settings.uploadedImages.find( 175 | (item: { imgUrl: string }) => item.imgUrl === imgPath 176 | ); 177 | if (selectedItem) { 178 | const res = await this.picGoDeleter.deleteImage([selectedItem]); 179 | if (res.success) { 180 | new Notice(t("Delete successfully")); 181 | const selection = editor.getSelection(); 182 | if (selection) { 183 | editor.replaceSelection(""); 184 | } 185 | this.settings.uploadedImages = 186 | this.settings.uploadedImages.filter( 187 | (item: { imgUrl: string }) => item.imgUrl !== imgPath 188 | ); 189 | this.saveSettings(); 190 | } else { 191 | new Notice(t("Delete failed")); 192 | } 193 | } 194 | } catch { 195 | new Notice(t("Error, could not delete")); 196 | } 197 | }) 198 | ); 199 | }; 200 | 201 | async downloadAllImageFiles() { 202 | const folderPath = this.getFileAssetPath(); 203 | const fileArray = this.helper.getAllFiles(); 204 | if (!existsSync(folderPath)) { 205 | mkdirSync(folderPath); 206 | } 207 | 208 | let imageArray = []; 209 | const nameSet = new Set(); 210 | for (const file of fileArray) { 211 | if (!file.path.startsWith("http")) { 212 | continue; 213 | } 214 | 215 | const url = file.path; 216 | const asset = getUrlAsset(url); 217 | let name = decodeURI(parse(asset).name).replaceAll( 218 | /[\\\\/:*?\"<>|]/g, 219 | "-" 220 | ); 221 | 222 | // 如果文件名已存在,则用随机值替换,不对文件后缀进行判断 223 | if (existsSync(join(folderPath))) { 224 | name = (Math.random() + 1).toString(36).substr(2, 5); 225 | } 226 | if (nameSet.has(name)) { 227 | name = `${name}-${(Math.random() + 1).toString(36).substr(2, 5)}`; 228 | } 229 | nameSet.add(name); 230 | 231 | const response = await this.download(url, folderPath, name); 232 | if (response.ok) { 233 | const activeFolder = normalizePath( 234 | this.app.workspace.getActiveFile().parent.path 235 | ); 236 | const abstractActiveFolder = ( 237 | this.app.vault.adapter as FileSystemAdapter 238 | ).getFullPath(activeFolder); 239 | 240 | imageArray.push({ 241 | source: file.source, 242 | name: name, 243 | path: normalizePath(relative(abstractActiveFolder, response.path)), 244 | }); 245 | } 246 | } 247 | 248 | let value = this.helper.getValue(); 249 | imageArray.map(image => { 250 | let name = this.handleName(image.name); 251 | 252 | value = value.replace( 253 | image.source, 254 | `![${name}](${encodeURI(image.path)})` 255 | ); 256 | }); 257 | 258 | this.helper.setValue(value); 259 | 260 | new Notice( 261 | `all: ${fileArray.length}\nsuccess: ${imageArray.length}\nfailed: ${ 262 | fileArray.length - imageArray.length 263 | }` 264 | ); 265 | } 266 | 267 | // 获取当前文件所属的附件文件夹 268 | getFileAssetPath() { 269 | const basePath = ( 270 | this.app.vault.adapter as FileSystemAdapter 271 | ).getBasePath(); 272 | 273 | // @ts-ignore 274 | const assetFolder: string = this.app.vault.config.attachmentFolderPath; 275 | const activeFile = this.app.vault.getAbstractFileByPath( 276 | this.app.workspace.getActiveFile().path 277 | ); 278 | 279 | // 当前文件夹下的子文件夹 280 | if (assetFolder.startsWith("./")) { 281 | const activeFolder = decodeURI(resolve(basePath, activeFile.parent.path)); 282 | return join(activeFolder, assetFolder); 283 | } else { 284 | // 根文件夹 285 | return join(basePath, assetFolder); 286 | } 287 | } 288 | 289 | async download(url: string, folderPath: string, name: string) { 290 | const response = await requestUrl({ url }); 291 | const type = await imageType(new Uint8Array(response.arrayBuffer)); 292 | 293 | if (response.status !== 200) { 294 | return { 295 | ok: false, 296 | msg: "error", 297 | }; 298 | } 299 | if (!type) { 300 | return { 301 | ok: false, 302 | msg: "error", 303 | }; 304 | } 305 | 306 | const buffer = Buffer.from(response.arrayBuffer); 307 | 308 | try { 309 | const path = join(folderPath, `${name}.${type.ext}`); 310 | 311 | writeFileSync(path, buffer); 312 | return { 313 | ok: true, 314 | msg: "ok", 315 | path: path, 316 | type, 317 | }; 318 | } catch (err) { 319 | return { 320 | ok: false, 321 | msg: err, 322 | }; 323 | } 324 | } 325 | 326 | registerFileMenu() { 327 | this.registerEvent( 328 | this.app.workspace.on( 329 | "file-menu", 330 | (menu: Menu, file: TFile, source: string, leaf) => { 331 | if (source === "canvas-menu") return false; 332 | if (!isAssetTypeAnImage(file.path)) return false; 333 | 334 | menu.addItem((item: MenuItem) => { 335 | item 336 | .setTitle("Upload") 337 | .setIcon("upload") 338 | .onClick(() => { 339 | if (!(file instanceof TFile)) { 340 | return false; 341 | } 342 | this.fileMenuUpload(file); 343 | }); 344 | }); 345 | } 346 | ) 347 | ); 348 | } 349 | 350 | fileMenuUpload(file: TFile) { 351 | let content = this.helper.getValue(); 352 | 353 | const basePath = ( 354 | this.app.vault.adapter as FileSystemAdapter 355 | ).getBasePath(); 356 | let imageList: Image[] = []; 357 | const fileArray = this.helper.getAllFiles(); 358 | 359 | for (const match of fileArray) { 360 | const imageName = match.name; 361 | const encodedUri = match.path; 362 | 363 | const fileName = basename(decodeURI(encodedUri)); 364 | 365 | if (file && file.name === fileName) { 366 | const abstractImageFile = join(basePath, file.path); 367 | 368 | if (isAssetTypeAnImage(abstractImageFile)) { 369 | imageList.push({ 370 | path: abstractImageFile, 371 | name: imageName, 372 | source: match.source, 373 | }); 374 | } 375 | } 376 | } 377 | 378 | if (imageList.length === 0) { 379 | new Notice("没有解析到图像文件"); 380 | return; 381 | } 382 | 383 | this.uploader.uploadFiles(imageList.map(item => item.path)).then(res => { 384 | if (res.success) { 385 | let uploadUrlList = res.result; 386 | imageList.map(item => { 387 | const uploadImage = uploadUrlList.shift(); 388 | let name = this.handleName(item.name); 389 | 390 | content = content.replaceAll( 391 | item.source, 392 | `![${name}](${uploadImage})` 393 | ); 394 | }); 395 | this.helper.setValue(content); 396 | 397 | if (this.settings.deleteSource) { 398 | imageList.map(image => { 399 | if (!image.path.startsWith("http")) { 400 | unlink(image.path, () => {}); 401 | } 402 | }); 403 | } 404 | } else { 405 | new Notice("Upload error"); 406 | } 407 | }); 408 | } 409 | 410 | filterFile(fileArray: Image[]) { 411 | const imageList: Image[] = []; 412 | 413 | for (const match of fileArray) { 414 | if (match.path.startsWith("http")) { 415 | if (this.settings.workOnNetWork) { 416 | if ( 417 | !this.helper.hasBlackDomain( 418 | match.path, 419 | this.settings.newWorkBlackDomains 420 | ) 421 | ) { 422 | imageList.push({ 423 | path: match.path, 424 | name: match.name, 425 | source: match.source, 426 | }); 427 | } 428 | } 429 | } else { 430 | imageList.push({ 431 | path: match.path, 432 | name: match.name, 433 | source: match.source, 434 | }); 435 | } 436 | } 437 | 438 | return imageList; 439 | } 440 | getFile(fileName: string, fileMap: any) { 441 | if (!fileMap) { 442 | fileMap = arrayToObject(this.app.vault.getFiles(), "name"); 443 | } 444 | return fileMap[fileName]; 445 | } 446 | // uploda all file 447 | uploadAllFile() { 448 | let content = this.helper.getValue(); 449 | 450 | const basePath = ( 451 | this.app.vault.adapter as FileSystemAdapter 452 | ).getBasePath(); 453 | const activeFile = this.app.workspace.getActiveFile(); 454 | const fileMap = arrayToObject(this.app.vault.getFiles(), "name"); 455 | const filePathMap = arrayToObject(this.app.vault.getFiles(), "path"); 456 | let imageList: Image[] = []; 457 | const fileArray = this.filterFile(this.helper.getAllFiles()); 458 | 459 | for (const match of fileArray) { 460 | const imageName = match.name; 461 | const encodedUri = match.path; 462 | 463 | if (encodedUri.startsWith("http")) { 464 | imageList.push({ 465 | path: match.path, 466 | name: imageName, 467 | source: match.source, 468 | }); 469 | } else { 470 | const fileName = basename(decodeURI(encodedUri)); 471 | let file; 472 | // 绝对路径 473 | if (filePathMap[decodeURI(encodedUri)]) { 474 | file = filePathMap[decodeURI(encodedUri)]; 475 | } 476 | 477 | // 相对路径 478 | if ( 479 | (!file && decodeURI(encodedUri).startsWith("./")) || 480 | decodeURI(encodedUri).startsWith("../") 481 | ) { 482 | const filePath = resolve( 483 | join(basePath, dirname(activeFile.path)), 484 | decodeURI(encodedUri) 485 | ); 486 | 487 | if (existsSync(filePath)) { 488 | const path = normalizePath( 489 | relative( 490 | basePath, 491 | resolve( 492 | join(basePath, dirname(activeFile.path)), 493 | decodeURI(encodedUri) 494 | ) 495 | ) 496 | ); 497 | 498 | file = filePathMap[path]; 499 | } 500 | } 501 | // 尽可能短路径 502 | if (!file) { 503 | file = this.getFile(fileName, fileMap); 504 | } 505 | 506 | if (file) { 507 | const abstractImageFile = join(basePath, file.path); 508 | 509 | if (isAssetTypeAnImage(abstractImageFile)) { 510 | imageList.push({ 511 | path: abstractImageFile, 512 | name: imageName, 513 | source: match.source, 514 | }); 515 | } 516 | } 517 | } 518 | } 519 | 520 | if (imageList.length === 0) { 521 | new Notice("没有解析到图像文件"); 522 | return; 523 | } else { 524 | new Notice(`共找到${imageList.length}个图像文件,开始上传`); 525 | } 526 | 527 | this.uploader.uploadFiles(imageList.map(item => item.path)).then(res => { 528 | if (res.success) { 529 | let uploadUrlList = res.result; 530 | 531 | imageList.map(item => { 532 | const uploadImage = uploadUrlList.shift(); 533 | 534 | let name = this.handleName(item.name); 535 | content = content.replaceAll( 536 | item.source, 537 | `![${name}](${uploadImage})` 538 | ); 539 | }); 540 | this.helper.setValue(content); 541 | 542 | if (this.settings.deleteSource) { 543 | imageList.map(image => { 544 | if (!image.path.startsWith("http")) { 545 | unlink(image.path, () => {}); 546 | } 547 | }); 548 | } 549 | } else { 550 | new Notice("Upload error"); 551 | } 552 | }); 553 | } 554 | // 剪切板上传 555 | setupPasteHandler() { 556 | this.registerEvent( 557 | this.app.workspace.on( 558 | "editor-paste", 559 | (evt: ClipboardEvent, editor: Editor, markdownView: MarkdownView) => { 560 | const allowUpload = this.helper.getFrontmatterValue( 561 | "image-auto-upload", 562 | this.settings.uploadByClipSwitch 563 | ); 564 | 565 | let files = evt.clipboardData.files; 566 | if (!allowUpload) { 567 | return; 568 | } 569 | 570 | // 剪贴板内容有md格式的图片时 571 | if (this.settings.workOnNetWork) { 572 | const clipboardValue = evt.clipboardData.getData("text/plain"); 573 | const imageList = this.helper 574 | .getImageLink(clipboardValue) 575 | .filter(image => image.path.startsWith("http")) 576 | .filter( 577 | image => 578 | !this.helper.hasBlackDomain( 579 | image.path, 580 | this.settings.newWorkBlackDomains 581 | ) 582 | ); 583 | 584 | if (imageList.length !== 0) { 585 | this.uploader 586 | .uploadFiles(imageList.map(item => item.path)) 587 | .then(res => { 588 | let value = this.helper.getValue(); 589 | if (res.success) { 590 | let uploadUrlList = res.result; 591 | imageList.map(item => { 592 | const uploadImage = uploadUrlList.shift(); 593 | let name = this.handleName(item.name); 594 | 595 | value = value.replaceAll( 596 | item.source, 597 | `![${name}](${uploadImage})` 598 | ); 599 | }); 600 | this.helper.setValue(value); 601 | } else { 602 | new Notice("Upload error"); 603 | } 604 | }); 605 | } 606 | } 607 | 608 | // 剪贴板中是图片时进行上传 609 | if (this.canUpload(evt.clipboardData)) { 610 | this.uploadFileAndEmbedImgurImage( 611 | editor, 612 | async (editor: Editor, pasteId: string) => { 613 | let res = await this.uploader.uploadFileByClipboard(evt.clipboardData); 614 | if (res.code !== 0) { 615 | this.handleFailedUpload(editor, pasteId, res.msg); 616 | return; 617 | } 618 | const url = res.data; 619 | 620 | return url; 621 | }, 622 | evt.clipboardData 623 | ).catch(); 624 | evt.preventDefault(); 625 | } 626 | } 627 | ) 628 | ); 629 | this.registerEvent( 630 | this.app.workspace.on( 631 | "editor-drop", 632 | async (evt: DragEvent, editor: Editor, markdownView: MarkdownView) => { 633 | const allowUpload = this.helper.getFrontmatterValue( 634 | "image-auto-upload", 635 | this.settings.uploadByClipSwitch 636 | ); 637 | let files = evt.dataTransfer.files; 638 | 639 | if (!allowUpload) { 640 | return; 641 | } 642 | 643 | if (files.length !== 0 && files[0].type.startsWith("image")) { 644 | let sendFiles: Array = []; 645 | let files = evt.dataTransfer.files; 646 | Array.from(files).forEach((item, index) => { 647 | sendFiles.push(item.path); 648 | }); 649 | evt.preventDefault(); 650 | 651 | const data = await this.uploader.uploadFiles(sendFiles); 652 | 653 | if (data.success) { 654 | data.result.map((value: string) => { 655 | let pasteId = (Math.random() + 1).toString(36).substr(2, 5); 656 | this.insertTemporaryText(editor, pasteId); 657 | this.embedMarkDownImage(editor, pasteId, value, files[0].name); 658 | }); 659 | } else { 660 | new Notice("Upload error"); 661 | } 662 | } 663 | } 664 | ) 665 | ); 666 | } 667 | 668 | canUpload(clipboardData: DataTransfer) { 669 | this.settings.applyImage; 670 | const files = clipboardData.files; 671 | const text = clipboardData.getData("text"); 672 | 673 | const hasImageFile = 674 | files.length !== 0 && files[0].type.startsWith("image"); 675 | if (hasImageFile) { 676 | if (!!text) { 677 | return this.settings.applyImage; 678 | } else { 679 | return true; 680 | } 681 | } else { 682 | return false; 683 | } 684 | } 685 | 686 | async uploadFileAndEmbedImgurImage( 687 | editor: Editor, 688 | callback: Function, 689 | clipboardData: DataTransfer 690 | ) { 691 | let pasteId = (Math.random() + 1).toString(36).substr(2, 5); 692 | this.insertTemporaryText(editor, pasteId); 693 | const name = clipboardData.files[0].name; 694 | 695 | try { 696 | const url = await callback(editor, pasteId); 697 | this.embedMarkDownImage(editor, pasteId, url, name); 698 | } catch (e) { 699 | this.handleFailedUpload(editor, pasteId, e); 700 | } 701 | } 702 | 703 | insertTemporaryText(editor: Editor, pasteId: string) { 704 | let progressText = imageAutoUploadPlugin.progressTextFor(pasteId); 705 | editor.replaceSelection(progressText + "\n"); 706 | } 707 | 708 | private static progressTextFor(id: string) { 709 | return `![Uploading file...${id}]()`; 710 | } 711 | 712 | embedMarkDownImage( 713 | editor: Editor, 714 | pasteId: string, 715 | imageUrl: any, 716 | name: string = "" 717 | ) { 718 | let progressText = imageAutoUploadPlugin.progressTextFor(pasteId); 719 | name = this.handleName(name); 720 | 721 | let markDownImage = `![${name}](${imageUrl})`; 722 | 723 | imageAutoUploadPlugin.replaceFirstOccurrence( 724 | editor, 725 | progressText, 726 | markDownImage 727 | ); 728 | } 729 | 730 | handleFailedUpload(editor: Editor, pasteId: string, reason: any) { 731 | new Notice(reason); 732 | console.error("Failed request: ", reason); 733 | let progressText = imageAutoUploadPlugin.progressTextFor(pasteId); 734 | imageAutoUploadPlugin.replaceFirstOccurrence( 735 | editor, 736 | progressText, 737 | "⚠️upload failed, check dev console" 738 | ); 739 | } 740 | 741 | handleName(name: string) { 742 | const imageSizeSuffix = this.settings.imageSizeSuffix || ""; 743 | 744 | if (this.settings.imageDesc === "origin") { 745 | return `${name}${imageSizeSuffix}`; 746 | } else if (this.settings.imageDesc === "none") { 747 | return ""; 748 | } else if (this.settings.imageDesc === "removeDefault") { 749 | if (name === "image.png") { 750 | return ""; 751 | } else { 752 | return `${name}${imageSizeSuffix}`; 753 | } 754 | } else { 755 | return `${name}${imageSizeSuffix}`; 756 | } 757 | } 758 | 759 | static replaceFirstOccurrence( 760 | editor: Editor, 761 | target: string, 762 | replacement: string 763 | ) { 764 | let lines = editor.getValue().split("\n"); 765 | for (let i = 0; i < lines.length; i++) { 766 | let ch = lines[i].indexOf(target); 767 | if (ch != -1) { 768 | let from = { line: i, ch: ch }; 769 | let to = { line: i, ch: ch + target.length }; 770 | editor.replaceRange(replacement, from, to); 771 | break; 772 | } 773 | } 774 | } 775 | } 776 | -------------------------------------------------------------------------------- /src/setting.ts: -------------------------------------------------------------------------------- 1 | import { App, PluginSettingTab, Setting } from "obsidian"; 2 | import imageAutoUploadPlugin from "./main"; 3 | import { t } from "./lang/helpers"; 4 | import { getOS } from "./utils"; 5 | 6 | export interface PluginSettings { 7 | uploadByClipSwitch: boolean; 8 | uploadServer: string; 9 | deleteServer: string; 10 | imageSizeSuffix: string; 11 | uploader: string; 12 | picgoCorePath: string; 13 | workOnNetWork: boolean; 14 | newWorkBlackDomains: string; 15 | fixPath: boolean; 16 | applyImage: boolean; 17 | deleteSource: boolean; 18 | imageDesc: "origin" | "none" | "removeDefault"; 19 | [propName: string]: any; 20 | blogSetting: { 21 | blogUrl: string; 22 | blogId: string; 23 | blogUserName: string; 24 | blogPassword: string; 25 | } 26 | githubSetting: { 27 | repo: string; 28 | branch: string; 29 | token: string; 30 | path: string; 31 | customUrl: string; 32 | } 33 | giteeSetting: { 34 | repo: string; 35 | branch: string; 36 | token: string; 37 | path: string; 38 | customUrl: string; 39 | } 40 | tencentSetting: { 41 | secretId: string; 42 | secretKey: string; 43 | region: string; 44 | bucketName: string; 45 | path: string; 46 | }, 47 | rename: boolean 48 | } 49 | 50 | export const DEFAULT_SETTINGS: PluginSettings = { 51 | uploadByClipSwitch: true, 52 | uploader: "PicGo", 53 | uploadServer: "http://127.0.0.1:36677/upload", 54 | deleteServer: "http://127.0.0.1:36677/delete", 55 | imageSizeSuffix: "", 56 | picgoCorePath: "", 57 | workOnNetWork: false, 58 | fixPath: false, 59 | applyImage: true, 60 | newWorkBlackDomains: "", 61 | deleteSource: false, 62 | imageDesc: "origin", 63 | blogSetting: { 64 | blogUrl: "", 65 | blogId: "", 66 | blogUserName: "", 67 | blogPassword: "", 68 | }, 69 | githubSetting: { 70 | repo: 'sancijun/images', 71 | branch: 'master', 72 | token: '', 73 | path: 'pics/', 74 | customUrl: `https://cdn.jsdelivr.net/gh/sancijun/images/` 75 | }, 76 | giteeSetting: { 77 | repo: 'sancijun/pictures', 78 | branch: 'master', 79 | token: '', 80 | path: '/imgs/', 81 | customUrl: 'https://cdn.jsdelivr.net/gh/sancijun/images/' 82 | }, 83 | tencentSetting: { 84 | secretId: '', 85 | secretKey: '', 86 | region: 'ap-guangzhou', 87 | bucketName: 'sancijun-1255318116', 88 | path: '/test/', 89 | }, 90 | rename: true, 91 | }; 92 | 93 | export class SettingTab extends PluginSettingTab { 94 | plugin: imageAutoUploadPlugin; 95 | 96 | constructor(app: App, plugin: imageAutoUploadPlugin) { 97 | super(app, plugin); 98 | this.plugin = plugin; 99 | } 100 | 101 | display(): void { 102 | let { containerEl } = this; 103 | 104 | const os = getOS(); 105 | 106 | containerEl.empty(); 107 | containerEl.createEl("h2", { text: t("Plugin Settings") }); 108 | const contentHTML = ` 109 |
110 | 111 | Bilibili 112 | 113 | 114 | TikTok 115 | 116 | 117 | 公众号 118 | 119 | 120 | 微信 121 | 122 |
123 | `; 124 | 125 | const contentDiv = containerEl.createEl("div"); 126 | contentDiv.innerHTML = contentHTML; 127 | 128 | new Setting(containerEl) 129 | .setName(t("Auto pasted upload")) 130 | .setDesc( 131 | t( 132 | "If you set this value true, when you paste image, it will be auto uploaded(you should set the picGo server rightly)" 133 | ) 134 | ) 135 | .addToggle(toggle => 136 | toggle 137 | .setValue(this.plugin.settings.uploadByClipSwitch) 138 | .onChange(async value => { 139 | this.plugin.settings.uploadByClipSwitch = value; 140 | await this.plugin.saveSettings(); 141 | }) 142 | ); 143 | 144 | new Setting(containerEl) 145 | .setName(t("Default uploader")) 146 | .setDesc(t("Default uploader")) 147 | .addDropdown(cb => 148 | cb 149 | .addOption("Blog", "Blog") 150 | .addOption("GitHub", "GitHub") 151 | .addOption("Gitee", "Gitee") 152 | .addOption("Tencent", "Tencent") 153 | .addOption("PicGo", "PicGo(app)") 154 | .addOption("PicGo-Core", "PicGo-Core") 155 | .setValue(this.plugin.settings.uploader) 156 | .onChange(async value => { 157 | this.plugin.settings.uploader = value; 158 | this.display(); 159 | await this.plugin.saveSettings(); 160 | }) 161 | ); 162 | if (this.plugin.settings.uploader === "Blog") { 163 | new Setting(containerEl) 164 | .setName(t("Blog URL")) 165 | .setDesc(t("Blog URL")) 166 | .addText(text => 167 | text 168 | .setPlaceholder(t("Please input blog url")) 169 | .setValue(this.plugin.settings.blogSetting.blogUrl) 170 | .onChange(async key => { 171 | this.plugin.settings.blogSetting.blogUrl = key; 172 | await this.plugin.saveSettings(); 173 | }) 174 | ); 175 | new Setting(containerEl) 176 | .setName(t("Blog ID")) 177 | .setDesc(t("Blog ID")) 178 | .addText(text => 179 | text 180 | .setPlaceholder(t("Please input blog ID")) 181 | .setValue(this.plugin.settings.blogSetting.blogId) 182 | .onChange(async key => { 183 | this.plugin.settings.blogSetting.blogId = key; 184 | await this.plugin.saveSettings(); 185 | }) 186 | ); 187 | 188 | new Setting(containerEl) 189 | .setName(t("Blog User Name")) 190 | .setDesc(t("Blog User Name")) 191 | .addText(text => 192 | text 193 | .setPlaceholder(t("Please input blog user name")) 194 | .setValue(this.plugin.settings.blogSetting.blogUserName) 195 | .onChange(async key => { 196 | this.plugin.settings.blogSetting.blogUserName = key; 197 | await this.plugin.saveSettings(); 198 | }) 199 | ); 200 | 201 | new Setting(containerEl) 202 | .setName(t("Blog Token")) 203 | .setDesc(t("Blog Token")) 204 | .addText(text => 205 | text 206 | .setPlaceholder(t("Please input blog token")) 207 | .setValue(this.plugin.settings.blogSetting.blogPassword) 208 | .onChange(async key => { 209 | this.plugin.settings.blogSetting.blogPassword = key; 210 | await this.plugin.saveSettings(); 211 | }) 212 | ); 213 | } 214 | 215 | if (this.plugin.settings.uploader === "GitHub") { 216 | new Setting(containerEl) 217 | .setName(t("Repository")) 218 | .addText(text => 219 | text 220 | .setPlaceholder(t("Please input your repository")) 221 | .setValue(this.plugin.settings.githubSetting.repo) 222 | .onChange(async key => { 223 | this.plugin.settings.githubSetting.repo = key; 224 | await this.plugin.saveSettings(); 225 | }) 226 | ); 227 | new Setting(containerEl) 228 | .setName(t("Branch")) 229 | .addText(text => 230 | text 231 | .setPlaceholder(t("Please input your branch")) 232 | .setValue(this.plugin.settings.githubSetting.branch) 233 | .onChange(async key => { 234 | this.plugin.settings.githubSetting.branch = key; 235 | await this.plugin.saveSettings(); 236 | }) 237 | ); 238 | 239 | new Setting(containerEl) 240 | .setName(t("Token")) 241 | .addText(text => 242 | text 243 | .setPlaceholder(t("Please input your token")) 244 | .setValue(this.plugin.settings.githubSetting.token) 245 | .onChange(async key => { 246 | this.plugin.settings.githubSetting.token = key; 247 | await this.plugin.saveSettings(); 248 | }) 249 | ); 250 | 251 | new Setting(containerEl) 252 | .setName(t("Path")) 253 | .addText(text => 254 | text 255 | .setPlaceholder(t("Please input your path")) 256 | .setValue(this.plugin.settings.githubSetting.path) 257 | .onChange(async key => { 258 | this.plugin.settings.githubSetting.path = key; 259 | await this.plugin.saveSettings(); 260 | }) 261 | ); 262 | 263 | new Setting(containerEl) 264 | .setName(t("Custom URL")) 265 | .addText(text => 266 | text 267 | .setPlaceholder(t("Please input custom URL")) 268 | .setValue(this.plugin.settings.githubSetting.customUrl) 269 | .onChange(async key => { 270 | this.plugin.settings.githubSetting.customUrl = key; 271 | await this.plugin.saveSettings(); 272 | }) 273 | ); 274 | } 275 | 276 | if (this.plugin.settings.uploader === "Gitee") { 277 | new Setting(containerEl) 278 | .setName(t("Repository")) 279 | .addText(text => 280 | text 281 | .setPlaceholder(t("Please input your repository")) 282 | .setValue(this.plugin.settings.giteeSetting.repo) 283 | .onChange(async key => { 284 | this.plugin.settings.giteeSetting.repo = key; 285 | await this.plugin.saveSettings(); 286 | }) 287 | ); 288 | new Setting(containerEl) 289 | .setName(t("Branch")) 290 | .addText(text => 291 | text 292 | .setPlaceholder(t("Please input your branch")) 293 | .setValue(this.plugin.settings.giteeSetting.branch) 294 | .onChange(async key => { 295 | this.plugin.settings.giteeSetting.branch = key; 296 | await this.plugin.saveSettings(); 297 | }) 298 | ); 299 | 300 | new Setting(containerEl) 301 | .setName(t("Token")) 302 | .addText(text => 303 | text 304 | .setPlaceholder(t("Please input your token")) 305 | .setValue(this.plugin.settings.giteeSetting.token) 306 | .onChange(async key => { 307 | this.plugin.settings.giteeSetting.token = key; 308 | await this.plugin.saveSettings(); 309 | }) 310 | ); 311 | 312 | new Setting(containerEl) 313 | .setName(t("Path")) 314 | .addText(text => 315 | text 316 | .setPlaceholder(t("Please input your path")) 317 | .setValue(this.plugin.settings.giteeSetting.path) 318 | .onChange(async key => { 319 | this.plugin.settings.giteeSetting.path = key; 320 | await this.plugin.saveSettings(); 321 | }) 322 | ); 323 | 324 | new Setting(containerEl) 325 | .setName(t("Custom URL")) 326 | .addText(text => 327 | text 328 | .setPlaceholder(t("Please input custom URL")) 329 | .setValue(this.plugin.settings.giteeSetting.customUrl) 330 | .onChange(async key => { 331 | this.plugin.settings.giteeSetting.customUrl = key; 332 | await this.plugin.saveSettings(); 333 | }) 334 | ); 335 | } 336 | 337 | if (this.plugin.settings.uploader === "Tencent") { 338 | new Setting(containerEl) 339 | .setName(t("Secret ID")) 340 | .addText(text => 341 | text 342 | .setPlaceholder(t("Please input your secret ID")) 343 | .setValue(this.plugin.settings.tencentSetting.secretId) 344 | .onChange(async key => { 345 | this.plugin.settings.tencentSetting.secretId = key; 346 | await this.plugin.saveSettings(); 347 | }) 348 | ); 349 | new Setting(containerEl) 350 | .setName(t("Secret Key")) 351 | .addText(text => 352 | text 353 | .setPlaceholder(t("Please input your secret key")) 354 | .setValue(this.plugin.settings.tencentSetting.secretKey) 355 | .onChange(async key => { 356 | this.plugin.settings.tencentSetting.secretKey = key; 357 | await this.plugin.saveSettings(); 358 | }) 359 | ); 360 | 361 | new Setting(containerEl) 362 | .setName(t("Region")) 363 | .addText(text => 364 | text 365 | .setPlaceholder(t("Please input your region")) 366 | .setValue(this.plugin.settings.tencentSetting.region) 367 | .onChange(async key => { 368 | this.plugin.settings.tencentSetting.region = key; 369 | await this.plugin.saveSettings(); 370 | }) 371 | ); 372 | 373 | new Setting(containerEl) 374 | .setName(t("Bucket")) 375 | .addText(text => 376 | text 377 | .setPlaceholder(t("Please input your bucket name")) 378 | .setValue(this.plugin.settings.tencentSetting.bucketName) 379 | .onChange(async key => { 380 | this.plugin.settings.tencentSetting.bucketName = key; 381 | await this.plugin.saveSettings(); 382 | }) 383 | ); 384 | 385 | new Setting(containerEl) 386 | .setName(t("Path")) 387 | .addText(text => 388 | text 389 | .setPlaceholder(t("Please input your path")) 390 | .setValue(this.plugin.settings.tencentSetting.path) 391 | .onChange(async key => { 392 | this.plugin.settings.tencentSetting.path = key; 393 | await this.plugin.saveSettings(); 394 | }) 395 | ); 396 | } 397 | 398 | if (this.plugin.settings.uploader === "PicGo") { 399 | new Setting(containerEl) 400 | .setName(t("PicGo server")) 401 | .setDesc(t("PicGo server")) 402 | .addText(text => 403 | text 404 | .setPlaceholder(t("Please input PicGo server")) 405 | .setValue(this.plugin.settings.uploadServer) 406 | .onChange(async key => { 407 | this.plugin.settings.uploadServer = key; 408 | await this.plugin.saveSettings(); 409 | }) 410 | ); 411 | 412 | new Setting(containerEl) 413 | .setName(t("PicGo delete server")) 414 | .setDesc(t("PicList desc")) 415 | .addText(text => 416 | text 417 | .setPlaceholder(t("Please input PicGo delete server")) 418 | .setValue(this.plugin.settings.deleteServer) 419 | .onChange(async key => { 420 | this.plugin.settings.deleteServer = key; 421 | await this.plugin.saveSettings(); 422 | }) 423 | ); 424 | } 425 | 426 | if (this.plugin.settings.uploader === "PicGo-Core") { 427 | new Setting(containerEl) 428 | .setName(t("PicGo-Core path")) 429 | .setDesc( 430 | t("Please input PicGo-Core path, default using environment variables") 431 | ) 432 | .addText(text => 433 | text 434 | .setPlaceholder("") 435 | .setValue(this.plugin.settings.picgoCorePath) 436 | .onChange(async value => { 437 | this.plugin.settings.picgoCorePath = value; 438 | await this.plugin.saveSettings(); 439 | }) 440 | ); 441 | 442 | if (os !== "Windows") { 443 | new Setting(containerEl) 444 | .setName(t("fixPath")) 445 | .setDesc(t("fixPathWarning")) 446 | .addToggle(toggle => 447 | toggle 448 | .setValue(this.plugin.settings.fixPath) 449 | .onChange(async value => { 450 | this.plugin.settings.fixPath = value; 451 | await this.plugin.saveSettings(); 452 | }) 453 | ); 454 | } 455 | } 456 | 457 | new Setting(containerEl) 458 | .setName(t("Rename")) 459 | .setDesc(t("Rename Desc")) 460 | .addToggle(toggle => 461 | toggle 462 | .setValue(this.plugin.settings.rename) 463 | .onChange(async value => { 464 | this.plugin.settings.rename = value; 465 | this.display(); 466 | await this.plugin.saveSettings(); 467 | }) 468 | ); 469 | 470 | // image desc setting 471 | new Setting(containerEl) 472 | .setName(t("Image desc")) 473 | .setDesc(t("Image desc")) 474 | .addDropdown(cb => 475 | cb 476 | .addOption("origin", t("reserve")) // 保留全部 477 | .addOption("none", t("remove all")) // 移除全部 478 | .addOption("removeDefault", t("remove default")) // 只移除默认即 image.png 479 | .setValue(this.plugin.settings.imageDesc) 480 | .onChange(async (value: "origin" | "none" | "removeDefault") => { 481 | this.plugin.settings.imageDesc = value; 482 | this.display(); 483 | await this.plugin.saveSettings(); 484 | }) 485 | ); 486 | 487 | new Setting(containerEl) 488 | .setName(t("Image size suffix")) 489 | .setDesc(t("Image size suffix Description")) 490 | .addText(text => 491 | text 492 | .setPlaceholder(t("Please input image size suffix")) 493 | .setValue(this.plugin.settings.imageSizeSuffix) 494 | .onChange(async key => { 495 | this.plugin.settings.imageSizeSuffix = key; 496 | await this.plugin.saveSettings(); 497 | }) 498 | ); 499 | 500 | new Setting(containerEl) 501 | .setName(t("Work on network")) 502 | .setDesc(t("Work on network Description")) 503 | .addToggle(toggle => 504 | toggle 505 | .setValue(this.plugin.settings.workOnNetWork) 506 | .onChange(async value => { 507 | this.plugin.settings.workOnNetWork = value; 508 | this.display(); 509 | await this.plugin.saveSettings(); 510 | }) 511 | ); 512 | 513 | new Setting(containerEl) 514 | .setName(t("Network Domain Black List")) 515 | .setDesc(t("Network Domain Black List Description")) 516 | .addTextArea(textArea => 517 | textArea 518 | .setValue(this.plugin.settings.newWorkBlackDomains) 519 | .onChange(async value => { 520 | this.plugin.settings.newWorkBlackDomains = value; 521 | await this.plugin.saveSettings(); 522 | }) 523 | ); 524 | 525 | new Setting(containerEl) 526 | .setName(t("Upload when clipboard has image and text together")) 527 | .setDesc( 528 | t( 529 | "When you copy, some application like Excel will image and text to clipboard, you can upload or not." 530 | ) 531 | ) 532 | .addToggle(toggle => 533 | toggle 534 | .setValue(this.plugin.settings.applyImage) 535 | .onChange(async value => { 536 | this.plugin.settings.applyImage = value; 537 | this.display(); 538 | await this.plugin.saveSettings(); 539 | }) 540 | ); 541 | 542 | new Setting(containerEl) 543 | .setName(t("Delete source file after you upload file")) 544 | .setDesc(t("Delete source file in ob assets after you upload file.")) 545 | .addToggle(toggle => 546 | toggle 547 | .setValue(this.plugin.settings.deleteSource) 548 | .onChange(async value => { 549 | this.plugin.settings.deleteSource = value; 550 | this.display(); 551 | await this.plugin.saveSettings(); 552 | }) 553 | ); 554 | } 555 | } 556 | -------------------------------------------------------------------------------- /src/uploader.ts: -------------------------------------------------------------------------------- 1 | import { PluginSettings } from "./setting"; 2 | import { streamToString, getLastImage, getCurrentTimestamp, fileToBase64, fileToBuffer } from "./utils"; 3 | import { exec } from "child_process"; 4 | import { Notice, requestUrl } from "obsidian"; 5 | import imageAutoUploadPlugin from "./main"; 6 | import * as fs from 'fs'; 7 | import { parseString } from 'xml2js'; 8 | import * as path from 'path'; 9 | import COS from 'cos-js-sdk-v5'; 10 | 11 | 12 | export interface PicGoResponse { 13 | success: string; 14 | msg: string; 15 | result: string[]; 16 | fullResult: Record[]; 17 | } 18 | 19 | export class PicGoUploader { 20 | settings: PluginSettings; 21 | plugin: imageAutoUploadPlugin; 22 | 23 | constructor(settings: PluginSettings, plugin: imageAutoUploadPlugin) { 24 | this.settings = settings; 25 | this.plugin = plugin; 26 | } 27 | 28 | async uploadFiles(fileList: Array): Promise { 29 | const response = await requestUrl({ 30 | url: this.settings.uploadServer, 31 | method: "POST", 32 | headers: { "Content-Type": "application/json" }, 33 | body: JSON.stringify({ list: fileList }), 34 | }); 35 | 36 | const data = await response.json; 37 | 38 | // piclist 39 | if (data.fullResult) { 40 | const uploadUrlFullResultList = data.fullResult || []; 41 | this.settings.uploadedImages = [ 42 | ...(this.settings.uploadedImages || []), 43 | ...uploadUrlFullResultList, 44 | ]; 45 | } 46 | 47 | return data; 48 | } 49 | 50 | async uploadFileByClipboard(clipboardData: DataTransfer): Promise { 51 | const res = await requestUrl({ 52 | url: this.settings.uploadServer, 53 | method: "POST", 54 | }); 55 | 56 | let data: PicGoResponse = await res.json; 57 | 58 | // piclist 59 | if (data.fullResult) { 60 | const uploadUrlFullResultList = data.fullResult || []; 61 | this.settings.uploadedImages = [ 62 | ...(this.settings.uploadedImages || []), 63 | ...uploadUrlFullResultList, 64 | ]; 65 | this.plugin.saveSettings(); 66 | } 67 | 68 | if (res.status !== 200) { 69 | let err = { response: data, body: data.msg }; 70 | return { 71 | code: -1, 72 | msg: data.msg, 73 | data: "", 74 | }; 75 | } else { 76 | return { 77 | code: 0, 78 | msg: "success", 79 | data: typeof data.result == "string" ? data.result : data.result[0], 80 | }; 81 | } 82 | } 83 | } 84 | 85 | export class PicGoCoreUploader { 86 | settings: PluginSettings; 87 | plugin: imageAutoUploadPlugin; 88 | 89 | constructor(settings: PluginSettings, plugin: imageAutoUploadPlugin) { 90 | this.settings = settings; 91 | this.plugin = plugin; 92 | } 93 | 94 | async uploadFiles(fileList: Array): Promise { 95 | const length = fileList.length; 96 | let cli = this.settings.picgoCorePath || "picgo"; 97 | let command = `${cli} upload ${fileList 98 | .map(item => `"${item}"`) 99 | .join(" ")}`; 100 | 101 | const res = await this.exec(command); 102 | const splitList = res.split("\n"); 103 | const splitListLength = splitList.length; 104 | 105 | const data = splitList.splice(splitListLength - 1 - length, length); 106 | 107 | if (res.includes("PicGo ERROR")) { 108 | console.log(command, res); 109 | 110 | return { 111 | success: false, 112 | msg: "失败", 113 | }; 114 | } else { 115 | return { 116 | success: true, 117 | result: data, 118 | }; 119 | } 120 | // {success:true,result:[]} 121 | } 122 | 123 | // PicGo-Core 上传处理 124 | async uploadFileByClipboard(clipboardData: DataTransfer) { 125 | const res = await this.uploadByClip(); 126 | const splitList = res.split("\n"); 127 | const lastImage = getLastImage(splitList); 128 | 129 | if (lastImage) { 130 | return { 131 | code: 0, 132 | msg: "success", 133 | data: lastImage, 134 | }; 135 | } else { 136 | console.log(splitList); 137 | 138 | // new Notice(`"Please check PicGo-Core config"\n${res}`); 139 | return { 140 | code: -1, 141 | msg: `"Please check PicGo-Core config"\n${res}`, 142 | data: "", 143 | }; 144 | } 145 | } 146 | 147 | // PicGo-Core的剪切上传反馈 148 | async uploadByClip() { 149 | let command; 150 | if (this.settings.picgoCorePath) { 151 | command = `${this.settings.picgoCorePath} upload`; 152 | } else { 153 | command = `picgo upload`; 154 | } 155 | const res = await this.exec(command); 156 | // const res = await this.spawnChild(); 157 | 158 | return res; 159 | } 160 | 161 | async exec(command: string) { 162 | let { stdout } = await exec(command); 163 | const res = await streamToString(stdout); 164 | return res; 165 | } 166 | 167 | async spawnChild() { 168 | const { spawn } = require("child_process"); 169 | const child = spawn("picgo", ["upload"], { 170 | shell: true, 171 | }); 172 | 173 | let data = ""; 174 | for await (const chunk of child.stdout) { 175 | data += chunk; 176 | } 177 | let error = ""; 178 | for await (const chunk of child.stderr) { 179 | error += chunk; 180 | } 181 | const exitCode = await new Promise((resolve, reject) => { 182 | child.on("close", resolve); 183 | }); 184 | 185 | if (exitCode) { 186 | throw new Error(`subprocess error exit ${exitCode}, ${error}`); 187 | } 188 | return data; 189 | } 190 | } 191 | 192 | export abstract class BaseUploader { 193 | settings: PluginSettings; 194 | plugin: imageAutoUploadPlugin; 195 | 196 | constructor(settings: PluginSettings, plugin: imageAutoUploadPlugin) { 197 | this.settings = settings; 198 | this.plugin = plugin; 199 | } 200 | 201 | async uploadFiles(fileList: String[]): Promise { 202 | console.log('uploadFiles', fileList); 203 | const urls: any[] = []; 204 | 205 | for (const imagePath of fileList) { 206 | let imageData: Buffer; 207 | 208 | if (imagePath.startsWith('http')) { 209 | const response = await requestUrl(imagePath.toString()); 210 | imageData = await Buffer.from(response.text); 211 | } else { 212 | imageData = fs.readFileSync(imagePath.toString()); 213 | } 214 | const fileName = this.settings.rename 215 | ? `${getCurrentTimestamp()}${path.extname(imagePath.toString())}` 216 | : path.basename(imagePath.toString()); 217 | const imageBase64String = imageData.toString('base64') 218 | const imageUrl = await this.upload(imageBase64String, fileName); 219 | urls.push(imageUrl); 220 | } 221 | console.log('urls', urls) 222 | return { 223 | success: true, 224 | result: urls, 225 | }; 226 | } 227 | 228 | async uploadFileByClipboard(clipboardData: DataTransfer): Promise { 229 | console.log('uploadFileByClipboard', clipboardData.types); 230 | const urls = []; 231 | // 处理每个文件 232 | for (let i = 0; i < clipboardData.files.length; i++) { 233 | const fileName = `${getCurrentTimestamp()}${path.extname(clipboardData.files[i].name)}`; 234 | const imageBase64String = await fileToBase64(clipboardData.files[i]); 235 | const imageUrl = await this.upload(imageBase64String, fileName); 236 | urls.push(imageUrl) 237 | } 238 | console.log('urls', urls) 239 | return { 240 | code: 0, 241 | msg: "success", 242 | data: urls[0], 243 | }; 244 | } 245 | 246 | abstract upload(imageData: string, fileName: string): Promise; 247 | } 248 | 249 | export class BlogUploader extends BaseUploader { 250 | 251 | async upload(imageData: string, fileName: string): Promise { 252 | const metaWeblogUrl = this.settings.blogSetting.blogUrl; 253 | const blogId = this.settings.blogSetting.blogId; 254 | const username = this.settings.blogSetting.blogUserName; 255 | const password = this.settings.blogSetting.blogPassword; 256 | 257 | const imageDataInfo = { 258 | name: 'image.jpg', 259 | type: 'image/jpeg', 260 | bits: imageData, // Convert binary data to Base64 string 261 | }; 262 | 263 | // Convert imageDataInfo to a string in XML-RPC format 264 | const xmlData = ` 265 | 266 | metaWeblog.newMediaObject 267 | 268 | 269 | 270 | ${blogId} 271 | 272 | 273 | 274 | 275 | ${username} 276 | 277 | 278 | 279 | 280 | ${password} 281 | 282 | 283 | 284 | 285 | 286 | 287 | name 288 | 289 | ${imageDataInfo.name} 290 | 291 | 292 | 293 | type 294 | 295 | ${imageDataInfo.type} 296 | 297 | 298 | 299 | bits 300 | 301 | ${imageDataInfo.bits} 302 | 303 | 304 | 305 | 306 | 307 | 308 | `; 309 | 310 | const headers = { 311 | 'Content-Type': 'text/xml', // Set the correct Content-Type for XML-RPC 312 | }; 313 | 314 | const response = await requestUrl({ 315 | url: metaWeblogUrl, 316 | method: 'POST', 317 | headers: headers, 318 | body: xmlData, 319 | }); 320 | 321 | const mediaInfo = await response.text; 322 | const imageUrl = await this.parseMediaInfo(mediaInfo); 323 | console.log('Image URL:', imageUrl); 324 | return imageUrl; 325 | } 326 | 327 | async parseMediaInfo(mediaInfo: string): Promise { 328 | return new Promise((resolve, reject) => { 329 | parseString(mediaInfo, (err, result) => { 330 | if (err) { 331 | reject(err); 332 | } else { 333 | const imageUrl = 334 | result.methodResponse.params[0].param[0].value[0].struct[0].member[0] 335 | .value[0].string[0]; 336 | resolve(imageUrl); 337 | } 338 | }); 339 | }); 340 | } 341 | } 342 | 343 | export class GithubUploader extends BaseUploader { 344 | 345 | async upload(imageData: string, fileName: string): Promise { 346 | const fileKey = path.join("/", this.settings.githubSetting.path, "/", fileName); 347 | const apiUrl = `https://api.github.com/repos/${this.settings.githubSetting.repo}/contents${fileKey}`; 348 | 349 | const requestData = { 350 | message: `Upload ${fileKey}`, 351 | branch: this.settings.githubSetting.branch, 352 | content: imageData, 353 | }; 354 | 355 | const response = await requestUrl({ 356 | url: apiUrl, 357 | method: 'PUT', 358 | headers: { 359 | Authorization: `token ${this.settings.githubSetting.token}`, 360 | 'Content-Type': 'application/json', 361 | }, 362 | body: JSON.stringify(requestData), 363 | }); 364 | 365 | const customUrl = this.settings.githubSetting.customUrl.trim(); 366 | const imageUrl = customUrl === '' ? response.json.content.download_url : customUrl + response.json.content.path; 367 | return imageUrl; 368 | } 369 | } 370 | 371 | export class GiteeUploader extends BaseUploader { 372 | 373 | async upload(imageData: string, fileName: string): Promise { 374 | const fileKey = path.join("/", this.settings.giteeSetting.path, "/", fileName); 375 | const apiUrl = `https://gitee.com/api/v5/repos/${this.settings.giteeSetting.repo}/contents${fileKey}`; 376 | 377 | // Build the API request data 378 | const requestData = { 379 | access_token: this.settings.giteeSetting.token, 380 | message: `Upload ${fileKey}`, 381 | branch: this.settings.giteeSetting.branch, 382 | content: imageData, 383 | }; 384 | const response = await requestUrl({ 385 | url: apiUrl, 386 | method: 'POST', 387 | headers: { 388 | 'Content-Type': 'application/json', 389 | }, 390 | body: JSON.stringify(requestData), 391 | }); 392 | 393 | console.log("gitee 200: ", response); 394 | const downloadUrl = response.json.content.download_url; 395 | return downloadUrl; 396 | } 397 | } 398 | 399 | export class TencentCosUploader extends BaseUploader { 400 | 401 | cos = new COS({ 402 | SecretId: this.settings.tencentSetting.secretId, 403 | SecretKey: this.settings.tencentSetting.secretKey, 404 | }); 405 | 406 | async upload(imageData: string, fileName: string): Promise { 407 | return new Promise((resolve, reject) => { 408 | const fileKey = path.join("/", this.settings.tencentSetting.path, "/", fileName); 409 | 410 | this.cos.putObject( 411 | { 412 | Bucket: this.settings.tencentSetting.bucketName, 413 | Region: this.settings.tencentSetting.region, 414 | Key: fileKey, 415 | StorageClass: 'STANDARD', 416 | Body: this.base64ToBlob(imageData), 417 | }, 418 | (err, data) => { 419 | if (err) { 420 | console.log("cos upload:", err) 421 | reject(err); 422 | } else { 423 | const location = data.Location || ''; 424 | resolve(`https://${location}`); 425 | } 426 | } 427 | ); 428 | }); 429 | } 430 | 431 | base64ToBlob(base64String: string, contentType: string = ''): Blob { 432 | // 解码 base64 字符串为二进制数据 433 | const binaryString = atob(base64String); 434 | const byteArray = new Uint8Array(binaryString.length); 435 | for (let i = 0; i < binaryString.length; i++) { 436 | byteArray[i] = binaryString.charCodeAt(i); 437 | } 438 | 439 | // 创建 Blob 对象 440 | if (contentType === '') { 441 | contentType = 'application/octet-stream'; // 默认为二进制流 442 | } 443 | return new Blob([byteArray], { type: contentType }); 444 | } 445 | 446 | } 447 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { extname, parse, posix } from "path"; 2 | import { Readable } from "stream"; 3 | import { clipboard } from "electron"; 4 | 5 | export interface IStringKeyMap { 6 | [key: string]: T; 7 | } 8 | 9 | const IMAGE_EXT_LIST = [ 10 | ".png", 11 | ".jpg", 12 | ".jpeg", 13 | ".bmp", 14 | ".gif", 15 | ".svg", 16 | ".tiff", 17 | ".webp", 18 | ".avif", 19 | ]; 20 | 21 | export function isAnImage(ext: string) { 22 | return IMAGE_EXT_LIST.includes(ext.toLowerCase()); 23 | } 24 | export function isAssetTypeAnImage(path: string): Boolean { 25 | return isAnImage(extname(path)); 26 | } 27 | 28 | export function getOS() { 29 | const { appVersion } = navigator; 30 | if (appVersion.indexOf("Win") !== -1) { 31 | return "Windows"; 32 | } else if (appVersion.indexOf("Mac") !== -1) { 33 | return "MacOS"; 34 | } else if (appVersion.indexOf("X11") !== -1) { 35 | return "Linux"; 36 | } else { 37 | return "Unknown OS"; 38 | } 39 | } 40 | export async function streamToString(stream: Readable) { 41 | const chunks = []; 42 | 43 | for await (const chunk of stream) { 44 | chunks.push(Buffer.from(chunk)); 45 | } 46 | 47 | return Buffer.concat(chunks).toString("utf-8"); 48 | } 49 | 50 | export function getUrlAsset(url: string) { 51 | return (url = url.substr(1 + url.lastIndexOf("/")).split("?")[0]).split( 52 | "#" 53 | )[0]; 54 | } 55 | 56 | export function isCopyImageFile() { 57 | let filePath = ""; 58 | const os = getOS(); 59 | 60 | if (os === "Windows") { 61 | var rawFilePath = clipboard.read("FileNameW"); 62 | filePath = rawFilePath.replace(new RegExp(String.fromCharCode(0), "g"), ""); 63 | } else if (os === "MacOS") { 64 | filePath = clipboard.read("public.file-url").replace("file://", ""); 65 | } else { 66 | filePath = ""; 67 | } 68 | return isAssetTypeAnImage(filePath); 69 | } 70 | 71 | export function getLastImage(list: string[]) { 72 | const reversedList = list.reverse(); 73 | let lastImage; 74 | reversedList.forEach(item => { 75 | if (item && item.startsWith("http")) { 76 | lastImage = item; 77 | return item; 78 | } 79 | }); 80 | return lastImage; 81 | } 82 | 83 | interface AnyObj { 84 | [key: string]: any; 85 | } 86 | 87 | export function arrayToObject( 88 | arr: T[], 89 | key: string 90 | ): { [key: string]: T } { 91 | const obj: { [key: string]: T } = {}; 92 | arr.forEach(element => { 93 | obj[element[key]] = element; 94 | }); 95 | return obj; 96 | } 97 | 98 | export async function fileToBase64(file: File): Promise { 99 | return new Promise((resolve, reject) => { 100 | const reader = new FileReader(); 101 | 102 | reader.onload = () => { 103 | const base64String = reader.result as string; 104 | const base64 = base64String.split(",")[1]; // 去除前缀 "data:xxx;base64," 105 | resolve(base64); 106 | }; 107 | 108 | reader.onerror = () => { 109 | reject(new Error("无法读取文件")); 110 | }; 111 | 112 | reader.readAsDataURL(file); 113 | }); 114 | } 115 | 116 | export async function fileToBuffer(file: File): Promise { 117 | return new Promise((resolve, reject) => { 118 | const reader = new FileReader(); 119 | 120 | // 当读取完成时的回调函数 121 | reader.onload = () => { 122 | if (reader.result instanceof ArrayBuffer) { 123 | // 将 ArrayBuffer 转换为 Buffer 124 | const buffer = Buffer.from(reader.result); 125 | resolve(buffer); 126 | } else { 127 | reject(new Error('Failed to read file as ArrayBuffer.')); 128 | } 129 | }; 130 | 131 | // 当读取失败时的回调函数 132 | reader.onerror = () => { 133 | reject(new Error('Error reading file.')); 134 | }; 135 | 136 | // 开始读取文件内容 137 | reader.readAsArrayBuffer(file); 138 | }); 139 | } 140 | 141 | 142 | export function getCurrentTimestamp(): string { 143 | const now = new Date(); 144 | 145 | const year = now.getFullYear(); 146 | const month = (now.getMonth() + 1).toString().padStart(2, '0'); 147 | const day = now.getDate().toString().padStart(2, '0'); 148 | const hours = now.getHours().toString().padStart(2, '0'); 149 | const minutes = now.getMinutes().toString().padStart(2, '0'); 150 | const seconds = now.getSeconds().toString().padStart(2, '0'); 151 | const milliseconds = now.getMilliseconds().toString().padStart(3, '0'); 152 | 153 | const formattedTimestamp = `${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`; 154 | return formattedTimestamp; 155 | } 156 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "es5", 8 | "downlevelIteration": true, 9 | "allowJs": true, 10 | "noImplicitAny": true, 11 | "moduleResolution": "node", 12 | "importHelpers": true, 13 | "lib": ["dom", "es5", "scripthost", "es2015", "es2020", "ESNext"], 14 | "allowSyntheticDefaultImports": true 15 | }, 16 | "include": ["**/*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "0.9.4": "0.10.7" 3 | } 4 | -------------------------------------------------------------------------------- /workspace.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "editor.defaultFormatter": "esbenp.prettier-vscode", 9 | "editor.formatOnSave": true, 10 | "editor.tabSize": 2 11 | } 12 | } 13 | --------------------------------------------------------------------------------