Hi,
I’m currently using ConText to render a Bible translation to PDF, with chapter and verse numbers in a sidebar rather than inline. You can see that I mean in this PDF:
Typst seems an interesting system to potentially add as a backend renderer, is this sort of layout currently possible?
It’s possible, but the implementation depends on your needs.
I guess you want the numbers to be identical with those on openenglishbible.org, rather than calculating numbers by a fragile self-developed and untested verse splitting algorithm?
If so, you have to come up with a way to mark the numbers.
Do you have any source text? What’s it like?
The source text is in a standard lightweight markup format for biblical texts (USFM). There is a Python framework which parses that, then renders into PDF (via ConText), RTF, HTML, ePub etc.
The tricky bit in ConText at least is taking something like “we saw that \v 6 the sky was blue and \v 7 the grass was green” and rendering the verse markers ‘6’ and ‘7’ appropriately in the sidebar rather than inline.
You’re right that I’m not amazingly keen on “calculating numbers by a fragile self-developed and untested verse splitting algorithm” :)
18 This was how the birth of Jesus Christ
took place. His mother Mary was engaged
to Joseph, but before they were married,
she found out that she was going to have
19 a baby by the Holy Spirit. Joseph was a
B:
18 This was how the birth of Jesus Christ
took place. His mother Mary was engaged
to Joseph, but before they were married,
she found out that she was going to have
a baby by the Holy Spirit.
19 Joseph was a…
C:
18 This was how the birth of Jesus Christ
took place. His mother Mary was engaged
to Joseph, but before they were married,
she found out that she was going
to have a baby by the Holy Spirit.
19 Joseph was a…
The result in the documentation you found is the most common way of rendering - the verse markers are done as small inline numbers. However I’m after the rendering in your first option (ie no artificial line break on the verse break).
The question of what to do if say \v 6 and \v 7 are on the same line is tricky. It can be fixed manually in the TeX, but I haven’t found a good automatic solution in ConText and have just let the numbers overlap in the sidebar in an ugly manner - luckily collisions are rare.
The ideal would be to have the sidebar show both numbers separated by a comma, eg
she found out that she was going to have
6, 7 a baby by the Holy Spirit. Joseph was a
To explain more clearly, I’ve attached a scan of sample page from another Bible from 1960 showing the same style. Of course that wasn’t automatically typeset by computer!
Here is a simple attempt at achieving what you are after. It uses marginalia to do the heavy lifting. The regex pattern may need some tweaking depending on the exact text you are dealing with, and performance may be terrible if you are trying to compile the entire Bible at once.
#import "@preview/marginalia:0.2.3" as marginalia: note, notefigure, wideblock
#show regex("v \d+"): it => {
linebreak()
show "v ": ""
note.with(
side: "left",
numbering: none,
shift: false
)(it)
}
we saw that \v 6 the sky was blue and \v 7 the grass was green
\v 18 This was how the birth of Jesus Christ took place. His mother Mary was engaged to Joseph, but before they were married, she found out that she was going to have a baby by the Holy Spirit. \v 19 Joseph was a
#set page(height: auto, width: 300pt, margin: 15pt)
#let make-bible(usfm) = {
show regex(`\\v \d+\s*`.text): it => context box(place(
bottom + start,
dx: 10pt - here().position().x,
dy: -0.3em,
align(right, box(width: 0pt, {
set text(0.6em)
it.text.replace(`\v `.text, "").trim()
})),
))
usfm.replace(regex(`\r?\n`.text), " ")
}
#make-bible(
```
\v 1 I put the text in a raw block to avoid unexpected escaping sequences.
\v 2 Ideally, you should read it from a file.
\v 3 Refer to the documentation for details.
\v 4 https://typst.app/docs/reference/data-loading/read/
\v 18 This was how the birth of Jesus Christ took place. His mother Mary was engaged
to Joseph, but before they were married, she found out that she was going to have a
baby by the Holy Spirit.
\v 19 Joseph was a man who always did what was right, but he did not want to disgrace
Mary publicly; so he made plans to break the engagement privately.
```.text,
)
#set page(height: auto, width: 350pt, margin: (left: 40pt, right: 15pt))
#let make-bible(usfm) = {
show regex(`\\v \d+\s*`.text): it => [#metadata(
it.text.replace(`\v `.text, "").trim(),
)<verse>]
set par.line(numbering: _ => {
let this-line = here().position().y
let last-line = this-line - par.leading.to-absolute() - text.size / 2
let numbers = query(<verse>)
.filter(verse => {
let y = verse.location().position().y
last-line < y and y <= this-line
})
.map(verse => verse.value)
// The height should be a fixed value, or the box will affect `here().position()`.
// This circular dependency will cause the layout to fail to converge.
box(height: 0pt, align(bottom, {
super(numbers.join(", "))
}))
})
usfm.replace(regex(`\r?\n`.text), " ")
}
#make-bible(
```
\v 1 I put the text in a raw block to avoid unexpected escaping sequences.
\v 2 Ideally, you should read it from a file.
\v 3 Refer to the documentation for details.
\v 4 https://typst.app/docs/reference/data-loading/read/
\v 18 This was how the birth of Jesus Christ took place. His mother Mary was engaged
to Joseph, but before they were married, she found out that she was going to have a
baby by the Holy Spirit.
\v 19 Joseph was a man who always did what was right, but he did not want to disgrace
Mary publicly; so he made plans to break the engagement privately.
```.text,
)
This isn’t a good idea, something like a function #vs(6) would be better. \v 6 is just v 6, so your solution with text like “Aviv 6” produces unexpected results:
Something like this works, however:
#import "@preview/marginalia:0.2.3" as marginalia: note, notefigure, wideblock
#let vs(n) = {
linebreak()
note(
side: "left",
numbering: none,
shift: false,
[#n]
)
// Don't add unnecessary spacing afterwards
h(0pt, weak: true)
}
we saw that Aviv 6 the sky was blue #vs(6) and I couldn't agree more #vs(7) with this
There are multiple answers which show that typst has the abilities I’m after and point me towards how to build a solution - should I mark more than one?
True, the regex pattern catches too many things and would need improvement to be usable.
I agree that using a function is much better than trying to catch and act on the \v # pattern, but it seemed like the text would come as-is with the pattern. If that is the case then a pre-process step could easily convert a file with \v 6 style verse markers into a file with function calls (ie #v(6)) and then compile the resulting file in Typst.
This thread has got me curious how long it would take to compile all books of the Bible as a single PDF. But not curious enough to actually test it .
As I said above, I suggest read the USFM from files.
In this way, the regex(`\\v \d+\s*`.text) is no longer a problem.
Unfortunately, it’s impossible.
I’ve encountered a similar situation. I suggest choosing the option you finally used.
If you have mixed multiple options or made significant improvements yourself, you can describe it and mark your own post as the answer.
In any case, it’s important to mark the question as answered. You can use to thank other replies.