Enhance Mindnet settings interface with new configuration options
Some checks are pending
Node.js build / build (20.x) (push) Waiting to run
Node.js build / build (22.x) (push) Waiting to run

- Added sections for Dictionary & Schema Configuration, Graph Traversal & Linting, Interview & Note Creation, Unresolved Link Handling, Templater Compatibility, Note Adoption, and Semantic Mapping Builder.
- Updated descriptions for various settings to provide clearer guidance in German.
- Introduced new settings for interview configuration paths, default notes folder, and handling of unresolved links.
- Improved user experience with additional validation options and clearer descriptions for existing settings.
This commit is contained in:
Lars 2026-01-17 10:54:32 +01:00
parent 5ed06e6b9a
commit 56049b9318

View File

@ -17,10 +17,21 @@ export class MindnetSettingTab extends PluginSettingTab {
containerEl.createEl("h2", { text: "Mindnet Settings" }); containerEl.createEl("h2", { text: "Mindnet Settings" });
// ============================================
// 1. Dictionary & Schema Configuration
// ============================================
containerEl.createEl("h3", { text: "📚 Dictionary & Schema" });
containerEl.createEl("p", {
text: "Konfigurationsdateien für Edge-Vokabular, Graph-Schema und Interview-Profile.",
cls: "setting-item-description",
});
// Edge vocabulary path // Edge vocabulary path
new Setting(containerEl) new Setting(containerEl)
.setName("Edge vocabulary path") .setName("Edge vocabulary path")
.setDesc("Vault-relative path to the edge vocabulary markdown file") .setDesc(
"Pfad zur Edge-Vokabular-Datei (Markdown). Definiert verfügbare Edge-Typen und deren Beschreibungen. Wird für die semantische Mapping-Erstellung verwendet."
)
.addText((text) => .addText((text) =>
text text
.setPlaceholder("_system/dictionary/edge_vocabulary.md") .setPlaceholder("_system/dictionary/edge_vocabulary.md")
@ -55,7 +66,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Graph schema path // Graph schema path
new Setting(containerEl) new Setting(containerEl)
.setName("Graph schema path") .setName("Graph schema path")
.setDesc("Vault-relative path to the graph schema markdown file") .setDesc(
"Pfad zur Graph-Schema-Datei (Markdown). Definiert typische und verbotene Edge-Typen für verschiedene Quelltypen. Wird für Empfehlungen beim Mapping verwendet."
)
.addText((text) => .addText((text) =>
text text
.setPlaceholder("_system/dictionary/graph_schema.md") .setPlaceholder("_system/dictionary/graph_schema.md")
@ -95,71 +108,12 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// Strict mode toggle
new Setting(containerEl)
.setName("Strict mode")
.setDesc("Enable strict validation mode")
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.strictMode)
.onChange(async (value) => {
this.plugin.settings.strictMode = value;
await this.plugin.saveSettings();
})
);
// Max hops number input
new Setting(containerEl)
.setName("Max hops")
.setDesc("Maximum number of hops for graph traversal")
.addText((text) =>
text
.setPlaceholder("3")
.setValue(String(this.plugin.settings.maxHops))
.onChange(async (value) => {
const numValue = parseInt(value, 10);
if (!isNaN(numValue) && numValue > 0) {
this.plugin.settings.maxHops = numValue;
await this.plugin.saveSettings();
}
})
);
// Show canonical hints toggle
new Setting(containerEl)
.setName("Show canonical hints")
.setDesc("Show INFO findings with canonical edge type resolution in lint results")
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.showCanonicalHints)
.onChange(async (value) => {
this.plugin.settings.showCanonicalHints = value;
await this.plugin.saveSettings();
})
);
// Chain direction dropdown
new Setting(containerEl)
.setName("Chain direction")
.setDesc("Direction for chain traversal: forward, backward, or both")
.addDropdown((dropdown) =>
dropdown
.addOption("forward", "Forward")
.addOption("backward", "Backward")
.addOption("both", "Both")
.setValue(this.plugin.settings.chainDirection)
.onChange(async (value) => {
if (value === "forward" || value === "backward" || value === "both") {
this.plugin.settings.chainDirection = value;
await this.plugin.saveSettings();
}
})
);
// Interview config path // Interview config path
new Setting(containerEl) new Setting(containerEl)
.setName("Interview config path") .setName("Interview config path")
.setDesc("Vault-relative path to the interview config YAML file") .setDesc(
"Pfad zur Interview-Konfigurationsdatei (YAML). Definiert verfügbare Interview-Profile mit ihren Schritten und Einstellungen."
)
.addText((text) => .addText((text) =>
text text
.setPlaceholder("_system/dictionary/interview_config.yaml") .setPlaceholder("_system/dictionary/interview_config.yaml")
@ -197,10 +151,99 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// Auto-start interview toggle // ============================================
// 2. Graph Traversal & Linting
// ============================================
containerEl.createEl("h3", { text: "🔍 Graph Traversal & Linting" });
containerEl.createEl("p", {
text: "Einstellungen für Graph-Durchquerung und Lint-Validierung.",
cls: "setting-item-description",
});
// Max hops
new Setting(containerEl)
.setName("Max hops")
.setDesc(
"Maximale Anzahl von Hops (Schritten) bei der Graph-Durchquerung. Bestimmt, wie tief der Graph durchsucht wird."
)
.addText((text) =>
text
.setPlaceholder("3")
.setValue(String(this.plugin.settings.maxHops))
.onChange(async (value) => {
const numValue = parseInt(value, 10);
if (!isNaN(numValue) && numValue > 0) {
this.plugin.settings.maxHops = numValue;
await this.plugin.saveSettings();
}
})
);
// Chain direction
new Setting(containerEl)
.setName("Chain direction")
.setDesc(
"Richtung für Chain-Traversal: 'Forward' (vorwärts), 'Backward' (rückwärts) oder 'Both' (beide Richtungen)."
)
.addDropdown((dropdown) =>
dropdown
.addOption("forward", "Forward")
.addOption("backward", "Backward")
.addOption("both", "Both")
.setValue(this.plugin.settings.chainDirection)
.onChange(async (value) => {
if (value === "forward" || value === "backward" || value === "both") {
this.plugin.settings.chainDirection = value;
await this.plugin.saveSettings();
}
})
);
// Strict mode
new Setting(containerEl)
.setName("Strict mode")
.setDesc(
"Aktiviert den strikten Validierungsmodus. Erzwingt strengere Regeln bei der Lint-Validierung."
)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.strictMode)
.onChange(async (value) => {
this.plugin.settings.strictMode = value;
await this.plugin.saveSettings();
})
);
// Show canonical hints
new Setting(containerEl)
.setName("Show canonical hints")
.setDesc(
"Zeigt INFO-Hinweise mit kanonischer Edge-Typ-Auflösung in den Lint-Ergebnissen an. Hilfreich für die Debugging von Edge-Typ-Zuordnungen."
)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.showCanonicalHints)
.onChange(async (value) => {
this.plugin.settings.showCanonicalHints = value;
await this.plugin.saveSettings();
})
);
// ============================================
// 3. Interview & Note Creation
// ============================================
containerEl.createEl("h3", { text: "📝 Interview & Note Creation" });
containerEl.createEl("p", {
text: "Einstellungen für Interview-Wizard und Notiz-Erstellung.",
cls: "setting-item-description",
});
// Auto-start interview on create
new Setting(containerEl) new Setting(containerEl)
.setName("Auto-start interview on create") .setName("Auto-start interview on create")
.setDesc("Automatically start interview wizard when creating a note from profile") .setDesc(
"Startet automatisch den Interview-Wizard, wenn eine neue Notiz über ein Profil erstellt wird."
)
.addToggle((toggle) => .addToggle((toggle) =>
toggle toggle
.setValue(this.plugin.settings.autoStartInterviewOnCreate) .setValue(this.plugin.settings.autoStartInterviewOnCreate)
@ -210,10 +253,37 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// Intercept unresolved links toggle // Default notes folder
new Setting(containerEl)
.setName("Default notes folder")
.setDesc(
"Standard-Ordner für neue Notizen (vault-relativer Pfad, leer für Root). Profil-spezifische Defaults haben Vorrang."
)
.addText((text) =>
text
.setPlaceholder("")
.setValue(this.plugin.settings.defaultNotesFolder)
.onChange(async (value) => {
this.plugin.settings.defaultNotesFolder = value || "";
await this.plugin.saveSettings();
})
);
// ============================================
// 4. Unresolved Link Handling
// ============================================
containerEl.createEl("h3", { text: "🔗 Unresolved Link Handling" });
containerEl.createEl("p", {
text: "Konfiguration für das Verhalten bei Klicks auf nicht aufgelöste Links.",
cls: "setting-item-description",
});
// Intercept unresolved links
new Setting(containerEl) new Setting(containerEl)
.setName("Intercept unresolved link clicks") .setName("Intercept unresolved link clicks")
.setDesc("Open profile selection when clicking unresolved internal links") .setDesc(
"Aktiviert die Abfangen von Klicks auf nicht aufgelöste interne Links. Öffnet die Profilauswahl, wenn auf einen nicht existierenden Link geklickt wird."
)
.addToggle((toggle) => .addToggle((toggle) =>
toggle toggle
.setValue(this.plugin.settings.interceptUnresolvedLinkClicks) .setValue(this.plugin.settings.interceptUnresolvedLinkClicks)
@ -223,10 +293,12 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// Auto-start interview on unresolved click toggle // Auto-start interview on unresolved click
new Setting(containerEl) new Setting(containerEl)
.setName("Auto-start interview on unresolved link click") .setName("Auto-start interview on unresolved link click")
.setDesc("Automatically start interview wizard when creating note from unresolved link") .setDesc(
"Startet automatisch den Interview-Wizard, wenn eine Notiz aus einem nicht aufgelösten Link erstellt wird. Erfordert, dass 'Intercept unresolved link clicks' aktiviert ist."
)
.addToggle((toggle) => .addToggle((toggle) =>
toggle toggle
.setValue(this.plugin.settings.autoStartOnUnresolvedClick) .setValue(this.plugin.settings.autoStartOnUnresolvedClick)
@ -239,7 +311,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Bypass modifier (Reading View) // Bypass modifier (Reading View)
new Setting(containerEl) new Setting(containerEl)
.setName("Bypass modifier (Reading View)") .setName("Bypass modifier (Reading View)")
.setDesc("Modifier key to bypass unresolved link intercept in Reading View (Alt/Ctrl/Shift/None)") .setDesc(
"Modifier-Taste zum Umgehen des Link-Intercepts in der Leseansicht. Wenn diese Taste gedrückt wird, wird der Standard-Link-Klick ausgeführt (z.B. zum Erstellen einer leeren Notiz)."
)
.addDropdown((dropdown) => .addDropdown((dropdown) =>
dropdown dropdown
.addOption("Alt", "Alt") .addOption("Alt", "Alt")
@ -258,7 +332,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Editor follow modifier (Live Preview/Source) // Editor follow modifier (Live Preview/Source)
new Setting(containerEl) new Setting(containerEl)
.setName("Editor follow modifier (Live Preview/Source)") .setName("Editor follow modifier (Live Preview/Source)")
.setDesc("Modifier key required to intercept unresolved links in editor (Alt/Ctrl/Shift/None). Default: Ctrl/Cmd") .setDesc(
"Modifier-Taste, die im Editor (Live Preview/Source) gedrückt werden muss, um den Link-Intercept zu aktivieren. Standard: Ctrl/Cmd. Verhindert versehentliche Intercepts beim normalen Bearbeiten."
)
.addDropdown((dropdown) => .addDropdown((dropdown) =>
dropdown dropdown
.addOption("Alt", "Alt") .addOption("Alt", "Alt")
@ -274,10 +350,21 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// ============================================
// 5. Templater Compatibility
// ============================================
containerEl.createEl("h3", { text: "⚙️ Templater Compatibility" });
containerEl.createEl("p", {
text: "Einstellungen für die Kompatibilität mit dem Templater-Plugin.",
cls: "setting-item-description",
});
// Wait for first modify after create // Wait for first modify after create
new Setting(containerEl) new Setting(containerEl)
.setName("Wait for first modify after create") .setName("Wait for first modify after create")
.setDesc("Wait for Templater to modify file before starting wizard (recommended if using Templater)") .setDesc(
"Wartet, bis Templater die Datei modifiziert hat, bevor der Wizard gestartet wird. Empfohlen, wenn Templater verwendet wird, um Konflikte zu vermeiden."
)
.addToggle((toggle) => .addToggle((toggle) =>
toggle toggle
.setValue(this.plugin.settings.waitForFirstModifyAfterCreate) .setValue(this.plugin.settings.waitForFirstModifyAfterCreate)
@ -290,7 +377,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Modify timeout // Modify timeout
new Setting(containerEl) new Setting(containerEl)
.setName("Modify timeout (ms)") .setName("Modify timeout (ms)")
.setDesc("Timeout in milliseconds for waiting for file modify event") .setDesc(
"Timeout in Millisekunden für das Warten auf ein File-Modify-Event. Wenn Templater nicht innerhalb dieser Zeit reagiert, wird der Wizard trotzdem gestartet."
)
.addText((text) => .addText((text) =>
text text
.setPlaceholder("1200") .setPlaceholder("1200")
@ -304,23 +393,21 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// Debug logging // ============================================
new Setting(containerEl) // 6. Note Adoption
.setName("Debug logging") // ============================================
.setDesc("Enable debug logging for unresolved link handling") containerEl.createEl("h3", { text: "🔄 Note Adoption" });
.addToggle((toggle) => containerEl.createEl("p", {
toggle text: "Einstellungen für die automatische Übernahme neu erstellter Notizen im Editor.",
.setValue(this.plugin.settings.debugLogging) cls: "setting-item-description",
.onChange(async (value) => { });
this.plugin.settings.debugLogging = value;
await this.plugin.saveSettings();
})
);
// Adopt new notes in editor // Adopt new notes in editor
new Setting(containerEl) new Setting(containerEl)
.setName("Adopt new notes in editor") .setName("Adopt new notes in editor")
.setDesc("Automatically adopt newly created notes in editor and convert to Mindnet format") .setDesc(
"Übernimmt automatisch neu erstellte Notizen im Editor und konvertiert sie in das Mindnet-Format (mit Frontmatter-ID). Nützlich, wenn Obsidian eine Notiz direkt erstellt, bevor unser Intercept greift."
)
.addToggle((toggle) => .addToggle((toggle) =>
toggle toggle
.setValue(this.plugin.settings.adoptNewNotesInEditor) .setValue(this.plugin.settings.adoptNewNotesInEditor)
@ -333,7 +420,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Adopt max chars // Adopt max chars
new Setting(containerEl) new Setting(containerEl)
.setName("Adopt max chars") .setName("Adopt max chars")
.setDesc("Maximum content length to consider a note as adopt-candidate (default: 200)") .setDesc(
"Maximale Inhaltslänge (in Zeichen), um eine Notiz als Übernahme-Kandidat zu betrachten. Leere oder sehr kurze Notizen werden bevorzugt übernommen."
)
.addText((text) => .addText((text) =>
text text
.setPlaceholder("200") .setPlaceholder("200")
@ -350,7 +439,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Adopt confirm mode // Adopt confirm mode
new Setting(containerEl) new Setting(containerEl)
.setName("Adopt confirm mode") .setName("Adopt confirm mode")
.setDesc("When to show adoption confirmation: always, onlyLowConfidence (skip for high-confidence), or never") .setDesc(
"Wann die Übernahme-Bestätigung angezeigt wird: 'Always ask' (immer fragen), 'Only for low confidence' (nur bei niedriger Konfidenz, überspringt bei hoher Konfidenz), oder 'Never ask' (nie fragen, automatisch übernehmen)."
)
.addDropdown((dropdown) => .addDropdown((dropdown) =>
dropdown dropdown
.addOption("always", "Always ask") .addOption("always", "Always ask")
@ -368,7 +459,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// High confidence window // High confidence window
new Setting(containerEl) new Setting(containerEl)
.setName("High confidence window (ms)") .setName("High confidence window (ms)")
.setDesc("Time window in milliseconds for high-confidence adoption (default: 3000)") .setDesc(
"Zeitfenster in Millisekunden für die hohe Konfidenz-Übernahme. Notizen, die innerhalb dieses Zeitfensters nach einem Klick erstellt wurden, werden mit hoher Konfidenz als Übernahme-Kandidaten betrachtet."
)
.addText((text) => .addText((text) =>
text text
.setPlaceholder("3000") .setPlaceholder("3000")
@ -382,13 +475,21 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// Semantic Mapping Builder section // ============================================
containerEl.createEl("h2", { text: "Semantic Mapping Builder" }); // 7. Semantic Mapping Builder
// ============================================
containerEl.createEl("h3", { text: "🕸️ Semantic Mapping Builder" });
containerEl.createEl("p", {
text: "Einstellungen für den Semantic Mapping Builder, der automatisch Mapping-Blöcke in Notizen erstellt.",
cls: "setting-item-description",
});
// Wrapper callout type // Wrapper callout type
new Setting(containerEl) new Setting(containerEl)
.setName("Mapping wrapper callout type") .setName("Mapping wrapper callout type")
.setDesc("Callout type for the mapping wrapper (e.g., 'abstract', 'info', 'note')") .setDesc(
"Callout-Typ für den Mapping-Wrapper (z.B. 'abstract', 'info', 'note'). Bestimmt das visuelle Erscheinungsbild des Mapping-Blocks."
)
.addText((text) => .addText((text) =>
text text
.setPlaceholder("abstract") .setPlaceholder("abstract")
@ -402,7 +503,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Wrapper title // Wrapper title
new Setting(containerEl) new Setting(containerEl)
.setName("Mapping wrapper title") .setName("Mapping wrapper title")
.setDesc("Title text for the mapping wrapper callout") .setDesc(
"Titel-Text für den Mapping-Wrapper-Callout. Wird als Überschrift des Mapping-Blocks angezeigt."
)
.addText((text) => .addText((text) =>
text text
.setPlaceholder("🕸️ Semantic Mapping") .setPlaceholder("🕸️ Semantic Mapping")
@ -416,7 +519,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Wrapper folded // Wrapper folded
new Setting(containerEl) new Setting(containerEl)
.setName("Mapping wrapper folded") .setName("Mapping wrapper folded")
.setDesc("Start with mapping wrapper callout folded (collapsed)") .setDesc(
"Startet mit dem Mapping-Wrapper-Callout eingeklappt (collapsed). Reduziert visuellen Lärm in der Notiz."
)
.addToggle((toggle) => .addToggle((toggle) =>
toggle toggle
.setValue(this.plugin.settings.mappingWrapperFolded) .setValue(this.plugin.settings.mappingWrapperFolded)
@ -426,24 +531,12 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// Default edge type
new Setting(containerEl)
.setName("Default edge type")
.setDesc("Default edge type for unmapped links (if unassignedHandling is 'defaultType')")
.addText((text) =>
text
.setPlaceholder("")
.setValue(this.plugin.settings.defaultEdgeType)
.onChange(async (value) => {
this.plugin.settings.defaultEdgeType = value;
await this.plugin.saveSettings();
})
);
// Unassigned handling // Unassigned handling
new Setting(containerEl) new Setting(containerEl)
.setName("Unassigned handling") .setName("Unassigned handling")
.setDesc("How to handle links without existing mappings: prompt (interactive), none, defaultType, or advisor") .setDesc(
"Wie Links ohne bestehende Mappings behandelt werden: 'Prompt (interactive)' (interaktive Auswahl), 'None (skip unmapped)' (überspringen), 'Use default edge type' (Standard-Typ verwenden), oder 'Use advisor' (zukünftig: E1-Engine)."
)
.addDropdown((dropdown) => .addDropdown((dropdown) =>
dropdown dropdown
.addOption("prompt", "Prompt (interactive)") .addOption("prompt", "Prompt (interactive)")
@ -459,10 +552,28 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// Default edge type
new Setting(containerEl)
.setName("Default edge type")
.setDesc(
"Standard-Edge-Typ für nicht zugeordnete Links. Wird nur verwendet, wenn 'Unassigned handling' auf 'Use default edge type' gesetzt ist."
)
.addText((text) =>
text
.setPlaceholder("")
.setValue(this.plugin.settings.defaultEdgeType)
.onChange(async (value) => {
this.plugin.settings.defaultEdgeType = value;
await this.plugin.saveSettings();
})
);
// Allow overwrite existing mappings // Allow overwrite existing mappings
new Setting(containerEl) new Setting(containerEl)
.setName("Allow overwrite existing mappings") .setName("Allow overwrite existing mappings")
.setDesc("If enabled, will prompt to confirm before overwriting existing edge type assignments") .setDesc(
"Wenn aktiviert, wird vor dem Überschreiben bestehender Edge-Typ-Zuordnungen eine Bestätigung angefordert. Wenn deaktiviert, werden bestehende Mappings immer beibehalten."
)
.addToggle((toggle) => .addToggle((toggle) =>
toggle toggle
.setValue(this.plugin.settings.allowOverwriteExistingMappings) .setValue(this.plugin.settings.allowOverwriteExistingMappings)
@ -472,16 +583,26 @@ export class MindnetSettingTab extends PluginSettingTab {
}) })
); );
// Default notes folder // ============================================
// 8. Debug & Development
// ============================================
containerEl.createEl("h3", { text: "🐛 Debug & Development" });
containerEl.createEl("p", {
text: "Einstellungen für Debugging und Entwicklung.",
cls: "setting-item-description",
});
// Debug logging
new Setting(containerEl) new Setting(containerEl)
.setName("Default notes folder") .setName("Debug logging")
.setDesc("Default folder for new notes (vault-relative path, empty for root). Profile defaults take precedence.") .setDesc(
.addText((text) => "Aktiviert ausführliches Debug-Logging für das Unresolved-Link-Handling. Logs erscheinen in der Browser-Konsole (F12). Nützlich für die Fehlersuche."
text )
.setPlaceholder("") .addToggle((toggle) =>
.setValue(this.plugin.settings.defaultNotesFolder) toggle
.setValue(this.plugin.settings.debugLogging)
.onChange(async (value) => { .onChange(async (value) => {
this.plugin.settings.defaultNotesFolder = value || ""; this.plugin.settings.debugLogging = value;
await this.plugin.saveSettings(); await this.plugin.saveSettings();
}) })
); );