Update routing in next.config.ts to redirect "/tercih-robotu" to the hero form, add simple-icons dependency in package.json, and enhance database indexing for improved query performance. Remove unused SVG files and update metadata across various pages for better SEO and clarity.
All checks were successful
Deploy / deploy (push) Successful in 14m14s
All checks were successful
Deploy / deploy (push) Successful in 14m14s
This commit is contained in:
90
src/lib/rehber.ts
Normal file
90
src/lib/rehber.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { marked } from "marked";
|
||||
|
||||
/**
|
||||
* Rehber makaleleri: content/rehber/*.md dosyaları build sırasında okunur ve
|
||||
* statik HTML'e gömülür (sayfalar generateStaticParams + dynamicParams=false
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type RehberOzet = {
|
||||
slug: string;
|
||||
baslik: string;
|
||||
aciklama: string;
|
||||
/** ISO tarih — Article JSON-LD datePublished */
|
||||
tarih: string;
|
||||
};
|
||||
|
||||
export type RehberYazi = RehberOzet & { html: string };
|
||||
|
||||
const REHBER_DIZIN = path.join(process.cwd(), "content", "rehber");
|
||||
|
||||
function parseFrontmatter(raw: string): {
|
||||
meta: Record<string, string>;
|
||||
body: string;
|
||||
} {
|
||||
const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
||||
if (!match) return { meta: {}, body: raw };
|
||||
const meta: Record<string, string> = {};
|
||||
for (const satir of match[1].split(/\r?\n/)) {
|
||||
const ayrac = satir.indexOf(":");
|
||||
if (ayrac === -1) continue;
|
||||
const anahtar = satir.slice(0, ayrac).trim();
|
||||
const deger = satir
|
||||
.slice(ayrac + 1)
|
||||
.trim()
|
||||
.replace(/^["']|["']$/g, "");
|
||||
if (anahtar) meta[anahtar] = deger;
|
||||
}
|
||||
return { meta, body: raw.slice(match[0].length) };
|
||||
}
|
||||
|
||||
function oku(slug: string): RehberYazi | null {
|
||||
const dosya = path.join(REHBER_DIZIN, `${slug}.md`);
|
||||
if (!fs.existsSync(dosya)) return null;
|
||||
const { meta, body } = parseFrontmatter(fs.readFileSync(dosya, "utf8"));
|
||||
if (!meta.baslik || !meta.aciklama || !meta.tarih) {
|
||||
throw new Error(
|
||||
`rehber: ${slug}.md frontmatter eksik (baslik/aciklama/tarih zorunlu)`,
|
||||
);
|
||||
}
|
||||
return {
|
||||
slug,
|
||||
baslik: meta.baslik,
|
||||
aciklama: meta.aciklama,
|
||||
tarih: meta.tarih,
|
||||
html: marked.parse(body, { gfm: true, async: false }),
|
||||
};
|
||||
}
|
||||
|
||||
export function getAllRehberSlugs(): string[] {
|
||||
if (!fs.existsSync(REHBER_DIZIN)) return [];
|
||||
return fs
|
||||
.readdirSync(REHBER_DIZIN)
|
||||
.filter((f) => f.endsWith(".md"))
|
||||
.map((f) => f.replace(/\.md$/, ""))
|
||||
.sort();
|
||||
}
|
||||
|
||||
export function getRehber(slug: string): RehberYazi | null {
|
||||
// path traversal koruması: slug yalnızca dosya adı olabilir
|
||||
if (!/^[a-z0-9-]+$/.test(slug)) return null;
|
||||
return oku(slug);
|
||||
}
|
||||
|
||||
export function getAllRehberler(): RehberOzet[] {
|
||||
return getAllRehberSlugs()
|
||||
.map((slug) => oku(slug))
|
||||
.filter((y): y is RehberYazi => y !== null)
|
||||
.map(({ slug, baslik, aciklama, tarih }) => ({
|
||||
slug,
|
||||
baslik,
|
||||
aciklama,
|
||||
tarih,
|
||||
}))
|
||||
.sort((a, b) => b.tarih.localeCompare(a.tarih));
|
||||
}
|
||||
Reference in New Issue
Block a user