feat(content): organize platform media sections
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { ContentContent } from "@/components/content-content";
|
||||
import { YOUTUBE_VIDEO_LINKS } from "@/data/youtube-videos";
|
||||
import { X_JAVASCRIPT_ANATOMY_VIDEOS } from "@/data/x-videos";
|
||||
import { getPdfNotes } from "@/lib/content-page";
|
||||
|
||||
export default async function ContentPage() {
|
||||
@@ -9,6 +10,7 @@ export default async function ContentPage() {
|
||||
<ContentContent
|
||||
youtubeLinks={YOUTUBE_VIDEO_LINKS}
|
||||
pdfFiles={pdfFiles}
|
||||
xVideos={X_JAVASCRIPT_ANATOMY_VIDEOS}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
+133
-137
@@ -1,107 +1,72 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { Icon } from "@iconify/react";
|
||||
import { Button, ButtonIcon, ButtonLabel, Card, Typography } from "poyraz-ui/atoms";
|
||||
import { Modal, ModalContent, ModalTitle } from "poyraz-ui/molecules";
|
||||
import { YoutubeLiteEmbed } from "@/components/youtube-lite-embed";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { YoutubeLiteEmbed } from "@/components/youtube-lite-embed";
|
||||
import type { XVideo } from "@/data/x-videos";
|
||||
import { X_JAVASCRIPT_ANATOMY_URL } from "@/data/x-videos";
|
||||
import type { PdfNote } from "@/lib/content-page";
|
||||
|
||||
type ContentContentProps = {
|
||||
youtubeLinks: readonly string[];
|
||||
pdfFiles: string[];
|
||||
pdfFiles: PdfNote[];
|
||||
xVideos: readonly XVideo[];
|
||||
};
|
||||
|
||||
function PdfFirstPagePreview({ src, title }: { src: string; title: string }) {
|
||||
const t = useTranslations("Content");
|
||||
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 };
|
||||
type SectionHeadingProps = {
|
||||
title: string;
|
||||
titlePrefix?: string;
|
||||
titleIcon: string;
|
||||
titleIconClassName?: string;
|
||||
href: string;
|
||||
label: string;
|
||||
handle: string;
|
||||
icon: 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 });
|
||||
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 = "100%";
|
||||
canvas.style.height = "auto";
|
||||
|
||||
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) {
|
||||
function SectionHeading({
|
||||
title,
|
||||
titlePrefix,
|
||||
titleIcon,
|
||||
titleIconClassName,
|
||||
href,
|
||||
label,
|
||||
handle,
|
||||
icon,
|
||||
}: SectionHeadingProps) {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center bg-muted/20 p-2">
|
||||
<Typography variant="small" className="text-muted-foreground">
|
||||
{t("pdfPreviewError")}
|
||||
</Typography>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full bg-white p-2">
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
aria-label={title}
|
||||
className="block h-auto w-full"
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<Typography
|
||||
variant="large"
|
||||
className="inline-flex items-center gap-1.5 text-base"
|
||||
>
|
||||
{titlePrefix ? <span>{titlePrefix}</span> : null}
|
||||
<Icon
|
||||
icon={titleIcon}
|
||||
width={18}
|
||||
height={18}
|
||||
aria-hidden="true"
|
||||
className={titleIconClassName}
|
||||
/>
|
||||
<span>{title}</span>
|
||||
</Typography>
|
||||
<Button asChild variant="outline" effect="swap" size="xs" radius="sm">
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={label}
|
||||
>
|
||||
<ButtonIcon>
|
||||
<Icon icon={icon} width={15} height={15} />
|
||||
</ButtonIcon>
|
||||
<ButtonLabel>{handle}</ButtonLabel>
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -109,6 +74,7 @@ function PdfFirstPagePreview({ src, title }: { src: string; title: string }) {
|
||||
export function ContentContent({
|
||||
youtubeLinks,
|
||||
pdfFiles,
|
||||
xVideos,
|
||||
}: ContentContentProps) {
|
||||
const t = useTranslations("Content");
|
||||
const [pdfModalOpen, setPdfModalOpen] = useState(false);
|
||||
@@ -117,7 +83,6 @@ export function ContentContent({
|
||||
const activePdf = pdfFiles[activePdfIndex] ?? null;
|
||||
const canGoPrev = activePdfIndex > 0;
|
||||
const canGoNext = activePdfIndex < pdfFiles.length - 1;
|
||||
|
||||
const embeddedVideos = useMemo(
|
||||
() => youtubeLinks.slice(0, 3),
|
||||
[youtubeLinks],
|
||||
@@ -129,25 +94,19 @@ export function ContentContent({
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="flex h-full flex-col gap-3 overflow-y-auto">
|
||||
<section className="space-y-2">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<Typography variant="large" className="text-base">
|
||||
{t("youtubeTitle")}
|
||||
</Typography>
|
||||
<Button asChild variant="outline" effect="swap" size="xs" radius="sm">
|
||||
<a
|
||||
<section className="flex h-full flex-col gap-4 overflow-y-auto">
|
||||
<section className="space-y-2" aria-labelledby="youtube-section-title">
|
||||
<div id="youtube-section-title">
|
||||
<SectionHeading
|
||||
title={t("youtubeTitle")}
|
||||
titlePrefix={t("youtubeTitlePrefix")}
|
||||
titleIcon="mdi:youtube"
|
||||
titleIconClassName="text-red-600"
|
||||
href="https://youtube.com/@poyrazavsever"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={t("youtubeChannel")}
|
||||
>
|
||||
<ButtonIcon>
|
||||
<Icon icon="mdi:youtube" width={15} height={15} />
|
||||
</ButtonIcon>
|
||||
<ButtonLabel>@poyrazavsever</ButtonLabel>
|
||||
</a>
|
||||
</Button>
|
||||
label={t("youtubeChannel")}
|
||||
handle="@poyrazavsever"
|
||||
icon="mdi:youtube"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2 md:grid-cols-3">
|
||||
{embeddedVideos.map((link) => (
|
||||
@@ -161,48 +120,84 @@ export function ContentContent({
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="space-y-2">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<Typography variant="large" className="text-base">
|
||||
{t("pdfTitle")}
|
||||
</Typography>
|
||||
<Button asChild variant="outline" effect="swap" size="xs" radius="sm">
|
||||
<a
|
||||
<section className="space-y-2" aria-labelledby="linkedin-section-title">
|
||||
<div id="linkedin-section-title">
|
||||
<SectionHeading
|
||||
title={t("pdfTitle")}
|
||||
titleIcon="mdi:linkedin"
|
||||
titleIconClassName="text-[#0a66c2]"
|
||||
href="https://www.linkedin.com/in/poyrazavsever/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={t("linkedinProfile")}
|
||||
>
|
||||
<ButtonIcon>
|
||||
<Icon icon="mdi:linkedin" width={15} height={15} />
|
||||
</ButtonIcon>
|
||||
<ButtonLabel>@poyrazavsever</ButtonLabel>
|
||||
</a>
|
||||
</Button>
|
||||
label={t("linkedinProfile")}
|
||||
handle="@poyrazavsever"
|
||||
icon="mdi:linkedin"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2 lg:grid-cols-3">
|
||||
{pdfFiles.map((pdf, index) => (
|
||||
<button
|
||||
key={pdf}
|
||||
key={pdf.fileName}
|
||||
type="button"
|
||||
onClick={() => openPdfModal(index)}
|
||||
className="cursor-pointer text-left"
|
||||
className="cursor-pointer text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||
aria-label={t("openPdf", { name: pdf.title })}
|
||||
>
|
||||
<Card className="overflow-hidden rounded-sm border-border p-0 transition-colors hover:border-zinc-700">
|
||||
<PdfFirstPagePreview
|
||||
src={`/pdf/${pdf}`}
|
||||
title={t("pdfPreviewTitle", { name: pdf })}
|
||||
<Card className="relative aspect-4/5 overflow-hidden rounded-sm border-border bg-muted/20 p-0 transition-colors hover:border-zinc-700">
|
||||
{pdf.thumbnailSrc ? (
|
||||
<Image
|
||||
src={pdf.thumbnailSrc}
|
||||
alt={t("pdfPreviewTitle", { name: pdf.title })}
|
||||
fill
|
||||
className="object-cover"
|
||||
sizes="(max-width: 768px) 50vw, 33vw"
|
||||
/>
|
||||
) : (
|
||||
<span className="flex h-full w-full flex-col items-center justify-center gap-2 p-4 text-center text-muted-foreground">
|
||||
<Icon icon="mdi:file-pdf-box" width={34} height={34} />
|
||||
<Typography variant="small">{pdf.title}</Typography>
|
||||
</span>
|
||||
)}
|
||||
</Card>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="space-y-2" aria-labelledby="x-section-title">
|
||||
<div id="x-section-title">
|
||||
<SectionHeading
|
||||
title={t("xTitle")}
|
||||
titleIcon="ri:twitter-x-fill"
|
||||
href={X_JAVASCRIPT_ANATOMY_URL}
|
||||
label={t("xSeries")}
|
||||
handle="@poyrazavsever"
|
||||
icon="ri:twitter-x-fill"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2 md:grid-cols-2">
|
||||
{xVideos.map((video) => (
|
||||
<Card
|
||||
key={video.src}
|
||||
className="relative aspect-video overflow-hidden rounded-sm border-border bg-black p-0"
|
||||
>
|
||||
<video
|
||||
controls
|
||||
playsInline
|
||||
preload="metadata"
|
||||
className="absolute inset-0 h-full w-full object-cover"
|
||||
aria-label={t("xVideoTitle", { episode: video.episode })}
|
||||
>
|
||||
<source src={video.src} type="video/mp4" />
|
||||
{t("videoUnsupported")}
|
||||
</video>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Modal open={pdfModalOpen} onOpenChange={setPdfModalOpen}>
|
||||
<ModalContent size="xl" className="rounded-sm p-4">
|
||||
<ModalTitle>
|
||||
{activePdf ? activePdf.replace(/\.pdf$/i, "") : t("pdfModalDefaultTitle")}
|
||||
{activePdf?.title ?? t("pdfModalDefaultTitle")}
|
||||
</ModalTitle>
|
||||
|
||||
<div className="mt-3 flex flex-wrap items-center justify-between gap-2">
|
||||
@@ -218,7 +213,7 @@ export function ContentContent({
|
||||
className="rounded-sm"
|
||||
disabled={!canGoPrev}
|
||||
onClick={() =>
|
||||
setActivePdfIndex((prev) => Math.max(0, prev - 1))
|
||||
setActivePdfIndex((previous) => Math.max(0, previous - 1))
|
||||
}
|
||||
>
|
||||
{t("prev")}
|
||||
@@ -229,8 +224,8 @@ export function ContentContent({
|
||||
className="rounded-sm"
|
||||
disabled={!canGoNext}
|
||||
onClick={() =>
|
||||
setActivePdfIndex((prev) =>
|
||||
Math.min(pdfFiles.length - 1, prev + 1),
|
||||
setActivePdfIndex((previous) =>
|
||||
Math.min(pdfFiles.length - 1, previous + 1),
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -242,9 +237,10 @@ export function ContentContent({
|
||||
{activePdf ? (
|
||||
<div className="mt-3 h-[70dvh] overflow-hidden rounded-sm border border-border">
|
||||
<iframe
|
||||
src={`/pdf/${activePdf}`}
|
||||
title={activePdf}
|
||||
src={activePdf.href}
|
||||
title={activePdf.title}
|
||||
className="h-full w-full"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
export type XVideo = {
|
||||
src: string;
|
||||
episode: number;
|
||||
};
|
||||
|
||||
export const X_JAVASCRIPT_ANATOMY_VIDEOS: readonly XVideo[] = [
|
||||
{
|
||||
src: "/video/bolum11render.mp4",
|
||||
episode: 11,
|
||||
},
|
||||
{
|
||||
src: "/video/bolum12Render.mp4",
|
||||
episode: 12,
|
||||
},
|
||||
];
|
||||
|
||||
export const X_JAVASCRIPT_ANATOMY_URL = "https://x.com/poyrazavsever";
|
||||
+43
-3
@@ -2,9 +2,49 @@ import { readdir } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
const PDF_DIR = path.join(process.cwd(), "public", "pdf");
|
||||
const PDF_THUMBNAIL_DIR = path.join(
|
||||
process.cwd(),
|
||||
"public",
|
||||
"pdf-thumbnails",
|
||||
);
|
||||
const PDF_LIMIT = 3;
|
||||
|
||||
export async function getPdfNotes() {
|
||||
const files = await readdir(PDF_DIR);
|
||||
export type PdfNote = {
|
||||
fileName: string;
|
||||
title: string;
|
||||
href: string;
|
||||
thumbnailSrc: string | null;
|
||||
};
|
||||
|
||||
function formatPdfTitle(fileName: string) {
|
||||
return fileName
|
||||
.replace(/\.pdf$/i, "")
|
||||
.split(/[-_]+/)
|
||||
.map((part) => part.charAt(0).toLocaleUpperCase("tr-TR") + part.slice(1))
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
export async function getPdfNotes(): Promise<PdfNote[]> {
|
||||
const [files, thumbnailFiles] = await Promise.all([
|
||||
readdir(PDF_DIR),
|
||||
readdir(PDF_THUMBNAIL_DIR).catch(() => [] as string[]),
|
||||
]);
|
||||
const thumbnails = new Set(thumbnailFiles);
|
||||
const pdfFiles = files.filter((file) => file.toLowerCase().endsWith(".pdf"));
|
||||
return pdfFiles.sort((a, b) => a.localeCompare(b));
|
||||
|
||||
return pdfFiles
|
||||
.sort((a, b) => a.localeCompare(b, "tr"))
|
||||
.slice(0, PDF_LIMIT)
|
||||
.map((fileName) => {
|
||||
const thumbnailName = `${fileName.replace(/\.pdf$/i, "")}.jpg`;
|
||||
|
||||
return {
|
||||
fileName,
|
||||
title: formatPdfTitle(fileName),
|
||||
href: `/pdf/${fileName}`,
|
||||
thumbnailSrc: thumbnails.has(thumbnailName)
|
||||
? `/pdf-thumbnails/${thumbnailName}`
|
||||
: null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
+8
-3
@@ -137,14 +137,19 @@
|
||||
"footer": "Press {shortcut} to open quickly"
|
||||
},
|
||||
"Content": {
|
||||
"youtubeTitle": "Latest YouTube Videos",
|
||||
"youtubeTitlePrefix": "Latest",
|
||||
"youtubeTitle": "Videos",
|
||||
"youtubeChannel": "My YouTube channel",
|
||||
"youtubeEmbedTitle": "YouTube video player",
|
||||
"pdfTitle": "LinkedIn PDF Notes",
|
||||
"pdfTitle": "PDF Notes",
|
||||
"linkedinProfile": "My LinkedIn profile",
|
||||
"pdfPreviewError": "Preview could not be loaded",
|
||||
"pdfPreviewTitle": "{name} preview",
|
||||
"openPdf": "Open the {name} PDF note",
|
||||
"pdfModalDefaultTitle": "PDF Note",
|
||||
"xTitle": "JavaScript Anatomy",
|
||||
"xSeries": "My JavaScript Anatomy series on X",
|
||||
"xVideoTitle": "JavaScript Anatomy, episode {episode}",
|
||||
"videoUnsupported": "Your browser does not support video playback.",
|
||||
"prev": "Previous",
|
||||
"next": "Next",
|
||||
"pdfNotFound": "No PDF files found inside `/public/pdf`."
|
||||
|
||||
+8
-3
@@ -137,14 +137,19 @@
|
||||
"footer": "Hızlıca açmak için {shortcut} kullan"
|
||||
},
|
||||
"Content": {
|
||||
"youtubeTitle": "Son YouTube Videoları",
|
||||
"youtubeTitlePrefix": "Son",
|
||||
"youtubeTitle": "Videoları",
|
||||
"youtubeChannel": "YouTube kanalım",
|
||||
"youtubeEmbedTitle": "YouTube video oynatıcı",
|
||||
"pdfTitle": "LinkedIn PDF Notları",
|
||||
"pdfTitle": "PDF Notları",
|
||||
"linkedinProfile": "LinkedIn profilim",
|
||||
"pdfPreviewError": "Önizleme yüklenemedi",
|
||||
"pdfPreviewTitle": "{name} önizleme",
|
||||
"openPdf": "{name} PDF notunu aç",
|
||||
"pdfModalDefaultTitle": "PDF Notu",
|
||||
"xTitle": "JavaScript Anatomisi",
|
||||
"xSeries": "X'teki JavaScript Anatomisi serim",
|
||||
"xVideoTitle": "JavaScript Anatomisi, bölüm {episode}",
|
||||
"videoUnsupported": "Tarayıcınız video oynatmayı desteklemiyor.",
|
||||
"prev": "Önceki",
|
||||
"next": "Sonraki",
|
||||
"pdfNotFound": "/public/pdf içinde PDF bulunamadı."
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
"mermaid": "^11.13.0",
|
||||
"next": "16.1.6",
|
||||
"next-intl": "4.13.0",
|
||||
"pdfjs-dist": "^5.5.207",
|
||||
"poyraz-ui": "3.0.2",
|
||||
"react": "19.2.3",
|
||||
"react-dom": "19.2.3",
|
||||
|
||||
Generated
+1
-134
@@ -26,9 +26,6 @@ importers:
|
||||
next-intl:
|
||||
specifier: 4.13.0
|
||||
version: 4.13.0(next@16.1.6(@babel/core@7.29.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(typescript@5.9.3)
|
||||
pdfjs-dist:
|
||||
specifier: ^5.5.207
|
||||
version: 5.7.284
|
||||
poyraz-ui:
|
||||
specifier: 3.0.2
|
||||
version: 3.0.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(mermaid@11.16.0)(react-dom@19.2.3(react@19.2.3))(react-hook-form@7.81.0(react@19.2.3))(react@19.2.3)(tailwindcss@4.3.2)(zod@4.4.3)
|
||||
@@ -529,81 +526,6 @@ packages:
|
||||
'@mixmark-io/domino@2.2.0':
|
||||
resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==}
|
||||
|
||||
'@napi-rs/canvas-android-arm64@0.1.100':
|
||||
resolution: {integrity: sha512-hjhCKhntPv9+t4ckHymdx0phYNcVW+GKQR6Lzw2zE+pOVjOplSmtx9nNNknTjbEDLcuLZqA1y8ufKg1XfgftzQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.100':
|
||||
resolution: {integrity: sha512-2PcswRaC7Ly645DGt88///zuFDhJxJYdKAs1uU3mfk1atYkXufgcgLfBpk6Tm12nCQBaNt1wpybuPZ4qOhTo8A==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@napi-rs/canvas-darwin-x64@0.1.100':
|
||||
resolution: {integrity: sha512-ePNZtj7pNIva/siZMg+HmbeozkIjqUIYdoymH8HaA3qK7LfzFN4WMBM8G6HQ9ZC+H3+Dnn5pqtiXpgLykaPOhw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.100':
|
||||
resolution: {integrity: sha512-d5cDB48oWFGU8/XPhUOFAlySgb/VAu7D+s8fi55K1Pcfg8aPplHWqMgibhVLU8ky7Pyg/fuiVLz4Nf3JrSTuUA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.100':
|
||||
resolution: {integrity: sha512-rDxgxRu69RvDlX/bh9o22DxLsGr8EqsNgotL9+RwQE1S0b0cqeatqsw6aW45mukm0B42DIAaAacKaYQ8cqS1nw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.100':
|
||||
resolution: {integrity: sha512-K3mDW66N+xT2/V439u1alFANiBUjdEx2gLiNYnCmUsva5jZMxWTjafBYwTzYK+EMFMHrUoabuU+T1BIP5CgbYQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.100':
|
||||
resolution: {integrity: sha512-mooqUBTIsccZpnoQC4NgrC1v6C1vof39etLNMnBwCY+p0gajWJvAHLGQ6g/gGyS5YrpDW+GefSN4+Cvcr08UWw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.100':
|
||||
resolution: {integrity: sha512-1eCvkDCazm7FFhsT7DfGOdSaHgZVK3bt/dSBl5EWHOWmnz+I7j8tPseJqqD81NF+MH21jKUK4wQSDjN0mdhnTg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.100':
|
||||
resolution: {integrity: sha512-20arT6lnI19S68qNlii73TSEDbECNgzMz2EpldC1V3mZFuRkeujXkcebRk0LRJe9SEUAooYiLokfMViY8IX7yA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@napi-rs/canvas-win32-arm64-msvc@0.1.100':
|
||||
resolution: {integrity: sha512-DZFFT1wIAg37LJw37yhMRFfjATd3vTQzjZ1Yki8u2vhO6Hi5VE6BVaGQ1aaDu7xb4iMErz+9EOwjpS7xcxFeBw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.100':
|
||||
resolution: {integrity: sha512-MyT1j3mHC2+Lu4pBi9mKyMJhtP6U7k7EldY7sj/uS5gJA65gTXt8MefJQXLJo5d/vZbuWmfxzkEUNc/urV3pHA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@napi-rs/canvas@0.1.100':
|
||||
resolution: {integrity: sha512-xglYA6q3XO5P3BNJYxVZ1IV7DLVjp1Py6nwag88YntrS+3vKHyYcMqXVS4ZztJmwz2uGvz1FWhI/4LgbR5uQDA==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@napi-rs/wasm-runtime@1.1.6':
|
||||
resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==}
|
||||
peerDependencies:
|
||||
@@ -2885,6 +2807,7 @@ packages:
|
||||
eslint@9.39.5:
|
||||
resolution: {integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
jiti: '*'
|
||||
@@ -4243,10 +4166,6 @@ packages:
|
||||
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
|
||||
engines: {node: '>=16 || 14 >=14.18'}
|
||||
|
||||
pdfjs-dist@5.7.284:
|
||||
resolution: {integrity: sha512-h4EdYQczmGhbOlqc3PPZwxevn7ApdWPbovAuWXOB/DjIyigSnwfy2oze7c6mRcSr9XgLp3eN3EeL4DyySTPMFw==}
|
||||
engines: {node: '>=22.13.0 || >=24'}
|
||||
|
||||
pend@1.2.0:
|
||||
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
|
||||
|
||||
@@ -5714,54 +5633,6 @@ snapshots:
|
||||
|
||||
'@mixmark-io/domino@2.2.0': {}
|
||||
|
||||
'@napi-rs/canvas-android-arm64@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-darwin-x64@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-win32-arm64-msvc@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.100':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas@0.1.100':
|
||||
optionalDependencies:
|
||||
'@napi-rs/canvas-android-arm64': 0.1.100
|
||||
'@napi-rs/canvas-darwin-arm64': 0.1.100
|
||||
'@napi-rs/canvas-darwin-x64': 0.1.100
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf': 0.1.100
|
||||
'@napi-rs/canvas-linux-arm64-gnu': 0.1.100
|
||||
'@napi-rs/canvas-linux-arm64-musl': 0.1.100
|
||||
'@napi-rs/canvas-linux-riscv64-gnu': 0.1.100
|
||||
'@napi-rs/canvas-linux-x64-gnu': 0.1.100
|
||||
'@napi-rs/canvas-linux-x64-musl': 0.1.100
|
||||
'@napi-rs/canvas-win32-arm64-msvc': 0.1.100
|
||||
'@napi-rs/canvas-win32-x64-msvc': 0.1.100
|
||||
optional: true
|
||||
|
||||
'@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
|
||||
dependencies:
|
||||
'@emnapi/core': 1.10.0
|
||||
@@ -9922,10 +9793,6 @@ snapshots:
|
||||
lru-cache: 10.4.3
|
||||
minipass: 7.1.3
|
||||
|
||||
pdfjs-dist@5.7.284:
|
||||
optionalDependencies:
|
||||
'@napi-rs/canvas': 0.1.100
|
||||
|
||||
pend@1.2.0: {}
|
||||
|
||||
performance-now@2.1.0: {}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user