### Clone Repository and Install Dependencies Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CONTRIBUTING.md Clone the repository and install project dependencies using npm. ```bash git clone https://github.com/mnaoumov/obsidian-dev-utils.git cd obsidian-dev-utils npm install ``` -------------------------------- ### SettingEx Usage Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/10-setting-components.md Demonstrates how to initialize and use SettingEx to add an email input field to plugin settings. ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian'; new SettingEx(containerEl) .setName('Email') .setDesc('Your email address') .addEmail((email) => { email.setValue(settings.email) .onChange((value) => { settings.email = value; }); }); ``` -------------------------------- ### CommandHandlerComponent AddHandler Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Example demonstrating how to add command handlers to a CommandHandlerComponent within a plugin. ```typescript export class MyPlugin extends PluginBase { protected commandComponent: CommandHandlerComponent; constructor(app: App, manifest: PluginManifest) { super(app, manifest); this.commandComponent = this.addChild(new CommandHandlerComponent(this)); this.commandComponent.addHandler(new MyGlobalCommandHandler()); this.commandComponent.addHandler(new MyFileCommandHandler()); } } ``` -------------------------------- ### Reload Plugin Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/2-plugin-base.md Example demonstrating how to call the reloadPlugin function, typically within the plugin's own context. ```typescript await reloadPlugin(this); ``` -------------------------------- ### Install Obsidian Dev Utils Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/README.md Install the package using npm. This command adds the obsidian-dev-utils library to your project dependencies. ```bash npm install obsidian-dev-utils ``` -------------------------------- ### Plugin Event Usage Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/2-plugin-base.md Shows how to subscribe to plugin events like 'layoutReady' and 'load' using the on() method. ```typescript const plugin = new MyPlugin(app, manifest); plugin.on('layoutReady', async () => { console.log('Workspace layout is ready'); }); plugin.on('load', async () => { console.log('Plugin loaded'); }); ``` -------------------------------- ### Instantiating a Command Handler Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Example of creating an instance of a concrete CommandHandler subclass with required parameters. ```typescript const handler = new MyCommandHandler({ id: 'my-command', name: 'Do something', icon: 'checkmark' }); ``` -------------------------------- ### FolderCommandHandler Execute Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Example of a FolderCommandHandler subclass that creates a new note within a specified folder. ```typescript class CreateNoteInFolderHandler extends FolderCommandHandler { protected async execute(folder: TFolder): Promise { const filename = await prompt({ app: this.app, title: 'New note name' }); if (filename) { const path = `${folder.path}/${filename}.md`; await this.app.vault.create(path, ''); } } } ``` -------------------------------- ### Example: DateTransformer Usage Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/6-transformers.md Shows how to use the DateTransformer to transform a Date object into an ISO string. ```typescript const transformer = new DateTransformer(); const date = new Date('2024-01-15'); const iso = transformer.transformValue(date, 'date'); // '2024-01-15T00:00:00.000Z' ``` -------------------------------- ### Add Child Component Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/2-plugin-base.md Demonstrates how to add a custom component as a child of the PluginBase. ```typescript class MyPlugin extends PluginBase { constructor(app: App, manifest: PluginManifest) { super(app, manifest); const myComponent = this.addChild(new MyCustomComponent()); } } ``` -------------------------------- ### Basic Plugin Setup with PluginBase Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/2-plugin-base.md Demonstrates the basic structure for setting up an Obsidian plugin using the PluginBase class. Ensures all universal components are loaded and accessible. ```typescript import { PluginBase } from 'obsidian-dev-utils/obsidian/plugin'; import { App, PluginManifest } from 'obsidian'; export class MyPlugin extends PluginBase { public constructor(app: App, manifest: PluginManifest) { super(app, manifest); } public override async onload(): Promise { await super.onload(); // Plugin is now loaded with all universal components // Access components via protected properties } public override async onunload(): Promise { // Components automatically unload await super.onunload(); } } export default MyPlugin; ``` -------------------------------- ### Complete Settings Tab Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/10-setting-components.md Demonstrates creating a full settings tab with various input components like text, email, dropdown, and checkbox. Ensure you have imported SettingEx and PluginSettingsTab. ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian'; import { PluginSettingsTab } from 'obsidian'; class MySettingsTab extends PluginSettingsTab { async display(): Promise { const container = this.containerEl; container.empty(); new SettingEx(container) .setName('Username') .setDesc('Your account username') .addText((text) => { text.setValue(this.plugin.settings.username) .setPlaceholder('Enter username') .onChange(async (value) => { this.plugin.settings.username = value; await this.plugin.saveSettings(); }); }); new SettingEx(container) .setName('Email') .setDesc('Your email address') .addEmail((email) => { email.setValue(this.plugin.settings.email) .onChange(async (value) => { this.plugin.settings.email = value; await this.plugin.saveSettings(); }); }); new SettingEx(container) .setName('Theme') .setDesc('Choose your preferred theme') .addTypedDropdown((drop) => { drop.addOption('light', 'Light') .addOption('dark', 'Dark') .setValue(this.plugin.settings.theme) .onChange(async (value) => { this.plugin.settings.theme = value; await this.plugin.saveSettings(); }); }); new SettingEx(container) .setName('Enable notifications') .setDesc('Show desktop notifications') .addCheckbox((check) => { check.setValue(this.plugin.settings.notificationsEnabled) .onChange(async (value) => { this.plugin.settings.notificationsEnabled = value; await this.plugin.saveSettings(); }); }); } } ``` -------------------------------- ### Basic Obsidian Plugin Setup Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md A boilerplate for creating a new Obsidian plugin using PluginBase. Ensure to implement initialization in `onload` and cleanup in `onunload`. ```typescript import { PluginBase } from 'obsidian-dev-utils/obsidian/plugin'; import { App, PluginManifest } from 'obsidian'; export class MyPlugin extends PluginBase { constructor(app: App, manifest: PluginManifest) { super(app, manifest); } public override async onload(): Promise { await super.onload(); // Your initialization } public override async onunload(): Promise { // Your cleanup await super.onunload(); } } export default MyPlugin; ``` -------------------------------- ### TypeScript File Structure Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Illustrates the standard file structure for source files within the project, including JSDoc comments and import conventions. ```typescript /** * @file * * Brief description of module purpose. */ import type { SomeType } from './some-module.ts'; import { something } from './other-module.ts'; export function myFunction(param: Type): ReturnType { // ... } ``` -------------------------------- ### Simple Confirmation Modal Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/3-modals.md Example of using the confirm modal to get a boolean confirmation from the user before proceeding with an action. ```typescript if (await confirm({ app: this.app, message: 'Delete file?' })) { await deleteFile(); } ``` -------------------------------- ### FileCommandHandler Execute Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Example of a FileCommandHandler subclass that renames a file based on user input. ```typescript class RenameFileHandler extends FileCommandHandler { protected async execute(file: TFile): Promise { const newName = await prompt({ app: this.app, defaultValue: file.name }); if (newName) { await this.app.fileManager.renameFile(file, newName); } } } ``` -------------------------------- ### String Case Conversion Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/5-core-utilities.md Demonstrates common string case conversions like camelCase, snake_case, and kebab-case. Import specific functions from 'obsidian-dev-utils/string'. ```typescript import { toKebabCase, toCamelCase } from 'obsidian-dev-utils/string'; const name = 'my-variable-name'; console.log(toCamelCase(name)); // 'myVariableName' ``` -------------------------------- ### PasswordComponent Usage Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Shows how to implement a password input field using PasswordComponent. Examples include direct instantiation and usage via SettingEx. ```typescript import { PasswordComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/password-component'; const password = new PasswordComponent(containerEl); password.setValue('foo'); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addPassword((password) => { password.setValue('foo'); }); ``` -------------------------------- ### Example Usage of Promisable Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/8-types-reference.md Demonstrates how to use the Promisable type in a function signature. The function accepts a callback that returns a Promisable value. ```typescript function process(fn: (value: string) => Promisable) { const result = fn('test'); if (result instanceof Promise) { await result; } } ``` -------------------------------- ### Sequential Modals for Workflow Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/3-modals.md Illustrates chaining multiple modals (confirm and prompt) to guide the user through a multi-step process, such as creating a file. ```typescript const action = await confirm({ app: this.app, message: 'Create new file?' }); if (action) { const name = await prompt({ app: this.app, title: 'Filename', placeholder: 'notes' }); if (name) { await vault.create(`${name}.md`, ''); } } ``` -------------------------------- ### Example EditorCommandHandler Implementation Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Demonstrates a concrete implementation of EditorCommandHandler for converting selected text to uppercase. Includes overriding canExecute and execute methods. ```typescript class UppercaseCommandHandler extends EditorCommandHandler { constructor() { super({ id: 'uppercase', name: 'Convert to uppercase', icon: 'bold' }); } protected canExecute(editor: Editor): boolean { return editor.somethingSelected(); } protected execute(editor: Editor): void { const selected = editor.getSelection().toUpperCase(); editor.replaceSelection(selected); } } ``` -------------------------------- ### Example Usage of MaybeReturn Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/8-types-reference.md Shows an example of using MaybeReturn for a validator function type. The validator returns an error message string or nothing. ```typescript type Validator = (value: string) => MaybeReturn; // Returns error message or nothing ``` -------------------------------- ### TimeComponent Usage Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Demonstrates setting time values using TimeComponent, including importing moment.js for duration objects. Examples show direct and SettingEx usage. ```typescript import { moment } from 'obsidian'; import { TimeComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/time-component'; const time = new TimeComponent(containerEl); time.setValue(moment.duration({ hours: 12, minutes: 34 })); ``` ```typescript import { moment } from 'obsidian'; import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addTime((time) => { time.setValue(moment.duration({ hours: 12, minutes: 34 })); }); ``` -------------------------------- ### MultipleTextComponent Usage Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Illustrates the usage of MultipleTextComponent for managing multiple text inputs. Examples show direct instantiation and use with SettingEx. ```typescript import { MultipleTextComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/multiple-text-component'; const multipleText = new MultipleTextComponent(containerEl); multipleText.setValue(['foo', 'bar']); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addMultipleText((multipleText) => { multipleText.setValue(['foo', 'bar']); }); ``` -------------------------------- ### getStackTrace Function Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/9-errors-reference.md Illustrates capturing the current stack trace using getStackTrace, intended for use with CustomStackTraceError. ```typescript import { getStackTrace } from 'obsidian-dev-utils'; function captureContext() { const stackTrace = getStackTrace(1); return stackTrace; // Use in error handlers } ``` -------------------------------- ### Example Usage of GenericObject Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/8-types-reference.md Illustrates how to use the GenericObject type. This function takes an object of type T and returns it as a GenericObject. ```typescript import { GenericObject } from 'obsidian-dev-utils/type-guards'; function processObject(obj: T): GenericObject { return obj as GenericObject; } ``` -------------------------------- ### Wrap CLI Task with Build Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Example of wrapping a build script task using `wrapCliTask` from `obsidian-dev-utils`. This utility helps manage command-line script execution. ```typescript // scripts/build.ts import { wrapCliTask } from 'obsidian-dev-utils/script-utils/cli-utils'; import { build } from 'obsidian-dev-utils/script-utils/bundlers/esbuild'; await wrapCliTask(() => build()); ``` -------------------------------- ### Implementing execute for GlobalCommandHandler Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Example of implementing the abstract execute method in GlobalCommandHandler to perform the command's core logic, reading and logging the content of the active file. ```typescript protected async execute(): Promise { const file = this.app.workspace.getActiveFile(); if (file) { const content = await this.app.vault.read(file); console.log(content); } } ``` -------------------------------- ### TriStateCheckboxComponent Usage Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Shows how to use TriStateCheckboxComponent for three-state checkboxes (checked, unchecked, indeterminate). Examples cover direct instantiation and SettingEx. ```typescript import { TriStateCheckboxComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/tri-state-checkbox-component'; const triStateCheckbox = new TriStateCheckboxComponent(containerEl); triStateCheckbox.setValue(null); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addTriStateCheckbox((triStateCheckbox) => { triStateCheckbox.setValue(null); }); ``` -------------------------------- ### Example: GroupTransformer Usage Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/6-transformers.md Demonstrates using GroupTransformer to apply multiple transformers (Date, Set, Map) to an object with various data types. ```typescript const group = new GroupTransformer( new DateTransformer(), new SetTransformer(), new MapTransformer() ); const transformed = group.transformObjectRecursively({ dates: [new Date(), new Date()], tags: new Set(['a', 'b']), config: new Map([['key', 'value']]) }); ``` -------------------------------- ### Plugin with Composed Components Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Example of a plugin class extending PluginBase and composing opt-in components like settings and an email checker. Components are added as children for lifecycle management. ```typescript export class Plugin extends PluginBase { constructor(app: App, manifest: PluginManifest) { super(app, manifest); // Only compose what you need this.settings = this.addChild(new PluginSettings()); this.emailChecker = this.addChild(new EmailChecker(app, this.settings)); } } ``` -------------------------------- ### errorToString Function Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/9-errors-reference.md Shows how to convert an error object into a detailed string representation, including its cause chain, for logging purposes. ```typescript import { errorToString } from 'obsidian-dev-utils'; try { await operation(); } catch (e) { const errorStr = errorToString(e); logger.error(errorStr); } ``` -------------------------------- ### Re-export Commitlint Config Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Example of a configuration script that re-exports a shared commitlint configuration from `obsidian-dev-utils`. This is useful for maintaining consistent commit message rules. ```typescript // scripts/commitlint-config.ts import { obsidianDevUtilsConfig } from 'obsidian-dev-utils/script-utils/commitlint-config'; export const config = obsidianDevUtilsConfig; ``` -------------------------------- ### Registering Menu Event Handlers in onRegistered Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Example of using the menuEventRegistrar within the onRegistered lifecycle method to handle file-specific menu events. ```typescript public onRegistered(context: CommandHandlerRegistrationContext): void { context.menuEventRegistrar.registerFileMenu( this.id, (file) => this.execute(file) ); } ``` -------------------------------- ### Build Project Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CONTRIBUTING.md Run the build script to compile the project. ```bash npm run build ``` -------------------------------- ### Vitest Test Pattern Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md A standard Vitest test setup for a module, including imports and a describe block. Ensure Vitest is configured for aliasing the 'obsidian' module. ```typescript import { describe, expect, it, vi } from 'vitest'; import { myFunction } from './my-module.ts'; describe('MyModule', () => { it('should do something', () => { expect(myFunction(input)).toBe(expected); }); }); ``` -------------------------------- ### Initialize FileComponent Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Illustrates how to set up a FileComponent and handle file selection changes. Useful for allowing users to select files within settings. ```typescript import { FileComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/file-component'; const file = new FileComponent(containerEl); file.onChange((value) => console.log(value)); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addFile((file) => { file.onChange((value) => console.log(value)); }); ``` -------------------------------- ### Implementing canExecute for GlobalCommandHandler Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Example of overriding the protected canExecute method in GlobalCommandHandler to add a condition for command execution, checking if an active file exists. ```typescript protected canExecute(): boolean { return this.app.workspace.getActiveFile() !== null; } ``` -------------------------------- ### Alert Modal with Custom Button Text Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/3-modals.md Example of displaying an alert modal and overriding the default 'OK' button text with a custom string, demonstrating i18next text customization. ```typescript await alert({ app: this.app, message: 'Done', okButtonText: 'Understood' // Overrides i18n }); ``` -------------------------------- ### getValue Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/10-setting-components.md Common method to get the current value of a component. ```APIDOC ## getValue() ### Description Gets the component's current value. ### Method Signature ```typescript getValue(): T ``` ### Returns * `T` - The current value of the component. ``` -------------------------------- ### Import Main Entry Point Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md Import core utilities like unique, alert, and PluginBase from the main entry point of the library. ```typescript import { unique, alert, PluginBase } from 'obsidian-dev-utils'; ``` -------------------------------- ### Get Component Value Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/10-setting-components.md Retrieves the current value of a component. ```typescript getValue(): T ``` -------------------------------- ### Plugin Orchestration with Settings Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Demonstrates how a plugin orchestrates its settings, including creating settings instances and optionally defining a custom settings tab. ```typescript // Plugin.ts export class Plugin extends PluginBase { protected override createSettings(): PluginSettings { return new PluginSettings(); } // Only override if you need custom tab UI protected override createSettingsTab(): PluginSettingsTab | null { return new CustomTab(this.app, this.settings); } } ``` -------------------------------- ### Run Tests Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CONTRIBUTING.md Execute project tests and generate a coverage report. ```bash npm run test npm run test:coverage ``` -------------------------------- ### Import All Core Utilities Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/5-core-utilities.md Import all core utility functions from the main entry point of the library. ```typescript import { unique, assertNonNullable, noop } from 'obsidian-dev-utils'; ``` -------------------------------- ### Initialize CodeHighlighterComponent Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Shows how to set up a CodeHighlighterComponent with a specific language and code value. Ideal for displaying code snippets within settings. ```typescript import { CodeHighlighterComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/code-highlighter-component'; const codeHighlighter = new CodeHighlighterComponent(containerEl); codeHighlighter .setLanguage('javascript') .setValue(`function foo() { console.log('bar'); }`); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addCodeHighlighter((codeHighlighter) => { codeHighlighter .setLanguage('javascript') .setValue(`function foo() { console.log('bar'); }`); }); ``` -------------------------------- ### Get Transformer Method Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/6-transformers.md Retrieves a specific transformer instance by its unique identifier. Throws an error if the transformer is not found. ```typescript getTransformer(transformerId: string): Transformer ``` -------------------------------- ### Import Obsidian SettingEx Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md Import the SettingEx class for enhanced settings UI from the obsidian module. ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian'; ``` -------------------------------- ### Example: Transform Object Recursively Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/6-transformers.md Demonstrates how to use transformObjectRecursively with a DateTransformer to transform nested Date objects within an object. ```typescript const transformer = new DateTransformer(); const transformed = transformer.transformObjectRecursively({ name: 'Event', date: new Date('2024-01-01'), metadata: { created: new Date('2023-12-01') } }); ``` -------------------------------- ### printError Function Example Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/9-errors-reference.md Demonstrates using the printError function to log an error with its full stack trace and causes to the console. ```typescript import { printError } from 'obsidian-dev-utils'; try { await operation(); } catch (e) { printError(e); // Prints: "Error message\n at ...stack..." } ``` -------------------------------- ### Import Obsidian Modals Utilities Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md Import modal dialog functions like alert, confirm, and prompt from the obsidian/modals submodule. ```typescript import { alert, confirm, prompt } from 'obsidian-dev-utils/obsidian/modals'; ``` -------------------------------- ### Conditional Execution Command Handler Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Example of an EditorCommandHandler that only executes when text is selected in the editor. Uses a modal for item selection. ```typescript class InsertTemplateCommand extends EditorCommandHandler { protected canExecute(editor: Editor): boolean { // Only available when editor has selected text return editor.somethingSelected(); } protected async execute(editor: Editor): Promise { const template = await selectItem({ app: this.app, items: ['Template 1', 'Template 2'], itemToString: (item) => item }); if (template) { editor.replaceSelection(template); } } } ``` -------------------------------- ### Prompt for User Input Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md Get text input from the user with optional validation. Returns the input string or null if cancelled. ```typescript const name = await prompt({ app: this.app, title: 'Name', valueValidator: (v) => v ? null : 'Required' }); ``` -------------------------------- ### Initialize DateComponent Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Illustrates creating a DateComponent and setting an initial date value. Useful for date selection in plugin settings. ```typescript import { DateComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/date-component'; const date = new DateComponent(containerEl); date.setValue(new Date()); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addDate((date) => { date.setValue(new Date()); }); ``` -------------------------------- ### MultipleFileComponent Usage Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Shows how to use the MultipleFileComponent to handle multiple file selections. It can be initialized directly or through SettingEx. ```typescript import { MultipleFileComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/multiple-file-component'; const multipleFile = new MultipleFileComponent(containerEl); multipleFile.onChange((value) => console.log(value)); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addMultipleFile((multipleFile) => { multipleFile.onChange((value) => console.log(value)); }); ``` -------------------------------- ### Initialize MultipleDropdownComponent Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Shows how to set up a MultipleDropdownComponent with options and pre-selected values. Use this for multi-select dropdowns in settings. ```typescript import { MultipleDropdownComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/multiple-dropdown-component'; const multipleDropdown = new MultipleDropdownComponent(containerEl); multipleDropdown.addOptions({ Value1: 'Display 1', Value2: 'Display 2', Value3: 'Display 3', Value4: 'Display 4', Value5: 'Display 5' }); multipleDropdown.setValue(['Value2', 'Value3']); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addMultipleDropdown((multipleDropdown) => { multipleDropdown.addOptions({ Value1: 'Display 1', Value2: 'Display 2', Value3: 'Display 3', Value4: 'Display 4', Value5: 'Display 5' }); multipleDropdown.setValue(['Value2', 'Value3']); }); ``` -------------------------------- ### SilentError Example: Validation Error Handling Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/9-errors-reference.md Shows how to use SilentError to display validation errors to the user without logging them to the console. ```typescript import { SilentError } from 'obsidian-dev-utils'; async function validateAndSave(data: unknown) { if (!isValid(data)) { // User sees error message, console stays clean throw new SilentError('Invalid data format'); } await save(data); } ``` -------------------------------- ### Get Library Debugger Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/5-core-utilities.md Use `getLibDebugger` to obtain a debug function, optionally with a namespace. This helps in organizing and filtering debug logs. ```typescript function getLibDebugger(namespace?: string): debug.Debugger ``` ```typescript const debug = getLibDebugger('MyModule'); debug('Something happened', data); // Enable with: DEBUG=obsidian-dev-utils:MyModule ``` -------------------------------- ### Initialize DateTimeComponent Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Demonstrates how to initialize a DateTimeComponent and set a specific date and time. Suitable for precise date and time inputs. ```typescript import { DateTimeComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/date-time-component'; const dateTime = new DateTimeComponent(containerEl); dateTime.setValue(new Date()); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addDateTime((dateTime) => { dateTime.setValue(new Date()); }); ``` -------------------------------- ### NumberComponent Usage Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Demonstrates how to set numerical values using NumberComponent. Both direct instantiation and the SettingEx method are shown. ```typescript import { NumberComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/number-component'; const number = new NumberComponent(containerEl); number.setValue(42); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addNumber((number) => { number.setValue(42); }); ``` -------------------------------- ### CustomStackTraceError Example: Async Error Wrapping Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/9-errors-reference.md Demonstrates wrapping an asynchronous operation's error with CustomStackTraceError to preserve context and improve debugging. ```typescript import { CustomStackTraceError, getStackTrace } from 'obsidian-dev-utils'; async function executeWithContext() { const stackTrace = getStackTrace(1); try { await riskyOperation(); } catch (e) { throw new CustomStackTraceError( 'Operation failed', stackTrace, e ); } } ``` -------------------------------- ### Initialize MonthComponent Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Demonstrates creating a MonthComponent and setting a specific month and year. Suitable for month and year selection. ```typescript import { MonthComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/month-component'; const month = new MonthComponent(containerEl); month.setValue({ month: 4, year: 2025 }); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addMonth((month) => { month.setValue({ month: 4, year: 2025 }); }); ``` -------------------------------- ### Add UrlComponent Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Instantiate and configure a UrlComponent directly or via SettingEx. Use this for URL input fields. ```typescript import { UrlComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/url-component'; const url = new UrlComponent(containerEl); url.setValue('https://foo.com/'); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addUrl((dateTime) => { url.setValue('https://foo.com/'); }); ``` -------------------------------- ### Get Enum Keys Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/5-core-utilities.md Use `getEnumKeys` to retrieve all keys from a given enum object. This is useful for iterating over enum values or accessing their names. ```typescript function getEnumKeys(enumObj: Record): Array ``` ```typescript enum Color { Red = 'RED', Green = 'GREEN', Blue = 'BLUE' } const keys = getEnumKeys(Color); // ['Red', 'Green', 'Blue'] ``` -------------------------------- ### Get Unique Array Elements Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md Create a new array containing only the unique elements from the input array. Preserves the order of first appearance. ```typescript const unique_items = unique([1, 2, 2, 3]); ``` -------------------------------- ### Registering Multiple Commands in Plugin Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/4-command-handlers.md Demonstrates registering multiple command handlers within a plugin's constructor using CommandHandlerComponent. ```typescript class MyPlugin extends PluginBase { constructor(app: App, manifest: PluginManifest) { super(app, manifest); const commands = this.addChild(new CommandHandlerComponent(this)); commands.addHandler(new NewNoteCommand()); commands.addHandler(new DeleteNoteCommand()); commands.addHandler(new RenameNoteCommand()); } } ``` -------------------------------- ### Importing Prompt Function (Root Obsidian Namespace) Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/helper-functions.md Import the prompt function using the root 'obsidian' namespace. This imports all utilities under the obsidian module. ```typescript import { obsidian } from 'obsidian-dev-utils'; await obsidian.modal.prompt.prompt({ app, title: 'Enter your name' }); ``` -------------------------------- ### Import Obsidian PluginBase Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md Import the PluginBase class for creating Obsidian plugins from the obsidian/plugin submodule. ```typescript import { PluginBase } from 'obsidian-dev-utils/obsidian/plugin'; ``` -------------------------------- ### Get Next Tick Async Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/1-async-utilities.md Returns a promise that resolves on the next tick of the event loop. Useful for yielding control back to the event loop. ```typescript async function nextTickAsync(): Promise ``` -------------------------------- ### PluginBase Constructor Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/2-plugin-base.md Initializes the PluginBase with the Obsidian App instance and plugin manifest. ```typescript constructor(app: App, manifest: PluginManifest) ``` -------------------------------- ### Execute Tasks Sequentially Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md Runs an array of asynchronous tasks one after another, collecting their results. Ensures that each task completes before the next one starts. ```typescript const results = await promiseAllSequentially([ task1(), task2(), task3() ]); ``` -------------------------------- ### Initialize EmailComponent Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Shows the creation and value setting for an EmailComponent. Use this for email address inputs in your plugin settings. ```typescript import { EmailComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/email-component'; const email = new EmailComponent(containerEl); email.setValue('foo@bar.com'); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addEmail((email) => { email.setValue('foo@bar.com'); }); ``` -------------------------------- ### Run Test Suite Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/cli-commands.md Runs the test suite using Vitest. ```typescript import { test } from 'obsidian-dev-utils/script-utils/test-runners/vitest/vitest'; await test(); ``` -------------------------------- ### Build Production Version Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/cli-commands.md Compiles the production version of your plugin into the `dist/build` folder. ```typescript import { build } from 'obsidian-dev-utils/script-utils/bundlers/esbuild/obsidian-plugin-builder'; await build(); ``` -------------------------------- ### Get Plugin Abort Signal Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md Retrieve the abort signal associated with the plugin's lifecycle. This signal can be used to cancel ongoing operations when the plugin is unloaded. ```typescript const signal = this.abortSignalComponent.getAbortSignal(); while (!signal.aborted) { // Work } ``` -------------------------------- ### Using Plugin Events with PluginBase Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/2-plugin-base.md Illustrates how to subscribe to and handle plugin events within a class extending PluginBase. Events like 'layoutReady' and 'load' can be used to trigger actions. ```typescript class MyPlugin extends PluginBase { constructor(app: App, manifest: PluginManifest) { super(app, manifest); this.on('layoutReady', async () => { // Workspace layout is now ready }); this.on('load', async () => { // Plugin is loaded }); } } ``` -------------------------------- ### Importing Prompt Function (Obsidian Namespace) Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/helper-functions.md Import the prompt function through the 'obsidian' namespace. This imports all utilities under the obsidian module. ```typescript import { modal } from 'obsidian-dev-utils/obsidian'; await modal.prompt.prompt({ app, title: 'Enter your name' }); ``` -------------------------------- ### Creating Email Setting UI Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/0-index.md Illustrates how to create a custom email input field within the Obsidian settings UI using SettingEx. The onChange callback handles updates to the settings and saves them. ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian'; new SettingEx(containerEl) .setName('Email') .setDesc('Your email address') .addEmail((email) => { email.setValue(settings.email) .onChange((value) => { settings.email = value; saveSettings(); }); }); // Additional setting types: // .addText(), .addPassword(), .addNumber(), .addCheckbox() // .addDropdown(), .addDate(), .addTime(), .addFile() // .addMultipleText(), .addMultipleEmail(), and more ``` -------------------------------- ### promiseAllSequentially Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/1-async-utilities.md Executes an array of promises sequentially, ensuring that each promise completes before the next one starts. This is useful when the order of execution or the side effects of promises depend on each other. ```APIDOC ## promiseAllSequentially(promises) ### Description Executes promises sequentially. This is useful when the order of execution or the side effects of promises depend on each other. ### Method `async function` ### Parameters #### Path Parameters - **promises** (Promisable[]): Required - Array of promises to execute sequentially ### Returns `Promise` — Array of resolved values in order ### Request Example ```typescript const results = await promiseAllSequentially([ fetchUser(1), fetchUser(2), fetchUser(3) ]); ``` ``` -------------------------------- ### Build Static Assets Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/cli-commands.md Copies the `static` folder to the `dist` folder. ```typescript import { buildStatic } from 'obsidian-dev-utils/script-utils/build'; await buildStatic(); ``` -------------------------------- ### Skip Private Properties Transformer Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/6-transformers.md Use SkipPrivatePropertyTransformer to exclude properties starting with an underscore during object transformation. This is useful for preventing sensitive or internal properties from being serialized. ```typescript class SkipPrivatePropertyTransformer extends Transformer const transformer = new SkipPrivatePropertyTransformer(); const obj = { name: 'Public', _private: 'Hidden', __internal: 'Also hidden' }; const transformed = transformer.transformObjectRecursively(obj); // { name: 'Public' } ``` -------------------------------- ### Plugin Settings (Decorator Approach) Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Defines plugin settings using decorators for a declarative approach to configuration, including name and description for each setting. ```typescript // PluginSettings.ts export class PluginSettings extends PluginSettingsBase { @setting({ name: 'Auto-refresh interval', desc: 'Seconds between refreshes' }) public autoRefreshIntervalInSeconds = 10; @setting({ name: 'Should prompt for folder', desc: 'Prompt when creating notes' }) public shouldPromptForFolderLocation = false; } ``` -------------------------------- ### Custom Settings Tab UI Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Illustrates how to create a custom settings tab for plugins requiring specialized UI elements beyond standard fields. ```typescript // PluginSettingsTab.ts export class PluginSettingsTab extends PluginSettingsTabBase { public override display(): void { super.display(); new SettingEx(this.containerEl) .setName('Email address') .addText((text) => this.bind(text, 'emailAddress')); } } ``` -------------------------------- ### Get Computed Element Attribute Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/5-core-utilities.md Use `getComputedAttribute` to retrieve the computed value of a CSS attribute for a given HTML element. This reflects the final, rendered style of the element. ```typescript function getComputedAttribute(element: HTMLElement, attribute: string): string ``` ```typescript const bgColor = getComputedAttribute(element, 'background-color'); ``` -------------------------------- ### Initialize Plugin Context for Styling Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/10-setting-components.md Initializes the plugin context for applying styles. This should be called within your plugin's `onload` method. Alternatively, you can manually include the styles.css file. ```typescript import { initPluginContext } from 'obsidian-dev-utils/obsidian'; export default class MyPlugin extends PluginBase { async onload() { await super.onload(); initPluginContext(this.manifest.id); } } ``` -------------------------------- ### Get Current Stack Trace Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/5-core-utilities.md Use `getStackTrace` to capture the current call stack as a string. You can specify the number of frames to skip to exclude irrelevant calls from the trace. ```typescript function getStackTrace(framesToSkip?: number): string ``` ```typescript const trace = getStackTrace(1); console.log(trace); ``` -------------------------------- ### Importing Prompt Function (Wildcard) Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/helper-functions.md Import all utilities from the 'obsidian-dev-utils' library using a wildcard import. This provides access to all exported functions and modules. ```typescript import * as obsidianDevUtils from 'obsidian-dev-utils'; await obsidianDevUtils.obsidian.modal.prompt.prompt({ app, title: 'Enter your name' }); ``` -------------------------------- ### Accessing Kebab-Case Identifier (Wildcard Import) Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/helper-functions.md Demonstrates accessing a module with a kebab-case name ('file-manager') using bracket notation with a wildcard import. This is necessary when the module name is not a valid JavaScript identifier. ```typescript import * as obsidian from 'obsidian-dev-utils/obsidian'; await obsidian['file-manager'].addAlias(app, file, 'new-alias'); ``` -------------------------------- ### Custom Error Handling Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/11-quick-reference.md Provides custom error types like `CustomStackTraceError` and `SilentError` for better error management. Includes utilities for printing errors and getting stack traces. ```typescript // Wrap in CustomStackTraceError throw new CustomStackTraceError('msg', getStackTrace(1), originalError); // Silent errors (user sees message, not console) throw new SilentError('User-facing message'); // Print error with full chain printError(error); // Get stack trace const trace = getStackTrace(1); // Emit async error event emitAsyncErrorEvent(error); // Check if silent error if (handleSilentError(error)) { // Already handled } ``` -------------------------------- ### Wrap CLI Task with Version Update Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Demonstrates wrapping a version update script task with `wrapCliTask`, passing command-line arguments. Requires `process` module for argv access. ```typescript // scripts/version.ts import process from 'node:process'; import { wrapCliTask } from 'obsidian-dev-utils/script-utils/cli-utils'; import { updateVersion } from 'obsidian-dev-utils/script-utils/version'; const [, , versionUpdateType] = process.argv; await wrapCliTask(() => updateVersion(versionUpdateType)); ``` -------------------------------- ### Prompt for User Input with Validation Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/0-index.md Use the `prompt` function to get user input with real-time validation. The `valueValidator` function should return `null` for valid input or an error message string. ```typescript const email = await prompt({ app: this.app, title: 'Email', valueValidator: (value) => { const isValid = /^["\w."-]+@["\w."-]+\.\w+$/.test(value); return isValid ? null : 'Invalid email'; } }); ``` -------------------------------- ### addFile Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/10-setting-components.md Adds a file selector component to the settings. ```APIDOC ## addFile(callback) ### Description Adds a file selector. ### Method Signature ```typescript addFile(cb: (file: FileComponent) => void): this ``` ### Parameters * `cb` (function) - Callback function that receives the FileComponent instance. ### Example ```typescript .setName('Template file') .addFile((file) => { file.setValue(settings.templatePath) .onChange((value) => settings.templatePath = value); }) ``` ``` -------------------------------- ### Override Default Styles Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/styling.md Override default Obsidian Dev Utils styles by targeting your plugin's ID in your plugin's `styles.css` file. This example shows how to style invalid elements. ```css .foo-bar.obsidian-dev-utils :invalid { box-shadow: 0 0 0 2px var(--text-error); } ``` -------------------------------- ### Simplest Plugin (Current) Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md The current structure for a simple Obsidian plugin without settings, requiring multiple boilerplate files. ```typescript // main.ts (boilerplate) // PluginTypes.ts (boilerplate) // Plugin.ts export class Plugin extends PluginBase { protected override async onloadImpl(): Promise { await super.onloadImpl(); new EditCommand(this).register(); } } ``` -------------------------------- ### Displaying User Dialogs Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/0-index.md Shows how to use modal dialogs for user interaction, including alerts, confirmations, and prompts for input. The prompt includes a value validator to ensure input is not empty. ```typescript import { alert, confirm, prompt } from 'obsidian-dev-utils/obsidian/modals'; // Simple alert await alert({ app: this.app, title: 'Information', message: 'Operation completed' }); // Ask for confirmation if (await confirm({ app: this.app, message: 'Delete file?' })) { await deleteFile(); } // Get user input with validation const name = await prompt({ app: this.app, title: 'New note', placeholder: 'Note name', valueValidator: (value) => { return value.trim() ? null : 'Name cannot be empty'; } }); ``` -------------------------------- ### Execute Promises Sequentially Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/1-async-utilities.md Use `promiseAllSequentially` to execute an array of promises in a sequential manner, ensuring each promise completes before the next one starts. This is useful when the order of execution or dependency between promises matters. ```typescript async function promiseAllSequentially(promises: Promisable[]): Promise ``` ```typescript const results = await promiseAllSequentially([ fetchUser(1), fetchUser(2), fetchUser(3) ]); ``` -------------------------------- ### Implement a Custom Point Transformer Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/_autodocs/6-transformers.md Define a custom transformer for a 'Point' interface using TypedTransformer. This example demonstrates how to check for object structure and specific properties before transforming the value into a string representation and restoring it. ```typescript import { TypedTransformer } from 'obsidian-dev-utils/transformers'; interface Point { x: number; y: number; } class PointTransformer extends TypedTransformer { public readonly id = 'point'; public canTransform(value: unknown): boolean { return typeof value === 'object' && value !== null && 'x' in value && 'y' in value; } public transformValue(value: unknown): string { const point = value as Point; return `${point.x},${point.y}`; } protected restoreValue(transformed: unknown): Point { const [x, y] = (transformed as string).split(',').map(Number); return { x, y }; } } ``` -------------------------------- ### Importing Prompt Function (Modal Namespace) Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/helper-functions.md Import the prompt function via the 'modal' namespace from the obsidian module. This approach imports a broader set of modal-related utilities. ```typescript import { prompt } from 'obsidian-dev-utils/obsidian/modal'; await prompt.prompt({ app, title: 'Enter your name' }); ``` -------------------------------- ### Inline Command Registration Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Shows the proposed simplified method for registering commands directly within the Plugin.onloadImpl() method using addCommand(). This reduces boilerplate compared to the previous two-class approach. ```typescript // In Plugin.onloadImpl() this.addCommand({ id: 'check-emails', name: 'Check emails', icon: 'mail', callback: () => this.emailChecker.checkEmails() }); ``` -------------------------------- ### Create Conventional Commit Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CONTRIBUTING.md Use the interactive commit prompt to create commits following Conventional Commits specification. ```bash npm run commit ``` -------------------------------- ### Previous Command Structure Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CLAUDE.md Illustrates the previous, more verbose structure for commands, which involved two separate classes (CommandInvocationBase and NonEditorCommandBase) per command, contributing to approximately 30 lines of code per command. ```typescript class CheckEmailsInvocation extends CommandInvocationBase { ... } export class CheckEmailsCommand extends NonEditorCommandBase { ... } ``` -------------------------------- ### Importing Prompt Function (Direct) Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/helper-functions.md Import the prompt function directly from its specific module path. This is useful for importing only the necessary function. ```typescript import { prompt } from 'obsidian-dev-utils/obsidian/modal/prompt'; await prompt({ app, title: 'Enter your name' }); ``` -------------------------------- ### Package.json Scripts for CLI Commands Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/cli-commands.md Defines script entry points in `package.json` for various development tasks using `jiti` to execute TypeScript files. ```json { "scripts": { "build": "jiti scripts/build.ts", "build:clean": "jiti scripts/build-clean.ts", "build:compile:typescript": "jiti scripts/build-compile-typescript.ts", "build:static": "jiti scripts/build-static.ts", "dev": "jiti scripts/dev.ts", "format": "jiti scripts/format.ts", "format:check": "jiti scripts/format-check.ts", "lint": "jiti scripts/lint.ts", "lint:fix": "jiti scripts/lint-fix.ts", "spellcheck": "jiti scripts/spellcheck.ts", "test": "jiti scripts/test.ts", "version": "jiti scripts/version.ts" }, "...": "..." } ``` -------------------------------- ### Publish Package to NPM Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/cli-commands.md Publishes the package to NPM. This command is usually not applicable for plugins. Consider setting `NPM_TOKEN` for bypass manual verification. ```typescript import { publish } from 'obsidian-dev-utils/script-utils/npm-publish'; await publish(); ``` -------------------------------- ### Check and Format Code Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/CONTRIBUTING.md Check code formatting and apply automatic formatting. ```bash npm run format:check npm run format ``` -------------------------------- ### MultipleEmailComponent Usage Source: https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/setting-components.md Demonstrates how to create and set values for the MultipleEmailComponent. It can be instantiated directly or used via the SettingEx helper. ```typescript import { MultipleEmailComponent } from 'obsidian-dev-utils/obsidian/components/setting-component/multiple-email-component'; const multipleEmail = new MultipleEmailComponent(containerEl); multipleEmail.setValue(['foo@bar.com', 'baz@qux.com']); ``` ```typescript import { SettingEx } from 'obsidian-dev-utils/obsidian/setting-ex'; new SettingEx() .addMultipleEmail((multipleEmail) => { multipleEmail.setValue(['foo@bar.com', 'baz@qux.com']); }); ```