mirror of
https://github.com/skylernorgaard/obsidian-bible-journal-plugin.git
synced 2026-07-22 08:30:44 +00:00
141 lines
3.8 KiB
TypeScript
141 lines
3.8 KiB
TypeScript
import { App, MarkdownView, Notice, TFile, normalizePath } from 'obsidian';
|
|
import type StudyBiblePlugin from './main';
|
|
import * as Utils from './utils';
|
|
import { openStudyNoteFile } from './openStudyNote';
|
|
|
|
type AppWithCommands = App & {
|
|
commands?: { executeCommandById: (id: string) => boolean };
|
|
};
|
|
|
|
async function resolveVersesBlockquote(
|
|
app: App,
|
|
plugin: StudyBiblePlugin,
|
|
book: string,
|
|
chapter: number,
|
|
verseRef: string
|
|
): Promise<string> {
|
|
const chapterPath = normalizePath(
|
|
`${plugin.settings.bibleBooksFolder}/${Utils.bookToDisplayName(book)} ${chapter}.md`
|
|
);
|
|
const chapterFile = app.vault.getAbstractFileByPath(chapterPath);
|
|
if (!(chapterFile instanceof TFile)) {
|
|
return '';
|
|
}
|
|
|
|
const content = await app.vault.read(chapterFile);
|
|
const verses = Utils.extractVersesFromChapterMarkdown(content, verseRef);
|
|
if (!verses) {
|
|
return '';
|
|
}
|
|
|
|
return `${verses} - ${Utils.BIBLE_TRANSLATION_LABEL}`;
|
|
}
|
|
|
|
export async function createStudyNote(
|
|
app: App,
|
|
plugin: StudyBiblePlugin,
|
|
chapterFile: TFile,
|
|
verseRef: string | null,
|
|
onCreated?: (file: TFile) => void,
|
|
title?: string,
|
|
referenceInput?: string
|
|
): Promise<TFile | null> {
|
|
const parsed = Utils.parseBookChapter(chapterFile.basename);
|
|
if (!parsed.book || parsed.chapter <= 0) {
|
|
new Notice('Could not read chapter from file');
|
|
return null;
|
|
}
|
|
|
|
let book = parsed.book;
|
|
let chapter = parsed.chapter;
|
|
let resolvedVerseRef = verseRef;
|
|
|
|
if (referenceInput?.trim()) {
|
|
const refParsed = Utils.parseStudyNoteReferenceInput(referenceInput.trim());
|
|
if (!refParsed) {
|
|
new Notice('Could not read verse reference');
|
|
return null;
|
|
}
|
|
book = refParsed.book;
|
|
chapter = refParsed.chapter;
|
|
resolvedVerseRef = refParsed.verseRef;
|
|
}
|
|
|
|
const notesFolder = plugin.settings.bibleNotesFolder;
|
|
const filename = Utils.buildQuickStudyNoteFilename(
|
|
book,
|
|
chapter,
|
|
resolvedVerseRef,
|
|
title
|
|
);
|
|
const path = normalizePath(`${notesFolder}/${filename}`);
|
|
|
|
if (await app.vault.adapter.exists(path)) {
|
|
new Notice('A note with this name already exists');
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const tags = [Utils.bookToTagName(book)];
|
|
const versesBlockquote =
|
|
resolvedVerseRef?.trim()
|
|
? await resolveVersesBlockquote(app, plugin, book, chapter, resolvedVerseRef)
|
|
: '';
|
|
const body = await Utils.buildStudyNoteBody(app, notesFolder, tags, {
|
|
versesBlockquote,
|
|
});
|
|
const file = await app.vault.create(path, body);
|
|
onCreated?.(file);
|
|
await openStudyNoteFile(app, file, {
|
|
notesFolder,
|
|
resolveReturnChapter: () =>
|
|
Utils.getLastBibleChapter() ?? plugin.getCurrentReaderChapter(),
|
|
});
|
|
if (title?.trim()) {
|
|
await focusJournalBlock(app);
|
|
} else {
|
|
await focusNoteTitle(app);
|
|
}
|
|
return file;
|
|
} catch (error) {
|
|
console.error('Failed to create study note', error);
|
|
new Notice('Could not create study note');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function waitForEditorReady(): Promise<void> {
|
|
await new Promise<void>((resolve) => {
|
|
window.requestAnimationFrame(() => window.requestAnimationFrame(() => resolve()));
|
|
});
|
|
}
|
|
|
|
async function focusJournalBlock(app: App): Promise<void> {
|
|
await waitForEditorReady();
|
|
|
|
const view = app.workspace.getActiveViewOfType(MarkdownView);
|
|
if (!view) {
|
|
return;
|
|
}
|
|
|
|
const content = view.editor.getValue();
|
|
const journalMatch = content.match(/\*\*Thoughts:\s*[\d/]+(?::)?\*\*\s*\n>\s*/);
|
|
if (journalMatch?.index !== undefined) {
|
|
const cursor = journalMatch.index + journalMatch[0].length;
|
|
view.editor.setCursor(view.editor.offsetToPos(cursor));
|
|
view.editor.focus();
|
|
}
|
|
}
|
|
|
|
async function focusNoteTitle(app: App): Promise<void> {
|
|
await waitForEditorReady();
|
|
|
|
const internal = app as AppWithCommands;
|
|
for (const commandId of ['workspace:edit-file-title', 'file-explorer:move-file']) {
|
|
if (internal.commands?.executeCommandById(commandId)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
await focusJournalBlock(app);
|
|
}
|