diff --git a/src/features/rehber/components/rehber-makale.tsx b/src/features/rehber/components/rehber-makale.tsx index 6177490..bd7612a 100644 --- a/src/features/rehber/components/rehber-makale.tsx +++ b/src/features/rehber/components/rehber-makale.tsx @@ -76,7 +76,7 @@ export function RehberMakale({ slug }: { slug: string }) { [&_strong]:font-semibold [&_strong]:text-slate-900 [&_ul]:mt-3 [&_ul]:list-disc [&_ul]:space-y-1.5 [&_ul]:pl-6 [&_ol]:mt-3 [&_ol]:list-decimal [&_ol]:space-y-1.5 [&_ol]:pl-6 - [&_table]:mt-4 [&_table]:w-full [&_table]:border-collapse [&_table]:text-sm + [&_.rehber-tablo]:mt-4 [&_.rehber-tablo]:overflow-x-auto [&_table]:w-full [&_table]:border-collapse [&_table]:text-sm [&_th]:border [&_th]:border-slate-200 [&_th]:bg-slate-50 [&_th]:px-3 [&_th]:py-2 [&_th]:text-left [&_th]:font-semibold [&_td]:border [&_td]:border-slate-200 [&_td]:px-3 [&_td]:py-2 [&_blockquote]:mt-4 [&_blockquote]:border-l-4 [&_blockquote]:border-primary/30 [&_blockquote]:pl-4 [&_blockquote]:italic [&_blockquote]:text-slate-600" diff --git a/src/lib/rehber.ts b/src/lib/rehber.ts index de62431..7610d96 100644 --- a/src/lib/rehber.ts +++ b/src/lib/rehber.ts @@ -9,7 +9,7 @@ import { marked } from "marked"; * ile tamamen prerender edilir; runtime'da fs erişimi olmaz). * * Frontmatter elle parse edilir (yalnızca düz `anahtar: değer` satırları) — - * 10 makale için gray-matter bağımlılığına gerek yok. + * bir avuç makale için gray-matter bağımlılığına gerek yok. * * ```mermaid çitleri HTML'e gömülmez: makale parçalara bölünür ve şemalar * sayfada ürünün ortak el çizimi bileşeniyle (ElCizimiSema) çizilir. Çitin @@ -57,6 +57,18 @@ const globalRehber = globalThis as unknown as { }; const CACHE_AKTIF = process.env.NODE_ENV === "production"; +// Değerin TAMAMI aynı tırnakla sarılıysa soyar. İki ucu bağımsız silmek +// `"Alıntı" diye başlayan cümle` gibi değerlerin yalnızca baştaki tırnağını +// yutuyordu; içinde aynı tırnak geçen değer de tam sarılı sayılmaz. +function tirnakSoy(deger: string): string { + if (deger.length < 2) return deger; + const tirnak = deger[0]; + if (tirnak !== '"' && tirnak !== "'") return deger; + if (deger[deger.length - 1] !== tirnak) return deger; + const ic = deger.slice(1, -1); + return ic.includes(tirnak) ? deger : ic; +} + function parseFrontmatter(raw: string): { meta: Record; body: string; @@ -68,10 +80,7 @@ function parseFrontmatter(raw: string): { const ayrac = satir.indexOf(":"); if (ayrac === -1) continue; const anahtar = satir.slice(0, ayrac).trim(); - const deger = satir - .slice(ayrac + 1) - .trim() - .replace(/^["']|["']$/g, ""); + const deger = tirnakSoy(satir.slice(ayrac + 1).trim()); if (anahtar) meta[anahtar] = deger; } return { meta, body: raw.slice(match[0].length) }; @@ -98,26 +107,34 @@ function parseSema(slug: string, ham: string): RehberSema { return { tanim: satirlar.join("\n").trim(), ariaLabel, altyazi }; } +// Geniş tablolar dar ekranda sayfayı taşırmasın: her tablo yatay kayan, +// klavyeyle odaklanabilir bir bölgeye sarılır (stil rehber-makale.tsx'te). +// marked ``'ı özniteliksiz basar; global `marked.use` ile renderer +// değiştirmek yerine çıktı burada sarılır. +function markdownHtml(md: string): string { + return marked + .parse(md, { gfm: true, async: false }) + .replaceAll( + "
", + '
', + ) + .replaceAll("
", ""); +} + function parcala(slug: string, body: string): RehberParca[] { const parcalar: RehberParca[] = []; let son = 0; for (const eslesme of body.matchAll(SEMA_CITI)) { const md = body.slice(son, eslesme.index).trim(); if (md) { - parcalar.push({ - tip: "html", - html: marked.parse(md, { gfm: true, async: false }), - }); + parcalar.push({ tip: "html", html: markdownHtml(md) }); } parcalar.push({ tip: "sema", sema: parseSema(slug, eslesme[1]) }); son = eslesme.index + eslesme[0].length; } const kalan = body.slice(son).trim(); if (kalan) { - parcalar.push({ - tip: "html", - html: marked.parse(kalan, { gfm: true, async: false }), - }); + parcalar.push({ tip: "html", html: markdownHtml(kalan) }); } return parcalar; }