diff --git a/packages/core/src/extensions/ExtensionManager.ts b/packages/core/src/extensions/ExtensionManager.ts index cdc5ee1..d762795 100644 --- a/packages/core/src/extensions/ExtensionManager.ts +++ b/packages/core/src/extensions/ExtensionManager.ts @@ -4,21 +4,37 @@ import type { Editor } from "../editor/Editor.ts"; import type { InkwellExtension } from "./types.ts"; /** - * The ExtensionManager class is responsible for managing and resolving extensions, binding their properties & exposing CodeMirror extensions to the editor. + * Manages and resolves extensions so the editor receives one complete CodeMirror setup. */ export class ExtensionManager { + /** Keeps this manager connected to its editor. */ private editor: Editor; + + /** Stores extensions passed directly to the editor. */ private _extensions: InkwellExtension[] = []; + + /** Stores root and child extensions that can contribute to editor setup. */ private _resolvedExtensions: InkwellExtension[] = []; + + /** Stores advanced CodeMirror additions from configured extensions. */ private _addonCMExtensions: CMExtension[] = []; + + /** Stores keybindings before they become one CodeMirror keymap. */ private _keybindings: KeyBinding[] = []; + /** + * Creates one extension setup lifecycle for the editor and its configured extensions. + * + * @param editor - Owns this extension lifecycle. + * @param extensions - Define the features available when the editor starts. + */ constructor(editor: Editor, extensions: InkwellExtension[]) { this.editor = editor; this._extensions = extensions; this._resolvedExtensions = this.resolveExtensions(); - for (const ext of this.sortExtensionsByPrio(this._resolvedExtensions)) { + const sortedExtensions = this.sortExtensionsByPrio(this._resolvedExtensions); + for (const ext of sortedExtensions) { if (ext.addNodes) this.bindNodes(ext.addNodes); if (ext.addMarks) this.bindMarks(ext.addMarks); if (ext.addCommands) this.bindCommands(ext.addCommands); @@ -27,23 +43,31 @@ export class ExtensionManager { } } + /** Provides the root extensions before child extensions are resolved. */ get extensions(): InkwellExtension[] { return [...this._extensions]; } + /** Provides CodeMirror extensions ready for the editor state. */ get cmExtensions(): CMExtension[] { return [keymap.of(this._keybindings), ...this._addonCMExtensions]; } + /** Provides root and child extensions that can contribute to editor setup. */ get resolvedExtensions(): InkwellExtension[] { return [...this._resolvedExtensions]; } + /** Provides one CodeMirror keymap containing all configured keybindings. */ get keybindings(): CMExtension { return keymap.of(this._keybindings); } - /** The resolved extension array, including child extensions */ + /** + * Expands child extensions so their contributions are included in editor setup. + * + * @returns The complete extension list, including child extensions. + */ resolveExtensions(): InkwellExtension[] { const resolved: InkwellExtension[] = []; const visited = new Set(); @@ -72,25 +96,47 @@ export class ExtensionManager { return resolved; } + /** + * Orders extensions so higher-priority behavior takes precedence predictably. + * + * @param extensions - The extensions that need a predictable contribution order. + * @returns A new array with higher-priority extensions first. + */ public sortExtensionsByPrio(extensions: InkwellExtension[]): InkwellExtension[] { return [...extensions].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0)); } + /** + * Reserves the node registration step until Inkwell has a document model. + * + * @param addNodes - Provides nodes from one extension. + */ private bindNodes(addNodes: NonNullable) { // TODO: implement node binding logic, noop for now } + /** + * Reserves the mark registration step until Inkwell has a document model. + * + * @param addMarks - Provides marks from one extension. + */ private bindMarks(addMarks: NonNullable) { // TODO: implement mark binding logic, noop for now } + /** + * Reserves command registration until Inkwell exposes a command registry. + * + * @param addCommands - Provides commands from one extension. + */ private bindCommands(addCommands: NonNullable) { // TODO: implement command binding logic, noop for now } /** - * Binds keymaps from all resolved extensions. - * @returns An array of KeyBinding objects from all resolved extensions. + * Collects configured keybindings so they become one consistent editor keymap. + * + * @param addKeybinds - Provides keybindings from one extension. */ private bindKeymaps(addKeybinds: NonNullable) { const keyBinds = @@ -100,9 +146,9 @@ export class ExtensionManager { } /** - * Binds CodeMirror extensions from all resolved extensions. - * @param addCodeMirrorExtensions - A function that returns an array of CodeMirror extensions. - * @returns An array of CodeMirror extensions from all resolved extensions. + * Keeps advanced CodeMirror additions in the same editor setup pipeline. + * + * @param addCodeMirrorExtensions - Provides CodeMirror additions from one extension. */ private bindCmExtensions( addCodeMirrorExtensions: NonNullable,