This commit is contained in:
1 parent
c1541b80df
commit
b4c7908029
97 files changed
+12403
-154
No files matched your search
@@ -0,0 +1,74 @@
|
||||
import Image from "next/image";
|
||||
import type { ComponentPropsWithoutRef, ReactNode } from "react";
|
||||
import { Callout } from "./callout";
|
||||
import { CodeBlock } from "./code-block";
|
||||
|
||||
/**
|
||||
* MDX 组件映射。
|
||||
*
|
||||
* 通过替换原生元素,把 DESIGN.md 的排版规则与可访问性要求统一注入正文:
|
||||
* - img → next/image(图片优化 + 保留 alt)
|
||||
* - pre → 带语言标签与复制按钮的代码块
|
||||
* - a → 外链自动补 rel/target
|
||||
*
|
||||
* 类型说明:这里不使用 `mdx/types` 的 MDXComponents,因为它依赖可选安装的
|
||||
* @types/mdx。改为按组件签名手写映射类型,避免引入额外类型包。
|
||||
*/
|
||||
|
||||
type MdxImageProps = ComponentPropsWithoutRef<"img">;
|
||||
type MdxAnchorProps = ComponentPropsWithoutRef<"a"> & { children?: ReactNode };
|
||||
|
||||
/**
|
||||
* MDX 组件映射类型。
|
||||
*
|
||||
* `next-mdx-remote` 内部使用 `MDXComponents`(带字符串索引签名),
|
||||
* 因此这里显式声明索引签名,保证类型兼容的同时仍然约束了我们实际用到的键。
|
||||
*/
|
||||
export interface MdxComponentMap {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[key: string]: any;
|
||||
img: (props: MdxImageProps) => ReactNode;
|
||||
a: (props: MdxAnchorProps) => ReactNode;
|
||||
pre: typeof CodeBlock;
|
||||
Callout: typeof Callout;
|
||||
}
|
||||
|
||||
export const mdxComponents: MdxComponentMap = {
|
||||
// 文章内图片改用 next/image,alt 缺失时降级为空字符串(装饰性图片)
|
||||
img: ({ src, alt, width, height }) => {
|
||||
if (typeof src !== "string") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Image
|
||||
src={src}
|
||||
alt={alt ?? ""}
|
||||
width={typeof width === "number" ? width : 1200}
|
||||
height={typeof height === "number" ? height : 630}
|
||||
className="rounded-lg border border-hairline"
|
||||
sizes="(max-width: 768px) 100vw, 720px"
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
// 外链统一加上安全属性;站内锚点(# 开头)与相对路径保持原样
|
||||
a: ({ href, children, ...props }) => {
|
||||
const isExternal = typeof href === "string" && /^https?:\/\//.test(href);
|
||||
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
{...(isExternal
|
||||
? { target: "_blank", rel: "noopener noreferrer" }
|
||||
: {})}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
|
||||
pre: CodeBlock,
|
||||
Callout,
|
||||
};
|
||||
Reference in new issue
Block a user