diff --git a/src/analysis.ts b/src/analysis.ts index 8819fad2..e517e553 100644 --- a/src/analysis.ts +++ b/src/analysis.ts @@ -97,6 +97,7 @@ export function setAnalysisLocale(locale?: string): void { const arabicScriptRe = /\p{Script=Arabic}/u const combiningMarkRe = /\p{M}/u +const currencySymbolRe = /\p{Sc}/u const decimalDigitRe = /\p{Nd}/u function containsArabicScript(text: string): boolean { @@ -270,7 +271,7 @@ function isLeftStickyPunctuationSegment(segment: string): boolean { if (isEscapedQuoteClusterSegment(segment)) return true let sawPunctuation = false for (const ch of segment) { - if (leftStickyPunctuation.has(ch)) { + if (leftStickyPunctuation.has(ch) || currencySymbolRe.test(ch)) { sawPunctuation = true continue } @@ -290,7 +291,7 @@ function isCJKLineStartProhibitedSegment(segment: string): boolean { function isForwardStickyClusterSegment(segment: string): boolean { if (isEscapedQuoteClusterSegment(segment)) return true for (const ch of segment) { - if (!kinsokuEnd.has(ch) && !forwardStickyGlue.has(ch) && !combiningMarkRe.test(ch)) return false + if (!kinsokuEnd.has(ch) && !forwardStickyGlue.has(ch) && !combiningMarkRe.test(ch) && !currencySymbolRe.test(ch)) return false } return segment.length > 0 } diff --git a/src/layout.test.ts b/src/layout.test.ts index d9b83327..6416a51b 100644 --- a/src/layout.test.ts +++ b/src/layout.test.ts @@ -465,6 +465,16 @@ describe('prepare invariants', () => { expect(prepared.segments).toEqual(['say', ' ', String.raw`\"hello\"`, ' ', 'there']) }) + test('keeps prefix currency symbols attached to the following number', () => { + const prepared = prepareWithSegments('costs $500 today', FONT) + expect(prepared.segments).toEqual(['costs', ' ', '$500', ' ', 'today']) + }) + + test('keeps postfix currency symbols attached to the preceding number', () => { + const prepared = prepareWithSegments('price 500€ each', FONT) + expect(prepared.segments).toEqual(['price', ' ', '500€', ' ', 'each']) + }) + test('keeps URL-like runs together as one breakable segment', () => { const prepared = prepareWithSegments('see https://example.com/reports/q3?lang=ar&mode=full now', FONT) expect(prepared.segments).toEqual([