fix: og image for glossary
This commit is contained in:
@@ -3,7 +3,7 @@ export const dynamic = "force-dynamic";
|
||||
import type { Metadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getAllGlossaryEntries } from "@/lib/api";
|
||||
import { buildOgMeta } from "@/lib/og";
|
||||
import { buildOgMeta, extractQuoteFromHl } from "@/lib/og";
|
||||
import { GlossaryClient } from "../glossary-client";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -11,12 +11,20 @@ import { GlossaryClient } from "../glossary-client";
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const DIACRITIC_TO_BASE: Record<string, string> = {
|
||||
Ā: "A", Ä: "A",
|
||||
Ī: "I", É: "I",
|
||||
Ū: "U", Ü: "U",
|
||||
Ṛ: "R", Ṝ: "R",
|
||||
Ś: "S", Ç: "S", Ṣ: "S",
|
||||
Ñ: "N", Ṇ: "N", Ṅ: "N",
|
||||
Ā: "A",
|
||||
Ä: "A",
|
||||
Ī: "I",
|
||||
É: "I",
|
||||
Ū: "U",
|
||||
Ü: "U",
|
||||
Ṛ: "R",
|
||||
Ṝ: "R",
|
||||
Ś: "S",
|
||||
Ç: "S",
|
||||
Ṣ: "S",
|
||||
Ñ: "N",
|
||||
Ṇ: "N",
|
||||
Ṅ: "N",
|
||||
Ṭ: "T",
|
||||
Ḍ: "D",
|
||||
Ḥ: "H",
|
||||
@@ -34,11 +42,53 @@ function getBaseLetter(term: string): string {
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
searchParams,
|
||||
}: {
|
||||
params: Promise<{ letter: string }>;
|
||||
searchParams: Promise<Record<string, string | string[] | undefined>>;
|
||||
}): Promise<Metadata> {
|
||||
const { letter } = await params;
|
||||
const sp = await searchParams;
|
||||
const l = letter.toUpperCase();
|
||||
|
||||
// If a specific term is referenced via ?term= param, show it in the OG image
|
||||
const termParam = typeof sp.term === "string" ? sp.term : null;
|
||||
if (termParam) {
|
||||
const allEntries = await getAllGlossaryEntries();
|
||||
const entry = allEntries.find(
|
||||
(e) => e.term.toLowerCase() === termParam.toLowerCase(),
|
||||
);
|
||||
if (entry) {
|
||||
// Strip HTML tags from definition for OG quote
|
||||
const plainDef = entry.definitionHtml
|
||||
.replace(/<[^>]*>/g, "")
|
||||
.replace(/&[^;]+;/g, " ")
|
||||
.trim();
|
||||
|
||||
// Check for ?hl= highlight param — extract actual selected text from definition
|
||||
const hlQuote = extractQuoteFromHl(sp, [entry.definitionHtml]);
|
||||
|
||||
return buildOgMeta({
|
||||
title: entry.term,
|
||||
detail: "Glossary — Prabhupāda Says",
|
||||
quote:
|
||||
hlQuote ||
|
||||
(plainDef.length > 260 ? plainDef.slice(0, 257) + "..." : plainDef),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check for ?hl= without ?term= — try to extract quote from all entries for this letter
|
||||
const hlQuote = extractQuoteFromHl(sp);
|
||||
if (hlQuote) {
|
||||
return buildOgMeta({
|
||||
title: `Glossary — ${l}`,
|
||||
detail: "Sanskrit & Vedic terms",
|
||||
quote: hlQuote,
|
||||
});
|
||||
}
|
||||
|
||||
// Default: letter-level OG
|
||||
return buildOgMeta({
|
||||
title: `Glossary — ${l}`,
|
||||
detail: `Sanskrit & Vedic terms starting with ${l}`,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useMemo, useRef, useEffect, useCallback } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import { Search, X, Menu, ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
@@ -289,6 +290,7 @@ export function GlossaryClient({
|
||||
letters,
|
||||
letterCounts,
|
||||
}: Props) {
|
||||
const router = useRouter();
|
||||
const [query, setQuery] = useState("");
|
||||
const [activeTermRaw, setActiveTerm] = useState(entries[0]?.term || "");
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
@@ -347,6 +349,17 @@ export function GlossaryClient({
|
||||
return idx !== undefined ? entries[idx] : null;
|
||||
}, [entries, termIndex, activeTerm]);
|
||||
|
||||
// Update URL with ?term= when active term changes (for OG + shareable links)
|
||||
useEffect(() => {
|
||||
const url = new URL(window.location.href);
|
||||
if (activeTerm) {
|
||||
url.searchParams.set("term", activeTerm);
|
||||
} else {
|
||||
url.searchParams.delete("term");
|
||||
}
|
||||
window.history.replaceState({}, "", url.toString());
|
||||
}, [activeTerm]);
|
||||
|
||||
const handleSelectTerm = useCallback((term: string) => {
|
||||
setActiveTerm(term);
|
||||
contentRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
|
||||
+20
-1
@@ -164,8 +164,27 @@ export function getSourceReference(): {
|
||||
return { title: parentTitle, detail: chapterTitle, url };
|
||||
}
|
||||
|
||||
// /glossary — general
|
||||
// /glossary/[letter]?term=...
|
||||
if (parts[0] === "glossary") {
|
||||
const h1 = document.querySelector("h1");
|
||||
const termFromH1 = h1?.textContent?.replace(/^Glossary:\s*/, "").trim();
|
||||
|
||||
// Try to get the term from the URL ?term= param
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const termFromUrl = urlParams.get("term");
|
||||
|
||||
const term = termFromUrl || termFromH1 || null;
|
||||
|
||||
if (term) {
|
||||
return { title: term, detail: "Glossary — Prabhupāda Says", url };
|
||||
}
|
||||
|
||||
// Fallback: letter-level
|
||||
const letter = parts[1]?.toUpperCase();
|
||||
if (letter) {
|
||||
return { title: `Glossary — ${letter}`, detail: null, url };
|
||||
}
|
||||
|
||||
return { title: "Glossary", detail: null, url };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user