init
This commit is contained in:
@@ -129,6 +129,9 @@ dist
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# Obsidian plugin build output
|
||||
main.js
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
|
||||
@@ -1,2 +1,90 @@
|
||||
# zeroq-qol-modules
|
||||
# ZeroQ QoL Modules
|
||||
|
||||
Модульный плагин для **Obsidian** с набором QoL-функций, которые можно включать и отключать в настройках.
|
||||
|
||||
## Установка
|
||||
|
||||
1. Скачайте `main.js`, `manifest.json` и `styles.css` из [релизов](https://github.com/your/repo/releases)
|
||||
2. Поместите их в папку `.obsidian/plugins/zeroq-qol-modules/` вашего хранилища
|
||||
3. В Obsidian: **Настройки** → **Community plugins** → **Включить**
|
||||
4. Активируйте плагин **ZeroQ QoL Modules**
|
||||
|
||||
## Модули
|
||||
|
||||
| Модуль | Описание |
|
||||
|--------|----------|
|
||||
| **Attachment Clean Paste** | Заменяет `![[вложение]]` на `[[вложение|имя]]` при вставке/перетаскивании файлов с указанными расширениями |
|
||||
|
||||
Каждый модуль включается/отключается в настройках плагина.
|
||||
|
||||
## Разработка
|
||||
|
||||
### Добавление нового модуля
|
||||
|
||||
1. Создайте папку `src/modules/my-module/`
|
||||
2. Создайте класс, унаследованный от `BaseModule`:
|
||||
|
||||
```typescript
|
||||
import { BaseModule } from '../base-module';
|
||||
|
||||
export class MyModule extends BaseModule {
|
||||
id = 'my-module';
|
||||
name = 'My Module';
|
||||
description = 'Описание модуля';
|
||||
|
||||
get defaultSettings() {
|
||||
return { /* настройки по умолчанию */ };
|
||||
}
|
||||
|
||||
onload(plugin, moduleSettings) {
|
||||
// инициализация: регистрация событий, команд, настроек
|
||||
}
|
||||
|
||||
onunload(plugin) {
|
||||
// очистка (cleanup происходит автоматически через registerCleanup)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Зарегистрируйте модуль в `src/modules/index.ts`:
|
||||
|
||||
```typescript
|
||||
import { MyModule } from './my-module';
|
||||
|
||||
export const MODULES: QoLModule[] = [
|
||||
new AttachmentCleanPasteModule(),
|
||||
new MyModule(),
|
||||
];
|
||||
```
|
||||
|
||||
4. Если модулю нужна своя вкладка настроек — создайте `PluginSettingTab` и добавьте её через `plugin.addSettingTab()` в `onload`
|
||||
|
||||
### Сборка
|
||||
|
||||
```bash
|
||||
npm run build # production-сборка
|
||||
npm run dev # dev-сборка с sourcemap
|
||||
```
|
||||
|
||||
### Архитектура
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.ts # точка входа, Plugin class
|
||||
├── settings.ts # общая панель настроек
|
||||
├── types.ts # базовые типы
|
||||
└── modules/
|
||||
├── index.ts # реестр модулей (статический импорт)
|
||||
├── base-module.ts # абстрактный класс модуля
|
||||
└── attachment-clean-paste/
|
||||
└── index.ts # реализация модуля
|
||||
```
|
||||
|
||||
**Принцип работы:**
|
||||
- `main.ts` загружает настройки, итерирует `MODULES` и вызывает `onload()` для включённых
|
||||
- Каждый модуль через `registerCleanup()` регистрирует функции отчистки, которые вызываются при выключении модуля или выгрузке плагина
|
||||
- В настройках отображаются все модули с чекбоксами вкл/выкл
|
||||
|
||||
## Лицензия
|
||||
|
||||
MIT
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import esbuild from 'esbuild';
|
||||
import process from 'process';
|
||||
import builtins from 'builtin-modules';
|
||||
|
||||
const banner = `/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
*/
|
||||
`;
|
||||
|
||||
const prod = process.argv[2] === 'production';
|
||||
|
||||
esbuild
|
||||
.build({
|
||||
banner: { js: banner },
|
||||
entryPoints: ['src/main.ts'],
|
||||
bundle: true,
|
||||
external: [
|
||||
'obsidian',
|
||||
'electron',
|
||||
'@codemirror/autocomplete',
|
||||
'@codemirror/collab',
|
||||
'@codemirror/commands',
|
||||
'@codemirror/language',
|
||||
'@codemirror/lint',
|
||||
'@codemirror/search',
|
||||
'@codemirror/state',
|
||||
'@codemirror/view',
|
||||
'@lezer/common',
|
||||
'@lezer/highlight',
|
||||
'@lezer/lr',
|
||||
...builtins,
|
||||
],
|
||||
format: 'cjs',
|
||||
target: 'es2018',
|
||||
logLevel: 'info',
|
||||
sourcemap: prod ? false : 'inline',
|
||||
treeShaking: true,
|
||||
outfile: 'main.js',
|
||||
})
|
||||
.catch(() => process.exit(1));
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"id": "zeroq-qol-modules",
|
||||
"name": "ZeroQ QoL Modules",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Набор QoL-модулей для Obsidian: clean paste, авто-линковка и другое",
|
||||
"author": "Custom",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
Generated
+575
@@ -0,0 +1,575 @@
|
||||
{
|
||||
"name": "zeroq-qol-modules",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "zeroq-qol-modules",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"builtin-modules": "^3.3.0",
|
||||
"esbuild": "0.17.19",
|
||||
"obsidian": "latest",
|
||||
"tslib": "^2.6.2",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.0.tgz",
|
||||
"integrity": "sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@marijn/find-cluster-break": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.38.6",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.6.tgz",
|
||||
"integrity": "sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.5.0",
|
||||
"crelt": "^1.0.6",
|
||||
"style-mod": "^4.1.0",
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
|
||||
"integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
|
||||
"integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
|
||||
"integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
|
||||
"integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
|
||||
"integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
|
||||
"integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
|
||||
"integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
|
||||
"integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
|
||||
"integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@marijn/find-cluster-break": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.3.tgz",
|
||||
"integrity": "sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/codemirror": {
|
||||
"version": "5.60.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz",
|
||||
"integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/tern": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
|
||||
"integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/tern": {
|
||||
"version": "0.23.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz",
|
||||
"integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/builtin-modules": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
|
||||
"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.7.tgz",
|
||||
"integrity": "sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
|
||||
"integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/android-arm": "0.17.19",
|
||||
"@esbuild/android-arm64": "0.17.19",
|
||||
"@esbuild/android-x64": "0.17.19",
|
||||
"@esbuild/darwin-arm64": "0.17.19",
|
||||
"@esbuild/darwin-x64": "0.17.19",
|
||||
"@esbuild/freebsd-arm64": "0.17.19",
|
||||
"@esbuild/freebsd-x64": "0.17.19",
|
||||
"@esbuild/linux-arm": "0.17.19",
|
||||
"@esbuild/linux-arm64": "0.17.19",
|
||||
"@esbuild/linux-ia32": "0.17.19",
|
||||
"@esbuild/linux-loong64": "0.17.19",
|
||||
"@esbuild/linux-mips64el": "0.17.19",
|
||||
"@esbuild/linux-ppc64": "0.17.19",
|
||||
"@esbuild/linux-riscv64": "0.17.19",
|
||||
"@esbuild/linux-s390x": "0.17.19",
|
||||
"@esbuild/linux-x64": "0.17.19",
|
||||
"@esbuild/netbsd-x64": "0.17.19",
|
||||
"@esbuild/openbsd-x64": "0.17.19",
|
||||
"@esbuild/sunos-x64": "0.17.19",
|
||||
"@esbuild/win32-arm64": "0.17.19",
|
||||
"@esbuild/win32-ia32": "0.17.19",
|
||||
"@esbuild/win32-x64": "0.17.19"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.29.4",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/obsidian": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.13.1.tgz",
|
||||
"integrity": "sha512-qtTEA2pmhJzhuhJqzbBFRYhpIOqvW+krDYjtFynv66KbxBbumHBlsJfWw3I4jtnK/6fZwbQhCrmmDdRwXmX56w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/codemirror": "5.60.8",
|
||||
"moment": "2.29.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@codemirror/state": "6.5.0",
|
||||
"@codemirror/view": "6.38.6"
|
||||
}
|
||||
},
|
||||
"node_modules/style-mod": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz",
|
||||
"integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/w3c-keyname": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "zeroq-qol-modules",
|
||||
"version": "1.0.0",
|
||||
"description": "Modular Obsidian plugin with toggleable QoL modules",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
"build": "node esbuild.config.mjs production"
|
||||
},
|
||||
"keywords": ["obsidian", "plugin"],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"builtin-modules": "^3.3.0",
|
||||
"esbuild": "0.17.19",
|
||||
"obsidian": "latest",
|
||||
"tslib": "^2.6.2",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
import { Plugin } from 'obsidian';
|
||||
import { ZeroQSettings, QoLModule } from './types';
|
||||
import { MODULES } from './modules';
|
||||
import { DEFAULT_SETTINGS, ZeroQSettingTab, getModuleSettings } from './settings';
|
||||
|
||||
export default class ZeroQoLModulesPlugin extends Plugin {
|
||||
settings: ZeroQSettings;
|
||||
private loadedModules: Set<string> = new Set();
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
|
||||
this.addSettingTab(new ZeroQSettingTab(this.app, this));
|
||||
|
||||
for (const module of MODULES) {
|
||||
const moduleCfg = this.settings.modules[module.id];
|
||||
if (moduleCfg?.enabled) {
|
||||
this.loadModule(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onunload() {
|
||||
for (const module of MODULES) {
|
||||
this.unloadModule(module);
|
||||
}
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign(
|
||||
{},
|
||||
DEFAULT_SETTINGS,
|
||||
await this.loadData(),
|
||||
) as ZeroQSettings;
|
||||
|
||||
for (const module of MODULES) {
|
||||
if (!this.settings.modules[module.id]) {
|
||||
this.settings.modules[module.id] = {
|
||||
enabled: true,
|
||||
settings: { ...module.defaultSettings },
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
|
||||
loadModule(module: QoLModule) {
|
||||
if (this.loadedModules.has(module.id)) return;
|
||||
|
||||
const moduleSettings = getModuleSettings(this.settings, module.id);
|
||||
module.onload(this, moduleSettings);
|
||||
this.loadedModules.add(module.id);
|
||||
}
|
||||
|
||||
unloadModule(module: QoLModule) {
|
||||
if (!this.loadedModules.has(module.id)) return;
|
||||
|
||||
module.onunload(this);
|
||||
this.loadedModules.delete(module.id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
import {
|
||||
App,
|
||||
Editor,
|
||||
MarkdownFileInfo,
|
||||
MarkdownView,
|
||||
Notice,
|
||||
PluginSettingTab,
|
||||
Setting,
|
||||
normalizePath,
|
||||
} from 'obsidian';
|
||||
import type ZeroQoLModulesPlugin from '../../main';
|
||||
import { BaseModule } from '../base-module';
|
||||
|
||||
const MODULE_ID = 'attachment-clean-paste';
|
||||
|
||||
interface AttachmentCleanPasteSettings {
|
||||
extensions: string;
|
||||
}
|
||||
|
||||
export class AttachmentCleanPasteModule extends BaseModule {
|
||||
id = MODULE_ID;
|
||||
name = 'Attachment Clean Paste';
|
||||
description =
|
||||
'Заменяет ![[вложение]] на [[вложение|имя]] для указанных расширений при вставке/перетаскивании';
|
||||
|
||||
private app: App;
|
||||
|
||||
get defaultSettings(): Record<string, unknown> {
|
||||
return {
|
||||
extensions: 'png, jpg, jpeg, gif, svg, webp, bmp, pdf',
|
||||
};
|
||||
}
|
||||
|
||||
onload(plugin: ZeroQoLModulesPlugin, moduleSettings: Record<string, unknown>): void {
|
||||
this.app = plugin.app;
|
||||
const settings = moduleSettings as unknown as AttachmentCleanPasteSettings;
|
||||
|
||||
plugin.addSettingTab(
|
||||
new AttachmentCleanPasteSettingTab(plugin.app, plugin, MODULE_ID),
|
||||
);
|
||||
|
||||
const pasteRef = plugin.app.workspace.on(
|
||||
'editor-paste',
|
||||
this.createPasteHandler(settings),
|
||||
);
|
||||
this.registerCleanup(() => plugin.app.workspace.offref(pasteRef));
|
||||
|
||||
const dropRef = plugin.app.workspace.on(
|
||||
'editor-drop',
|
||||
this.createDropHandler(settings),
|
||||
);
|
||||
this.registerCleanup(() => plugin.app.workspace.offref(dropRef));
|
||||
}
|
||||
|
||||
private createPasteHandler(settings: AttachmentCleanPasteSettings) {
|
||||
return async (
|
||||
evt: ClipboardEvent,
|
||||
editor: Editor,
|
||||
_info: MarkdownView | MarkdownFileInfo,
|
||||
): Promise<void> => {
|
||||
const files = evt.clipboardData?.files;
|
||||
if (!files || files.length === 0) return;
|
||||
|
||||
const matchingFiles = Array.from(files).filter((f) =>
|
||||
this.shouldProcess(f.name, settings),
|
||||
);
|
||||
if (matchingFiles.length === 0) return;
|
||||
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
|
||||
for (const file of matchingFiles) {
|
||||
await this.processFile(file, editor, settings);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private createDropHandler(settings: AttachmentCleanPasteSettings) {
|
||||
return async (
|
||||
evt: DragEvent,
|
||||
editor: Editor,
|
||||
_info: MarkdownView | MarkdownFileInfo,
|
||||
): Promise<void> => {
|
||||
const files = evt.dataTransfer?.files;
|
||||
if (!files || files.length === 0) return;
|
||||
|
||||
const matchingFiles = Array.from(files).filter((f) =>
|
||||
this.shouldProcess(f.name, settings),
|
||||
);
|
||||
if (matchingFiles.length === 0) return;
|
||||
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
|
||||
for (const file of matchingFiles) {
|
||||
await this.processFile(file, editor, settings);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private shouldProcess(
|
||||
filename: string,
|
||||
settings: AttachmentCleanPasteSettings,
|
||||
): boolean {
|
||||
const dotIndex = filename.lastIndexOf('.');
|
||||
if (dotIndex === -1) return false;
|
||||
const ext = filename.slice(dotIndex + 1).toLowerCase();
|
||||
|
||||
const exts = settings.extensions
|
||||
.split(',')
|
||||
.map((e) => e.trim().toLowerCase())
|
||||
.filter((e) => e.length > 0);
|
||||
|
||||
return exts.some((e) => {
|
||||
const cleanExt = e.startsWith('.') ? e.slice(1) : e;
|
||||
return cleanExt === ext;
|
||||
});
|
||||
}
|
||||
|
||||
private async processFile(
|
||||
file: File,
|
||||
editor: Editor,
|
||||
_settings: AttachmentCleanPasteSettings,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const filename = file.name;
|
||||
const nameWithoutExt = filename.replace(/\.[^/.]+$/, '');
|
||||
|
||||
let attachmentFolder = this.app.vault.getConfig(
|
||||
'attachmentFolderPath',
|
||||
) as string;
|
||||
if (!attachmentFolder) attachmentFolder = 'attachments';
|
||||
|
||||
const folderPath = normalizePath(attachmentFolder);
|
||||
if (!(await this.app.vault.adapter.exists(folderPath))) {
|
||||
await this.app.vault.createFolder(folderPath);
|
||||
}
|
||||
|
||||
const ext = filename.slice(filename.lastIndexOf('.') + 1);
|
||||
const basePath = normalizePath(`${folderPath}/${nameWithoutExt}`);
|
||||
|
||||
const availablePath = await this.app.vault.getAvailablePath(
|
||||
basePath,
|
||||
ext,
|
||||
);
|
||||
|
||||
await this.app.vault.createBinary(availablePath, arrayBuffer);
|
||||
|
||||
const link = `[[${availablePath}|${nameWithoutExt}]]`;
|
||||
editor.replaceSelection(link);
|
||||
} catch (e) {
|
||||
new Notice(`Clean Paste error: ${e.message}`);
|
||||
console.error('Attachment Clean Paste:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AttachmentCleanPasteSettingTab extends PluginSettingTab {
|
||||
private plugin: ZeroQoLModulesPlugin;
|
||||
private moduleId: string;
|
||||
|
||||
constructor(app: App, plugin: ZeroQoLModulesPlugin, moduleId: string) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
this.moduleId = moduleId;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
|
||||
containerEl.createEl('h2', { text: 'Attachment Clean Paste' });
|
||||
containerEl.createEl('p', {
|
||||
text: 'Заменяет ![[вложение]] на [[вложение|имя]] для указанных расширений.',
|
||||
attr: { style: 'color: var(--text-muted); margin-bottom: 20px;' },
|
||||
});
|
||||
|
||||
const rawSettings = this.plugin.settings.modules[this.moduleId]?.settings as
|
||||
| AttachmentCleanPasteSettings
|
||||
| undefined;
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Расширения файлов')
|
||||
.setDesc(
|
||||
'Расширения через запятую (например: png, jpg, pdf, mp3). Файлы с этими расширениями будут вставляться как [[path/file|name]] вместо ![[path/file]].',
|
||||
)
|
||||
.addTextArea((textarea) => {
|
||||
textarea
|
||||
.setPlaceholder('png, jpg, jpeg, gif, svg, webp, pdf')
|
||||
.setValue(rawSettings?.extensions ?? '')
|
||||
.onChange(async (value) => {
|
||||
if (this.plugin.settings.modules[this.moduleId]) {
|
||||
this.plugin.settings.modules[this.moduleId].settings = {
|
||||
extensions: value,
|
||||
};
|
||||
}
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
textarea.inputEl.rows = 4;
|
||||
textarea.inputEl.style.width = '100%';
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Plugin } from 'obsidian';
|
||||
import { QoLModule } from '../types';
|
||||
|
||||
export abstract class BaseModule implements QoLModule {
|
||||
abstract id: string;
|
||||
abstract name: string;
|
||||
abstract description: string;
|
||||
|
||||
private cleanupFns: (() => void)[] = [];
|
||||
|
||||
get defaultSettings(): Record<string, unknown> {
|
||||
return {};
|
||||
}
|
||||
|
||||
abstract onload(plugin: Plugin, moduleSettings: Record<string, unknown>): void;
|
||||
|
||||
onunload(_plugin: Plugin): void {
|
||||
for (const fn of this.cleanupFns) {
|
||||
fn();
|
||||
}
|
||||
this.cleanupFns = [];
|
||||
}
|
||||
|
||||
protected registerCleanup(fn: () => void): void {
|
||||
this.cleanupFns.push(fn);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { AttachmentCleanPasteModule } from './attachment-clean-paste';
|
||||
import { QoLModule } from '../types';
|
||||
|
||||
export const MODULES: QoLModule[] = [new AttachmentCleanPasteModule()];
|
||||
@@ -0,0 +1,74 @@
|
||||
import { App, PluginSettingTab, Setting } from 'obsidian';
|
||||
import type ZeroQoLModulesPlugin from './main';
|
||||
import { MODULES } from './modules';
|
||||
import { ZeroQSettings } from './types';
|
||||
|
||||
const MODULE_DEFAULTS = MODULES.reduce(
|
||||
(acc, mod) => {
|
||||
acc[mod.id] = {
|
||||
enabled: true,
|
||||
settings: { ...mod.defaultSettings },
|
||||
};
|
||||
return acc;
|
||||
},
|
||||
{} as ZeroQSettings['modules'],
|
||||
);
|
||||
|
||||
export const DEFAULT_SETTINGS: ZeroQSettings = {
|
||||
modules: MODULE_DEFAULTS,
|
||||
};
|
||||
|
||||
export function getModuleSettings(
|
||||
settings: ZeroQSettings,
|
||||
moduleId: string,
|
||||
): Record<string, unknown> {
|
||||
return settings.modules[moduleId]?.settings ?? {};
|
||||
}
|
||||
|
||||
export class ZeroQSettingTab extends PluginSettingTab {
|
||||
plugin: ZeroQoLModulesPlugin;
|
||||
|
||||
constructor(app: App, plugin: ZeroQoLModulesPlugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
|
||||
containerEl.createEl('h1', { text: 'ZeroQ QoL Modules' });
|
||||
containerEl.createEl('p', {
|
||||
text: 'Включайте и отключайте модули по своему усмотрению.',
|
||||
attr: { style: 'color: var(--text-muted); margin-bottom: 20px;' },
|
||||
});
|
||||
|
||||
for (const module of MODULES) {
|
||||
const moduleSettings = this.plugin.settings.modules[module.id];
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(module.name)
|
||||
.setDesc(module.description)
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(moduleSettings?.enabled ?? true)
|
||||
.onChange(async (value) => {
|
||||
if (!this.plugin.settings.modules[module.id]) {
|
||||
this.plugin.settings.modules[module.id] = {
|
||||
enabled: value,
|
||||
settings: { ...module.defaultSettings },
|
||||
};
|
||||
} else {
|
||||
this.plugin.settings.modules[module.id].enabled = value;
|
||||
}
|
||||
await this.plugin.saveSettings();
|
||||
if (value) {
|
||||
this.plugin.loadModule(module);
|
||||
} else {
|
||||
this.plugin.unloadModule(module);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Plugin } from 'obsidian';
|
||||
|
||||
export interface ModuleSettings {
|
||||
enabled: boolean;
|
||||
settings: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface ZeroQSettings {
|
||||
modules: Record<string, ModuleSettings>;
|
||||
}
|
||||
|
||||
export interface QoLModule {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
defaultSettings: Record<string, unknown>;
|
||||
onload(plugin: Plugin, moduleSettings: Record<string, unknown>): void;
|
||||
onunload(plugin: Plugin): void;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/* ZeroQ QoL Modules - no custom styles needed */
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"target": "ES6",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"lib": ["DOM", "ES5", "ES6", "ES7"],
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strictNullChecks": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user