--- // Poet (/p238), category (/p238/shaeri/c641) and poem (/p238/shaeri/c641/sh6556) pages import Base from '../layouts/Base.astro'; import Seg from '../components/Seg.astro'; import Tags from '../components/Tags.astro'; import { api } from '../lib/api'; import { asUser, COOKIE } from '../lib/auth'; import { phraseParts, phraseRe } from '../lib/phrases'; import { ud, years, highlighter, parts } from '../lib/urdu'; const url = '/' + (Astro.params.path ?? ''); const page = await api(`/api/page?url=${encodeURIComponent(url)}`); if (!page) return new Response(null, { status: 404, statusText: 'Not found' }); // group verses into couplets / single lines / paragraphs for rendering type Verse = { position: string; couplet: number; text: string }; const blocks: { kind: 'couplet' | 'single' | 'para'; lines: string[]; c: number; mark?: string }[] = []; if (page.type === 'poem') { const { matla, maqta } = page.poem; for (const v of page.verses as Verse[]) { if (v.position === 'Right') blocks.push({ kind: 'couplet', lines: [v.text], c: v.couplet, mark: v.couplet === matla ? 'مطلع' : v.couplet === maqta ? 'مقطع' : undefined }); else if (v.position === 'Left' && blocks.at(-1)?.kind === 'couplet' && blocks.at(-1)!.lines.length === 1) blocks.at(-1)!.lines.push(v.text); else if (v.position === 'Paragraph') blocks.push({ kind: 'para', lines: [v.text], c: v.couplet }); else blocks.push({ kind: 'single', lines: [v.text], c: v.couplet }); } } // pen name (marked ؔ in the text) set apart; split() with a capture group puts matches at odd indexes // ?hl= (from search results) marks the searched words on the page; segments: [text, 'mark' | 'pen' | ''] const hlq = Astro.url.searchParams.get('hl') ?? ''; const re = highlighter(hlq); // bookmarked phrases first ('bmk', carrying what to un-bookmark), then search hits, then the pen name type Mark = { part: string; save: string }; const show = (line: string, marks: Mark[] = []): [string, string, string?][] => { const plain = (text: string) => parts(text, re).flatMap((s, i): [string, string][] => i % 2 ? [[s, 'mark']] : s.split(/(\S*\u0614\S*)/).map((t, j) => [t, j % 2 ? 'pen' : ''])); if (!marks.length) return plain(line); const bm = new RegExp(`(${marks.map((m) => phraseRe(m.part).source).join('|')})`, 'u'); return line.split(bm).flatMap((s, i): [string, string, string?][] => i % 2 ? [[s, 'bmk', marks.find((m) => phraseRe(m.part).test(s))?.save]] : plain(s)); }; // contents of a divan grouped by radif letter ("ردیف الف … ی"); ے is filed under ی as in printed divans const LETTER = (l: string) => (l === 'ا' ? 'الف' : l === 'ے' ? 'ی' : l); const groups: { letter: string | null; poems: any[] }[] = []; for (const p of page.poems ?? []) { const l = p.radif_letter ? LETTER(p.radif_letter) : null; if (groups.at(-1)?.letter !== l || !groups.length) groups.push({ letter: l, poems: [] }); groups.at(-1)!.poems.push(p); } const crumbs = page.breadcrumbs ?? []; // what the signed-in reader has bookmarked on this page (poet, book/chapter, poem, couplets, phrases) const token = Astro.locals.user ? Astro.cookies.get(COOKIE)?.value : undefined; const poetId = page.poet?.id, poemId = page.type === 'poem' ? page.poem.id : undefined; const categoryId = page.type === 'category' ? page.category.id : undefined; const saved = token ? (await asUser(token, `/api/library/state?poet=${poetId ?? ''}&category=${categoryId ?? ''}&poem=${poemId ?? ''}`)).data : { poet: false, category: false, poem: false, couplets: [], phrases: [] }; // on contents pages: which works are bookmarked or hold bookmarks, and which books/chapters do const marks = token && page.type !== 'poem' ? (await asUser(token, '/api/library/marks')).data : { poems: {}, categories: [] }; const glyph = (poemId: number) => (marks.poems[poemId]?.fav ? ' mark-fav' : '') + (marks.poems[poemId]?.bm ? ' mark-bm' : ''); // the marked part of each line of a block, for its bookmarked phrases const lineMarks = (c: number, lines: string[]) => { const out: Mark[][] = lines.map(() => []); for (const p of saved.phrases.filter((x: any) => x.couplet === c)) { const save = JSON.stringify({ kind: 'phrase', poemId, couplet: c, phrase: p.phrase }); phraseParts(lines, p.phrase).forEach((part, i) => part && out[i].push({ part, save })); } return out; }; const label = (on: unknown) => (on ? 'محفوظ شدہ' : 'محفوظ کریں'); // bookmark buttons // moderators who may edit this work get edit and history links const modCan = token && poemId && ['mod-l2', 'mod-l1', 'admin'].includes(Astro.locals.user?.role ?? '') ? (await asUser(token, `/api/mod/can?poem=${poemId}`)).data : { edit: false }; // on poet and book/section pages, moderators with the arrange permission get "ترتیب دیں" (#41) const catCan = token && page.type !== 'poem' && ['mod-l2', 'mod-l1', 'admin'].includes(Astro.locals.user?.role ?? '') ? (await asUser(token, `/api/mod/can?category=${page.category.id}`)).data : {}; const arrange = catCan.arrange, tagCan = page.type === 'poem' ? modCan.tags : catCan.tags; // tags (#52): the page's own, and each couplet's (tags count couplets from 1, verses from 0) const pageTags = (page.tags ?? []).filter((t: any) => !t.couplet); const coupletTags = (c: number) => (page.tags ?? []).filter((t: any) => t.couplet === c + 1); // every poet has an ای بکس section beside their books and genres (/p17/ebooks) const ebookCount = page.type === 'poet' ? ((await api(`/api/ebooks?poet=${poetId}`)) ?? []).length : 0; const tagTarget = page.type === 'poem' ? `work/${poemId}` : `category/${page.category?.id}`; const bookmark = (c: number) => JSON.stringify({ kind: 'couplet', poemId, couplet: c }); const title = page.type === 'poem' ? page.poem.title : page.type === 'poet' ? page.poet.nickname : page.category.title; import Icon from '../components/Icon.astro'; --- {page.type !== 'poet' && ( )} {page.type === 'poet' && ( <>

{page.poet.name}

{arrange && <>
}{tagCan && <>
}

{years(page.poet)}

{page.poet.description &&
{page.poet.description}
} )} {page.type === 'category' && ( <>

{page.category.title}

{arrange && <>
}{tagCan && <>
}
)} {page.type !== 'poem' && (page.children.length > 0 || page.type === 'poet') && (
{page.children.map((c: any) => ( {c.title}{c.poems > 0 && {ud(c.poems)}} ))} {page.type === 'poet' && ای بکس{ebookCount > 0 && {ud(ebookCount)}}}
)} {page.type !== 'poem' && groups.map((g) => ( <> {g.letter &&

ردیف {g.letter}

}
    {g.poems.map((p: any) =>
  1. {p.title}
  2. )}
))} {page.type === 'poem' && ( <>

{re && (

«{hlq}» نمایاں · تلاش کے نتائج · نشان ہٹائیں

)}
{modCan.edit && <>
}{tagCan && <>
}
{page.poem.radif != null &&

{page.poem.radif ? `ردیف: ${page.poem.radif}` : 'غیر مردف'}

}
{blocks.map((b) => { const bm =

کسی لفظ کو منتخب کریں تو اس کے معنی اور تلفظ ساتھ نظر آئیں گے۔

{page.divan && (

دیوان کا ورژن {ud(page.divan.version)} · ترمیم: {page.divan.by}{page.divan.reviewedBy && <> · جائزہ: {page.divan.reviewedBy}} · اشاعت: {page.divan.publishedBy} · {new Date(page.divan.at).toISOString().slice(0, 10)} {page.divan.commit_url && <> · تبدیلی دیکھیں}

)} {page.poem.source_url && (

ماخذ: ویکی ماخذ · {page.poet && {page.poet.nickname}}

)} )} {re && }