feat: add user centric features
This commit is contained in:
@@ -247,6 +247,128 @@ export function getSourceReference(): {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL-only variant of getSourceReference — pure function, safe on server.
|
||||
*
|
||||
* For `/books/...` paths we can derive a clean citation (e.g.
|
||||
* "Bhagavad-gītā As It Is — Chapter 1, Verse 1") from the path alone.
|
||||
* Mirrors the logic in `lib/og.ts`'s `ogForVerse` so post cards display
|
||||
* the same reference the OG image carries.
|
||||
*
|
||||
* For non-book paths the title lives in the page DOM (h1) which we don't
|
||||
* have at card-render time, so we return null — callers should fall back
|
||||
* to whatever `source_title` was saved at compose time.
|
||||
*/
|
||||
export function referenceFromUrl(
|
||||
sourceUrl: string,
|
||||
): { title: string; detail: string | null } | null {
|
||||
if (!sourceUrl) return null;
|
||||
let path: string;
|
||||
try {
|
||||
if (sourceUrl.startsWith("/")) {
|
||||
path = sourceUrl.split("?")[0];
|
||||
} else {
|
||||
const u = new URL(sourceUrl);
|
||||
path = u.pathname;
|
||||
}
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parts = path.split("/").filter(Boolean);
|
||||
if (parts[0] !== "books" || parts.length < 2) return null;
|
||||
|
||||
const code = parts[1];
|
||||
const bookName = BOOK_NAMES[code] || code.toUpperCase();
|
||||
|
||||
// Verse-based: /books/bg/[chapter]/[verse]
|
||||
if (code === "bg" && parts.length >= 4) {
|
||||
return {
|
||||
title: bookName,
|
||||
detail: `Chapter ${parts[2]}, Verse ${parts[3]}`,
|
||||
};
|
||||
}
|
||||
// SB: /books/sb/[canto]/[chapter]/[verse]
|
||||
if (code === "sb" && parts.length >= 5) {
|
||||
return {
|
||||
title: bookName,
|
||||
detail: `Canto ${parts[2]}, Chapter ${parts[3]}, Verse ${parts[4]}`,
|
||||
};
|
||||
}
|
||||
// CC: /books/cc/[lila]/[chapter]/[verse]
|
||||
if (code === "cc" && parts.length >= 5) {
|
||||
const lila = CC_LILAS[parts[2]] || parts[2];
|
||||
return {
|
||||
title: bookName,
|
||||
detail: `${lila}, Chapter ${parts[3]}, Verse ${parts[4]}`,
|
||||
};
|
||||
}
|
||||
// CC lila index: /books/cc/[lila]
|
||||
if (code === "cc" && parts.length === 3) {
|
||||
const lila = CC_LILAS[parts[2]] || parts[2];
|
||||
return { title: bookName, detail: lila };
|
||||
}
|
||||
// SB1962: /books/sb1962/[chapter]/[verse]
|
||||
if (code === "sb1962" && parts.length >= 4) {
|
||||
return {
|
||||
title: bookName,
|
||||
detail: `Chapter ${parts[2]}, Verse ${parts[3]}`,
|
||||
};
|
||||
}
|
||||
// ISO / NOI: /books/{code}/[mantra]
|
||||
if ((code === "iso" || code === "noi") && parts.length >= 3) {
|
||||
const num = parts[2];
|
||||
const label = code === "iso" ? "Mantra" : "Text";
|
||||
return { title: bookName, detail: `${label} ${num}` };
|
||||
}
|
||||
// BS/MM/NBS verse: /books/{code}/[chapter]/[verse]
|
||||
if (
|
||||
(code === "bs" || code === "mm" || code === "nbs") &&
|
||||
parts.length >= 4
|
||||
) {
|
||||
return {
|
||||
title: bookName,
|
||||
detail: `Chapter ${parts[2]}, Verse ${parts[3]}`,
|
||||
};
|
||||
}
|
||||
// KB: /books/kb/[volume]/[slug]
|
||||
if (code === "kb" && parts.length >= 4) {
|
||||
return {
|
||||
title: bookName,
|
||||
detail: `Volume ${parts[2]}, Chapter ${parts[3]}`,
|
||||
};
|
||||
}
|
||||
// Generic prose: /books/{code}/[chapter]
|
||||
if (parts.length >= 3) {
|
||||
const chSlug = parts[2];
|
||||
const chNum = parseInt(chSlug, 10);
|
||||
const detail = isNaN(chNum)
|
||||
? chSlug.replace(/-/g, " ")
|
||||
: `Chapter ${chNum}`;
|
||||
return { title: bookName, detail };
|
||||
}
|
||||
// Book index
|
||||
return { title: bookName, detail: null };
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a one-line citation string for a post/bookmark card.
|
||||
*
|
||||
* For book URLs we always prefer the URL-derived reference (canonical
|
||||
* format, no stale data). For non-book content (letters, essays, etc.)
|
||||
* the saved `source_title` is the source of truth.
|
||||
*/
|
||||
export function displaySourceLabel(
|
||||
sourceUrl: string,
|
||||
storedTitle?: string | null,
|
||||
): string {
|
||||
const ref = referenceFromUrl(sourceUrl);
|
||||
if (ref) {
|
||||
return ref.detail ? `${ref.title} — ${ref.detail}` : ref.title;
|
||||
}
|
||||
return storedTitle?.trim() || "Source";
|
||||
}
|
||||
|
||||
/**
|
||||
* Format selected text with source attribution appended.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user