diff --git a/src/lib/components/ScriptureViewSofria.svelte b/src/lib/components/ScriptureViewSofria.svelte index 56005618..91bcc2c1 100644 --- a/src/lib/components/ScriptureViewSofria.svelte +++ b/src/lib/components/ScriptureViewSofria.svelte @@ -529,10 +529,12 @@ LOGGING: const spanV = document.createElement('span'); spanV.classList.add('v'); // 'number' can be a range of verse numbers - const numbers = element.atts['number'] - .split(verseRangeSeparator) - .map((x) => numerals.formatNumber(numeralSystem, x)); - spanV.innerText = numbers.join(verseRangeSeparator); + spanV.innerText = numerals.formatNumberRange( + numeralSystem, + element.atts['number'], + direction + ); + const spanVsp = document.createElement('span'); spanVsp.classList.add('vsp'); spanVsp.innerText = '\u00A0'; //   diff --git a/src/lib/scripts/numeralSystem.test.ts b/src/lib/scripts/numeralSystem.test.ts index 7bf3ce7a..e1ed7e27 100644 --- a/src/lib/scripts/numeralSystem.test.ts +++ b/src/lib/scripts/numeralSystem.test.ts @@ -1,5 +1,4 @@ import { expect, test, vi } from 'vitest'; -import { getStyle } from './configUtils'; import * as num from './numeralSystem'; test('fromString returns Oriya correctly', () => { @@ -20,6 +19,16 @@ test('formatNumber to khmer', () => { ); }); +test('formatNumberRange with separator', () => { + expect(num.formatNumberRange(num.NumeralSystemData.DEFAULT, '4-7', 'ltr')).toBe('4-7'); +}); + +test('formatNumberRange with separator and rtl', () => { + expect(num.formatNumberRange(num.NumeralSystemData.DEFAULT, '4-7', 'rtl')).toBe( + '\u200F4\u200F-7' + ); +}); + test('systemForBook gets numeralSystem from book collection', () => { const config = { bookCollections: [ diff --git a/src/lib/scripts/numeralSystem.ts b/src/lib/scripts/numeralSystem.ts index ba512bda..f5bc0c43 100644 --- a/src/lib/scripts/numeralSystem.ts +++ b/src/lib/scripts/numeralSystem.ts @@ -42,6 +42,35 @@ export function systemForBook(config: any, collection: string, book: string): Nu return systemFromString(system); } +export function formatNumberRange(system: NumeralSystem, value: string, direction: string) { + // Regular expression to match a single number or a range + const match = value.match(/^(\d+)(.*?)(\d+)?$/); + + if (!match) { + throw new Error( + 'Input value must be a single number or a range separated by valid characters.' + ); + } + + const [, firstNumber, separator, secondNumber] = match; + + // Format the first number + const formattedFirst = formatNumber(system, firstNumber); + + if (!secondNumber) { + // If there's no second number, return the single formatted number + return formattedFirst; + } + + // Format the second number and join them with the captured separator + const formattedSecond = formatNumber(system, secondNumber); + // Proskomma is not including the RTL marker in the number range. + // For RTL, this matches the formatting that the native app does. + return direction.toLowerCase() === 'rtl' + ? `\u200F${formattedFirst}\u200F${separator}${formattedSecond}` + : `${formattedFirst}${separator}${formattedSecond}`; +} + export function formatNumber(system: NumeralSystem, value: string): any { let fmt = ''; for (let i = 0; i < value.length; i++) {