1 Commits

Author SHA1 Message Date
lwoodard
9ae40151db Adding bible block method 2026-05-15 07:52:07 -06:00
3 changed files with 90 additions and 20 deletions

View File

@@ -158,6 +158,7 @@ export default class LocalBibleRefSettingTab extends PluginSettingTab {
.addOptions({ .addOptions({
[BibleFormat.LocalBibleRef]: 'Local Bible Ref', [BibleFormat.LocalBibleRef]: 'Local Bible Ref',
[BibleFormat.BibleLinker]: 'Bible Linker', [BibleFormat.BibleLinker]: 'Bible Linker',
[BibleFormat.BlockRef]: 'Block Ref',
}) })
.setValue(this.plugin.settings.bibleFormat) .setValue(this.plugin.settings.bibleFormat)
.onChange(async (value) => { .onChange(async (value) => {
@@ -329,4 +330,5 @@ export default class LocalBibleRefSettingTab extends PluginSettingTab {
export enum BibleFormat { export enum BibleFormat {
LocalBibleRef = 'localBibleRef', LocalBibleRef = 'localBibleRef',
BibleLinker = 'bibleLinker', BibleLinker = 'bibleLinker',
BlockRef = 'blockRef',
} }

View File

@@ -68,13 +68,15 @@ export default class PassageReference
/** Stringifies the passage reference back into text. */ /** Stringifies the passage reference back into text. */
stringify(): string { stringify(): string {
const versionSuffix = this.version ? ` - ${this.version}` : '';
// multi-chapter ref // multi-chapter ref
if (this.startVerse === 1 && this.endVerse === -1) { if (this.startVerse === 1 && this.endVerse === -1) {
if (this.startChapter === this.endChapter) if (this.startChapter === this.endChapter)
return this.book.name + ` ${this.startChapter} - ${this.version}`; return `${this.book.name} ${this.startChapter}${versionSuffix}`;
return ( return (
`${this.book.name} ${this.startChapter}-` + `${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.startChapter === this.endChapter) {
if (this.startVerse === this.endVerse) if (this.startVerse === this.endVerse)
return ( return (
this.book.name + `${this.book.name} ${this.startChapter}:` +
` ${this.startChapter}:${this.startVerse} - ${this.version}` `${this.startVerse}${versionSuffix}`
); );
return ( return (
`${this.book.name} ${this.startChapter}:` + `${this.book.name} ${this.startChapter}:` +
`${this.startVerse}-${this.endVerse} - ${this.version}` `${this.startVerse}-${this.endVerse}${versionSuffix}`
); );
} }
// multi-chapter-and-verse ref // multi-chapter-and-verse ref
const a = `${this.startChapter}:${this.startVerse}`; const a = `${this.startChapter}:${this.startVerse}`;
const b = `${this.endChapter}:${this.endVerse}`; const b = `${this.endChapter}:${this.endVerse}`;
return `${this.book.name} ${a}-${b} - ${this.version}`; return `${this.book.name} ${a}-${b}${versionSuffix}`;
} }
/** /**

View File

@@ -84,7 +84,7 @@ export default class PassageSuggest extends EditorSuggest<PassageSuggestion> {
context: EditorSuggestContext context: EditorSuggestContext
): Promise<PassageSuggestion[]> { ): Promise<PassageSuggestion[]> {
let version = this.settings.defaultVersionShorthand; let version = this.settings.defaultVersionShorthand;
if (!version) { if (!version && this.settings.bibleFormat !== BibleFormat.BlockRef) {
const folder = this.app.vault.getFolderByPath(this.settings.biblesPath); const folder = this.app.vault.getFolderByPath(this.settings.biblesPath);
version = version =
folder?.children?.filter((c) => c instanceof TFolder)?.first()?.name ?? folder?.children?.filter((c) => c instanceof TFolder)?.first()?.name ??
@@ -147,6 +147,12 @@ export default class PassageSuggest extends EditorSuggest<PassageSuggestion> {
ref: PassageReference ref: PassageReference
): Promise<string[] | null> { ): Promise<string[] | null> {
let basePath = ''; let basePath = '';
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]) { for (const alias of [ref.book.name, ...ref.book.aliases]) {
basePath = [this.settings.biblesPath, ref.version, alias].join('/'); basePath = [this.settings.biblesPath, ref.version, alias].join('/');
basePath = normalizePath(basePath); basePath = normalizePath(basePath);
@@ -160,6 +166,7 @@ export default class PassageSuggest extends EditorSuggest<PassageSuggestion> {
break; break;
} }
} }
}
const texts: string[] = []; const texts: string[] = [];
@@ -175,14 +182,55 @@ export default class PassageSuggest extends EditorSuggest<PassageSuggestion> {
return texts; return texts;
} }
/**
* Locates the book folder under `<biblesPath>/<N> - <Testament>/<N> - <Book>`.
* 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. */ /** Extracts the text in the chapter from the start verse to the end. */
private getTextFromStartVerse( private getTextFromStartVerse(
text: string, text: string,
ref: PassageReference ref: PassageReference
): string | null { ): string | null {
let pattern = ''; let pattern = '';
let flags = '';
if (this.settings.bibleFormat === BibleFormat.BibleLinker) { if (this.settings.bibleFormat === BibleFormat.BibleLinker) {
pattern = `#{1,6} [a-zA-Z]*${ref.startVerse}[a-zA-Z]*\\n\\w+`; 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 { } else {
const quoteOrList = '(?:[>-] )*'; const quoteOrList = '(?:[>-] )*';
const chapterNum = '(?:\\*\\*\\d{1,3}\\*\\* )?'; const chapterNum = '(?:\\*\\*\\d{1,3}\\*\\* )?';
@@ -190,7 +238,7 @@ export default class PassageSuggest extends EditorSuggest<PassageSuggestion> {
pattern = quoteOrList + chapterNum + verseNum; pattern = quoteOrList + chapterNum + verseNum;
} }
const regExp = new RegExp(pattern); const regExp = new RegExp(pattern, flags);
const match = text.match(regExp); const match = text.match(regExp);
if (!match) return null; if (!match) return null;
@@ -207,15 +255,19 @@ export default class PassageSuggest extends EditorSuggest<PassageSuggestion> {
if (ref.endVerse === -1) return text; if (ref.endVerse === -1) return text;
let pattern = ''; let pattern = '';
let flags = '';
if (this.settings.bibleFormat === BibleFormat.BibleLinker) { if (this.settings.bibleFormat === BibleFormat.BibleLinker) {
pattern = `#{1,6} [a-zA-Z]*${ref.endVerse + 1}[a-zA-Z]*\\n\\w+`; 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 { } else {
const quoteOrList = '(?:[>-] )*'; const quoteOrList = '(?:[>-] )*';
const verseNum = `<sup>${ref.endVerse + 1}</sup>`; const verseNum = `<sup>${ref.endVerse + 1}</sup>`;
pattern = quoteOrList + verseNum; pattern = quoteOrList + verseNum;
} }
const regex = new RegExp(pattern); const regex = new RegExp(pattern, flags);
return text.split(regex, 1)[0].trim(); return text.split(regex, 1)[0].trim();
} }
@@ -226,6 +278,8 @@ export default class PassageSuggest extends EditorSuggest<PassageSuggestion> {
): string { ): string {
if (this.settings.bibleFormat === BibleFormat.BibleLinker) { if (this.settings.bibleFormat === BibleFormat.BibleLinker) {
text = this.formatBibleLinkerVerses(text); text = this.formatBibleLinkerVerses(text);
} else if (this.settings.bibleFormat === BibleFormat.BlockRef) {
text = this.formatBlockRefVerses(text);
} }
text = this.removeChapterNumbers(text); text = this.removeChapterNumbers(text);
@@ -234,7 +288,10 @@ export default class PassageSuggest extends EditorSuggest<PassageSuggestion> {
text = this.removeBOF(text); text = this.removeBOF(text);
text = this.removeEOF(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); text = this.removeVerseSpacing(text);
} }
@@ -260,6 +317,15 @@ export default class PassageSuggest extends EditorSuggest<PassageSuggestion> {
); );
} }
/** 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 "<sup>N</sup> "
text = text.replace(/^(\d{1,3}) /gm, '<sup>$1</sup> ');
return text;
}
/** Removes chapter numbers from the given text. */ /** Removes chapter numbers from the given text. */
private removeChapterNumbers(text: string): string { private removeChapterNumbers(text: string): string {
return text.replace(/\*\*\d{1,3}\*\* /g, ''); return text.replace(/\*\*\d{1,3}\*\* /g, '');