Skip to content

Commit e79b182

Browse files
authored
Handle references with verse ranges and other exceptions (#445)
* Handle references with verse ranges and other exceptions * Add new file * Delete unneeded import * Fix issue where links didn't work if you changed book collection * Lint changes * Handle header references. Also navigate to verse. * Change method name and remove console log * Add extra material checks, book name is book id check and non word characters
1 parent 806414c commit e79b182

File tree

7 files changed

+1536
-315
lines changed

7 files changed

+1536
-315
lines changed

scripts/convertMarkdown.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,13 @@ function getReferenceFromString(
270270
}
271271
}
272272
}
273-
return [bookCollectionId, bookId, fromChapter, toChapter, verseRanges];
273+
return [
274+
bookCollectionId.toUpperCase(),
275+
bookId.toUpperCase(),
276+
fromChapter,
277+
toChapter,
278+
verseRanges
279+
];
274280
}
275281

276282
function parseChapterRange(chapterRange: string): [number, number] {

src/lib/components/ScriptureViewSofria.svelte

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ TODO:
1313
import config from '$lib/data/config';
1414
import { base } from '$app/paths';
1515
import { footnotes, isBibleBook, refs } from '$lib/data/stores';
16-
import { generateHTML } from '$lib/scripts/scripture-reference-utils';
16+
import { generateHTML, handleHeaderLinkPressed } from '$lib/scripts/scripture-reference-utils';
1717
import {
1818
onClickText,
1919
deselectAllElements,
@@ -207,7 +207,7 @@ TODO:
207207
let child;
208208
spanElement.classList.add(spanClass);
209209
if (spanClass === 'xt') {
210-
spanElement.innerHTML = generateHTML(phrase);
210+
spanElement.innerHTML = phrase;
211211
} else {
212212
child = document.createTextNode(phrase);
213213
spanElement.appendChild(child);
@@ -295,7 +295,13 @@ TODO:
295295
event.stopPropagation();
296296
const root = event.target.parentNode.parentNode;
297297
const footnote = root.querySelector(`div#${root.getAttribute('data-graft')}`);
298-
const parsed = footnote.innerHTML;
298+
const workingSpan = footnote.cloneNode(true);
299+
const spans = workingSpan.querySelectorAll('span.xt');
300+
// Loop through each span and modify its inner HTML
301+
spans.forEach(span => {
302+
span.innerHTML = generateHTML(span.innerHTML, ''); // Change inner HTML as needed
303+
});
304+
const parsed = workingSpan.innerHTML;
299305
footnotes.push(parsed);
300306
}
301307
}
@@ -319,6 +325,29 @@ TODO:
319325
refs.set({ docSet: refDocSet, book: refBook, chapter: splitChapter, verse:splitVerse });
320326
return;
321327
}
328+
async function headerLinkClickReference(event: any) {
329+
event.stopPropagation();
330+
let start = JSON.parse(event.target.getAttribute('data-start-ref'));
331+
let end =
332+
event.target.getAttribute('data-end-ref') === 'undefined'
333+
? undefined
334+
: JSON.parse(event.target.getAttribute('data-end-ref'));
335+
if (config.mainFeatures['scripture-refs-display'] === 'viewer') {
336+
navigate(start);
337+
} else {
338+
const footnoteHTML = await handleHeaderLinkPressed(start, end);
339+
footnotes.push(footnoteHTML);
340+
}
341+
}
342+
function navigate(reference) {
343+
refs.set({
344+
docSet: reference.docSet,
345+
book: reference.book,
346+
chapter: reference.chapter,
347+
verse: reference.verse
348+
});
349+
footnotes.reset();
350+
}
322351
function addNotesDiv(workspace) {
323352
const phraseIndex = fnc.charAt(workspace.currentPhraseIndex);
324353
const notesSpan = document.createElement('span');
@@ -571,6 +600,9 @@ TODO:
571600
referenceLinkClickHandler(e);
572601
break;
573602
}
603+
if (e.target.classList.contains('header-ref')) {
604+
headerLinkClickReference(e);
605+
}
574606
if (!$audioPlayer.playing) {
575607
onClickText(e, selectedVerses, maxSelections);
576608
}
@@ -670,7 +702,7 @@ TODO:
670702
if (!displayingIntroduction) {
671703
var els = document.getElementsByTagName('div');
672704
for (var i = 0; i < els.length; i++) {
673-
if (els[i].classList.contains('seltxt') && els[i].id != '') {
705+
if ((els[i].classList.contains('seltxt') && els[i].id != '') || (els[i].classList.contains('r'))) {
674706
els[i].addEventListener('click', onClick, false);
675707
}
676708
}
@@ -797,7 +829,11 @@ TODO:
797829
);
798830
const innerDiv = document.createElement('div');
799831
innerDiv.id = prefix + count;
800-
innerDiv.innerText = workspace.headerText;
832+
if (headingParaClass == 'r') {
833+
innerDiv.innerHTML = workspace.headerText;
834+
} else {
835+
innerDiv.innerText = workspace.headerText;
836+
}
801837
div.appendChild(innerDiv);
802838
workspace.root.appendChild(div);
803839
workspace.headerText = '';
@@ -921,7 +957,15 @@ TODO:
921957
break;
922958
}
923959
case 'heading': {
924-
workspace.headerText += text;
960+
const blockType = context.sequences[0].block.subType;
961+
if (
962+
blockType.includes('usfm:r')
963+
) {
964+
const refText = generateHTML(text, 'header-ref');
965+
workspace.headerText += refText;
966+
} else {
967+
workspace.headerText += text;
968+
}
925969
break;
926970
}
927971
case 'fig': {
@@ -1203,6 +1247,7 @@ TODO:
12031247
const cachedSequencePointer = workspace.currentSequence;
12041248
workspace.currentSequence = graftRecord.sequence;
12051249
environment.context.renderer.renderSequence(environment);
1250+
// Runs after all segments in graft have run
12061251
workspace.currentSequence = cachedSequencePointer;
12071252
if (element.subType === 'xref' || element.subType === 'footnote') {
12081253
const div = workspace.phraseDiv.cloneNode(true);

src/lib/components/StackView.svelte

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
import config from '$lib/data/config';
1010
import { isNotBlank, splitString } from '$lib/scripts/stringUtils';
11+
import { handleHeaderLinkPressed } from '$lib/scripts/scripture-reference-utils';
1112
let stack;
1213
let listening = false;
1314
$: PrimaryColor = $themeColors['PrimaryColor'];
@@ -22,7 +23,8 @@
2223
refs.set({
2324
docSet: reference.docSet,
2425
book: reference.book,
25-
chapter: reference.chapter
26+
chapter: reference.chapter,
27+
verse: reference.verse
2628
});
2729
footnotes.reset();
2830
}
@@ -61,28 +63,8 @@
6163
if (config.mainFeatures['scripture-refs-display-from-popup'] === 'viewer') {
6264
navigate(start);
6365
} else {
64-
const root = document.createElement('div');
65-
const textDiv = document.createElement('div');
66-
const iconDiv = document.createElement('div');
67-
iconDiv.id = 'icon';
68-
const referenceSpan = document.createElement('span');
69-
const footnoteSpan = document.createElement('span');
70-
const icon = document.createElement('button');
71-
root.classList.add('flex', 'flex-row', 'justify-space-between');
72-
referenceSpan.classList.add('fr');
73-
footnoteSpan.classList.add('ft');
74-
icon.setAttribute('reference', JSON.stringify(start));
75-
icon.classList.add('p-2');
76-
icon.innerHTML = openInNewIcon();
77-
referenceSpan.innerText = `${start.phrase} `;
78-
console.log(start, end);
79-
footnoteSpan.innerText = await getVerseText(start, end);
80-
textDiv.appendChild(referenceSpan);
81-
textDiv.appendChild(footnoteSpan);
82-
iconDiv.appendChild(icon);
83-
root.appendChild(textDiv);
84-
root.appendChild(iconDiv);
85-
footnotes.push(root.outerHTML);
66+
const footnoteHTML = await handleHeaderLinkPressed(start, end);
67+
footnotes.push(footnoteHTML);
8668
}
8769
} else if (event.target.classList.contains('ref-link')) {
8870
referenceLinkClickHandler(event);

src/lib/scripts/numeralUtils.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { isNotBlank } from './stringUtils';
2+
3+
export function getIntFromNumberString(str: string): number {
4+
let result: number = 0;
5+
6+
try {
7+
result = parseInt(str, 10);
8+
} catch (e) {
9+
// This could be because it was a different numeral system rather than 0...9
10+
const str0to9: string = convertDigitsInStringToDefaultNumeralSystem(str);
11+
if (isNotBlank(str0to9)) {
12+
try {
13+
result = parseInt(str0to9, 10);
14+
} catch (e2) {
15+
// The string contains non-digit characters
16+
}
17+
}
18+
}
19+
20+
return result;
21+
}
22+
23+
/**
24+
* Converts digits in the string to the default numeral system
25+
*/
26+
export function convertDigitsInStringToDefaultNumeralSystem(str: string): string {
27+
const sb: string[] = [];
28+
29+
for (let i = 0; i < str.length; i++) {
30+
const ch = str.charAt(i);
31+
const val = parseInt(ch, 10);
32+
if (!isNaN(val)) {
33+
sb.push(val.toString());
34+
} else {
35+
sb.push(ch);
36+
}
37+
}
38+
39+
return sb.join('');
40+
}

0 commit comments

Comments
 (0)