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.
*
* Format: `?hl=<prefix>,<suffix>,<length>`
* Format: `?hl=<prefix>§<suffix>§<length>`
* - 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 };
}