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:
bilalgursen
2026-08-02 04:25:58 +03:00
parent 716f7bb3fb
commit 6bd210075f
10 changed files with 1215 additions and 4 deletions

View File

@@ -0,0 +1,50 @@
---
baslik: Merkezi Yerleştirme Nasıl Çalışır? ÖSYM Seni Nasıl Yerleştirir?
aciklama: "Üst sıraya yazarsam şansımı yakar mıyım?" korkusunun cevabı sistemin kendisinde. ÖSYM'nin yerleştirme mantığı, tek şemada ve öğrenci diliyle.
tarih: 2026-07-26
---
Tercih döneminin en çok aranan sorularından biri şu: *"Tercihler nasıl değerlendiriliyor? Üst sıraya iddialı bir bölüm yazarsam alttaki şansımı kaybeder miyim?"* Kısa cevap: **hayır, kaybetmezsin.** Nedenini anlamak için ÖSYM'nin yerleştirme mantığını bir kez görmek yeter — sistem sandığından çok daha basit çalışır.
## Sistem tek cümlede
ÖSYM önce **adayları** puana göre sıralar, sonra sıra sana gelince **senin listeni** yukarıdan aşağı okur ve boş kontenjan bulduğu ilk satıra seni yerleştirir. Hepsi bu.
```mermaid
%% aria: Merkezi yerleştirme akış şeması: ÖSYM tüm adayları puana göre sıralar ve sıra puanı yüksekten düşüğe ilerler; sıra sana gelince tercih listen birinci satırdan başlayarak kontrol edilir, boş kontenjan bulunan ilk programa yerleşirsin ve alttaki satırlara hiç bakılmaz; 24 satırın hiçbirinde yer yoksa boşta kalırsın ama ek yerleştirme hakkın devam eder.
%% altyazi: Sistem listene her zaman yukarıdan aşağı bakar; bir satıra yerleştiğin an alttaki satırlar devre dışı kalır.
flowchart TD
P("ÖSYM tüm adayları puana göre sıralar<br/>sıra, puanı yüksekten düşüğe ilerler") --> S("Sıra sana geldi:<br/>listen 1. satırdan okunmaya başlar")
S --> T1{"1. tercihinde boş<br/>kontenjan var mı?"}
T1 -- "evet" --> Y("Yerleştin<br/>alttaki satırlara hiç bakılmaz")
T1 -- "hayır" --> T2{"2. tercihinde<br/>boş yer var mı?"}
T2 -- "evet" --> Y
T2 -- "hayır" --> D("aynı soru 24. satıra<br/>kadar tekrarlanır")
D --> B{"24 satırın hiçbirinde<br/>yer kalmadı mı?"}
B -- "boşta kaldın" --> E("Üzülme, bitmedi:<br/>ek yerleştirme hakkın saklı")
classDef garanti fill:#d1fae5,stroke:#10b981,color:#065f46
classDef uyari fill:#fef3c7,stroke:#f59e0b,color:#92400e
class Y garanti
class E uyari
```
## Bu mantıktan çıkan üç altın kural
**1) Üst sıradaki "hayal" tercihi alttakilere zarar veremez.** Sistem 1. tercihinde yer bulamazsa hiç duraksamadan 2.'ye geçer. Hayal bölümünü en üste yazmanın tek "maliyeti" bir satırdır; alttaki dengeli ve garanti tercihlerinin ihtimali kılını bile kıpırdatmaz. Bu yüzden listenin başı gönlüne göre, sonu aklına göre kurulur — dilim mantığının tamamı [tercih listesi rehberinde](/rehber/tercih-listesi-nasil-yapilir) var.
**2) Yerleştiğin satırın altı yok hükmündedir.** 3. tercihine yerleştiysen 4-24 arası hiç okunmaz. Bu yüzden listeyi *yerleşme ihtimaline göre değil, istek sırana göre* dizmelisin: en çok istediğin hep daha üstte durmalı. "Daha çok istediğim bölüm alttaydı, keşke" cümlesinin telafisi yoktur.
**3) Taban sıralaması yerleştirme bittikten sonra oluşur.** Bir programın tabanı, o programa **yerleşen son kişinin** sıralamasıdır. Yani tabanlar önceden ilan edilen bir eşik değil, o yılın adaylarının tercih davranışının sonucudur — bu yüzden yıldan yıla oynar. Detayı [tabanlar nasıl değişir](/rehber/taban-siralamalar-nasil-degisir) yazısında.
## Peki neden hâlâ "ölü tercih" diye bir şey var?
Sistemin yukarıdan aşağı okuması, sıralamanın çok üstünde kapatan bir programı listenin *sonuna* yazmayı anlamsızlaştırır: o satıra sıra geldiyse zaten üstteki 20 satırda yer bulamamışsındır; tabanı senden çok iyi olan o program sana hiç açılmayacaktır. Bu satırlar listede yer kaplayan boş kurşunlardır — tanımı ve temizleme yöntemi için [ölü tercih nedir](/rehber/olu-tercih-nedir) yazısına bak.
## Pratik sonuç
- Listenin başına puanın "yetmeyecek gibi" duran ama çok istediğin programları çekinmeden yaz.
- Ortayı sıralamana yakın programlarla doldur, sona gerçekten razı olacağın garantileri koy.
- Sıralamanla hangi dilime neyin girdiğini görmek için [tercih robotuna](/tercih-robotu) sıralamanı girmen yeterli.
Sistemi bilen aday, listeyi korkuyla değil stratejiyle kurar. Korku listesi hep aşağı yığılır; strateji listesi yukarıdan kazanır.

View File

@@ -0,0 +1,47 @@
---
baslik: OBP Nedir, Nasıl Hesaplanır? Diploma Notu Kaç Puan Getirir?
aciklama: Ortaöğretim başarı puanının hesabı, yerleştirme puanına gerçek katkısı ve "geçen yıl yerleştiysen çarpan yarıya düşer" kuralı — sayılarla ve tek şemada.
tarih: 2026-07-27
---
Tercih döneminde en çok aranan hesap sorusu: *"Diploma notum yerleştirme puanıma kaç puan ekler?"* Cevap net bir formüle dayanır ve iki dakikada öğrenilir. Ama formülün ucunda, tercih stratejini doğrudan etkileyen bir kural saklı: **geçen yıl bir programa yerleşenlerin katkısı yarıya düşer.**
## Hesap üç adımda
Lise diploma notun 50-100 arasındadır. ÖSYM bunu 5 ile çarpar ve **OBP** (Ortaöğretim Başarı Puanı) 250-500 arasında bir değere dönüşür. Yerleştirme puanına eklenen katkı ise OBP'nin 0,12 ile çarpımıdır:
```mermaid
%% aria: OBP hesap şeması: 50 ile 100 arasındaki diploma notu 5 ile çarpılarak 250 ile 500 arasında OBP değerine dönüşür; OBP 0,12 ile çarpılarak 30 ile 60 puan arasında bir katkı üretir ve ham YKS puanına eklenerek yerleştirme puanını oluşturur; geçen yıl merkezi yerleştirmeyle bir programa yerleştiysen çarpan 0,06'ya düşer ve katkı 15 ile 30 puan arasına iner.
%% altyazi: Katkı aralığı 30-60 puandır; iki aday arasındaki gerçek fark ise çoğu zaman birkaç puandır çünkü herkes en az 30 alır.
flowchart TD
D("Diploma notun<br/>50 ile 100 arası") -- "5 ile çarpılır" --> O("OBP<br/>250 ile 500 arası")
O -- "0,12 ile çarpılır" --> K("Yerleştirme puanına katkı<br/>30 ile 60 puan arası")
K --> P("Ham YKS puanın + katkı<br/>= yerleştirme puanın")
O -. "geçen yıl bir programa yerleştiysen<br/>çarpan 0,06 olur" .-> Z("Katkı yarıya düşer<br/>15 ile 30 puan arası")
classDef garanti fill:#d1fae5,stroke:#10b981,color:#065f46
classDef hayal fill:#fee2e2,stroke:#ef4444,color:#991b1b
class P garanti
class Z hayal
```
## Sayının doğru okuması: 60 değil, fark önemli
"60 puana kadar katkı" kulağa devasa gelir ama herkes **en az 30** alır (diploma notu 50 bile olsa). Yani seninle rakibin arasındaki gerçek OBP farkı en fazla 30 puandır ve diploma notları yakınsa bu fark birkaç puana iner. Diploma notu 85 olan bir aday 51 puan katkı alır; 95 olan 57 alır — arada sadece 6 puan vardır. OBP kimseyi tek başına bölüm atlatmaz; **eşit puan bölgesinde sıralamayı birkaç bin kaydırır.** Sıralamanın puandan neden daha önemli olduğu ayrı bir yazının konusu: [taban puan mı, sıralama mı?](/rehber/taban-puan-mi-siralama-mi)
## Kritik kural: çarpan neden yarıya düşer?
Geçen yıl merkezi yerleştirmeyle bir programa **yerleştirildiysen** — kayıt yaptırmamış olsan bile — bu yıl OBP çarpanın 0,12 yerine **0,06** uygulanır (kontenjansız açıköğretim programları bu kuralın dışındadır). Yani "bir yere yerleşeyim de garantim olsun, seneye yine denerim" planının görünmez bir bedeli vardır: gelecek yılki puanından 15-30 puan peşinen gider.
Bunun tercih listene çevirisi şudur: **yerleşsen bile gitmeyeceğin programı listene yazma.** Bu kuralın diğer bedelleriyle birlikte tamamı [tercih listesi rehberinde](/rehber/tercih-listesi-nasil-yapilir) anlatılıyor.
## Okul birincilerine ayrı kapı
Okul birincileri için üniversitelerde **ayrı bir kontenjan** ayrılır (2026'da yaklaşık 17 bin 862 kişilik). Okul birincisi, hem genel kontenjandan hem de okul birincisi kontenjanından değerlendirilir — hangisinden yerleşirse o geçerli olur. Ayrıca 2026'da şehit ve gazi yakınları ile 34 yaş üstü kadın adaylar için de özel kontenjanlar var; sonuç belgende bu kontenjanlardan birine hakkın görünüyorsa tercih ekranında ayrıca işaretlemeyi unutma.
## Özet
- OBP = diploma notu × 5; katkı = OBP × 0,12 → **30-60 puan arası.**
- Herkes en az 30 aldığı için gerçek rekabet farkı küçüktür; asıl belirleyici sınav performansın ve sıralamandır.
- Geçen yıl yerleştiysen çarpan yarıya düşer — istemediğin programı listeye yazmanın en somut cezası budur.
- Sıralamanla nereye uzanabildiğini görmek için [tercih robotunu](/tercih-robotu) kullanabilirsin.

View File

@@ -0,0 +1,59 @@
---
baslik: Üniversite Kaydı Nasıl Yapılır? 2026 e-Kayıt ve Belge Rehberi
aciklama: Yerleştin, tebrikler — şimdi kaydını kaçırma. e-Devlet'ten 5 dakikada e-kayıt, şahsen kayıtta istenen belgeler ve "kayıt yaptırmazsam ne olur" sorusunun net cevabı.
tarih: 2026-07-28
---
Yerleştirme sonuçlarııklandıktan sonra en çok aranan soru değişir: "nereye yerleştim"in yerini **"kayıt nasıl yapılır, son gün ne zaman?"** alır. 2026'da kayıtlar **24-28 Ağustos** tarihleri arasında; e-Devlet üzerinden elektronik kayıt ise **24-26 Ağustos** günlerinde yapılabiliyor. Takvimin tamamı için [2026 tercih takvimi](/rehber/yks-tercih-takvimi-2026) yazısına bakabilirsin.
## Önce e-kayıt dene: belge yok, yol yok, sıra yok
Üniversitelerin büyük bölümü e-Devlet üzerinden **e-kayıt** kabul ediyor. e-Devlet'e girip *"Üniversite E-Kayıt"* hizmetini açtığında yerleştiğin program listeleniyorsa birkaç onayla kaydın tamamlanır — diploma, fotoğraf, şehirlerarası yolculuk gerekmez. Kayıt belgeni yine e-Devlet'ten barkodlu indirebilirsin.
```mermaid
%% aria: Üniversite kayıt akış şeması: bir programa yerleştikten sonra kayıt yaptırmaya karar verirsen önce e-Devlet'te e-kayıt seçeneğini kontrol edersin; açıksa 24-26 Ağustos arasında belgesiz ve sırasız e-kayıt yaparsın, kapalıysa 24-28 Ağustos arasında belgelerinle üniversiteye giderek şahsen kayıt olursun; iki yol da kaydını tamamlar. Kayıt yaptırmazsan bu yılki hakkın yanar, yerleştiğin için ek yerleştirmeye giremezsin ve gelecek yıl OBP katkın yarıya düşer.
%% altyazi: e-kayıt penceresi şahsen kayıttan iki gün önce kapanır; önce e-kaydı dene, olmuyorsa belgelerle yola çık.
flowchart TD
S("Sonuçlar açıklandı:<br/>bir programa yerleştin") --> K{"Kayıt yaptıracak mısın?"}
K -- "evet" --> E{"e-Devlet'te e-kayıt<br/>seçeneğin açık mı?"}
E -- "evet" --> E1("24-26 Ağustos: e-kayıt<br/>belge yok, sıra yok, 5 dakika")
E -- "hayır" --> E2("24-28 Ağustos: üniversitede şahsen kayıt<br/>belgelerini yanına al")
E1 --> T("Kaydın tamam,<br/>artık öğrencisin")
E2 --> T
K -- "hayır" --> R("Bu yılki hakkın yanar:<br/>ek yerleştirmeye giremezsin,<br/>gelecek yıl OBP katkın yarıya düşer")
classDef garanti fill:#d1fae5,stroke:#10b981,color:#065f46
classDef hayal fill:#fee2e2,stroke:#ef4444,color:#991b1b
class T garanti
class R hayal
```
## Şahsen kayıtta istenen belgeler
Üniversiteler kendi listesini yayımlar; standart çekirdek şudur:
- **Lise diploması** (aslı) ya da yeni mezunlar için mezuniyet belgesi
- **ÖSYS yerleştirme sonuç belgesi** (internet çıktısı yeterli)
- Nüfus cüzdanı / T.C. kimlik kartı ve fotokopisi
- Vesikalık fotoğraf (genelde 4-6 adet)
- Bazı programlar için ek koşul belgeleri: sağlık raporu, boy-kilo şartı, mülakat sonucu gibi — bunlar kılavuzda programın yanındaki koşul numaralarında yazar
İkinci öğretim ya da vakıf programına yerleştiysen ilk taksit/öğrenim ücreti dekontu da istenir. Gitmeden önce üniversitenin kayıt sayfasını mutlaka aç; eksik belge, kayıt döneminin en klasik zaman kaybıdır.
## "Kayıt yaptırmazsam ne olur?"
Bu sorunun cevabı üç maddedir ve üçü de önemlidir:
1. **Bu yılki hakkın yanar.** Yerleştiğin programa sonradan "vazgeçtim, geleyim" diyemezsin.
2. **Ek yerleştirmeye giremezsin.** Kayıt yaptırmasan bile *yerleştirilmiş* sayılırsın ve [ek yerleştirme](/rehber/ek-yerlestirme-2026) kapısı sana kapanır.
3. **Gelecek yıl OBP çarpanın yarıya düşer.** Seneye tekrar sınava girersen diploma notu katkın 0,12 yerine 0,06 ile hesaplanır — [OBP yazısında](/rehber/obp-nedir-nasil-hesaplanir) sayılarla anlattık.
Bu üç maddenin tek bir tercih dersi var: **kayıt yaptırmayacağın programı listene hiç yazma.** Liste kurarken bu süzgeci nasıl uygulayacağın [tercih listesi rehberinde](/rehber/tercih-listesi-nasil-yapilir).
## Kayıt sonrası küçük ama önemli işler
- Ders kaydı / oryantasyon tarihlerini üniversitenin öğrenci işleri sayfasından not al; kayıt olmak çoğu üniversitede ders seçimini otomatik yapmaz.
- Yurt başvurusu (KYK) ayrı bir takvimle yürür — kayıt haftasını beklemeden başvuru dönemini takip et.
- Öğrenci belgeni e-Devlet'ten alabilirsin; indirim ve burs başvurularının çoğu bunu ister.
Yerleşmek maratonun bitişi, kayıt ise ipi göğüslemek. Son güne bırakma — e-kayıt penceresi, şahsen kayıttan **iki gün önce** kapanıyor.

View File

@@ -0,0 +1,55 @@
---
baslik: Yerleşemedim ya da İstemediğim Bölüme Yerleştim — Şimdi Ne Olacak?
aciklama: Sonuç ekranı istediğin gibi çıkmadıysa önünde hâlâ üç yol var: ek yerleştirme, yatay geçiş ve yeniden deneme. Hangi durumda hangisi mantıklı, tek şemada.
tarih: 2026-08-01
---
Sonuçlar açıklandığında iki tür hayal kırıklığı yaşanır: hiçbir tercihe yerleşememek ya da listenin sonlarındaki "keşke yazmasaydım" satırına yerleşmek. İkisi de yolun sonu değil — ama ikisinin kuralları **birbirinden çok farklı** ve yanlış hamle, doğru kapıyı kapatabiliyor.
## Önce durumunu netleştir
```mermaid
%% aria: Yerleşememe durumunda karar şeması: sonuç ekranında hiçbir tercihe yerleşemediysen ek yerleştirmeye başvurabilirsin ve boş kontenjanlar için yeni bir 24 tercihlik liste yaparsın; istemediğin bir programa yerleştiysen iki yol vardır: kayıt yaptırırsan birinci sınıfta merkezi yerleştirme puanınla yatay geçiş kapısını araştırabilirsin, kayıt yaptırmazsan yerleşmiş sayıldığın için ek yerleştirmeye giremezsin ve kalan tek yol gelecek yıl yeniden sınava girmektir.
%% altyazi: Kritik ayrım: "yerleşemedim" ek yerleştirme kapısını açar; "yerleştim ama gitmedim" o kapıyı kapatır.
flowchart TD
S{"Sonuç ekranında<br/>ne yazıyor?"}
S -- "hiçbir tercihe yerleşemedin" --> E("Ek yerleştirme hakkın var:<br/>boş kontenjanlar için yeni bir liste")
E --> E2("Eylülde ÖSYM kılavuzu yayımlar,<br/>yeniden 24 tercih yaparsın")
S -- "istemediğin bir programa yerleştin" --> K{"Kayıt yaptıracak mısın?"}
K -- "evet" --> Y("Kayıt ol; 1. sınıfta merkezi puanla<br/>yatay geçiş kapısını araştır")
K -- "hayır" --> R("Yerleşmiş sayılırsın:<br/>ek yerleştirmeye giremezsin,<br/>kalan yol gelecek yıl yeniden YKS")
classDef uyari fill:#fef3c7,stroke:#f59e0b,color:#92400e
classDef garanti fill:#d1fae5,stroke:#10b981,color:#065f46
classDef hayal fill:#fee2e2,stroke:#ef4444,color:#991b1b
class E,E2 uyari
class Y garanti
class R hayal
```
## Yol 1: Ek yerleştirme — boşta kalanların ikinci şansı
İlk yerleştirmede **hiçbir programa yerleşemediysen** ek yerleştirmeye başvurabilirsin. Kayıt dönemi bitince boş kalan ve kayıt yaptırılmadığı için boşalan kontenjanlar ÖSYM'nin ek kılavuzunda ilan edilir; yeniden en fazla 24 tercih yaparsın. Tabanlar ilk yerleştirmeye göre genelde gevşer ama en çok istenen programlar ek yerleştirmeye nadiren kalır. Kimin başvurabileceği, takvimi ve stratejisiyle tüm detaylar [ek yerleştirme rehberinde](/rehber/ek-yerlestirme-2026).
Kritik kural bir kez daha: bir programa **yerleştirildiysen** — kayıt yaptırmamış olsan bile — ek yerleştirme sana kapalıdır. "İstemediğim yere yerleştim, kayıt olmayayım, ek tercihte daha iyisini yazarım" planı **çalışmaz.**
## Yol 2: Kayıt ol + yatay geçişi araştır
İstemediğin programa yerleştiysen çoğu durumda en az riskli hamle **kayıt olmaktır.** Çünkü kayıtlı öğrenciye açık bir kapı var: **merkezi yerleştirme puanıyla (Ek Madde-1) yatay geçiş.** Mantığı şu:
- YKS'de aldığın puan, yerleştiğin yıl için geçerliliğini korur.
- Puanın, geçmek istediğin programın **senin yerleştiğin yıldaki** taban puanına eşit ya da ondan yüksekse başvurabilirsin.
- Başvuru, yerleştiğin yıl içinde değil, öğrenimin başladıktan sonraki dönemlerde (üniversitelerin ilan ettiği kontenjan ve takvimle) yapılır ve bu hak **bir kez** kullanılır.
Yani "puanım aslında X bölümüne yetiyordu ama listeme yazmamıştım" durumundaysan, bir dönem/yıl sonra o bölüme sınavsız geçme ihtimalin var. Kontenjanlar sınırlı ve üniversiteden üniversiteye değişir; hedef üniversitenin yatay geçiş sayfasını şimdiden takibe al.
## Yol 3: Yeniden denemek — bedelini bilerek
Gelecek yıl tekrar sınava girmek meşru bir plan; ama iki bedelini baştan bil:
1. **OBP çarpanı:** bir programa yerleştirildiysen (kayıt yaptırmasan bile) gelecek yıl diploma notu katkın yarıya düşer — hesabı [OBP yazısında](/rehber/obp-nedir-nasil-hesaplanir).
2. **Tabanlar sabit durmaz:** bu yıl "az farkla kaçırdığın" bölümün tabanı seneye aynı yerde olmayabilir — [tabanlar nasıl değişir](/rehber/taban-siralamalar-nasil-degisir) yazısı bu oynaklığı verilerle gösteriyor.
## Bir dahaki listeye ders
Bu durumların neredeyse tamamı, liste kurulurken önlenebilir: sonuna gerçekten razı olacağın garantiler koymak, kayıt yaptırmayacağın satırı hiç yazmamak ve [ölü tercihleri](/rehber/olu-tercih-nedir) temizlemek. Ek yerleştirme listesi kuracaksan da aynı disiplin geçerli — sıralamana göre gerçekçi seçenekleri [tercih robotunda](/tercih-robotu) saniyeler içinde görebilirsin.

View File

@@ -27,6 +27,7 @@
"lenis": "^1.3.25", "lenis": "^1.3.25",
"lucide-react": "^1.25.0", "lucide-react": "^1.25.0",
"marked": "^18.0.7", "marked": "^18.0.7",
"mermaid": "^11.16.0",
"motion": "^12.42.2", "motion": "^12.42.2",
"next": "16.2.10", "next": "16.2.10",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
@@ -45,6 +46,7 @@
"turkey-map-react": "^2.0.5", "turkey-map-react": "^2.0.5",
"tw-animate-css": "^1.4.0", "tw-animate-css": "^1.4.0",
"use-stick-to-bottom": "^1.1.6", "use-stick-to-bottom": "^1.1.6",
"vaul": "^1.1.2",
"zod": "^4.4.3" "zod": "^4.4.3"
}, },
"devDependencies": { "devDependencies": {

836
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@ import { ChevronRight } from "lucide-react";
import { getAllRehberSlugs, getAllRehberler, getRehber } from "@/lib/rehber"; import { getAllRehberSlugs, getAllRehberler, getRehber } from "@/lib/rehber";
import { JsonLd, articleJsonLd, breadcrumbJsonLd } from "@/lib/seo"; import { JsonLd, articleJsonLd, breadcrumbJsonLd } from "@/lib/seo";
import { CtaSiraForm } from "@/components/cta-sira-form"; import { CtaSiraForm } from "@/components/cta-sira-form";
import { ElCizimiSema } from "@/components/el-cizimi-sema";
import { RehberKapak } from "@/components/rehber-kapak"; import { RehberKapak } from "@/components/rehber-kapak";
import { SiteFooter } from "@/components/site-footer"; import { SiteFooter } from "@/components/site-footer";
@@ -103,8 +104,23 @@ export default async function RehberYaziPage({
[&_th]:border [&_th]:border-slate-200 [&_th]:bg-slate-50 [&_th]:px-3 [&_th]:py-2 [&_th]:text-left [&_th]:font-semibold [&_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 [&_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" [&_blockquote]:mt-4 [&_blockquote]:border-l-4 [&_blockquote]:border-primary/30 [&_blockquote]:pl-4 [&_blockquote]:italic [&_blockquote]:text-slate-600"
dangerouslySetInnerHTML={{ __html: yazi.html }} >
/> {yazi.parcalar.map((parca, i) =>
parca.tip === "html" ? (
<div
key={i}
dangerouslySetInnerHTML={{ __html: parca.html }}
/>
) : (
<ElCizimiSema
key={i}
tanim={parca.sema.tanim}
ariaLabel={parca.sema.ariaLabel}
figcaption={parca.sema.altyazi}
/>
),
)}
</div>
</article> </article>
<div className="mt-12"> <div className="mt-12">

View File

@@ -0,0 +1,85 @@
"use client";
// Ürün genelindeki "el çizimi" mermaid şemalarının tek kaynağı: /meraklisina
// hunisi de rehber yazılarındaki şemalar da bu bileşenle çizilir, böylece
// görünüm (font, renk teması, çizgi titremesi) her yerde birebir aynı kalır.
// Mermaid ağır bir paket olduğu için useEffect içinde dinamik import edilir;
// sayfa paketine girmez.
import { useEffect, useId, useState } from "react";
import localFont from "next/font/local";
// Şemanın "el çizimi" görünümüne uyan el yazısı fontu (Sweet Cucumber
// Mocktail, Misti's Fonts). Türkçe glifler doğrulandı (ş, ğ, ı, İ… hepsi
// var). DİKKAT: lisans "kişisel kullanım için ücretsiz" — canlıya çıkmadan
// mistifonts.com/sweet-cucumber-mocktail adresinden ticari lisans alınmalı.
const elYazisi = localFont({
src: "../fonts/SweetCucumberMocktail.woff2",
display: "swap",
});
export function ElCizimiSema({
tanim,
ariaLabel,
figcaption,
}: {
/** Mermaid tanımı (flowchart vb.) */
tanim: string;
/** Şemanın tamamını anlatan erişilebilirlik metni */
ariaLabel: string;
figcaption?: React.ReactNode;
}) {
const [svg, setSvg] = useState<string | null>(null);
// mermaid.render'ın istediği DOM id'si: useId'nin ":" karakterleri geçersiz
const semaId = `sema-${useId().replace(/[^a-zA-Z0-9-]/g, "")}`;
useEffect(() => {
let iptal = false;
import("mermaid").then(async ({ default: mermaid }) => {
mermaid.initialize({
startOnLoad: false,
look: "handDrawn",
handDrawnSeed: 7, // her render'da aynı çizgi titremesi (deterministik)
theme: "base",
fontFamily: `${elYazisi.style.fontFamily}, cursive`,
themeVariables: {
primaryColor: "#ffffff",
primaryBorderColor: "#e2e8f0",
primaryTextColor: "#0f172a",
lineColor: "#94a3b8",
edgeLabelBackground: "#ffffff",
fontFamily: `${elYazisi.style.fontFamily}, cursive`,
fontSize: "17px", // script fontun x-yüksekliği düşük; okunurluk için büyütüldü
},
});
const sonuc = await mermaid.render(semaId, tanim);
if (!iptal) setSvg(sonuc.svg);
});
return () => {
iptal = true;
};
}, [semaId, tanim]);
return (
<figure className="mt-6">
{svg ? (
<div
role="img"
aria-label={ariaLabel}
className={`${elYazisi.className} overflow-x-auto [&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full`}
dangerouslySetInnerHTML={{ __html: svg }}
/>
) : (
<div
aria-hidden
className="h-96 animate-pulse rounded-xl bg-slate-100"
/>
)}
{figcaption ? (
<figcaption className="mt-3 text-xs text-slate-500">
{figcaption}
</figcaption>
) : null}
</figure>
);
}

Binary file not shown.

View File

@@ -9,6 +9,11 @@ import { marked } from "marked";
* *
* Frontmatter elle parse edilir (yalnızca düz `anahtar: değer` satırları) — * 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. * 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 = { export type RehberOzet = {
@@ -19,7 +24,18 @@ export type RehberOzet = {
tarih: string; 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"); 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) }; 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 { function oku(slug: string): RehberYazi | null {
const dosya = path.join(REHBER_DIZIN, `${slug}.md`); const dosya = path.join(REHBER_DIZIN, `${slug}.md`);
if (!fs.existsSync(dosya)) return null; if (!fs.existsSync(dosya)) return null;
@@ -57,7 +118,7 @@ function oku(slug: string): RehberYazi | null {
baslik: meta.baslik, baslik: meta.baslik,
aciklama: meta.aciklama, aciklama: meta.aciklama,
tarih: meta.tarih, tarih: meta.tarih,
html: marked.parse(body, { gfm: true, async: false }), parcalar: parcala(slug, body),
}; };
} }