obsidian#Editor TypeScript Examples

The following examples show how to use obsidian#Editor. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From obsidian-editor-shortcuts with MIT License 7 votes vote down vote up
findAllMatchPositions = ({
  editor,
  searchText,
  searchWithinWords,
  documentContent,
}: {
  editor: Editor;
  searchText: string;
  searchWithinWords: boolean;
  documentContent: string;
}) => {
  const matches = findAllMatches({
    searchText,
    searchWithinWords,
    documentContent,
  });
  const matchPositions = [];
  for (const match of matches) {
    matchPositions.push({
      anchor: editor.offsetToPos(match.index),
      head: editor.offsetToPos(match.index + searchText.length),
    });
  }
  return matchPositions;
}
Example #2
Source File: utils.ts    From nldates-obsidian with MIT License 7 votes vote down vote up
export function getSelectedText(editor: Editor): string {
  if (editor.somethingSelected()) {
    return editor.getSelection();
  } else {
    const wordBoundaries = getWordBoundaries(editor);
    editor.setSelection(wordBoundaries.from, wordBoundaries.to); // TODO check if this needs to be updated/improved
    return editor.getSelection();
  }
}
Example #3
Source File: utils.ts    From obsidian-editor-shortcuts with MIT License 7 votes vote down vote up
getSearchText = ({
  editor,
  allSelections,
  autoExpand,
}: {
  editor: Editor;
  allSelections: EditorSelection[];
  autoExpand: boolean;
}) => {
  // Don't search if multiple selection contents are not identical
  const singleSearchText = hasSameSelectionContent(editor, allSelections);
  const firstSelection = allSelections[0];
  const { from, to } = getSelectionBoundaries(firstSelection);
  let searchText = editor.getRange(from, to);
  if (searchText.length === 0 && autoExpand) {
    const wordRange = wordRangeAtPos(from, editor.getLine(from.line));
    searchText = editor.getRange(wordRange.anchor, wordRange.head);
  }
  return {
    searchText,
    singleSearchText,
  };
}
Example #4
Source File: utils.ts    From obsidian-map-view with GNU General Public License v3.0 7 votes vote down vote up
/**
 * Go to a character index in the note
 * @param editor The Obsidian Editor instance
 * @param fileLocation The character index in the file to go to
 * @param highlight If true will select the whole line
 */
export async function goToEditorLocation(
    editor: Editor,
    fileLocation: number,
    highlight: boolean
) {
    if (fileLocation) {
        let pos = editor.offsetToPos(fileLocation);
        if (highlight) {
            const lineContent = editor.getLine(pos.line);
            editor.setSelection(
                { ch: 0, line: pos.line },
                { ch: lineContent.length, line: pos.line }
            );
        } else {
            editor.setCursor(pos);
            editor.refresh();
        }
    }
    editor.focus();
}
Example #5
Source File: util.ts    From obsidian-charts with GNU Affero General Public License v3.0 7 votes vote down vote up
export async function saveImageToVaultAndPaste(editor: Editor, app: App, renderer: Renderer, source: TFile, settings: ChartPluginSettings) {
    const image = await renderer.imageRenderer(editor.getSelection(), settings.imageSettings);
    console.log("image converted")
    const file = await app.vault.createBinary(
        //@ts-ignore
        await app.vault.getAvailablePathForAttachments(`Chart ${new Date().toDateString()}`, settings.imageSettings.format.split('/').last(), source),
        base64ToArrayBuffer(image)
    );
    console.log("Image saved")

    editor.replaceSelection(app.fileManager.generateMarkdownLink(file, source.path));
}
Example #6
Source File: utils.ts    From obsidian-map-view with GNU General Public License v3.0 7 votes vote down vote up
// Creates or modifies a front matter that has the field `fieldName: fieldValue`.
// Returns true if a change to the note was made.
export function verifyOrAddFrontMatter(
    editor: Editor,
    fieldName: string,
    fieldValue: string
): boolean {
    const content = editor.getValue();
    const frontMatterRegex = /^---(.*?)^---/ms;
    const frontMatter = content.match(frontMatterRegex);
    const existingFieldRegex = new RegExp(`^---.*${fieldName}:.*^---`, 'ms');
    const existingField = content.match(existingFieldRegex);
    const cursorLocation = editor.getCursor();
    // That's not the best usage of the API, and rather be converted to editor transactions or something else
    // that can preserve the cursor position better
    if (frontMatter && !existingField) {
        const replaced = `---${frontMatter[1]}${fieldName}: ${fieldValue}\n---`;
        editor.setValue(content.replace(frontMatterRegex, replaced));
        editor.setCursor({
            line: cursorLocation.line + 1,
            ch: cursorLocation.ch,
        });
        return true;
    } else if (!frontMatter) {
        const newFrontMatter = `---\n${fieldName}: ${fieldValue}\n---\n\n`;
        editor.setValue(newFrontMatter + content);
        editor.setCursor({
            line: cursorLocation.line + newFrontMatter.split('\n').length - 1,
            ch: cursorLocation.ch,
        });
        return true;
    }
    return false;
}
Example #7
Source File: actions.ts    From obsidian-editor-shortcuts with MIT License 6 votes vote down vote up
joinLines = (editor: Editor, selection: EditorSelection) => {
  const { line } = selection.head;
  const endOfCurrentLine = getLineEndPos(line, editor);
  if (line < editor.lineCount() - 1) {
    const endOfNextLine = getLineEndPos(line + 1, editor);
    const contentsOfNextLine = editor
      .getLine(line + 1)
      .replace(/^\s*((-|\+|\*|\d+\.) )?/, '');
    editor.replaceRange(
      contentsOfNextLine.length > 0
        ? ' ' + contentsOfNextLine
        : contentsOfNextLine,
      endOfCurrentLine,
      endOfNextLine,
    );
  }
  return { anchor: endOfCurrentLine };
}
Example #8
Source File: main.ts    From obsidian-linter with MIT License 6 votes vote down vote up
runLinterEditor(editor: Editor) {
      console.log('running linter');

      const file = this.app.workspace.getActiveFile();
      const oldText = editor.getValue();
      const newText = this.lintText(oldText, file);

      // Replace changed lines
      const dmp = new DiffMatchPatch.diff_match_patch(); // eslint-disable-line new-cap
      const changes = dmp.diff_main(oldText, newText);
      let curText = '';
      changes.forEach((change) => {
        function endOfDocument(doc: string) {
          const lines = doc.split('\n');
          return {line: lines.length - 1, ch: lines[lines.length - 1].length};
        }

        const [type, value] = change;

        if (type == DiffMatchPatch.DIFF_INSERT) {
          editor.replaceRange(value, endOfDocument(curText));
          curText += value;
        } else if (type == DiffMatchPatch.DIFF_DELETE) {
          const start = endOfDocument(curText);
          let tempText = curText;
          tempText += value;
          const end = endOfDocument(tempText);
          editor.replaceRange('', start, end);
        } else {
          curText += value;
        }
      });

      const charsAdded = changes.map((change) => change[0] == DiffMatchPatch.DIFF_INSERT ? change[1].length : 0).reduce((a, b) => a + b, 0);
      const charsRemoved = changes.map((change) => change[0] == DiffMatchPatch.DIFF_DELETE ? change[1].length : 0).reduce((a, b) => a + b, 0);
      this.displayChangedMessage(charsAdded, charsRemoved);
    }
Example #9
Source File: main.ts    From obsidian-emoji-shortcodes with MIT License 6 votes vote down vote up
onTrigger(cursor: EditorPosition, editor: Editor, _: TFile): EditorSuggestTriggerInfo | null {
		if (this.plugin.settings.suggester) {
			const sub = editor.getLine(cursor.line).substring(0, cursor.ch);
			const match = sub.match(/:\S+$/)?.first();
			if (match) {
				return {
					end: cursor,
					start: {
						ch: sub.lastIndexOf(match),
						line: cursor.line,
					},
					query: match,
				}
			}
		}
		return null;
	}
Example #10
Source File: customContextMenu.ts    From obsidian-dictionary with GNU Affero General Public License v3.0 6 votes vote down vote up
export default function handleContextMenu(menu: Menu, instance: Editor, plugin: DictionaryPlugin): void {
    if (!plugin.settings.shouldShowCustomContextMenu) {
        return;
    }
    const selection = instance.getSelection();

    if (selection && selection.trim().split(" ").length === 1) {
        if (!plugin.settings.shouldShowSynonymPopover) {
            menu.addItem((item) => {
                item.setTitle(t('Show Synonyms'))
                    .setIcon('synonyms')
                    .onClick(async (_) => {
                        plugin.handlePointerUp();
                    });
            });
        }
        menu.addItem((item) => {
            item.setTitle(t('Look up'))
                .setIcon('quote-glyph')
                .onClick(async (_) => {
                    let leaf: WorkspaceLeaf = plugin.app.workspace.getLeavesOfType(VIEW_TYPE).first();
                    if(!leaf){
                        leaf = plugin.app.workspace.getRightLeaf(false);
                        await leaf.setViewState({
                            type: VIEW_TYPE,
                        });
                    }
                    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                    //@ts-ignore
                    leaf.view.query(selection.trim());
                    plugin.app.workspace.revealLeaf(leaf);
                });
        });
    }
}
Example #11
Source File: chartFromTable.ts    From obsidian-charts with GNU Affero General Public License v3.0 6 votes vote down vote up
export async function chartFromTable(editor: Editor, layout: 'columns' | 'rows') {
    const {labels, dataFields} = generateTableData(editor.getSelection(), layout);
    const chart = `\`\`\`chart
type: bar
labels: [${labels}]
series:
${dataFields
    .map((data) => `  - title: ${data.dataTitle}\n    data: [${data.data}]`)
    .join("\n")}
width: 80%
beginAtZero: true
\`\`\``;

    editor.replaceSelection(chart);
}
Example #12
Source File: main.ts    From quick_latex_obsidian with MIT License 6 votes vote down vote up
private readonly withinAnyBrackets_document = (
		editor: Editor,
		open_symbol: string,
		close_symbol: string
	): Boolean => {
		const document_text = editor.getValue()
		const cursorPos = editor.getCursor()
		const cursor_index = editor.posToOffset(cursorPos)
		// count open symbols
		let from = 0;
		let found = document_text.indexOf(open_symbol, from);
		let count = 0;
		while (found != -1 && found < cursor_index) {
			count += 1;
			from = found + 1;
			found = document_text.indexOf(open_symbol, from);
		}
		const open_symbol_counts = count

		// count close symbols
		from = 0;
		found = document_text.indexOf(close_symbol, from);
		count = 0;
		while (found != -1 && found < cursor_index) {
			count += 1;
			from = found + 1;
			found = document_text.indexOf(close_symbol, from);
		}
		const close_symbol_counts = count

		return open_symbol_counts > close_symbol_counts;
	};
Example #13
Source File: actions.ts    From obsidian-editor-shortcuts with MIT License 6 votes vote down vote up
copyLine = (
  editor: Editor,
  selection: EditorSelection,
  direction: 'up' | 'down',
) => {
  const { from, to } = getSelectionBoundaries(selection);
  const fromLineStart = getLineStartPos(from.line);
  const toLineEnd = getLineEndPos(to.line, editor);
  const contentsOfSelectedLines = editor.getRange(fromLineStart, toLineEnd);
  if (direction === 'up') {
    editor.replaceRange('\n' + contentsOfSelectedLines, toLineEnd);
    return selection;
  } else {
    editor.replaceRange(contentsOfSelectedLines + '\n', fromLineStart);
    const linesSelected = to.line - from.line + 1;
    return {
      anchor: { line: to.line + 1, ch: from.ch },
      head: { line: to.line + linesSelected, ch: to.ch },
    };
  }
}
Example #14
Source File: main.ts    From quick_latex_obsidian with MIT License 6 votes vote down vote up
//utility functions
	private readonly unclosed_bracket = (
		editor: Editor,
		open_symbol: string,
		close_symbol: string,
		before: number,
		after: number,
		unclosed_open_symbol: boolean = true //false for unclosed_close_symbol
	): [boolean, number[]] => {
		// determine if there are unclosed bracket within the range specified by before and after
		const position = editor.getCursor();
		const text = editor.getRange(
			{ line: position.line, ch: after },
			{ line: position.line, ch: before });
		let open_array: number[] = []
		let close_array: number[] = []
		for (let i = 0; i < text.length; i++) {
			switch (text[i]) {
				case open_symbol:
					open_array.push(after + i);
					break;
				case close_symbol:
					if (open_array.length > 0) {
						open_array.pop()
					} else {
						close_array.push(after + i);
					}
					break;
			}
		}
		if (unclosed_open_symbol) {
			return [open_array.length > 0, open_array];
		} else {
			return [close_array.length > 0, close_array];
		}

	};
Example #15
Source File: actions.ts    From obsidian-editor-shortcuts with MIT License 6 votes vote down vote up
navigateLine = (
  editor: Editor,
  selection: EditorSelection,
  direction: 'up' | 'down',
) => {
  const pos = selection.head;
  let line: number;

  if (direction === 'up') {
    line = Math.max(pos.line - 1, 0);
  } else {
    line = Math.min(pos.line + 1, editor.lineCount() - 1);
  }

  const endOfLine = getLineEndPos(line, editor);
  const ch = Math.min(pos.ch, endOfLine.ch);

  return { anchor: { line, ch } };
}
Example #16
Source File: suggest.ts    From obsidian-admonition with MIT License 6 votes vote down vote up
onTrigger(
        cursor: EditorPosition,
        editor: Editor,
        file: TFile
    ): EditorSuggestTriggerInfo {
        const line = editor.getLine(cursor.line);
        //not inside the bracket
        if (/> \[!\w+\]/.test(line.slice(0, cursor.ch))) return null;
        if (!/> \[!\w*/.test(line)) return null;

        const match = line.match(/> \[!(\w*)\]?/);
        if (!match) return null;

        const [_, query] = match;

        if (
            !query ||
            Object.keys(this.plugin.admonitions).find(
                (p) => p.toLowerCase() == query.toLowerCase()
            )
        ) {
            return null;
        }
        const matchData = {
            end: cursor,
            start: {
                ch: match.index + 4,
                line: cursor.line
            },
            query
        };
        return matchData;
    }
Example #17
Source File: locationSuggest.ts    From obsidian-map-view with GNU General Public License v3.0 6 votes vote down vote up
onTrigger(
        cursor: EditorPosition,
        editor: Editor,
        file: TFile
    ): EditorSuggestTriggerInfo | null {
        const currentLink = this.getGeolinkOfCursor(cursor, editor);
        if (currentLink)
            return {
                start: { line: cursor.line, ch: currentLink.index },
                end: { line: cursor.line, ch: currentLink.linkEnd },
                query: currentLink.name,
            };
        return null;
    }
Example #18
Source File: main.ts    From quick_latex_obsidian with MIT License 6 votes vote down vote up
private addCasesBlock(editor: Editor) {
		const view = this.app.workspace.getActiveViewOfType(MarkdownView);
		if (!view) return;
		if (!this.settings.addCasesBlock_toggle) return;
		const selected_text = editor.getSelection()
		editor.replaceSelection(
			'\\begin{cases}\n' +
			selected_text +
			'\n\\end{cases}'
		);
		const position = editor.getCursor();
		editor.setCursor({ line: position.line - 1, ch: editor.getLine(position.line - 1).length })
	}
Example #19
Source File: urlConvertor.ts    From obsidian-map-view with GNU General Public License v3.0 6 votes vote down vote up
/**
     * Insert a geo link into the editor at the cursor position
     * @param location The geolocation to convert to text and insert
     * @param editor The Obsidian Editor instance
     * @param replaceStart The EditorPosition to start the replacement at. If null will replace any text selected
     * @param replaceLength The EditorPosition to stop the replacement at. If null will replace any text selected
     */
    insertLocationToEditor(
        location: leaflet.LatLng,
        editor: Editor,
        replaceStart?: EditorPosition,
        replaceLength?: number
    ) {
        const locationString = `[](geo:${location.lat},${location.lng})`;
        const cursor = editor.getCursor();
        if (replaceStart && replaceLength) {
            editor.replaceRange(locationString, replaceStart, {
                line: replaceStart.line,
                ch: replaceStart.ch + replaceLength,
            });
        } else editor.replaceSelection(locationString);
        // We want to put the cursor right after the beginning of the newly-inserted link
        const newCursorPos = replaceStart ? replaceStart.ch + 1 : cursor.ch + 1;
        editor.setCursor({ line: cursor.line, ch: newCursorPos });
        utils.verifyOrAddFrontMatter(editor, 'locations', '');
    }
Example #20
Source File: main.ts    From obsidian-consistent-attachments-and-links with MIT License 6 votes vote down vote up
async collectAttachmentsCurrentNote(editor: Editor, view: MarkdownView) {
		let note = view.file;
		if (this.isPathIgnored(note.path)) {
			new Notice("Note path is ignored");
			return;
		}

		let result = await this.fh.collectAttachmentsForCachedNote(
			note.path,
			this.settings.attachmentsSubfolder,
			this.settings.deleteExistFilesWhenMoveNote);

		if (result && result.movedAttachments && result.movedAttachments.length > 0) {
			await this.lh.updateChangedPathsInNote(note.path, result.movedAttachments)
		}

		if (result.movedAttachments.length == 0)
			new Notice("No files found that need to be moved");
		else
			new Notice("Moved " + result.movedAttachments.length + " attachment" + (result.movedAttachments.length > 1 ? "s" : ""));
	}
Example #21
Source File: fixtureUtils.ts    From obsidian-switcher-plus with GNU General Public License v3.0 6 votes vote down vote up
export function makeLeaf(sourceFile?: TFile): MockProxy<WorkspaceLeaf> {
  const mockView = mock<MarkdownView>({
    file: sourceFile ?? new TFile(),
    editor: mock<Editor>(),
  });

  mockView.getViewType.mockReturnValue('markdown');

  return mock<WorkspaceLeaf>({
    view: mockView,
  });
}
Example #22
Source File: tools.ts    From obsidian-chartsview-plugin with MIT License 6 votes vote down vote up
export function insertEditor(editor: Editor, data: string): void {
    editor.somethingSelected
    ?
    editor.replaceSelection(data)
    :
    editor.setLine(
        editor.getCursor().line,
        data
    );
}
Example #23
Source File: date-suggest.ts    From nldates-obsidian with MIT License 6 votes vote down vote up
onTrigger(
    cursor: EditorPosition,
    editor: Editor,
    file: TFile
  ): EditorSuggestTriggerInfo {
    if (!this.plugin.settings.isAutosuggestEnabled) {
      return null;
    }

    const triggerPhrase = this.plugin.settings.autocompleteTriggerPhrase;
    const startPos = this.context?.start || {
      line: cursor.line,
      ch: cursor.ch - triggerPhrase.length,
    };

    if (!editor.getRange(startPos, cursor).startsWith(triggerPhrase)) {
      return null;
    }

    const precedingChar = editor.getRange(
      {
        line: startPos.line,
        ch: startPos.ch - 1,
      },
      startPos
    );

    // Short-circuit if `@` as a part of a word (e.g. part of an email address)
    if (precedingChar && /[`a-zA-Z0-9]/.test(precedingChar)) {
      return null;
    }

    return {
      start: startPos,
      end: cursor,
      query: editor.getRange(startPos, cursor).substring(triggerPhrase.length),
    };
  }
Example #24
Source File: Autocomplete.ts    From Templater with GNU Affero General Public License v3.0 6 votes vote down vote up
onTrigger(
        cursor: EditorPosition,
        editor: Editor,
        file: TFile
    ): EditorSuggestTriggerInfo | null {
        const range = editor.getRange(
            { line: cursor.line, ch: 0 },
            { line: cursor.line, ch: cursor.ch }
        );
        const match = this.tp_keyword_regex.exec(range);
        if (!match) {
            return null;
        }

        let query: string;
        const module_name = match.groups["module"] || "";
        this.module_name = module_name;

        if (match.groups["fn_trigger"]) {
            if (module_name == "" || !is_module_name(module_name)) {
                return;
            }
            this.function_trigger = true;
            this.function_name = match.groups["fn"] || "";
            query = this.function_name;
        } else {
            this.function_trigger = false;
            query = this.module_name;
        }

        const trigger_info: EditorSuggestTriggerInfo = {
            start: { line: cursor.line, ch: cursor.ch - query.length },
            end: { line: cursor.line, ch: cursor.ch },
            query: query,
        };
        this.latest_trigger_info = trigger_info;
        return trigger_info;
    }
Example #25
Source File: main.ts    From obsidian-custom-attachment-location with GNU General Public License v3.0 6 votes vote down vote up
async handleDrop(event: DragEvent, editor: Editor, view: MarkdownView){
        console.log('Handle Drop');

        let mdFileName = view.file.basename;
        let mdFolderPath: string = Path.dirname(view.file.path);

        let path = this.getAttachmentFolderPath(mdFileName);
        let fullPath = this.getAttachmentFolderFullPath(mdFolderPath, mdFileName);

        if(!this.useRelativePath && !await this.adapter.exists(fullPath))
            await this.app.vault.createFolder(fullPath);
        
        this.updateAttachmentFolderConfig(path);
    }
Example #26
Source File: ImgurPlugin.ts    From obsidian-imgur-plugin with MIT License 6 votes vote down vote up
private static replaceFirstOccurrence(
    editor: Editor,
    target: string,
    replacement: string
  ) {
    const lines = editor.getValue().split("\n");
    for (let i = 0; i < lines.length; i += 1) {
      const ch = lines[i].indexOf(target);
      if (ch !== -1) {
        const from = { line: i, ch };
        const to = { line: i, ch: ch + target.length };
        editor.replaceRange(replacement, from, to);
        break;
      }
    }
  }
Example #27
Source File: main.ts    From quick_latex_obsidian with MIT License 6 votes vote down vote up
private addMatrixBlock(editor: Editor) {
		const view = this.app.workspace.getActiveViewOfType(MarkdownView);
		if (!view) return;
		if (!this.settings.addMatrixBlock_toggle) return;
		editor.replaceSelection(
			'\\begin{' + this.settings.addMatrixBlock_parameter + '}' +
			'\\end{' + this.settings.addMatrixBlock_parameter + '}'
		);
		const position = editor.getCursor();
		const retract_length = ('\\end{' + this.settings.addMatrixBlock_parameter + '}').length
		editor.setCursor({ line: position.line, ch: position.ch - retract_length })
	}
Example #28
Source File: plugin-callback.ts    From obsidian-imgur-plugin with MIT License 6 votes vote down vote up
editorCheckCallbackFor =
  (size: ImgurSize) => (checking: boolean, editor: Editor) => {
    const lineNumber = editor.getCursor().line;
    const match = findImgurMarkdownImage(
      editor.getLine(lineNumber),
      editor.getCursor().ch
    );

    if (!match.exists) return false;
    if (checking && match.exists) return true;

    let replacement;
    try {
      replacement = resizeTo(size)(match.mdImagePieces);
    } catch (e) {
      if (e instanceof Error)
        // eslint-disable-next-line no-new
        new Notice(e.message);
      // eslint-disable-next-line no-console
      else console.error(e);
      return false;
    }

    editor.replaceRange(
      replacement.content,
      { line: lineNumber, ch: replacement.from },
      { line: lineNumber, ch: replacement.to }
    );
    return true;
  }
Example #29
Source File: main.ts    From quick_latex_obsidian with MIT License 6 votes vote down vote up
private addAlignBlock(editor: Editor) {
		const view = this.app.workspace.getActiveViewOfType(MarkdownView);
		if (!view) return;
		if (!this.settings.addAlignBlock_toggle) return;
		const selected_text = editor.getSelection()
		editor.replaceSelection(
			'\\begin{' + this.settings.addAlignBlock_parameter + '}\n' +
			selected_text +
			'\n\\end{' + this.settings.addAlignBlock_parameter + '}'
		);
		const position = editor.getCursor();
		editor.setCursor({ line: position.line - 1, ch: editor.getLine(position.line - 1).length })
	}