mirror of
https://github.com/zenlm/zen-blog.git
synced 2026-10-30 15:05:49 +00:00
- Replace Hugo static site generator with Next.js 15 + fumadocs-mdx - Convert 71 blog posts from Hugo format to MDX/MD - Convert Hugo shortcodes (figure, button, video, example, fullwidth) to MDX components (Figure, LinkButton, Video, Fullwidth) - Add remark-math + rehype-katex for LaTeX math rendering - Copy JSON case files to public/cases/ for reference - Update branding for Zen LM (site-nav, footer, metadata) - Static export for Cloudflare Pages deployment - Chinese (.zh.md) translations deferred for future migration
60 lines
1.3 KiB
TypeScript
60 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface MediaViewerProps {
|
|
src: string;
|
|
alt?: string;
|
|
type?: "image" | "video";
|
|
className?: string;
|
|
width?: number;
|
|
height?: number;
|
|
}
|
|
|
|
export function MediaViewer({
|
|
src,
|
|
alt = "",
|
|
type = "image",
|
|
className,
|
|
width,
|
|
height,
|
|
}: MediaViewerProps) {
|
|
const mediaProps = {
|
|
src,
|
|
alt,
|
|
className: cn(
|
|
"w-full h-full object-cover rounded-lg border overflow-hidden aspect-video",
|
|
className
|
|
),
|
|
...(width && height ? { width, height } : {}),
|
|
};
|
|
|
|
const renderMedia = () => {
|
|
if (type === "video") {
|
|
return (
|
|
<video {...mediaProps} controls loop>
|
|
Your browser does not support the video tag.
|
|
</video>
|
|
);
|
|
}
|
|
|
|
// eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text
|
|
return <img {...mediaProps} />;
|
|
};
|
|
|
|
return (
|
|
<div className="my-6 w-full">
|
|
<div className="relative w-full aspect-video">{renderMedia()}</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Helper components for easier MDX usage
|
|
export function ImageViewer(props: Omit<MediaViewerProps, "type">) {
|
|
return <MediaViewer {...props} type="image" />;
|
|
}
|
|
|
|
export function VideoViewer(props: Omit<MediaViewerProps, "type">) {
|
|
return <MediaViewer {...props} type="video" />;
|
|
}
|