Skip to content

Commit 8807d08

Browse files
committed
docs(verse): add comments to improve code readability
1 parent 706b89d commit 8807d08

File tree

1 file changed

+24
-0
lines changed

1 file changed

+24
-0
lines changed

packages/ui/src/components/verse.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ type ExtractedNotes = {
2929
notes: Record<string, VerseNotes>;
3030
};
3131

32+
/**
33+
* Checks if a node should be excluded from verse text reconstruction.
34+
* Excludes: verse markers (.yv-v), verse labels (.yv-vlbl), headers (.yv-h), and footnotes (.yv-n).
35+
*/
3236
function isExcludedNode(node: Node): boolean {
3337
if (!(node instanceof Element)) return false;
3438
if (node.classList.contains('yv-v') || node.classList.contains('yv-vlbl')) return true;
@@ -37,6 +41,20 @@ function isExcludedNode(node: Node): boolean {
3741
return false;
3842
}
3943

44+
/**
45+
* Extracts footnotes from Bible HTML and prepares data for footnote popovers.
46+
*
47+
* This function does three things:
48+
* 1. Identifies verse boundaries using `.yv-v[v]` markers (verses can span multiple paragraphs)
49+
* 2. For each verse with footnotes, builds a plain-text version with A/B/C markers for the popover
50+
* 3. Inserts placeholder spans at the end of each verse (where the footnote icon will render)
51+
*
52+
* The challenge: verses don't respect paragraph boundaries. A verse starts at `.yv-v[v="X"]`
53+
* and ends at the next `.yv-v[v]` marker, potentially spanning multiple `<div class="p">` elements.
54+
* We use a TreeWalker to flatten the DOM into document order, then use index ranges to define verses.
55+
*
56+
* @returns Modified HTML with footnotes removed and placeholders inserted, plus notes data for popovers
57+
*/
4058
function extractNotesFromHtml(html: string): ExtractedNotes {
4159
if (typeof window === 'undefined') return { html, notes: {} };
4260

@@ -47,6 +65,7 @@ function extractNotesFromHtml(html: string): ExtractedNotes {
4765
const verseMarkers = Array.from(doc.querySelectorAll('.yv-v[v]'));
4866
if (!verseMarkers.length) return { html: doc.body.innerHTML, notes: {} };
4967

68+
// Flatten DOM into document order so we can define verse boundaries by index ranges
5069
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
5170
const allNodes: Node[] = [];
5271
do {
@@ -56,6 +75,7 @@ function extractNotesFromHtml(html: string): ExtractedNotes {
5675
const nodeIndex = new Map(allNodes.map((n, i) => [n, i]));
5776
const footnotes = doc.querySelectorAll('.yv-n.f');
5877

78+
// Define verse boundaries: each verse spans from its marker to the next marker (or end of content)
5979
const verses = verseMarkers.map((marker, i) => {
6080
const nextMarker = verseMarkers[i + 1];
6181
return {
@@ -66,6 +86,7 @@ function extractNotesFromHtml(html: string): ExtractedNotes {
6686
};
6787
});
6888

89+
// Assign each footnote to its containing verse (find verse whose range contains the footnote)
6990
footnotes.forEach((fn) => {
7091
const idx = nodeIndex.get(fn);
7192
if (idx !== undefined) {
@@ -78,6 +99,7 @@ function extractNotesFromHtml(html: string): ExtractedNotes {
7899

79100
const notes: Record<string, VerseNotes> = {};
80101
withNotes.forEach((verse) => {
102+
// Build plain-text verse content for popover, replacing footnotes with A/B/C markers
81103
let text = '';
82104
let noteIdx = 0;
83105
let lastP: Element | null = null;
@@ -101,6 +123,7 @@ function extractNotesFromHtml(html: string): ExtractedNotes {
101123
} else if (node.nodeType === Node.TEXT_NODE && parent) {
102124
if (parent.closest('.yv-h') || parent.closest('.yv-n.f')) continue;
103125
if (parent.classList.contains('yv-v') || parent.classList.contains('yv-vlbl')) continue;
126+
// Add space when transitioning between paragraphs (verses can span multiple <p> elements)
104127
const curP = parent.closest('.p, p, div.p');
105128
if (lastP && curP && lastP !== curP) text += ' ';
106129
text += node.textContent || '';
@@ -110,6 +133,7 @@ function extractNotesFromHtml(html: string): ExtractedNotes {
110133

111134
notes[verse.num] = { verseHtml: text, notes: verse.fns.map((fn) => fn.innerHTML) };
112135

136+
// Insert placeholder at end of verse content (walk backwards to find last text node)
113137
for (let i = verse.end - 1; i > verse.start; i--) {
114138
const node = allNodes[i];
115139
if (!node) continue;

0 commit comments

Comments
 (0)