From d791b6294d12d142e7351e69e8e0b2e3bdb162c4 Mon Sep 17 00:00:00 2001 From: caasion <103465188+caasion@users.noreply.github.com> Date: Fri, 15 Aug 2025 18:28:29 -0400 Subject: [PATCH 01/16] Update All Dependecies --- package.json | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index daa56ee..d48f27c 100644 --- a/package.json +++ b/package.json @@ -11,21 +11,22 @@ "author": "", "license": "MIT", "devDependencies": { - "@codemirror/lang-python": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@eslint/js": "^9.31.0", - "@types/node": "^16.11.6", - "@typescript-eslint/eslint-plugin": "^8.37.0", - "@typescript-eslint/parser": "^8.37.0", - "builtin-modules": "3.3.0", - "codemirror": "^6.0.0", - "esbuild": "^0.14.47", - "eslint": "^9.31.0", + "@codemirror/lang-python": "^6.2.1", + "@codemirror/state": "^6.5.2", + "@codemirror/view": "^6.38.1", + "@eslint/js": "^9.33.0", + "@types/node": "^24.3.0", + "@typescript-eslint/eslint-plugin": "^8.39.1", + "@typescript-eslint/parser": "^8.39.1", + "builtin-modules": "5.0.0", + "codemirror": "^6.0.2", + "esbuild": "^0.25.9", + "esbuild-plugin-wasm": "^1.1.0", + "eslint": "^9.33.0", "globals": "^16.3.0", "obsidian": "latest", - "tslib": "2.4.0", - "typescript": "5.8.3", - "typescript-eslint": "^8.37.0" + "tslib": "2.8.1", + "typescript": "5.9.2", + "typescript-eslint": "^8.39.1" } } From 99ca7a05c15a11f99de908cac01af764358adf77 Mon Sep 17 00:00:00 2001 From: caasion <103465188+caasion@users.noreply.github.com> Date: Fri, 15 Aug 2025 20:00:40 -0400 Subject: [PATCH 02/16] Fix Esbuild compile (from updating dependencies) --- esbuild.config.mjs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/esbuild.config.mjs b/esbuild.config.mjs index 49b2f33..b201c50 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -69,7 +69,7 @@ let copyFile = { }, } -esbuild.build({ +const options = { banner: { js: banner, }, @@ -97,11 +97,25 @@ esbuild.build({ ...builtins ], format: 'cjs', - watch: !prod, target: 'es2016', logLevel: "info", sourcemap: prod ? false : 'inline', treeShaking: true, outfile: path.join(pluginDir, 'main.js'), -}).catch(() => process.exit(1)) +} + +try { + if (prod) { + // production build + await esbuild.build(options); + } else { + // development build with watch + const ctx = await esbuild.context(options); + await ctx.watch(); + console.log("👀 Watching for changes..."); + } +} catch (err) { + console.error(err); + process.exit(1); +} From f0687f97c92a9f40f17c33b7070e890fd0ee000d Mon Sep 17 00:00:00 2001 From: caasion <103465188+caasion@users.noreply.github.com> Date: Fri, 15 Aug 2025 20:09:04 -0400 Subject: [PATCH 03/16] Install Svelte --- esbuild.config.mjs | 6 +++++- package.json | 3 +++ src/components/RuleEditor.svelte | 7 +++++++ src/settings.ts | 5 +++++ tsconfig.json | 3 ++- 5 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 src/components/RuleEditor.svelte diff --git a/esbuild.config.mjs b/esbuild.config.mjs index b201c50..e14094b 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -3,6 +3,7 @@ import process from "process"; import builtins from 'builtin-modules' import fs from "fs"; import path from "path"; +import sveltePlugin from 'esbuild-svelte'; const banner = `/* @@ -73,7 +74,10 @@ const options = { banner: { js: banner, }, - plugins: [wasmPlugin, copyFile], + plugins: [ + wasmPlugin, + copyFile, + sveltePlugin()], entryPoints: ['src/main.ts'], bundle: true, external: [ diff --git a/package.json b/package.json index d48f27c..4e3b3bf 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@codemirror/state": "^6.5.2", "@codemirror/view": "^6.38.1", "@eslint/js": "^9.33.0", + "@tsconfig/svelte": "^5.0.4", "@types/node": "^24.3.0", "@typescript-eslint/eslint-plugin": "^8.39.1", "@typescript-eslint/parser": "^8.39.1", @@ -22,9 +23,11 @@ "codemirror": "^6.0.2", "esbuild": "^0.25.9", "esbuild-plugin-wasm": "^1.1.0", + "esbuild-svelte": "^0.9.3", "eslint": "^9.33.0", "globals": "^16.3.0", "obsidian": "latest", + "svelte": "^5.38.1", "tslib": "2.8.1", "typescript": "5.9.2", "typescript-eslint": "^8.39.1" diff --git a/src/components/RuleEditor.svelte b/src/components/RuleEditor.svelte new file mode 100644 index 0000000..70aca53 --- /dev/null +++ b/src/components/RuleEditor.svelte @@ -0,0 +1,7 @@ + + + + +

Hello!

\ No newline at end of file diff --git a/src/settings.ts b/src/settings.ts index 274a758..008a995 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -7,6 +7,8 @@ import { syntaxHighlighting, HighlightStyle } from "@codemirror/language"; import { python } from "@codemirror/lang-python"; import { tags as t } from "@lezer/highlight"; import { log } from "./utils"; +import { mount } from "svelte"; +import RuleEditor from "./components/RuleEditor.svelte"; export const config = { name: "obsidian", @@ -151,6 +153,9 @@ export class SettingTab extends PluginSettingTab { ); this.ruleEditor = createRuleEditorInContainer(containerEl, plugin, this.editorState); + + + mount(RuleEditor, { target: containerEl }); } } diff --git a/tsconfig.json b/tsconfig.json index b87cdc2..82c00ef 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,6 +19,7 @@ "outDir": "build" }, "include": [ - "**/*.ts" + "**/*.ts", + "**/*.svelte" ] } From ff4068c803a3312f9b8a35a7db5bfde44170b0d6 Mon Sep 17 00:00:00 2001 From: caasion <103465188+caasion@users.noreply.github.com> Date: Fri, 15 Aug 2025 20:17:18 -0400 Subject: [PATCH 04/16] Create Skeleton of Rule Editor in svelte --- src/components/RuleEditor.svelte | 63 +++++++++++++++++++++++++++++++- src/settings.ts | 5 +-- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/components/RuleEditor.svelte b/src/components/RuleEditor.svelte index 70aca53..cc1fd92 100644 --- a/src/components/RuleEditor.svelte +++ b/src/components/RuleEditor.svelte @@ -1,7 +1,66 @@ + type RuleEditorProps = { + plugin: TypingTransformer, + state: State; + } + let props: RuleEditorProps = $props(); + -

Hello!

\ No newline at end of file +
+
+
Rules
+
+ Enter conversion, selection, and deletion rules here. NOTES: +
    +
  1. Each line is one rule. Rules that come first have higher priority.
  2. +
  3. Lines starting with "#" are treated as comments and ignored. Inline comments are also allowed
  4. +
  5. The character '|' indicates where your cursor will be placed after the rule is applied.
  6. +
  7. To use special characters like '|' for conversion, you escape them with a backslash, for example: '\|'
  8. +
  9. Whatever tab you are on when the plugin settings tab quits will be the profile that is chosen
  10. +
  11. The 'global' profile will always be active
  12. +
+
+
+
+
+
global
+
+
+
+
+
+
+
+ +
+ +
+
+
+
+ +
+
diff --git a/src/settings.ts b/src/settings.ts index 008a995..0fc6796 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -154,12 +154,11 @@ export class SettingTab extends PluginSettingTab { this.ruleEditor = createRuleEditorInContainer(containerEl, plugin, this.editorState); - - mount(RuleEditor, { target: containerEl }); + mount(RuleEditor, { target: containerEl, props: { plugin: plugin, state: this.editorState} }); } } -interface State { +export interface State { selectedProfileName: string, selectedProfileEl: HTMLElement, baseProfileEl: HTMLElement, From a2223c30f729d8632246b1087a0308670f85681e Mon Sep 17 00:00:00 2001 From: caasion <103465188+caasion@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:09:22 -0400 Subject: [PATCH 05/16] Refactor Editor into its own component --- main.css | 9 +++ src/components/RuleSettings.svelte | 91 ++++++++++++++++++++++++++++++ src/settings.ts | 9 +-- 3 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 main.css create mode 100644 src/components/RuleSettings.svelte diff --git a/main.css b/main.css new file mode 100644 index 0000000..22f82cd --- /dev/null +++ b/main.css @@ -0,0 +1,9 @@ +/* fakecss:C:/Users/isaac/Main/Plugin Development/.obsidian/plugins/typing-transformer-obsidian/src/components/RuleEditor.esbuild-svelte-fake-css */ +.rules-editor-wrapper.svelte-1p6huli { + height: 20em; + resize: vertical; + overflow: auto; + font-size: var(--font-inputs); + border: 1px solid var(--background-modifier-border); +} +/*# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiUnVsZUVkaXRvci5zdmVsdGUiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIjxzY3JpcHQgbGFuZz1cInRzXCI+XHJcbiAgICBpbXBvcnQgeyBvbk1vdW50IH0gZnJvbSAnc3ZlbHRlJztcclxuICAgIGltcG9ydCB7IHB5dGhvbiB9IGZyb20gJ0Bjb2RlbWlycm9yL2xhbmctcHl0aG9uJztcclxuICAgIGltcG9ydCB7IGxpbmVOdW1iZXJzLCBFZGl0b3JWaWV3LCBWaWV3VXBkYXRlIH0gZnJvbSAnQGNvZGVtaXJyb3Ivdmlldyc7XHJcbiAgICBpbXBvcnQgeyBBbm5vdGF0aW9uLCBFZGl0b3JTdGF0ZSwgRXh0ZW5zaW9uIH0gZnJvbSAnQGNvZGVtaXJyb3Ivc3RhdGUnO1xyXG4gICAgaW1wb3J0IHsgc3ludGF4SGlnaGxpZ2h0aW5nLCBIaWdobGlnaHRTdHlsZSB9IGZyb20gJ0Bjb2RlbWlycm9yL2xhbmd1YWdlJztcclxuICAgIGltcG9ydCB7IGNvbmZpZyB9IGZyb20gJ3NyYy9zZXR0aW5ncyc7XHJcbiAgICBpbXBvcnQgeyB0YWdzIGFzIHQgfSBmcm9tIFwiQGxlemVyL2hpZ2hsaWdodFwiO1xyXG5cclxuICAgIGludGVyZmFjZSBSdWxlRWRpdG9yUHJvcHMge1xyXG4gICAgICAgIGluaXRpYWxUZXh0OiBzdHJpbmcsXHJcbiAgICAgICAgb25DaGFuZ2U6ICh0ZXh0OiBzdHJpbmcpID0+IHZvaWQsXHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHsgaW5pdGlhbFRleHQsIG9uQ2hhbmdlIH06IFJ1bGVFZGl0b3JQcm9wcyA9ICRwcm9wcygpO1xyXG5cclxuICAgIGNvbnN0IFByb2ZpbGVTd2l0Y2ggPSBBbm5vdGF0aW9uLmRlZmluZTxib29sZWFuPigpO1xyXG5cclxuXHJcbiAgICBsZXQgZWRpdG9yQ29udGFpbmVyOiBIVE1MRGl2RWxlbWVudDtcclxuICAgIGxldCBlZGl0b3I6IEVkaXRvclZpZXc7XHJcblxyXG4gICAgY29uc3Qgb2JzaWRpYW5UaGVtZSA9IEVkaXRvclZpZXcudGhlbWUoe1xyXG4gICAgICAgIFwiJlwiOiB7XHJcbiAgICAgICAgICAgIGNvbG9yOiBjb25maWcuZm9yZWdyb3VuZCxcclxuICAgICAgICAgICAgYmFja2dyb3VuZENvbG9yOiBjb25maWcuYmFja2dyb3VuZCxcclxuICAgICAgICB9LFxyXG4gICAgICAgIFwiLmNtLWNvbnRlbnRcIjogeyBjYXJldENvbG9yOiBjb25maWcuY3Vyc29yIH0sXHJcbiAgICAgICAgXCImLmNtLWZvY3VzZWQgLmNtLWN1cnNvclwiOiB7IGJvcmRlckxlZnRDb2xvcjogY29uZmlnLmN1cnNvciB9LFxyXG4gICAgICAgIFwiJi5jbS1mb2N1c2VkIC5jbS1zZWxlY3Rpb25CYWNrZ3JvdW5kLCAuY20tc2VsZWN0aW9uQmFja2dyb3VuZCwgJiA6OnNlbGVjdGlvblwiOiB7IGJhY2tncm91bmRDb2xvcjogY29uZmlnLnNlbGVjdGlvbiB9LFxyXG4gICAgICAgIFwiLmNtLWFjdGl2ZUxpbmVcIjogeyBiYWNrZ3JvdW5kQ29sb3I6IGNvbmZpZy5hY3RpdmVMaW5lIH0sXHJcbiAgICAgICAgXCIuY20tYWN0aXZlTGluZUd1dHRlclwiOiB7IGJhY2tncm91bmRDb2xvcjogY29uZmlnLmJhY2tncm91bmQgfSxcclxuICAgICAgICBcIi5jbS1zZWxlY3Rpb25NYXRjaFwiOiB7IGJhY2tncm91bmRDb2xvcjogY29uZmlnLnNlbGVjdGlvbiB9LFxyXG4gICAgICAgIFwiLmNtLWd1dHRlcnNcIjoge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IGNvbmZpZy5iYWNrZ3JvdW5kLFxyXG4gICAgICAgICAgICBjb2xvcjogY29uZmlnLmNvbW1lbnQsXHJcbiAgICAgICAgICAgIGJvcmRlclJpZ2h0OiBcIjFweCBzb2xpZCB2YXIoLS1iYWNrZ3JvdW5kLW1vZGlmaWVyLWJvcmRlcilcIlxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgXCIuY20tbGluZU51bWJlcnMsIC5jbS1ndXR0ZXJFbGVtZW50XCI6IHsgY29sb3I6IFwiaW5oZXJpdFwiIH0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCBvYnNpZGlhbkhpZ2hsaWdodFN0eWxlID0gSGlnaGxpZ2h0U3R5bGUuZGVmaW5lKFtcclxuICAgICAgICB7IHRhZzogW3QucHJvY2Vzc2luZ0luc3RydWN0aW9uLCB0LnN0cmluZywgdC5pbnNlcnRlZCwgdC5zcGVjaWFsKHQuc3RyaW5nKV0sIGNvbG9yOiBjb25maWcuc3RyaW5nIH0sXHJcbiAgICAgICAgeyB0YWc6IFt0LmNvbG9yLCB0LmNvbnN0YW50KHQubmFtZSksIHQuc3RhbmRhcmQodC5uYW1lKV0sIGNvbG9yOiBjb25maWcuY29uc3RhbnQgfSxcclxuICAgICAgICB7IHRhZzogdC5jb21tZW50LCBjb2xvcjogY29uZmlnLmNvbW1lbnQgfSxcclxuICAgICAgICB7IHRhZzogdC5pbnZhbGlkLCBjb2xvcjogY29uZmlnLmludmFsaWQgfSxcclxuICAgIF0pO1xyXG5cclxuICAgIGNvbnN0IGV4dGVuc2lvbnM6IEV4dGVuc2lvbltdID0gW1xyXG4gICAgICAgIG9ic2lkaWFuVGhlbWUsXHJcbiAgICAgICAgbGluZU51bWJlcnMoKSxcclxuICAgICAgICBFZGl0b3JWaWV3LmxpbmVXcmFwcGluZyxcclxuICAgICAgICBweXRob24oKSwgLy8gaXQgaXMgYmV0dGVyIHRvIHdyaXRlIGEgbGFuZ3VhZ2Ugc3VwcG9ydCBmb3IgcnVsZXNcclxuICAgICAgICBzeW50YXhIaWdobGlnaHRpbmcob2JzaWRpYW5IaWdobGlnaHRTdHlsZSksXHJcbiAgICAgICAgRWRpdG9yVmlldy51cGRhdGVMaXN0ZW5lci5vZihhc3luYyAodjogVmlld1VwZGF0ZSkgPT4ge1xyXG4gICAgICAgICAgICBpZiAodi5kb2NDaGFuZ2VkKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHYuc3RhdGUuZG9jLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgICAgICBvbkNoYW5nZSh2YWx1ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KVxyXG4gICAgXTtcclxuXHJcbiAgb25Nb3VudCgoKSA9PiB7XHJcbiAgICBjb25zdCBzdGF0ZSA9IEVkaXRvclN0YXRlLmNyZWF0ZSh7XHJcbiAgICAgIGRvYzogaW5pdGlhbFRleHQsXHJcbiAgICAgIGV4dGVuc2lvbnM6IGV4dGVuc2lvbnNcclxuICAgIH0pO1xyXG5cclxuICAgIGVkaXRvciA9IG5ldyBFZGl0b3JWaWV3KHtcclxuICAgICAgc3RhdGUsXHJcbiAgICAgIHBhcmVudDogZWRpdG9yQ29udGFpbmVyXHJcbiAgICB9KTtcclxuICB9KTtcclxuPC9zY3JpcHQ+XHJcblxyXG48ZGl2IGJpbmQ6dGhpcz17ZWRpdG9yQ29udGFpbmVyfSBjbGFzcz1cInJ1bGVzLWVkaXRvci13cmFwcGVyXCI+PC9kaXY+XHJcblxyXG48c3R5bGU+XHJcbiAgLnJ1bGVzLWVkaXRvci13cmFwcGVyIHtcclxuICAgIGhlaWdodDogMjBlbTtcclxuICAgIHJlc2l6ZTogdmVydGljYWw7XHJcbiAgICBvdmVyZmxvdzogYXV0bztcclxuICAgIGZvbnQtc2l6ZTogdmFyKC0tZm9udC1pbnB1dHMpO1xyXG4gICAgYm9yZGVyOiAxcHggc29saWQgdmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ib3JkZXIpO1xyXG4gIH1cclxuPC9zdHlsZT5cclxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQThFRSxDQUFBLG9CQUFBLENBQUE7QUFDRSxVQUFBO0FBQ0EsVUFBQTtBQUNBLFlBQUE7QUFDQSxhQUFBLElBQUE7QUFDQSxVQUFBLElBQUEsTUFBQSxJQUFBO0FBQ0o7IiwKICAibmFtZXMiOiBbXQp9Cg== */ diff --git a/src/components/RuleSettings.svelte b/src/components/RuleSettings.svelte new file mode 100644 index 0000000..ac8c664 --- /dev/null +++ b/src/components/RuleSettings.svelte @@ -0,0 +1,91 @@ + + +
+
+
Rules
+
+ Enter conversion, selection, and deletion rules here. NOTES: +
    +
  1. Each line is one rule. Rules that come first have higher priority.
  2. +
  3. Lines starting with "#" are treated as comments and ignored. Inline comments are also allowed
  4. +
  5. The character '|' indicates where your cursor will be placed after the rule is applied.
  6. +
  7. To use special characters like '|' for conversion, you escape them with a backslash, for example: '\|'
  8. +
  9. Whatever tab you are on when the plugin settings tab quits will be the profile that is chosen
  10. +
  11. The 'global' profile will always be active
  12. +
+
+
+
+
+
global
+
+
+
+ + +
+
diff --git a/src/settings.ts b/src/settings.ts index 0fc6796..2b23996 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -8,7 +8,7 @@ import { python } from "@codemirror/lang-python"; import { tags as t } from "@lezer/highlight"; import { log } from "./utils"; import { mount } from "svelte"; -import RuleEditor from "./components/RuleEditor.svelte"; +import RuleSettings from "./components/RuleSettings.svelte"; export const config = { name: "obsidian", @@ -55,11 +55,6 @@ const obsidianTheme = EditorView.theme({ export const BaseProfileName = "global"; const ProfileSwitch = Annotation.define(); -interface Profile { - title: string; - content: string; -} - export interface TypingTransformerSettings { debug: boolean, convertRules: string, @@ -154,7 +149,7 @@ export class SettingTab extends PluginSettingTab { this.ruleEditor = createRuleEditorInContainer(containerEl, plugin, this.editorState); - mount(RuleEditor, { target: containerEl, props: { plugin: plugin, state: this.editorState} }); + mount(RuleSettings, { target: containerEl, props: { plugin: plugin, pluginState: this.editorState} }); } } From 88ba7859b6d5ceb99e6ebc7467a4c2c6624867d1 Mon Sep 17 00:00:00 2001 From: caasion <103465188+caasion@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:09:31 -0400 Subject: [PATCH 06/16] Fix Validity Indicator --- src/components/RuleEditor.svelte | 138 ++++++++++++++++++------------- 1 file changed, 79 insertions(+), 59 deletions(-) diff --git a/src/components/RuleEditor.svelte b/src/components/RuleEditor.svelte index cc1fd92..cbb7f8c 100644 --- a/src/components/RuleEditor.svelte +++ b/src/components/RuleEditor.svelte @@ -1,66 +1,86 @@ -
-
-
Rules
-
- Enter conversion, selection, and deletion rules here. NOTES: -
    -
  1. Each line is one rule. Rules that come first have higher priority.
  2. -
  3. Lines starting with "#" are treated as comments and ignored. Inline comments are also allowed
  4. -
  5. The character '|' indicates where your cursor will be placed after the rule is applied.
  6. -
  7. To use special characters like '|' for conversion, you escape them with a backslash, for example: '\|'
  8. -
  9. Whatever tab you are on when the plugin settings tab quits will be the profile that is chosen
  10. -
  11. The 'global' profile will always be active
  12. -
-
-
-
-
-
global
-
+
-
-
-
-
-
- -
- -
-
-
-
- -
-
+
+ + From 387289d6446c9c5b058b21e3f846806931314e81 Mon Sep 17 00:00:00 2001 From: caasion <103465188+caasion@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:48:29 -0400 Subject: [PATCH 07/16] Refactor StringINputModal --- main.css | 9 --- src/components/RuleSettings.svelte | 89 ++++++++++++++++++++------ src/components/StringInputModal.svelte | 44 +++++++++++++ 3 files changed, 114 insertions(+), 28 deletions(-) delete mode 100644 main.css create mode 100644 src/components/StringInputModal.svelte diff --git a/main.css b/main.css deleted file mode 100644 index 22f82cd..0000000 --- a/main.css +++ /dev/null @@ -1,9 +0,0 @@ -/* fakecss:C:/Users/isaac/Main/Plugin Development/.obsidian/plugins/typing-transformer-obsidian/src/components/RuleEditor.esbuild-svelte-fake-css */ -.rules-editor-wrapper.svelte-1p6huli { - height: 20em; - resize: vertical; - overflow: auto; - font-size: var(--font-inputs); - border: 1px solid var(--background-modifier-border); -} -/*# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiUnVsZUVkaXRvci5zdmVsdGUiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIjxzY3JpcHQgbGFuZz1cInRzXCI+XHJcbiAgICBpbXBvcnQgeyBvbk1vdW50IH0gZnJvbSAnc3ZlbHRlJztcclxuICAgIGltcG9ydCB7IHB5dGhvbiB9IGZyb20gJ0Bjb2RlbWlycm9yL2xhbmctcHl0aG9uJztcclxuICAgIGltcG9ydCB7IGxpbmVOdW1iZXJzLCBFZGl0b3JWaWV3LCBWaWV3VXBkYXRlIH0gZnJvbSAnQGNvZGVtaXJyb3Ivdmlldyc7XHJcbiAgICBpbXBvcnQgeyBBbm5vdGF0aW9uLCBFZGl0b3JTdGF0ZSwgRXh0ZW5zaW9uIH0gZnJvbSAnQGNvZGVtaXJyb3Ivc3RhdGUnO1xyXG4gICAgaW1wb3J0IHsgc3ludGF4SGlnaGxpZ2h0aW5nLCBIaWdobGlnaHRTdHlsZSB9IGZyb20gJ0Bjb2RlbWlycm9yL2xhbmd1YWdlJztcclxuICAgIGltcG9ydCB7IGNvbmZpZyB9IGZyb20gJ3NyYy9zZXR0aW5ncyc7XHJcbiAgICBpbXBvcnQgeyB0YWdzIGFzIHQgfSBmcm9tIFwiQGxlemVyL2hpZ2hsaWdodFwiO1xyXG5cclxuICAgIGludGVyZmFjZSBSdWxlRWRpdG9yUHJvcHMge1xyXG4gICAgICAgIGluaXRpYWxUZXh0OiBzdHJpbmcsXHJcbiAgICAgICAgb25DaGFuZ2U6ICh0ZXh0OiBzdHJpbmcpID0+IHZvaWQsXHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHsgaW5pdGlhbFRleHQsIG9uQ2hhbmdlIH06IFJ1bGVFZGl0b3JQcm9wcyA9ICRwcm9wcygpO1xyXG5cclxuICAgIGNvbnN0IFByb2ZpbGVTd2l0Y2ggPSBBbm5vdGF0aW9uLmRlZmluZTxib29sZWFuPigpO1xyXG5cclxuXHJcbiAgICBsZXQgZWRpdG9yQ29udGFpbmVyOiBIVE1MRGl2RWxlbWVudDtcclxuICAgIGxldCBlZGl0b3I6IEVkaXRvclZpZXc7XHJcblxyXG4gICAgY29uc3Qgb2JzaWRpYW5UaGVtZSA9IEVkaXRvclZpZXcudGhlbWUoe1xyXG4gICAgICAgIFwiJlwiOiB7XHJcbiAgICAgICAgICAgIGNvbG9yOiBjb25maWcuZm9yZWdyb3VuZCxcclxuICAgICAgICAgICAgYmFja2dyb3VuZENvbG9yOiBjb25maWcuYmFja2dyb3VuZCxcclxuICAgICAgICB9LFxyXG4gICAgICAgIFwiLmNtLWNvbnRlbnRcIjogeyBjYXJldENvbG9yOiBjb25maWcuY3Vyc29yIH0sXHJcbiAgICAgICAgXCImLmNtLWZvY3VzZWQgLmNtLWN1cnNvclwiOiB7IGJvcmRlckxlZnRDb2xvcjogY29uZmlnLmN1cnNvciB9LFxyXG4gICAgICAgIFwiJi5jbS1mb2N1c2VkIC5jbS1zZWxlY3Rpb25CYWNrZ3JvdW5kLCAuY20tc2VsZWN0aW9uQmFja2dyb3VuZCwgJiA6OnNlbGVjdGlvblwiOiB7IGJhY2tncm91bmRDb2xvcjogY29uZmlnLnNlbGVjdGlvbiB9LFxyXG4gICAgICAgIFwiLmNtLWFjdGl2ZUxpbmVcIjogeyBiYWNrZ3JvdW5kQ29sb3I6IGNvbmZpZy5hY3RpdmVMaW5lIH0sXHJcbiAgICAgICAgXCIuY20tYWN0aXZlTGluZUd1dHRlclwiOiB7IGJhY2tncm91bmRDb2xvcjogY29uZmlnLmJhY2tncm91bmQgfSxcclxuICAgICAgICBcIi5jbS1zZWxlY3Rpb25NYXRjaFwiOiB7IGJhY2tncm91bmRDb2xvcjogY29uZmlnLnNlbGVjdGlvbiB9LFxyXG4gICAgICAgIFwiLmNtLWd1dHRlcnNcIjoge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IGNvbmZpZy5iYWNrZ3JvdW5kLFxyXG4gICAgICAgICAgICBjb2xvcjogY29uZmlnLmNvbW1lbnQsXHJcbiAgICAgICAgICAgIGJvcmRlclJpZ2h0OiBcIjFweCBzb2xpZCB2YXIoLS1iYWNrZ3JvdW5kLW1vZGlmaWVyLWJvcmRlcilcIlxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgXCIuY20tbGluZU51bWJlcnMsIC5jbS1ndXR0ZXJFbGVtZW50XCI6IHsgY29sb3I6IFwiaW5oZXJpdFwiIH0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCBvYnNpZGlhbkhpZ2hsaWdodFN0eWxlID0gSGlnaGxpZ2h0U3R5bGUuZGVmaW5lKFtcclxuICAgICAgICB7IHRhZzogW3QucHJvY2Vzc2luZ0luc3RydWN0aW9uLCB0LnN0cmluZywgdC5pbnNlcnRlZCwgdC5zcGVjaWFsKHQuc3RyaW5nKV0sIGNvbG9yOiBjb25maWcuc3RyaW5nIH0sXHJcbiAgICAgICAgeyB0YWc6IFt0LmNvbG9yLCB0LmNvbnN0YW50KHQubmFtZSksIHQuc3RhbmRhcmQodC5uYW1lKV0sIGNvbG9yOiBjb25maWcuY29uc3RhbnQgfSxcclxuICAgICAgICB7IHRhZzogdC5jb21tZW50LCBjb2xvcjogY29uZmlnLmNvbW1lbnQgfSxcclxuICAgICAgICB7IHRhZzogdC5pbnZhbGlkLCBjb2xvcjogY29uZmlnLmludmFsaWQgfSxcclxuICAgIF0pO1xyXG5cclxuICAgIGNvbnN0IGV4dGVuc2lvbnM6IEV4dGVuc2lvbltdID0gW1xyXG4gICAgICAgIG9ic2lkaWFuVGhlbWUsXHJcbiAgICAgICAgbGluZU51bWJlcnMoKSxcclxuICAgICAgICBFZGl0b3JWaWV3LmxpbmVXcmFwcGluZyxcclxuICAgICAgICBweXRob24oKSwgLy8gaXQgaXMgYmV0dGVyIHRvIHdyaXRlIGEgbGFuZ3VhZ2Ugc3VwcG9ydCBmb3IgcnVsZXNcclxuICAgICAgICBzeW50YXhIaWdobGlnaHRpbmcob2JzaWRpYW5IaWdobGlnaHRTdHlsZSksXHJcbiAgICAgICAgRWRpdG9yVmlldy51cGRhdGVMaXN0ZW5lci5vZihhc3luYyAodjogVmlld1VwZGF0ZSkgPT4ge1xyXG4gICAgICAgICAgICBpZiAodi5kb2NDaGFuZ2VkKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHYuc3RhdGUuZG9jLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgICAgICBvbkNoYW5nZSh2YWx1ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KVxyXG4gICAgXTtcclxuXHJcbiAgb25Nb3VudCgoKSA9PiB7XHJcbiAgICBjb25zdCBzdGF0ZSA9IEVkaXRvclN0YXRlLmNyZWF0ZSh7XHJcbiAgICAgIGRvYzogaW5pdGlhbFRleHQsXHJcbiAgICAgIGV4dGVuc2lvbnM6IGV4dGVuc2lvbnNcclxuICAgIH0pO1xyXG5cclxuICAgIGVkaXRvciA9IG5ldyBFZGl0b3JWaWV3KHtcclxuICAgICAgc3RhdGUsXHJcbiAgICAgIHBhcmVudDogZWRpdG9yQ29udGFpbmVyXHJcbiAgICB9KTtcclxuICB9KTtcclxuPC9zY3JpcHQ+XHJcblxyXG48ZGl2IGJpbmQ6dGhpcz17ZWRpdG9yQ29udGFpbmVyfSBjbGFzcz1cInJ1bGVzLWVkaXRvci13cmFwcGVyXCI+PC9kaXY+XHJcblxyXG48c3R5bGU+XHJcbiAgLnJ1bGVzLWVkaXRvci13cmFwcGVyIHtcclxuICAgIGhlaWdodDogMjBlbTtcclxuICAgIHJlc2l6ZTogdmVydGljYWw7XHJcbiAgICBvdmVyZmxvdzogYXV0bztcclxuICAgIGZvbnQtc2l6ZTogdmFyKC0tZm9udC1pbnB1dHMpO1xyXG4gICAgYm9yZGVyOiAxcHggc29saWQgdmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ib3JkZXIpO1xyXG4gIH1cclxuPC9zdHlsZT5cclxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQThFRSxDQUFBLG9CQUFBLENBQUE7QUFDRSxVQUFBO0FBQ0EsVUFBQTtBQUNBLFlBQUE7QUFDQSxhQUFBLElBQUE7QUFDQSxVQUFBLElBQUEsTUFBQSxJQUFBO0FBQ0o7IiwKICAibmFtZXMiOiBbXQp9Cg== */ diff --git a/src/components/RuleSettings.svelte b/src/components/RuleSettings.svelte index ac8c664..a2bf917 100644 --- a/src/components/RuleSettings.svelte +++ b/src/components/RuleSettings.svelte @@ -19,8 +19,10 @@ let { plugin, pluginState }: RuleSettingsProps = $props(); + let { selectedProfileName, selectedProfileEl, baseProfileEl, profilesMap, editedProfile } = pluginState; + // Check Validity - import { setIcon } from "obsidian"; + import { Modal, Notice, setIcon } from "obsidian"; let validityText = $state(""); let validityIconEl: HTMLElement; @@ -43,11 +45,41 @@ } //Profile Actions + import StringInputModal from "./StringInputModal.svelte"; + import { mount } from "svelte"; + interface Profile { title: string; content: string; } + function selectProfile(name: string) { + selectedProfileName = name; + } + + function removeProfile(name: string) { + if (selectedProfileName === name) { + selectedProfileName = "global"; + } + profilesMap.delete(name); + } + + let showNewProfileModal = $state(false); + let newProfileModalError = $state(""); + + function handleProfileSubmit(name: string): boolean { + if (profilesMap.has(name)) { + newProfileModalError = "Profile already exists!"; + return false; + } + + profilesMap.set(name, ""); + selectedProfileName = name; + showNewProfileModal = false; + return true; + } + +
@@ -67,25 +99,44 @@
-
global
-
+
-
- - +
diff --git a/src/components/StringInputModal.svelte b/src/components/StringInputModal.svelte new file mode 100644 index 0000000..a3be777 --- /dev/null +++ b/src/components/StringInputModal.svelte @@ -0,0 +1,44 @@ + + + From 352b0af77e5a4053be3ba11cc4022aa9750253f6 Mon Sep 17 00:00:00 2001 From: caasion <103465188+caasion@users.noreply.github.com> Date: Sat, 16 Aug 2025 11:55:07 -0400 Subject: [PATCH 08/16] Refactor Validity Checker --- main.css | 9 ++ src/components/RuleEditor.svelte | 24 +++-- src/components/RuleSettings.svelte | 136 +++++++++++++++----------- src/components/ValidityChecker.svelte | 28 ++++++ src/settings.ts | 8 +- 5 files changed, 140 insertions(+), 65 deletions(-) create mode 100644 main.css create mode 100644 src/components/ValidityChecker.svelte diff --git a/main.css b/main.css new file mode 100644 index 0000000..921eafc --- /dev/null +++ b/main.css @@ -0,0 +1,9 @@ +/* fakecss:C:/Users/isaac/Main/Plugin Development/.obsidian/plugins/typing-transformer-obsidian/src/components/RuleEditor.esbuild-svelte-fake-css */ +.rules-editor-wrapper.svelte-1p6huli { + height: 20em; + resize: vertical; + overflow: auto; + font-size: var(--font-inputs); + border: 1px solid var(--background-modifier-border); +} +/*# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiUnVsZUVkaXRvci5zdmVsdGUiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIjxzY3JpcHQgbGFuZz1cInRzXCI+XHJcbiAgICBpbXBvcnQgeyBvbk1vdW50IH0gZnJvbSAnc3ZlbHRlJztcclxuICAgIGltcG9ydCB7IHB5dGhvbiB9IGZyb20gJ0Bjb2RlbWlycm9yL2xhbmctcHl0aG9uJztcclxuICAgIGltcG9ydCB7IGxpbmVOdW1iZXJzLCBFZGl0b3JWaWV3LCBWaWV3VXBkYXRlIH0gZnJvbSAnQGNvZGVtaXJyb3Ivdmlldyc7XHJcbiAgICBpbXBvcnQgeyBBbm5vdGF0aW9uLCBFZGl0b3JTdGF0ZSwgRXh0ZW5zaW9uIH0gZnJvbSAnQGNvZGVtaXJyb3Ivc3RhdGUnO1xyXG4gICAgaW1wb3J0IHsgc3ludGF4SGlnaGxpZ2h0aW5nLCBIaWdobGlnaHRTdHlsZSB9IGZyb20gJ0Bjb2RlbWlycm9yL2xhbmd1YWdlJztcclxuICAgIGltcG9ydCB7IGNvbmZpZyB9IGZyb20gJ3NyYy9zZXR0aW5ncyc7XHJcbiAgICBpbXBvcnQgeyB0YWdzIGFzIHQgfSBmcm9tIFwiQGxlemVyL2hpZ2hsaWdodFwiO1xyXG4gICAgaW1wb3J0IHsgbG9nIH0gZnJvbSAnc3JjL3V0aWxzJztcclxuXHJcbiAgICBpbnRlcmZhY2UgUnVsZUVkaXRvclByb3BzIHtcclxuICAgICAgICBjb250ZW50OiBzdHJpbmc7XHJcbiAgICAgICAgb25DaGFuZ2U6ICh0ZXh0OiBzdHJpbmcpID0+IHZvaWQ7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHsgY29udGVudCA9ICRiaW5kYWJsZSgpLCBvbkNoYW5nZSB9OiBSdWxlRWRpdG9yUHJvcHMgPSAkcHJvcHMoKTtcclxuXHJcbiAgICBjb25zdCBQcm9maWxlU3dpdGNoID0gQW5ub3RhdGlvbi5kZWZpbmU8Ym9vbGVhbj4oKTtcclxuXHJcblxyXG4gICAgbGV0IGVkaXRvckNvbnRhaW5lcjogSFRNTERpdkVsZW1lbnQ7XHJcbiAgICBsZXQgZWRpdG9yOiBFZGl0b3JWaWV3O1xyXG5cclxuICAgIGNvbnN0IG9ic2lkaWFuVGhlbWUgPSBFZGl0b3JWaWV3LnRoZW1lKHtcclxuICAgICAgICBcIiZcIjoge1xyXG4gICAgICAgICAgICBjb2xvcjogY29uZmlnLmZvcmVncm91bmQsXHJcbiAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogY29uZmlnLmJhY2tncm91bmQsXHJcbiAgICAgICAgfSxcclxuICAgICAgICBcIi5jbS1jb250ZW50XCI6IHsgY2FyZXRDb2xvcjogY29uZmlnLmN1cnNvciB9LFxyXG4gICAgICAgIFwiJi5jbS1mb2N1c2VkIC5jbS1jdXJzb3JcIjogeyBib3JkZXJMZWZ0Q29sb3I6IGNvbmZpZy5jdXJzb3IgfSxcclxuICAgICAgICBcIiYuY20tZm9jdXNlZCAuY20tc2VsZWN0aW9uQmFja2dyb3VuZCwgLmNtLXNlbGVjdGlvbkJhY2tncm91bmQsICYgOjpzZWxlY3Rpb25cIjogeyBiYWNrZ3JvdW5kQ29sb3I6IGNvbmZpZy5zZWxlY3Rpb24gfSxcclxuICAgICAgICBcIi5jbS1hY3RpdmVMaW5lXCI6IHsgYmFja2dyb3VuZENvbG9yOiBjb25maWcuYWN0aXZlTGluZSB9LFxyXG4gICAgICAgIFwiLmNtLWFjdGl2ZUxpbmVHdXR0ZXJcIjogeyBiYWNrZ3JvdW5kQ29sb3I6IGNvbmZpZy5iYWNrZ3JvdW5kIH0sXHJcbiAgICAgICAgXCIuY20tc2VsZWN0aW9uTWF0Y2hcIjogeyBiYWNrZ3JvdW5kQ29sb3I6IGNvbmZpZy5zZWxlY3Rpb24gfSxcclxuICAgICAgICBcIi5jbS1ndXR0ZXJzXCI6IHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZENvbG9yOiBjb25maWcuYmFja2dyb3VuZCxcclxuICAgICAgICAgICAgY29sb3I6IGNvbmZpZy5jb21tZW50LFxyXG4gICAgICAgICAgICBib3JkZXJSaWdodDogXCIxcHggc29saWQgdmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ib3JkZXIpXCJcclxuICAgICAgICB9LFxyXG4gICAgICAgIFwiLmNtLWxpbmVOdW1iZXJzLCAuY20tZ3V0dGVyRWxlbWVudFwiOiB7IGNvbG9yOiBcImluaGVyaXRcIiB9LFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3Qgb2JzaWRpYW5IaWdobGlnaHRTdHlsZSA9IEhpZ2hsaWdodFN0eWxlLmRlZmluZShbXHJcbiAgICAgICAgeyB0YWc6IFt0LnByb2Nlc3NpbmdJbnN0cnVjdGlvbiwgdC5zdHJpbmcsIHQuaW5zZXJ0ZWQsIHQuc3BlY2lhbCh0LnN0cmluZyldLCBjb2xvcjogY29uZmlnLnN0cmluZyB9LFxyXG4gICAgICAgIHsgdGFnOiBbdC5jb2xvciwgdC5jb25zdGFudCh0Lm5hbWUpLCB0LnN0YW5kYXJkKHQubmFtZSldLCBjb2xvcjogY29uZmlnLmNvbnN0YW50IH0sXHJcbiAgICAgICAgeyB0YWc6IHQuY29tbWVudCwgY29sb3I6IGNvbmZpZy5jb21tZW50IH0sXHJcbiAgICAgICAgeyB0YWc6IHQuaW52YWxpZCwgY29sb3I6IGNvbmZpZy5pbnZhbGlkIH0sXHJcbiAgICBdKTtcclxuXHJcbiAgICBjb25zdCBleHRlbnNpb25zOiBFeHRlbnNpb25bXSA9IFtcclxuICAgICAgICBvYnNpZGlhblRoZW1lLFxyXG4gICAgICAgIGxpbmVOdW1iZXJzKCksXHJcbiAgICAgICAgRWRpdG9yVmlldy5saW5lV3JhcHBpbmcsXHJcbiAgICAgICAgcHl0aG9uKCksIC8vIGl0IGlzIGJldHRlciB0byB3cml0ZSBhIGxhbmd1YWdlIHN1cHBvcnQgZm9yIHJ1bGVzXHJcbiAgICAgICAgc3ludGF4SGlnaGxpZ2h0aW5nKG9ic2lkaWFuSGlnaGxpZ2h0U3R5bGUpLFxyXG4gICAgICAgIEVkaXRvclZpZXcudXBkYXRlTGlzdGVuZXIub2YoYXN5bmMgKHY6IFZpZXdVcGRhdGUpID0+IHtcclxuICAgICAgICAgICAgaWYgKHYuZG9jQ2hhbmdlZCkge1xyXG4gICAgICAgICAgICAgICAgY29udGVudCA9IHYuc3RhdGUuZG9jLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgICAgICBvbkNoYW5nZShjb250ZW50KVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSlcclxuICAgIF07XHJcblxyXG4gIG9uTW91bnQoKCkgPT4ge1xyXG4gICAgY29uc3Qgc3RhdGUgPSBFZGl0b3JTdGF0ZS5jcmVhdGUoe1xyXG4gICAgICBkb2M6IGNvbnRlbnQsXHJcbiAgICAgIGV4dGVuc2lvbnM6IGV4dGVuc2lvbnNcclxuICAgIH0pO1xyXG5cclxuICAgIGVkaXRvciA9IG5ldyBFZGl0b3JWaWV3KHtcclxuICAgICAgc3RhdGUsXHJcbiAgICAgIHBhcmVudDogZWRpdG9yQ29udGFpbmVyXHJcbiAgICB9KTtcclxuXHJcbiAgICBsb2coY29udGVudClcclxuXHJcbiAgICBsb2coXCJFZGl0b3IgbGF1bmNoZWRcIiwgZWRpdG9yKVxyXG4gIH0pO1xyXG5cclxuICAkZWZmZWN0KCgpID0+IHtcclxuICAgIGlmIChlZGl0b3IgJiYgY29udGVudCAhPT0gZWRpdG9yLnN0YXRlLmRvYy50b1N0cmluZygpKSB7XHJcbiAgICBlZGl0b3IuZGlzcGF0Y2goe1xyXG4gICAgICBjaGFuZ2VzOiB7IGZyb206IDAsIHRvOiBlZGl0b3Iuc3RhdGUuZG9jLmxlbmd0aCwgaW5zZXJ0OiBjb250ZW50IH1cclxuICAgIH0pO1xyXG4gIH19KVxyXG48L3NjcmlwdD5cclxuXHJcbjxkaXYgYmluZDp0aGlzPXtlZGl0b3JDb250YWluZXJ9IGNsYXNzPVwicnVsZXMtZWRpdG9yLXdyYXBwZXJcIj48L2Rpdj5cclxuXHJcbjxzdHlsZT5cclxuICAucnVsZXMtZWRpdG9yLXdyYXBwZXIge1xyXG4gICAgaGVpZ2h0OiAyMGVtO1xyXG4gICAgcmVzaXplOiB2ZXJ0aWNhbDtcclxuICAgIG92ZXJmbG93OiBhdXRvO1xyXG4gICAgZm9udC1zaXplOiB2YXIoLS1mb250LWlucHV0cyk7XHJcbiAgICBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1iYWNrZ3JvdW5kLW1vZGlmaWVyLWJvcmRlcik7XHJcbiAgfVxyXG48L3N0eWxlPlxyXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBMEZFLENBQUEsb0JBQUEsQ0FBQTtBQUNFLFVBQUE7QUFDQSxVQUFBO0FBQ0EsWUFBQTtBQUNBLGFBQUEsSUFBQTtBQUNBLFVBQUEsSUFBQSxNQUFBLElBQUE7QUFDSjsiLAogICJuYW1lcyI6IFtdCn0K */ diff --git a/src/components/RuleEditor.svelte b/src/components/RuleEditor.svelte index cbb7f8c..ec5a15a 100644 --- a/src/components/RuleEditor.svelte +++ b/src/components/RuleEditor.svelte @@ -6,13 +6,14 @@ import { syntaxHighlighting, HighlightStyle } from '@codemirror/language'; import { config } from 'src/settings'; import { tags as t } from "@lezer/highlight"; + import { log } from 'src/utils'; interface RuleEditorProps { - initialText: string, - onChange: (text: string) => void, + content: string; + onChange: (text: string) => void; } - let { initialText, onChange }: RuleEditorProps = $props(); + let { content = $bindable(), onChange }: RuleEditorProps = $props(); const ProfileSwitch = Annotation.define(); @@ -54,15 +55,15 @@ syntaxHighlighting(obsidianHighlightStyle), EditorView.updateListener.of(async (v: ViewUpdate) => { if (v.docChanged) { - const value = v.state.doc.toString(); - onChange(value); + content = v.state.doc.toString(); + onChange(content) } }) ]; onMount(() => { const state = EditorState.create({ - doc: initialText, + doc: content, extensions: extensions }); @@ -70,7 +71,18 @@ state, parent: editorContainer }); + + log(content) + + log("Editor launched", editor) }); + + $effect(() => { + if (editor && content !== editor.state.doc.toString()) { + editor.dispatch({ + changes: { from: 0, to: editor.state.doc.length, insert: content } + }); + }})
diff --git a/src/components/RuleSettings.svelte b/src/components/RuleSettings.svelte index a2bf917..0f931fa 100644 --- a/src/components/RuleSettings.svelte +++ b/src/components/RuleSettings.svelte @@ -1,28 +1,30 @@ @@ -99,29 +107,41 @@
- {#each Array.from(profilesMap.keys()) as name (name)} -
- - - {#if name !== "global"} - - {/if} + {#each profiles as profile (profile.title)}
+ + {#if profile.title !== "global"} + + {/if} +
{/each} - - + + {#if newProfilePromptDisplay} + { + if (e.key === "Enter") handleAddProfile(newProfileName); + }} + /> + + + {:else} + + {/if}
- + diff --git a/styles.css b/styles.css index 0233944..9bdbc09 100644 --- a/styles.css +++ b/styles.css @@ -38,16 +38,20 @@ } -.rules-profile-button { +.rules-profile-container { display: flex; height: 40px; min-width: 20px; align-items: center; padding: 0px 10px 12px 10px; - + background-color: var(--interactive-normal); +} + +.rules-profile-container:hover { + background-color: var(--interactive-normal); } -.rules-profile-button svg { +.rules-profile-container svg { width: 12px !important; height: 12px !important; } @@ -57,13 +61,17 @@ margin-right: 0px; } -.rules-profile-button.selected { +.rules-profile-container.selected { background: var(--background-primary); color: var(--text-on-accent); } -.rules-profile-button.clickable-icon { - margin: 0 5px; +.rules-profile-container button { + background-color: transparent; +} + +.rules-profile-container button:hover { + background-color: transparent !important; } .rules-footer { From bdfc3716607e74402db64756af2c4219ad7a66a9 Mon Sep 17 00:00:00 2001 From: caasion <103465188+caasion@users.noreply.github.com> Date: Sun, 17 Aug 2025 09:11:49 -0400 Subject: [PATCH 16/16] Remove Old Settings --- src/settings.ts | 235 ------------------------------------------------ 1 file changed, 235 deletions(-) diff --git a/src/settings.ts b/src/settings.ts index 06f62a9..221f2ff 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -134,241 +134,6 @@ export class SettingTab extends PluginSettingTab { } } -export interface State { - selectedProfileName: string, - selectedProfileEl: HTMLElement, - baseProfileEl: HTMLElement, - profilesMap: Map, - editedProfile: Set -} - -function createRuleEditorInContainer(container: HTMLElement, plugin: TypingTransformer, state: State): EditorView { - // source: obsidian-latex-suite setting tab, thanks a lot. - const fragment = document.createDocumentFragment(); - fragment.createEl("span", { text: "Enter conversion, selection, and deletion rules here. NOTES:" }); //line 1 - const ol = fragment.createEl("ol"); - ol.createEl("li", { text: "Each line is one rule. Rules that come first have higher priority." }); //note 1 - ol.createEl("li", { text: "Lines starting with \"#\" are treated as comments and ignored. Inline comments are also allowed" }); //note 2 - ol.createEl("li", { text: "The character '|' indicates where your cursor will be placed after the rule is applied."}); //note 3 - ol.createEl("li", { text: "To use special characters like '|' for conversion, you escape them with a backslash, for example: '\\|' "}); - ol.createEl("li", { text: "Whatever tab you are on when the plugin settings tab quits will be the profile that is chosen" }); - ol.createEl("li", { text: "The 'global' profile will always be active" }); - - const convertRulesSetting = new Setting(container) - .setName("Rules") - .setDesc(fragment) - .setClass("rules-text-area"); - - const profilesContainer = convertRulesSetting.controlEl.createDiv("rules-profiles"); - const customCSSWrapper = convertRulesSetting.controlEl.createDiv("rules-editor-wrapper"); - const rulesFooter = convertRulesSetting.controlEl.createDiv("rules-footer"); - const validity = rulesFooter.createDiv("rules-editor-validity"); - - const validityIndicator = new ExtraButtonComponent(validity); - validityIndicator.setIcon("checkmark") - .extraSettingsEl.addClass("rules-editor-validity-indicator"); - - const validityText = validity.createDiv("rules-editor-validity-text"); - validityText.classList.add("setting-item-description", "rules-editor-validity-txt"); - - function resetValidityIndicator() { - validityIndicator.setIcon(''); - validityIndicator.extraSettingsEl.removeClasses(["invalid", "valid"]); - validityText.setText(''); - } - - async function tryResetValidityIndicator(): Promise { - if (validityIndicator.extraSettingsEl.hasClass("invalid")) { - return new Promise((resolve, _reject) => { - new ConfirmationModal( - app, - "Are you sure you want to discard changes?", - async (ans: boolean) => { - if (ans) resetValidityIndicator(); - resolve(ans); - }, - ).open(); - }); - } else { - resetValidityIndicator(); - return new Promise((resolve, _reject) => resolve(true)); - } - } - - function updateValidityIndicator(success: boolean, errs: string[]) { - validityIndicator.setIcon(success ? "checkmark" : "cross"); - validityIndicator.extraSettingsEl.removeClass(success ? "invalid" : "valid"); - validityIndicator.extraSettingsEl.addClass(success ? "valid" : "invalid"); - const fragment = document.createDocumentFragment(); - for (const err of errs) { - fragment.createEl("div", { text: err }); - } - validityText.setText(success ? "Saved" : fragment); - } - - const extensions: Extension[] = [ - obsidianTheme, - lineNumbers(), - EditorView.lineWrapping, - python(), // it is better to write a language support for rules - syntaxHighlighting(obsidianHighlightStyle), - EditorView.updateListener.of(async (v: ViewUpdate) => { - if (v.docChanged) { - if (v.transactions.reduce((swtich, tr): boolean => swtich || tr.annotation(ProfileSwitch), false)) { - return; - } - const value = v.state.doc.toString(); - await feedRules(value); - } - }) - ]; - - const feedRules = async (newRule: string) => { - const errs = await plugin.checkRules(newRule); - if (errs.length != 0) { - updateValidityIndicator(false, errs); - } else { - updateValidityIndicator(true, []); - const { selectedProfileName: target, profilesMap: map, editedProfile: set } = state; - map.set(target, newRule); - set.add(target); - } - }; - - const setCMEditorContent = (text: string) => { - convertRulesEditor.dispatch({ - changes: { from: 0, to: convertRulesEditor.state.doc.length, insert: text }, - annotations: ProfileSwitch.of(true) - }); - }; - - const convertRulesEditor = new EditorView({ - state: EditorState.create({ doc: plugin.settings.convertRules, extensions: extensions }) - }); - customCSSWrapper.appendChild(convertRulesEditor.dom); - - const buttonsDiv = rulesFooter.createDiv("rules-editor-buttons"); - const reset = new ButtonComponent(buttonsDiv); - reset.setIcon("switch") - .setTooltip("Reset to default rules") - .onClick(async () => { - convertRulesEditor.setState(EditorState.create({ doc: DEFAULT_RULES, extensions: extensions })); - await feedRules(DEFAULT_RULES); - }); - - const onProfileClick = async (name: string, el: HTMLElement) => { - if (! await tryResetValidityIndicator()) return; - state.selectedProfileEl?.removeClass("selected"); - el?.addClass("selected"); - state.selectedProfileEl = el; - state.selectedProfileName = name; - setCMEditorContent(state.profilesMap.get(name)); - }; - - const onRemoveProfileClick = (name: string, el: HTMLElement) => { - if (el === state.selectedProfileEl) - // switch to base profile - onProfileClick(BaseProfileName, state.baseProfileEl); - state.profilesMap.delete(name); - state.editedProfile.add(name); - profilesContainer.removeChild(el); - }; - - const addProfile = (profile: Profile, selected: boolean) => { - const button = new ExtraButtonComponent(profilesContainer); - const el = button.extraSettingsEl; - el.accessKey = profile.title; - button.onClick(() => onProfileClick(profile.title, el)); - el.addClass("rules-profile-button"); - el.setText(profile.title); - if (profile.title != BaseProfileName) { // base profile can't be deleted - const closeEl = new ExtraButtonComponent(el).setIcon("cross").extraSettingsEl; - closeEl.onClickEvent((ev) => { ev.stopPropagation(); onRemoveProfileClick(profile.title, el); }); - closeEl.addClass("rules-profile-close"); - } else { - state.baseProfileEl = el; - } - if (selected) { onProfileClick(profile.title, el); } - }; - - for (const profile of plugin.settings.profiles) { - addProfile(profile, profile.title === plugin.settings.activeProfile); - } - - const addButton = new ExtraButtonComponent(profilesContainer).onClick(() => { - if (state.profilesMap.size > 5) { - new Notice("You can only have 6 profiles at most."); - return; - } - new StringInputModal(app, (value: string): boolean => { - if (state.profilesMap.has(value)) return false; - if (value === undefined) return true; - state.profilesMap.set(value, ""); - state.editedProfile.add(value); - profilesContainer.removeChild(addButton.extraSettingsEl); - addProfile({ title: value, content: "" }, true); - profilesContainer.appendChild(addButton.extraSettingsEl); - return true; - }).open(); - }); - addButton.extraSettingsEl.addClass("rules-profile-button"); - addButton.extraSettingsEl.setText("+"); - - return convertRulesEditor; -} - - - -class StringInputModal extends Modal { - err: HTMLElement; - result: string; - onSubmit: (result: string) => boolean; - - constructor(app: App, onSubmit: (result: string) => boolean) { - super(app); - this.onSubmit = onSubmit; - } - - submitEnterCallback = (evt: KeyboardEvent) => { - if (evt.key === "Enter") { - evt.preventDefault(); - this.submit(); - } - }; - - submit() { - if (this.onSubmit(this.result)) this.close(); - else this.err.setText("Profile already exists!"); - } - - onOpen() { - const { titleEl, contentEl } = this; - - titleEl.setText("Profile Name"); - - const container = contentEl.createDiv(); - const textComponent = new TextComponent(container); - this.err = container.createEl("p"); - - textComponent.inputEl.style.width = "100%"; - textComponent - .onChange((value) => this.result = value) - .inputEl.addEventListener('keydown', this.submitEnterCallback); - - new Setting(contentEl) - .addButton((btn) => btn - .setButtonText("Submit") - .setCta() - .onClick(() => this.submit())); - } - - onClose() { - this.contentEl.empty(); - } -} - - - export class ConfirmationModal extends Modal { constructor(app: App, prompt: string, confirmCb: (ans: boolean) => Promise) {