### Install Dependencies Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/00-START-HERE.md Installs all necessary project dependencies. Run this before other development commands. ```bash npm install ``` -------------------------------- ### Manual Plugin Installation for Testing Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/AGENTS.md Instructions for manually installing a plugin for local testing by copying files to the Obsidian plugins directory. ```bash /.obsidian/plugins// ``` -------------------------------- ### Example: Accessing and Updating Plugin Settings Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/types.md Demonstrates how to read, update, and save plugin settings. Includes examples for direct access and updating within a settings tab UI. ```typescript // Access the setting console.log(plugin.settings.mySetting); // 'default' initially // Update the setting plugin.settings.mySetting = 'new value'; await plugin.saveSettings(); // In settings tab new Setting(containerEl) .addText((text) => text .setValue(this.plugin.settings.mySetting) .onChange(async (value) => { this.plugin.settings.mySetting = value; await this.plugin.saveSettings(); }) ); ``` -------------------------------- ### Plugin Version Examples Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md Examples of semantic versioning for the plugin. Follows MAJOR.MINOR.PATCH format. ```json "version": "1.0.0" ``` ```json "version": "1.2.3" ``` ```json "version": "2.0.0" ``` -------------------------------- ### Modal Lifecycle Methods for Setup and Cleanup Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/EVENTS.md Implement `onOpen` for setup logic when a modal is displayed and `onClose` for cleanup logic when it's dismissed. This pattern ensures resources are managed correctly during the modal's lifetime. ```typescript class SampleModal extends Modal { onOpen() { // Setup when opened } onClose() { // Cleanup when closed } } ``` -------------------------------- ### Simple Command Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/types.md Example of a simple command that does not require editor access. This command opens a modal when executed. ```typescript this.addCommand({ id: 'open-modal-simple', name: 'Open modal (simple)', callback: () => { new SampleModal(this.app).open(); } }); ``` -------------------------------- ### Sample Plugin Manifest Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/configuration.md A basic example of a plugin manifest file (manifest.json) with essential fields. ```json { "id": "sample-plugin", "name": "Sample Plugin", "version": "1.0.0", "minAppVersion": "1.0.0", "description": "Demonstrates some of the capabilities of the Obsidian API.", "author": "Obsidian", "authorUrl": "https://obsidian.md", "fundingUrl": "https://obsidian.md/pricing", "isDesktopOnly": false } ``` -------------------------------- ### Plugin Funding URL Example (Multiple) Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md An object mapping funding platform names to their respective URLs. ```json "fundingUrl": { "Buy Me a Coffee": "https://buymeacoffee.com", "GitHub Sponsor": "https://github.com/sponsors/username", "Patreon": "https://www.patreon.com/username" } ``` -------------------------------- ### Registering a SampleSettingTab Instance Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplesettingtab.md Example of how to create and register an instance of SampleSettingTab with the Obsidian application. ```typescript // Create and register a settings tab const settingTab = new SampleSettingTab(this.app, this); this.addSettingTab(settingTab); ``` -------------------------------- ### saveSettings() Method Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/myplugin.md Provides an example of updating a plugin setting and then persisting it using saveSettings(). This ensures settings are saved to Obsidian's plugin data storage. ```typescript // Update a setting and save plugin.settings.mySetting = 'new value'; await plugin.saveSettings(); // Settings are now persisted and will be restored on plugin reload ``` -------------------------------- ### Desktop-Only Plugin Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md A boolean indicating if the plugin should only load on desktop versions of Obsidian. ```json "isDesktopOnly": true ``` -------------------------------- ### versions.json for releasing plugins Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/configuration.md Example of `versions.json` showing multiple plugin versions and their corresponding minimum Obsidian version requirements. ```json { "1.0.0": "1.0.0", "1.1.0": "1.0.5", "2.0.0": "1.5.0" } ``` -------------------------------- ### Plugin Funding URL Example (Single) Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md A single URL for donation or funding links for the plugin. ```json "fundingUrl": "https://buymeacoffee.com" ``` -------------------------------- ### Minimum App Version Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md Specifies the minimum Obsidian version required for the plugin to function correctly. ```json "minAppVersion": "1.0.0" ``` -------------------------------- ### Interval Callback Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/types.md Example of registering an interval timer using `registerInterval`. This logs a message to the console every 5 minutes. ```typescript this.registerInterval( window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000) ); ``` -------------------------------- ### Manual Plugin Installation Directory Structure Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/configuration.md Copy the built plugin files (main.js, manifest.json, styles.css) to this directory within your Obsidian vault for manual installation. ```text VaultFolder/.obsidian/plugins/sample-plugin/ ├── main.js ├── manifest.json └── styles.css ``` -------------------------------- ### Editor Command Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/types.md Example of a command that operates on the active editor. This command replaces the selected text in the editor. ```typescript this.addCommand({ id: 'replace-selected', name: 'Replace selected content', editorCallback: ( editor: Editor, _ctx: MarkdownView | MarkdownFileInfo, ) => { editor.replaceSelection('Sample editor command'); } }); ``` -------------------------------- ### Plugin Description Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md A short description of the plugin's functionality, displayed in plugin listings. ```json "description": "Demonstrates some of the capabilities of the Obsidian API." ``` -------------------------------- ### Add Version Entry to versions.json Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md Example of adding a new version entry to `versions.json` after updating `manifest.json` and `minAppVersion`. ```bash # After updating manifest.json version to 1.1.0 # and minAppVersion to 1.0.5 # Add to versions.json { "1.0.0": "1.0.0", "1.1.0": "1.0.5" # <- Add this line } # Commit and tag git add manifest.json versions.json git commit -m "Release v1.1.0" git tag 1.1.0 git push origin main --tags ``` -------------------------------- ### Plugin Author Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md The name of the plugin author or development team. ```json "author": "Obsidian" ``` -------------------------------- ### Check Callback Command Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/types.md Example of a conditional command that checks for specific conditions before execution. This command opens a modal only if an active Markdown view is present. ```typescript this.addCommand({ id: 'open-modal-complex', name: 'Open modal (complex)', checkCallback: (checking: boolean) => { const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView); if (markdownView) { if (!checking) { new SampleModal(this.app).open(); } return true; } return false; } }); ``` -------------------------------- ### onload() Method Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/myplugin.md Illustrates how to manually trigger the onload() method for testing or specific initialization scenarios. This method is typically called automatically by Obsidian. ```typescript // The onload method is called automatically by Obsidian // No explicit call is needed // To listen for when the plugin loads: const myPlugin = new MyPlugin(); await myPlugin.loadManifest(); // Load manifest first await myPlugin.load(); // This calls onload() internally ``` -------------------------------- ### loadSettings() Method Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/myplugin.md Demonstrates calling loadSettings() to populate plugin settings, either from saved data or defaults. This is typically invoked automatically during plugin initialization. ```typescript // Called automatically in onload() const plugin = new MyPlugin(); await plugin.loadSettings(); // plugin.settings is now populated with saved values or defaults console.log(plugin.settings.mySetting); // 'default' if no prior save ``` -------------------------------- ### DOM Event Handler Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/types.md Example of registering a DOM event listener for clicks on the active document. A notice is shown when a click occurs. ```typescript this.registerDomEvent(activeDocument, 'click', (_evt: MouseEvent) => { new Notice('Click'); }); ``` -------------------------------- ### Plugin Name Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md The human-readable name of the plugin, displayed in various Obsidian interfaces. ```json "name": "Sample Plugin" ``` -------------------------------- ### Example Settings Data Structure Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/SETTINGS.md Illustrates the structure of the data.json file used for storing plugin settings within an Obsidian vault. Settings persist across reloads and restarts. ```json { "mySetting": "custom-value" } ``` -------------------------------- ### Settings State Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/ARCHITECTURE.md Illustrates a simple, flat settings state structure with basic value types. This state is designed for straightforward data representation without complex nesting. ```typescript this.settings = { mySetting: 'value' // Single field } ``` -------------------------------- ### Plugin Author URL Examples Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md A URL for the plugin author's website, GitHub profile, or contact page. ```json "authorUrl": "https://obsidian.md" ``` ```json "authorUrl": "https://github.com/username" ``` ```json "authorUrl": "https://mywebsite.com" ``` -------------------------------- ### Plugin ID Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md The unique identifier for the plugin. Must be lowercase alphanumeric and hyphens. ```json "id": "sample-plugin" ``` -------------------------------- ### Full Featured Plugin Manifest Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md An example of a comprehensive manifest.json file for an Obsidian plugin, including optional fields like description, author, authorUrl, fundingUrl, and isDesktopOnly. ```json { "id": "advanced-plugin", "name": "Advanced Plugin", "version": "2.5.3", "minAppVersion": "1.4.0", "description": "An advanced plugin with many features.", "author": "Developer Name", "authorUrl": "https://github.com/developer", "fundingUrl": { "Buy Me a Coffee": "https://buymeacoffee.com/developer", "GitHub Sponsor": "https://github.com/sponsors/developer" }, "isDesktopOnly": false } ``` -------------------------------- ### Watch Mode Compilation Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/00-START-HERE.md Starts a development server that automatically recompiles code on changes. Useful for rapid development. ```bash npm run dev ``` -------------------------------- ### Persist Plugin Settings Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/AGENTS.md This example demonstrates how to load and save plugin settings using `this.loadData()` and `this.saveData()`. It initializes settings with defaults and merges loaded data. ```typescript interface MySettings { enabled: boolean } const DEFAULT_SETTINGS: MySettings = { enabled: true }; async onload() { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData() as Partial); await this.saveData(this.settings); } ``` -------------------------------- ### onunload() Method Example Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/myplugin.md Shows the onunload() method, which is called automatically by Obsidian when the plugin is disabled. Cleanup is generally handled by the base Plugin class. ```typescript // Cleanup handled automatically by Obsidian plugin system // onunload() is called internally when plugin is disabled ``` -------------------------------- ### Create and Open a SampleModal Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplemodal.md Demonstrates how to instantiate and display a SampleModal. The onOpen method is automatically called when .open() is invoked. ```typescript // Create and open a modal const modal = new SampleModal(this.app); modal.open(); ``` ```typescript // The onOpen method is called automatically when modal.open() is invoked const modal = new SampleModal(this.app); modal.open(); // This triggers onOpen() // The modal now displays "Woah!" as text ``` ```typescript // The onClose method is called automatically when the modal is closed // This can happen when: // - User clicks outside the modal // - User presses Escape key // - close() method is called programmatically const modal = new SampleModal(this.app); modal.open(); // ... user closes modal or modal.close() is called // onClose() is automatically invoked ``` -------------------------------- ### Open SampleModal from Command Callback Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplemodal.md Demonstrates how to open a SampleModal when a specific command is executed. ```typescript // In a command callback this.addCommand({ id: 'open-modal-simple', name: 'Open modal (simple)', callback: () => { new SampleModal(this.app).open(); } }); ``` -------------------------------- ### Basic Modal Creation and Display Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplemodal.md Shows the fundamental way to create and open a SampleModal instance. ```typescript // Basic modal creation and display const modal = new SampleModal(this.app); modal.open(); ``` -------------------------------- ### SampleSettingTab display() Method Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplesettingtab.md Renders the settings UI in the settings panel. This method is called by Obsidian and handles the creation of UI elements for plugin configuration. ```APIDOC ## Method display() ### Description Renders the settings UI in the settings panel. This method is called by Obsidian when the settings tab is displayed. It creates the UI elements for plugin configuration, including text inputs and toggles, and handles saving changes. ### Parameters None ### Return Value `void` ### Example ```typescript // The display method is called automatically by Obsidian // when the user opens the plugin's settings tab. // To manually trigger a refresh (rare): const settingTab = new SampleSettingTab(this.app, this.plugin); settingTab.display(); // Re-renders the UI // Extending to add more settings: display(): void { const { containerEl } = this; containerEl.empty(); new Setting(containerEl) .setName('Setting 1') .setDesc('First setting') .addText((text) => text .setPlaceholder('Enter value') .setValue(this.plugin.settings.mySetting) .onChange(async (value) => { this.plugin.settings.mySetting = value; await this.plugin.saveSettings(); }) ); new Setting(containerEl) .setName('Setting 2') .setDesc('Second setting') .addToggle((toggle) => toggle .setValue(false) .onChange(async (value) => { // Handle second setting await this.plugin.saveSettings(); }) ); } ``` ``` -------------------------------- ### SampleModal Constructor Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplemodal.md Initializes a SampleModal instance. The `app` parameter must be passed to the Modal parent constructor. ```APIDOC ## Constructor ```typescript constructor(app: App) ``` ### Description Initializes a SampleModal instance. The `app` parameter must be passed to the Modal parent constructor. ### Parameters - **app** (App) - Required - The Obsidian App instance, used to construct the Modal ### Example ```typescript // Create and open a modal const modal = new SampleModal(this.app); modal.open(); ``` ``` -------------------------------- ### Plugin Load Timing Flowchart Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/EVENTS.md Illustrates the sequence of events from Obsidian startup to a plugin being ready for use. ```text Obsidian starts ↓ User enables plugin in settings ↓ Plugin manifest loaded ↓ Plugin class instantiated ↓ onload() called ↓ UI elements registered ↓ Commands available ↓ Events listening ↓ Plugin ready ``` -------------------------------- ### SampleSettingTab display() Method Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplesettingtab.md Renders the settings UI for the plugin. This method is automatically called by Obsidian when the settings tab is opened. ```typescript display(): void ``` -------------------------------- ### Settings Data Flow: Load Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/ARCHITECTURE.md Illustrates the process of loading plugin settings, merging default settings with data loaded from disk. ```text Obsidian Start │ ▼ loadSettings() │ ├─ loadData() ──────────────────── Load from disk │ └─> data.json │ ├─ Object.assign() │ ├─ {} (empty) │ ├─ DEFAULT_SETTINGS │ └─ loaded data │ ▼ this.settings = merged result ``` -------------------------------- ### SampleSettingTab Constructor Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplesettingtab.md Initializes a SampleSettingTab instance. It calls the parent PluginSettingTab constructor and stores the plugin reference. ```APIDOC ## Constructor SampleSettingTab ### Description Initializes a SampleSettingTab instance. Calls the parent PluginSettingTab constructor with `app` and `plugin` parameters, then stores the plugin reference for use in the `display()` method. ### Parameters #### Parameters - **app** (App) - Required - The Obsidian App instance - **plugin** (MyPlugin) - Required - The plugin instance that owns this settings tab ### Example ```typescript // Create and register a settings tab const settingTab = new SampleSettingTab(this.app, this); this.addSettingTab(settingTab); ``` ``` -------------------------------- ### Provide Sensible Default Settings Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/SETTINGS.md Initialize settings with sensible defaults that match their expected usage. Avoid undefined or null defaults for properties that require specific types. ```typescript // ✅ Good: defaults match expected usage export const DEFAULT_SETTINGS: MyPluginSettings = { name: '', count: 0, enabled: false, }; // ❌ Bad: defaults are undefined or inconsistent export const DEFAULT_SETTINGS: MyPluginSettings = { name: undefined, count: null, enabled: undefined, }; ``` -------------------------------- ### Importing Plugin Components Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MODULES.md Demonstrates how to import the main plugin class and settings components from the compiled JavaScript output of the Obsidian Sample Plugin. ```typescript import MyPlugin from './obsidian-sample-plugin/main.js'; import { MyPluginSettings, DEFAULT_SETTINGS, SampleSettingTab } from './obsidian-sample-plugin/main.js'; ``` -------------------------------- ### Build Obsidian Plugin for Release Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/index.md Use these commands to create a production build, version the plugin, and prepare it for release. Ensure you commit and tag the release before pushing. ```bash npm run build # Production build npm version patch # Bump version git add manifest.json versions.json main.js git commit -m "Release v1.0.1" git tag 1.0.1 git push origin main --tags ``` -------------------------------- ### loadSettings() Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/myplugin.md Loads plugin settings from persistent storage and merges with defaults. ```APIDOC ## loadSettings() ### Description Loads plugin settings from persistent storage and merges with defaults. ### Method `async loadSettings(): Promise` ### Parameters None ### Return Value `Promise` ### Description Retrieves the settings object from Obsidian's plugin data storage. Uses `Object.assign()` to merge saved settings with `DEFAULT_SETTINGS`, ensuring any missing settings use their default values. Stores the result in the `settings` property. ### Example ```typescript // Called automatically in onload() const plugin = new MyPlugin(); await plugin.loadSettings(); // plugin.settings is now populated with saved values or defaults console.log(plugin.settings.mySetting); // 'default' if no prior save ``` ### Throws/Rejects Rejects if data storage access fails ``` -------------------------------- ### Desktop-Only Plugin Manifest Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md A manifest.json example for an Obsidian plugin that is restricted to desktop environments, indicated by the 'isDesktopOnly' field set to true. ```json { "id": "desktop-plugin", "name": "Desktop Only Plugin", "version": "1.0.0", "minAppVersion": "1.0.0", "description": "This plugin only works on desktop.", "isDesktopOnly": true } ``` -------------------------------- ### SampleModal Constructor Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplemodal.md Initializes a SampleModal instance. The 'app' parameter is required and passed to the parent Modal constructor. ```typescript constructor(app: App) ``` -------------------------------- ### Empty OnUnload for Automatic Cleanup Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/ARCHITECTURE.md An example of an empty `onunload()` method, signifying that all necessary cleanup is handled automatically by the Plugin base class. No manual resource management is required. ```typescript onunload() {} // All cleanup automatic ``` -------------------------------- ### Run Production Build Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/README.md Executes a production build of the plugin. This is a single pass that includes minification and type checking. ```bash npm run build # Single pass, minified # Type checking included # Output: main.js ``` -------------------------------- ### Extend Default Settings Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/SETTINGS.md Adds default values for newly introduced settings fields. This ensures new settings have a defined starting point when the plugin is first used or reset. ```typescript export const DEFAULT_SETTINGS: MyPluginSettings = { mySetting: 'default', newBooleanSetting: false, newNumberSetting: 0, newArraySetting: [], }; ``` -------------------------------- ### Command Callback Implementation Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/COMMANDS.md The callback function for the 'open-modal-simple' command. It instantiates and opens a SampleModal. ```typescript callback: () => { new SampleModal(this.app).open(); } ``` -------------------------------- ### Build Plugin Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md Build the plugin using the npm script. This is a required step before committing changes for release. ```bash npm run build ``` -------------------------------- ### Register DOM Event Listeners Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/EVENTS.md Provides examples of registering various DOM event listeners like click, keydown, scroll, and focus. These listeners are automatically unregistered on plugin disable. ```typescript // Click event this.registerDomEvent(activeDocument, 'click', (evt: MouseEvent) => { console.log('Clicked at', evt.pageX, evt.pageY); }); ``` ```typescript // Keyboard event this.registerDomEvent(activeDocument, 'keydown', (evt: KeyboardEvent) => { if (evt.key === 'Enter') { console.log('Enter pressed'); } }); ``` ```typescript // Scroll event this.registerDomEvent(activeDocument, 'scroll', (evt: Event) => { console.log('Scrolled'); }); ``` ```typescript // Focus event this.registerDomEvent(activeDocument, 'focus', (evt: FocusEvent) => { console.log('Window focused'); }); ``` -------------------------------- ### SampleSettingTab Display Method Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/SETTINGS.md Renders the settings UI for the plugin. It creates a text input field for a secret setting, updates the plugin's settings on change, and persists them. ```typescript display(): void { const { containerEl } = this; containerEl.empty(); new Setting(containerEl) .setName('Settings #1') .setDesc("It's a secret") .addText((text) => text .setPlaceholder('Enter your secret') .setValue(this.plugin.settings.mySetting) .onChange(async (value) => { this.plugin.settings.mySetting = value; await this.plugin.saveSettings(); })); } ``` -------------------------------- ### Settings Persistence Flowchart Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/EVENTS.md Outlines the process of saving and loading plugin settings, ensuring data is preserved across reloads. ```text User changes setting ↓ onChange triggered ↓ saveSettings() ↓ Data written to Obsidian vault ↓ On plugin reload, loadSettings() retrieves saved data ↓ Default values merged with saved values ``` -------------------------------- ### Plugin Lifecycle Management Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/ARCHITECTURE.md Illustrates the initialization (onload) and cleanup (onunload) phases of a plugin. The base class handles automatic cleanup of registered listeners and timers. ```text onload() ─────────────────────────────► Setup Phase ├─ loadSettings() Load config ├─ addRibbonIcon() Register UI ├─ addCommand() Register commands ├─ registerDomEvent() Register listeners └─ registerInterval() Start timers │ ▼ onunload() ───────────────────────► Cleanup Phase (automatic cleanup by base class) ``` -------------------------------- ### Command Execution Flow: Simple Command Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/ARCHITECTURE.md Traces the execution path for a simple command, from palette selection to callback invocation. ```text User opens Command Palette │ ▼ Obsidian lists all commands │ ▼ User selects "Open modal (simple)" │ ▼ Obsidian calls callback() │ ├─ new SampleModal(this.app) ├─ .open() │ ▼ Modal appears ``` -------------------------------- ### Module Dependencies Structure Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/README.md Shows the import relationships between the main plugin file and its settings module. ```text main.ts (entry point) │ ├─ Imports from obsidian │ ├─ Plugin (base class) │ ├─ Modal (base class) │ ├─ Editor, MarkdownView │ ├─ Notice, App │ └─ Other UI components │ └─ Imports from settings.ts ├─ MyPluginSettings (interface) ├─ DEFAULT_SETTINGS (constant) └─ SampleSettingTab (class) settings.ts │ └─ Imports from main.ts └─ MyPlugin (for type annotation) ``` -------------------------------- ### SampleSettingTab Constructor Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplesettingtab.md Initializes a SampleSettingTab instance. It calls the parent constructor and stores the plugin reference. ```typescript constructor(app: App, plugin: MyPlugin) ``` -------------------------------- ### Build Scripts for Plugin Development Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/README.md Provides common npm scripts for development, building, linting, and version management. ```bash npm run dev # Watch mode compilation npm run build # Production build (minified) npm run lint # ESLint static analysis npm version # Auto version bump ``` -------------------------------- ### Loading Plugin Settings Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/configuration.md Code snippet demonstrating how to load plugin settings, merging saved data with default settings. ```typescript this.settings = Object.assign( {}, DEFAULT_SETTINGS, (await this.loadData()) as Partial, ); ``` -------------------------------- ### Implement Plugin Initialization with onload() Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/EVENTS.md The `onload()` method is called once when the plugin is enabled. Use it to load settings, register UI elements, commands, event listeners, and intervals. ```typescript async onload() { await this.loadSettings(); this.addRibbonIcon('dice', 'Sample', (_evt: MouseEvent) => { new Notice('This is a notice!'); }); // More initialization... } ``` -------------------------------- ### SampleSettingTab Class Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MODULES.md Represents the UI tab for managing plugin settings. It extends Obsidian's PluginSettingTab and provides methods to display the settings. ```APIDOC ## SampleSettingTab ### Description Class for rendering the plugin's settings UI. ### Base Class PluginSettingTab ### Properties - **plugin** (MyPlugin) - Public - Reference to plugin instance ### Methods - **constructor(app: App, plugin: MyPlugin)**: Initialize settings tab - **display(): void**: Render settings UI ``` -------------------------------- ### Main Plugin Entry Point Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/README.md Defines the main `MyPlugin` class extending Obsidian's `Plugin`. Includes lifecycle methods like `onload`, `onunload`, `loadSettings`, and `saveSettings`. ```typescript export default class MyPlugin extends Plugin { async onload(): Promise onunload(): void async loadSettings(): Promise async saveSettings(): Promise } ``` -------------------------------- ### onload() Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/myplugin.md Called when the plugin is loaded. Initializes all plugin features, UI elements, commands, and event listeners. ```APIDOC ## onload() ### Description Called when the plugin is loaded. Initializes all plugin features, UI elements, commands, and event listeners. ### Method `async onload(): Promise` ### Parameters None ### Return Value `Promise` ### Description This lifecycle method executes once when the plugin is enabled. It performs the following: - Loads plugin settings from persistent storage via `loadSettings()` - Adds a ribbon icon ("dice") that displays a Notice when clicked - Adds a status bar item showing "Status bar text" - Registers three commands: - `open-modal-simple`: Opens a simple modal - `replace-selected`: Editor command that replaces selected content - `open-modal-complex`: Opens a modal only when a Markdown view is active - Registers a global DOM click event listener that shows a Notice for every click - Registers a global interval that logs to console every 5 minutes ### Example ```typescript // The onload method is called automatically by Obsidian // No explicit call is needed // To listen for when the plugin loads: const myPlugin = new MyPlugin(); await myPlugin.loadManifest(); // Load manifest first await myPlugin.load(); // This calls onload() internally ``` ### Throws/Rejects None ``` -------------------------------- ### Run Development Build Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/README.md Executes a development build of the plugin. This command runs in watch mode, compiling code automatically on file changes. ```bash npm run dev # Watch mode, compiles on file change # Output: main.js ``` -------------------------------- ### Obsidian Sample Plugin File Structure Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/README.md Overview of the directory structure for the Obsidian Sample Plugin project. This includes the location of core source files, metadata, and configuration files. ```tree obsidian-sample-plugin/ ├── src/ │ ├── main.ts # Plugin core, modal, lifecycle │ └── settings.ts # Settings interface, UI, defaults ├── manifest.json # Plugin metadata ├── package.json # Build configuration ├── tsconfig.json # TypeScript configuration └── versions.json # Version compatibility map ``` -------------------------------- ### Plugin Lifecycle Flow Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/README.md Illustrates the sequence of events during a plugin's lifecycle, from loading to unloading. ```text Obsidian Start ↓ Plugin enabled by user ↓ onload() ────────────────────────── Setup phase ├─ loadSettings() ├─ addRibbonIcon() ├─ addStatusBarItem() ├─ addCommand() × 3 ├─ addSettingTab() ├─ registerDomEvent() └─ registerInterval() ↓ Plugin active ──────────────────── Ready state ├─ Commands available ├─ Events firing ├─ Settings editable └─ UI responsive ↓ Plugin disabled by user ↓ onunload() ─────────────────────── Cleanup phase └─ (automatic cleanup) ↓ Resources freed ``` -------------------------------- ### Open SampleModal with Conditional Logic Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplemodal.md Illustrates opening a SampleModal only if a MarkdownView is currently active, using checkCallback for conditional command execution. ```typescript // With conditional logic this.addCommand({ id: 'open-modal-complex', name: 'Open modal (complex)', checkCallback: (checking: boolean) => { const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView); if (markdownView) { if (!checking) { new SampleModal(this.app).open(); } return true; } return false; } }); ``` -------------------------------- ### Add Entry to versions.json Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/configuration.md Manually add a new version entry to the versions.json file. ```json { "1.0.0": "1.0.0", "1.1.0": "1.0.0" } ``` -------------------------------- ### Manually Triggering display() and Extending Settings UI Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplesettingtab.md Demonstrates how to manually call the display method to re-render the UI and how to extend the display method to add multiple settings, including text inputs and toggles. ```typescript // The display method is called automatically by Obsidian // when the user opens the plugin's settings tab. // To manually trigger a refresh (rare): const settingTab = new SampleSettingTab(this.app, this.plugin); settingTab.display(); // Re-renders the UI // Extending to add more settings: display(): void { const { containerEl } = this; containerEl.empty(); new Setting(containerEl) .setName('Setting 1') .setDesc('First setting') .addText((text) => text .setPlaceholder('Enter value') .setValue(this.plugin.settings.mySetting) .onChange(async (value) => { this.plugin.settings.mySetting = value; await this.plugin.saveSettings(); }) ); new Setting(containerEl) .setName('Setting 2') .setDesc('Second setting') .addToggle((toggle) => toggle .setValue(false) .onChange(async (value) => { // Handle second setting await this.plugin.saveSettings(); }) ); } ``` -------------------------------- ### SampleModal onOpen Method Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplemodal.md This lifecycle method is invoked immediately after the modal DOM element is created and displayed. It uses the `contentEl` property inherited from Modal to set text content. ```APIDOC ## onOpen() ### Description Called when the modal is opened. Sets up the modal's content. This lifecycle method is invoked immediately after the modal DOM element is created and displayed. It uses the `contentEl` property inherited from Modal to set text content. In this example, it simply displays "Woah!" as the modal's content. ### Method Signature ```typescript onOpen(): void ``` ### Parameters None ### Return Value `void` ### Example ```typescript // The onOpen method is called automatically when modal.open() is invoked const modal = new SampleModal(this.app); modal.open(); // This triggers onOpen() // The modal now displays "Woah!" as text ``` ``` -------------------------------- ### Handle Version Migrations for New Settings Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/SETTINGS.md When adding new settings in updates, implement migration logic in `loadSettings()` to ensure backward compatibility. This involves checking for the existence of new fields and assigning default values if they are missing. ```typescript async loadSettings() { this.settings = Object.assign( {}, DEFAULT_SETTINGS, await this.loadData(), ); // Migration: add new field to old settings if (!('newField' in this.settings)) { this.settings.newField = 'default'; await this.saveSettings(); } } ``` -------------------------------- ### Accessing Plugin Instance in Command Callback Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/myplugin.md Demonstrates how to access and modify plugin settings from within a command's callback function. Ensure the plugin instance is correctly referenced. ```typescript // The plugin class is instantiated and managed by Obsidian // In the context of Obsidian plugin development: // Accessing the plugin from a command callback this.addCommand({ id: 'example-command', name: 'Example Command', callback: () => { // 'this' refers to the MyPlugin instance console.log(this.settings.mySetting); this.settings.mySetting = 'updated'; this.saveSettings(); } }); // Accessing the plugin instance in a settings tab constructor(app: App, plugin: MyPlugin) { super(app, plugin); this.plugin = plugin; // Store reference to plugin } ``` -------------------------------- ### Organize Plugin Code: Main Lifecycle File Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/AGENTS.md The main.ts file should be minimal, focusing only on plugin lifecycle events like initialization and command registration. It imports and delegates feature logic to separate modules. ```typescript import { Plugin } from 'obsidian'; import { MySettings, DEFAULT_SETTINGS } from './settings'; import { registerCommands } from './commands'; export default class MyPlugin extends Plugin { settings!: MySettings; aSync onload() { this.settings = Object.assign( {}, DEFAULT_SETTINGS, (await this.loadData()) as Partial, ); registerCommands(this); } } ``` -------------------------------- ### Command Execution Flow: Editor Command Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/ARCHITECTURE.md Illustrates the execution of a command that requires an active editor, passing the editor instance to the callback. ```text User opens Command Palette │ ▼ Obsidian filters: only when editor active │ ▼ User selects "Replace selected content" │ ▼ Obsidian calls editorCallback(editor, ctx) │ ├─ editor.replaceSelection() │ ▼ Text replaced ``` -------------------------------- ### Creating a Dropdown Setting Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/api-reference/samplesettingtab.md Add a dropdown menu for selecting from predefined options. Use addOption to define key-value pairs for the dropdown items and setValue for the default selection. ```typescript new Setting(containerEl) .setName('Dropdown Setting') .addDropdown((dropdown) => dropdown .addOption('option1', 'Option 1') .addOption('option2', 'Option 2') .setValue(currentValue) .onChange(async (value) => { settings.field = value; await saveSettings(); }) ); ``` -------------------------------- ### Simple Command Template Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/COMMANDS.md A basic template for registering a simple command that executes a callback function. This is suitable for actions that do not require editor access. ```typescript this.addCommand({ id: 'my-command-id', name: 'My Command Name', callback: () => { // Your action here new Notice('Command executed!'); }, }); ``` -------------------------------- ### MyPluginSettings Interface and Defaults Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/00-START-HERE.md Defines the interface for plugin settings, MyPluginSettings, and provides default values for these settings. This is useful for managing plugin configuration. ```typescript export interface MyPluginSettings { mySetting: string; } export const DEFAULT_SETTINGS: MyPluginSettings = { mySetting: 'default', }; ``` -------------------------------- ### Create and Use a Custom Modal Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/index.md Define and utilize a custom modal window for user input within the plugin. This includes creating a modal class with input fields and a submit button, and then opening it via a command. ```typescript class MyCustomModal extends Modal { constructor(app: App, private callback: (result: string) => void) { super(app); } onOpen() { const { contentEl } = this; contentEl.createEl('h2', { text: 'Enter value:' }); const input = contentEl.createEl('input'); input.type = 'text'; const btn = contentEl.createEl('button', { text: 'Submit' }); btn.onclick = () => { this.callback(input.value); this.close(); }; } onClose() { const { contentEl } = this; contentEl.empty(); } } // Use it this.addCommand({ id: 'open-custom-modal', name: 'Open Custom Modal', callback: () => { new MyCustomModal(this.app, (result) => { console.log('User entered:', result); }).open(); } }); ``` -------------------------------- ### Command Palette Strategies Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/ARCHITECTURE.md Defines different strategies for command registration in Obsidian, including simple callbacks, editor-specific callbacks, and conditional callbacks. ```typescript // Simple strategy: always available { id: 'open-modal-simple', callback: () => { /* execute */ } } ``` ```typescript // Editor strategy: requires editor { id: 'replace-selected', editorCallback: (editor) => { /* execute with editor */ } } ``` ```typescript // Conditional strategy: check preconditions { id: 'open-modal-complex', checkCallback: (checking) => { /* check or execute */ } } ``` -------------------------------- ### Commit Release Changes Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md Stage, commit, tag, and push all relevant files for the new release. This includes manifest, versions, package files, and the built main JavaScript file. ```bash git add manifest.json versions.json package.json main.js git commit -m "Release v1.1.0" git tag 1.1.0 git push origin main --tags ``` -------------------------------- ### Settings Data Flow: Restore on Reload Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/ARCHITECTURE.md Explains how previously saved settings are restored when the plugin reloads. ```text Plugin reload │ ▼ loadSettings() │ ├─ Load saved data from disk │ └─ Merge with defaults │ ▼ User sees previous values ``` -------------------------------- ### Settings Interface and Defaults Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/README.md Defines the `MyPluginSettings` interface and `DEFAULT_SETTINGS` constant for plugin configuration. Also includes the `SampleSettingTab` class for UI. ```typescript export interface MyPluginSettings { mySetting: string; } export const DEFAULT_SETTINGS: MyPluginSettings = { mySetting: 'default' }; export class SampleSettingTab extends PluginSettingTab { constructor(app: App, plugin: MyPlugin) display(): void } ``` -------------------------------- ### Automated Version Bumping with npm Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MANIFEST.md Use npm version commands to automatically update manifest.json, package.json, and create git tags. These commands also run the 'version' script and create a git commit. ```bash npm version patch # 1.0.0 → 1.0.1 (updates manifest.json and versions.json) npm version minor # 1.0.0 → 1.1.0 npm version major # 1.0.0 → 2.0.0 ``` -------------------------------- ### Manage Plugin Version Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/README.md Manages the version of the plugin using npm. This command automatically updates manifest.json, package.json, versions.json, and creates a Git tag. ```bash npm version patch # 1.0.0 → 1.0.1 npm version minor # 1.0.0 → 1.1.0 npm version major # 1.0.0 → 2.0.0 # Auto-updates: # - manifest.json # - package.json # - versions.json # - Git tag ``` -------------------------------- ### MyPluginSettings Interface Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/_autodocs/MODULES.md Defines the structure for user-configurable settings in the plugin. It includes a single field for a text setting. ```APIDOC ## MyPluginSettings ### Description Interface defining the structure for plugin settings. ### Fields - **mySetting** (string) - User-configurable text setting ``` -------------------------------- ### Basic Funding URL in manifest.json Source: https://github.com/obsidianmd/obsidian-sample-plugin/blob/master/README.md Include a single funding URL in your plugin's manifest.json file to allow users to support your work. ```json { "fundingUrl": "https://buymeacoffee.com" } ```