@youversion/platform-react-ui 1.14.3 → 1.15.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.
- package/dist/components/bible-card.d.ts +8 -0
- package/dist/components/bible-card.d.ts.map +1 -0
- package/dist/components/bible-version-picker.d.ts.map +1 -1
- package/dist/components/bible-widget-view.d.ts +10 -7
- package/dist/components/bible-widget-view.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/verse.d.ts.map +1 -1
- package/dist/index.cjs +178 -174
- package/dist/index.js +185 -182
- package/dist/lib/verse-html-utils.d.ts +20 -20
- package/dist/lib/verse-html-utils.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type BibleCardProps = {
|
|
2
|
+
reference: string;
|
|
3
|
+
versionId: number;
|
|
4
|
+
background?: 'light' | 'dark';
|
|
5
|
+
showVersionPicker?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function BibleCard({ reference, versionId, background, showVersionPicker, }: BibleCardProps): React.ReactNode;
|
|
8
|
+
//# sourceMappingURL=bible-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bible-card.d.ts","sourceRoot":"","sources":["../../src/components/bible-card.tsx"],"names":[],"mappings":"AAQA,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AACF,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,SAAS,EACT,UAAU,EACV,iBAAyB,GAC1B,EAAE,cAAc,GAAG,KAAK,CAAC,SAAS,CAmElC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bible-version-picker.d.ts","sourceRoot":"","sources":["../../src/components/bible-version-picker.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,2BAA2B,CAAC;AASxE,OAAO,EAEL,KAAK,SAAS,EAOf,MAAM,OAAO,CAAC;AASf,OAAO,EAA2B,cAAc,EAAE,MAAM,cAAc,CAAC;AAGvE,eAAO,MAAM,mBAAmB,+CAA+C,CAAC;AAqIhF,MAAM,MAAM,SAAS,GAAG;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,iBAAS,IAAI,CAAC,EACZ,SAAS,EAAE,mBAAmB,EAC9B,eAAe,EACf,UAAU,EACV,IAAY,EACZ,QAAQ,GACT,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"bible-version-picker.d.ts","sourceRoot":"","sources":["../../src/components/bible-version-picker.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,2BAA2B,CAAC;AASxE,OAAO,EAEL,KAAK,SAAS,EAOf,MAAM,OAAO,CAAC;AASf,OAAO,EAA2B,cAAc,EAAE,MAAM,cAAc,CAAC;AAGvE,eAAO,MAAM,mBAAmB,+CAA+C,CAAC;AAqIhF,MAAM,MAAM,SAAS,GAAG;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,iBAAS,IAAI,CAAC,EACZ,SAAS,EAAE,mBAAmB,EAC9B,eAAe,EACf,UAAU,EACV,IAAY,EACZ,QAAQ,GACT,EAAE,SAAS,2CA+IX;AAED,MAAM,MAAM,8BAA8B,GAAG,IAAI,CAC/C,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,EAC3C,UAAU,CACX,GAAG;IACF,QAAQ,CAAC,EACL,KAAK,CAAC,SAAS,GACf,CAAC,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;CACtF,CAAC;AAEF,iBAAS,OAAO,CAAC,EAAE,OAAc,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,8BAA8B,2CAkBtF;AAED,iBAAS,OAAO,4CAsTf;AAED,eAAO,MAAM,kBAAkB;;;;CAAgD,CAAC;AAChF,MAAM,MAAM,2BAA2B,GAAG,SAAS,CAAC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { BibleCard } from './bible-card';
|
|
2
|
+
import type { BibleCardProps } from './bible-card';
|
|
3
|
+
/**
|
|
4
|
+
* @deprecated Use `BibleCardProps` instead. This type alias will be removed in a future major version.
|
|
5
|
+
*/
|
|
6
|
+
export type BibleWidgetViewProps = BibleCardProps;
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Use `BibleCard` instead. This component will be removed in a future major version.
|
|
9
|
+
*/
|
|
10
|
+
export declare const BibleWidgetView: typeof BibleCard;
|
|
8
11
|
//# sourceMappingURL=bible-widget-view.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bible-widget-view.d.ts","sourceRoot":"","sources":["../../src/components/bible-widget-view.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bible-widget-view.d.ts","sourceRoot":"","sources":["../../src/components/bible-widget-view.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,eAAe,kBAAY,CAAC"}
|
|
@@ -4,5 +4,6 @@ export { BibleVersionPicker, type BibleVersionPickerRootProps, type BibleVersion
|
|
|
4
4
|
export { YouVersionAuthButton, type YouVersionAuthButtonProps } from './YouVersionAuthButton';
|
|
5
5
|
export { VerseOfTheDay, type VerseOfTheDayProps } from './verse-of-the-day';
|
|
6
6
|
export { BibleTextView, type BibleTextViewProps } from './verse';
|
|
7
|
+
export { BibleCard, type BibleCardProps } from './bible-card';
|
|
7
8
|
export { BibleWidgetView, type BibleWidgetViewProps } from './bible-widget-view';
|
|
8
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC/F,OAAO,EAAE,WAAW,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACL,kBAAkB,EAClB,KAAK,2BAA2B,EAChC,KAAK,8BAA8B,GACpC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC/F,OAAO,EAAE,WAAW,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACL,kBAAkB,EAClB,KAAK,2BAA2B,EAChC,KAAK,8BAA8B,GACpC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verse.d.ts","sourceRoot":"","sources":["../../src/components/verse.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verse.d.ts","sourceRoot":"","sources":["../../src/components/verse.tsx"],"names":[],"mappings":"AAcA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,wBAAwB,CAAC;AA6JhC;;GAEG;AACH,KAAK,UAAU,GAAG;IAChB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,KAAK;IAChB;;;;;;;;OAQG;mCACwC,UAAU,KAAG,KAAK,CAAC,YAAY;;CAwE3E,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,qJAY3B,kBAAkB,KAAG,KAAK,CAAC,YA2D7B,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
ApiClient: () => ApiClient,
|
|
36
36
|
BOOK_CANON: () => BOOK_CANON,
|
|
37
37
|
BOOK_IDS: () => BOOK_IDS,
|
|
38
|
+
BibleCard: () => BibleCard,
|
|
38
39
|
BibleChapterPicker: () => BibleChapterPicker,
|
|
39
40
|
BibleClient: () => BibleClient,
|
|
40
41
|
BibleReader: () => BibleReader,
|
|
@@ -15139,7 +15140,17 @@ function Root5({
|
|
|
15139
15140
|
const [searchQuery, setSearchQuery] = (0, import_react2.useState)("");
|
|
15140
15141
|
const [isLanguagesOpen, setIsLanguagesOpen] = (0, import_react2.useState)(false);
|
|
15141
15142
|
const [recentVersions, setRecentVersions] = (0, import_react2.useState)(getRecentVersions);
|
|
15142
|
-
const [isPopoverOpen,
|
|
15143
|
+
const [isPopoverOpen, setIsPopoverOpenRaw] = (0, import_react2.useState)(false);
|
|
15144
|
+
const setIsPopoverOpen = (0, import_react2.useCallback)(
|
|
15145
|
+
(open) => {
|
|
15146
|
+
setIsPopoverOpenRaw(open);
|
|
15147
|
+
if (!open) {
|
|
15148
|
+
setSearchQuery("");
|
|
15149
|
+
setIsLanguagesOpen(false);
|
|
15150
|
+
}
|
|
15151
|
+
},
|
|
15152
|
+
[setSearchQuery]
|
|
15153
|
+
);
|
|
15143
15154
|
const addRecentVersion = (0, import_react2.useCallback)((version2) => {
|
|
15144
15155
|
setRecentVersions((prev) => {
|
|
15145
15156
|
const filtered = prev.filter((v) => v.id !== version2.id);
|
|
@@ -15569,13 +15580,24 @@ function PersonIcon(props) {
|
|
|
15569
15580
|
|
|
15570
15581
|
// src/components/verse.tsx
|
|
15571
15582
|
var import_platform_react_hooks3 = require("@youversion/platform-react-hooks");
|
|
15572
|
-
var import_isomorphic_dompurify = __toESM(require("isomorphic-dompurify"), 1);
|
|
15573
15583
|
var import_react3 = require("react");
|
|
15574
15584
|
var import_react_dom = require("react-dom");
|
|
15575
15585
|
|
|
15576
15586
|
// src/lib/verse-html-utils.ts
|
|
15587
|
+
var import_isomorphic_dompurify = __toESM(require("isomorphic-dompurify"), 1);
|
|
15577
15588
|
var NON_BREAKING_SPACE = "\xA0";
|
|
15578
15589
|
var LETTERS = "abcdefghijklmnopqrstuvwxyz";
|
|
15590
|
+
function getFootnoteMarker(index) {
|
|
15591
|
+
const base = LETTERS.length;
|
|
15592
|
+
if (base === 0) return String(index + 1);
|
|
15593
|
+
let value = index;
|
|
15594
|
+
let marker = "";
|
|
15595
|
+
do {
|
|
15596
|
+
marker = LETTERS[value % base] + marker;
|
|
15597
|
+
value = Math.floor(value / base) - 1;
|
|
15598
|
+
} while (value >= 0);
|
|
15599
|
+
return marker;
|
|
15600
|
+
}
|
|
15579
15601
|
var INTER_FONT = '"Inter", sans-serif';
|
|
15580
15602
|
var SOURCE_SERIF_FONT = '"Source Serif 4", serif';
|
|
15581
15603
|
function wrapVerseContent(doc) {
|
|
@@ -15668,73 +15690,125 @@ function wrapVerseContent(doc) {
|
|
|
15668
15690
|
const verseMarkers = Array.from(doc.querySelectorAll(".yv-v[v]"));
|
|
15669
15691
|
verseMarkers.forEach(processVerseMarker);
|
|
15670
15692
|
}
|
|
15693
|
+
var NEEDS_SPACE_BEFORE = /^[^\s.,;:!?)}\]'"»›]/;
|
|
15694
|
+
function buildVerseHtml(wrappers) {
|
|
15695
|
+
const parts = [];
|
|
15696
|
+
let noteIdx = 0;
|
|
15697
|
+
for (let i = 0; i < wrappers.length; i++) {
|
|
15698
|
+
if (i > 0) parts.push(" ");
|
|
15699
|
+
const clone2 = wrappers[i].cloneNode(true);
|
|
15700
|
+
const ownerDoc = wrappers[i].ownerDocument;
|
|
15701
|
+
clone2.querySelectorAll(".yv-h, .yv-vlbl").forEach((el) => el.remove());
|
|
15702
|
+
clone2.querySelectorAll(".yv-n.f").forEach((fn) => {
|
|
15703
|
+
const marker = ownerDoc.createElement("sup");
|
|
15704
|
+
marker.className = "yv:text-muted-foreground";
|
|
15705
|
+
marker.textContent = getFootnoteMarker(noteIdx++);
|
|
15706
|
+
fn.replaceWith(marker);
|
|
15707
|
+
});
|
|
15708
|
+
parts.push(clone2.innerHTML);
|
|
15709
|
+
}
|
|
15710
|
+
return parts.join("");
|
|
15711
|
+
}
|
|
15712
|
+
function replaceFootnotesWithAnchors(doc, footnotes) {
|
|
15713
|
+
for (const fn of footnotes) {
|
|
15714
|
+
const verseNum = fn.closest(".yv-v[v]")?.getAttribute("v");
|
|
15715
|
+
if (!verseNum) continue;
|
|
15716
|
+
const prev = fn.previousSibling;
|
|
15717
|
+
const next = fn.nextSibling;
|
|
15718
|
+
const prevText = prev?.textContent ?? "";
|
|
15719
|
+
const nextText = next?.textContent ?? "";
|
|
15720
|
+
const prevNeedsSpace = prevText.length > 0 && !/\s$/.test(prevText);
|
|
15721
|
+
const nextNeedsSpace = nextText.length > 0 && NEEDS_SPACE_BEFORE.test(nextText);
|
|
15722
|
+
if (prevNeedsSpace && nextNeedsSpace && fn.parentNode) {
|
|
15723
|
+
fn.parentNode.insertBefore(doc.createTextNode(" "), fn);
|
|
15724
|
+
}
|
|
15725
|
+
const anchor = doc.createElement("span");
|
|
15726
|
+
anchor.setAttribute("data-verse-footnote", verseNum);
|
|
15727
|
+
fn.replaceWith(anchor);
|
|
15728
|
+
}
|
|
15729
|
+
}
|
|
15671
15730
|
function extractNotesFromWrappedHtml(doc) {
|
|
15672
15731
|
const footnotes = Array.from(doc.querySelectorAll(".yv-n.f"));
|
|
15673
15732
|
if (!footnotes.length) return {};
|
|
15674
15733
|
const footnotesByVerse = /* @__PURE__ */ new Map();
|
|
15675
|
-
|
|
15734
|
+
for (const fn of footnotes) {
|
|
15676
15735
|
const verseNum = fn.closest(".yv-v[v]")?.getAttribute("v");
|
|
15677
|
-
if (verseNum)
|
|
15678
|
-
|
|
15679
|
-
|
|
15680
|
-
|
|
15681
|
-
|
|
15682
|
-
}
|
|
15683
|
-
arr.push(fn);
|
|
15736
|
+
if (!verseNum) continue;
|
|
15737
|
+
let arr = footnotesByVerse.get(verseNum);
|
|
15738
|
+
if (!arr) {
|
|
15739
|
+
arr = [];
|
|
15740
|
+
footnotesByVerse.set(verseNum, arr);
|
|
15684
15741
|
}
|
|
15742
|
+
arr.push(fn);
|
|
15743
|
+
}
|
|
15744
|
+
const wrappersByVerse = /* @__PURE__ */ new Map();
|
|
15745
|
+
doc.querySelectorAll(".yv-v[v]").forEach((el) => {
|
|
15746
|
+
const verseNum = el.getAttribute("v");
|
|
15747
|
+
if (!verseNum) return;
|
|
15748
|
+
const arr = wrappersByVerse.get(verseNum);
|
|
15749
|
+
if (arr) arr.push(el);
|
|
15750
|
+
else wrappersByVerse.set(verseNum, [el]);
|
|
15685
15751
|
});
|
|
15686
15752
|
const notes = {};
|
|
15687
|
-
const
|
|
15688
|
-
footnotesByVerse.forEach((fns, verseNum) => {
|
|
15689
|
-
const verseWrappers = Array.from(doc.querySelectorAll(`.yv-v[v="${verseNum}"]`));
|
|
15690
|
-
let verseHtml = "";
|
|
15691
|
-
let noteIdx = 0;
|
|
15692
|
-
verseWrappers.forEach((wrapper, wrapperIdx) => {
|
|
15693
|
-
if (wrapperIdx > 0) verseHtml += " ";
|
|
15694
|
-
const walker = doc.createTreeWalker(wrapper, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
|
|
15695
|
-
let lastWasFootnote = false;
|
|
15696
|
-
while (walker.nextNode()) {
|
|
15697
|
-
const node = walker.currentNode;
|
|
15698
|
-
if (node instanceof Element) {
|
|
15699
|
-
if (node.classList.contains("yv-n") && node.classList.contains("f")) {
|
|
15700
|
-
verseHtml += `<sup class="yv:text-muted-foreground">${LETTERS[noteIdx++] || noteIdx}</sup>`;
|
|
15701
|
-
lastWasFootnote = true;
|
|
15702
|
-
}
|
|
15703
|
-
} else if (node.nodeType === Node.TEXT_NODE) {
|
|
15704
|
-
const parent = node.parentElement;
|
|
15705
|
-
if (parent?.closest(".yv-n.f") || parent?.closest(".yv-h")) continue;
|
|
15706
|
-
if (parent?.classList.contains("yv-vlbl")) continue;
|
|
15707
|
-
let text = node.textContent || "";
|
|
15708
|
-
if (lastWasFootnote && text && NEEDS_SPACE_BEFORE.test(text)) {
|
|
15709
|
-
text = " " + text;
|
|
15710
|
-
}
|
|
15711
|
-
verseHtml += text;
|
|
15712
|
-
lastWasFootnote = false;
|
|
15713
|
-
}
|
|
15714
|
-
}
|
|
15715
|
-
});
|
|
15753
|
+
for (const [verseNum, fns] of footnotesByVerse) {
|
|
15716
15754
|
notes[verseNum] = {
|
|
15717
|
-
verseHtml,
|
|
15755
|
+
verseHtml: buildVerseHtml(wrappersByVerse.get(verseNum) ?? []),
|
|
15718
15756
|
notes: fns.map((fn) => fn.innerHTML)
|
|
15719
15757
|
};
|
|
15720
|
-
|
|
15721
|
-
|
|
15722
|
-
|
|
15723
|
-
|
|
15724
|
-
|
|
15758
|
+
}
|
|
15759
|
+
replaceFootnotesWithAnchors(doc, footnotes);
|
|
15760
|
+
return notes;
|
|
15761
|
+
}
|
|
15762
|
+
function addNbspToVerseLabels(doc) {
|
|
15763
|
+
doc.querySelectorAll(".yv-vlbl").forEach((label) => {
|
|
15764
|
+
const text = label.textContent || "";
|
|
15765
|
+
if (!text.endsWith(NON_BREAKING_SPACE)) {
|
|
15766
|
+
label.textContent = text + NON_BREAKING_SPACE;
|
|
15725
15767
|
}
|
|
15726
15768
|
});
|
|
15727
|
-
|
|
15728
|
-
|
|
15729
|
-
|
|
15730
|
-
const
|
|
15731
|
-
|
|
15732
|
-
|
|
15733
|
-
|
|
15769
|
+
}
|
|
15770
|
+
function fixIrregularTables(doc) {
|
|
15771
|
+
doc.querySelectorAll("table").forEach((table) => {
|
|
15772
|
+
const rows = table.querySelectorAll("tr");
|
|
15773
|
+
if (rows.length === 0) return;
|
|
15774
|
+
let maxColumns = 0;
|
|
15775
|
+
rows.forEach((row) => {
|
|
15776
|
+
let count = 0;
|
|
15777
|
+
row.querySelectorAll("td, th").forEach((cell) => {
|
|
15778
|
+
count += cell instanceof HTMLTableCellElement ? parseInt(cell.getAttribute("colspan") || "1", 10) : 1;
|
|
15779
|
+
});
|
|
15780
|
+
maxColumns = Math.max(maxColumns, count);
|
|
15781
|
+
});
|
|
15782
|
+
if (maxColumns > 1) {
|
|
15783
|
+
rows.forEach((row) => {
|
|
15784
|
+
const cells = row.querySelectorAll("td, th");
|
|
15785
|
+
if (cells.length === 1 && cells[0] instanceof HTMLTableCellElement) {
|
|
15786
|
+
const existing = parseInt(cells[0].getAttribute("colspan") || "1", 10);
|
|
15787
|
+
if (existing < maxColumns) {
|
|
15788
|
+
cells[0].setAttribute("colspan", maxColumns.toString());
|
|
15789
|
+
}
|
|
15790
|
+
}
|
|
15791
|
+
});
|
|
15734
15792
|
}
|
|
15735
|
-
fn.remove();
|
|
15736
15793
|
});
|
|
15737
|
-
|
|
15794
|
+
}
|
|
15795
|
+
var DOMPURIFY_CONFIG = {
|
|
15796
|
+
ALLOWED_ATTR: ["class", "style", "id", "v", "usfm"],
|
|
15797
|
+
ALLOW_DATA_ATTR: true
|
|
15798
|
+
};
|
|
15799
|
+
function transformBibleHtml(html) {
|
|
15800
|
+
if (typeof window === "undefined" || !("DOMParser" in window)) {
|
|
15801
|
+
return { html, notes: {} };
|
|
15802
|
+
}
|
|
15803
|
+
const doc = new DOMParser().parseFromString(
|
|
15804
|
+
import_isomorphic_dompurify.default.sanitize(html, DOMPURIFY_CONFIG),
|
|
15805
|
+
"text/html"
|
|
15806
|
+
);
|
|
15807
|
+
wrapVerseContent(doc);
|
|
15808
|
+
const notes = extractNotesFromWrappedHtml(doc);
|
|
15809
|
+
addNbspToVerseLabels(doc);
|
|
15810
|
+
fixIrregularTables(doc);
|
|
15811
|
+
return { html: doc.body.innerHTML, notes };
|
|
15738
15812
|
}
|
|
15739
15813
|
|
|
15740
15814
|
// src/components/icons/footnote.tsx
|
|
@@ -15795,20 +15869,23 @@ var VerseFootnoteButton = (0, import_react3.memo)(function VerseFootnoteButton2(
|
|
|
15795
15869
|
dangerouslySetInnerHTML: { __html: verseNotes.verseHtml }
|
|
15796
15870
|
}
|
|
15797
15871
|
),
|
|
15798
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "yv:list-none yv:p-0 yv:m-0 yv:space-y-1", children: verseNotes.notes.map((note, index) =>
|
|
15799
|
-
|
|
15800
|
-
|
|
15801
|
-
|
|
15802
|
-
|
|
15803
|
-
|
|
15804
|
-
|
|
15805
|
-
|
|
15806
|
-
|
|
15807
|
-
|
|
15808
|
-
|
|
15809
|
-
|
|
15810
|
-
|
|
15811
|
-
|
|
15872
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "yv:list-none yv:p-0 yv:m-0 yv:space-y-1", children: verseNotes.notes.map((note, index) => {
|
|
15873
|
+
const marker = getFootnoteMarker(index);
|
|
15874
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
15875
|
+
"li",
|
|
15876
|
+
{
|
|
15877
|
+
className: "yv:flex yv:gap-2 yv:text-xs yv:border-b yv:border-border yv:py-2",
|
|
15878
|
+
children: [
|
|
15879
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "", children: [
|
|
15880
|
+
marker,
|
|
15881
|
+
"."
|
|
15882
|
+
] }),
|
|
15883
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { dangerouslySetInnerHTML: { __html: note } })
|
|
15884
|
+
]
|
|
15885
|
+
},
|
|
15886
|
+
marker
|
|
15887
|
+
);
|
|
15888
|
+
}) })
|
|
15812
15889
|
] })
|
|
15813
15890
|
}
|
|
15814
15891
|
)
|
|
@@ -15825,57 +15902,39 @@ function BibleTextHtml({
|
|
|
15825
15902
|
highlightedVerses = {}
|
|
15826
15903
|
}) {
|
|
15827
15904
|
const contentRef = (0, import_react3.useRef)(null);
|
|
15828
|
-
const [placeholders, setPlaceholders] = (0, import_react3.useState)(
|
|
15905
|
+
const [placeholders, setPlaceholders] = (0, import_react3.useState)([]);
|
|
15829
15906
|
const providerTheme = (0, import_platform_react_hooks3.useTheme)();
|
|
15830
15907
|
const currentTheme = theme || providerTheme;
|
|
15831
15908
|
(0, import_react3.useLayoutEffect)(() => {
|
|
15832
15909
|
if (!contentRef.current) return;
|
|
15833
15910
|
contentRef.current.innerHTML = html;
|
|
15834
|
-
const
|
|
15835
|
-
|
|
15836
|
-
|
|
15837
|
-
|
|
15911
|
+
const anchors = contentRef.current.querySelectorAll("[data-verse-footnote]");
|
|
15912
|
+
const result = [];
|
|
15913
|
+
anchors.forEach((el) => {
|
|
15914
|
+
const verseNum = el.getAttribute("data-verse-footnote");
|
|
15915
|
+
if (verseNum) result.push({ verseNum, el });
|
|
15838
15916
|
});
|
|
15839
|
-
setPlaceholders(
|
|
15840
|
-
}, [html
|
|
15917
|
+
setPlaceholders(result);
|
|
15918
|
+
}, [html]);
|
|
15841
15919
|
(0, import_react3.useLayoutEffect)(() => {
|
|
15842
15920
|
if (!contentRef.current) return;
|
|
15843
|
-
|
|
15844
|
-
verseElements.forEach((el) => {
|
|
15921
|
+
contentRef.current.querySelectorAll(".yv-v[v]").forEach((el) => {
|
|
15845
15922
|
const verseNum = parseInt(el.getAttribute("v") || "0", 10);
|
|
15846
|
-
|
|
15847
|
-
|
|
15848
|
-
} else {
|
|
15849
|
-
el.classList.remove("yv-v-selected");
|
|
15850
|
-
}
|
|
15851
|
-
if (highlightedVerses[verseNum]) {
|
|
15852
|
-
el.classList.add("yv-v-highlighted");
|
|
15853
|
-
} else {
|
|
15854
|
-
el.classList.remove("yv-v-highlighted");
|
|
15855
|
-
}
|
|
15923
|
+
el.classList.toggle("yv-v-selected", selectedVerses.includes(verseNum));
|
|
15924
|
+
el.classList.toggle("yv-v-highlighted", !!highlightedVerses[verseNum]);
|
|
15856
15925
|
});
|
|
15857
15926
|
}, [html, selectedVerses, highlightedVerses]);
|
|
15858
|
-
const
|
|
15859
|
-
|
|
15860
|
-
|
|
15861
|
-
const
|
|
15862
|
-
if (!
|
|
15863
|
-
const
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
if (!verseEl) return;
|
|
15867
|
-
const verseNum = parseInt(verseEl.getAttribute("v") || "0", 10);
|
|
15868
|
-
if (verseNum === 0) return;
|
|
15869
|
-
const current = selectedVersesRef.current;
|
|
15870
|
-
const newSelected = current.includes(verseNum) ? current.filter((v) => v !== verseNum) : [...current, verseNum].sort((a, b) => a - b);
|
|
15871
|
-
onVerseSelect(newSelected);
|
|
15872
|
-
};
|
|
15873
|
-
element.addEventListener("click", handleClick);
|
|
15874
|
-
return () => element.removeEventListener("click", handleClick);
|
|
15875
|
-
}, [onVerseSelect]);
|
|
15927
|
+
const handleClick = onVerseSelect ? (e) => {
|
|
15928
|
+
const verseEl = e.target.closest(".yv-v[v]");
|
|
15929
|
+
if (!verseEl) return;
|
|
15930
|
+
const verseNum = parseInt(verseEl.getAttribute("v") || "0", 10);
|
|
15931
|
+
if (!verseNum) return;
|
|
15932
|
+
const newSelected = selectedVerses.includes(verseNum) ? selectedVerses.filter((v) => v !== verseNum) : [...selectedVerses, verseNum].sort((a, b) => a - b);
|
|
15933
|
+
onVerseSelect(newSelected);
|
|
15934
|
+
} : void 0;
|
|
15876
15935
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
15877
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { ref: contentRef }),
|
|
15878
|
-
|
|
15936
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { ref: contentRef, onClick: handleClick }),
|
|
15937
|
+
placeholders.map(({ verseNum, el }, index) => {
|
|
15879
15938
|
const verseNotes = notes[verseNum];
|
|
15880
15939
|
if (!verseNotes) return null;
|
|
15881
15940
|
return (0, import_react_dom.createPortal)(
|
|
@@ -15889,68 +15948,12 @@ function BibleTextHtml({
|
|
|
15889
15948
|
theme: currentTheme
|
|
15890
15949
|
}
|
|
15891
15950
|
),
|
|
15892
|
-
el
|
|
15951
|
+
el,
|
|
15952
|
+
`${verseNum}-${index}`
|
|
15893
15953
|
);
|
|
15894
15954
|
})
|
|
15895
15955
|
] });
|
|
15896
15956
|
}
|
|
15897
|
-
var DOMPURIFY_CONFIG = {
|
|
15898
|
-
ALLOWED_ATTR: ["class", "style", "id", "v", "usfm"],
|
|
15899
|
-
ALLOW_DATA_ATTR: true
|
|
15900
|
-
};
|
|
15901
|
-
function yvDomTransformer(html, extractNotes = false) {
|
|
15902
|
-
if (typeof window === "undefined" || !("DOMParser" in window)) {
|
|
15903
|
-
return { html, notes: {} };
|
|
15904
|
-
}
|
|
15905
|
-
const doc = new DOMParser().parseFromString(
|
|
15906
|
-
import_isomorphic_dompurify.default.sanitize(html, DOMPURIFY_CONFIG),
|
|
15907
|
-
"text/html"
|
|
15908
|
-
);
|
|
15909
|
-
wrapVerseContent(doc);
|
|
15910
|
-
const extractedNotes = extractNotes ? extractNotesFromWrappedHtml(doc) : {};
|
|
15911
|
-
const verseLabels = doc.querySelectorAll(".yv-vlbl");
|
|
15912
|
-
verseLabels.forEach((label) => {
|
|
15913
|
-
const text = label.textContent || "";
|
|
15914
|
-
if (!text.endsWith(NON_BREAKING_SPACE)) {
|
|
15915
|
-
label.textContent = text + NON_BREAKING_SPACE;
|
|
15916
|
-
}
|
|
15917
|
-
});
|
|
15918
|
-
const tables = doc.querySelectorAll("table");
|
|
15919
|
-
tables.forEach((table) => {
|
|
15920
|
-
const rows = table.querySelectorAll("tr");
|
|
15921
|
-
if (rows.length === 0) return;
|
|
15922
|
-
let maxColumns = 0;
|
|
15923
|
-
rows.forEach((row) => {
|
|
15924
|
-
const cells = row.querySelectorAll("td, th");
|
|
15925
|
-
let rowColumnCount = 0;
|
|
15926
|
-
cells.forEach((cell) => {
|
|
15927
|
-
if (cell instanceof HTMLTableCellElement) {
|
|
15928
|
-
const colspan = parseInt(cell.getAttribute("colspan") || "1", 10);
|
|
15929
|
-
rowColumnCount += colspan;
|
|
15930
|
-
} else {
|
|
15931
|
-
rowColumnCount += 1;
|
|
15932
|
-
}
|
|
15933
|
-
});
|
|
15934
|
-
maxColumns = Math.max(maxColumns, rowColumnCount);
|
|
15935
|
-
});
|
|
15936
|
-
if (maxColumns > 1) {
|
|
15937
|
-
rows.forEach((row) => {
|
|
15938
|
-
const cells = row.querySelectorAll("td, th");
|
|
15939
|
-
if (cells.length === 1) {
|
|
15940
|
-
const cell = cells[0];
|
|
15941
|
-
if (cell instanceof HTMLTableCellElement) {
|
|
15942
|
-
const existingColspan = parseInt(cell.getAttribute("colspan") || "1", 10);
|
|
15943
|
-
if (existingColspan < maxColumns) {
|
|
15944
|
-
cell.setAttribute("colspan", maxColumns.toString());
|
|
15945
|
-
}
|
|
15946
|
-
}
|
|
15947
|
-
}
|
|
15948
|
-
});
|
|
15949
|
-
}
|
|
15950
|
-
});
|
|
15951
|
-
const modifiedHtml = doc.body.innerHTML;
|
|
15952
|
-
return { html: modifiedHtml, notes: extractedNotes };
|
|
15953
|
-
}
|
|
15954
15957
|
var Verse = {
|
|
15955
15958
|
/**
|
|
15956
15959
|
* Renders a single verse with superscript number and text.
|
|
@@ -15991,12 +15994,9 @@ var Verse = {
|
|
|
15991
15994
|
onVerseSelect,
|
|
15992
15995
|
highlightedVerses
|
|
15993
15996
|
}, ref) => {
|
|
15994
|
-
const
|
|
15997
|
+
const transformedData = (0, import_react3.useMemo)(() => transformBibleHtml(html), [html]);
|
|
15995
15998
|
const providerTheme = (0, import_platform_react_hooks3.useTheme)();
|
|
15996
15999
|
const currentTheme = theme || providerTheme;
|
|
15997
|
-
(0, import_react3.useEffect)(() => {
|
|
15998
|
-
setTransformedData(yvDomTransformer(html, true));
|
|
15999
|
-
}, [html]);
|
|
16000
16000
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
16001
16001
|
"section",
|
|
16002
16002
|
{
|
|
@@ -16260,7 +16260,7 @@ function Content5() {
|
|
|
16260
16260
|
function UserMenu() {
|
|
16261
16261
|
const { auth, signIn, signOut, userInfo } = (0, import_platform_react_hooks4.useYVAuth)();
|
|
16262
16262
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Popover, { children: [
|
|
16263
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PopoverTrigger, { "data-testid": "user-menu-trigger", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Button, { size: "icon", variant: "secondary", children: auth.isAuthenticated && userInfo?.avatarUrlFormat ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
16263
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PopoverTrigger, { asChild: true, "data-testid": "user-menu-trigger", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Button, { size: "icon", variant: "secondary", children: auth.isAuthenticated && userInfo?.avatarUrlFormat ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
16264
16264
|
"img",
|
|
16265
16265
|
{
|
|
16266
16266
|
src: userInfo.getAvatarUrl(32, 32)?.toString(),
|
|
@@ -16353,7 +16353,7 @@ function Toolbar({ border = "top" }) {
|
|
|
16353
16353
|
)
|
|
16354
16354
|
] }),
|
|
16355
16355
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Popover, { children: [
|
|
16356
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PopoverTrigger, { "aria-label": "Settings", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Button, { size: "icon", variant: "secondary", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GearIcon, { className: "yv:text-foreground" }) }) }),
|
|
16356
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PopoverTrigger, { asChild: true, "aria-label": "Settings", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Button, { size: "icon", variant: "secondary", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GearIcon, { className: "yv:text-foreground" }) }) }),
|
|
16357
16357
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PopoverContent, { sideOffset: 16, heading: "Reader Settings", theme: background, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "yv:flex yv:flex-col yv:gap-4 yv:p-4", children: [
|
|
16358
16358
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "yv:grid yv:grid-cols-2", children: [
|
|
16359
16359
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
@@ -16972,11 +16972,11 @@ function VerseOfTheDay({
|
|
|
16972
16972
|
);
|
|
16973
16973
|
}
|
|
16974
16974
|
|
|
16975
|
-
// src/components/bible-
|
|
16975
|
+
// src/components/bible-card.tsx
|
|
16976
16976
|
var import_platform_react_hooks7 = require("@youversion/platform-react-hooks");
|
|
16977
16977
|
var import_react8 = require("react");
|
|
16978
16978
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
16979
|
-
function
|
|
16979
|
+
function BibleCard({
|
|
16980
16980
|
reference,
|
|
16981
16981
|
versionId,
|
|
16982
16982
|
background,
|
|
@@ -17038,7 +17038,7 @@ function BibleWidgetView({
|
|
|
17038
17038
|
}
|
|
17039
17039
|
),
|
|
17040
17040
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "yv:grid yv:grid-cols-[1fr_auto] yv:gap-4 yv:items-center yv:mt-4", children: [
|
|
17041
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("
|
|
17041
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "yv:text-balance yv:text-muted-foreground yv:justify-self-start yv:font-bold yv:text-[0.5rem]", children: version2?.copyright }),
|
|
17042
17042
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "yv:justify-self-end", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(SvgComponent, { fontSize: 12 }) })
|
|
17043
17043
|
] })
|
|
17044
17044
|
]
|
|
@@ -17046,6 +17046,9 @@ function BibleWidgetView({
|
|
|
17046
17046
|
);
|
|
17047
17047
|
}
|
|
17048
17048
|
|
|
17049
|
+
// src/components/bible-widget-view.tsx
|
|
17050
|
+
var BibleWidgetView = BibleCard;
|
|
17051
|
+
|
|
17049
17052
|
// src/index.ts
|
|
17050
17053
|
var import_platform_react_hooks8 = require("@youversion/platform-react-hooks");
|
|
17051
17054
|
injectStyles();
|
|
@@ -17054,6 +17057,7 @@ injectStyles();
|
|
|
17054
17057
|
ApiClient,
|
|
17055
17058
|
BOOK_CANON,
|
|
17056
17059
|
BOOK_IDS,
|
|
17060
|
+
BibleCard,
|
|
17057
17061
|
BibleChapterPicker,
|
|
17058
17062
|
BibleClient,
|
|
17059
17063
|
BibleReader,
|
package/dist/index.js
CHANGED
|
@@ -14726,9 +14726,9 @@ import {
|
|
|
14726
14726
|
import {
|
|
14727
14727
|
createContext as createContext3,
|
|
14728
14728
|
useContext as useContext3,
|
|
14729
|
-
useEffect as
|
|
14729
|
+
useEffect as useEffect3,
|
|
14730
14730
|
useLayoutEffect as useLayoutEffect2,
|
|
14731
|
-
useMemo as
|
|
14731
|
+
useMemo as useMemo4,
|
|
14732
14732
|
useState as useState4
|
|
14733
14733
|
} from "react";
|
|
14734
14734
|
|
|
@@ -15121,7 +15121,17 @@ function Root5({
|
|
|
15121
15121
|
const [searchQuery, setSearchQuery] = useState2("");
|
|
15122
15122
|
const [isLanguagesOpen, setIsLanguagesOpen] = useState2(false);
|
|
15123
15123
|
const [recentVersions, setRecentVersions] = useState2(getRecentVersions);
|
|
15124
|
-
const [isPopoverOpen,
|
|
15124
|
+
const [isPopoverOpen, setIsPopoverOpenRaw] = useState2(false);
|
|
15125
|
+
const setIsPopoverOpen = useCallback(
|
|
15126
|
+
(open) => {
|
|
15127
|
+
setIsPopoverOpenRaw(open);
|
|
15128
|
+
if (!open) {
|
|
15129
|
+
setSearchQuery("");
|
|
15130
|
+
setIsLanguagesOpen(false);
|
|
15131
|
+
}
|
|
15132
|
+
},
|
|
15133
|
+
[setSearchQuery]
|
|
15134
|
+
);
|
|
15125
15135
|
const addRecentVersion = useCallback((version2) => {
|
|
15126
15136
|
setRecentVersions((prev) => {
|
|
15127
15137
|
const filtered = prev.filter((v) => v.id !== version2.id);
|
|
@@ -15551,11 +15561,10 @@ function PersonIcon(props) {
|
|
|
15551
15561
|
|
|
15552
15562
|
// src/components/verse.tsx
|
|
15553
15563
|
import { usePassage, useTheme as useTheme3 } from "@youversion/platform-react-hooks";
|
|
15554
|
-
import DOMPurify from "isomorphic-dompurify";
|
|
15555
15564
|
import {
|
|
15556
15565
|
forwardRef as forwardRef2,
|
|
15557
15566
|
memo,
|
|
15558
|
-
|
|
15567
|
+
useMemo as useMemo3,
|
|
15559
15568
|
useLayoutEffect,
|
|
15560
15569
|
useRef as useRef3,
|
|
15561
15570
|
useState as useState3
|
|
@@ -15563,8 +15572,20 @@ import {
|
|
|
15563
15572
|
import { createPortal } from "react-dom";
|
|
15564
15573
|
|
|
15565
15574
|
// src/lib/verse-html-utils.ts
|
|
15575
|
+
import DOMPurify from "isomorphic-dompurify";
|
|
15566
15576
|
var NON_BREAKING_SPACE = "\xA0";
|
|
15567
15577
|
var LETTERS = "abcdefghijklmnopqrstuvwxyz";
|
|
15578
|
+
function getFootnoteMarker(index) {
|
|
15579
|
+
const base = LETTERS.length;
|
|
15580
|
+
if (base === 0) return String(index + 1);
|
|
15581
|
+
let value = index;
|
|
15582
|
+
let marker = "";
|
|
15583
|
+
do {
|
|
15584
|
+
marker = LETTERS[value % base] + marker;
|
|
15585
|
+
value = Math.floor(value / base) - 1;
|
|
15586
|
+
} while (value >= 0);
|
|
15587
|
+
return marker;
|
|
15588
|
+
}
|
|
15568
15589
|
var INTER_FONT = '"Inter", sans-serif';
|
|
15569
15590
|
var SOURCE_SERIF_FONT = '"Source Serif 4", serif';
|
|
15570
15591
|
function wrapVerseContent(doc) {
|
|
@@ -15657,73 +15678,125 @@ function wrapVerseContent(doc) {
|
|
|
15657
15678
|
const verseMarkers = Array.from(doc.querySelectorAll(".yv-v[v]"));
|
|
15658
15679
|
verseMarkers.forEach(processVerseMarker);
|
|
15659
15680
|
}
|
|
15681
|
+
var NEEDS_SPACE_BEFORE = /^[^\s.,;:!?)}\]'"»›]/;
|
|
15682
|
+
function buildVerseHtml(wrappers) {
|
|
15683
|
+
const parts = [];
|
|
15684
|
+
let noteIdx = 0;
|
|
15685
|
+
for (let i = 0; i < wrappers.length; i++) {
|
|
15686
|
+
if (i > 0) parts.push(" ");
|
|
15687
|
+
const clone2 = wrappers[i].cloneNode(true);
|
|
15688
|
+
const ownerDoc = wrappers[i].ownerDocument;
|
|
15689
|
+
clone2.querySelectorAll(".yv-h, .yv-vlbl").forEach((el) => el.remove());
|
|
15690
|
+
clone2.querySelectorAll(".yv-n.f").forEach((fn) => {
|
|
15691
|
+
const marker = ownerDoc.createElement("sup");
|
|
15692
|
+
marker.className = "yv:text-muted-foreground";
|
|
15693
|
+
marker.textContent = getFootnoteMarker(noteIdx++);
|
|
15694
|
+
fn.replaceWith(marker);
|
|
15695
|
+
});
|
|
15696
|
+
parts.push(clone2.innerHTML);
|
|
15697
|
+
}
|
|
15698
|
+
return parts.join("");
|
|
15699
|
+
}
|
|
15700
|
+
function replaceFootnotesWithAnchors(doc, footnotes) {
|
|
15701
|
+
for (const fn of footnotes) {
|
|
15702
|
+
const verseNum = fn.closest(".yv-v[v]")?.getAttribute("v");
|
|
15703
|
+
if (!verseNum) continue;
|
|
15704
|
+
const prev = fn.previousSibling;
|
|
15705
|
+
const next = fn.nextSibling;
|
|
15706
|
+
const prevText = prev?.textContent ?? "";
|
|
15707
|
+
const nextText = next?.textContent ?? "";
|
|
15708
|
+
const prevNeedsSpace = prevText.length > 0 && !/\s$/.test(prevText);
|
|
15709
|
+
const nextNeedsSpace = nextText.length > 0 && NEEDS_SPACE_BEFORE.test(nextText);
|
|
15710
|
+
if (prevNeedsSpace && nextNeedsSpace && fn.parentNode) {
|
|
15711
|
+
fn.parentNode.insertBefore(doc.createTextNode(" "), fn);
|
|
15712
|
+
}
|
|
15713
|
+
const anchor = doc.createElement("span");
|
|
15714
|
+
anchor.setAttribute("data-verse-footnote", verseNum);
|
|
15715
|
+
fn.replaceWith(anchor);
|
|
15716
|
+
}
|
|
15717
|
+
}
|
|
15660
15718
|
function extractNotesFromWrappedHtml(doc) {
|
|
15661
15719
|
const footnotes = Array.from(doc.querySelectorAll(".yv-n.f"));
|
|
15662
15720
|
if (!footnotes.length) return {};
|
|
15663
15721
|
const footnotesByVerse = /* @__PURE__ */ new Map();
|
|
15664
|
-
|
|
15722
|
+
for (const fn of footnotes) {
|
|
15665
15723
|
const verseNum = fn.closest(".yv-v[v]")?.getAttribute("v");
|
|
15666
|
-
if (verseNum)
|
|
15667
|
-
|
|
15668
|
-
|
|
15669
|
-
|
|
15670
|
-
|
|
15671
|
-
}
|
|
15672
|
-
arr.push(fn);
|
|
15724
|
+
if (!verseNum) continue;
|
|
15725
|
+
let arr = footnotesByVerse.get(verseNum);
|
|
15726
|
+
if (!arr) {
|
|
15727
|
+
arr = [];
|
|
15728
|
+
footnotesByVerse.set(verseNum, arr);
|
|
15673
15729
|
}
|
|
15730
|
+
arr.push(fn);
|
|
15731
|
+
}
|
|
15732
|
+
const wrappersByVerse = /* @__PURE__ */ new Map();
|
|
15733
|
+
doc.querySelectorAll(".yv-v[v]").forEach((el) => {
|
|
15734
|
+
const verseNum = el.getAttribute("v");
|
|
15735
|
+
if (!verseNum) return;
|
|
15736
|
+
const arr = wrappersByVerse.get(verseNum);
|
|
15737
|
+
if (arr) arr.push(el);
|
|
15738
|
+
else wrappersByVerse.set(verseNum, [el]);
|
|
15674
15739
|
});
|
|
15675
15740
|
const notes = {};
|
|
15676
|
-
const
|
|
15677
|
-
footnotesByVerse.forEach((fns, verseNum) => {
|
|
15678
|
-
const verseWrappers = Array.from(doc.querySelectorAll(`.yv-v[v="${verseNum}"]`));
|
|
15679
|
-
let verseHtml = "";
|
|
15680
|
-
let noteIdx = 0;
|
|
15681
|
-
verseWrappers.forEach((wrapper, wrapperIdx) => {
|
|
15682
|
-
if (wrapperIdx > 0) verseHtml += " ";
|
|
15683
|
-
const walker = doc.createTreeWalker(wrapper, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
|
|
15684
|
-
let lastWasFootnote = false;
|
|
15685
|
-
while (walker.nextNode()) {
|
|
15686
|
-
const node = walker.currentNode;
|
|
15687
|
-
if (node instanceof Element) {
|
|
15688
|
-
if (node.classList.contains("yv-n") && node.classList.contains("f")) {
|
|
15689
|
-
verseHtml += `<sup class="yv:text-muted-foreground">${LETTERS[noteIdx++] || noteIdx}</sup>`;
|
|
15690
|
-
lastWasFootnote = true;
|
|
15691
|
-
}
|
|
15692
|
-
} else if (node.nodeType === Node.TEXT_NODE) {
|
|
15693
|
-
const parent = node.parentElement;
|
|
15694
|
-
if (parent?.closest(".yv-n.f") || parent?.closest(".yv-h")) continue;
|
|
15695
|
-
if (parent?.classList.contains("yv-vlbl")) continue;
|
|
15696
|
-
let text = node.textContent || "";
|
|
15697
|
-
if (lastWasFootnote && text && NEEDS_SPACE_BEFORE.test(text)) {
|
|
15698
|
-
text = " " + text;
|
|
15699
|
-
}
|
|
15700
|
-
verseHtml += text;
|
|
15701
|
-
lastWasFootnote = false;
|
|
15702
|
-
}
|
|
15703
|
-
}
|
|
15704
|
-
});
|
|
15741
|
+
for (const [verseNum, fns] of footnotesByVerse) {
|
|
15705
15742
|
notes[verseNum] = {
|
|
15706
|
-
verseHtml,
|
|
15743
|
+
verseHtml: buildVerseHtml(wrappersByVerse.get(verseNum) ?? []),
|
|
15707
15744
|
notes: fns.map((fn) => fn.innerHTML)
|
|
15708
15745
|
};
|
|
15709
|
-
|
|
15710
|
-
|
|
15711
|
-
|
|
15712
|
-
|
|
15713
|
-
|
|
15746
|
+
}
|
|
15747
|
+
replaceFootnotesWithAnchors(doc, footnotes);
|
|
15748
|
+
return notes;
|
|
15749
|
+
}
|
|
15750
|
+
function addNbspToVerseLabels(doc) {
|
|
15751
|
+
doc.querySelectorAll(".yv-vlbl").forEach((label) => {
|
|
15752
|
+
const text = label.textContent || "";
|
|
15753
|
+
if (!text.endsWith(NON_BREAKING_SPACE)) {
|
|
15754
|
+
label.textContent = text + NON_BREAKING_SPACE;
|
|
15714
15755
|
}
|
|
15715
15756
|
});
|
|
15716
|
-
|
|
15717
|
-
|
|
15718
|
-
|
|
15719
|
-
const
|
|
15720
|
-
|
|
15721
|
-
|
|
15722
|
-
|
|
15757
|
+
}
|
|
15758
|
+
function fixIrregularTables(doc) {
|
|
15759
|
+
doc.querySelectorAll("table").forEach((table) => {
|
|
15760
|
+
const rows = table.querySelectorAll("tr");
|
|
15761
|
+
if (rows.length === 0) return;
|
|
15762
|
+
let maxColumns = 0;
|
|
15763
|
+
rows.forEach((row) => {
|
|
15764
|
+
let count = 0;
|
|
15765
|
+
row.querySelectorAll("td, th").forEach((cell) => {
|
|
15766
|
+
count += cell instanceof HTMLTableCellElement ? parseInt(cell.getAttribute("colspan") || "1", 10) : 1;
|
|
15767
|
+
});
|
|
15768
|
+
maxColumns = Math.max(maxColumns, count);
|
|
15769
|
+
});
|
|
15770
|
+
if (maxColumns > 1) {
|
|
15771
|
+
rows.forEach((row) => {
|
|
15772
|
+
const cells = row.querySelectorAll("td, th");
|
|
15773
|
+
if (cells.length === 1 && cells[0] instanceof HTMLTableCellElement) {
|
|
15774
|
+
const existing = parseInt(cells[0].getAttribute("colspan") || "1", 10);
|
|
15775
|
+
if (existing < maxColumns) {
|
|
15776
|
+
cells[0].setAttribute("colspan", maxColumns.toString());
|
|
15777
|
+
}
|
|
15778
|
+
}
|
|
15779
|
+
});
|
|
15723
15780
|
}
|
|
15724
|
-
fn.remove();
|
|
15725
15781
|
});
|
|
15726
|
-
|
|
15782
|
+
}
|
|
15783
|
+
var DOMPURIFY_CONFIG = {
|
|
15784
|
+
ALLOWED_ATTR: ["class", "style", "id", "v", "usfm"],
|
|
15785
|
+
ALLOW_DATA_ATTR: true
|
|
15786
|
+
};
|
|
15787
|
+
function transformBibleHtml(html) {
|
|
15788
|
+
if (typeof window === "undefined" || !("DOMParser" in window)) {
|
|
15789
|
+
return { html, notes: {} };
|
|
15790
|
+
}
|
|
15791
|
+
const doc = new DOMParser().parseFromString(
|
|
15792
|
+
DOMPurify.sanitize(html, DOMPURIFY_CONFIG),
|
|
15793
|
+
"text/html"
|
|
15794
|
+
);
|
|
15795
|
+
wrapVerseContent(doc);
|
|
15796
|
+
const notes = extractNotesFromWrappedHtml(doc);
|
|
15797
|
+
addNbspToVerseLabels(doc);
|
|
15798
|
+
fixIrregularTables(doc);
|
|
15799
|
+
return { html: doc.body.innerHTML, notes };
|
|
15727
15800
|
}
|
|
15728
15801
|
|
|
15729
15802
|
// src/components/icons/footnote.tsx
|
|
@@ -15784,20 +15857,23 @@ var VerseFootnoteButton = memo(function VerseFootnoteButton2({
|
|
|
15784
15857
|
dangerouslySetInnerHTML: { __html: verseNotes.verseHtml }
|
|
15785
15858
|
}
|
|
15786
15859
|
),
|
|
15787
|
-
/* @__PURE__ */ jsx20("ul", { className: "yv:list-none yv:p-0 yv:m-0 yv:space-y-1", children: verseNotes.notes.map((note, index) =>
|
|
15788
|
-
|
|
15789
|
-
|
|
15790
|
-
|
|
15791
|
-
|
|
15792
|
-
|
|
15793
|
-
|
|
15794
|
-
"
|
|
15795
|
-
|
|
15796
|
-
|
|
15797
|
-
|
|
15798
|
-
|
|
15799
|
-
|
|
15800
|
-
|
|
15860
|
+
/* @__PURE__ */ jsx20("ul", { className: "yv:list-none yv:p-0 yv:m-0 yv:space-y-1", children: verseNotes.notes.map((note, index) => {
|
|
15861
|
+
const marker = getFootnoteMarker(index);
|
|
15862
|
+
return /* @__PURE__ */ jsxs6(
|
|
15863
|
+
"li",
|
|
15864
|
+
{
|
|
15865
|
+
className: "yv:flex yv:gap-2 yv:text-xs yv:border-b yv:border-border yv:py-2",
|
|
15866
|
+
children: [
|
|
15867
|
+
/* @__PURE__ */ jsxs6("span", { className: "", children: [
|
|
15868
|
+
marker,
|
|
15869
|
+
"."
|
|
15870
|
+
] }),
|
|
15871
|
+
/* @__PURE__ */ jsx20("span", { dangerouslySetInnerHTML: { __html: note } })
|
|
15872
|
+
]
|
|
15873
|
+
},
|
|
15874
|
+
marker
|
|
15875
|
+
);
|
|
15876
|
+
}) })
|
|
15801
15877
|
] })
|
|
15802
15878
|
}
|
|
15803
15879
|
)
|
|
@@ -15814,57 +15890,39 @@ function BibleTextHtml({
|
|
|
15814
15890
|
highlightedVerses = {}
|
|
15815
15891
|
}) {
|
|
15816
15892
|
const contentRef = useRef3(null);
|
|
15817
|
-
const [placeholders, setPlaceholders] = useState3(
|
|
15893
|
+
const [placeholders, setPlaceholders] = useState3([]);
|
|
15818
15894
|
const providerTheme = useTheme3();
|
|
15819
15895
|
const currentTheme = theme || providerTheme;
|
|
15820
15896
|
useLayoutEffect(() => {
|
|
15821
15897
|
if (!contentRef.current) return;
|
|
15822
15898
|
contentRef.current.innerHTML = html;
|
|
15823
|
-
const
|
|
15824
|
-
|
|
15825
|
-
|
|
15826
|
-
|
|
15899
|
+
const anchors = contentRef.current.querySelectorAll("[data-verse-footnote]");
|
|
15900
|
+
const result = [];
|
|
15901
|
+
anchors.forEach((el) => {
|
|
15902
|
+
const verseNum = el.getAttribute("data-verse-footnote");
|
|
15903
|
+
if (verseNum) result.push({ verseNum, el });
|
|
15827
15904
|
});
|
|
15828
|
-
setPlaceholders(
|
|
15829
|
-
}, [html
|
|
15905
|
+
setPlaceholders(result);
|
|
15906
|
+
}, [html]);
|
|
15830
15907
|
useLayoutEffect(() => {
|
|
15831
15908
|
if (!contentRef.current) return;
|
|
15832
|
-
|
|
15833
|
-
verseElements.forEach((el) => {
|
|
15909
|
+
contentRef.current.querySelectorAll(".yv-v[v]").forEach((el) => {
|
|
15834
15910
|
const verseNum = parseInt(el.getAttribute("v") || "0", 10);
|
|
15835
|
-
|
|
15836
|
-
|
|
15837
|
-
} else {
|
|
15838
|
-
el.classList.remove("yv-v-selected");
|
|
15839
|
-
}
|
|
15840
|
-
if (highlightedVerses[verseNum]) {
|
|
15841
|
-
el.classList.add("yv-v-highlighted");
|
|
15842
|
-
} else {
|
|
15843
|
-
el.classList.remove("yv-v-highlighted");
|
|
15844
|
-
}
|
|
15911
|
+
el.classList.toggle("yv-v-selected", selectedVerses.includes(verseNum));
|
|
15912
|
+
el.classList.toggle("yv-v-highlighted", !!highlightedVerses[verseNum]);
|
|
15845
15913
|
});
|
|
15846
15914
|
}, [html, selectedVerses, highlightedVerses]);
|
|
15847
|
-
const
|
|
15848
|
-
|
|
15849
|
-
|
|
15850
|
-
const
|
|
15851
|
-
if (!
|
|
15852
|
-
const
|
|
15853
|
-
|
|
15854
|
-
|
|
15855
|
-
if (!verseEl) return;
|
|
15856
|
-
const verseNum = parseInt(verseEl.getAttribute("v") || "0", 10);
|
|
15857
|
-
if (verseNum === 0) return;
|
|
15858
|
-
const current = selectedVersesRef.current;
|
|
15859
|
-
const newSelected = current.includes(verseNum) ? current.filter((v) => v !== verseNum) : [...current, verseNum].sort((a, b) => a - b);
|
|
15860
|
-
onVerseSelect(newSelected);
|
|
15861
|
-
};
|
|
15862
|
-
element.addEventListener("click", handleClick);
|
|
15863
|
-
return () => element.removeEventListener("click", handleClick);
|
|
15864
|
-
}, [onVerseSelect]);
|
|
15915
|
+
const handleClick = onVerseSelect ? (e) => {
|
|
15916
|
+
const verseEl = e.target.closest(".yv-v[v]");
|
|
15917
|
+
if (!verseEl) return;
|
|
15918
|
+
const verseNum = parseInt(verseEl.getAttribute("v") || "0", 10);
|
|
15919
|
+
if (!verseNum) return;
|
|
15920
|
+
const newSelected = selectedVerses.includes(verseNum) ? selectedVerses.filter((v) => v !== verseNum) : [...selectedVerses, verseNum].sort((a, b) => a - b);
|
|
15921
|
+
onVerseSelect(newSelected);
|
|
15922
|
+
} : void 0;
|
|
15865
15923
|
return /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
15866
|
-
/* @__PURE__ */ jsx20("div", { ref: contentRef }),
|
|
15867
|
-
|
|
15924
|
+
/* @__PURE__ */ jsx20("div", { ref: contentRef, onClick: handleClick }),
|
|
15925
|
+
placeholders.map(({ verseNum, el }, index) => {
|
|
15868
15926
|
const verseNotes = notes[verseNum];
|
|
15869
15927
|
if (!verseNotes) return null;
|
|
15870
15928
|
return createPortal(
|
|
@@ -15878,68 +15936,12 @@ function BibleTextHtml({
|
|
|
15878
15936
|
theme: currentTheme
|
|
15879
15937
|
}
|
|
15880
15938
|
),
|
|
15881
|
-
el
|
|
15939
|
+
el,
|
|
15940
|
+
`${verseNum}-${index}`
|
|
15882
15941
|
);
|
|
15883
15942
|
})
|
|
15884
15943
|
] });
|
|
15885
15944
|
}
|
|
15886
|
-
var DOMPURIFY_CONFIG = {
|
|
15887
|
-
ALLOWED_ATTR: ["class", "style", "id", "v", "usfm"],
|
|
15888
|
-
ALLOW_DATA_ATTR: true
|
|
15889
|
-
};
|
|
15890
|
-
function yvDomTransformer(html, extractNotes = false) {
|
|
15891
|
-
if (typeof window === "undefined" || !("DOMParser" in window)) {
|
|
15892
|
-
return { html, notes: {} };
|
|
15893
|
-
}
|
|
15894
|
-
const doc = new DOMParser().parseFromString(
|
|
15895
|
-
DOMPurify.sanitize(html, DOMPURIFY_CONFIG),
|
|
15896
|
-
"text/html"
|
|
15897
|
-
);
|
|
15898
|
-
wrapVerseContent(doc);
|
|
15899
|
-
const extractedNotes = extractNotes ? extractNotesFromWrappedHtml(doc) : {};
|
|
15900
|
-
const verseLabels = doc.querySelectorAll(".yv-vlbl");
|
|
15901
|
-
verseLabels.forEach((label) => {
|
|
15902
|
-
const text = label.textContent || "";
|
|
15903
|
-
if (!text.endsWith(NON_BREAKING_SPACE)) {
|
|
15904
|
-
label.textContent = text + NON_BREAKING_SPACE;
|
|
15905
|
-
}
|
|
15906
|
-
});
|
|
15907
|
-
const tables = doc.querySelectorAll("table");
|
|
15908
|
-
tables.forEach((table) => {
|
|
15909
|
-
const rows = table.querySelectorAll("tr");
|
|
15910
|
-
if (rows.length === 0) return;
|
|
15911
|
-
let maxColumns = 0;
|
|
15912
|
-
rows.forEach((row) => {
|
|
15913
|
-
const cells = row.querySelectorAll("td, th");
|
|
15914
|
-
let rowColumnCount = 0;
|
|
15915
|
-
cells.forEach((cell) => {
|
|
15916
|
-
if (cell instanceof HTMLTableCellElement) {
|
|
15917
|
-
const colspan = parseInt(cell.getAttribute("colspan") || "1", 10);
|
|
15918
|
-
rowColumnCount += colspan;
|
|
15919
|
-
} else {
|
|
15920
|
-
rowColumnCount += 1;
|
|
15921
|
-
}
|
|
15922
|
-
});
|
|
15923
|
-
maxColumns = Math.max(maxColumns, rowColumnCount);
|
|
15924
|
-
});
|
|
15925
|
-
if (maxColumns > 1) {
|
|
15926
|
-
rows.forEach((row) => {
|
|
15927
|
-
const cells = row.querySelectorAll("td, th");
|
|
15928
|
-
if (cells.length === 1) {
|
|
15929
|
-
const cell = cells[0];
|
|
15930
|
-
if (cell instanceof HTMLTableCellElement) {
|
|
15931
|
-
const existingColspan = parseInt(cell.getAttribute("colspan") || "1", 10);
|
|
15932
|
-
if (existingColspan < maxColumns) {
|
|
15933
|
-
cell.setAttribute("colspan", maxColumns.toString());
|
|
15934
|
-
}
|
|
15935
|
-
}
|
|
15936
|
-
}
|
|
15937
|
-
});
|
|
15938
|
-
}
|
|
15939
|
-
});
|
|
15940
|
-
const modifiedHtml = doc.body.innerHTML;
|
|
15941
|
-
return { html: modifiedHtml, notes: extractedNotes };
|
|
15942
|
-
}
|
|
15943
15945
|
var Verse = {
|
|
15944
15946
|
/**
|
|
15945
15947
|
* Renders a single verse with superscript number and text.
|
|
@@ -15980,12 +15982,9 @@ var Verse = {
|
|
|
15980
15982
|
onVerseSelect,
|
|
15981
15983
|
highlightedVerses
|
|
15982
15984
|
}, ref) => {
|
|
15983
|
-
const
|
|
15985
|
+
const transformedData = useMemo3(() => transformBibleHtml(html), [html]);
|
|
15984
15986
|
const providerTheme = useTheme3();
|
|
15985
15987
|
const currentTheme = theme || providerTheme;
|
|
15986
|
-
useEffect3(() => {
|
|
15987
|
-
setTransformedData(yvDomTransformer(html, true));
|
|
15988
|
-
}, [html]);
|
|
15989
15988
|
return /* @__PURE__ */ jsx20(
|
|
15990
15989
|
"section",
|
|
15991
15990
|
{
|
|
@@ -16145,10 +16144,10 @@ function Root6({
|
|
|
16145
16144
|
setCurrentFontFamily(savedFontFamily);
|
|
16146
16145
|
}
|
|
16147
16146
|
}, []);
|
|
16148
|
-
|
|
16147
|
+
useEffect3(() => {
|
|
16149
16148
|
localStorage.setItem("youversion-platform:reader:font-size", currentFontSize.toString());
|
|
16150
16149
|
}, [currentFontSize]);
|
|
16151
|
-
|
|
16150
|
+
useEffect3(() => {
|
|
16152
16151
|
localStorage.setItem("youversion-platform:reader:font-family", currentFontFamily);
|
|
16153
16152
|
}, [currentFontFamily]);
|
|
16154
16153
|
const providerTheme = useTheme4();
|
|
@@ -16191,7 +16190,7 @@ function Content5() {
|
|
|
16191
16190
|
} = useBibleReaderContext();
|
|
16192
16191
|
const { books } = useBooks2(versionId);
|
|
16193
16192
|
const { version: version2 } = useVersion2(versionId);
|
|
16194
|
-
const bookData =
|
|
16193
|
+
const bookData = useMemo4(() => {
|
|
16195
16194
|
return books?.data?.find((b) => b.id === book);
|
|
16196
16195
|
}, [books?.data, book]);
|
|
16197
16196
|
const usfmReference = `${book}.${chapter}`;
|
|
@@ -16249,7 +16248,7 @@ function Content5() {
|
|
|
16249
16248
|
function UserMenu() {
|
|
16250
16249
|
const { auth, signIn, signOut, userInfo } = useYVAuth();
|
|
16251
16250
|
return /* @__PURE__ */ jsxs7(Popover, { children: [
|
|
16252
|
-
/* @__PURE__ */ jsx21(PopoverTrigger, { "data-testid": "user-menu-trigger", children: /* @__PURE__ */ jsx21(Button, { size: "icon", variant: "secondary", children: auth.isAuthenticated && userInfo?.avatarUrlFormat ? /* @__PURE__ */ jsx21(
|
|
16251
|
+
/* @__PURE__ */ jsx21(PopoverTrigger, { asChild: true, "data-testid": "user-menu-trigger", children: /* @__PURE__ */ jsx21(Button, { size: "icon", variant: "secondary", children: auth.isAuthenticated && userInfo?.avatarUrlFormat ? /* @__PURE__ */ jsx21(
|
|
16253
16252
|
"img",
|
|
16254
16253
|
{
|
|
16255
16254
|
src: userInfo.getAvatarUrl(32, 32)?.toString(),
|
|
@@ -16342,7 +16341,7 @@ function Toolbar({ border = "top" }) {
|
|
|
16342
16341
|
)
|
|
16343
16342
|
] }),
|
|
16344
16343
|
/* @__PURE__ */ jsxs7(Popover, { children: [
|
|
16345
|
-
/* @__PURE__ */ jsx21(PopoverTrigger, { "aria-label": "Settings", children: /* @__PURE__ */ jsx21(Button, { size: "icon", variant: "secondary", children: /* @__PURE__ */ jsx21(GearIcon, { className: "yv:text-foreground" }) }) }),
|
|
16344
|
+
/* @__PURE__ */ jsx21(PopoverTrigger, { asChild: true, "aria-label": "Settings", children: /* @__PURE__ */ jsx21(Button, { size: "icon", variant: "secondary", children: /* @__PURE__ */ jsx21(GearIcon, { className: "yv:text-foreground" }) }) }),
|
|
16346
16345
|
/* @__PURE__ */ jsx21(PopoverContent, { sideOffset: 16, heading: "Reader Settings", theme: background, children: /* @__PURE__ */ jsxs7("div", { className: "yv:flex yv:flex-col yv:gap-4 yv:p-4", children: [
|
|
16347
16346
|
/* @__PURE__ */ jsxs7("div", { className: "yv:grid yv:grid-cols-2", children: [
|
|
16348
16347
|
/* @__PURE__ */ jsx21(
|
|
@@ -16433,7 +16432,7 @@ function Toolbar({ border = "top" }) {
|
|
|
16433
16432
|
var BibleReader = Object.assign({}, { Root: Root6, Content: Content5, Toolbar });
|
|
16434
16433
|
|
|
16435
16434
|
// src/components/YouVersionAuthButton.tsx
|
|
16436
|
-
import React10, { useMemo as
|
|
16435
|
+
import React10, { useMemo as useMemo5 } from "react";
|
|
16437
16436
|
|
|
16438
16437
|
// src/components/icons/loader.tsx
|
|
16439
16438
|
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
@@ -16595,7 +16594,7 @@ var YouVersionAuthButton = React10.forwardRef(
|
|
|
16595
16594
|
}
|
|
16596
16595
|
};
|
|
16597
16596
|
const buttonLoading = auth.isLoading;
|
|
16598
|
-
const buttonText =
|
|
16597
|
+
const buttonText = useMemo5(() => {
|
|
16599
16598
|
if (text) return text;
|
|
16600
16599
|
const isSignOut = mode === "signOut" || mode === "auto" && auth.isAuthenticated;
|
|
16601
16600
|
if (size === "short") {
|
|
@@ -16967,11 +16966,11 @@ function VerseOfTheDay({
|
|
|
16967
16966
|
);
|
|
16968
16967
|
}
|
|
16969
16968
|
|
|
16970
|
-
// src/components/bible-
|
|
16969
|
+
// src/components/bible-card.tsx
|
|
16971
16970
|
import { usePassage as usePassage3, useVersion as useVersion4, useTheme as useTheme7 } from "@youversion/platform-react-hooks";
|
|
16972
16971
|
import { useState as useState5 } from "react";
|
|
16973
16972
|
import { jsx as jsx29, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
16974
|
-
function
|
|
16973
|
+
function BibleCard({
|
|
16975
16974
|
reference,
|
|
16976
16975
|
versionId,
|
|
16977
16976
|
background,
|
|
@@ -17033,7 +17032,7 @@ function BibleWidgetView({
|
|
|
17033
17032
|
}
|
|
17034
17033
|
),
|
|
17035
17034
|
/* @__PURE__ */ jsxs14("div", { className: "yv:grid yv:grid-cols-[1fr_auto] yv:gap-4 yv:items-center yv:mt-4", children: [
|
|
17036
|
-
/* @__PURE__ */ jsx29("
|
|
17035
|
+
/* @__PURE__ */ jsx29("p", { className: "yv:text-balance yv:text-muted-foreground yv:justify-self-start yv:font-bold yv:text-[0.5rem]", children: version2?.copyright }),
|
|
17037
17036
|
/* @__PURE__ */ jsx29("div", { className: "yv:justify-self-end", children: /* @__PURE__ */ jsx29(SvgComponent, { fontSize: 12 }) })
|
|
17038
17037
|
] })
|
|
17039
17038
|
]
|
|
@@ -17041,6 +17040,9 @@ function BibleWidgetView({
|
|
|
17041
17040
|
);
|
|
17042
17041
|
}
|
|
17043
17042
|
|
|
17043
|
+
// src/components/bible-widget-view.tsx
|
|
17044
|
+
var BibleWidgetView = BibleCard;
|
|
17045
|
+
|
|
17044
17046
|
// src/index.ts
|
|
17045
17047
|
import {
|
|
17046
17048
|
YouVersionProvider,
|
|
@@ -17051,6 +17053,7 @@ export {
|
|
|
17051
17053
|
ApiClient,
|
|
17052
17054
|
BOOK_CANON,
|
|
17053
17055
|
BOOK_IDS,
|
|
17056
|
+
BibleCard,
|
|
17054
17057
|
BibleChapterPicker,
|
|
17055
17058
|
BibleClient,
|
|
17056
17059
|
BibleReader,
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Converts a 0-based footnote index into an alphabetic marker.
|
|
3
|
+
*
|
|
4
|
+
* Examples with LETTERS = "abcdefghijklmnopqrstuvwxyz":
|
|
5
|
+
* 0 -> "a", 25 -> "z", 26 -> "aa", 27 -> "ab"
|
|
6
|
+
*
|
|
7
|
+
* This uses spreadsheet-style indexing and derives its base from
|
|
8
|
+
* LETTERS.length so there are no hardcoded numeric assumptions.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getFootnoteMarker(index: number): string;
|
|
3
11
|
export type VerseNotes = {
|
|
4
12
|
verseHtml: string;
|
|
5
13
|
notes: string[];
|
|
@@ -8,24 +16,16 @@ export declare const INTER_FONT: "\"Inter\", sans-serif";
|
|
|
8
16
|
export declare const SOURCE_SERIF_FONT: "\"Source Serif 4\", serif";
|
|
9
17
|
export type FontFamily = typeof INTER_FONT | typeof SOURCE_SERIF_FONT | (string & {});
|
|
10
18
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Transforms empty verse markers into wrapping containers. When a verse spans
|
|
14
|
-
* multiple paragraphs, creates duplicate wrappers in each paragraph (Bible.com pattern).
|
|
15
|
-
*
|
|
16
|
-
* Before: <span class="yv-v" v="1"></span><span class="yv-vlbl">1</span>Text...
|
|
17
|
-
* After: <span class="yv-v" v="1"><span class="yv-vlbl">1</span>Text...</span>
|
|
19
|
+
* Full transformation pipeline for Bible HTML from the API.
|
|
18
20
|
*
|
|
19
|
-
*
|
|
21
|
+
* 1. Sanitize (DOMPurify)
|
|
22
|
+
* 2. Wrap verse content in selectable spans
|
|
23
|
+
* 3. Extract footnotes and replace with portal anchors
|
|
24
|
+
* 4. Add non-breaking spaces to verse labels
|
|
25
|
+
* 5. Fix irregular table layouts
|
|
20
26
|
*/
|
|
21
|
-
export declare function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* This function assumes verses are already wrapped in `.yv-v[v]` elements (by wrapVerseContent).
|
|
26
|
-
* It uses `.closest('.yv-v[v]')` to find which verse each footnote belongs to.
|
|
27
|
-
*
|
|
28
|
-
* @returns Notes data for popovers, keyed by verse number
|
|
29
|
-
*/
|
|
30
|
-
export declare function extractNotesFromWrappedHtml(doc: Document): Record<string, VerseNotes>;
|
|
27
|
+
export declare function transformBibleHtml(html: string): {
|
|
28
|
+
html: string;
|
|
29
|
+
notes: Record<string, VerseNotes>;
|
|
30
|
+
};
|
|
31
31
|
//# sourceMappingURL=verse-html-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verse-html-utils.d.ts","sourceRoot":"","sources":["../../src/lib/verse-html-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verse-html-utils.d.ts","sourceRoot":"","sources":["../../src/lib/verse-html-utils.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAavD;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAG,uBAA8B,CAAC;AACzD,eAAO,MAAM,iBAAiB,EAAG,2BAAkC,CAAC;AACpE,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,GAAG,OAAO,iBAAiB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AA0UtF;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;CAAE,CAgBpG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@youversion/platform-react-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "React SDK for YouVersion Platform",
|
|
5
5
|
"license": "TBD",
|
|
6
6
|
"type": "module",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"isomorphic-dompurify": "2.23.0",
|
|
39
39
|
"tailwind-merge": "3.3.1",
|
|
40
40
|
"tw-animate-css": "1.4.0",
|
|
41
|
-
"@youversion/platform-core": "1.
|
|
42
|
-
"@youversion/platform-react-hooks": "1.
|
|
41
|
+
"@youversion/platform-core": "1.15.0",
|
|
42
|
+
"@youversion/platform-react-hooks": "1.15.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"react": ">=19.1.0 <20.0.0",
|