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" });
// ============================================
// 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
new Setting(containerEl)
.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) =>
text
.setPlaceholder("_system/dictionary/edge_vocabulary.md")
@ -55,7 +66,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Graph schema path
new Setting(containerEl)
.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) =>
text
.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
new Setting(containerEl)
.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) =>
text
.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)
.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) =>
toggle
.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)
.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) =>
toggle
.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)
.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) =>
toggle
.setValue(this.plugin.settings.autoStartOnUnresolvedClick)
@ -239,7 +311,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Bypass modifier (Reading View)
new Setting(containerEl)
.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) =>
dropdown
.addOption("Alt", "Alt")
@ -258,7 +332,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Editor follow modifier (Live Preview/Source)
new Setting(containerEl)
.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) =>
dropdown
.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
new Setting(containerEl)
.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) =>
toggle
.setValue(this.plugin.settings.waitForFirstModifyAfterCreate)
@ -290,7 +377,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Modify timeout
new Setting(containerEl)
.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) =>
text
.setPlaceholder("1200")
@ -304,23 +393,21 @@ export class MindnetSettingTab extends PluginSettingTab {
})
);
// Debug logging
new Setting(containerEl)
.setName("Debug logging")
.setDesc("Enable debug logging for unresolved link handling")
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.debugLogging)
.onChange(async (value) => {
this.plugin.settings.debugLogging = value;
await this.plugin.saveSettings();
})
);
// ============================================
// 6. Note Adoption
// ============================================
containerEl.createEl("h3", { text: "🔄 Note Adoption" });
containerEl.createEl("p", {
text: "Einstellungen für die automatische Übernahme neu erstellter Notizen im Editor.",
cls: "setting-item-description",
});
// Adopt new notes in editor
new Setting(containerEl)
.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) =>
toggle
.setValue(this.plugin.settings.adoptNewNotesInEditor)
@ -333,7 +420,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Adopt max chars
new Setting(containerEl)
.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) =>
text
.setPlaceholder("200")
@ -350,7 +439,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Adopt confirm mode
new Setting(containerEl)
.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) =>
dropdown
.addOption("always", "Always ask")
@ -368,7 +459,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// High confidence window
new Setting(containerEl)
.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) =>
text
.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
new Setting(containerEl)
.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) =>
text
.setPlaceholder("abstract")
@ -402,7 +503,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Wrapper title
new Setting(containerEl)
.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) =>
text
.setPlaceholder("🕸️ Semantic Mapping")
@ -416,7 +519,9 @@ export class MindnetSettingTab extends PluginSettingTab {
// Wrapper folded
new Setting(containerEl)
.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) =>
toggle
.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
new Setting(containerEl)
.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) =>
dropdown
.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
new Setting(containerEl)
.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) =>
toggle
.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)
.setName("Default notes folder")
.setDesc("Default folder for new notes (vault-relative path, empty for root). Profile defaults take precedence.")
.addText((text) =>
text
.setPlaceholder("")
.setValue(this.plugin.settings.defaultNotesFolder)
.setName("Debug logging")
.setDesc(
"Aktiviert ausführliches Debug-Logging für das Unresolved-Link-Handling. Logs erscheinen in der Browser-Konsole (F12). Nützlich für die Fehlersuche."
)
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.debugLogging)
.onChange(async (value) => {
this.plugin.settings.defaultNotesFolder = value || "";
this.plugin.settings.debugLogging = value;
await this.plugin.saveSettings();
})
);