├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github └── workflows │ └── release.yml ├── .gitignore ├── .npmrc ├── LICENSE ├── MAKEFILE ├── README.md ├── README_ZH.md ├── attachment ├── Usage_CN.png └── Usage_EN.png ├── manifest-beta.json ├── manifest.json ├── md └── CHANGELOG.md ├── package-lock.json ├── package.json ├── scripts ├── esbuild.config.mjs ├── esbuild.config.test.mjs └── version-bump.mjs ├── src ├── i18n │ ├── en.ts │ ├── i18n.ts │ ├── types.ts │ ├── zh-tw.ts │ └── zh.ts ├── main.ts ├── settings │ ├── folderSuggester.ts │ ├── settingstab.ts │ └── suggesters.ts ├── styles.css ├── types.ts └── utils │ └── utils.ts ├── styles.css ├── tsconfig.json └── versions.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = tab 9 | indent_size = 4 10 | tab_width = 4 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | scripts/ 4 | attachment/ 5 | main.js 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "env": { "node": true }, 5 | "plugins": [ 6 | "@typescript-eslint" 7 | ], 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "parserOptions": { 14 | "sourceType": "module" 15 | }, 16 | "rules": { 17 | "no-unused-vars": "off", 18 | "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], 19 | "@typescript-eslint/ban-ts-comment": "off", 20 | "no-prototype-builtins": "off", 21 | "@typescript-eslint/no-empty-function": "off" 22 | } 23 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Obsidian plugin 2 | 3 | on: 4 | push: 5 | # Sequence of patterns matched against refs/tags 6 | tags: 7 | - "*" # Push events to matching any tag format, i.e. 1.0, 20.15.10 8 | 9 | env: 10 | PLUGIN_NAME: obsidian-custom-icons 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Use Node.js 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: "16.x" # You might need to adjust this value to your own version 22 | - name: Build 23 | id: build 24 | run: | 25 | npm install -g yarn 26 | yarn 27 | yarn run build --if-present 28 | mkdir ${{ env.PLUGIN_NAME }} 29 | cp main.js manifest.json styles.css ${{ env.PLUGIN_NAME }} 30 | zip -r ${{ env.PLUGIN_NAME }}.zip ${{ env.PLUGIN_NAME }} 31 | ls 32 | echo "::set-output name=tag_name::$(git tag --sort version:refname | tail -n 1)" 33 | 34 | - name: Create Release 35 | id: create_release 36 | uses: actions/create-release@v1 37 | env: 38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 39 | VERSION: ${{ github.ref }} 40 | with: 41 | tag_name: ${{ github.ref }} 42 | release_name: ${{ github.ref }} 43 | draft: false 44 | prerelease: ${{ contains(github.ref, 'b') && true || false }} 45 | 46 | - name: Upload zip file 47 | id: upload-zip 48 | uses: actions/upload-release-asset@v1 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | with: 52 | upload_url: ${{ steps.create_release.outputs.upload_url }} 53 | asset_path: ./${{ env.PLUGIN_NAME }}.zip 54 | asset_name: ${{ env.PLUGIN_NAME }}-${{ steps.build.outputs.tag_name }}.zip 55 | asset_content_type: application/zip 56 | 57 | - name: Upload main.js 58 | id: upload-main 59 | uses: actions/upload-release-asset@v1 60 | env: 61 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 62 | with: 63 | upload_url: ${{ steps.create_release.outputs.upload_url }} 64 | asset_path: ./main.js 65 | asset_name: main.js 66 | asset_content_type: text/javascript 67 | 68 | - name: Upload manifest.json 69 | id: upload-manifest 70 | uses: actions/upload-release-asset@v1 71 | env: 72 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 73 | with: 74 | upload_url: ${{ steps.create_release.outputs.upload_url }} 75 | asset_path: ./manifest.json 76 | asset_name: manifest.json 77 | asset_content_type: application/json 78 | 79 | - name: Upload styles.css 80 | id: upload-styles 81 | uses: actions/upload-release-asset@v1 82 | env: 83 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 84 | with: 85 | upload_url: ${{ steps.create_release.outputs.upload_url }} 86 | asset_path: ./styles.css 87 | asset_name: styles.css 88 | asset_content_type: text/css -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # vscode 2 | .vscode 3 | 4 | # Intellij 5 | *.iml 6 | .idea 7 | 8 | # npm 9 | node_modules 10 | 11 | # Don't include the compiled main.js file in the repo. 12 | # They should be uploaded to GitHub releases instead. 13 | main.js 14 | 15 | # Exclude sourcemaps 16 | *.map 17 | 18 | # obsidian 19 | data.json 20 | 21 | # Exclude macOS Finder (System Explorer) View States 22 | .DS_Store 23 | 24 | # other 25 | *.bat 26 | *.zip 27 | .env 28 | dist -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | tag-version-prefix="" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 RavenHogWarts 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. 22 | -------------------------------------------------------------------------------- /MAKEFILE: -------------------------------------------------------------------------------- 1 | push: 2 | @git tag "$(tag)" 3 | @git push origin "$(tag)" 4 | 5 | del: 6 | @git tag -d "$(tag)" 7 | @git push origin --delete "$(tag)" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Custom Icons 2 | 3 | Enhance your workspace with customizable icons for documents and folders. 4 | 5 |
6 | 7 | ![Obsidian Downloads](https://img.shields.io/badge/dynamic/json?logo=obsidian&color=%23483699&label=downloads&query=%24%5B%22custom-sidebar-icons%22%5D.downloads&url=https%3A%2F%2Fraw.githubusercontent.com%2Fobsidianmd%2Fobsidian-releases%2Fmaster%2Fcommunity-plugin-stats.json) 8 | ![GitHub stars](https://img.shields.io/github/stars/RavenHogWarts/obsidian-custom-icons?style=flat) 9 | ![latest download](https://img.shields.io/github/downloads/RavenHogWarts/obsidian-custom-icons/latest/total?style=plastic) 10 | [![Github release](https://img.shields.io/github/manifest-json/v/RavenHogWarts/obsidian-custom-icons?color=blue)](https://github.com/RavenHogWarts/obsidian-custom-icons/releases/latest) 11 | ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/RavenHogWarts/obsidian-custom-icons?include_prereleases&label=BRAT%20beta) 12 | 13 | [中文](https://github.com/RavenHogWarts/obsidian-custom-icons/blob/master/README_ZH.md) | [English](README.md) 14 | 15 |
16 | 17 | ## Usage 18 | 19 | Currently, there are two ways to set the icons: 20 | 21 | - Custom: This includes using online URLs, local relative or absolute file paths, Base64 encodings, or SVG tags. 22 | - Lucide icons: This method requires only the name of the icon from [Lucide](https://lucide.dev/icons/). Note that the official Obsidian icons also use Lucide icons. 23 | 24 | ### Examples 25 | 26 | - Online URL: `https://www.example.com/favicon.ico` 27 | - Local images: 28 | - Relative path: `.obsidian/svg/example.svg` 29 | - Absolute path (Unix-style): `/Users/YourUsername/Pictures/example.jpg` 30 | - Absolute path (Windows-style): `D:\Pictures\example.png` 31 | - Base64 encoding: Starting with `data:` 32 | - SVG tags: Enclosed within `` tags 33 | - Lucide source icons: Directly use the icon name from Lucide. 34 | 35 | ![Usage](attachment/Usage_EN.png) 36 | 37 | ## Installation 38 | 39 | ### Install from Community Plugins 40 | 41 | [Click to install](obsidian://show-plugin?id=custom-sidebar-icons), or: 42 | 43 | 1. Open Obsidian and go to `Settings > Community Plugins`. 44 | 2. Search for "Custom Icons". 45 | 3. Click "Install". 46 | 47 | ### Install via BRAT Plugin 48 | 49 | 1. Install the [BRAT plugin](obsidian://show-plugin?id=obsidian42-brat) from Community Plugins. 50 | 2. In the BRAT plugin settings, click "Add Beta Plugin". 51 | 3. Enter the URL `https://github.com/RavenHogWarts/obsidian-custom-icons`. 52 | 4. Enable "Custom Icons" in "Third-party Plugins". 53 | 54 | ### Manual Installation 55 | 56 | 1. Download the latest release from [Releases](https://github.com/RavenHogWarts/obsidian-custom-icons/releases/latest). 57 | 2. Copy `main.js`, `styles.css` and `manifest.json` to `VaultFolder/.obsidian/plugins/custom-sidebar-icons/`. 58 | 3. Reload plugins and enable "Custom Icons" in "Third-party Plugins". 59 | 60 | ## How to Build 61 | 62 | 1. Clone the repository: `git clone https://github.com/RavenHogWarts/obsidian-custom-icons`. 63 | 2. Install dependencies: `npm install`. 64 | 3. Start development: `npm run dev`. 65 | 4. Build for production: `npm run build`. 66 | 67 | ## License 68 | 69 | [Custom Icons](https://github.com/RavenHogWarts/obsidian-custom-icons) is licensed under the MIT License. See [LICENSE](https://github.com/RavenHogWarts/obsidian-custom-icons/blob/master/LICENSE) for more information. 70 | 71 | ## Acknowledgements 72 | 73 | - [obsidian-metadata-icon](https://github.com/Benature/obsidian-metadata-icon) 74 | - [Templater](https://github.com/SilentVoid13/Templater) 75 | 76 | ## Support 77 | 78 | If you find this plugin useful and wish to support its development, you can do so through the following methods: WeChat, Alipay, [Love Power Donation](https://afdian.net/a/ravenhogwarts) or [Paypal](https://www.paypal.com/paypalme/RavenHogwarts). Any amount of support is appreciated. Thank you! 79 | 80 |

81 | 82 |

-------------------------------------------------------------------------------- /README_ZH.md: -------------------------------------------------------------------------------- 1 | # 自定义图标 2 | 3 | 通过为文档和文件夹设置可自定义的图标,增强您的工作空间美观及易用性。 4 | 5 |
6 | 7 | ![Obsidian 下载量](https://img.shields.io/badge/dynamic/json?logo=obsidian&color=%23483699&label=downloads&query=%24%5B%22custom-sidebar-icons%22%5D.downloads&url=https%3A%2F%2Fraw.githubusercontent.com%2Fobsidianmd%2Fobsidian-releases%2Fmaster%2Fcommunity-plugin-stats.json) 8 | ![GitHub 星标](https://img.shields.io/github/stars/RavenHogWarts/obsidian-custom-icons?style=flat) 9 | ![最新下载](https://img.shields.io/github/downloads/RavenHogWarts/obsidian-custom-icons/latest/total?style=plastic) 10 | [![Github 发布](https://img.shields.io/github/manifest-json/v/RavenHogWarts/obsidian-custom-icons?color=blue)](https://github.com/RavenHogWarts/obsidian-custom-icons/releases/latest) 11 | ![GitHub 发布(包括预发布的最新日期)](https://img.shields.io/github/v/release/RavenHogWarts/obsidian-custom-icons?include_prereleases&label=BRAT%20beta) 12 | 13 | [中文](README_ZH.md) | [English](https://github.com/RavenHogWarts/obsidian-custom-icons/blob/master/README.md) 14 | 15 |
16 | 17 | ## 使用方法 18 | 19 | 目前,有两种设置图标的方法: 20 | - 自定义:包括使用在线 URL、本地相对(绝对)文件路径、Base64 编码或 SVG 标签。 21 | - Lucide 图标:此方法仅需从 [Lucide](https://lucide.dev/icons/) 获取图标名称。值得注意的是,官方图标也使用 Lucide 图标。 22 | 23 | ### 示例 24 | 25 | - 在线 URL:`https://www.example.com/favicon.ico` 26 | - 本地图片: 27 | - 相对路径:`.obsidian/svg/example.svg` 28 | - 绝对路径(Unix 风格):`/Users/YourUsername/Pictures/example.jpg` 29 | - 绝对路径(Windows 风格):`D:\Pictures\example.png` 30 | - Base64 编码:以 `data:` 开头 31 | - SVG 标签:包裹在 `` 标签内 32 | - Lucide 源图标:直接使用来自 Lucide 的图标名称。 33 | 34 | ![使用方法](attachment/Usage_CN.png) 35 | 36 | ## 安装方法 37 | 38 | ### 从社区插件安装 39 | 40 | [点击安装](obsidian://show-plugin?id=custom-sidebar-icons),或按以下步骤操作: 41 | 42 | 1. 打开 Obsidian 并前往 `设置 > 第三方插件`。 43 | 2. 搜索 “Custom Icons”。 44 | 3. 点击 “安装”。 45 | 46 | ### 通过 BRAT 插件安装 47 | 48 | 1. 从社区插件中安装 [BRAT 插件](obsidian://show-plugin?id=obsidian42-brat)。 49 | 2. 在 BRAT 插件设置中,点击 "Add Beta Plugin"。 50 | 3. 输入 URL `https://github.com/RavenHogWarts/obsidian-custom-icons`。 51 | 4. 在 “第三方插件” 中启用 “Custom Icons”。 52 | 53 | ### 手动安装 54 | 55 | 1. 从 [发布页面](https://github.com/RavenHogWarts/obsidian-custom-icons/releases/latest) 下载最新发布版本。 56 | 2. 复制 `main.js`,`styles.css` 和 `manifest.json` 到您的仓库文件夹 `VaultFolder/.obsidian/plugins/custom-sidebar-icons/`。 57 | 3. 重新加载插件并在 “第三方插件” 中启用 “Custom Icons”。 58 | 59 | ## 如何构建 60 | 61 | 1. 克隆仓库:`git clone https://github.com/RavenHogWarts/obsidian-custom-icons`。 62 | 2. 安装依赖:`npm install`。 63 | 3. 开始开发:`npm run dev`。 64 | 4. 为生产环境构建:`npm run build`。 65 | 66 | ## 许可证 67 | 68 | [Custom Icons](https://github.com/RavenHogWarts/obsidian-custom-icons) 采用 MIT 许可证。更多信息请查看 [LICENSE](https://github.com/RavenHogWarts/obsidian-custom-icons/blob/master/LICENSE)。 69 | 70 | ## 鸣谢 71 | 72 | - [obsidian-metadata-icon](https://github.com/Benature/obsidian-metadata-icon) 73 | - [Templater](https://github.com/SilentVoid13/Templater) 74 | 75 | ## 支持 76 | 77 | 如果您觉得这个插件有用,并希望支持其开发,您可以通过以下方式赞助我:微信,支付宝,[爱发电](https://afdian.net/a/ravenhogwarts) 或 [Paypal](https://www.paypal.com/paypalme/RavenHogwarts)。感谢您的任何支持! 78 | 79 |

80 | 81 |

-------------------------------------------------------------------------------- /attachment/Usage_CN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RavenHogWarts/obsidian-custom-icons/2151799f1e9ab86d64e48540e8dddc962f1f8aaf/attachment/Usage_CN.png -------------------------------------------------------------------------------- /attachment/Usage_EN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RavenHogWarts/obsidian-custom-icons/2151799f1e9ab86d64e48540e8dddc962f1f8aaf/attachment/Usage_EN.png -------------------------------------------------------------------------------- /manifest-beta.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "custom-sidebar-icons", 3 | "name": "Custom Icons", 4 | "version": "0.6.3", 5 | "minAppVersion": "1.5.0", 6 | "description": "Enhance your workspace with customizable icons for documents and folders.", 7 | "author": "RavenHogWarts", 8 | "authorUrl": "https://github.com/RavenHogWarts", 9 | "fundingUrl": { 10 | "爱发电": "https://afdian.net/a/ravenhogwarts", 11 | "微信/支付宝": "https://s2.loli.net/2024/05/06/lWBj3ObszUXSV2f.png", 12 | "paypal": "https://www.paypal.com/paypalme/RavenHogwarts" 13 | }, 14 | "isDesktopOnly": false 15 | } 16 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "custom-sidebar-icons", 3 | "name": "Custom Icons", 4 | "version": "0.6.2", 5 | "minAppVersion": "1.5.0", 6 | "description": "Enhance your workspace with customizable icons for documents and folders.", 7 | "author": "RavenHogWarts", 8 | "authorUrl": "https://github.com/RavenHogWarts", 9 | "fundingUrl": { 10 | "爱发电": "https://afdian.net/a/ravenhogwarts", 11 | "微信/支付宝": "https://s2.loli.net/2024/05/06/lWBj3ObszUXSV2f.png", 12 | "paypal": "https://www.paypal.com/paypalme/RavenHogwarts" 13 | }, 14 | "isDesktopOnly": false 15 | } 16 | -------------------------------------------------------------------------------- /md/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | ## Version 0.6.3 (2024-05-29) 3 | - [feature] 设置的lucide图标可以自适应当前基础颜色 [#5](https://github.com/RavenHogWarts/obsidian-custom-icons/issues/5) [#13](https://github.com/RavenHogWarts/obsidian-custom-icons/issues/13) 4 | - [fix] bug: "Faild to unload plugin custom-sidebar-icons" 5 | 6 | ## Version 0.6.2 (2024-05-14) 7 | - [feature] 支持显示内部链接的文件图标 [#12](https://github.com/RavenHogWarts/obsidian-custom-icons/issues/12) 8 | - [changed] 插件设置界面UI修改 9 | - [updated] pin在侧边的文件如果锁定,锁定的图标会被隐藏 10 | 11 | ## Version 0.6.1 (2024-05-06) 12 | - [updated] 文件图标修改功能可同时为多个后缀设置相同图标 [#9](https://github.com/RavenHogWarts/obsidian-custom-icons/issues/9) 13 | - [changed] 修改插件设置about页面 14 | 15 | ## Version 0.6.0 (2024-05-04) 16 | - [changed] 正式修改插件名称为"Custom Icons" 17 | - [feature] 增加修改文件图标功能 [#7](https://github.com/RavenHogWarts/obsidian-custom-icons/issues/7) 18 | - [changed] 修改插件设置界面 19 | 20 | ## Version 0.5.0 (2024-05-03) 21 | - [feature] 增加修改文件夹图标功能 22 | - [changed] 修改数据结构,数据自动从customIcons迁移至SidebarIcons 23 | - [changed] 修改插件设置界面 24 | 25 | ## Version 0.4.0 (2024-04-20) 26 | - [feature] 支持lucide源图标 [#2](https://github.com/RavenHogWarts/obsidian-custom-icons/issues/2) 27 | 28 | ### 0.4.0.1 (2024-04-21) 29 | - [fix] 设置界面补丁 30 | 31 | ## Version 0.3.3 (2024-04-18) 32 | ### 0.3.3.2 33 | - [updated] 增加数据迁移功能,确保用户之前的数据能够使用 34 | 35 | ### 0.3.3.1 36 | - [changed] customIcons增加type类型, CustomIconSettingTab增加Dropdown类型选择 37 | - [fix] bug: 图标后面会叠加图片 38 | 39 | ## Version 0.3.2 (2024-04-10) 40 | - [changed] 依据官方要求优化代码 41 | - [fix] bug: Windows无法使用绝对路径添加图标 42 | 43 | ## Version 0.3.1 (2024-04-04) 44 | - [changed] 优化代码结构,样式修改至styles.css 45 | 46 | ## Version 0.3.0 (2024-04-02) 47 | - [feature] 支持多种图像格式,包括在线URL,本地图像,base64编码和svg标签 48 | - [changed] 数据结构发生变化,需要重新配置插件 49 | - [fix] bug: 在删除多个图标时会导致错误删除对象 50 | 51 | ## Version 0.2.1 (2024-03-27) 52 | - [updated] 支持显示彩色svg图标 53 | 54 | ## Version 0.2.0 (2024-03-26) 55 | - [updated] 新增了svg图标预览功能 56 | 57 | ## Version 0.1.0 (2024-03-25) 58 | - [feature] 基础功能:修改侧边栏图标 -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-sidebar-icons", 3 | "version": "0.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "custom-sidebar-icons", 9 | "version": "0.1.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@popperjs/core": "^2.11.8", 13 | "dotenv": "^16.4.5", 14 | "lucide-static": "^0.372.0" 15 | }, 16 | "devDependencies": { 17 | "@types/node": "^16.11.6", 18 | "@typescript-eslint/eslint-plugin": "5.29.0", 19 | "@typescript-eslint/parser": "5.29.0", 20 | "builtin-modules": "3.3.0", 21 | "esbuild": "0.17.3", 22 | "obsidian": "latest", 23 | "tslib": "2.4.0", 24 | "typescript": "4.7.4" 25 | } 26 | }, 27 | "node_modules/@codemirror/state": { 28 | "version": "6.4.1", 29 | "resolved": "https://registry.npmmirror.com/@codemirror/state/-/state-6.4.1.tgz", 30 | "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==", 31 | "dev": true, 32 | "peer": true 33 | }, 34 | "node_modules/@codemirror/view": { 35 | "version": "6.26.3", 36 | "resolved": "https://registry.npmmirror.com/@codemirror/view/-/view-6.26.3.tgz", 37 | "integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==", 38 | "dev": true, 39 | "peer": true, 40 | "dependencies": { 41 | "@codemirror/state": "^6.4.0", 42 | "style-mod": "^4.1.0", 43 | "w3c-keyname": "^2.2.4" 44 | } 45 | }, 46 | "node_modules/@esbuild/android-arm": { 47 | "version": "0.17.3", 48 | "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.17.3.tgz", 49 | "integrity": "sha512-1Mlz934GvbgdDmt26rTLmf03cAgLg5HyOgJN+ZGCeP3Q9ynYTNMn2/LQxIl7Uy+o4K6Rfi2OuLsr12JQQR8gNg==", 50 | "cpu": [ 51 | "arm" 52 | ], 53 | "dev": true, 54 | "optional": true, 55 | "os": [ 56 | "android" 57 | ], 58 | "engines": { 59 | "node": ">=12" 60 | } 61 | }, 62 | "node_modules/@esbuild/android-arm64": { 63 | "version": "0.17.3", 64 | "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.17.3.tgz", 65 | "integrity": "sha512-XvJsYo3dO3Pi4kpalkyMvfQsjxPWHYjoX4MDiB/FUM4YMfWcXa5l4VCwFWVYI1+92yxqjuqrhNg0CZg3gSouyQ==", 66 | "cpu": [ 67 | "arm64" 68 | ], 69 | "dev": true, 70 | "optional": true, 71 | "os": [ 72 | "android" 73 | ], 74 | "engines": { 75 | "node": ">=12" 76 | } 77 | }, 78 | "node_modules/@esbuild/android-x64": { 79 | "version": "0.17.3", 80 | "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.17.3.tgz", 81 | "integrity": "sha512-nuV2CmLS07Gqh5/GrZLuqkU9Bm6H6vcCspM+zjp9TdQlxJtIe+qqEXQChmfc7nWdyr/yz3h45Utk1tUn8Cz5+A==", 82 | "cpu": [ 83 | "x64" 84 | ], 85 | "dev": true, 86 | "optional": true, 87 | "os": [ 88 | "android" 89 | ], 90 | "engines": { 91 | "node": ">=12" 92 | } 93 | }, 94 | "node_modules/@esbuild/darwin-arm64": { 95 | "version": "0.17.3", 96 | "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.3.tgz", 97 | "integrity": "sha512-01Hxaaat6m0Xp9AXGM8mjFtqqwDjzlMP0eQq9zll9U85ttVALGCGDuEvra5Feu/NbP5AEP1MaopPwzsTcUq1cw==", 98 | "cpu": [ 99 | "arm64" 100 | ], 101 | "dev": true, 102 | "optional": true, 103 | "os": [ 104 | "darwin" 105 | ], 106 | "engines": { 107 | "node": ">=12" 108 | } 109 | }, 110 | "node_modules/@esbuild/darwin-x64": { 111 | "version": "0.17.3", 112 | "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.17.3.tgz", 113 | "integrity": "sha512-Eo2gq0Q/er2muf8Z83X21UFoB7EU6/m3GNKvrhACJkjVThd0uA+8RfKpfNhuMCl1bKRfBzKOk6xaYKQZ4lZqvA==", 114 | "cpu": [ 115 | "x64" 116 | ], 117 | "dev": true, 118 | "optional": true, 119 | "os": [ 120 | "darwin" 121 | ], 122 | "engines": { 123 | "node": ">=12" 124 | } 125 | }, 126 | "node_modules/@esbuild/freebsd-arm64": { 127 | "version": "0.17.3", 128 | "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.3.tgz", 129 | "integrity": "sha512-CN62ESxaquP61n1ZjQP/jZte8CE09M6kNn3baos2SeUfdVBkWN5n6vGp2iKyb/bm/x4JQzEvJgRHLGd5F5b81w==", 130 | "cpu": [ 131 | "arm64" 132 | ], 133 | "dev": true, 134 | "optional": true, 135 | "os": [ 136 | "freebsd" 137 | ], 138 | "engines": { 139 | "node": ">=12" 140 | } 141 | }, 142 | "node_modules/@esbuild/freebsd-x64": { 143 | "version": "0.17.3", 144 | "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.3.tgz", 145 | "integrity": "sha512-feq+K8TxIznZE+zhdVurF3WNJ/Sa35dQNYbaqM/wsCbWdzXr5lyq+AaTUSER2cUR+SXPnd/EY75EPRjf4s1SLg==", 146 | "cpu": [ 147 | "x64" 148 | ], 149 | "dev": true, 150 | "optional": true, 151 | "os": [ 152 | "freebsd" 153 | ], 154 | "engines": { 155 | "node": ">=12" 156 | } 157 | }, 158 | "node_modules/@esbuild/linux-arm": { 159 | "version": "0.17.3", 160 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.17.3.tgz", 161 | "integrity": "sha512-CLP3EgyNuPcg2cshbwkqYy5bbAgK+VhyfMU7oIYyn+x4Y67xb5C5ylxsNUjRmr8BX+MW3YhVNm6Lq6FKtRTWHQ==", 162 | "cpu": [ 163 | "arm" 164 | ], 165 | "dev": true, 166 | "optional": true, 167 | "os": [ 168 | "linux" 169 | ], 170 | "engines": { 171 | "node": ">=12" 172 | } 173 | }, 174 | "node_modules/@esbuild/linux-arm64": { 175 | "version": "0.17.3", 176 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.17.3.tgz", 177 | "integrity": "sha512-JHeZXD4auLYBnrKn6JYJ0o5nWJI9PhChA/Nt0G4MvLaMrvXuWnY93R3a7PiXeJQphpL1nYsaMcoV2QtuvRnF/g==", 178 | "cpu": [ 179 | "arm64" 180 | ], 181 | "dev": true, 182 | "optional": true, 183 | "os": [ 184 | "linux" 185 | ], 186 | "engines": { 187 | "node": ">=12" 188 | } 189 | }, 190 | "node_modules/@esbuild/linux-ia32": { 191 | "version": "0.17.3", 192 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.17.3.tgz", 193 | "integrity": "sha512-FyXlD2ZjZqTFh0sOQxFDiWG1uQUEOLbEh9gKN/7pFxck5Vw0qjWSDqbn6C10GAa1rXJpwsntHcmLqydY9ST9ZA==", 194 | "cpu": [ 195 | "ia32" 196 | ], 197 | "dev": true, 198 | "optional": true, 199 | "os": [ 200 | "linux" 201 | ], 202 | "engines": { 203 | "node": ">=12" 204 | } 205 | }, 206 | "node_modules/@esbuild/linux-loong64": { 207 | "version": "0.17.3", 208 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.17.3.tgz", 209 | "integrity": "sha512-OrDGMvDBI2g7s04J8dh8/I7eSO+/E7nMDT2Z5IruBfUO/RiigF1OF6xoH33Dn4W/OwAWSUf1s2nXamb28ZklTA==", 210 | "cpu": [ 211 | "loong64" 212 | ], 213 | "dev": true, 214 | "optional": true, 215 | "os": [ 216 | "linux" 217 | ], 218 | "engines": { 219 | "node": ">=12" 220 | } 221 | }, 222 | "node_modules/@esbuild/linux-mips64el": { 223 | "version": "0.17.3", 224 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.3.tgz", 225 | "integrity": "sha512-DcnUpXnVCJvmv0TzuLwKBC2nsQHle8EIiAJiJ+PipEVC16wHXaPEKP0EqN8WnBe0TPvMITOUlP2aiL5YMld+CQ==", 226 | "cpu": [ 227 | "mips64el" 228 | ], 229 | "dev": true, 230 | "optional": true, 231 | "os": [ 232 | "linux" 233 | ], 234 | "engines": { 235 | "node": ">=12" 236 | } 237 | }, 238 | "node_modules/@esbuild/linux-ppc64": { 239 | "version": "0.17.3", 240 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.3.tgz", 241 | "integrity": "sha512-BDYf/l1WVhWE+FHAW3FzZPtVlk9QsrwsxGzABmN4g8bTjmhazsId3h127pliDRRu5674k1Y2RWejbpN46N9ZhQ==", 242 | "cpu": [ 243 | "ppc64" 244 | ], 245 | "dev": true, 246 | "optional": true, 247 | "os": [ 248 | "linux" 249 | ], 250 | "engines": { 251 | "node": ">=12" 252 | } 253 | }, 254 | "node_modules/@esbuild/linux-riscv64": { 255 | "version": "0.17.3", 256 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.3.tgz", 257 | "integrity": "sha512-WViAxWYMRIi+prTJTyV1wnqd2mS2cPqJlN85oscVhXdb/ZTFJdrpaqm/uDsZPGKHtbg5TuRX/ymKdOSk41YZow==", 258 | "cpu": [ 259 | "riscv64" 260 | ], 261 | "dev": true, 262 | "optional": true, 263 | "os": [ 264 | "linux" 265 | ], 266 | "engines": { 267 | "node": ">=12" 268 | } 269 | }, 270 | "node_modules/@esbuild/linux-s390x": { 271 | "version": "0.17.3", 272 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.17.3.tgz", 273 | "integrity": "sha512-Iw8lkNHUC4oGP1O/KhumcVy77u2s6+KUjieUqzEU3XuWJqZ+AY7uVMrrCbAiwWTkpQHkr00BuXH5RpC6Sb/7Ug==", 274 | "cpu": [ 275 | "s390x" 276 | ], 277 | "dev": true, 278 | "optional": true, 279 | "os": [ 280 | "linux" 281 | ], 282 | "engines": { 283 | "node": ">=12" 284 | } 285 | }, 286 | "node_modules/@esbuild/linux-x64": { 287 | "version": "0.17.3", 288 | "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.17.3.tgz", 289 | "integrity": "sha512-0AGkWQMzeoeAtXQRNB3s4J1/T2XbigM2/Mn2yU1tQSmQRmHIZdkGbVq2A3aDdNslPyhb9/lH0S5GMTZ4xsjBqg==", 290 | "cpu": [ 291 | "x64" 292 | ], 293 | "dev": true, 294 | "optional": true, 295 | "os": [ 296 | "linux" 297 | ], 298 | "engines": { 299 | "node": ">=12" 300 | } 301 | }, 302 | "node_modules/@esbuild/netbsd-x64": { 303 | "version": "0.17.3", 304 | "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.3.tgz", 305 | "integrity": "sha512-4+rR/WHOxIVh53UIQIICryjdoKdHsFZFD4zLSonJ9RRw7bhKzVyXbnRPsWSfwybYqw9sB7ots/SYyufL1mBpEg==", 306 | "cpu": [ 307 | "x64" 308 | ], 309 | "dev": true, 310 | "optional": true, 311 | "os": [ 312 | "netbsd" 313 | ], 314 | "engines": { 315 | "node": ">=12" 316 | } 317 | }, 318 | "node_modules/@esbuild/openbsd-x64": { 319 | "version": "0.17.3", 320 | "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.3.tgz", 321 | "integrity": "sha512-cVpWnkx9IYg99EjGxa5Gc0XmqumtAwK3aoz7O4Dii2vko+qXbkHoujWA68cqXjhh6TsLaQelfDO4MVnyr+ODeA==", 322 | "cpu": [ 323 | "x64" 324 | ], 325 | "dev": true, 326 | "optional": true, 327 | "os": [ 328 | "openbsd" 329 | ], 330 | "engines": { 331 | "node": ">=12" 332 | } 333 | }, 334 | "node_modules/@esbuild/sunos-x64": { 335 | "version": "0.17.3", 336 | "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.17.3.tgz", 337 | "integrity": "sha512-RxmhKLbTCDAY2xOfrww6ieIZkZF+KBqG7S2Ako2SljKXRFi+0863PspK74QQ7JpmWwncChY25JTJSbVBYGQk2Q==", 338 | "cpu": [ 339 | "x64" 340 | ], 341 | "dev": true, 342 | "optional": true, 343 | "os": [ 344 | "sunos" 345 | ], 346 | "engines": { 347 | "node": ">=12" 348 | } 349 | }, 350 | "node_modules/@esbuild/win32-arm64": { 351 | "version": "0.17.3", 352 | "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.17.3.tgz", 353 | "integrity": "sha512-0r36VeEJ4efwmofxVJRXDjVRP2jTmv877zc+i+Pc7MNsIr38NfsjkQj23AfF7l0WbB+RQ7VUb+LDiqC/KY/M/A==", 354 | "cpu": [ 355 | "arm64" 356 | ], 357 | "dev": true, 358 | "optional": true, 359 | "os": [ 360 | "win32" 361 | ], 362 | "engines": { 363 | "node": ">=12" 364 | } 365 | }, 366 | "node_modules/@esbuild/win32-ia32": { 367 | "version": "0.17.3", 368 | "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.17.3.tgz", 369 | "integrity": "sha512-wgO6rc7uGStH22nur4aLFcq7Wh86bE9cOFmfTr/yxN3BXvDEdCSXyKkO+U5JIt53eTOgC47v9k/C1bITWL/Teg==", 370 | "cpu": [ 371 | "ia32" 372 | ], 373 | "dev": true, 374 | "optional": true, 375 | "os": [ 376 | "win32" 377 | ], 378 | "engines": { 379 | "node": ">=12" 380 | } 381 | }, 382 | "node_modules/@esbuild/win32-x64": { 383 | "version": "0.17.3", 384 | "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.17.3.tgz", 385 | "integrity": "sha512-FdVl64OIuiKjgXBjwZaJLKp0eaEckifbhn10dXWhysMJkWblg3OEEGKSIyhiD5RSgAya8WzP3DNkngtIg3Nt7g==", 386 | "cpu": [ 387 | "x64" 388 | ], 389 | "dev": true, 390 | "optional": true, 391 | "os": [ 392 | "win32" 393 | ], 394 | "engines": { 395 | "node": ">=12" 396 | } 397 | }, 398 | "node_modules/@eslint-community/eslint-utils": { 399 | "version": "4.4.0", 400 | "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", 401 | "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", 402 | "dev": true, 403 | "peer": true, 404 | "dependencies": { 405 | "eslint-visitor-keys": "^3.3.0" 406 | }, 407 | "engines": { 408 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 409 | }, 410 | "peerDependencies": { 411 | "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" 412 | } 413 | }, 414 | "node_modules/@eslint-community/regexpp": { 415 | "version": "4.10.0", 416 | "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", 417 | "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", 418 | "dev": true, 419 | "peer": true, 420 | "engines": { 421 | "node": "^12.0.0 || ^14.0.0 || >=16.0.0" 422 | } 423 | }, 424 | "node_modules/@eslint/eslintrc": { 425 | "version": "2.1.4", 426 | "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", 427 | "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", 428 | "dev": true, 429 | "peer": true, 430 | "dependencies": { 431 | "ajv": "^6.12.4", 432 | "debug": "^4.3.2", 433 | "espree": "^9.6.0", 434 | "globals": "^13.19.0", 435 | "ignore": "^5.2.0", 436 | "import-fresh": "^3.2.1", 437 | "js-yaml": "^4.1.0", 438 | "minimatch": "^3.1.2", 439 | "strip-json-comments": "^3.1.1" 440 | }, 441 | "engines": { 442 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 443 | }, 444 | "funding": { 445 | "url": "https://opencollective.com/eslint" 446 | } 447 | }, 448 | "node_modules/@eslint/js": { 449 | "version": "8.57.0", 450 | "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-8.57.0.tgz", 451 | "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", 452 | "dev": true, 453 | "peer": true, 454 | "engines": { 455 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 456 | } 457 | }, 458 | "node_modules/@humanwhocodes/config-array": { 459 | "version": "0.11.14", 460 | "resolved": "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", 461 | "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", 462 | "dev": true, 463 | "peer": true, 464 | "dependencies": { 465 | "@humanwhocodes/object-schema": "^2.0.2", 466 | "debug": "^4.3.1", 467 | "minimatch": "^3.0.5" 468 | }, 469 | "engines": { 470 | "node": ">=10.10.0" 471 | } 472 | }, 473 | "node_modules/@humanwhocodes/module-importer": { 474 | "version": "1.0.1", 475 | "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 476 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 477 | "dev": true, 478 | "peer": true, 479 | "engines": { 480 | "node": ">=12.22" 481 | } 482 | }, 483 | "node_modules/@humanwhocodes/object-schema": { 484 | "version": "2.0.3", 485 | "resolved": "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", 486 | "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", 487 | "dev": true, 488 | "peer": true 489 | }, 490 | "node_modules/@nodelib/fs.scandir": { 491 | "version": "2.1.5", 492 | "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 493 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 494 | "dev": true, 495 | "dependencies": { 496 | "@nodelib/fs.stat": "2.0.5", 497 | "run-parallel": "^1.1.9" 498 | }, 499 | "engines": { 500 | "node": ">= 8" 501 | } 502 | }, 503 | "node_modules/@nodelib/fs.stat": { 504 | "version": "2.0.5", 505 | "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 506 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 507 | "dev": true, 508 | "engines": { 509 | "node": ">= 8" 510 | } 511 | }, 512 | "node_modules/@nodelib/fs.walk": { 513 | "version": "1.2.8", 514 | "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 515 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 516 | "dev": true, 517 | "dependencies": { 518 | "@nodelib/fs.scandir": "2.1.5", 519 | "fastq": "^1.6.0" 520 | }, 521 | "engines": { 522 | "node": ">= 8" 523 | } 524 | }, 525 | "node_modules/@popperjs/core": { 526 | "version": "2.11.8", 527 | "resolved": "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.8.tgz", 528 | "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", 529 | "funding": { 530 | "type": "opencollective", 531 | "url": "https://opencollective.com/popperjs" 532 | } 533 | }, 534 | "node_modules/@types/codemirror": { 535 | "version": "5.60.8", 536 | "resolved": "https://registry.npmmirror.com/@types/codemirror/-/codemirror-5.60.8.tgz", 537 | "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==", 538 | "dev": true, 539 | "dependencies": { 540 | "@types/tern": "*" 541 | } 542 | }, 543 | "node_modules/@types/estree": { 544 | "version": "1.0.5", 545 | "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz", 546 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", 547 | "dev": true 548 | }, 549 | "node_modules/@types/json-schema": { 550 | "version": "7.0.15", 551 | "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", 552 | "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", 553 | "dev": true 554 | }, 555 | "node_modules/@types/node": { 556 | "version": "16.18.97", 557 | "resolved": "https://registry.npmmirror.com/@types/node/-/node-16.18.97.tgz", 558 | "integrity": "sha512-4muilE1Lbfn57unR+/nT9AFjWk0MtWi5muwCEJqnOvfRQDbSfLCUdN7vCIg8TYuaANfhLOV85ve+FNpiUsbSRg==", 559 | "dev": true 560 | }, 561 | "node_modules/@types/tern": { 562 | "version": "0.23.9", 563 | "resolved": "https://registry.npmmirror.com/@types/tern/-/tern-0.23.9.tgz", 564 | "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", 565 | "dev": true, 566 | "dependencies": { 567 | "@types/estree": "*" 568 | } 569 | }, 570 | "node_modules/@typescript-eslint/eslint-plugin": { 571 | "version": "5.29.0", 572 | "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz", 573 | "integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==", 574 | "dev": true, 575 | "dependencies": { 576 | "@typescript-eslint/scope-manager": "5.29.0", 577 | "@typescript-eslint/type-utils": "5.29.0", 578 | "@typescript-eslint/utils": "5.29.0", 579 | "debug": "^4.3.4", 580 | "functional-red-black-tree": "^1.0.1", 581 | "ignore": "^5.2.0", 582 | "regexpp": "^3.2.0", 583 | "semver": "^7.3.7", 584 | "tsutils": "^3.21.0" 585 | }, 586 | "engines": { 587 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 588 | }, 589 | "funding": { 590 | "type": "opencollective", 591 | "url": "https://opencollective.com/typescript-eslint" 592 | }, 593 | "peerDependencies": { 594 | "@typescript-eslint/parser": "^5.0.0", 595 | "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" 596 | }, 597 | "peerDependenciesMeta": { 598 | "typescript": { 599 | "optional": true 600 | } 601 | } 602 | }, 603 | "node_modules/@typescript-eslint/parser": { 604 | "version": "5.29.0", 605 | "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.29.0.tgz", 606 | "integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", 607 | "dev": true, 608 | "dependencies": { 609 | "@typescript-eslint/scope-manager": "5.29.0", 610 | "@typescript-eslint/types": "5.29.0", 611 | "@typescript-eslint/typescript-estree": "5.29.0", 612 | "debug": "^4.3.4" 613 | }, 614 | "engines": { 615 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 616 | }, 617 | "funding": { 618 | "type": "opencollective", 619 | "url": "https://opencollective.com/typescript-eslint" 620 | }, 621 | "peerDependencies": { 622 | "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" 623 | }, 624 | "peerDependenciesMeta": { 625 | "typescript": { 626 | "optional": true 627 | } 628 | } 629 | }, 630 | "node_modules/@typescript-eslint/scope-manager": { 631 | "version": "5.29.0", 632 | "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", 633 | "integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", 634 | "dev": true, 635 | "dependencies": { 636 | "@typescript-eslint/types": "5.29.0", 637 | "@typescript-eslint/visitor-keys": "5.29.0" 638 | }, 639 | "engines": { 640 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 641 | }, 642 | "funding": { 643 | "type": "opencollective", 644 | "url": "https://opencollective.com/typescript-eslint" 645 | } 646 | }, 647 | "node_modules/@typescript-eslint/type-utils": { 648 | "version": "5.29.0", 649 | "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", 650 | "integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==", 651 | "dev": true, 652 | "dependencies": { 653 | "@typescript-eslint/utils": "5.29.0", 654 | "debug": "^4.3.4", 655 | "tsutils": "^3.21.0" 656 | }, 657 | "engines": { 658 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 659 | }, 660 | "funding": { 661 | "type": "opencollective", 662 | "url": "https://opencollective.com/typescript-eslint" 663 | }, 664 | "peerDependencies": { 665 | "eslint": "*" 666 | }, 667 | "peerDependenciesMeta": { 668 | "typescript": { 669 | "optional": true 670 | } 671 | } 672 | }, 673 | "node_modules/@typescript-eslint/types": { 674 | "version": "5.29.0", 675 | "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-5.29.0.tgz", 676 | "integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", 677 | "dev": true, 678 | "engines": { 679 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 680 | }, 681 | "funding": { 682 | "type": "opencollective", 683 | "url": "https://opencollective.com/typescript-eslint" 684 | } 685 | }, 686 | "node_modules/@typescript-eslint/typescript-estree": { 687 | "version": "5.29.0", 688 | "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", 689 | "integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", 690 | "dev": true, 691 | "dependencies": { 692 | "@typescript-eslint/types": "5.29.0", 693 | "@typescript-eslint/visitor-keys": "5.29.0", 694 | "debug": "^4.3.4", 695 | "globby": "^11.1.0", 696 | "is-glob": "^4.0.3", 697 | "semver": "^7.3.7", 698 | "tsutils": "^3.21.0" 699 | }, 700 | "engines": { 701 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 702 | }, 703 | "funding": { 704 | "type": "opencollective", 705 | "url": "https://opencollective.com/typescript-eslint" 706 | }, 707 | "peerDependenciesMeta": { 708 | "typescript": { 709 | "optional": true 710 | } 711 | } 712 | }, 713 | "node_modules/@typescript-eslint/utils": { 714 | "version": "5.29.0", 715 | "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-5.29.0.tgz", 716 | "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", 717 | "dev": true, 718 | "dependencies": { 719 | "@types/json-schema": "^7.0.9", 720 | "@typescript-eslint/scope-manager": "5.29.0", 721 | "@typescript-eslint/types": "5.29.0", 722 | "@typescript-eslint/typescript-estree": "5.29.0", 723 | "eslint-scope": "^5.1.1", 724 | "eslint-utils": "^3.0.0" 725 | }, 726 | "engines": { 727 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 728 | }, 729 | "funding": { 730 | "type": "opencollective", 731 | "url": "https://opencollective.com/typescript-eslint" 732 | }, 733 | "peerDependencies": { 734 | "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" 735 | } 736 | }, 737 | "node_modules/@typescript-eslint/visitor-keys": { 738 | "version": "5.29.0", 739 | "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", 740 | "integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", 741 | "dev": true, 742 | "dependencies": { 743 | "@typescript-eslint/types": "5.29.0", 744 | "eslint-visitor-keys": "^3.3.0" 745 | }, 746 | "engines": { 747 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 748 | }, 749 | "funding": { 750 | "type": "opencollective", 751 | "url": "https://opencollective.com/typescript-eslint" 752 | } 753 | }, 754 | "node_modules/@ungap/structured-clone": { 755 | "version": "1.2.0", 756 | "resolved": "https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", 757 | "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", 758 | "dev": true, 759 | "peer": true 760 | }, 761 | "node_modules/acorn": { 762 | "version": "8.11.3", 763 | "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.11.3.tgz", 764 | "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", 765 | "dev": true, 766 | "peer": true, 767 | "bin": { 768 | "acorn": "bin/acorn" 769 | }, 770 | "engines": { 771 | "node": ">=0.4.0" 772 | } 773 | }, 774 | "node_modules/acorn-jsx": { 775 | "version": "5.3.2", 776 | "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 777 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 778 | "dev": true, 779 | "peer": true, 780 | "peerDependencies": { 781 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 782 | } 783 | }, 784 | "node_modules/ajv": { 785 | "version": "6.12.6", 786 | "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", 787 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 788 | "dev": true, 789 | "peer": true, 790 | "dependencies": { 791 | "fast-deep-equal": "^3.1.1", 792 | "fast-json-stable-stringify": "^2.0.0", 793 | "json-schema-traverse": "^0.4.1", 794 | "uri-js": "^4.2.2" 795 | }, 796 | "funding": { 797 | "type": "github", 798 | "url": "https://github.com/sponsors/epoberezkin" 799 | } 800 | }, 801 | "node_modules/ansi-regex": { 802 | "version": "5.0.1", 803 | "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", 804 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 805 | "dev": true, 806 | "peer": true, 807 | "engines": { 808 | "node": ">=8" 809 | } 810 | }, 811 | "node_modules/ansi-styles": { 812 | "version": "4.3.0", 813 | "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", 814 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 815 | "dev": true, 816 | "peer": true, 817 | "dependencies": { 818 | "color-convert": "^2.0.1" 819 | }, 820 | "engines": { 821 | "node": ">=8" 822 | }, 823 | "funding": { 824 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 825 | } 826 | }, 827 | "node_modules/argparse": { 828 | "version": "2.0.1", 829 | "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", 830 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 831 | "dev": true, 832 | "peer": true 833 | }, 834 | "node_modules/array-union": { 835 | "version": "2.1.0", 836 | "resolved": "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz", 837 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 838 | "dev": true, 839 | "engines": { 840 | "node": ">=8" 841 | } 842 | }, 843 | "node_modules/balanced-match": { 844 | "version": "1.0.2", 845 | "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", 846 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 847 | "dev": true, 848 | "peer": true 849 | }, 850 | "node_modules/brace-expansion": { 851 | "version": "1.1.11", 852 | "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", 853 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 854 | "dev": true, 855 | "peer": true, 856 | "dependencies": { 857 | "balanced-match": "^1.0.0", 858 | "concat-map": "0.0.1" 859 | } 860 | }, 861 | "node_modules/braces": { 862 | "version": "3.0.3", 863 | "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", 864 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 865 | "dev": true, 866 | "dependencies": { 867 | "fill-range": "^7.1.1" 868 | }, 869 | "engines": { 870 | "node": ">=8" 871 | } 872 | }, 873 | "node_modules/builtin-modules": { 874 | "version": "3.3.0", 875 | "resolved": "https://registry.npmmirror.com/builtin-modules/-/builtin-modules-3.3.0.tgz", 876 | "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", 877 | "dev": true, 878 | "engines": { 879 | "node": ">=6" 880 | }, 881 | "funding": { 882 | "url": "https://github.com/sponsors/sindresorhus" 883 | } 884 | }, 885 | "node_modules/callsites": { 886 | "version": "3.1.0", 887 | "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", 888 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 889 | "dev": true, 890 | "peer": true, 891 | "engines": { 892 | "node": ">=6" 893 | } 894 | }, 895 | "node_modules/chalk": { 896 | "version": "4.1.2", 897 | "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", 898 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 899 | "dev": true, 900 | "peer": true, 901 | "dependencies": { 902 | "ansi-styles": "^4.1.0", 903 | "supports-color": "^7.1.0" 904 | }, 905 | "engines": { 906 | "node": ">=10" 907 | }, 908 | "funding": { 909 | "url": "https://github.com/chalk/chalk?sponsor=1" 910 | } 911 | }, 912 | "node_modules/color-convert": { 913 | "version": "2.0.1", 914 | "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", 915 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 916 | "dev": true, 917 | "peer": true, 918 | "dependencies": { 919 | "color-name": "~1.1.4" 920 | }, 921 | "engines": { 922 | "node": ">=7.0.0" 923 | } 924 | }, 925 | "node_modules/color-name": { 926 | "version": "1.1.4", 927 | "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", 928 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 929 | "dev": true, 930 | "peer": true 931 | }, 932 | "node_modules/concat-map": { 933 | "version": "0.0.1", 934 | "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", 935 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 936 | "dev": true, 937 | "peer": true 938 | }, 939 | "node_modules/cross-spawn": { 940 | "version": "7.0.3", 941 | "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", 942 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 943 | "dev": true, 944 | "peer": true, 945 | "dependencies": { 946 | "path-key": "^3.1.0", 947 | "shebang-command": "^2.0.0", 948 | "which": "^2.0.1" 949 | }, 950 | "engines": { 951 | "node": ">= 8" 952 | } 953 | }, 954 | "node_modules/debug": { 955 | "version": "4.3.4", 956 | "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", 957 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 958 | "dev": true, 959 | "dependencies": { 960 | "ms": "2.1.2" 961 | }, 962 | "engines": { 963 | "node": ">=6.0" 964 | }, 965 | "peerDependenciesMeta": { 966 | "supports-color": { 967 | "optional": true 968 | } 969 | } 970 | }, 971 | "node_modules/deep-is": { 972 | "version": "0.1.4", 973 | "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", 974 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 975 | "dev": true, 976 | "peer": true 977 | }, 978 | "node_modules/dir-glob": { 979 | "version": "3.0.1", 980 | "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz", 981 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 982 | "dev": true, 983 | "dependencies": { 984 | "path-type": "^4.0.0" 985 | }, 986 | "engines": { 987 | "node": ">=8" 988 | } 989 | }, 990 | "node_modules/doctrine": { 991 | "version": "3.0.0", 992 | "resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz", 993 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 994 | "dev": true, 995 | "peer": true, 996 | "dependencies": { 997 | "esutils": "^2.0.2" 998 | }, 999 | "engines": { 1000 | "node": ">=6.0.0" 1001 | } 1002 | }, 1003 | "node_modules/dotenv": { 1004 | "version": "16.4.5", 1005 | "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.4.5.tgz", 1006 | "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", 1007 | "engines": { 1008 | "node": ">=12" 1009 | }, 1010 | "funding": { 1011 | "url": "https://dotenvx.com" 1012 | } 1013 | }, 1014 | "node_modules/esbuild": { 1015 | "version": "0.17.3", 1016 | "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.17.3.tgz", 1017 | "integrity": "sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g==", 1018 | "dev": true, 1019 | "hasInstallScript": true, 1020 | "bin": { 1021 | "esbuild": "bin/esbuild" 1022 | }, 1023 | "engines": { 1024 | "node": ">=12" 1025 | }, 1026 | "optionalDependencies": { 1027 | "@esbuild/android-arm": "0.17.3", 1028 | "@esbuild/android-arm64": "0.17.3", 1029 | "@esbuild/android-x64": "0.17.3", 1030 | "@esbuild/darwin-arm64": "0.17.3", 1031 | "@esbuild/darwin-x64": "0.17.3", 1032 | "@esbuild/freebsd-arm64": "0.17.3", 1033 | "@esbuild/freebsd-x64": "0.17.3", 1034 | "@esbuild/linux-arm": "0.17.3", 1035 | "@esbuild/linux-arm64": "0.17.3", 1036 | "@esbuild/linux-ia32": "0.17.3", 1037 | "@esbuild/linux-loong64": "0.17.3", 1038 | "@esbuild/linux-mips64el": "0.17.3", 1039 | "@esbuild/linux-ppc64": "0.17.3", 1040 | "@esbuild/linux-riscv64": "0.17.3", 1041 | "@esbuild/linux-s390x": "0.17.3", 1042 | "@esbuild/linux-x64": "0.17.3", 1043 | "@esbuild/netbsd-x64": "0.17.3", 1044 | "@esbuild/openbsd-x64": "0.17.3", 1045 | "@esbuild/sunos-x64": "0.17.3", 1046 | "@esbuild/win32-arm64": "0.17.3", 1047 | "@esbuild/win32-ia32": "0.17.3", 1048 | "@esbuild/win32-x64": "0.17.3" 1049 | } 1050 | }, 1051 | "node_modules/escape-string-regexp": { 1052 | "version": "4.0.0", 1053 | "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1054 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1055 | "dev": true, 1056 | "peer": true, 1057 | "engines": { 1058 | "node": ">=10" 1059 | }, 1060 | "funding": { 1061 | "url": "https://github.com/sponsors/sindresorhus" 1062 | } 1063 | }, 1064 | "node_modules/eslint": { 1065 | "version": "8.57.0", 1066 | "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.57.0.tgz", 1067 | "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", 1068 | "dev": true, 1069 | "peer": true, 1070 | "dependencies": { 1071 | "@eslint-community/eslint-utils": "^4.2.0", 1072 | "@eslint-community/regexpp": "^4.6.1", 1073 | "@eslint/eslintrc": "^2.1.4", 1074 | "@eslint/js": "8.57.0", 1075 | "@humanwhocodes/config-array": "^0.11.14", 1076 | "@humanwhocodes/module-importer": "^1.0.1", 1077 | "@nodelib/fs.walk": "^1.2.8", 1078 | "@ungap/structured-clone": "^1.2.0", 1079 | "ajv": "^6.12.4", 1080 | "chalk": "^4.0.0", 1081 | "cross-spawn": "^7.0.2", 1082 | "debug": "^4.3.2", 1083 | "doctrine": "^3.0.0", 1084 | "escape-string-regexp": "^4.0.0", 1085 | "eslint-scope": "^7.2.2", 1086 | "eslint-visitor-keys": "^3.4.3", 1087 | "espree": "^9.6.1", 1088 | "esquery": "^1.4.2", 1089 | "esutils": "^2.0.2", 1090 | "fast-deep-equal": "^3.1.3", 1091 | "file-entry-cache": "^6.0.1", 1092 | "find-up": "^5.0.0", 1093 | "glob-parent": "^6.0.2", 1094 | "globals": "^13.19.0", 1095 | "graphemer": "^1.4.0", 1096 | "ignore": "^5.2.0", 1097 | "imurmurhash": "^0.1.4", 1098 | "is-glob": "^4.0.0", 1099 | "is-path-inside": "^3.0.3", 1100 | "js-yaml": "^4.1.0", 1101 | "json-stable-stringify-without-jsonify": "^1.0.1", 1102 | "levn": "^0.4.1", 1103 | "lodash.merge": "^4.6.2", 1104 | "minimatch": "^3.1.2", 1105 | "natural-compare": "^1.4.0", 1106 | "optionator": "^0.9.3", 1107 | "strip-ansi": "^6.0.1", 1108 | "text-table": "^0.2.0" 1109 | }, 1110 | "bin": { 1111 | "eslint": "bin/eslint.js" 1112 | }, 1113 | "engines": { 1114 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1115 | }, 1116 | "funding": { 1117 | "url": "https://opencollective.com/eslint" 1118 | } 1119 | }, 1120 | "node_modules/eslint-scope": { 1121 | "version": "5.1.1", 1122 | "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", 1123 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 1124 | "dev": true, 1125 | "dependencies": { 1126 | "esrecurse": "^4.3.0", 1127 | "estraverse": "^4.1.1" 1128 | }, 1129 | "engines": { 1130 | "node": ">=8.0.0" 1131 | } 1132 | }, 1133 | "node_modules/eslint-utils": { 1134 | "version": "3.0.0", 1135 | "resolved": "https://registry.npmmirror.com/eslint-utils/-/eslint-utils-3.0.0.tgz", 1136 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", 1137 | "dev": true, 1138 | "dependencies": { 1139 | "eslint-visitor-keys": "^2.0.0" 1140 | }, 1141 | "engines": { 1142 | "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" 1143 | }, 1144 | "peerDependencies": { 1145 | "eslint": ">=5" 1146 | } 1147 | }, 1148 | "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { 1149 | "version": "2.1.0", 1150 | "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 1151 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 1152 | "dev": true, 1153 | "engines": { 1154 | "node": ">=10" 1155 | } 1156 | }, 1157 | "node_modules/eslint-visitor-keys": { 1158 | "version": "3.4.3", 1159 | "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", 1160 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", 1161 | "dev": true, 1162 | "engines": { 1163 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1164 | }, 1165 | "funding": { 1166 | "url": "https://opencollective.com/eslint" 1167 | } 1168 | }, 1169 | "node_modules/eslint/node_modules/eslint-scope": { 1170 | "version": "7.2.2", 1171 | "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.2.tgz", 1172 | "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", 1173 | "dev": true, 1174 | "peer": true, 1175 | "dependencies": { 1176 | "esrecurse": "^4.3.0", 1177 | "estraverse": "^5.2.0" 1178 | }, 1179 | "engines": { 1180 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1181 | }, 1182 | "funding": { 1183 | "url": "https://opencollective.com/eslint" 1184 | } 1185 | }, 1186 | "node_modules/eslint/node_modules/estraverse": { 1187 | "version": "5.3.0", 1188 | "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", 1189 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1190 | "dev": true, 1191 | "peer": true, 1192 | "engines": { 1193 | "node": ">=4.0" 1194 | } 1195 | }, 1196 | "node_modules/espree": { 1197 | "version": "9.6.1", 1198 | "resolved": "https://registry.npmmirror.com/espree/-/espree-9.6.1.tgz", 1199 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", 1200 | "dev": true, 1201 | "peer": true, 1202 | "dependencies": { 1203 | "acorn": "^8.9.0", 1204 | "acorn-jsx": "^5.3.2", 1205 | "eslint-visitor-keys": "^3.4.1" 1206 | }, 1207 | "engines": { 1208 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1209 | }, 1210 | "funding": { 1211 | "url": "https://opencollective.com/eslint" 1212 | } 1213 | }, 1214 | "node_modules/esquery": { 1215 | "version": "1.5.0", 1216 | "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.5.0.tgz", 1217 | "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", 1218 | "dev": true, 1219 | "peer": true, 1220 | "dependencies": { 1221 | "estraverse": "^5.1.0" 1222 | }, 1223 | "engines": { 1224 | "node": ">=0.10" 1225 | } 1226 | }, 1227 | "node_modules/esquery/node_modules/estraverse": { 1228 | "version": "5.3.0", 1229 | "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", 1230 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1231 | "dev": true, 1232 | "peer": true, 1233 | "engines": { 1234 | "node": ">=4.0" 1235 | } 1236 | }, 1237 | "node_modules/esrecurse": { 1238 | "version": "4.3.0", 1239 | "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", 1240 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1241 | "dev": true, 1242 | "dependencies": { 1243 | "estraverse": "^5.2.0" 1244 | }, 1245 | "engines": { 1246 | "node": ">=4.0" 1247 | } 1248 | }, 1249 | "node_modules/esrecurse/node_modules/estraverse": { 1250 | "version": "5.3.0", 1251 | "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", 1252 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1253 | "dev": true, 1254 | "engines": { 1255 | "node": ">=4.0" 1256 | } 1257 | }, 1258 | "node_modules/estraverse": { 1259 | "version": "4.3.0", 1260 | "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", 1261 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 1262 | "dev": true, 1263 | "engines": { 1264 | "node": ">=4.0" 1265 | } 1266 | }, 1267 | "node_modules/esutils": { 1268 | "version": "2.0.3", 1269 | "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", 1270 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1271 | "dev": true, 1272 | "peer": true, 1273 | "engines": { 1274 | "node": ">=0.10.0" 1275 | } 1276 | }, 1277 | "node_modules/fast-deep-equal": { 1278 | "version": "3.1.3", 1279 | "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1280 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1281 | "dev": true, 1282 | "peer": true 1283 | }, 1284 | "node_modules/fast-glob": { 1285 | "version": "3.3.2", 1286 | "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz", 1287 | "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", 1288 | "dev": true, 1289 | "dependencies": { 1290 | "@nodelib/fs.stat": "^2.0.2", 1291 | "@nodelib/fs.walk": "^1.2.3", 1292 | "glob-parent": "^5.1.2", 1293 | "merge2": "^1.3.0", 1294 | "micromatch": "^4.0.4" 1295 | }, 1296 | "engines": { 1297 | "node": ">=8.6.0" 1298 | } 1299 | }, 1300 | "node_modules/fast-glob/node_modules/glob-parent": { 1301 | "version": "5.1.2", 1302 | "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", 1303 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1304 | "dev": true, 1305 | "dependencies": { 1306 | "is-glob": "^4.0.1" 1307 | }, 1308 | "engines": { 1309 | "node": ">= 6" 1310 | } 1311 | }, 1312 | "node_modules/fast-json-stable-stringify": { 1313 | "version": "2.1.0", 1314 | "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1315 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1316 | "dev": true, 1317 | "peer": true 1318 | }, 1319 | "node_modules/fast-levenshtein": { 1320 | "version": "2.0.6", 1321 | "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1322 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 1323 | "dev": true, 1324 | "peer": true 1325 | }, 1326 | "node_modules/fastq": { 1327 | "version": "1.17.1", 1328 | "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.17.1.tgz", 1329 | "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", 1330 | "dev": true, 1331 | "dependencies": { 1332 | "reusify": "^1.0.4" 1333 | } 1334 | }, 1335 | "node_modules/file-entry-cache": { 1336 | "version": "6.0.1", 1337 | "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 1338 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 1339 | "dev": true, 1340 | "peer": true, 1341 | "dependencies": { 1342 | "flat-cache": "^3.0.4" 1343 | }, 1344 | "engines": { 1345 | "node": "^10.12.0 || >=12.0.0" 1346 | } 1347 | }, 1348 | "node_modules/fill-range": { 1349 | "version": "7.1.1", 1350 | "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", 1351 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1352 | "dev": true, 1353 | "dependencies": { 1354 | "to-regex-range": "^5.0.1" 1355 | }, 1356 | "engines": { 1357 | "node": ">=8" 1358 | } 1359 | }, 1360 | "node_modules/find-up": { 1361 | "version": "5.0.0", 1362 | "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", 1363 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1364 | "dev": true, 1365 | "peer": true, 1366 | "dependencies": { 1367 | "locate-path": "^6.0.0", 1368 | "path-exists": "^4.0.0" 1369 | }, 1370 | "engines": { 1371 | "node": ">=10" 1372 | }, 1373 | "funding": { 1374 | "url": "https://github.com/sponsors/sindresorhus" 1375 | } 1376 | }, 1377 | "node_modules/flat-cache": { 1378 | "version": "3.2.0", 1379 | "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.2.0.tgz", 1380 | "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", 1381 | "dev": true, 1382 | "peer": true, 1383 | "dependencies": { 1384 | "flatted": "^3.2.9", 1385 | "keyv": "^4.5.3", 1386 | "rimraf": "^3.0.2" 1387 | }, 1388 | "engines": { 1389 | "node": "^10.12.0 || >=12.0.0" 1390 | } 1391 | }, 1392 | "node_modules/flatted": { 1393 | "version": "3.3.1", 1394 | "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.1.tgz", 1395 | "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", 1396 | "dev": true, 1397 | "peer": true 1398 | }, 1399 | "node_modules/fs.realpath": { 1400 | "version": "1.0.0", 1401 | "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", 1402 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 1403 | "dev": true, 1404 | "peer": true 1405 | }, 1406 | "node_modules/functional-red-black-tree": { 1407 | "version": "1.0.1", 1408 | "resolved": "https://registry.npmmirror.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1409 | "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", 1410 | "dev": true 1411 | }, 1412 | "node_modules/glob": { 1413 | "version": "7.2.3", 1414 | "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", 1415 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 1416 | "deprecated": "Glob versions prior to v9 are no longer supported", 1417 | "dev": true, 1418 | "peer": true, 1419 | "dependencies": { 1420 | "fs.realpath": "^1.0.0", 1421 | "inflight": "^1.0.4", 1422 | "inherits": "2", 1423 | "minimatch": "^3.1.1", 1424 | "once": "^1.3.0", 1425 | "path-is-absolute": "^1.0.0" 1426 | }, 1427 | "engines": { 1428 | "node": "*" 1429 | }, 1430 | "funding": { 1431 | "url": "https://github.com/sponsors/isaacs" 1432 | } 1433 | }, 1434 | "node_modules/glob-parent": { 1435 | "version": "6.0.2", 1436 | "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", 1437 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 1438 | "dev": true, 1439 | "peer": true, 1440 | "dependencies": { 1441 | "is-glob": "^4.0.3" 1442 | }, 1443 | "engines": { 1444 | "node": ">=10.13.0" 1445 | } 1446 | }, 1447 | "node_modules/globals": { 1448 | "version": "13.24.0", 1449 | "resolved": "https://registry.npmmirror.com/globals/-/globals-13.24.0.tgz", 1450 | "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", 1451 | "dev": true, 1452 | "peer": true, 1453 | "dependencies": { 1454 | "type-fest": "^0.20.2" 1455 | }, 1456 | "engines": { 1457 | "node": ">=8" 1458 | }, 1459 | "funding": { 1460 | "url": "https://github.com/sponsors/sindresorhus" 1461 | } 1462 | }, 1463 | "node_modules/globby": { 1464 | "version": "11.1.0", 1465 | "resolved": "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz", 1466 | "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", 1467 | "dev": true, 1468 | "dependencies": { 1469 | "array-union": "^2.1.0", 1470 | "dir-glob": "^3.0.1", 1471 | "fast-glob": "^3.2.9", 1472 | "ignore": "^5.2.0", 1473 | "merge2": "^1.4.1", 1474 | "slash": "^3.0.0" 1475 | }, 1476 | "engines": { 1477 | "node": ">=10" 1478 | }, 1479 | "funding": { 1480 | "url": "https://github.com/sponsors/sindresorhus" 1481 | } 1482 | }, 1483 | "node_modules/graphemer": { 1484 | "version": "1.4.0", 1485 | "resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz", 1486 | "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", 1487 | "dev": true, 1488 | "peer": true 1489 | }, 1490 | "node_modules/has-flag": { 1491 | "version": "4.0.0", 1492 | "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", 1493 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1494 | "dev": true, 1495 | "peer": true, 1496 | "engines": { 1497 | "node": ">=8" 1498 | } 1499 | }, 1500 | "node_modules/ignore": { 1501 | "version": "5.3.1", 1502 | "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.1.tgz", 1503 | "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", 1504 | "dev": true, 1505 | "engines": { 1506 | "node": ">= 4" 1507 | } 1508 | }, 1509 | "node_modules/import-fresh": { 1510 | "version": "3.3.0", 1511 | "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz", 1512 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1513 | "dev": true, 1514 | "peer": true, 1515 | "dependencies": { 1516 | "parent-module": "^1.0.0", 1517 | "resolve-from": "^4.0.0" 1518 | }, 1519 | "engines": { 1520 | "node": ">=6" 1521 | }, 1522 | "funding": { 1523 | "url": "https://github.com/sponsors/sindresorhus" 1524 | } 1525 | }, 1526 | "node_modules/imurmurhash": { 1527 | "version": "0.1.4", 1528 | "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", 1529 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 1530 | "dev": true, 1531 | "peer": true, 1532 | "engines": { 1533 | "node": ">=0.8.19" 1534 | } 1535 | }, 1536 | "node_modules/inflight": { 1537 | "version": "1.0.6", 1538 | "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", 1539 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1540 | "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", 1541 | "dev": true, 1542 | "peer": true, 1543 | "dependencies": { 1544 | "once": "^1.3.0", 1545 | "wrappy": "1" 1546 | } 1547 | }, 1548 | "node_modules/inherits": { 1549 | "version": "2.0.4", 1550 | "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", 1551 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1552 | "dev": true, 1553 | "peer": true 1554 | }, 1555 | "node_modules/is-extglob": { 1556 | "version": "2.1.1", 1557 | "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", 1558 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1559 | "dev": true, 1560 | "engines": { 1561 | "node": ">=0.10.0" 1562 | } 1563 | }, 1564 | "node_modules/is-glob": { 1565 | "version": "4.0.3", 1566 | "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", 1567 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1568 | "dev": true, 1569 | "dependencies": { 1570 | "is-extglob": "^2.1.1" 1571 | }, 1572 | "engines": { 1573 | "node": ">=0.10.0" 1574 | } 1575 | }, 1576 | "node_modules/is-number": { 1577 | "version": "7.0.0", 1578 | "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", 1579 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1580 | "dev": true, 1581 | "engines": { 1582 | "node": ">=0.12.0" 1583 | } 1584 | }, 1585 | "node_modules/is-path-inside": { 1586 | "version": "3.0.3", 1587 | "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz", 1588 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", 1589 | "dev": true, 1590 | "peer": true, 1591 | "engines": { 1592 | "node": ">=8" 1593 | } 1594 | }, 1595 | "node_modules/isexe": { 1596 | "version": "2.0.0", 1597 | "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", 1598 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1599 | "dev": true, 1600 | "peer": true 1601 | }, 1602 | "node_modules/js-yaml": { 1603 | "version": "4.1.0", 1604 | "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", 1605 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1606 | "dev": true, 1607 | "peer": true, 1608 | "dependencies": { 1609 | "argparse": "^2.0.1" 1610 | }, 1611 | "bin": { 1612 | "js-yaml": "bin/js-yaml.js" 1613 | } 1614 | }, 1615 | "node_modules/json-buffer": { 1616 | "version": "3.0.1", 1617 | "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", 1618 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", 1619 | "dev": true, 1620 | "peer": true 1621 | }, 1622 | "node_modules/json-schema-traverse": { 1623 | "version": "0.4.1", 1624 | "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1625 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1626 | "dev": true, 1627 | "peer": true 1628 | }, 1629 | "node_modules/json-stable-stringify-without-jsonify": { 1630 | "version": "1.0.1", 1631 | "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1632 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 1633 | "dev": true, 1634 | "peer": true 1635 | }, 1636 | "node_modules/keyv": { 1637 | "version": "4.5.4", 1638 | "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", 1639 | "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", 1640 | "dev": true, 1641 | "peer": true, 1642 | "dependencies": { 1643 | "json-buffer": "3.0.1" 1644 | } 1645 | }, 1646 | "node_modules/levn": { 1647 | "version": "0.4.1", 1648 | "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", 1649 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1650 | "dev": true, 1651 | "peer": true, 1652 | "dependencies": { 1653 | "prelude-ls": "^1.2.1", 1654 | "type-check": "~0.4.0" 1655 | }, 1656 | "engines": { 1657 | "node": ">= 0.8.0" 1658 | } 1659 | }, 1660 | "node_modules/locate-path": { 1661 | "version": "6.0.0", 1662 | "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", 1663 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1664 | "dev": true, 1665 | "peer": true, 1666 | "dependencies": { 1667 | "p-locate": "^5.0.0" 1668 | }, 1669 | "engines": { 1670 | "node": ">=10" 1671 | }, 1672 | "funding": { 1673 | "url": "https://github.com/sponsors/sindresorhus" 1674 | } 1675 | }, 1676 | "node_modules/lodash.merge": { 1677 | "version": "4.6.2", 1678 | "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", 1679 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1680 | "dev": true, 1681 | "peer": true 1682 | }, 1683 | "node_modules/lucide-static": { 1684 | "version": "0.372.0", 1685 | "resolved": "https://registry.npmmirror.com/lucide-static/-/lucide-static-0.372.0.tgz", 1686 | "integrity": "sha512-Nhv52WMoVtelJnO6YOHi8gRPabe9RXLy9RZX4rb/IKvTHV+iVN+QE/F/uSuP9P/Qtc9xQBGfc59Mbhnkf7WK9A==" 1687 | }, 1688 | "node_modules/merge2": { 1689 | "version": "1.4.1", 1690 | "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", 1691 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1692 | "dev": true, 1693 | "engines": { 1694 | "node": ">= 8" 1695 | } 1696 | }, 1697 | "node_modules/micromatch": { 1698 | "version": "4.0.7", 1699 | "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.7.tgz", 1700 | "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", 1701 | "dev": true, 1702 | "dependencies": { 1703 | "braces": "^3.0.3", 1704 | "picomatch": "^2.3.1" 1705 | }, 1706 | "engines": { 1707 | "node": ">=8.6" 1708 | } 1709 | }, 1710 | "node_modules/minimatch": { 1711 | "version": "3.1.2", 1712 | "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", 1713 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1714 | "dev": true, 1715 | "peer": true, 1716 | "dependencies": { 1717 | "brace-expansion": "^1.1.7" 1718 | }, 1719 | "engines": { 1720 | "node": "*" 1721 | } 1722 | }, 1723 | "node_modules/moment": { 1724 | "version": "2.29.4", 1725 | "resolved": "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz", 1726 | "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", 1727 | "dev": true, 1728 | "engines": { 1729 | "node": "*" 1730 | } 1731 | }, 1732 | "node_modules/ms": { 1733 | "version": "2.1.2", 1734 | "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", 1735 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1736 | "dev": true 1737 | }, 1738 | "node_modules/natural-compare": { 1739 | "version": "1.4.0", 1740 | "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", 1741 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 1742 | "dev": true, 1743 | "peer": true 1744 | }, 1745 | "node_modules/obsidian": { 1746 | "version": "1.5.7-1", 1747 | "resolved": "https://registry.npmmirror.com/obsidian/-/obsidian-1.5.7-1.tgz", 1748 | "integrity": "sha512-T5ZRuQ1FnfXqEoakTTHVDYvzUEEoT8zSPnQCW31PVgYwG4D4tZCQfKHN2hTz1ifnCe8upvwa6mBTAP2WUA5Vng==", 1749 | "dev": true, 1750 | "dependencies": { 1751 | "@types/codemirror": "5.60.8", 1752 | "moment": "2.29.4" 1753 | }, 1754 | "peerDependencies": { 1755 | "@codemirror/state": "^6.0.0", 1756 | "@codemirror/view": "^6.0.0" 1757 | } 1758 | }, 1759 | "node_modules/once": { 1760 | "version": "1.4.0", 1761 | "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", 1762 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1763 | "dev": true, 1764 | "peer": true, 1765 | "dependencies": { 1766 | "wrappy": "1" 1767 | } 1768 | }, 1769 | "node_modules/optionator": { 1770 | "version": "0.9.4", 1771 | "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", 1772 | "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", 1773 | "dev": true, 1774 | "peer": true, 1775 | "dependencies": { 1776 | "deep-is": "^0.1.3", 1777 | "fast-levenshtein": "^2.0.6", 1778 | "levn": "^0.4.1", 1779 | "prelude-ls": "^1.2.1", 1780 | "type-check": "^0.4.0", 1781 | "word-wrap": "^1.2.5" 1782 | }, 1783 | "engines": { 1784 | "node": ">= 0.8.0" 1785 | } 1786 | }, 1787 | "node_modules/p-limit": { 1788 | "version": "3.1.0", 1789 | "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", 1790 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1791 | "dev": true, 1792 | "peer": true, 1793 | "dependencies": { 1794 | "yocto-queue": "^0.1.0" 1795 | }, 1796 | "engines": { 1797 | "node": ">=10" 1798 | }, 1799 | "funding": { 1800 | "url": "https://github.com/sponsors/sindresorhus" 1801 | } 1802 | }, 1803 | "node_modules/p-locate": { 1804 | "version": "5.0.0", 1805 | "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", 1806 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1807 | "dev": true, 1808 | "peer": true, 1809 | "dependencies": { 1810 | "p-limit": "^3.0.2" 1811 | }, 1812 | "engines": { 1813 | "node": ">=10" 1814 | }, 1815 | "funding": { 1816 | "url": "https://github.com/sponsors/sindresorhus" 1817 | } 1818 | }, 1819 | "node_modules/parent-module": { 1820 | "version": "1.0.1", 1821 | "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", 1822 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1823 | "dev": true, 1824 | "peer": true, 1825 | "dependencies": { 1826 | "callsites": "^3.0.0" 1827 | }, 1828 | "engines": { 1829 | "node": ">=6" 1830 | } 1831 | }, 1832 | "node_modules/path-exists": { 1833 | "version": "4.0.0", 1834 | "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", 1835 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1836 | "dev": true, 1837 | "peer": true, 1838 | "engines": { 1839 | "node": ">=8" 1840 | } 1841 | }, 1842 | "node_modules/path-is-absolute": { 1843 | "version": "1.0.1", 1844 | "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1845 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1846 | "dev": true, 1847 | "peer": true, 1848 | "engines": { 1849 | "node": ">=0.10.0" 1850 | } 1851 | }, 1852 | "node_modules/path-key": { 1853 | "version": "3.1.1", 1854 | "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", 1855 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1856 | "dev": true, 1857 | "peer": true, 1858 | "engines": { 1859 | "node": ">=8" 1860 | } 1861 | }, 1862 | "node_modules/path-type": { 1863 | "version": "4.0.0", 1864 | "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", 1865 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 1866 | "dev": true, 1867 | "engines": { 1868 | "node": ">=8" 1869 | } 1870 | }, 1871 | "node_modules/picomatch": { 1872 | "version": "2.3.1", 1873 | "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", 1874 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1875 | "dev": true, 1876 | "engines": { 1877 | "node": ">=8.6" 1878 | }, 1879 | "funding": { 1880 | "url": "https://github.com/sponsors/jonschlinkert" 1881 | } 1882 | }, 1883 | "node_modules/prelude-ls": { 1884 | "version": "1.2.1", 1885 | "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", 1886 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1887 | "dev": true, 1888 | "peer": true, 1889 | "engines": { 1890 | "node": ">= 0.8.0" 1891 | } 1892 | }, 1893 | "node_modules/punycode": { 1894 | "version": "2.3.1", 1895 | "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", 1896 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 1897 | "dev": true, 1898 | "peer": true, 1899 | "engines": { 1900 | "node": ">=6" 1901 | } 1902 | }, 1903 | "node_modules/queue-microtask": { 1904 | "version": "1.2.3", 1905 | "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", 1906 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1907 | "dev": true, 1908 | "funding": [ 1909 | { 1910 | "type": "github", 1911 | "url": "https://github.com/sponsors/feross" 1912 | }, 1913 | { 1914 | "type": "patreon", 1915 | "url": "https://www.patreon.com/feross" 1916 | }, 1917 | { 1918 | "type": "consulting", 1919 | "url": "https://feross.org/support" 1920 | } 1921 | ] 1922 | }, 1923 | "node_modules/regexpp": { 1924 | "version": "3.2.0", 1925 | "resolved": "https://registry.npmmirror.com/regexpp/-/regexpp-3.2.0.tgz", 1926 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 1927 | "dev": true, 1928 | "engines": { 1929 | "node": ">=8" 1930 | } 1931 | }, 1932 | "node_modules/resolve-from": { 1933 | "version": "4.0.0", 1934 | "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", 1935 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1936 | "dev": true, 1937 | "peer": true, 1938 | "engines": { 1939 | "node": ">=4" 1940 | } 1941 | }, 1942 | "node_modules/reusify": { 1943 | "version": "1.0.4", 1944 | "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz", 1945 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1946 | "dev": true, 1947 | "engines": { 1948 | "iojs": ">=1.0.0", 1949 | "node": ">=0.10.0" 1950 | } 1951 | }, 1952 | "node_modules/rimraf": { 1953 | "version": "3.0.2", 1954 | "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", 1955 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1956 | "deprecated": "Rimraf versions prior to v4 are no longer supported", 1957 | "dev": true, 1958 | "peer": true, 1959 | "dependencies": { 1960 | "glob": "^7.1.3" 1961 | }, 1962 | "bin": { 1963 | "rimraf": "bin.js" 1964 | }, 1965 | "funding": { 1966 | "url": "https://github.com/sponsors/isaacs" 1967 | } 1968 | }, 1969 | "node_modules/run-parallel": { 1970 | "version": "1.2.0", 1971 | "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", 1972 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1973 | "dev": true, 1974 | "funding": [ 1975 | { 1976 | "type": "github", 1977 | "url": "https://github.com/sponsors/feross" 1978 | }, 1979 | { 1980 | "type": "patreon", 1981 | "url": "https://www.patreon.com/feross" 1982 | }, 1983 | { 1984 | "type": "consulting", 1985 | "url": "https://feross.org/support" 1986 | } 1987 | ], 1988 | "dependencies": { 1989 | "queue-microtask": "^1.2.2" 1990 | } 1991 | }, 1992 | "node_modules/semver": { 1993 | "version": "7.6.2", 1994 | "resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.2.tgz", 1995 | "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", 1996 | "dev": true, 1997 | "bin": { 1998 | "semver": "bin/semver.js" 1999 | }, 2000 | "engines": { 2001 | "node": ">=10" 2002 | } 2003 | }, 2004 | "node_modules/shebang-command": { 2005 | "version": "2.0.0", 2006 | "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", 2007 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2008 | "dev": true, 2009 | "peer": true, 2010 | "dependencies": { 2011 | "shebang-regex": "^3.0.0" 2012 | }, 2013 | "engines": { 2014 | "node": ">=8" 2015 | } 2016 | }, 2017 | "node_modules/shebang-regex": { 2018 | "version": "3.0.0", 2019 | "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", 2020 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2021 | "dev": true, 2022 | "peer": true, 2023 | "engines": { 2024 | "node": ">=8" 2025 | } 2026 | }, 2027 | "node_modules/slash": { 2028 | "version": "3.0.0", 2029 | "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", 2030 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2031 | "dev": true, 2032 | "engines": { 2033 | "node": ">=8" 2034 | } 2035 | }, 2036 | "node_modules/strip-ansi": { 2037 | "version": "6.0.1", 2038 | "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", 2039 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2040 | "dev": true, 2041 | "peer": true, 2042 | "dependencies": { 2043 | "ansi-regex": "^5.0.1" 2044 | }, 2045 | "engines": { 2046 | "node": ">=8" 2047 | } 2048 | }, 2049 | "node_modules/strip-json-comments": { 2050 | "version": "3.1.1", 2051 | "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2052 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2053 | "dev": true, 2054 | "peer": true, 2055 | "engines": { 2056 | "node": ">=8" 2057 | }, 2058 | "funding": { 2059 | "url": "https://github.com/sponsors/sindresorhus" 2060 | } 2061 | }, 2062 | "node_modules/style-mod": { 2063 | "version": "4.1.2", 2064 | "resolved": "https://registry.npmmirror.com/style-mod/-/style-mod-4.1.2.tgz", 2065 | "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", 2066 | "dev": true, 2067 | "peer": true 2068 | }, 2069 | "node_modules/supports-color": { 2070 | "version": "7.2.0", 2071 | "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", 2072 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2073 | "dev": true, 2074 | "peer": true, 2075 | "dependencies": { 2076 | "has-flag": "^4.0.0" 2077 | }, 2078 | "engines": { 2079 | "node": ">=8" 2080 | } 2081 | }, 2082 | "node_modules/text-table": { 2083 | "version": "0.2.0", 2084 | "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", 2085 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", 2086 | "dev": true, 2087 | "peer": true 2088 | }, 2089 | "node_modules/to-regex-range": { 2090 | "version": "5.0.1", 2091 | "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", 2092 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2093 | "dev": true, 2094 | "dependencies": { 2095 | "is-number": "^7.0.0" 2096 | }, 2097 | "engines": { 2098 | "node": ">=8.0" 2099 | } 2100 | }, 2101 | "node_modules/tslib": { 2102 | "version": "2.4.0", 2103 | "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.0.tgz", 2104 | "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", 2105 | "dev": true 2106 | }, 2107 | "node_modules/tsutils": { 2108 | "version": "3.21.0", 2109 | "resolved": "https://registry.npmmirror.com/tsutils/-/tsutils-3.21.0.tgz", 2110 | "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", 2111 | "dev": true, 2112 | "dependencies": { 2113 | "tslib": "^1.8.1" 2114 | }, 2115 | "engines": { 2116 | "node": ">= 6" 2117 | }, 2118 | "peerDependencies": { 2119 | "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" 2120 | } 2121 | }, 2122 | "node_modules/tsutils/node_modules/tslib": { 2123 | "version": "1.14.1", 2124 | "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz", 2125 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 2126 | "dev": true 2127 | }, 2128 | "node_modules/type-check": { 2129 | "version": "0.4.0", 2130 | "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", 2131 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2132 | "dev": true, 2133 | "peer": true, 2134 | "dependencies": { 2135 | "prelude-ls": "^1.2.1" 2136 | }, 2137 | "engines": { 2138 | "node": ">= 0.8.0" 2139 | } 2140 | }, 2141 | "node_modules/type-fest": { 2142 | "version": "0.20.2", 2143 | "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz", 2144 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2145 | "dev": true, 2146 | "peer": true, 2147 | "engines": { 2148 | "node": ">=10" 2149 | }, 2150 | "funding": { 2151 | "url": "https://github.com/sponsors/sindresorhus" 2152 | } 2153 | }, 2154 | "node_modules/typescript": { 2155 | "version": "4.7.4", 2156 | "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.7.4.tgz", 2157 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", 2158 | "dev": true, 2159 | "bin": { 2160 | "tsc": "bin/tsc", 2161 | "tsserver": "bin/tsserver" 2162 | }, 2163 | "engines": { 2164 | "node": ">=4.2.0" 2165 | } 2166 | }, 2167 | "node_modules/uri-js": { 2168 | "version": "4.4.1", 2169 | "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", 2170 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2171 | "dev": true, 2172 | "peer": true, 2173 | "dependencies": { 2174 | "punycode": "^2.1.0" 2175 | } 2176 | }, 2177 | "node_modules/w3c-keyname": { 2178 | "version": "2.2.8", 2179 | "resolved": "https://registry.npmmirror.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz", 2180 | "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", 2181 | "dev": true, 2182 | "peer": true 2183 | }, 2184 | "node_modules/which": { 2185 | "version": "2.0.2", 2186 | "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", 2187 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2188 | "dev": true, 2189 | "peer": true, 2190 | "dependencies": { 2191 | "isexe": "^2.0.0" 2192 | }, 2193 | "bin": { 2194 | "node-which": "bin/node-which" 2195 | }, 2196 | "engines": { 2197 | "node": ">= 8" 2198 | } 2199 | }, 2200 | "node_modules/word-wrap": { 2201 | "version": "1.2.5", 2202 | "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", 2203 | "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", 2204 | "dev": true, 2205 | "peer": true, 2206 | "engines": { 2207 | "node": ">=0.10.0" 2208 | } 2209 | }, 2210 | "node_modules/wrappy": { 2211 | "version": "1.0.2", 2212 | "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", 2213 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2214 | "dev": true, 2215 | "peer": true 2216 | }, 2217 | "node_modules/yocto-queue": { 2218 | "version": "0.1.0", 2219 | "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", 2220 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2221 | "dev": true, 2222 | "peer": true, 2223 | "engines": { 2224 | "node": ">=10" 2225 | }, 2226 | "funding": { 2227 | "url": "https://github.com/sponsors/sindresorhus" 2228 | } 2229 | } 2230 | } 2231 | } 2232 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-sidebar-icons", 3 | "version": "0.1.0", 4 | "description": "Customize sidebar workspace document icons.", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "node scripts/esbuild.config.test.mjs", 8 | "dev": "node scripts/esbuild.config.mjs", 9 | "build": "tsc -noEmit -skipLibCheck && node scripts/esbuild.config.mjs production", 10 | "version": "node scripts/version-bump.mjs && git add manifest.json versions.json" 11 | }, 12 | "keywords": [], 13 | "author": "RavenHogWarts", 14 | "license": "MIT", 15 | "devDependencies": { 16 | "@types/node": "^16.11.6", 17 | "@typescript-eslint/eslint-plugin": "5.29.0", 18 | "@typescript-eslint/parser": "5.29.0", 19 | "builtin-modules": "3.3.0", 20 | "esbuild": "0.17.3", 21 | "obsidian": "latest", 22 | "tslib": "2.4.0", 23 | "typescript": "4.7.4" 24 | }, 25 | "dependencies": { 26 | "@popperjs/core": "^2.11.8", 27 | "dotenv": "^16.4.5", 28 | "lucide-static": "^0.372.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scripts/esbuild.config.mjs: -------------------------------------------------------------------------------- 1 | import esbuild from "esbuild"; 2 | import process from "process"; 3 | import builtins from "builtin-modules"; 4 | 5 | const banner = 6 | `/* 7 | THIS IS A GENERATED/BUNDLED FILE BY ESBUILD 8 | if you want to view the source, please visit the github repository of this plugin 9 | */ 10 | `; 11 | 12 | const prod = (process.argv[2] === "production"); 13 | 14 | const context = await esbuild.context({ 15 | banner: { 16 | js: banner, 17 | }, 18 | entryPoints: ["src/main.ts", "src/styles.css"], 19 | bundle: true, 20 | external: [ 21 | "obsidian", 22 | "electron", 23 | "@codemirror/autocomplete", 24 | "@codemirror/collab", 25 | "@codemirror/commands", 26 | "@codemirror/language", 27 | "@codemirror/lint", 28 | "@codemirror/search", 29 | "@codemirror/state", 30 | "@codemirror/view", 31 | "@lezer/common", 32 | "@lezer/highlight", 33 | "@lezer/lr", 34 | ...builtins], 35 | format: "cjs", 36 | target: "es2018", 37 | logLevel: "info", 38 | sourcemap: prod ? false : "inline", 39 | treeShaking: true, 40 | outdir: "./", 41 | minify: prod, 42 | }); 43 | 44 | if (prod) { 45 | await context.rebuild(); 46 | process.exit(0); 47 | } else { 48 | await context.watch(); 49 | } -------------------------------------------------------------------------------- /scripts/esbuild.config.test.mjs: -------------------------------------------------------------------------------- 1 | import esbuild from "esbuild"; 2 | import process from "process"; 3 | import builtins from "builtin-modules"; 4 | import { config } from "dotenv"; 5 | import fs from "fs"; 6 | import path from "path"; 7 | 8 | config(); 9 | 10 | const banner =``; 11 | 12 | const prod = (process.argv[2] === "production"); 13 | let outdir = "./"; 14 | 15 | if(process.env.OUT === "1"){ 16 | const vaultDir = process.env.REAL === "1" ? process.env.REAL_VAULT : process.env.TEST_VAULT; 17 | fs.promises.copyFile( 18 | path.join("./", "manifest.json"), 19 | path.join(vaultDir, "manifest.json") 20 | ); 21 | outdir = vaultDir; 22 | } 23 | 24 | console.info(`\nSaving plugin to ${outdir}\n`); 25 | 26 | esbuild.build({ 27 | banner: { 28 | js: banner, 29 | }, 30 | entryPoints: ["src/main.ts", "src/styles.css"], 31 | bundle: true, 32 | external: [ 33 | "obsidian", 34 | "electron", 35 | "@codemirror/autocomplete", 36 | "@codemirror/collab", 37 | "@codemirror/commands", 38 | "@codemirror/language", 39 | "@codemirror/lint", 40 | "@codemirror/search", 41 | "@codemirror/state", 42 | "@codemirror/view", 43 | "@lezer/common", 44 | "@lezer/highlight", 45 | "@lezer/lr", 46 | ...builtins], 47 | format: "cjs", 48 | target: "es2018", 49 | logLevel: "info", 50 | sourcemap: prod ? false : "inline", 51 | treeShaking: true, 52 | outdir: outdir, 53 | minify: prod, 54 | }).catch(() => process.exit(1)); -------------------------------------------------------------------------------- /scripts/version-bump.mjs: -------------------------------------------------------------------------------- 1 | import { readFileSync, writeFileSync } from "fs"; 2 | 3 | const targetVersion = process.env.npm_package_version; 4 | 5 | // read minAppVersion from manifest.json and bump version to target version 6 | let manifest = JSON.parse(readFileSync("manifest.json", "utf8")); 7 | const { minAppVersion } = manifest; 8 | manifest.version = targetVersion; 9 | writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t")); 10 | 11 | // update versions.json with target version and minAppVersion from manifest.json 12 | let versions = JSON.parse(readFileSync("versions.json", "utf8")); 13 | versions[targetVersion] = minAppVersion; 14 | writeFileSync("versions.json", JSON.stringify(versions, null, "\t")); 15 | -------------------------------------------------------------------------------- /src/i18n/en.ts: -------------------------------------------------------------------------------- 1 | import { LocalProperty } from './types'; 2 | 3 | export const EN: LocalProperty = { 4 | Tab_Title: "Custom Icons", 5 | Tab_Sidebar: "Sidebar Workspace", 6 | Tab_SidebarIcons: "Pin Files", 7 | SidebarIcons_FileName: "Enter File Name", 8 | Tab_Folder: "Folders Directory", 9 | Tab_FolderIcons: "Folders", 10 | FolderIcons_Title: "Set Folder Icons", 11 | FolderIcons_Default: "Set Default Icon for New Folders", 12 | FolderIcons_FileName: "Enter Folder Path", 13 | Tab_FileIcons: "Files", 14 | FileIcons_Title: "Set File Icons", 15 | FileIcons_Default: "Set Default Icon for New Files", 16 | FileIcons_FileExt: "Enter File Extension", 17 | Tab_Editor: "Notes Area", 18 | Tab_InternalLinkIcons: "Internal Links", 19 | InternalLinkIcons_Title: "Set Internal Link Icons", 20 | Tab_About: "About", 21 | IconID: "{num}", 22 | IconImg: "Enter Icon Path", 23 | Type_Custom: "Custom", 24 | Type_Lucide: "Lucide", 25 | About: 26 | ` 27 |

Brief Introduction

28 | 31 | 35 | 38 |

Tips

39 |

Sidebar Workspace

40 |
Pin File Icons
41 | 45 |

File Directory Area

46 |
File Icons
47 | 50 |
Folder Icons
51 | 54 |

Note Area

55 |
Internal Link Icons
56 | 60 | 64 |

Support

65 |

66 | If you find this plugin useful and wish to support its development, you can sponsor me through the following ways:
67 | WeChat, Alipay, 68 | Love to Generate, 69 | Paypal.
70 | Thank you for any support! 71 |

72 |

![Related Image](https://s2.loli.net/2024/05/06/lWBj3ObszUXSV2f.png)

73 | `, 74 | Tips: "For the plugin usage instructions, please see the [About] interface.", 75 | }; -------------------------------------------------------------------------------- /src/i18n/i18n.ts: -------------------------------------------------------------------------------- 1 | import { EN } from "./en"; 2 | import { LocalProperty } from "./types"; 3 | import { ZH } from "./zh"; 4 | import { ZHtw } from "./zh-tw"; 5 | 6 | export class Locals { 7 | 8 | static get(): LocalProperty { 9 | const lang = window.localStorage.getItem("language"); 10 | // console.log(lang); 11 | switch (lang) { 12 | case "zh": 13 | return ZH; 14 | case "zh-TW": 15 | return ZHtw; 16 | default: 17 | return EN; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/i18n/types.ts: -------------------------------------------------------------------------------- 1 | export interface LocalProperty { 2 | Tab_Title: string; 3 | Tab_Sidebar: string; 4 | Tab_SidebarIcons: string; 5 | SidebarIcons_FileName: string; 6 | Tab_Folder: string; 7 | Tab_FolderIcons: string; 8 | FolderIcons_Title: string; 9 | FolderIcons_Default: string; 10 | FolderIcons_FileName: string 11 | Tab_FileIcons: string; 12 | FileIcons_Title: string; 13 | FileIcons_Default: string; 14 | FileIcons_FileExt: string; 15 | Tab_Editor: string; 16 | Tab_InternalLinkIcons: string; 17 | InternalLinkIcons_Title: string; 18 | Tab_About: string; 19 | About: string; 20 | IconID: string; 21 | IconImg: string; 22 | Type_Custom: string; 23 | Type_Lucide: string; 24 | Tips: string; 25 | } -------------------------------------------------------------------------------- /src/i18n/zh-tw.ts: -------------------------------------------------------------------------------- 1 | import { LocalProperty } from "./types"; 2 | 3 | export const ZHtw: LocalProperty = { 4 | Tab_Title: "自訂圖標", 5 | Tab_Sidebar: "側邊工作區", 6 | Tab_SidebarIcons: "釘選檔案", 7 | SidebarIcons_FileName: "輸入檔案名稱", 8 | Tab_Folder: "檔案目錄區", 9 | Tab_FolderIcons: "檔案夾", 10 | FolderIcons_Title: "設定檔案夾圖標", 11 | FolderIcons_Default: "設定新建檔案夾圖標預設值", 12 | FolderIcons_FileName: "輸入檔案夾路徑", 13 | Tab_FileIcons: "檔案", 14 | FileIcons_Title: "設定檔案圖標", 15 | FileIcons_Default: "設定新建檔案圖標預設值", 16 | FileIcons_FileExt: "輸入檔案後綴名", 17 | Tab_Editor: "筆記區", 18 | Tab_InternalLinkIcons: "內部連結", 19 | InternalLinkIcons_Title: "設定內部連結圖標", 20 | Tab_About: "關於", 21 | IconID: "{num}", 22 | IconImg: "輸入圖標路徑", 23 | Type_Custom: "自訂", 24 | Type_Lucide: "Lucide", 25 | About: 26 | ` 27 |

簡要說明

28 | 31 | 35 | 38 |

Tips

39 |

側邊工作區

40 |
Pin文件圖標
41 | 45 |

文件目錄區

46 |
文件圖標
47 | 50 |
文件夾圖標
51 | 54 |

筆記區

55 |
內部連結圖標
56 | 60 | 64 |

支持

65 |

66 | 如果您覺得這個插件有用,並希望支持其開發,您可以通過以下方式贊助我:
67 | 微信,支付寶, 68 | 愛發電, 69 | Paypal
70 | 感謝您的任何支持! 71 |

72 |

![Related Image](https://s2.loli.net/2024/05/06/lWBj3ObszUXSV2f.png)

73 | `, 74 | Tips: "插件使用說明請查看[關於]界面", 75 | }; -------------------------------------------------------------------------------- /src/i18n/zh.ts: -------------------------------------------------------------------------------- 1 | import { LocalProperty } from './types'; 2 | 3 | export const ZH: LocalProperty = { 4 | Tab_Title: "Custom Icons", 5 | Tab_Sidebar: "侧边工作区", 6 | Tab_SidebarIcons: "Pin文件", 7 | SidebarIcons_FileName: "输入文件名称", 8 | Tab_Folder: "文件目录区", 9 | Tab_FolderIcons: "文件夹", 10 | FolderIcons_Title: "设置文件夹图标", 11 | FolderIcons_Default: "设置新建文件夹图标默认值", 12 | FolderIcons_FileName: "输入文件夹路径", 13 | Tab_FileIcons: "文件", 14 | FileIcons_Title: "设置文件图标", 15 | FileIcons_Default: "设置新建文件图标默认值", 16 | FileIcons_FileExt: "输入文件后缀名", 17 | Tab_Editor: "笔记区", 18 | Tab_InternalLinkIcons: "内部链接", 19 | InternalLinkIcons_Title: "设置内部链接图标", 20 | Tab_About: "关于", 21 | IconID: "{num}", 22 | IconImg: "输入图标路径", 23 | Type_Custom: "自定义", 24 | Type_Lucide: "Lucide", 25 | About: 26 | ` 27 |

简要说明

28 | 31 | 35 | 38 |

Tips

39 |

侧边工作区

40 |
Pin文件图标
41 | 45 |

文件目录区

46 |
文件图标
47 | 50 |
文件夹图标
51 | 54 |

笔记区

55 |
内部链接图标
56 | 60 | 64 |

支持

65 |

66 | 如果您觉得这个插件有用,并希望支持其开发,您可以通过以下方式赞助我:
67 | 微信,支付宝, 68 | 爱发电, 69 | Paypal
70 | 感谢您的任何支持! 71 |

72 |

73 | `, 74 | Tips: "插件使用说明请查看[关于]界面", 75 | }; -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { App, Plugin } from 'obsidian'; 2 | import { CustomIconSettings, SidebarIcons, FolderIcons, FileIcons, InternalLinkIcons, DEFAULT_SETTINGS} from './types'; 3 | import { EMPTY_PNG_DATA_URL } from './types'; 4 | import { generateUniqueId, updatePreview, convertToCamelCase } from './utils/utils'; 5 | import * as lucideIcons from 'lucide-static'; 6 | 7 | import { CustomIconSettingTab } from 'src/settings/settingstab'; 8 | 9 | const css_filename = "CustomIcon-AutoGen"; 10 | 11 | export default class CustomIconPlugin extends Plugin { 12 | settings: CustomIconSettings; 13 | resourceBase: string; 14 | themeObserver: MutationObserver | null = null; 15 | 16 | async onload() { 17 | await this.loadSettings(); 18 | this.registerEvent( 19 | this.app.workspace.on('layout-change', () => { 20 | this.refreshSidebarIcons(); 21 | }) 22 | ); 23 | this.addSettingTab(new CustomIconSettingTab(this.app, this)); 24 | await this.genSnippetCSS(this); 25 | this.observeThemeChange(); 26 | } 27 | 28 | onunload() { 29 | // @ts-ignore 30 | const customCss = this.app.customCss; 31 | customCss.enabledSnippets.delete(css_filename); 32 | customCss.requestLoadSnippets(); 33 | if (this.themeObserver) { 34 | this.themeObserver.disconnect(); 35 | this.themeObserver = null; 36 | } 37 | } 38 | 39 | async loadSettings() { 40 | this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); 41 | this.migrateData(); 42 | } 43 | 44 | async saveSettings() { 45 | await this.saveData(this.settings); 46 | } 47 | 48 | observeThemeChange() { 49 | this.themeObserver = new MutationObserver(mutations => { 50 | mutations.forEach(mutation => { 51 | if (mutation.attributeName === 'class') { 52 | const body = document.body; 53 | if (body.classList.contains('theme-light') || body.classList.contains('theme-dark')) { 54 | this.genSnippetCSS(this); 55 | } 56 | } 57 | }); 58 | }); 59 | 60 | this.themeObserver.observe(document.body, { 61 | attributes: true, 62 | attributeFilter: ['class'] 63 | }); 64 | } 65 | 66 | migrateData() { 67 | if (this.settings.customIcons && this.settings.customIcons.length > 0) { 68 | this.settings.SidebarIcons = [...this.settings.SidebarIcons, ...this.settings.customIcons]; 69 | delete (this.settings as { customIcons?: unknown }).customIcons; 70 | this.saveSettings(); 71 | } 72 | 73 | this.settings.SidebarIcons.forEach(icon => { 74 | if (icon.id.startsWith('icon')) { 75 | icon.id = generateUniqueId("sidebar-icon"); 76 | this.saveSettings(); 77 | } 78 | }); 79 | 80 | this.settings.FolderIcons.forEach(icon => { 81 | if (icon.id.startsWith('icon')) { 82 | icon.id = generateUniqueId("folder-icon"); 83 | this.saveSettings(); 84 | } 85 | }); 86 | 87 | if (this.settings.FileIcons && this.settings.FileIcons.length > 0) { 88 | this.settings.FileIcons.forEach(icon => { 89 | if (typeof icon.path === 'string') { 90 | icon.path = [icon.path]; 91 | } 92 | }); 93 | this.saveSettings(); 94 | } 95 | } 96 | 97 | async genSnippetCSS(plugin: CustomIconPlugin) { 98 | const content: string[] = [ 99 | "/* * WARNING: This file will be overwritten by plugin `Custom Icon`.", 100 | " * DO NOT EDIT THIS FILE DIRECTLY!!!", 101 | " * Do not edit this file directly!!!", 102 | "*/", 103 | "", 104 | ]; 105 | plugin.settings.SidebarIcons.forEach(iconSetting => { 106 | content.push(this.genSidebarIconsEntryCSS(iconSetting)); 107 | }); 108 | plugin.settings.FolderIcons.forEach(iconSetting => { 109 | content.push(this.genFolderIconsEntryCSS(iconSetting)); 110 | }); 111 | plugin.settings.FileIcons.forEach(iconSetting => { 112 | content.push(this.genFileIconsEntryCSS(iconSetting)); 113 | }); 114 | plugin.settings.InternalLinkIcons.forEach(iconSetting => { 115 | content.push(this.genInternalLinkIconsEntryCSS(iconSetting)); 116 | }); 117 | 118 | const vault = plugin.app.vault; 119 | const ob_config_path = vault.configDir; 120 | const snippets_path = ob_config_path + "/snippets"; 121 | 122 | const path = `${snippets_path}/${css_filename}.css`; 123 | if (!(await vault.adapter.exists(snippets_path))) { await vault.adapter.mkdir(snippets_path); } 124 | if (await vault.adapter.exists(path)) { await vault.adapter.remove(path) } 125 | await plugin.app.vault.create(path, content.join('\n')); 126 | // @ts-ignore 127 | const customCss = plugin.app.customCss; 128 | customCss.enabledSnippets.add(css_filename); 129 | customCss.requestLoadSnippets(); 130 | } 131 | 132 | genSidebarIconsEntryCSS(settings: SidebarIcons): string { 133 | const selector = `aria-label="${settings.label}"`; 134 | const iconUrl = this.getResourcePathwithType(settings.image, settings.type); 135 | let body: string[] = [ 136 | `.custom-icon.workspace-tab-header[${selector}] .workspace-tab-header-inner-icon::before {`, 137 | `content: '';`, 138 | `display: inline-block;`, 139 | `width: 1em;`, 140 | `height: 1em;`, 141 | `background-color: transparent;`, 142 | `background-blend-mode: normal;`, 143 | `background-image: url("${iconUrl}");`, 144 | `background-size: contain;`, 145 | `background-repeat: no-repeat;`, 146 | `background-position: center;`, 147 | `}`, 148 | ]; 149 | return body.join('\n'); 150 | } 151 | genFolderIconsEntryCSS(settings: FolderIcons): string { 152 | const selector = `data-path="${settings.path}"`; 153 | const iconUrl = this.getResourcePathwithType(settings.image, settings.type); 154 | let body: string[] = [ 155 | `.nav-folder-title[${selector}] .nav-folder-title-content::before {`, 156 | `content: '';`, 157 | `display: inline-block;`, 158 | `width: 16px;`, 159 | `height: 16px;`, 160 | `margin: 0px 2px -4px 0px;`, 161 | `background-color: transparent;`, 162 | `background-blend-mode: normal;`, 163 | `background-image: url("${iconUrl}");`, 164 | `background-size: contain;`, 165 | `background-repeat: no-repeat;`, 166 | `}`, 167 | ]; 168 | return body.join('\n'); 169 | } 170 | genFileIconsEntryCSS(settings: FileIcons): string { 171 | const iconUrl = this.getResourcePathwithType(settings.image, settings.type); 172 | let body: string[] = settings.path.map((path) => { 173 | const selector = `data-path$="${path}"`; 174 | return [ 175 | `.nav-file-title[${selector}] .nav-file-title-content::before {`, 176 | `content: '';`, 177 | `display: inline-block;`, 178 | `width: 16px;`, 179 | `height: 16px;`, 180 | `margin: 0px 2px -4px 0px;`, 181 | `background-color: transparent;`, 182 | `background-blend-mode: normal;`, 183 | `background-image: url("${iconUrl}");`, 184 | `background-size: contain;`, 185 | `background-repeat: no-repeat;`, 186 | `}` 187 | ].join('\n'); 188 | }); 189 | return body.join('\n\n'); 190 | } 191 | genInternalLinkIconsEntryCSS(settings: InternalLinkIcons): string { 192 | const iconUrl = this.getResourcePathwithType(settings.image, settings.type); 193 | let body: string[] = settings.path.map((path) => { 194 | const selector = `data-href$="${path}"`; 195 | return [ 196 | `.custom-icon .internal-link[${selector}]::before {`, 197 | `content: '';`, 198 | `display: inline-block;`, 199 | `width: 16px;`, 200 | `height: 16px;`, 201 | `margin: 0px 2px -2px 0px;`, 202 | `background-color: transparent;`, 203 | `background-blend-mode: normal;`, 204 | `background-image: url("${iconUrl}");`, 205 | `background-size: contain;`, 206 | `background-repeat: no-repeat;`, 207 | `}` 208 | ].join('\n'); 209 | }); 210 | return body.join('\n\n'); 211 | } 212 | 213 | svgToDataURI(svgContent: string): string { 214 | const encodedSVG = encodeURIComponent(svgContent); 215 | const dataURI = `data:image/svg+xml;charset=utf-8,${encodedSVG}`; 216 | return dataURI; 217 | } 218 | 219 | getResourcePath(path: string): string { 220 | let resourcePath = this.app.vault.adapter.getResourcePath(""); 221 | this.resourceBase = resourcePath.match(/(app:\/\/\w*?)\//)?.[1] as string; 222 | 223 | if (/^(https?:\/\/|data:)/.test(path)) { 224 | return path; 225 | } 226 | 227 | if (path.startsWith("'); 256 | } 257 | } 258 | 259 | getResourcePathwithType(path: string, type: string): string { 260 | let PATH = path.trim(); 261 | switch(type){ 262 | case 'custom': 263 | PATH = this.getResourcePath(path); 264 | break; 265 | case 'lucide': 266 | PATH = this.getLucidePath(path); 267 | break; 268 | default: 269 | PATH = this.getResourcePath(EMPTY_PNG_DATA_URL); 270 | break; 271 | } 272 | return PATH; 273 | } 274 | 275 | refreshSidebarIcons() { 276 | this.settings.SidebarIcons.forEach(icon => { 277 | document.querySelectorAll(`.workspace-tab-header[aria-label="${icon.label}"]`) 278 | .forEach(tabHeader => { 279 | tabHeader.classList.add('custom-icon'); 280 | tabHeader.setAttribute('data-icon-id', icon.id); 281 | }); 282 | }); 283 | 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /src/settings/folderSuggester.ts: -------------------------------------------------------------------------------- 1 | import { TAbstractFile, TFolder } from "obsidian"; 2 | import { TextInputSuggest } from "./suggesters"; 3 | 4 | export class FolderSuggest extends TextInputSuggest { 5 | getSuggestions(inputStr: string): TFolder[] { 6 | const abstractFiles = this.app.vault.getAllLoadedFiles(); 7 | const folders: TFolder[] = []; 8 | const lowerCaseInputStr = inputStr.toLowerCase(); 9 | 10 | abstractFiles.forEach((folder: TAbstractFile) => { 11 | if ( 12 | folder instanceof TFolder && 13 | folder.path.toLowerCase().contains(lowerCaseInputStr) 14 | ) { 15 | folders.push(folder); 16 | } 17 | }); 18 | 19 | return folders; 20 | } 21 | 22 | renderSuggestion(file: TFolder, el: HTMLElement): void { 23 | el.setText(file.path); 24 | } 25 | 26 | selectSuggestion(file: TFolder): void { 27 | this.inputEl.value = file.path; 28 | // this.inputEl.trigger("input"); 29 | this.inputEl.dispatchEvent(new Event('input')); 30 | this.close(); 31 | } 32 | } -------------------------------------------------------------------------------- /src/settings/settingstab.ts: -------------------------------------------------------------------------------- 1 | import { App, PluginSettingTab, Setting, DropdownComponent, TextAreaComponent, debounce } from 'obsidian'; 2 | import CustomIconPlugin from 'src/main'; 3 | import { DEFAULT_FILE_ICON, DEFAULT_FOLDER_ICON, DEFAULT_SETTINGS, DEFAULT_SIDEBAR_ICON } from 'src/types'; 4 | import { FolderSuggest } from 'src/settings/folderSuggester'; 5 | import { generateUniqueId, updatePreview } from 'src/utils/utils'; 6 | import { Locals } from 'src/i18n/i18n'; 7 | import { LocalProperty } from 'src/i18n/types'; 8 | 9 | export class CustomIconSettingTab extends PluginSettingTab { 10 | plugin: CustomIconPlugin; 11 | activeTab: string = 'SidebarTab'; 12 | activeSubTab: string; 13 | subTabState: Record; 14 | debouncedGenerate: Function; 15 | 16 | constructor(app: App, plugin: CustomIconPlugin) { 17 | super(app, plugin); 18 | this.plugin = plugin; 19 | this.debouncedGenerate = debounce(this.generateSnippet, 1000, true); 20 | this.subTabState = {}; 21 | } 22 | async generateSnippet() { 23 | await this.plugin.genSnippetCSS(this.plugin); 24 | } 25 | 26 | display(): void { 27 | const { containerEl } = this; 28 | const t = Locals.get(); 29 | 30 | containerEl.empty(); 31 | const settingsTitle = containerEl.createEl('div', {cls: 'csbi-setting-title'}); 32 | settingsTitle.createEl('h1', {text: `${t.Tab_Title}`}); 33 | 34 | const settingsTip = settingsTitle.createEl('div', {cls: 'csbi-setting-tip'}); 35 | settingsTip.createEl('h6', {text: `${t.Tips}`}); 36 | 37 | const settingsTabHeader = containerEl.createEl('nav', {cls: 'csbi-setting-header'}); 38 | const tabGroup = settingsTabHeader.createEl('div', {cls: 'csbi-setting-tab-group'}) 39 | 40 | const SidebarIconsTab = tabGroup.createEl('div', {cls: `csbi-tab ${this.activeTab === 'SidebarTab' ? 'csbi-tab-active' : ''}`, text: `${t.Tab_Sidebar}`}); 41 | SidebarIconsTab.addEventListener('click', () => { 42 | this.subTabState[this.activeTab] = this.activeSubTab; 43 | this.activeTab = 'SidebarTab'; 44 | this.activeSubTab = this.subTabState[this.activeTab] || 'SidebarIconsTab'; 45 | this.display(); 46 | }); 47 | const FolderIconsTab = tabGroup.createEl('div', {cls: `csbi-tab ${this.activeTab === 'FolderTab' ? 'csbi-tab-active' : ''}`, text: `${t.Tab_Folder}`}); 48 | FolderIconsTab.addEventListener('click', () => { 49 | this.subTabState[this.activeTab] = this.activeSubTab; 50 | this.activeTab = 'FolderTab'; 51 | this.activeSubTab = this.subTabState[this.activeTab] || 'FileIconsTab'; 52 | this.display(); 53 | }); 54 | const EditorIconsTab = tabGroup.createEl('div', {cls: `csbi-tab ${this.activeTab === 'EditorTab' ? 'csbi-tab-active' : ''}`, text: `${t.Tab_Editor}`}); 55 | EditorIconsTab.addEventListener('click', () => { 56 | this.subTabState[this.activeTab] = this.activeSubTab; 57 | this.activeTab = 'EditorTab'; 58 | this.activeSubTab = this.subTabState[this.activeTab] || 'InternalLinkIconsTab'; 59 | this.display(); 60 | }); 61 | const AboutTab = tabGroup.createEl('div', {cls: `csbi-tab ${this.activeTab === 'AboutTab' ? 'csbi-tab-active' : ''}`, text: `${t.Tab_About}`}); 62 | AboutTab.addEventListener('click', () => { 63 | this.activeTab = 'AboutTab'; 64 | this.display(); 65 | }); 66 | 67 | const settingsContent = containerEl.createEl('div', {cls: 'csbi-setting-content'}); 68 | const settingsFill = settingsTabHeader.createEl('div', {cls: 'csbi-fill'}); 69 | 70 | switch (this.activeTab) { 71 | case 'SidebarTab': 72 | this.displaySidebarTab(settingsContent, t); 73 | break; 74 | case 'FolderTab': 75 | this.displayFolderTab(settingsContent, t); 76 | break; 77 | case 'EditorTab': 78 | this.displayEditorTab(settingsContent, t); 79 | break; 80 | case 'AboutTab': 81 | this.displayAboutTab(settingsContent, t); 82 | break; 83 | default: 84 | break; 85 | } 86 | } 87 | 88 | displaySidebarTab(containerEl: HTMLElement, t: LocalProperty): void { 89 | const subTab = this.subTabState[this.activeTab] || 'SidebarIconsTab'; 90 | containerEl.empty(); 91 | const settingsSubTabHeader = containerEl.createEl('nav', {cls: 'csbi-setting-header'}); 92 | const subTabGroup = settingsSubTabHeader.createEl('div', {cls: 'csbi-setting-sub-tab-group'}); 93 | 94 | const SidebarIconsTab = subTabGroup.createEl('div', {cls: `csbi-sub-tab ${subTab === 'SidebarIconsTab' ? 'csbi-sub-tab-active' : ''}`, text: `${t.Tab_SidebarIcons}`}); 95 | SidebarIconsTab.addEventListener('click', () => { 96 | this.activeSubTab = 'SidebarIconsTab'; 97 | this.subTabState[this.activeTab] = this.activeSubTab; 98 | this.displaySidebarTab(containerEl,t); 99 | }); 100 | 101 | const subTabContent = containerEl.createEl('div', {cls: 'csbi-setting-sub-content'}); 102 | 103 | switch (subTab) { 104 | case 'SidebarIconsTab': 105 | this.SidebarIconsSetting(subTabContent, t); 106 | break; 107 | default: 108 | break; 109 | } 110 | } 111 | 112 | SidebarIconsSetting(containerEl: HTMLElement, t: LocalProperty): void { 113 | this.plugin.settings.SidebarIcons.forEach((icon, index) => { 114 | let previewEl: HTMLDivElement; 115 | 116 | const iconSetting = new Setting(containerEl) 117 | .setName(t.IconID.replace('{num}', `${icon.id}`)) 118 | 119 | iconSetting.addText(text => { 120 | text 121 | .setPlaceholder(t.SidebarIcons_FileName) 122 | .setValue(icon.label) 123 | .onChange(async (value) => { 124 | icon.label = value; 125 | await this.plugin.saveSettings(); 126 | this.plugin.refreshSidebarIcons(); 127 | this.debouncedGenerate(); 128 | let image = icon.image || DEFAULT_SIDEBAR_ICON; 129 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type) ); 130 | }) 131 | }); 132 | iconSetting.addDropdown(dropdown => { 133 | dropdown 134 | .addOption('custom', t.Type_Custom) 135 | .addOption('lucide', t.Type_Lucide) 136 | .setValue(icon.type || 'custom') 137 | .onChange(async (value) => { 138 | icon.type = value; 139 | await this.plugin.saveSettings(); 140 | let image = icon.image || DEFAULT_FILE_ICON; 141 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type) ); 142 | }) 143 | }); 144 | iconSetting.addTextArea(textArea => { 145 | previewEl = createDiv({ cls: 'icon-preview' }); 146 | textArea.inputEl.parentElement?.prepend(previewEl); 147 | textArea 148 | .setPlaceholder(t.IconImg) 149 | .setValue(icon.image) 150 | .onChange(async (value) => { 151 | icon.image = value; 152 | await this.plugin.saveSettings(); 153 | this.plugin.refreshSidebarIcons(); 154 | this.debouncedGenerate(); 155 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_SIDEBAR_ICON), icon.type) ); 156 | }) 157 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_SIDEBAR_ICON), icon.type) ); 158 | }); 159 | iconSetting.addButton(button => { 160 | button 161 | .setIcon("trash-2") 162 | .setCta() 163 | .onClick(async () => { 164 | const tabHeaderElement = document.querySelector(`.workspace-tab-header[data-icon-id="${icon.id}"]`); 165 | tabHeaderElement?.classList.remove('custom-icon'); 166 | tabHeaderElement?.removeAttribute('data-icon-id'); 167 | this.debouncedGenerate(); 168 | 169 | this.plugin.settings.SidebarIcons.splice(index, 1); 170 | await this.plugin.saveSettings(); 171 | this.display(); 172 | }) 173 | }); 174 | }); 175 | 176 | new Setting(containerEl) 177 | .addButton(button => 178 | button 179 | .setIcon("plus") 180 | .onClick(async () => { 181 | this.plugin.settings.SidebarIcons.push({ 182 | id: generateUniqueId("sidebar-icon"), 183 | label: '', 184 | image: '', 185 | type: "custom" 186 | }); 187 | await this.plugin.saveSettings(); 188 | this.display(); 189 | }) 190 | ); 191 | } 192 | 193 | displayFolderTab(containerEl: HTMLElement, t: LocalProperty): void { 194 | const subTab = this.subTabState[this.activeTab] || 'FileIconsTab'; 195 | containerEl.empty(); 196 | const settingsSubTabHeader = containerEl.createEl('nav', {cls: 'csbi-setting-header'}); 197 | const subTabGroup = settingsSubTabHeader.createEl('div', {cls: 'csbi-setting-sub-tab-group'}); 198 | 199 | const FileIconsTab = subTabGroup.createEl('div', {cls: `csbi-sub-tab ${subTab === 'FileIconsTab' ? 'csbi-sub-tab-active' : ''}`, text: `${t.Tab_FileIcons}`}); 200 | FileIconsTab.addEventListener('click', () => { 201 | this.activeSubTab = 'FileIconsTab'; 202 | this.subTabState[this.activeTab] = this.activeSubTab; 203 | this.displayFolderTab(containerEl,t); 204 | }); 205 | const FolderIconsTab = subTabGroup.createEl('div', {cls: `csbi-sub-tab ${subTab === 'FolderIconsTab' ? 'csbi-sub-tab-active' : ''}`, text: `${t.Tab_FolderIcons}`}); 206 | FolderIconsTab.addEventListener('click', () => { 207 | this.activeSubTab = 'FolderIconsTab'; 208 | this.subTabState[this.activeTab] = this.activeSubTab; 209 | this.displayFolderTab(containerEl,t); 210 | }); 211 | 212 | const subTabContent = containerEl.createEl('div', {cls: 'csbi-setting-sub-content'}); 213 | 214 | switch (subTab) { 215 | case 'FolderIconsTab': 216 | this.DefaultFolderIcon(subTabContent, t); 217 | this.FolderIconsSetting(subTabContent, t); 218 | break; 219 | case 'FileIconsTab': 220 | this.DefaultFileIcon(subTabContent, t); 221 | this.FileIconsSetting(subTabContent, t); 222 | break; 223 | default: 224 | break; 225 | } 226 | } 227 | 228 | DefaultFolderIcon(containerEl: HTMLElement, t: LocalProperty): void { 229 | let previewEl: HTMLDivElement; 230 | let dropdownComponent: DropdownComponent; 231 | let textAreaComponent: TextAreaComponent; 232 | const icon = this.plugin.settings.DefaultFolderIcon[0]; 233 | 234 | containerEl.createEl('h2', {text: t.FolderIcons_Title}); 235 | 236 | const iconSetting = new Setting(containerEl) 237 | .setName(t.FolderIcons_Default); 238 | 239 | iconSetting.addDropdown(dropdown => { 240 | dropdownComponent = dropdown; 241 | dropdown 242 | .addOption('custom', t.Type_Custom) 243 | .addOption('lucide', t.Type_Lucide) 244 | .setValue(icon.type || 'custom') 245 | .onChange(async (value) => { 246 | icon.type = value; 247 | let image = icon.image || DEFAULT_FOLDER_ICON; 248 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type)); 249 | await this.plugin.saveSettings(); 250 | }); 251 | }); 252 | iconSetting.addTextArea(textArea => { 253 | textAreaComponent = textArea; 254 | previewEl = createDiv({ cls: 'icon-preview' }); 255 | textArea.inputEl.parentElement?.prepend(previewEl); 256 | textArea 257 | .setPlaceholder(t.IconImg) 258 | .setValue(icon.image) 259 | .onChange(async (value) => { 260 | icon.image = value; 261 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FOLDER_ICON), icon.type)); 262 | await this.plugin.saveSettings(); 263 | }); 264 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FOLDER_ICON), icon.type)); 265 | }); 266 | iconSetting.addButton(button => { 267 | button 268 | .setIcon("rotate-cw") 269 | .setCta() 270 | .onClick(async () => { 271 | icon.type = DEFAULT_SETTINGS.DefaultFolderIcon[0].type; 272 | icon.image = DEFAULT_SETTINGS.DefaultFolderIcon[0].image; 273 | dropdownComponent.setValue(icon.type); 274 | textAreaComponent.setValue(icon.image); 275 | updatePreview(previewEl, this.plugin.getResourcePathwithType(icon.image, icon.type)); 276 | await this.plugin.saveSettings(); 277 | }); 278 | }); 279 | } 280 | 281 | DefaultFileIcon(containerEl: HTMLElement, t: LocalProperty): void { 282 | let previewEl: HTMLDivElement; 283 | let dropdownComponent: DropdownComponent; 284 | let textAreaComponent: TextAreaComponent; 285 | const icon = this.plugin.settings.DefaultFileIcon[0]; 286 | 287 | containerEl.createEl('h2', {text: t.FileIcons_Title}); 288 | 289 | const iconSetting = new Setting(containerEl) 290 | .setName(t.FileIcons_Default); 291 | 292 | iconSetting.addDropdown(dropdown => { 293 | dropdownComponent = dropdown; 294 | dropdown 295 | .addOption('custom', t.Type_Custom) 296 | .addOption('lucide', t.Type_Lucide) 297 | .setValue(icon.type || 'custom') 298 | .onChange(async (value) => { 299 | icon.type = value; 300 | let image = icon.image || DEFAULT_FILE_ICON; 301 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type)); 302 | await this.plugin.saveSettings(); 303 | }); 304 | }); 305 | iconSetting.addTextArea(textArea => { 306 | textAreaComponent = textArea; 307 | previewEl = createDiv({ cls: 'icon-preview' }); 308 | textArea.inputEl.parentElement?.prepend(previewEl); 309 | textArea 310 | .setPlaceholder(t.IconImg) 311 | .setValue(icon.image) 312 | .onChange(async (value) => { 313 | icon.image = value; 314 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FILE_ICON), icon.type)); 315 | await this.plugin.saveSettings(); 316 | }); 317 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FILE_ICON), icon.type)); 318 | }); 319 | iconSetting.addButton(button => { 320 | button 321 | .setIcon("rotate-cw") 322 | .setCta() 323 | .onClick(async () => { 324 | icon.type = DEFAULT_SETTINGS.DefaultFileIcon[0].type; 325 | icon.image = DEFAULT_SETTINGS.DefaultFileIcon[0].image; 326 | dropdownComponent.setValue(icon.type); 327 | textAreaComponent.setValue(icon.image); 328 | updatePreview(previewEl, this.plugin.getResourcePathwithType(icon.image, icon.type)); 329 | await this.plugin.saveSettings(); 330 | }); 331 | }); 332 | } 333 | 334 | FolderIconsSetting(containerEl: HTMLElement, t: LocalProperty): void { 335 | this.plugin.settings.FolderIcons.forEach((icon, index) => { 336 | let previewEl: HTMLDivElement; 337 | 338 | const iconSetting = new Setting(containerEl) 339 | .setName(t.IconID.replace('{num}', `${icon.id}`)) 340 | 341 | iconSetting.addSearch(search => { 342 | new FolderSuggest(this.app, search.inputEl); 343 | search 344 | .setPlaceholder(t.FolderIcons_FileName) 345 | .setValue(icon.path) 346 | .onChange(path => { 347 | icon.path = path; 348 | this.plugin.saveSettings(); 349 | this.debouncedGenerate(); 350 | let image = icon.image || DEFAULT_FOLDER_ICON; 351 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type)); 352 | }) 353 | }); 354 | iconSetting.addDropdown(dropdown => { 355 | dropdown 356 | .addOption('custom', t.Type_Custom) 357 | .addOption('lucide', t.Type_Lucide) 358 | .setValue(icon.type || 'custom') 359 | .onChange(async (value) => { 360 | icon.type = value; 361 | await this.plugin.saveSettings(); 362 | this.debouncedGenerate(); 363 | let image = icon.image || DEFAULT_FOLDER_ICON; 364 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type)); 365 | }) 366 | }); 367 | iconSetting.addTextArea(textArea => { 368 | previewEl = createDiv({ cls: 'icon-preview' }); 369 | textArea.inputEl.parentElement?.prepend(previewEl); 370 | textArea 371 | .setPlaceholder(t.IconImg) 372 | .setValue(icon.image) 373 | .onChange(async (value) => { 374 | icon.image = value; 375 | await this.plugin.saveSettings(); 376 | this.debouncedGenerate(); 377 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FOLDER_ICON), icon.type)); 378 | }); 379 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FOLDER_ICON), icon.type)); 380 | }); 381 | iconSetting.addButton(button => { 382 | button 383 | .setIcon("trash-2") 384 | .setCta() 385 | .onClick(async () => { 386 | // const tabHeaderElement = document.querySelector(`.nav-folder-title[data-icon-id="${icon.id}"]`); 387 | // tabHeaderElement?.classList.remove('custom-icon'); 388 | // tabHeaderElement?.removeAttribute('data-icon-id'); 389 | this.debouncedGenerate(); 390 | 391 | this.plugin.settings.FolderIcons.splice(index, 1); 392 | await this.plugin.saveSettings(); 393 | this.display(); 394 | }) 395 | }); 396 | }); 397 | 398 | new Setting(containerEl) 399 | .addButton(button => 400 | button 401 | .setIcon("plus") 402 | .onClick(async () => { 403 | this.plugin.settings.FolderIcons.push({ 404 | id: generateUniqueId("folder-icon"), 405 | path: '', 406 | image: this.plugin.settings.DefaultFolderIcon[0].image, 407 | type: this.plugin.settings.DefaultFolderIcon[0].type 408 | }); 409 | await this.plugin.saveSettings(); 410 | this.display(); 411 | }) 412 | ); 413 | } 414 | 415 | FileIconsSetting(containerEl: HTMLElement, t: LocalProperty): void { 416 | this.plugin.settings.FileIcons.forEach((icon, index) => { 417 | let previewEl: HTMLDivElement; 418 | 419 | const iconSetting = new Setting(containerEl) 420 | .setName(t.IconID.replace('{num}', `${icon.id}`)) 421 | 422 | iconSetting.addText(text => { 423 | text 424 | .setPlaceholder(t.FileIcons_FileExt) 425 | .setValue(icon.path.join(',')) 426 | .onChange(async (value) => { 427 | icon.path = value.split(',').map(ext => ext.trim());; 428 | await this.plugin.saveSettings(); 429 | this.plugin.refreshSidebarIcons(); 430 | this.debouncedGenerate(); 431 | let image = icon.image || DEFAULT_FILE_ICON; 432 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type)); 433 | }) 434 | }); 435 | iconSetting.addDropdown(dropdown => { 436 | dropdown 437 | .addOption('custom', t.Type_Custom) 438 | .addOption('lucide', t.Type_Lucide) 439 | .setValue(icon.type || 'custom') 440 | .onChange(async (value) => { 441 | icon.type = value; 442 | await this.plugin.saveSettings(); 443 | this.debouncedGenerate(); 444 | let image = icon.image || DEFAULT_FILE_ICON; 445 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type)); 446 | }) 447 | }); 448 | iconSetting.addTextArea(textArea => { 449 | previewEl = createDiv({ cls: 'icon-preview' }); 450 | textArea.inputEl.parentElement?.prepend(previewEl); 451 | textArea 452 | .setValue(icon.image) 453 | .setPlaceholder(t.IconImg) 454 | .onChange(async (value) => { 455 | icon.image = value; 456 | await this.plugin.saveSettings(); 457 | this.debouncedGenerate(); 458 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FILE_ICON), icon.type)); 459 | }) 460 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FILE_ICON), icon.type)); 461 | }); 462 | iconSetting.addButton(button => { 463 | button 464 | .setIcon("trash-2") 465 | .setCta() 466 | .onClick(async () => { 467 | // const tabHeaderElement = document.querySelector(`.nav-file-title[data-icon-id="${icon.id}"]`); 468 | // tabHeaderElement?.classList.remove('custom-icon'); 469 | // tabHeaderElement?.removeAttribute('data-icon-id'); 470 | this.debouncedGenerate(); 471 | 472 | this.plugin.settings.FileIcons.splice(index, 1); 473 | await this.plugin.saveSettings(); 474 | this.display(); 475 | }) 476 | }); 477 | }); 478 | 479 | new Setting(containerEl) 480 | .addButton(button => 481 | button 482 | .setIcon("plus") 483 | .onClick(async () => { 484 | this.plugin.settings.FileIcons.push({ 485 | id: generateUniqueId("file-icon"), 486 | path: [''], 487 | image: this.plugin.settings.DefaultFileIcon[0].image, 488 | type: this.plugin.settings.DefaultFileIcon[0].type 489 | }); 490 | await this.plugin.saveSettings(); 491 | this.display(); 492 | }) 493 | ); 494 | } 495 | 496 | displayEditorTab(containerEl: HTMLElement, t: LocalProperty): void { 497 | const subTab = this.subTabState[this.activeTab] || 'InternalLinkIconsTab'; 498 | containerEl.empty(); 499 | const settingsSubTabHeader = containerEl.createEl('nav', {cls: 'csbi-setting-header'}); 500 | const subTabGroup = settingsSubTabHeader.createEl('div', {cls: 'csbi-setting-sub-tab-group'}); 501 | 502 | const InternalLinkIconsTab = subTabGroup.createEl('div', {cls: `csbi-sub-tab ${subTab === 'InternalLinkIconsTab' ? 'csbi-sub-tab-active' : ''}`, text: `${t.Tab_InternalLinkIcons}`}); 503 | 504 | InternalLinkIconsTab.addEventListener('click', () => { 505 | this.activeSubTab = 'InternalLinkIconsTab'; 506 | this.subTabState[this.activeTab] = this.activeSubTab; 507 | this.displayEditorTab(containerEl,t); 508 | }); 509 | 510 | const subTabContent = containerEl.createEl('div', {cls: 'csbi-setting-sub-content'}); 511 | 512 | switch (subTab) { 513 | case 'InternalLinkIconsTab': 514 | this.InternalLinkIconsSetting(subTabContent, t); 515 | break; 516 | default: 517 | break; 518 | } 519 | } 520 | 521 | InternalLinkIconsSetting(containerEl: HTMLElement, t: LocalProperty): void { 522 | containerEl.createEl('h2', {text: t.InternalLinkIcons_Title}); 523 | this.plugin.settings.InternalLinkIcons.forEach((icon, index) => { 524 | let previewEl: HTMLDivElement; 525 | 526 | const iconSetting = new Setting(containerEl) 527 | .setName(t.IconID.replace('{num}', `${icon.id}`)) 528 | 529 | iconSetting.addText(text => { 530 | text 531 | .setPlaceholder(t.FileIcons_FileExt) 532 | .setValue(icon.path.join(',')) 533 | .onChange(async (value) => { 534 | icon.path = value.split(',').map(ext => ext.trim());; 535 | await this.plugin.saveSettings(); 536 | this.plugin.refreshSidebarIcons(); 537 | this.debouncedGenerate(); 538 | let image = icon.image || DEFAULT_FILE_ICON; 539 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type)); 540 | }) 541 | }); 542 | iconSetting.addDropdown(dropdown => { 543 | dropdown 544 | .addOption('custom', t.Type_Custom) 545 | .addOption('lucide', t.Type_Lucide) 546 | .setValue(icon.type || 'custom') 547 | .onChange(async (value) => { 548 | icon.type = value; 549 | await this.plugin.saveSettings(); 550 | this.debouncedGenerate(); 551 | let image = icon.image || DEFAULT_FILE_ICON; 552 | updatePreview(previewEl, this.plugin.getResourcePathwithType(image, icon.type)); 553 | }) 554 | }); 555 | iconSetting.addTextArea(textArea => { 556 | previewEl = createDiv({ cls: 'icon-preview' }); 557 | textArea.inputEl.parentElement?.prepend(previewEl); 558 | textArea 559 | .setValue(icon.image) 560 | .setPlaceholder(t.IconImg) 561 | .onChange(async (value) => { 562 | icon.image = value; 563 | await this.plugin.saveSettings(); 564 | this.debouncedGenerate(); 565 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FILE_ICON), icon.type)); 566 | }) 567 | updatePreview(previewEl, this.plugin.getResourcePathwithType((icon.image.trim() || DEFAULT_FILE_ICON), icon.type)); 568 | }); 569 | iconSetting.addButton(button => { 570 | button 571 | .setIcon("trash-2") 572 | .setCta() 573 | .onClick(async () => { 574 | // const tabHeaderElement = document.querySelector(`.internal-link[data-icon-id="${icon.id}"]`); 575 | // tabHeaderElement?.classList.remove('custom-icon'); 576 | // tabHeaderElement?.removeAttribute('data-icon-id'); 577 | this.debouncedGenerate(); 578 | 579 | this.plugin.settings.InternalLinkIcons.splice(index, 1); 580 | await this.plugin.saveSettings(); 581 | this.display(); 582 | }) 583 | }); 584 | }); 585 | 586 | new Setting(containerEl) 587 | .addButton(button => 588 | button 589 | .setIcon("plus") 590 | .onClick(async () => { 591 | this.plugin.settings.InternalLinkIcons.push({ 592 | id: generateUniqueId("internalLink-icon"), 593 | path: [''], 594 | image: "file-text", 595 | type: "lucide" 596 | }); 597 | await this.plugin.saveSettings(); 598 | this.display(); 599 | }) 600 | ); 601 | } 602 | 603 | displayAboutTab(containerEl: HTMLElement, t: LocalProperty): void { 604 | const pEl = containerEl.createEl('div'); 605 | pEl.addClass("csbi-setting-about"); 606 | pEl.innerHTML = t.About; 607 | } 608 | } -------------------------------------------------------------------------------- /src/settings/suggesters.ts: -------------------------------------------------------------------------------- 1 | import { ISuggestOwner, Scope, App } from "obsidian"; 2 | import { createPopper, Instance as PopperInstance } from "@popperjs/core"; 3 | 4 | const wrapAround = (value: number, size: number): number => { 5 | return ((value % size) + size) % size; 6 | }; 7 | 8 | class Suggest { 9 | private owner: ISuggestOwner; 10 | private values: T[]; 11 | private suggestions: HTMLDivElement[]; 12 | private selectedItem: number; 13 | private containerEl: HTMLElement; 14 | private app: App; 15 | 16 | constructor( 17 | owner: ISuggestOwner, 18 | containerEl: HTMLElement, 19 | scope: Scope, 20 | app: App 21 | ){ 22 | this.owner = owner; 23 | this.containerEl = containerEl; 24 | this.app = app; 25 | 26 | containerEl.on( 27 | "click", 28 | ".suggestion-item", 29 | this.onSuggestionClick.bind(this) 30 | ); 31 | containerEl.on( 32 | "mousemove", 33 | ".suggestion-item", 34 | this.onSuggestionMouseover.bind(this) 35 | ); 36 | 37 | scope.register([], "ArrowUp", (event) => { 38 | if (!event.isComposing) { 39 | this.setSelectedItem(this.selectedItem - 1, true); 40 | return false; 41 | } 42 | }); 43 | 44 | scope.register([], "ArrowDown", (event) => { 45 | if (!event.isComposing) { 46 | this.setSelectedItem(this.selectedItem + 1, true); 47 | return false; 48 | } 49 | }); 50 | 51 | scope.register([], "Enter", (event) => { 52 | if (!event.isComposing) { 53 | this.useSelectedItem(event); 54 | return false; 55 | } 56 | }); 57 | } 58 | 59 | onSuggestionClick(event: MouseEvent, el: HTMLDivElement): void { 60 | event.preventDefault(); 61 | 62 | const item = this.suggestions.indexOf(el); 63 | this.setSelectedItem(item, false); 64 | this.useSelectedItem(event); 65 | } 66 | 67 | onSuggestionMouseover(_event: MouseEvent, el: HTMLDivElement): void { 68 | const item = this.suggestions.indexOf(el); 69 | this.setSelectedItem(item, false); 70 | } 71 | 72 | setSuggestions(values: T[]) { 73 | this.containerEl.empty(); 74 | const suggestionEls: HTMLDivElement[] = []; 75 | 76 | values.forEach((value) => { 77 | const suggestionEl = this.containerEl.createDiv("suggestion-item"); 78 | this.owner.renderSuggestion(value, suggestionEl); 79 | suggestionEls.push(suggestionEl); 80 | }); 81 | 82 | this.values = values; 83 | this.suggestions = suggestionEls; 84 | this.setSelectedItem(0, false); 85 | } 86 | 87 | useSelectedItem(event: MouseEvent | KeyboardEvent) { 88 | const currentValue = this.values[this.selectedItem]; 89 | if (currentValue) { 90 | this.owner.selectSuggestion(currentValue, event); 91 | } 92 | } 93 | 94 | setSelectedItem(selectedIndex: number, scrollIntoView: boolean) { 95 | const normalizedIndex = wrapAround( 96 | selectedIndex, 97 | this.suggestions.length 98 | ); 99 | const prevSelectedSuggestion = this.suggestions[this.selectedItem]; 100 | const selectedSuggestion = this.suggestions[normalizedIndex]; 101 | 102 | prevSelectedSuggestion?.removeClass("is-selected"); 103 | selectedSuggestion?.addClass("is-selected"); 104 | 105 | this.selectedItem = normalizedIndex; 106 | 107 | if (scrollIntoView) { 108 | selectedSuggestion.scrollIntoView(false); 109 | } 110 | } 111 | } 112 | 113 | export abstract class TextInputSuggest implements ISuggestOwner { 114 | protected inputEl: HTMLInputElement | HTMLTextAreaElement; 115 | protected app: App; 116 | 117 | private popper: PopperInstance; 118 | private scope: Scope; 119 | private suggestEl: HTMLElement; 120 | private suggest: Suggest; 121 | 122 | constructor(app: App, inputEl: HTMLInputElement | HTMLTextAreaElement) { 123 | this.app = app; 124 | this.inputEl = inputEl; 125 | this.scope = new Scope(); 126 | 127 | this.suggestEl = createDiv("suggestion-container"); 128 | const suggestion = this.suggestEl.createDiv("suggestion"); 129 | this.suggest = new Suggest(this, suggestion, this.scope, app); 130 | 131 | this.scope.register([], "Escape", this.close.bind(this)); 132 | 133 | this.inputEl.addEventListener("input", this.onInputChanged.bind(this)); 134 | this.inputEl.addEventListener("focus", this.onInputChanged.bind(this)); 135 | this.inputEl.addEventListener("blur", this.close.bind(this)); 136 | this.suggestEl.on( 137 | "mousedown", 138 | ".suggestion-container", 139 | (event: MouseEvent) => { 140 | event.preventDefault(); 141 | } 142 | ); 143 | } 144 | 145 | onInputChanged(): void { 146 | const inputStr = this.inputEl.value; 147 | const suggestions = this.getSuggestions(inputStr); 148 | 149 | if (!suggestions) { 150 | this.close(); 151 | return; 152 | } 153 | 154 | if (suggestions.length > 0) { 155 | this.suggest.setSuggestions(suggestions); 156 | // @ts-ignore 157 | // this.open(this.app.dom.appContainerEl, this.inputEl); 158 | this.open(this.app.workspace.containerEl, this.inputEl); 159 | } else { 160 | this.close(); 161 | } 162 | } 163 | 164 | open(container: HTMLElement, inputEl: HTMLElement): void { 165 | this.app.keymap.pushScope(this.scope); 166 | 167 | container.appendChild(this.suggestEl); 168 | this.popper = createPopper(inputEl, this.suggestEl, { 169 | placement: "bottom-start", 170 | modifiers: [ 171 | { 172 | name: "sameWidth", 173 | enabled: true, 174 | fn: ({ state, instance }) => { 175 | const targetWidth = `${state.rects.reference.width}px`; 176 | if (state.styles.popper.width === targetWidth) { 177 | return; 178 | } 179 | state.styles.popper.width = targetWidth; 180 | instance.update(); 181 | }, 182 | phase: "beforeWrite", 183 | requires: ["computeStyles"], 184 | }, 185 | ], 186 | }); 187 | } 188 | 189 | close(): void { 190 | this.app.keymap.popScope(this.scope); 191 | 192 | this.suggest.setSuggestions([]); 193 | if (this.popper) this.popper.destroy(); 194 | this.suggestEl.detach(); 195 | } 196 | 197 | abstract getSuggestions(inputStr: string): T[]; 198 | abstract renderSuggestion(item: T, el: HTMLElement): void; 199 | abstract selectSuggestion(item: T): void; 200 | } 201 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | :root { 3 | --tab-font-size: 14px; 4 | --sub-tab-font-size: 12px; 5 | } 6 | 7 | .csbi-setting-title { 8 | display: flex; 9 | align-items: baseline; 10 | justify-content: space-between; 11 | } 12 | .csbi-setting-tip { 13 | display: flex; 14 | align-items: baseline; 15 | justify-content: space-between; 16 | font-size: 12px; 17 | color: var(--text-muted); 18 | } 19 | .csbi-setting-header { 20 | margin-bottom: 4px; 21 | overflow-y: hidden; 22 | overflow-x: auto; 23 | } 24 | .csbi-setting-tab-group, 25 | .csbi-setting-sub-tab-group { 26 | display: flex; 27 | align-items: flex-end; 28 | border-bottom: 2px solid var(--background-modifier-border); 29 | margin-bottom: 4px; 30 | } 31 | .csbi-tab, 32 | .csbi-sub-tab { 33 | padding: 6px 12px; 34 | font-weight: 600; 35 | cursor: pointer; 36 | white-space: nowrap; 37 | color: var(--text-muted); 38 | transition: color 0.2s ease-in-out, background-color 0.2s ease-in-out; 39 | } 40 | .csbi-tab { 41 | font-size: var(--tab-font-size); 42 | } 43 | .csbi-sub-tab { 44 | font-size: var(--sub-tab-font-size); 45 | } 46 | .csbi-tab:hover, 47 | .csbi-sub-tab:hover { 48 | background-color: var(--background-modifier-hover); 49 | color: var(--text-normal); 50 | border-radius: 3px; 51 | } 52 | .csbi-tab.csbi-tab-active, 53 | .csbi-sub-tab.csbi-sub-tab-active { 54 | transform: translateY(2px); 55 | border: 2px solid var(--interactive-accent); 56 | background-color: var(--background-primary); 57 | color: var(--text-accent); 58 | } 59 | .csbi-tab.csbi-tab-active { 60 | border-radius: 3px; 61 | border-bottom-color: transparent; 62 | } 63 | .csbi-sub-tab.csbi-sub-tab-active { 64 | border-radius: 100px; 65 | } 66 | .csbi-setting-content, 67 | .csbi-setting-sub-content { 68 | height: calc(100% - 10rem); 69 | } 70 | .csbi-fill { 71 | border: 2px solid #0000; 72 | width: 100%; 73 | } 74 | .csbi-setting-about { 75 | font-size: 12px; 76 | } 77 | 78 | .icon-preview { 79 | display: inline-flex; 80 | width: 32px; 81 | height: 32px; 82 | align-items: center; 83 | justify-content: center; 84 | margin-right: 2px; 85 | border-radius: 50%; 86 | border: 1px solid var(--background-modifier-border); 87 | background-size: 24px 24px; 88 | background-repeat: no-repeat; 89 | background-position: center; 90 | } 91 | 92 | .custom-icon.workspace-tab-header[data-icon-id] .workspace-tab-header-inner-icon > svg { 93 | display: none; 94 | } 95 | .custom-icon[aria-label] .workspace-tab-header-status-container { 96 | display: none; 97 | } -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | export const EMPTY_PNG_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" 2 | export const DEFAULT_SIDEBAR_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWZpbGUiPjxwYXRoIGQ9Ik0xNSAySDZhMiAyIDAgMCAwLTIgMnYxNmEyIDIgMCAwIDAgMiAyaDEyYTIgMiAwIDAgMCAyLTJWN1oiLz48cGF0aCBkPSJNMTQgMnY0YTIgMiAwIDAgMCAyIDJoNCIvPjwvc3ZnPg=="; 3 | export const DEFAULT_FOLDER_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWNyb3duIj48cGF0aCBkPSJNMTEuNTYyIDMuMjY2YS41LjUgMCAwIDEgLjg3NiAwTDE1LjM5IDguODdhMSAxIDAgMCAwIDEuNTE2LjI5NEwyMS4xODMgNS41YS41LjUgMCAwIDEgLjc5OC41MTlsLTIuODM0IDEwLjI0NmExIDEgMCAwIDEtLjk1Ni43MzRINS44MWExIDEgMCAwIDEtLjk1Ny0uNzM0TDIuMDIgNi4wMmEuNS41IDAgMCAxIC43OTgtLjUxOWw0LjI3NiAzLjY2NGExIDEgMCAwIDAgMS41MTYtLjI5NHoiLz48cGF0aCBkPSJNNSAyMWgxNCIvPjwvc3ZnPg==" 4 | export const DEFAULT_FILE_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWZpbGUtdGV4dCI+PHBhdGggZD0iTTE1IDJINmEyIDIgMCAwIDAtMiAydjE2YTIgMiAwIDAgMCAyIDJoMTJhMiAyIDAgMCAwIDItMlY3WiIvPjxwYXRoIGQ9Ik0xNCAydjRhMiAyIDAgMCAwIDIgMmg0Ii8+PHBhdGggZD0iTTEwIDlIOCIvPjxwYXRoIGQ9Ik0xNiAxM0g4Ii8+PHBhdGggZD0iTTE2IDE3SDgiLz48L3N2Zz4="; 5 | export interface CustomIconSettings { 6 | customIcons: Array; 7 | SidebarIcons: Array; 8 | FolderIcons: Array; 9 | FileIcons: Array; 10 | InternalLinkIcons: Array; 11 | DefaultFolderIcon: Array; 12 | DefaultFileIcon: Array; 13 | } 14 | 15 | export interface DefaultIcon { 16 | image: string; 17 | type: string; 18 | } 19 | 20 | export interface SidebarIcons { 21 | id: string; 22 | label: string; 23 | image: string; 24 | type: string; 25 | } 26 | 27 | export interface FolderIcons { 28 | id: string; 29 | path: string; 30 | image: string; 31 | type: string; 32 | } 33 | 34 | export interface FileIcons { 35 | id: string; 36 | path: string[]; 37 | image: string; 38 | type: string; 39 | } 40 | 41 | export interface InternalLinkIcons { 42 | id: string; 43 | path: string[]; 44 | image: string; 45 | type: string; 46 | } 47 | 48 | export const DEFAULT_SETTINGS: CustomIconSettings = { 49 | DefaultFolderIcon: [{ image: "crown", type: "lucide" }], 50 | DefaultFileIcon: [{ image: "file-text", type: "lucide" }], 51 | SidebarIcons: [], 52 | FolderIcons: [], 53 | FileIcons: [], 54 | InternalLinkIcons: [{id: "internalLink-icon-123456789", path: ["md"], image: "file-text", type: "lucide"}], 55 | customIcons: [] 56 | } -------------------------------------------------------------------------------- /src/utils/utils.ts: -------------------------------------------------------------------------------- 1 | export function generateUniqueId(prefixstr: string): string { 2 | return prefixstr + '-' + Math.random().toString(36).substr(2, 9); 3 | } 4 | 5 | export function updatePreview(previewEl: HTMLDivElement, image: string): void { 6 | previewEl.empty(); 7 | previewEl.setAttribute('style', `background-image: url('${image}')`); 8 | } 9 | 10 | export function convertToCamelCase(name: string): string { 11 | return name.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join(''); 12 | } -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | :root{--tab-font-size: 14px;--sub-tab-font-size: 12px}.csbi-setting-title{display:flex;align-items:baseline;justify-content:space-between}.csbi-setting-tip{display:flex;align-items:baseline;justify-content:space-between;font-size:12px;color:var(--text-muted)}.csbi-setting-header{margin-bottom:4px;overflow-y:hidden;overflow-x:auto}.csbi-setting-tab-group,.csbi-setting-sub-tab-group{display:flex;align-items:flex-end;border-bottom:2px solid var(--background-modifier-border);margin-bottom:4px}.csbi-tab,.csbi-sub-tab{padding:6px 12px;font-weight:600;cursor:pointer;white-space:nowrap;color:var(--text-muted);transition:color .2s ease-in-out,background-color .2s ease-in-out}.csbi-tab{font-size:var(--tab-font-size)}.csbi-sub-tab{font-size:var(--sub-tab-font-size)}.csbi-tab:hover,.csbi-sub-tab:hover{background-color:var(--background-modifier-hover);color:var(--text-normal);border-radius:3px}.csbi-tab.csbi-tab-active,.csbi-sub-tab.csbi-sub-tab-active{transform:translateY(2px);border:2px solid var(--interactive-accent);background-color:var(--background-primary);color:var(--text-accent)}.csbi-tab.csbi-tab-active{border-radius:3px;border-bottom-color:transparent}.csbi-sub-tab.csbi-sub-tab-active{border-radius:100px}.csbi-setting-content,.csbi-setting-sub-content{height:calc(100% - 10rem)}.csbi-fill{border:2px solid #0000;width:100%}.csbi-setting-about{font-size:12px}.icon-preview{display:inline-flex;width:32px;height:32px;align-items:center;justify-content:center;margin-right:2px;border-radius:50%;border:1px solid var(--background-modifier-border);background-size:24px 24px;background-repeat:no-repeat;background-position:center}.custom-icon.workspace-tab-header[data-icon-id] .workspace-tab-header-inner-icon>svg{display:none}.custom-icon[aria-label] .workspace-tab-header-status-container{display:none} 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "ES6", 8 | "allowJs": true, 9 | "noImplicitAny": true, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "isolatedModules": true, 13 | "strictNullChecks": true, 14 | "lib": [ 15 | "DOM", 16 | "ES5", 17 | "ES6", 18 | "ES7" 19 | ] 20 | }, 21 | "include": [ 22 | "**/*.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "0.1.0": "0.15.0" 3 | } 4 | --------------------------------------------------------------------------------