@youversion/platform-core 1.20.2 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,245 @@
1
+ // src/bible-html-transformer.ts
2
+ var NON_BREAKING_SPACE = "\xA0";
3
+ var FOOTNOTE_KEY_ATTR = "data-footnote-key";
4
+ var NEEDS_SPACE_BEFORE = /^[^\s.,;:!?)}\]'"'»›]/;
5
+ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
6
+ "DIV",
7
+ "P",
8
+ "SPAN",
9
+ "SUP",
10
+ "SUB",
11
+ "EM",
12
+ "STRONG",
13
+ "I",
14
+ "B",
15
+ "SMALL",
16
+ "BR",
17
+ "SECTION",
18
+ "TABLE",
19
+ "THEAD",
20
+ "TBODY",
21
+ "TR",
22
+ "TD",
23
+ "TH"
24
+ ]);
25
+ var DROP_ENTIRELY_TAGS = /* @__PURE__ */ new Set([
26
+ "SCRIPT",
27
+ "STYLE",
28
+ "IFRAME",
29
+ "OBJECT",
30
+ "EMBED",
31
+ "SVG",
32
+ "MATH",
33
+ "FORM",
34
+ "INPUT",
35
+ "BUTTON",
36
+ "TEXTAREA",
37
+ "SELECT",
38
+ "TEMPLATE",
39
+ "LINK",
40
+ "META",
41
+ "BASE",
42
+ "NOSCRIPT"
43
+ ]);
44
+ var ALLOWED_ATTRS = /* @__PURE__ */ new Set(["class", "v", "colspan", "rowspan", "dir", "usfm"]);
45
+ function sanitizeBibleHtmlDocument(doc) {
46
+ const root = doc.body ?? doc.documentElement;
47
+ for (const el of Array.from(root.querySelectorAll("*"))) {
48
+ const tag = el.tagName;
49
+ if (DROP_ENTIRELY_TAGS.has(tag)) {
50
+ el.remove();
51
+ continue;
52
+ }
53
+ if (!ALLOWED_TAGS.has(tag)) {
54
+ el.replaceWith(...Array.from(el.childNodes));
55
+ continue;
56
+ }
57
+ for (const attr of Array.from(el.attributes)) {
58
+ const name = attr.name.toLowerCase();
59
+ if (name.startsWith("on")) {
60
+ el.removeAttribute(attr.name);
61
+ continue;
62
+ }
63
+ if (!ALLOWED_ATTRS.has(name) && !name.startsWith("data-")) {
64
+ el.removeAttribute(attr.name);
65
+ }
66
+ }
67
+ }
68
+ }
69
+ function wrapVerseContent(doc) {
70
+ function wrapParagraphContent(doc2, paragraph, verseNum) {
71
+ const children = Array.from(paragraph.childNodes);
72
+ if (children.length === 0) return;
73
+ const wrapper = doc2.createElement("span");
74
+ wrapper.className = "yv-v";
75
+ wrapper.setAttribute("v", verseNum);
76
+ const firstChild = children[0];
77
+ if (firstChild) {
78
+ paragraph.insertBefore(wrapper, firstChild);
79
+ }
80
+ children.forEach((child) => {
81
+ wrapper.appendChild(child);
82
+ });
83
+ }
84
+ function wrapParagraphsUntilBoundary(doc2, verseNum, startParagraph, endParagraph) {
85
+ if (!startParagraph) return;
86
+ let currentParagraph = startParagraph.nextElementSibling;
87
+ while (currentParagraph && currentParagraph !== endParagraph) {
88
+ const isHeading = currentParagraph.classList.contains("yv-h") || currentParagraph.matches(
89
+ ".s1, .s2, .s3, .s4, .ms, .ms1, .ms2, .ms3, .ms4, .mr, .sp, .sr, .qa, .r"
90
+ );
91
+ if (isHeading) {
92
+ currentParagraph = currentParagraph.nextElementSibling;
93
+ continue;
94
+ }
95
+ if (currentParagraph.querySelector(".yv-v[v]")) break;
96
+ if (currentParagraph.classList.contains("p") || currentParagraph.tagName === "P") {
97
+ wrapParagraphContent(doc2, currentParagraph, verseNum);
98
+ }
99
+ currentParagraph = currentParagraph.nextElementSibling;
100
+ }
101
+ }
102
+ function handleParagraphWrapping(doc2, currentParagraph, nextParagraph, verseNum) {
103
+ if (!currentParagraph) return;
104
+ if (!nextParagraph) {
105
+ wrapParagraphsUntilBoundary(doc2, verseNum, currentParagraph);
106
+ return;
107
+ }
108
+ if (currentParagraph !== nextParagraph) {
109
+ wrapParagraphsUntilBoundary(doc2, verseNum, currentParagraph, nextParagraph);
110
+ }
111
+ }
112
+ function processVerseMarker(marker, index, markers) {
113
+ const verseNum = marker.getAttribute("v");
114
+ if (!verseNum) return;
115
+ const nextMarker = markers[index + 1];
116
+ const nodesToWrap = collectNodesBetweenMarkers(marker, nextMarker);
117
+ if (nodesToWrap.length === 0) return;
118
+ const currentParagraph = marker.closest(".p, p, div.p");
119
+ const nextParagraph = nextMarker?.closest(".p, p, div.p") || null;
120
+ const doc2 = marker.ownerDocument;
121
+ wrapNodesInVerse(marker, verseNum, nodesToWrap);
122
+ handleParagraphWrapping(doc2, currentParagraph, nextParagraph, verseNum);
123
+ }
124
+ function wrapNodesInVerse(marker, verseNum, nodes) {
125
+ const wrapper = marker.ownerDocument.createElement("span");
126
+ wrapper.className = "yv-v";
127
+ wrapper.setAttribute("v", verseNum);
128
+ const firstNode = nodes[0];
129
+ if (firstNode) {
130
+ marker.parentNode?.insertBefore(wrapper, firstNode);
131
+ }
132
+ nodes.forEach((node) => {
133
+ wrapper.appendChild(node);
134
+ });
135
+ marker.remove();
136
+ }
137
+ function shouldStopCollecting(node, endMarker) {
138
+ if (node === endMarker) return true;
139
+ if (endMarker && node.nodeType === 1 && node.contains(endMarker)) return true;
140
+ return false;
141
+ }
142
+ function shouldSkipNode(node) {
143
+ return node.nodeType === 1 && node.classList.contains("yv-h");
144
+ }
145
+ function collectNodesBetweenMarkers(startMarker, endMarker) {
146
+ const nodes = [];
147
+ let current = startMarker.nextSibling;
148
+ while (current && !shouldStopCollecting(current, endMarker)) {
149
+ if (shouldSkipNode(current)) {
150
+ current = current.nextSibling;
151
+ continue;
152
+ }
153
+ nodes.push(current);
154
+ current = current.nextSibling;
155
+ }
156
+ return nodes;
157
+ }
158
+ const verseMarkers = Array.from(doc.querySelectorAll(".yv-v[v]"));
159
+ verseMarkers.forEach(processVerseMarker);
160
+ }
161
+ function assignFootnoteKeys(doc) {
162
+ let introIdx = 0;
163
+ doc.querySelectorAll(".yv-n.f").forEach((fn) => {
164
+ const verseNum = fn.closest(".yv-v[v]")?.getAttribute("v");
165
+ fn.setAttribute(FOOTNOTE_KEY_ATTR, verseNum ?? `intro-${introIdx++}`);
166
+ });
167
+ }
168
+ function replaceFootnotesWithAnchors(doc, footnotes) {
169
+ for (const fn of footnotes) {
170
+ const key = fn.getAttribute(FOOTNOTE_KEY_ATTR);
171
+ if (!key) continue;
172
+ const prev = fn.previousSibling;
173
+ const next = fn.nextSibling;
174
+ const prevText = prev?.textContent ?? "";
175
+ const nextText = next?.textContent ?? "";
176
+ const prevNeedsSpace = prevText.length > 0 && !/\s$/.test(prevText);
177
+ const nextNeedsSpace = nextText.length > 0 && NEEDS_SPACE_BEFORE.test(nextText);
178
+ if (prevNeedsSpace && nextNeedsSpace && fn.parentNode) {
179
+ fn.parentNode.insertBefore(doc.createTextNode(" "), fn);
180
+ }
181
+ const anchor = doc.createElement("span");
182
+ anchor.setAttribute("data-verse-footnote", key);
183
+ anchor.setAttribute("data-verse-footnote-content", fn.innerHTML);
184
+ fn.replaceWith(anchor);
185
+ }
186
+ }
187
+ function addNbspToVerseLabels(doc) {
188
+ doc.querySelectorAll(".yv-vlbl").forEach((label) => {
189
+ const text = label.textContent || "";
190
+ if (!text.endsWith(NON_BREAKING_SPACE)) {
191
+ label.textContent = text + NON_BREAKING_SPACE;
192
+ }
193
+ });
194
+ }
195
+ function fixIrregularTables(doc) {
196
+ doc.querySelectorAll("table").forEach((table) => {
197
+ const rows = table.querySelectorAll("tr");
198
+ if (rows.length === 0) return;
199
+ let maxColumns = 0;
200
+ rows.forEach((row) => {
201
+ let count = 0;
202
+ row.querySelectorAll("td, th").forEach((cell) => {
203
+ count += parseInt(cell.getAttribute("colspan") || "1", 10);
204
+ });
205
+ maxColumns = Math.max(maxColumns, count);
206
+ });
207
+ if (maxColumns > 1) {
208
+ rows.forEach((row) => {
209
+ const cells = row.querySelectorAll("td, th");
210
+ if (cells.length === 1) {
211
+ const existing = parseInt(cells[0].getAttribute("colspan") || "1", 10);
212
+ if (existing < maxColumns) {
213
+ cells[0].setAttribute("colspan", maxColumns.toString());
214
+ }
215
+ }
216
+ });
217
+ }
218
+ });
219
+ }
220
+ function transformBibleHtml(html, options) {
221
+ const doc = options.parseHtml(html);
222
+ sanitizeBibleHtmlDocument(doc);
223
+ wrapVerseContent(doc);
224
+ assignFootnoteKeys(doc);
225
+ const footnotes = Array.from(doc.querySelectorAll(".yv-n.f"));
226
+ replaceFootnotesWithAnchors(doc, footnotes);
227
+ addNbspToVerseLabels(doc);
228
+ fixIrregularTables(doc);
229
+ const transformedHtml = options.serializeHtml(doc);
230
+ return { html: transformedHtml };
231
+ }
232
+ function transformBibleHtmlForBrowser(html) {
233
+ if (typeof globalThis.DOMParser === "undefined") {
234
+ throw new Error("DOMParser is required to transform Bible HTML in browser environments");
235
+ }
236
+ return transformBibleHtml(html, {
237
+ parseHtml: (h) => new DOMParser().parseFromString(h, "text/html"),
238
+ serializeHtml: (doc) => doc.body.innerHTML
239
+ });
240
+ }
241
+
242
+ export {
243
+ transformBibleHtml,
244
+ transformBibleHtmlForBrowser
245
+ };
package/dist/index.cjs CHANGED
@@ -36,7 +36,8 @@ __export(index_exports, {
36
36
  YouVersionAPIUsers: () => YouVersionAPIUsers,
37
37
  YouVersionPlatformConfiguration: () => YouVersionPlatformConfiguration,
38
38
  YouVersionUserInfo: () => YouVersionUserInfo,
39
- getAdjacentChapter: () => getAdjacentChapter
39
+ getAdjacentChapter: () => getAdjacentChapter,
40
+ transformBibleHtml: () => transformBibleHtml
40
41
  });
41
42
  module.exports = __toCommonJS(index_exports);
42
43
 
@@ -789,12 +790,18 @@ var BibleClient = class _BibleClient {
789
790
  /**
790
791
  * Fetches a passage (range of verses) from the Bible using the passages endpoint.
791
792
  * This is the new API format that returns HTML-formatted content.
793
+ *
794
+ * Note: The HTML returned from the API contains inline footnote content that should
795
+ * be transformed before rendering. Use `transformBibleHtml()` or
796
+ * `transformBibleHtmlForBrowser()` to clean up the HTML and extract footnotes.
797
+ *
792
798
  * @param versionId The version ID.
793
799
  * @param usfm The USFM reference (e.g., "JHN.3.1-2", "GEN.1", "JHN.3.16").
794
800
  * @param format The format to return ("html" or "text", default: "html").
795
801
  * @param include_headings Whether to include headings in the content.
796
802
  * @param include_notes Whether to include notes in the content.
797
803
  * @returns The requested BiblePassage object with HTML content.
804
+ *
798
805
  * @example
799
806
  * ```ts
800
807
  * // Get a single verse
@@ -805,6 +812,10 @@ var BibleClient = class _BibleClient {
805
812
  *
806
813
  * // Get an entire chapter
807
814
  * const chapter = await bibleClient.getPassage(3034, "GEN.1");
815
+ *
816
+ * // Transform HTML before rendering
817
+ * const passage = await bibleClient.getPassage(3034, "JHN.3.16", "html", true, true);
818
+ * const transformed = transformBibleHtmlForBrowser(passage.content);
808
819
  * ```
809
820
  */
810
821
  async getPassage(versionId, usfm, format = "html", include_headings, include_notes) {
@@ -1732,6 +1743,238 @@ function lastCanonicalOfPreviousBook(books, bookIndex) {
1732
1743
  }
1733
1744
  return null;
1734
1745
  }
1746
+
1747
+ // src/bible-html-transformer.ts
1748
+ var NON_BREAKING_SPACE = "\xA0";
1749
+ var FOOTNOTE_KEY_ATTR = "data-footnote-key";
1750
+ var NEEDS_SPACE_BEFORE = /^[^\s.,;:!?)}\]'"'»›]/;
1751
+ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
1752
+ "DIV",
1753
+ "P",
1754
+ "SPAN",
1755
+ "SUP",
1756
+ "SUB",
1757
+ "EM",
1758
+ "STRONG",
1759
+ "I",
1760
+ "B",
1761
+ "SMALL",
1762
+ "BR",
1763
+ "SECTION",
1764
+ "TABLE",
1765
+ "THEAD",
1766
+ "TBODY",
1767
+ "TR",
1768
+ "TD",
1769
+ "TH"
1770
+ ]);
1771
+ var DROP_ENTIRELY_TAGS = /* @__PURE__ */ new Set([
1772
+ "SCRIPT",
1773
+ "STYLE",
1774
+ "IFRAME",
1775
+ "OBJECT",
1776
+ "EMBED",
1777
+ "SVG",
1778
+ "MATH",
1779
+ "FORM",
1780
+ "INPUT",
1781
+ "BUTTON",
1782
+ "TEXTAREA",
1783
+ "SELECT",
1784
+ "TEMPLATE",
1785
+ "LINK",
1786
+ "META",
1787
+ "BASE",
1788
+ "NOSCRIPT"
1789
+ ]);
1790
+ var ALLOWED_ATTRS = /* @__PURE__ */ new Set(["class", "v", "colspan", "rowspan", "dir", "usfm"]);
1791
+ function sanitizeBibleHtmlDocument(doc) {
1792
+ const root = doc.body ?? doc.documentElement;
1793
+ for (const el of Array.from(root.querySelectorAll("*"))) {
1794
+ const tag = el.tagName;
1795
+ if (DROP_ENTIRELY_TAGS.has(tag)) {
1796
+ el.remove();
1797
+ continue;
1798
+ }
1799
+ if (!ALLOWED_TAGS.has(tag)) {
1800
+ el.replaceWith(...Array.from(el.childNodes));
1801
+ continue;
1802
+ }
1803
+ for (const attr of Array.from(el.attributes)) {
1804
+ const name = attr.name.toLowerCase();
1805
+ if (name.startsWith("on")) {
1806
+ el.removeAttribute(attr.name);
1807
+ continue;
1808
+ }
1809
+ if (!ALLOWED_ATTRS.has(name) && !name.startsWith("data-")) {
1810
+ el.removeAttribute(attr.name);
1811
+ }
1812
+ }
1813
+ }
1814
+ }
1815
+ function wrapVerseContent(doc) {
1816
+ function wrapParagraphContent(doc2, paragraph, verseNum) {
1817
+ const children = Array.from(paragraph.childNodes);
1818
+ if (children.length === 0) return;
1819
+ const wrapper = doc2.createElement("span");
1820
+ wrapper.className = "yv-v";
1821
+ wrapper.setAttribute("v", verseNum);
1822
+ const firstChild = children[0];
1823
+ if (firstChild) {
1824
+ paragraph.insertBefore(wrapper, firstChild);
1825
+ }
1826
+ children.forEach((child) => {
1827
+ wrapper.appendChild(child);
1828
+ });
1829
+ }
1830
+ function wrapParagraphsUntilBoundary(doc2, verseNum, startParagraph, endParagraph) {
1831
+ if (!startParagraph) return;
1832
+ let currentParagraph = startParagraph.nextElementSibling;
1833
+ while (currentParagraph && currentParagraph !== endParagraph) {
1834
+ const isHeading = currentParagraph.classList.contains("yv-h") || currentParagraph.matches(
1835
+ ".s1, .s2, .s3, .s4, .ms, .ms1, .ms2, .ms3, .ms4, .mr, .sp, .sr, .qa, .r"
1836
+ );
1837
+ if (isHeading) {
1838
+ currentParagraph = currentParagraph.nextElementSibling;
1839
+ continue;
1840
+ }
1841
+ if (currentParagraph.querySelector(".yv-v[v]")) break;
1842
+ if (currentParagraph.classList.contains("p") || currentParagraph.tagName === "P") {
1843
+ wrapParagraphContent(doc2, currentParagraph, verseNum);
1844
+ }
1845
+ currentParagraph = currentParagraph.nextElementSibling;
1846
+ }
1847
+ }
1848
+ function handleParagraphWrapping(doc2, currentParagraph, nextParagraph, verseNum) {
1849
+ if (!currentParagraph) return;
1850
+ if (!nextParagraph) {
1851
+ wrapParagraphsUntilBoundary(doc2, verseNum, currentParagraph);
1852
+ return;
1853
+ }
1854
+ if (currentParagraph !== nextParagraph) {
1855
+ wrapParagraphsUntilBoundary(doc2, verseNum, currentParagraph, nextParagraph);
1856
+ }
1857
+ }
1858
+ function processVerseMarker(marker, index, markers) {
1859
+ const verseNum = marker.getAttribute("v");
1860
+ if (!verseNum) return;
1861
+ const nextMarker = markers[index + 1];
1862
+ const nodesToWrap = collectNodesBetweenMarkers(marker, nextMarker);
1863
+ if (nodesToWrap.length === 0) return;
1864
+ const currentParagraph = marker.closest(".p, p, div.p");
1865
+ const nextParagraph = nextMarker?.closest(".p, p, div.p") || null;
1866
+ const doc2 = marker.ownerDocument;
1867
+ wrapNodesInVerse(marker, verseNum, nodesToWrap);
1868
+ handleParagraphWrapping(doc2, currentParagraph, nextParagraph, verseNum);
1869
+ }
1870
+ function wrapNodesInVerse(marker, verseNum, nodes) {
1871
+ const wrapper = marker.ownerDocument.createElement("span");
1872
+ wrapper.className = "yv-v";
1873
+ wrapper.setAttribute("v", verseNum);
1874
+ const firstNode = nodes[0];
1875
+ if (firstNode) {
1876
+ marker.parentNode?.insertBefore(wrapper, firstNode);
1877
+ }
1878
+ nodes.forEach((node) => {
1879
+ wrapper.appendChild(node);
1880
+ });
1881
+ marker.remove();
1882
+ }
1883
+ function shouldStopCollecting(node, endMarker) {
1884
+ if (node === endMarker) return true;
1885
+ if (endMarker && node.nodeType === 1 && node.contains(endMarker)) return true;
1886
+ return false;
1887
+ }
1888
+ function shouldSkipNode(node) {
1889
+ return node.nodeType === 1 && node.classList.contains("yv-h");
1890
+ }
1891
+ function collectNodesBetweenMarkers(startMarker, endMarker) {
1892
+ const nodes = [];
1893
+ let current = startMarker.nextSibling;
1894
+ while (current && !shouldStopCollecting(current, endMarker)) {
1895
+ if (shouldSkipNode(current)) {
1896
+ current = current.nextSibling;
1897
+ continue;
1898
+ }
1899
+ nodes.push(current);
1900
+ current = current.nextSibling;
1901
+ }
1902
+ return nodes;
1903
+ }
1904
+ const verseMarkers = Array.from(doc.querySelectorAll(".yv-v[v]"));
1905
+ verseMarkers.forEach(processVerseMarker);
1906
+ }
1907
+ function assignFootnoteKeys(doc) {
1908
+ let introIdx = 0;
1909
+ doc.querySelectorAll(".yv-n.f").forEach((fn) => {
1910
+ const verseNum = fn.closest(".yv-v[v]")?.getAttribute("v");
1911
+ fn.setAttribute(FOOTNOTE_KEY_ATTR, verseNum ?? `intro-${introIdx++}`);
1912
+ });
1913
+ }
1914
+ function replaceFootnotesWithAnchors(doc, footnotes) {
1915
+ for (const fn of footnotes) {
1916
+ const key = fn.getAttribute(FOOTNOTE_KEY_ATTR);
1917
+ if (!key) continue;
1918
+ const prev = fn.previousSibling;
1919
+ const next = fn.nextSibling;
1920
+ const prevText = prev?.textContent ?? "";
1921
+ const nextText = next?.textContent ?? "";
1922
+ const prevNeedsSpace = prevText.length > 0 && !/\s$/.test(prevText);
1923
+ const nextNeedsSpace = nextText.length > 0 && NEEDS_SPACE_BEFORE.test(nextText);
1924
+ if (prevNeedsSpace && nextNeedsSpace && fn.parentNode) {
1925
+ fn.parentNode.insertBefore(doc.createTextNode(" "), fn);
1926
+ }
1927
+ const anchor = doc.createElement("span");
1928
+ anchor.setAttribute("data-verse-footnote", key);
1929
+ anchor.setAttribute("data-verse-footnote-content", fn.innerHTML);
1930
+ fn.replaceWith(anchor);
1931
+ }
1932
+ }
1933
+ function addNbspToVerseLabels(doc) {
1934
+ doc.querySelectorAll(".yv-vlbl").forEach((label) => {
1935
+ const text = label.textContent || "";
1936
+ if (!text.endsWith(NON_BREAKING_SPACE)) {
1937
+ label.textContent = text + NON_BREAKING_SPACE;
1938
+ }
1939
+ });
1940
+ }
1941
+ function fixIrregularTables(doc) {
1942
+ doc.querySelectorAll("table").forEach((table) => {
1943
+ const rows = table.querySelectorAll("tr");
1944
+ if (rows.length === 0) return;
1945
+ let maxColumns = 0;
1946
+ rows.forEach((row) => {
1947
+ let count = 0;
1948
+ row.querySelectorAll("td, th").forEach((cell) => {
1949
+ count += parseInt(cell.getAttribute("colspan") || "1", 10);
1950
+ });
1951
+ maxColumns = Math.max(maxColumns, count);
1952
+ });
1953
+ if (maxColumns > 1) {
1954
+ rows.forEach((row) => {
1955
+ const cells = row.querySelectorAll("td, th");
1956
+ if (cells.length === 1) {
1957
+ const existing = parseInt(cells[0].getAttribute("colspan") || "1", 10);
1958
+ if (existing < maxColumns) {
1959
+ cells[0].setAttribute("colspan", maxColumns.toString());
1960
+ }
1961
+ }
1962
+ });
1963
+ }
1964
+ });
1965
+ }
1966
+ function transformBibleHtml(html, options) {
1967
+ const doc = options.parseHtml(html);
1968
+ sanitizeBibleHtmlDocument(doc);
1969
+ wrapVerseContent(doc);
1970
+ assignFootnoteKeys(doc);
1971
+ const footnotes = Array.from(doc.querySelectorAll(".yv-n.f"));
1972
+ replaceFootnotesWithAnchors(doc, footnotes);
1973
+ addNbspToVerseLabels(doc);
1974
+ fixIrregularTables(doc);
1975
+ const transformedHtml = options.serializeHtml(doc);
1976
+ return { html: transformedHtml };
1977
+ }
1735
1978
  // Annotate the CommonJS export names for ESM import in node:
1736
1979
  0 && (module.exports = {
1737
1980
  ApiClient,
@@ -1750,5 +1993,6 @@ function lastCanonicalOfPreviousBook(books, bookIndex) {
1750
1993
  YouVersionAPIUsers,
1751
1994
  YouVersionPlatformConfiguration,
1752
1995
  YouVersionUserInfo,
1753
- getAdjacentChapter
1996
+ getAdjacentChapter,
1997
+ transformBibleHtml
1754
1998
  });
package/dist/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ export { a as TransformBibleHtmlOptions, T as TransformedBibleHtml, t as transformBibleHtml } from './browser-DzQ1yOHv.cjs';
2
3
 
3
4
  declare const SignInWithYouVersionPermission: {
4
5
  readonly bibles: "bibles";
@@ -390,12 +391,18 @@ declare class BibleClient {
390
391
  /**
391
392
  * Fetches a passage (range of verses) from the Bible using the passages endpoint.
392
393
  * This is the new API format that returns HTML-formatted content.
394
+ *
395
+ * Note: The HTML returned from the API contains inline footnote content that should
396
+ * be transformed before rendering. Use `transformBibleHtml()` or
397
+ * `transformBibleHtmlForBrowser()` to clean up the HTML and extract footnotes.
398
+ *
393
399
  * @param versionId The version ID.
394
400
  * @param usfm The USFM reference (e.g., "JHN.3.1-2", "GEN.1", "JHN.3.16").
395
401
  * @param format The format to return ("html" or "text", default: "html").
396
402
  * @param include_headings Whether to include headings in the content.
397
403
  * @param include_notes Whether to include notes in the content.
398
404
  * @returns The requested BiblePassage object with HTML content.
405
+ *
399
406
  * @example
400
407
  * ```ts
401
408
  * // Get a single verse
@@ -406,6 +413,10 @@ declare class BibleClient {
406
413
  *
407
414
  * // Get an entire chapter
408
415
  * const chapter = await bibleClient.getPassage(3034, "GEN.1");
416
+ *
417
+ * // Transform HTML before rendering
418
+ * const passage = await bibleClient.getPassage(3034, "JHN.3.16", "html", true, true);
419
+ * const transformed = transformBibleHtmlForBrowser(passage.content);
409
420
  * ```
410
421
  */
411
422
  getPassage(versionId: number, usfm: string, format?: 'html' | 'text', include_headings?: boolean, include_notes?: boolean): Promise<BiblePassage>;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ export { a as TransformBibleHtmlOptions, T as TransformedBibleHtml, t as transformBibleHtml } from './browser-DzQ1yOHv.js';
2
3
 
3
4
  declare const SignInWithYouVersionPermission: {
4
5
  readonly bibles: "bibles";
@@ -390,12 +391,18 @@ declare class BibleClient {
390
391
  /**
391
392
  * Fetches a passage (range of verses) from the Bible using the passages endpoint.
392
393
  * This is the new API format that returns HTML-formatted content.
394
+ *
395
+ * Note: The HTML returned from the API contains inline footnote content that should
396
+ * be transformed before rendering. Use `transformBibleHtml()` or
397
+ * `transformBibleHtmlForBrowser()` to clean up the HTML and extract footnotes.
398
+ *
393
399
  * @param versionId The version ID.
394
400
  * @param usfm The USFM reference (e.g., "JHN.3.1-2", "GEN.1", "JHN.3.16").
395
401
  * @param format The format to return ("html" or "text", default: "html").
396
402
  * @param include_headings Whether to include headings in the content.
397
403
  * @param include_notes Whether to include notes in the content.
398
404
  * @returns The requested BiblePassage object with HTML content.
405
+ *
399
406
  * @example
400
407
  * ```ts
401
408
  * // Get a single verse
@@ -406,6 +413,10 @@ declare class BibleClient {
406
413
  *
407
414
  * // Get an entire chapter
408
415
  * const chapter = await bibleClient.getPassage(3034, "GEN.1");
416
+ *
417
+ * // Transform HTML before rendering
418
+ * const passage = await bibleClient.getPassage(3034, "JHN.3.16", "html", true, true);
419
+ * const transformed = transformBibleHtmlForBrowser(passage.content);
409
420
  * ```
410
421
  */
411
422
  getPassage(versionId: number, usfm: string, format?: 'html' | 'text', include_headings?: boolean, include_notes?: boolean): Promise<BiblePassage>;
package/dist/index.js CHANGED
@@ -1,3 +1,7 @@
1
+ import {
2
+ transformBibleHtml
3
+ } from "./chunk-2Z2S2WY3.js";
4
+
1
5
  // src/client.ts
2
6
  var ApiClient = class {
3
7
  baseURL;
@@ -747,12 +751,18 @@ var BibleClient = class _BibleClient {
747
751
  /**
748
752
  * Fetches a passage (range of verses) from the Bible using the passages endpoint.
749
753
  * This is the new API format that returns HTML-formatted content.
754
+ *
755
+ * Note: The HTML returned from the API contains inline footnote content that should
756
+ * be transformed before rendering. Use `transformBibleHtml()` or
757
+ * `transformBibleHtmlForBrowser()` to clean up the HTML and extract footnotes.
758
+ *
750
759
  * @param versionId The version ID.
751
760
  * @param usfm The USFM reference (e.g., "JHN.3.1-2", "GEN.1", "JHN.3.16").
752
761
  * @param format The format to return ("html" or "text", default: "html").
753
762
  * @param include_headings Whether to include headings in the content.
754
763
  * @param include_notes Whether to include notes in the content.
755
764
  * @returns The requested BiblePassage object with HTML content.
765
+ *
756
766
  * @example
757
767
  * ```ts
758
768
  * // Get a single verse
@@ -763,6 +773,10 @@ var BibleClient = class _BibleClient {
763
773
  *
764
774
  * // Get an entire chapter
765
775
  * const chapter = await bibleClient.getPassage(3034, "GEN.1");
776
+ *
777
+ * // Transform HTML before rendering
778
+ * const passage = await bibleClient.getPassage(3034, "JHN.3.16", "html", true, true);
779
+ * const transformed = transformBibleHtmlForBrowser(passage.content);
766
780
  * ```
767
781
  */
768
782
  async getPassage(versionId, usfm, format = "html", include_headings, include_notes) {
@@ -1707,5 +1721,6 @@ export {
1707
1721
  YouVersionAPIUsers,
1708
1722
  YouVersionPlatformConfiguration,
1709
1723
  YouVersionUserInfo,
1710
- getAdjacentChapter
1724
+ getAdjacentChapter,
1725
+ transformBibleHtml
1711
1726
  };