Add new podcast episodes and update content structure
- Created new podcast episode files for "Freelance Client Stories", "Productivity Without Burnout", "Conversations with Builders", "Stable Frontend Systems", "Writing Cleaner Service Layers", and "Foundations Over Tools" with relevant metadata and episode notes. - Introduced a new TypeScript type definition for PodcastKind and PodcastEpisode to enhance type safety. - Implemented a content reading function to fetch and sort podcast episodes by date. - Updated package.json to include new dependencies: gray-matter for markdown parsing and pdfjs-dist for PDF handling. - Added PDF files for Atomic Design and personal resume to the public directory.
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
import { ContentContent } from "@/components/content-content";
|
||||||
|
import { YOUTUBE_VIDEO_LINKS } from "@/data/youtube-videos";
|
||||||
|
import { getPdfNotes, getPodcastCollections } from "@/lib/content-page";
|
||||||
|
|
||||||
|
export default async function ContentPage() {
|
||||||
|
const [{ yazilim, masaBasi }, pdfFiles] = await Promise.all([
|
||||||
|
getPodcastCollections(),
|
||||||
|
getPdfNotes(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ContentContent
|
||||||
|
yazilimEpisodes={yazilim}
|
||||||
|
masaBasiEpisodes={masaBasi}
|
||||||
|
youtubeLinks={YOUTUBE_VIDEO_LINKS}
|
||||||
|
pdfFiles={pdfFiles}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,371 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import ReactMarkdown from "react-markdown";
|
||||||
|
import remarkGfm from "remark-gfm";
|
||||||
|
import { Icon } from "@iconify/react";
|
||||||
|
import { Badge, Button, Card, Typography } from "poyraz-ui/atoms";
|
||||||
|
import { Modal, ModalContent, ModalTitle, Sheet, SheetContent, SheetTitle } from "poyraz-ui/molecules";
|
||||||
|
import type { PodcastEpisode } from "@/data/content-types";
|
||||||
|
|
||||||
|
type ContentContentProps = {
|
||||||
|
yazilimEpisodes: PodcastEpisode[];
|
||||||
|
masaBasiEpisodes: PodcastEpisode[];
|
||||||
|
youtubeLinks: readonly string[];
|
||||||
|
pdfFiles: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
function PdfFirstPagePreview({ src, title }: { src: string; title: string }) {
|
||||||
|
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
||||||
|
const [failed, setFailed] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let cancelled = false;
|
||||||
|
let loadingTask: { promise: Promise<unknown>; destroy?: () => void } | null = null;
|
||||||
|
|
||||||
|
const render = async () => {
|
||||||
|
try {
|
||||||
|
const pdfjs = await import("pdfjs-dist");
|
||||||
|
const lib = pdfjs as unknown as {
|
||||||
|
version: string;
|
||||||
|
getDocument: (src: string) => { promise: Promise<unknown>; destroy?: () => void };
|
||||||
|
GlobalWorkerOptions: { workerSrc: string };
|
||||||
|
};
|
||||||
|
|
||||||
|
lib.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${lib.version}/build/pdf.worker.min.mjs`;
|
||||||
|
loadingTask = lib.getDocument(src);
|
||||||
|
|
||||||
|
const pdf = (await loadingTask.promise) as {
|
||||||
|
getPage: (page: number) => Promise<{
|
||||||
|
getViewport: (opts: { scale: number }) => { width: number; height: number };
|
||||||
|
render: (opts: {
|
||||||
|
canvasContext: CanvasRenderingContext2D;
|
||||||
|
viewport: { width: number; height: number };
|
||||||
|
}) => { promise: Promise<void> };
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const page = await pdf.getPage(1);
|
||||||
|
const viewport = page.getViewport({ scale: 1.2 });
|
||||||
|
const canvas = canvasRef.current;
|
||||||
|
if (!canvas || cancelled) return;
|
||||||
|
|
||||||
|
const context = canvas.getContext("2d");
|
||||||
|
if (!context) return;
|
||||||
|
|
||||||
|
const ratio = window.devicePixelRatio || 1;
|
||||||
|
canvas.width = Math.floor(viewport.width * ratio);
|
||||||
|
canvas.height = Math.floor(viewport.height * ratio);
|
||||||
|
canvas.style.width = `${viewport.width}px`;
|
||||||
|
canvas.style.height = `${viewport.height}px`;
|
||||||
|
|
||||||
|
context.setTransform(ratio, 0, 0, ratio, 0, 0);
|
||||||
|
await page.render({ canvasContext: context, viewport }).promise;
|
||||||
|
} catch {
|
||||||
|
if (!cancelled) {
|
||||||
|
setFailed(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void render();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
if (loadingTask?.destroy) {
|
||||||
|
loadingTask.destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [src]);
|
||||||
|
|
||||||
|
if (failed) {
|
||||||
|
return (
|
||||||
|
<div className="flex h-full w-full items-center justify-center bg-muted/20 p-2">
|
||||||
|
<Typography variant="small" className="text-muted-foreground">
|
||||||
|
Preview unavailable
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex h-full w-full items-center justify-center bg-white p-2">
|
||||||
|
<canvas ref={canvasRef} aria-label={title} className="h-auto max-h-full w-auto max-w-full" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getYoutubeEmbedUrl(link: string) {
|
||||||
|
try {
|
||||||
|
const url = new URL(link);
|
||||||
|
const videoId = url.searchParams.get("v");
|
||||||
|
return videoId ? `https://www.youtube.com/embed/${videoId}` : null;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function PodcastColumn({
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
episodes,
|
||||||
|
onOpenEpisode,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
subtitle: string;
|
||||||
|
episodes: PodcastEpisode[];
|
||||||
|
onOpenEpisode: (episode: PodcastEpisode) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Card className="rounded-sm border-border p-4">
|
||||||
|
<Typography variant="large" className="text-base">
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="small" className="mt-1 text-muted-foreground">
|
||||||
|
{subtitle}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<div className="mt-3 grid gap-2">
|
||||||
|
{episodes.slice(0, 3).map((episode) => (
|
||||||
|
<button
|
||||||
|
key={`${episode.podcast}-${episode.slug}`}
|
||||||
|
type="button"
|
||||||
|
onClick={() => onOpenEpisode(episode)}
|
||||||
|
className="cursor-pointer text-left"
|
||||||
|
>
|
||||||
|
<Card className="rounded-sm border-border p-3 transition-colors hover:border-zinc-700">
|
||||||
|
<Typography variant="small" className="font-semibold text-foreground">
|
||||||
|
{episode.title}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="small" className="mt-0.5 text-muted-foreground">
|
||||||
|
{episode.date}
|
||||||
|
</Typography>
|
||||||
|
</Card>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ContentContent({
|
||||||
|
yazilimEpisodes,
|
||||||
|
masaBasiEpisodes,
|
||||||
|
youtubeLinks,
|
||||||
|
pdfFiles,
|
||||||
|
}: ContentContentProps) {
|
||||||
|
const [selectedEpisode, setSelectedEpisode] = useState<PodcastEpisode | null>(null);
|
||||||
|
const [sheetOpen, setSheetOpen] = useState(false);
|
||||||
|
const [pdfModalOpen, setPdfModalOpen] = useState(false);
|
||||||
|
const [activePdfIndex, setActivePdfIndex] = useState(0);
|
||||||
|
|
||||||
|
const activePdf = pdfFiles[activePdfIndex] ?? null;
|
||||||
|
const canGoPrev = activePdfIndex > 0;
|
||||||
|
const canGoNext = activePdfIndex < pdfFiles.length - 1;
|
||||||
|
|
||||||
|
const embeddedVideos = useMemo(
|
||||||
|
() =>
|
||||||
|
youtubeLinks
|
||||||
|
.map((link) => ({ link, embedUrl: getYoutubeEmbedUrl(link) }))
|
||||||
|
.slice(0, 3),
|
||||||
|
[youtubeLinks],
|
||||||
|
);
|
||||||
|
|
||||||
|
const openEpisode = (episode: PodcastEpisode) => {
|
||||||
|
setSelectedEpisode(episode);
|
||||||
|
setSheetOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openPdfModal = (index: number) => {
|
||||||
|
setActivePdfIndex(index);
|
||||||
|
setPdfModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="flex h-full flex-col gap-3 overflow-y-auto">
|
||||||
|
<section className="grid gap-3 md:grid-cols-2">
|
||||||
|
<PodcastColumn
|
||||||
|
title="Poyraz ile Yazilim"
|
||||||
|
subtitle="Regular schedule, every Sunday."
|
||||||
|
episodes={yazilimEpisodes}
|
||||||
|
onOpenEpisode={openEpisode}
|
||||||
|
/>
|
||||||
|
<PodcastColumn
|
||||||
|
title="Poyraz ile Masa Basi"
|
||||||
|
subtitle="Irregular schedule, guest-focused."
|
||||||
|
episodes={masaBasiEpisodes}
|
||||||
|
onOpenEpisode={openEpisode}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="space-y-2">
|
||||||
|
<Typography variant="large" className="text-base">
|
||||||
|
Latest YouTube Videos
|
||||||
|
</Typography>
|
||||||
|
<div className="grid gap-2 md:grid-cols-3">
|
||||||
|
{embeddedVideos.map((item) => (
|
||||||
|
<Card key={item.link} className="overflow-hidden rounded-sm border-border p-0">
|
||||||
|
{item.embedUrl ? (
|
||||||
|
<div className="aspect-video w-full">
|
||||||
|
<iframe
|
||||||
|
src={item.embedUrl}
|
||||||
|
title="YouTube video player"
|
||||||
|
className="h-full w-full"
|
||||||
|
loading="lazy"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||||
|
referrerPolicy="strict-origin-when-cross-origin"
|
||||||
|
allowFullScreen
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="p-3">
|
||||||
|
<Typography variant="small" className="text-muted-foreground">
|
||||||
|
Invalid video link.
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="space-y-2">
|
||||||
|
<Typography variant="large" className="text-base">
|
||||||
|
LinkedIn PDF Notes
|
||||||
|
</Typography>
|
||||||
|
<div className="grid gap-2 grid-cols-2 md:grid-cols-3">
|
||||||
|
{pdfFiles.map((pdf, index) => (
|
||||||
|
<button
|
||||||
|
key={pdf}
|
||||||
|
type="button"
|
||||||
|
onClick={() => openPdfModal(index)}
|
||||||
|
className="cursor-pointer text-left"
|
||||||
|
>
|
||||||
|
<Card className="overflow-hidden rounded-sm border-border p-0 transition-colors hover:border-zinc-700">
|
||||||
|
<div className="aspect-square w-full">
|
||||||
|
<PdfFirstPagePreview src={`/pdf/${pdf}`} title={`${pdf} preview`} />
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
|
||||||
|
<SheetContent side="right" className="w-full max-w-xl p-0">
|
||||||
|
<div className="border-b border-border px-4 py-3">
|
||||||
|
<SheetTitle>{selectedEpisode?.title ?? "Episode"}</SheetTitle>
|
||||||
|
{selectedEpisode ? (
|
||||||
|
<Typography variant="small" className="mt-1 text-muted-foreground">
|
||||||
|
{selectedEpisode.date}
|
||||||
|
</Typography>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex max-h-[calc(100dvh-64px)] flex-col gap-3 overflow-y-auto p-4">
|
||||||
|
{selectedEpisode ? (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Badge className="rounded-sm">{selectedEpisode.podcast}</Badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Link
|
||||||
|
href={selectedEpisode.youtubeUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="inline-flex items-center gap-1.5 rounded-sm border border-border px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:text-foreground"
|
||||||
|
>
|
||||||
|
<Icon icon="mdi:youtube" width={16} height={16} className="text-red-600" />
|
||||||
|
YouTube
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href={selectedEpisode.spotifyUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="inline-flex items-center gap-1.5 rounded-sm border border-border px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:text-foreground"
|
||||||
|
>
|
||||||
|
<Icon icon="mdi:spotify" width={16} height={16} className="text-green-600" />
|
||||||
|
Spotify
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Card className="rounded-sm border-border p-3">
|
||||||
|
<ReactMarkdown
|
||||||
|
remarkPlugins={[remarkGfm]}
|
||||||
|
components={{
|
||||||
|
h2: ({ children }) => (
|
||||||
|
<Typography variant="large" className="mt-3 text-foreground first:mt-0">
|
||||||
|
{children}
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
p: ({ children }) => (
|
||||||
|
<Typography variant="small" className="mt-1 text-muted-foreground first:mt-0">
|
||||||
|
{children}
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
li: ({ children }) => (
|
||||||
|
<li className="ml-5 list-disc text-sm text-muted-foreground">{children}</li>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{selectedEpisode.markdown}
|
||||||
|
</ReactMarkdown>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
|
||||||
|
<Modal open={pdfModalOpen} onOpenChange={setPdfModalOpen}>
|
||||||
|
<ModalContent size="xl" className="rounded-sm p-4">
|
||||||
|
<ModalTitle>{activePdf ? activePdf.replace(/\.pdf$/i, "") : "PDF Note"}</ModalTitle>
|
||||||
|
|
||||||
|
<div className="mt-3 flex flex-wrap items-center justify-between gap-2">
|
||||||
|
<Typography variant="small" className="text-muted-foreground">
|
||||||
|
{pdfFiles.length === 0 ? "0 / 0" : `${activePdfIndex + 1} / ${pdfFiles.length}`}
|
||||||
|
</Typography>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
className="rounded-sm"
|
||||||
|
disabled={!canGoPrev}
|
||||||
|
onClick={() => setActivePdfIndex((prev) => Math.max(0, prev - 1))}
|
||||||
|
>
|
||||||
|
Prev
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
className="rounded-sm"
|
||||||
|
disabled={!canGoNext}
|
||||||
|
onClick={() => setActivePdfIndex((prev) => Math.min(pdfFiles.length - 1, prev + 1))}
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{activePdf ? (
|
||||||
|
<div className="mt-3 h-[70dvh] overflow-hidden rounded-sm border border-border">
|
||||||
|
<iframe
|
||||||
|
src={`/pdf/${activePdf}`}
|
||||||
|
title={activePdf}
|
||||||
|
className="h-full w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Card className="mt-3 rounded-sm border-border p-3">
|
||||||
|
<Typography variant="small" className="text-muted-foreground">
|
||||||
|
No PDF found in /public/pdf.
|
||||||
|
</Typography>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "Freelance Client Stories"
|
||||||
|
date: "2026-01-30"
|
||||||
|
youtubeUrl: "https://www.youtube.com/watch?v=XWUeVzf0t6Y&t=2s"
|
||||||
|
spotifyUrl: "https://open.spotify.com/show/placeholder-masabasi"
|
||||||
|
podcast: "masa-basi"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Episode Notes
|
||||||
|
|
||||||
|
Real stories from client communication, scope alignment, and delivery expectations.
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
- Proposal templates
|
||||||
|
- Client handoff checklist
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "Productivity Without Burnout"
|
||||||
|
date: "2026-02-20"
|
||||||
|
youtubeUrl: "https://www.youtube.com/watch?v=H8sP8HejI7A"
|
||||||
|
spotifyUrl: "https://open.spotify.com/show/placeholder-masabasi"
|
||||||
|
podcast: "masa-basi"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Episode Notes
|
||||||
|
|
||||||
|
An informal talk on balancing shipping speed with sustainable routines.
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
- Weekly planning template
|
||||||
|
- Timeboxing references
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "Conversations with Builders"
|
||||||
|
date: "2026-03-07"
|
||||||
|
youtubeUrl: "https://www.youtube.com/watch?v=9JEOGCX5aSQ&t=22s"
|
||||||
|
spotifyUrl: "https://open.spotify.com/show/placeholder-masabasi"
|
||||||
|
podcast: "masa-basi"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Episode Notes
|
||||||
|
|
||||||
|
Guest conversation about discipline, career direction, and making room for deep work.
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
- Guest reading list
|
||||||
|
- Workflow snapshots
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "Stable Frontend Systems"
|
||||||
|
date: "2026-02-23"
|
||||||
|
youtubeUrl: "https://www.youtube.com/watch?v=XWUeVzf0t6Y&t=2s"
|
||||||
|
spotifyUrl: "https://open.spotify.com/show/placeholder-yazilim"
|
||||||
|
podcast: "yazilim"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Episode Notes
|
||||||
|
|
||||||
|
This one is about component contracts, UI consistency, and reducing regressions in fast-moving projects.
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
- Design token architecture references
|
||||||
|
- Next.js App Router docs
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "Writing Cleaner Service Layers"
|
||||||
|
date: "2026-03-02"
|
||||||
|
youtubeUrl: "https://www.youtube.com/watch?v=H8sP8HejI7A"
|
||||||
|
spotifyUrl: "https://open.spotify.com/show/placeholder-yazilim"
|
||||||
|
podcast: "yazilim"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Episode Notes
|
||||||
|
|
||||||
|
We discuss service-layer boundaries, validation ownership, and error mapping strategy.
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
- Practical clean architecture examples
|
||||||
|
- Team code review checklist
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: "Foundations Over Tools"
|
||||||
|
date: "2026-03-09"
|
||||||
|
youtubeUrl: "https://www.youtube.com/watch?v=9JEOGCX5aSQ&t=22s"
|
||||||
|
spotifyUrl: "https://open.spotify.com/show/placeholder-yazilim"
|
||||||
|
podcast: "yazilim"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Episode Notes
|
||||||
|
|
||||||
|
This episode focuses on software fundamentals and why architecture basics matter more than tool hype.
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
- Domain modeling notes
|
||||||
|
- Node.js internals docs
|
||||||
|
- System design interview references
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export type PodcastKind = "yazilim" | "masa-basi";
|
||||||
|
|
||||||
|
export type PodcastEpisode = {
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
youtubeUrl: string;
|
||||||
|
spotifyUrl: string;
|
||||||
|
podcast: PodcastKind;
|
||||||
|
markdown: string;
|
||||||
|
};
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { readdir, readFile } from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
import matter from "gray-matter";
|
||||||
|
import type { PodcastEpisode, PodcastKind } from "@/data/content-types";
|
||||||
|
|
||||||
|
type EpisodeFrontmatter = {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
youtubeUrl: string;
|
||||||
|
spotifyUrl: string;
|
||||||
|
podcast: PodcastKind;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PODCAST_DIR = path.join(process.cwd(), "content", "podcasts");
|
||||||
|
const PDF_DIR = path.join(process.cwd(), "public", "pdf");
|
||||||
|
|
||||||
|
function sortEpisodesByDateDesc(episodes: PodcastEpisode[]) {
|
||||||
|
return [...episodes].sort((a, b) => {
|
||||||
|
const aTime = Number(new Date(a.date));
|
||||||
|
const bTime = Number(new Date(b.date));
|
||||||
|
|
||||||
|
if (!Number.isNaN(aTime) && !Number.isNaN(bTime)) {
|
||||||
|
return bTime - aTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.title.localeCompare(b.title);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readPodcastEpisodes(kind: PodcastKind): Promise<PodcastEpisode[]> {
|
||||||
|
const folder = path.join(PODCAST_DIR, kind);
|
||||||
|
const files = await readdir(folder);
|
||||||
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
||||||
|
|
||||||
|
const episodes = await Promise.all(
|
||||||
|
mdFiles.map(async (file) => {
|
||||||
|
const fullPath = path.join(folder, file);
|
||||||
|
const raw = await readFile(fullPath, "utf8");
|
||||||
|
const parsed = matter(raw);
|
||||||
|
const data = parsed.data as Partial<EpisodeFrontmatter>;
|
||||||
|
|
||||||
|
return {
|
||||||
|
slug: file.replace(/\.md$/, ""),
|
||||||
|
title: data.title ?? "Untitled Episode",
|
||||||
|
date: data.date ?? "1970-01-01",
|
||||||
|
youtubeUrl: data.youtubeUrl ?? "",
|
||||||
|
spotifyUrl: data.spotifyUrl ?? "",
|
||||||
|
podcast: data.podcast ?? kind,
|
||||||
|
markdown: parsed.content.trim(),
|
||||||
|
} satisfies PodcastEpisode;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return sortEpisodesByDateDesc(episodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getPodcastCollections() {
|
||||||
|
const [yazilim, masaBasi] = await Promise.all([
|
||||||
|
readPodcastEpisodes("yazilim"),
|
||||||
|
readPodcastEpisodes("masa-basi"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
yazilim,
|
||||||
|
masaBasi,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getPdfNotes() {
|
||||||
|
const files = await readdir(PDF_DIR);
|
||||||
|
const pdfFiles = files.filter((file) => file.toLowerCase().endsWith(".pdf"));
|
||||||
|
return pdfFiles.sort((a, b) => a.localeCompare(b));
|
||||||
|
}
|
||||||
@@ -10,8 +10,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iconify/react": "^6.0.2",
|
"@iconify/react": "^6.0.2",
|
||||||
|
"gray-matter": "^4.0.3",
|
||||||
"mermaid": "^11.13.0",
|
"mermaid": "^11.13.0",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
|
"pdfjs-dist": "^5.5.207",
|
||||||
"poyraz-ui": "^2.0.1",
|
"poyraz-ui": "^2.0.1",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
"react-dom": "19.2.3",
|
"react-dom": "19.2.3",
|
||||||
|
|||||||
Generated
+213
@@ -11,12 +11,18 @@ importers:
|
|||||||
'@iconify/react':
|
'@iconify/react':
|
||||||
specifier: ^6.0.2
|
specifier: ^6.0.2
|
||||||
version: 6.0.2(react@19.2.3)
|
version: 6.0.2(react@19.2.3)
|
||||||
|
gray-matter:
|
||||||
|
specifier: ^4.0.3
|
||||||
|
version: 4.0.3
|
||||||
mermaid:
|
mermaid:
|
||||||
specifier: ^11.13.0
|
specifier: ^11.13.0
|
||||||
version: 11.13.0
|
version: 11.13.0
|
||||||
next:
|
next:
|
||||||
specifier: 16.1.6
|
specifier: 16.1.6
|
||||||
version: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
version: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
pdfjs-dist:
|
||||||
|
specifier: ^5.5.207
|
||||||
|
version: 5.5.207
|
||||||
poyraz-ui:
|
poyraz-ui:
|
||||||
specifier: ^2.0.1
|
specifier: ^2.0.1
|
||||||
version: 2.0.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react-hook-form@7.71.2(react@19.2.3))(react@19.2.3)(tailwindcss@4.2.1)(zod@4.3.6)
|
version: 2.0.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react-hook-form@7.71.2(react@19.2.3))(react@19.2.3)(tailwindcss@4.2.1)(zod@4.3.6)
|
||||||
@@ -407,6 +413,76 @@ packages:
|
|||||||
'@mermaid-js/parser@1.0.1':
|
'@mermaid-js/parser@1.0.1':
|
||||||
resolution: {integrity: sha512-opmV19kN1JsK0T6HhhokHpcVkqKpF+x2pPDKKM2ThHtZAB5F4PROopk0amuVYK5qMrIA4erzpNm8gmPNJgMDxQ==}
|
resolution: {integrity: sha512-opmV19kN1JsK0T6HhhokHpcVkqKpF+x2pPDKKM2ThHtZAB5F4PROopk0amuVYK5qMrIA4erzpNm8gmPNJgMDxQ==}
|
||||||
|
|
||||||
|
'@napi-rs/canvas-android-arm64@0.1.96':
|
||||||
|
resolution: {integrity: sha512-ew1sPrN3dGdZ3L4FoohPfnjq0f9/Jk7o+wP7HkQZokcXgIUD6FIyICEWGhMYzv53j63wUcPvZeAwgewX58/egg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-darwin-arm64@0.1.96':
|
||||||
|
resolution: {integrity: sha512-Q/wOXZ5PzTqpdmA5eUOcegCf4Go/zz3aZ5DlzSeDpOjFmfwMKh8EzLAoweQ+mJVagcHQyzoJhaTEnrO68TNyNg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-darwin-x64@0.1.96':
|
||||||
|
resolution: {integrity: sha512-UrXiQz28tQEvGM1qvyptewOAfmUrrd5+wvi6Rzjj2VprZI8iZ2KIvBD2lTTG1bVF95AbeDeG7PJA0D9sLKaOFA==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.96':
|
||||||
|
resolution: {integrity: sha512-I90ODxweD8aEP6XKU/NU+biso95MwCtQ2F46dUvhec1HesFi0tq/tAJkYic/1aBSiO/1kGKmSeD1B0duOHhEHQ==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-arm64-gnu@0.1.96':
|
||||||
|
resolution: {integrity: sha512-Dx/0+RFV++w3PcRy+4xNXkghhXjA5d0Mw1bs95emn5Llinp1vihMaA6WJt3oYv2LAHc36+gnrhIBsPhUyI2SGw==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-arm64-musl@0.1.96':
|
||||||
|
resolution: {integrity: sha512-UvOi7fii3IE2KDfEfhh8m+LpzSRvhGK7o1eho99M2M0HTik11k3GX+2qgVx9EtujN3/bhFFS1kSO3+vPMaJ0Mg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-riscv64-gnu@0.1.96':
|
||||||
|
resolution: {integrity: sha512-MBSukhGCQ5nRtf9NbFYWOU080yqkZU1PbuH4o1ROvB4CbPl12fchDR35tU83Wz8gWIM9JTn99lBn9DenPIv7Ig==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [riscv64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-x64-gnu@0.1.96':
|
||||||
|
resolution: {integrity: sha512-I/ccu2SstyKiV3HIeVzyBIWfrJo8cN7+MSQZPnabewWV6hfJ2nY7Df2WqOHmobBRUw84uGR6zfQHsUEio/m5Vg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-x64-musl@0.1.96':
|
||||||
|
resolution: {integrity: sha512-H3uov7qnTl73GDT4h52lAqpJPsl1tIUyNPWJyhQ6gHakohNqqRq3uf80+NEpzcytKGEOENP1wX3yGwZxhjiWEQ==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-win32-arm64-msvc@0.1.96':
|
||||||
|
resolution: {integrity: sha512-ATp6Y+djOjYtkfV/VRH7CZ8I1MEtkUQBmKUbuWw5zWEHHqfL0cEcInE4Cxgx7zkNAhEdBbnH8HMVrqNp+/gwxA==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@napi-rs/canvas-win32-x64-msvc@0.1.96':
|
||||||
|
resolution: {integrity: sha512-UYGdTltVd+Z8mcIuoqGmAXXUvwH5CLf2M6mIB5B0/JmX5J041jETjqtSYl7gN+aj3k1by/SG6sS0hAwCqyK7zw==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@napi-rs/canvas@0.1.96':
|
||||||
|
resolution: {integrity: sha512-6NNmNxvoJKeucVjxaaRUt3La2i5jShgiAbaY3G/72s1Vp3U06XPrAIxkAjBxpDcamEn/t+WJ4OOlGmvILo4/Ew==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
|
||||||
'@napi-rs/wasm-runtime@0.2.12':
|
'@napi-rs/wasm-runtime@0.2.12':
|
||||||
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
|
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
|
||||||
|
|
||||||
@@ -1436,6 +1512,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
argparse@1.0.10:
|
||||||
|
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
|
||||||
|
|
||||||
argparse@2.0.1:
|
argparse@2.0.1:
|
||||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||||
|
|
||||||
@@ -2017,6 +2096,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
|
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
|
esprima@4.0.1:
|
||||||
|
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
esquery@1.7.0:
|
esquery@1.7.0:
|
||||||
resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
|
resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
|
||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
@@ -2036,6 +2120,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
extend-shallow@2.0.1:
|
||||||
|
resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
extend@3.0.2:
|
extend@3.0.2:
|
||||||
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
|
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
|
||||||
|
|
||||||
@@ -2158,6 +2246,10 @@ packages:
|
|||||||
graceful-fs@4.2.11:
|
graceful-fs@4.2.11:
|
||||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||||
|
|
||||||
|
gray-matter@4.0.3:
|
||||||
|
resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
|
||||||
|
engines: {node: '>=6.0'}
|
||||||
|
|
||||||
hachure-fill@0.5.2:
|
hachure-fill@0.5.2:
|
||||||
resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==}
|
resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==}
|
||||||
|
|
||||||
@@ -2293,6 +2385,10 @@ packages:
|
|||||||
is-decimal@2.0.1:
|
is-decimal@2.0.1:
|
||||||
resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
|
resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
|
||||||
|
|
||||||
|
is-extendable@0.1.1:
|
||||||
|
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
is-extglob@2.1.1:
|
is-extglob@2.1.1:
|
||||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -2385,6 +2481,10 @@ packages:
|
|||||||
js-tokens@4.0.0:
|
js-tokens@4.0.0:
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||||
|
|
||||||
|
js-yaml@3.14.2:
|
||||||
|
resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
js-yaml@4.1.1:
|
js-yaml@4.1.1:
|
||||||
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
|
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -2426,6 +2526,10 @@ packages:
|
|||||||
khroma@2.1.0:
|
khroma@2.1.0:
|
||||||
resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==}
|
resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==}
|
||||||
|
|
||||||
|
kind-of@6.0.3:
|
||||||
|
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
langium@4.2.1:
|
langium@4.2.1:
|
||||||
resolution: {integrity: sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==}
|
resolution: {integrity: sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==}
|
||||||
engines: {node: '>=20.10.0', npm: '>=10.2.3'}
|
engines: {node: '>=20.10.0', npm: '>=10.2.3'}
|
||||||
@@ -2754,6 +2858,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==}
|
resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
node-readable-to-web-readable-stream@0.4.2:
|
||||||
|
resolution: {integrity: sha512-/cMZNI34v//jUTrI+UIo4ieHAB5EZRY/+7OmXZgBxaWBMcW2tGdceIw06RFxWxrKZ5Jp3sI2i5TsRo+CBhtVLQ==}
|
||||||
|
|
||||||
node-releases@2.0.36:
|
node-releases@2.0.36:
|
||||||
resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==}
|
resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==}
|
||||||
|
|
||||||
@@ -2832,6 +2939,10 @@ packages:
|
|||||||
pathe@2.0.3:
|
pathe@2.0.3:
|
||||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||||
|
|
||||||
|
pdfjs-dist@5.5.207:
|
||||||
|
resolution: {integrity: sha512-WMqqw06w1vUt9ZfT0gOFhMf3wHsWhaCrxGrckGs5Cci6ybDW87IvPaOd2pnBwT6BJuP/CzXDZxjFgmSULLdsdw==}
|
||||||
|
engines: {node: '>=20.19.0 || >=22.13.0 || >=24'}
|
||||||
|
|
||||||
picocolors@1.1.1:
|
picocolors@1.1.1:
|
||||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||||
|
|
||||||
@@ -3040,6 +3151,10 @@ packages:
|
|||||||
scheduler@0.27.0:
|
scheduler@0.27.0:
|
||||||
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
||||||
|
|
||||||
|
section-matter@1.0.0:
|
||||||
|
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
semver@6.3.1:
|
semver@6.3.1:
|
||||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -3102,6 +3217,9 @@ packages:
|
|||||||
space-separated-tokens@2.0.2:
|
space-separated-tokens@2.0.2:
|
||||||
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
|
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
|
||||||
|
|
||||||
|
sprintf-js@1.0.3:
|
||||||
|
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||||
|
|
||||||
stable-hash@0.0.5:
|
stable-hash@0.0.5:
|
||||||
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
|
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
|
||||||
|
|
||||||
@@ -3135,6 +3253,10 @@ packages:
|
|||||||
stringify-entities@4.0.4:
|
stringify-entities@4.0.4:
|
||||||
resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
|
resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
|
||||||
|
|
||||||
|
strip-bom-string@1.0.0:
|
||||||
|
resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
strip-bom@3.0.0:
|
strip-bom@3.0.0:
|
||||||
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
|
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -3747,6 +3869,54 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
langium: 4.2.1
|
langium: 4.2.1
|
||||||
|
|
||||||
|
'@napi-rs/canvas-android-arm64@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-darwin-arm64@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-darwin-x64@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-arm64-gnu@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-arm64-musl@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-riscv64-gnu@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-x64-gnu@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-linux-x64-musl@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-win32-arm64-msvc@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas-win32-x64-msvc@0.1.96':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@napi-rs/canvas@0.1.96':
|
||||||
|
optionalDependencies:
|
||||||
|
'@napi-rs/canvas-android-arm64': 0.1.96
|
||||||
|
'@napi-rs/canvas-darwin-arm64': 0.1.96
|
||||||
|
'@napi-rs/canvas-darwin-x64': 0.1.96
|
||||||
|
'@napi-rs/canvas-linux-arm-gnueabihf': 0.1.96
|
||||||
|
'@napi-rs/canvas-linux-arm64-gnu': 0.1.96
|
||||||
|
'@napi-rs/canvas-linux-arm64-musl': 0.1.96
|
||||||
|
'@napi-rs/canvas-linux-riscv64-gnu': 0.1.96
|
||||||
|
'@napi-rs/canvas-linux-x64-gnu': 0.1.96
|
||||||
|
'@napi-rs/canvas-linux-x64-musl': 0.1.96
|
||||||
|
'@napi-rs/canvas-win32-arm64-msvc': 0.1.96
|
||||||
|
'@napi-rs/canvas-win32-x64-msvc': 0.1.96
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@napi-rs/wasm-runtime@0.2.12':
|
'@napi-rs/wasm-runtime@0.2.12':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@emnapi/core': 1.8.1
|
'@emnapi/core': 1.8.1
|
||||||
@@ -4773,6 +4943,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
color-convert: 2.0.1
|
color-convert: 2.0.1
|
||||||
|
|
||||||
|
argparse@1.0.10:
|
||||||
|
dependencies:
|
||||||
|
sprintf-js: 1.0.3
|
||||||
|
|
||||||
argparse@2.0.1: {}
|
argparse@2.0.1: {}
|
||||||
|
|
||||||
aria-hidden@1.2.6:
|
aria-hidden@1.2.6:
|
||||||
@@ -5550,6 +5724,8 @@ snapshots:
|
|||||||
acorn-jsx: 5.3.2(acorn@8.16.0)
|
acorn-jsx: 5.3.2(acorn@8.16.0)
|
||||||
eslint-visitor-keys: 4.2.1
|
eslint-visitor-keys: 4.2.1
|
||||||
|
|
||||||
|
esprima@4.0.1: {}
|
||||||
|
|
||||||
esquery@1.7.0:
|
esquery@1.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
estraverse: 5.3.0
|
estraverse: 5.3.0
|
||||||
@@ -5564,6 +5740,10 @@ snapshots:
|
|||||||
|
|
||||||
esutils@2.0.3: {}
|
esutils@2.0.3: {}
|
||||||
|
|
||||||
|
extend-shallow@2.0.1:
|
||||||
|
dependencies:
|
||||||
|
is-extendable: 0.1.1
|
||||||
|
|
||||||
extend@3.0.2: {}
|
extend@3.0.2: {}
|
||||||
|
|
||||||
fast-deep-equal@3.1.3: {}
|
fast-deep-equal@3.1.3: {}
|
||||||
@@ -5686,6 +5866,13 @@ snapshots:
|
|||||||
|
|
||||||
graceful-fs@4.2.11: {}
|
graceful-fs@4.2.11: {}
|
||||||
|
|
||||||
|
gray-matter@4.0.3:
|
||||||
|
dependencies:
|
||||||
|
js-yaml: 3.14.2
|
||||||
|
kind-of: 6.0.3
|
||||||
|
section-matter: 1.0.0
|
||||||
|
strip-bom-string: 1.0.0
|
||||||
|
|
||||||
hachure-fill@0.5.2: {}
|
hachure-fill@0.5.2: {}
|
||||||
|
|
||||||
has-bigints@1.1.0: {}
|
has-bigints@1.1.0: {}
|
||||||
@@ -5838,6 +6025,8 @@ snapshots:
|
|||||||
|
|
||||||
is-decimal@2.0.1: {}
|
is-decimal@2.0.1: {}
|
||||||
|
|
||||||
|
is-extendable@0.1.1: {}
|
||||||
|
|
||||||
is-extglob@2.1.1: {}
|
is-extglob@2.1.1: {}
|
||||||
|
|
||||||
is-finalizationregistry@1.1.1:
|
is-finalizationregistry@1.1.1:
|
||||||
@@ -5927,6 +6116,11 @@ snapshots:
|
|||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
|
|
||||||
|
js-yaml@3.14.2:
|
||||||
|
dependencies:
|
||||||
|
argparse: 1.0.10
|
||||||
|
esprima: 4.0.1
|
||||||
|
|
||||||
js-yaml@4.1.1:
|
js-yaml@4.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
argparse: 2.0.1
|
argparse: 2.0.1
|
||||||
@@ -5962,6 +6156,8 @@ snapshots:
|
|||||||
|
|
||||||
khroma@2.1.0: {}
|
khroma@2.1.0: {}
|
||||||
|
|
||||||
|
kind-of@6.0.3: {}
|
||||||
|
|
||||||
langium@4.2.1:
|
langium@4.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
chevrotain: 11.1.2
|
chevrotain: 11.1.2
|
||||||
@@ -6502,6 +6698,9 @@ snapshots:
|
|||||||
object.entries: 1.1.9
|
object.entries: 1.1.9
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
|
|
||||||
|
node-readable-to-web-readable-stream@0.4.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
node-releases@2.0.36: {}
|
node-releases@2.0.36: {}
|
||||||
|
|
||||||
object-assign@4.1.1: {}
|
object-assign@4.1.1: {}
|
||||||
@@ -6595,6 +6794,11 @@ snapshots:
|
|||||||
|
|
||||||
pathe@2.0.3: {}
|
pathe@2.0.3: {}
|
||||||
|
|
||||||
|
pdfjs-dist@5.5.207:
|
||||||
|
optionalDependencies:
|
||||||
|
'@napi-rs/canvas': 0.1.96
|
||||||
|
node-readable-to-web-readable-stream: 0.4.2
|
||||||
|
|
||||||
picocolors@1.1.1: {}
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
picomatch@2.3.1: {}
|
picomatch@2.3.1: {}
|
||||||
@@ -6867,6 +7071,11 @@ snapshots:
|
|||||||
|
|
||||||
scheduler@0.27.0: {}
|
scheduler@0.27.0: {}
|
||||||
|
|
||||||
|
section-matter@1.0.0:
|
||||||
|
dependencies:
|
||||||
|
extend-shallow: 2.0.1
|
||||||
|
kind-of: 6.0.3
|
||||||
|
|
||||||
semver@6.3.1: {}
|
semver@6.3.1: {}
|
||||||
|
|
||||||
semver@7.7.4: {}
|
semver@7.7.4: {}
|
||||||
@@ -6968,6 +7177,8 @@ snapshots:
|
|||||||
|
|
||||||
space-separated-tokens@2.0.2: {}
|
space-separated-tokens@2.0.2: {}
|
||||||
|
|
||||||
|
sprintf-js@1.0.3: {}
|
||||||
|
|
||||||
stable-hash@0.0.5: {}
|
stable-hash@0.0.5: {}
|
||||||
|
|
||||||
stop-iteration-iterator@1.1.0:
|
stop-iteration-iterator@1.1.0:
|
||||||
@@ -7030,6 +7241,8 @@ snapshots:
|
|||||||
character-entities-html4: 2.1.0
|
character-entities-html4: 2.1.0
|
||||||
character-entities-legacy: 3.0.0
|
character-entities-legacy: 3.0.0
|
||||||
|
|
||||||
|
strip-bom-string@1.0.0: {}
|
||||||
|
|
||||||
strip-bom@3.0.0: {}
|
strip-bom@3.0.0: {}
|
||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
strip-json-comments@3.1.1: {}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user