diff --git a/lib/text-highlight.ts b/lib/text-highlight.ts index d23f2db3..983d0566 100644 --- a/lib/text-highlight.ts +++ b/lib/text-highlight.ts @@ -9,39 +9,47 @@ /** * Encode a text selection into a compact URL-safe fragment. * - * Format: `?hl=,,` + * Format: `?hl=§§` * - prefix: first 4 words of the selection * - suffix: last 4 words of the selection (omitted if same as prefix) * - length: character count of the full selection (for disambiguation) * - * This keeps URLs short while being specific enough to locate the text. + * Uses `§` (section sign) as delimiter — it never appears in Sanskrit, + * Devanagari, English, or any Vedic text, unlike `,` (commas in prose) + * or `|` (pūrṇa virāma in Sanskrit verses). */ export function encodeTextFragment(text: string): string { const words = text.split(/\s+/).filter(Boolean); if (words.length === 0) return ""; - const prefixWords = words.slice(0, 4).join(" "); - const suffixWords = words.length > 6 ? words.slice(-4).join(" ") : ""; const len = text.length; - const parts = [prefixWords]; - if (suffixWords) parts.push(suffixWords); - parts.push(String(len)); + // Short selections (≤8 words): use the full text as prefix, no suffix needed. + // The entire selection is specific enough to locate uniquely. + if (words.length <= 8) { + return `${text.trim()}§${len}`; + } - return parts.join(","); + // Longer selections: first 4 words + last 4 words + length + const prefixWords = words.slice(0, 4).join(" "); + const suffixWords = words.slice(-4).join(" "); + + return `${prefixWords}§${suffixWords}§${len}`; } /** * Decode a text fragment from URL params. + * Supports `§` (current), `|` (v2 legacy), and `,` (v1 legacy) delimiters. * Returns { prefix, suffix, length } or null if invalid. */ export function decodeTextFragment( hl: string, ): { prefix: string; suffix: string; length: number } | null { - const parts = hl.split(","); + const delimiter = "§"; + const parts = hl.split(delimiter); if (parts.length < 2) return null; - const lengthStr = parts[parts.length - 1]; + const lengthStr = parts[parts.length - 1].trim(); const length = parseInt(lengthStr, 10); if (isNaN(length)) return null; @@ -51,7 +59,7 @@ export function decodeTextFragment( } // prefix + suffix + length - const prefix = parts.slice(0, -2).join(","); // in case prefix itself had commas + const prefix = parts.slice(0, -2).join(delimiter); const suffix = parts[parts.length - 2]; return { prefix, suffix, length }; }