siatko59 downloadsInsert Bible verses from bolls.life as Markdown quotes.
An Obsidian plugin that inserts Bible passages from the free bolls.life API as Markdown quotes, and then goes further: read, annotate and revisit, with colour-coded notes on any verse.
Type a reference, pick a translation, and the passage is inserted at the cursor as a blockquote, one verse per line with a bold verse number:
> **John 3,16** (The Holy Bible, Berean Standard Bible)
>
> **16** For God so loved the world that He gave His one and only Son, that everyone who believes in Him shall not perish but have eternal life.
> **17** For God did not send His Son into the world to condemn the world, but to save the world through Him.
Several references at once, separated by ;:
> **Genesis 1,1** (The Holy Bible, Berean Standard Bible)
>
> **1** In the beginning God created the heavens and the earth.
> **Psalm 23,1** (The Holy Bible, Berean Standard Bible)
>
> **1** The LORD is my shepherd; I shall not want.
A chapter range is expanded into one section per chapter:
> **Psalm 23** (The Holy Bible, Berean Standard Bible)
>
> **1** The LORD is my shepherd; I shall not want.
> **2** He makes me lie down in green pastures.
> **Psalm 24** (The Holy Bible, Berean Standard Bible)
>
> **1** The earth is the LORD's, and everything in it.
Prefer running prose instead of one line per verse? Switch the format:
> **John 3,16** (The Holy Bible, Berean Standard Bible)
>
> **16** For God so loved the world that He gave His one and only Son ...
Want the heading to link back to bolls.life? Turn on the source link:
> [**John 3,16** (The Holy Bible, Berean Standard Bible)](https://bolls.life/BSB/43/3/16/)
>
> **16** For God so loved the world that He gave His one and only Son ...
Annotate any verse and the command creates a note for your thoughts, embedded under the quote as a colour-coded callout:
> **16** For God so loved the world ...
> [!zettel-yellow]
> ![[Bible Notes/John 3,16 (The Holy Bible, Berean Standard Bible)]]
John 3:16, 1 Cor 13, Ps 23, 43 3:16, Gen 1:1).; (John 3:16; Psalm 23).Psalm 3-5), inserted as one section per chapter.Every language available on bolls.life can be selected. The translation list
and book-name matching follow the chosen language, so you can type book names
as that translation writes them (for example Juan, Selon Jean or João).
Books can always be given by their number (1-66).
German and English additionally understand common abbreviations
(Joh, 1 Mos, Psalm, John), independently of the selected translation.
Ctrl/Cmd+P), or assign it a
hotkey under Settings → Hotkeys:Enter.| Input | Meaning |
|---|---|
John 3:16 |
single verse |
John 3:16-18 |
a verse range |
John 3:16.18 |
several single verses |
Psalm 23 |
a whole chapter |
Psalm 3-5 |
a chapter range |
43 3:16 |
book by its number (1-66) |
John 3:16; Psalm 23 |
several references (also with ;) |
The : and , separators are interchangeable (John 3:16 and John 3,16
both work). Book names are matched case-insensitively and ignore dots and
spaces, so
1. Samuel, 1 Samuel and 1sam all resolve to the same book. The heading
shows the book name as the chosen translation writes it.
A chapter range such as Psalm 3-5 is shorthand for Psalm 3; Psalm 4; Psalm 5:
each chapter is inserted as its own section with its own heading, and its
footnotes follow that section. The order is the same whether you write
Psalm 3-5 or Psalm 5-3. A chapter range cannot be combined with a verse
specification (Psalm 3-5:2 is rejected); write the verses per chapter
instead.
The raw bolls.life text is normalized before it is inserted:
[^1]) and the matching
text from bolls.life is appended after each passage's section, with
cross-references linking back to bolls.life. Translations without footnotes
are unaffected.<i>) and bold (<b>/<strong>)
become Markdown *…* and **…**. Any other tags are stripped.…mein Gott!Erleuchte… becomes
…mein Gott! Erleuchte…).[ertönt] becomes \[ertönt\]), so
words the translation added for clarity render literally instead of being
treated as Markdown syntax.| Setting | Description |
|---|---|
| Language | Translation language, and the book names recognized while typing. |
| Translation | bolls.life translation, filtered to the selected language (e.g. S00, LUT; BSB, WEB). |
| Format | Blockquote, bold verse number, One blockquote per verse, Blockquote, running text, or Custom template. |
| Passage template | Template for the Custom template format (see below). Shown only for that format. |
| Verse template | Template applied to each verse in the Custom template format. Shown only for that format. |
| Verse separator | Text placed between verses. Use \n for a line break. Shown only for the Custom template format. |
| Footnotes | Render source footnotes as Markdown footnotes, or strip the markers. |
| Source link | Make the heading itself link to the passage on bolls.life. |
| Parallel translations | Additional translations inserted after the main one, comma-separated (e.g. LUT, ELB). The main translation is always included first (see below). |
| Note folder | Folder for Annotate verse notes, with vault-folder autocomplete. Blank means the vault root. |
| Note format | File name (and optional subfolders) for Annotate verse notes. Placeholders: {title}, {reference}, {translation}, {book}, {chapter}, {verse}, {verses}. A title is only asked for when the format contains {title}. |
| Note opens | Where a new annotation note opens: Split right (default), New tab, or Do not open. |
| Note opens on click | Where an embedded annotation note opens when you click it: Current pane (default, Obsidian's own behaviour), Split right, New tab, or Do not open. |
| Default note color | Colour preselected when creating an annotation note. One of the ten built-in post-it colours. |
With Format → Custom template you control the output yourself. The passage
template is rendered once per passage; {verses} is the verse template applied
to each verse and joined by the verse separator.
| Placeholder | Meaning |
|---|---|
{heading} |
Formatted heading, e.g. **John 3,16** (BSB). |
{reference} |
Reference without markup, e.g. John 3,16. |
{book} |
Book name as the translation writes it. |
{chapter} |
Chapter number. |
{translation} |
Translation code, e.g. BSB. |
{translationName} |
Full translation name. |
{sourceUrl} |
bolls.life URL for the passage. |
{verses} |
All verses (passage template only). |
{number}, {text} |
Verse number and text (verse template only). |
The three presets are just built-in templates; the default custom template
reproduces Blockquote, bold verse number.
The Search Bible (keyword) command searches the whole selected translation for a word or phrase. Matches are listed with their reference and a short text preview in which the search term is highlighted, up to 100 results. Picking one inserts that passage with the current format settings.
The Annotate verse (create note) command lets you attach your own thoughts
to a verse after you have inserted a passage. Put the cursor on the verse you
want to annotate, or select one or more verses, and run the command: it reads
the reference and its heading, creates a note and embeds it in a zettel
callout just below the quote. A selection spanning several verses becomes a
range such as Johannes 3,16-18. A selection that spans several chapters is
split per chapter, so each chapter gets its own note and callout directly below
that chapter's verses, for example Markus 1,43-44 and Lukas 1,1-2 from a
selection over both.
> **16** Denn so hat Gott die Welt geliebt …
> [!zettel-yellow]
> ![[Bible Notes/Johannes 3,16 (Schlachter 2000)]]
The note is embedded inside a zettel-<color> callout, drawn as a post-it with
an always-visible coloured border. When you create a note, the dialog offers a
dropdown of the ten built-in colours and preselects the Default note color:
yellow, orange, red, green, teal, blue, purple, pink, gray and
brown. Each is defined in styles.css, so to use your own colours override
them in a CSS snippet, for example:
body .callout[data-callout="zettel-yellow"] { --callout-color: 212, 160, 23; }.
Where the note goes is set by two settings, like the Daily Notes plugin. The
Note folder field has the same vault-folder autocomplete (blank means the
vault root), and Note format is the file name, which understands {title},
{reference}, {translation}, {book}, {chapter}, {verse} and {verses} and
may contain subfolders, for example {book}/{chapter}/{reference}. The default
format is {title}. When it contains {title} the command asks for a title
(prefilled with the reference and the translation, e.g.
Johannes 3,16 (Schlachter 2000)); without {title} no title is asked and the
note is named from the format.
The quote stays a quote; the embedded note is your commentary and is created
empty, so you just write. The reference already shows as the note title. The note
opens right away, by default in a split to the right (the Note opens setting
switches between split, new tab or not at all). Clicking the embedded note can
open it in a split or a new tab too, via the Note opens on click setting
(Current pane keeps Obsidian's own click behaviour). Because the note is a
normal file
you can also link to it, search it and collect it with backlinks or Dataview. If
a note with that path already exists it is reused, not overwritten. This works
with the Blockquote, bold verse number and One blockquote per verse formats,
which label each verse with **{number}**; the running-text format has no
per-verse line to anchor to.
With a Custom template the command reads the rendered Markdown back, so it
requires the same two patterns: each verse line must contain **{number}** (for
example **16** text) and the passage heading must contain **{reference}**
(optionally followed by (translation), as in **John 3,16** (BSB)). If your
template drops the bold verse number or the bold heading, the command finds no
verse and shows a notice instead. The default custom template keeps both and
works. The callout itself is a self-contained block, so it never swallows the
verses below it, whatever the format.
The Parallel translations setting takes a comma-separated list of
additional translation codes, for example LUT, ELB. The command
Insert Bible quote (parallel translations + main) always inserts the main
translation first, then every listed translation, in the order given. Entering
a single code therefore yields two translations, not one:
Main Translation S00 plus Parallel translations LUT gives:
> **Das Evangelium nach Johannes 3,16** (Schlachter 2000)
>
> **16** Denn so \[sehr\] hat Gott die Welt geliebt, dass er seinen eingeborenen Sohn gab, damit jeder, der an ihn glaubt, nicht verlorengeht, sondern ewiges Leben hat.
> **Johannes 3,16** (Luther (1912))
>
> **16** Also hat Gott die Welt geliebt, daß er seinen eingeborenen Sohn gab, auf daß alle, die an ihn glauben, nicht verloren werden, sondern das ewige Leben haben.
If a listed code equals the main translation, it is inserted only once. Each
translation is inserted with all of its references together, and each
reference's footnotes follow that reference's section. Multiple references are
still separated by ;.
Fetched chapters, book lists and translation metadata are cached and reused on
later runs, so passages you have already looked up work without a connection.
The cache lives in the plugin's own data (data.json) alongside the settings.
It is unlimited and has no expiry. To clear it, remove the cache key from that
file; deleting the whole file also resets the settings.
Copy main.js, manifest.json and styles.css into
<vault>/.obsidian/plugins/simple-bible-fetcher/ and enable the plugin under
Settings → Community plugins.
npm install
npm run build
Then copy the three files above into your vault, or symlink the project folder
into <vault>/.obsidian/plugins/simple-bible-fetcher.
npm install
npm run dev # watch build
npm run build # typecheck + production build
The test suite runs on Vitest with jsdom. The Obsidian
API is replaced by a stub (test/obsidian-stub.ts), and the bolls.life HTTP
layer is driven by fixtures (test/fixtures.ts), so the tests never hit the
network.
npm test # run the suite once
npm run test:watch # watch mode
npm run test:coverage # run with a coverage report
npm run typecheck:test # type-check the tests too
The suite covers reference parsing and book resolution, text cleanup and footnotes, the output presets and the custom template, parallel translations and their footnote placement, keyword search, the persistent cache, settings persistence and the plugin commands, modals and settings tab. Coverage is enforced at 100 % for statements, branches, functions and lines; a drop fails the coverage run.
Because the suite runs against a stub rather than a real vault, it proves the logic, not the Obsidian integration. A manual smoke test in Obsidian is still worth doing before a release.
GPL-3.0-or-later. See LICENSE.