From 9ae40151db6dbde1e3ba892d50e1093494b6f574 Mon Sep 17 00:00:00 2001 From: lwoodard <92559124+WoodardDigital@users.noreply.github.com> Date: Fri, 15 May 2026 07:52:07 -0600 Subject: [PATCH] Adding bible block method --- src/local-bible-ref-setting-tab.ts | 2 + src/passage-reference.ts | 14 +++-- src/passage-suggest.ts | 94 +++++++++++++++++++++++++----- 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/src/local-bible-ref-setting-tab.ts b/src/local-bible-ref-setting-tab.ts index 559d3a9..d5adeda 100644 --- a/src/local-bible-ref-setting-tab.ts +++ b/src/local-bible-ref-setting-tab.ts @@ -158,6 +158,7 @@ export default class LocalBibleRefSettingTab extends PluginSettingTab { .addOptions({ [BibleFormat.LocalBibleRef]: 'Local Bible Ref', [BibleFormat.BibleLinker]: 'Bible Linker', + [BibleFormat.BlockRef]: 'Block Ref', }) .setValue(this.plugin.settings.bibleFormat) .onChange(async (value) => { @@ -329,4 +330,5 @@ export default class LocalBibleRefSettingTab extends PluginSettingTab { export enum BibleFormat { LocalBibleRef = 'localBibleRef', BibleLinker = 'bibleLinker', + BlockRef = 'blockRef', } diff --git a/src/passage-reference.ts b/src/passage-reference.ts index a68fb9c..d14de43 100644 --- a/src/passage-reference.ts +++ b/src/passage-reference.ts @@ -68,13 +68,15 @@ export default class PassageReference /** Stringifies the passage reference back into text. */ stringify(): string { + const versionSuffix = this.version ? ` - ${this.version}` : ''; + // multi-chapter ref if (this.startVerse === 1 && this.endVerse === -1) { if (this.startChapter === this.endChapter) - return this.book.name + ` ${this.startChapter} - ${this.version}`; + return `${this.book.name} ${this.startChapter}${versionSuffix}`; return ( `${this.book.name} ${this.startChapter}-` + - `${this.endChapter} - ${this.version}` + `${this.endChapter}${versionSuffix}` ); } @@ -82,19 +84,19 @@ export default class PassageReference if (this.startChapter === this.endChapter) { if (this.startVerse === this.endVerse) return ( - this.book.name + - ` ${this.startChapter}:${this.startVerse} - ${this.version}` + `${this.book.name} ${this.startChapter}:` + + `${this.startVerse}${versionSuffix}` ); return ( `${this.book.name} ${this.startChapter}:` + - `${this.startVerse}-${this.endVerse} - ${this.version}` + `${this.startVerse}-${this.endVerse}${versionSuffix}` ); } // multi-chapter-and-verse ref const a = `${this.startChapter}:${this.startVerse}`; const b = `${this.endChapter}:${this.endVerse}`; - return `${this.book.name} ${a}-${b} - ${this.version}`; + return `${this.book.name} ${a}-${b}${versionSuffix}`; } /** diff --git a/src/passage-suggest.ts b/src/passage-suggest.ts index efc9429..aff58e4 100644 --- a/src/passage-suggest.ts +++ b/src/passage-suggest.ts @@ -84,7 +84,7 @@ export default class PassageSuggest extends EditorSuggest { context: EditorSuggestContext ): Promise { let version = this.settings.defaultVersionShorthand; - if (!version) { + if (!version && this.settings.bibleFormat !== BibleFormat.BlockRef) { const folder = this.app.vault.getFolderByPath(this.settings.biblesPath); version = folder?.children?.filter((c) => c instanceof TFolder)?.first()?.name ?? @@ -147,17 +147,24 @@ export default class PassageSuggest extends EditorSuggest { ref: PassageReference ): Promise { let basePath = ''; - for (const alias of [ref.book.name, ...ref.book.aliases]) { - basePath = [this.settings.biblesPath, ref.version, alias].join('/'); - basePath = normalizePath(basePath); - // if the book exists at this alias, use the alias instead - // and add the previous book name to the aliases - if (this.app.vault.getFolderByPath(basePath)) { - ref.book.aliases.push(ref.book.name); - ref.book.aliases.remove(alias); - ref.book.name = alias; - break; + if (this.settings.bibleFormat === BibleFormat.BlockRef) { + const folderPath = this.findBlockRefBookFolder(ref); + if (!folderPath) return null; + basePath = folderPath; + } else { + for (const alias of [ref.book.name, ...ref.book.aliases]) { + basePath = [this.settings.biblesPath, ref.version, alias].join('/'); + basePath = normalizePath(basePath); + + // if the book exists at this alias, use the alias instead + // and add the previous book name to the aliases + if (this.app.vault.getFolderByPath(basePath)) { + ref.book.aliases.push(ref.book.name); + ref.book.aliases.remove(alias); + ref.book.name = alias; + break; + } } } @@ -175,14 +182,55 @@ export default class PassageSuggest extends EditorSuggest { return texts; } + /** + * Locates the book folder under `/ - / - `. + * Updates `ref.book.name` to match the folder's book name on success. + */ + private findBlockRefBookFolder(ref: PassageReference): string | null { + const root = this.app.vault.getFolderByPath(this.settings.biblesPath); + if (!root) return null; + + const candidates = [ref.book.name, ...ref.book.aliases].map((s) => + s.toLowerCase() + ); + + for (const testament of root.children) { + if (!(testament instanceof TFolder)) continue; + + for (const bookFolder of testament.children) { + if (!(bookFolder instanceof TFolder)) continue; + + const match = bookFolder.name.match(/^\d+ - (.+)$/); + if (!match) continue; + + const folderBookName = match[1]; + if (!candidates.includes(folderBookName.toLowerCase())) continue; + + if (folderBookName !== ref.book.name) { + ref.book.aliases.push(ref.book.name); + ref.book.aliases.remove(folderBookName); + ref.book.name = folderBookName; + } + + return bookFolder.path; + } + } + + return null; + } + /** Extracts the text in the chapter from the start verse to the end. */ private getTextFromStartVerse( text: string, ref: PassageReference ): string | null { let pattern = ''; + let flags = ''; if (this.settings.bibleFormat === BibleFormat.BibleLinker) { pattern = `#{1,6} [a-zA-Z]*${ref.startVerse}[a-zA-Z]*\\n\\w+`; + } else if (this.settings.bibleFormat === BibleFormat.BlockRef) { + pattern = `^${ref.startVerse} `; + flags = 'm'; } else { const quoteOrList = '(?:[>-] )*'; const chapterNum = '(?:\\*\\*\\d{1,3}\\*\\* )?'; @@ -190,7 +238,7 @@ export default class PassageSuggest extends EditorSuggest { pattern = quoteOrList + chapterNum + verseNum; } - const regExp = new RegExp(pattern); + const regExp = new RegExp(pattern, flags); const match = text.match(regExp); if (!match) return null; @@ -207,15 +255,19 @@ export default class PassageSuggest extends EditorSuggest { if (ref.endVerse === -1) return text; let pattern = ''; + let flags = ''; if (this.settings.bibleFormat === BibleFormat.BibleLinker) { pattern = `#{1,6} [a-zA-Z]*${ref.endVerse + 1}[a-zA-Z]*\\n\\w+`; + } else if (this.settings.bibleFormat === BibleFormat.BlockRef) { + pattern = `^${ref.endVerse + 1} `; + flags = 'm'; } else { const quoteOrList = '(?:[>-] )*'; const verseNum = `${ref.endVerse + 1}`; pattern = quoteOrList + verseNum; } - const regex = new RegExp(pattern); + const regex = new RegExp(pattern, flags); return text.split(regex, 1)[0].trim(); } @@ -226,6 +278,8 @@ export default class PassageSuggest extends EditorSuggest { ): string { if (this.settings.bibleFormat === BibleFormat.BibleLinker) { text = this.formatBibleLinkerVerses(text); + } else if (this.settings.bibleFormat === BibleFormat.BlockRef) { + text = this.formatBlockRefVerses(text); } text = this.removeChapterNumbers(text); @@ -234,7 +288,10 @@ export default class PassageSuggest extends EditorSuggest { text = this.removeBOF(text); text = this.removeEOF(text); - if (this.settings.bibleFormat === BibleFormat.BibleLinker) { + if ( + this.settings.bibleFormat === BibleFormat.BibleLinker || + this.settings.bibleFormat === BibleFormat.BlockRef + ) { text = this.removeVerseSpacing(text); } @@ -260,6 +317,15 @@ export default class PassageSuggest extends EditorSuggest { ); } + /** Formats verses that use Block Ref formatting. */ + private formatBlockRefVerses(text: string): string { + // strip trailing block IDs (e.g. ` ^1` at end of line) + text = text.replace(/ \^\d+(?=\s|$)/gm, ''); + // convert leading "N " (at line start) to "N " + text = text.replace(/^(\d{1,3}) /gm, '$1 '); + return text; + } + /** Removes chapter numbers from the given text. */ private removeChapterNumbers(text: string): string { return text.replace(/\*\*\d{1,3}\*\* /g, '');