Rehbere mermaid şema desteği ve 4 yeni tercih dönemi yazısı ekle
Markdown'daki \`\`\`mermaid çitleri artık yazıyı parçalara bölüyor ve şemalar üründeki ortak el çizimi bileşeniyle (ElCizimiSema) çiziliyor; çitte "%% aria:" satırı zorunlu, "%% altyazi:" figcaption veriyor. Tercih dönemi aramalarına dayanan dört yeni yazı: merkezi yerleştirme algoritması, OBP hesabı, üniversite kayıt rehberi ve yerleşememe/istenmeyen bölüm karar ağacı — her biri risk renk dilinde birer şemayla. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,11 @@ import { marked } from "marked";
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ```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
|
||||
* içinde `%% aria:` satırı zorunludur (erişilebilirlik metni), `%% altyazi:`
|
||||
* isteğe bağlı figcaption verir; iki satır da mermaid tanımından çıkarılır.
|
||||
*/
|
||||
|
||||
export type RehberOzet = {
|
||||
@@ -19,7 +24,18 @@ export type RehberOzet = {
|
||||
tarih: string;
|
||||
};
|
||||
|
||||
export type RehberYazi = RehberOzet & { html: string };
|
||||
export type RehberSema = {
|
||||
/** Mermaid tanımı (aria/altyazi yönergeleri ayıklanmış hâli) */
|
||||
tanim: string;
|
||||
ariaLabel: string;
|
||||
altyazi?: string;
|
||||
};
|
||||
|
||||
export type RehberParca =
|
||||
| { tip: "html"; html: string }
|
||||
| { tip: "sema"; sema: RehberSema };
|
||||
|
||||
export type RehberYazi = RehberOzet & { parcalar: RehberParca[] };
|
||||
|
||||
const REHBER_DIZIN = path.join(process.cwd(), "content", "rehber");
|
||||
|
||||
@@ -43,6 +59,51 @@ function parseFrontmatter(raw: string): {
|
||||
return { meta, body: raw.slice(match[0].length) };
|
||||
}
|
||||
|
||||
const SEMA_CITI = /^```mermaid[ \t]*\r?\n([\s\S]*?)^```[ \t]*$/gm;
|
||||
|
||||
function parseSema(slug: string, ham: string): RehberSema {
|
||||
let ariaLabel = "";
|
||||
let altyazi: string | undefined;
|
||||
const satirlar: string[] = [];
|
||||
for (const satir of ham.split(/\r?\n/)) {
|
||||
const aria = satir.match(/^%%\s*aria:\s*(.+)$/);
|
||||
const alt = satir.match(/^%%\s*altyazi:\s*(.+)$/);
|
||||
if (aria) ariaLabel = aria[1].trim();
|
||||
else if (alt) altyazi = alt[1].trim();
|
||||
else satirlar.push(satir);
|
||||
}
|
||||
if (!ariaLabel) {
|
||||
throw new Error(
|
||||
`rehber: ${slug}.md içindeki mermaid şemasında "%% aria: ..." satırı zorunlu`,
|
||||
);
|
||||
}
|
||||
return { tanim: satirlar.join("\n").trim(), ariaLabel, altyazi };
|
||||
}
|
||||
|
||||
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: "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 }),
|
||||
});
|
||||
}
|
||||
return parcalar;
|
||||
}
|
||||
|
||||
function oku(slug: string): RehberYazi | null {
|
||||
const dosya = path.join(REHBER_DIZIN, `${slug}.md`);
|
||||
if (!fs.existsSync(dosya)) return null;
|
||||
@@ -57,7 +118,7 @@ function oku(slug: string): RehberYazi | null {
|
||||
baslik: meta.baslik,
|
||||
aciklama: meta.aciklama,
|
||||
tarih: meta.tarih,
|
||||
html: marked.parse(body, { gfm: true, async: false }),
|
||||
parcalar: parcala(slug, body),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user