diff --git a/main.ts b/main.ts index 2d07212..52e3f88 100644 --- a/main.ts +++ b/main.ts @@ -1,82 +1,119 @@ -import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; +import {App, Editor, EditorPosition, MarkdownView, SuggestModal, Notice, Plugin, PluginSettingTab, Setting} from 'obsidian'; // Remember to rename these classes and interfaces! -interface MyPluginSettings { + + +interface TextMoverPluginSettings { mySetting: string; } -const DEFAULT_SETTINGS: MyPluginSettings = { +const DEFAULT_SETTINGS: TextMoverPluginSettings = { mySetting: 'default' } -export default class MyPlugin extends Plugin { - settings: MyPluginSettings; + +interface Heading { + heading: string; + level: number; + position: object; + } + + + +export class HeadingSuggestionModal extends SuggestModal { + // Returns all available suggestions. + headings: Heading[]; + result: object + onSubmit: (result: object) => void; + + constructor(app: App, headings: Heading[], onSubmit: (result: object) => void) { + super(app); + console.log("inside constructor"); + this.headings = headings; + // console.log(this.headings); + this.onSubmit = onSubmit; + + } + + + getSuggestions(query: string): Heading[] { + return this.headings.filter((item) => + item.heading.toLowerCase().includes(query.toLowerCase()) + ); + } + + // Renders each suggestion item. + renderSuggestion(heading: Heading, el: HTMLElement) { + el.createEl("div", { text: heading.heading }); + } + + // Perform action on the selected suggestion. + onChooseSuggestion(heading: Heading, evt: MouseEvent | KeyboardEvent) { + this.onSubmit(heading); + } + } + + +export default class TextMoverPlugin extends Plugin { + settings: TextMoverPluginSettings; async onload() { - await this.loadSettings(); - // This creates an icon in the left ribbon. - const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', (evt: MouseEvent) => { - // Called when the user clicks the icon. - new Notice('This is a notice!'); - }); - // Perform additional things with the ribbon - ribbonIconEl.addClass('my-plugin-ribbon-class'); + // await this.loadSettings(); + console.log("loading") + this.registerEvent( + this.app.workspace.on("editor-menu", (menu, editor, view) => { + menu.addItem((item) => { + item + .setTitle("Move text to heading") + .setIcon("document") + .onClick(async () => { + let selection = editor.getSelection(); + const cursorposition = editor.getCursor() + + if (selection == "" ){ + // get clicked text + selection = editor.getLine(cursorposition.line) + } + console.log(selection) + // TODO: get cursor position - // This adds a status bar item to the bottom of the app. Does not work on mobile apps. - const statusBarItemEl = this.addStatusBarItem(); - statusBarItemEl.setText('Status Bar Text'); + let file = this.app.workspace.getActiveFile() + // get headings from file + const filecache = this.app.metadataCache.getFileCache(file) + let headings: Heading[] = []; + if (filecache && filecache.headings) { + headings = filecache.headings.map(headingCache => { + return { + heading: headingCache.heading, + level: headingCache.level, + position: headingCache.position + }; + }); + } - // This adds a simple command that can be triggered anywhere - this.addCommand({ - id: 'open-sample-modal-simple', - name: 'Open sample modal (simple)', - callback: () => { - new SampleModal(this.app).open(); - } - }); - // This adds an editor command that can perform some operation on the current editor instance - this.addCommand({ - id: 'sample-editor-command', - name: 'Sample editor command', - editorCallback: (editor: Editor, view: MarkdownView) => { - console.log(editor.getSelection()); - editor.replaceSelection('Sample Editor Command'); - } - }); - // This adds a complex command that can check whether the current state of the app allows execution of the command - this.addCommand({ - id: 'open-sample-modal-complex', - name: 'Open sample modal (complex)', - checkCallback: (checking: boolean) => { - // Conditions to check - const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView); - if (markdownView) { - // If checking is true, we're simply "checking" if the command can be run. - // If checking is false, then we want to actually perform the operation. - if (!checking) { - new SampleModal(this.app).open(); - } + let hmodal = new HeadingSuggestionModal(this.app, headings, (result) => { + const cursorposition = editor.getCursor() + let targetPosition = {"line": result.position.end.line, "ch": result.position.end.ch}//editor.getCursor() + // insert selection under heading + editor.replaceRange(`\n${selection}`, targetPosition) + + let start = {"line":cursorposition.line, "ch":0} + let end = {"line":cursorposition.line, "ch":selection.length+1} + editor.replaceRange("", start, end) + }); + + hmodal.open() + + }); + + }) - // This command will only show up in Command Palette when the check function returns true - return true; - } - } - }); - - // This adds a settings tab so the user can configure various aspects of the plugin - this.addSettingTab(new SampleSettingTab(this.app, this)); - - // If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin) - // Using this function will automatically remove the event listener when this plugin is disabled. - this.registerDomEvent(document, 'click', (evt: MouseEvent) => { - console.log('click', evt); - }); - - // When registering intervals, this function will automatically clear the interval when the plugin is disabled. - this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); + })) } + + onunload() { @@ -90,45 +127,3 @@ export default class MyPlugin extends Plugin { await this.saveData(this.settings); } } - -class SampleModal extends Modal { - constructor(app: App) { - super(app); - } - - onOpen() { - const {contentEl} = this; - contentEl.setText('Woah!'); - } - - onClose() { - const {contentEl} = this; - contentEl.empty(); - } -} - -class SampleSettingTab extends PluginSettingTab { - plugin: MyPlugin; - - constructor(app: App, plugin: MyPlugin) { - super(app, plugin); - this.plugin = plugin; - } - - display(): void { - const {containerEl} = this; - - containerEl.empty(); - - new Setting(containerEl) - .setName('Setting #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(); - })); - } -} diff --git a/manifest.json b/manifest.json index dfa940e..86cfefc 100644 --- a/manifest.json +++ b/manifest.json @@ -1,9 +1,9 @@ { - "id": "sample-plugin", - "name": "Sample Plugin", + "id": "move-text-to-heading", + "name": "Move Text To Heading", "version": "1.0.0", "minAppVersion": "0.15.0", - "description": "Demonstrates some of the capabilities of the Obsidian API.", + "description": "Easy way to move text to heading", "author": "Obsidian", "authorUrl": "https://obsidian.md", "fundingUrl": "https://obsidian.md/pricing",