fix: handle text selection edge cases using new delimeter

This commit is contained in:
gosangam
2026-05-06 11:56:43 +05:30
parent 99eb17da4b
commit e6529ef62e
+19 -11
View File
@@ -9,39 +9,47 @@
/** /**
* Encode a text selection into a compact URL-safe fragment. * Encode a text selection into a compact URL-safe fragment.
* *
* Format: `?hl=<prefix>,<suffix>,<length>` * Format: `?hl=<prefix>§<suffix>§<length>`
* - prefix: first 4 words of the selection * - prefix: first 4 words of the selection
* - suffix: last 4 words of the selection (omitted if same as prefix) * - suffix: last 4 words of the selection (omitted if same as prefix)
* - length: character count of the full selection (for disambiguation) * - 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 { export function encodeTextFragment(text: string): string {
const words = text.split(/\s+/).filter(Boolean); const words = text.split(/\s+/).filter(Boolean);
if (words.length === 0) return ""; 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 len = text.length;
const parts = [prefixWords]; // Short selections (≤8 words): use the full text as prefix, no suffix needed.
if (suffixWords) parts.push(suffixWords); // The entire selection is specific enough to locate uniquely.
parts.push(String(len)); 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. * Decode a text fragment from URL params.
* Supports `§` (current), `|` (v2 legacy), and `,` (v1 legacy) delimiters.
* Returns { prefix, suffix, length } or null if invalid. * Returns { prefix, suffix, length } or null if invalid.
*/ */
export function decodeTextFragment( export function decodeTextFragment(
hl: string, hl: string,
): { prefix: string; suffix: string; length: number } | null { ): { prefix: string; suffix: string; length: number } | null {
const parts = hl.split(","); const delimiter = "§";
const parts = hl.split(delimiter);
if (parts.length < 2) return null; if (parts.length < 2) return null;
const lengthStr = parts[parts.length - 1]; const lengthStr = parts[parts.length - 1].trim();
const length = parseInt(lengthStr, 10); const length = parseInt(lengthStr, 10);
if (isNaN(length)) return null; if (isNaN(length)) return null;
@@ -51,7 +59,7 @@ export function decodeTextFragment(
} }
// prefix + suffix + length // 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]; const suffix = parts[parts.length - 2];
return { prefix, suffix, length }; return { prefix, suffix, length };
} }