@ bacons/ mdx (英语)
通用 磁共振 用于博览会的应用程序和网站.
- Build-time MDX以回放原生或回放DOM组件.
- 服务器将MDX交给一个CMS下载内容.
- 自定义组件和样式定义 .
将软件包添加到您的 npm 依赖性
bun add @bacons/mdx
设置
添加导入支持 md 财务报告和审定财务报表 mdx 在您的文件中 metro.config.js 文档.
metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const { withMdx } = require("@bacons/mdx/metro");
const config = withMdx(getDefaultConfig(__dirname));
module.exports = config;
手动设置
如果你需要自定义 babelTransformerPath 更多, 不使用此手动设置 :
metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const config = getDefaultConfig(__dirname);
config.resolver.sourceExts.push("md", "mdx");
config.transformer.babelTransformerPath = require.resolve("./transformer.js");
module.exports = config;
创建自定义地铁变压器 。 用于将MDX文件转换为JS + React Industrial后再与Babel相接.
./transformer.js
const upstreamTransformer = require("@expo/metro-config/babel-transformer");
const MdxTransformer = require("@bacons/mdx/metro-transformer");
module.exports.transform = async (props) => {
// Then pass it to the upstream transformer.
return upstreamTransformer.transform(
// Transpile MDX first.
await MdxTransformer.transform(props)
);
};
使用量
创建下标文件 :
./demo.mdx
import { CustomComponent } from './my-custom-component';
# Hello World
I **am** a _markdown_ file!
<CustomComponent />
此文件可导入并作为反应组件处理 :
./App.js
import Demo from "./demo.mdx";
export default function App() {
return <Demo />;
}
自定义组件
默认情况下,这个软件包对DOM元素使用一套不完整的通用回放原生组件. 您可能想要改进组件, 添加更多, 或者把它们交换给您自己 .
import { Text } from "react-native";
import { MDXComponents } from "@bacons/mdx";
export default function App() {
return (
<Demo
components={{
h1: (props) => <h1 {...props} />,
// Add custom components which can be used as JSX elements.
RedText: (props) => <Text {...props} style={{ color: "red" }} />,
// This can be used as `<RedText />` without the need to import it.
}}
/>
);
}
现在,您可以使用自定义组件 :
# Hello World
<RedText />
您可以使用 MDXComponents 反应上下文组件 .
import { Text } from "react-native";
import { MDXComponents } from "@bacons/mdx";
export default function App() {
// Pass any HTML element as a key to the MDXComponents component.
return (
<MDXComponents
components={{
h1: (props) => <Text {...props} />,
// Add custom components which can be used as JSX elements.
RedText: (props) => <Text {...props} style={{ color: "red" }} />,
// This can be used as `<RedText />` without the need to import it.
}}
>
<Demo />
</MDXComponents>
);
}
一定要通过
style向下推到你使用的组件, 这就是样式的级联.
自定义样式
这个软件包与大多数文件网站类似。 你为整个网站创造了高级风格. 这可以被分级缩小一个风格的范围.
import { MDXStyles } from "@bacons/mdx";
export default function App() {
// Pass any HTML element as a key to the MDXStyles component.
return (
<MDXStyles
h1={{
fontSize: 32,
fontWeight: "bold",
color: "red",
}}
>
<Demo />
</MDXStyles>
);
}
这个 <MDXStyles> 组件可以堆放在不同级别,想想这些像CSS类.
字体
您可以为导入添加支持 .mdx 在您的文件中 tsconfig.json 文档.
tsconfig.json
{
"compilerOptions": {
"typeRoots": ["./global.d.ts"]
},
"extends": "expo/tsconfig.base"
}
现在创建一个文件来宣布模块.
./global.d.ts
declare module "*.mdx" {
import React from "react";
import { CustomComponentsProp } from "@bacons/mdx";
const Component: React.FC<{
components?: CustomComponentsProp;
}>;
export default Component;
}
实验本地错误
可选的本土唯一步骤,MDX不需要工作.
React Industrial在本地使用 React DOM 组件或将字符串制成外部时,其错误信息不理想 <Text /> 要素。 这会使迁徙和代码共享非常痛苦. 这个软件包有一个实验性的 dev-唯一功能,在本地化上渲染出div,p,h1等内置反应时打印出优化错误.
简而言之,在你的 babel.config.js,并清除变换缓存 npx expo start --clear数字 :
module.exports = function (api) {
api.cache(true);
return {
presets: [["babel-preset-expo", { jsxImportSource: "@bacons/mdx/jsx" }]],
};
};
当你在本地生成一个 div, p, h1 等时, 你会得到一个有用的错误信息 .
export default function App() {
return <div>Hey</div>;
}
ERROR Unsupported DOM <p /> at: /Users/evanbacon/Documents/GitHub/bacons/mdx/apps/demo/src/App.tsx:1:11
This will break in production.
只网络组件
可以将MDX分解为DOM元素,而不是通用组件. 这在只建网络或只从网络迁移时可能有用. 要做到这一点,拉入 getDOMComponents 函数并传递给 components mDX组件的道具.
import { getDOMComponents } from "@bacons/mdx";
import Demo from "./readme.md";
export default function App() {
return <Demo components={getDOMComponents()} />;
}
这将使下列MDX成为DOM元素:
# Hello World
I **am** a _markdown_ file!
还有DOM:
<h1>Hello World</h1>
<p>I <strong>am</strong> a <em>markdown</em> file!</p>
下一个.js 用法
- 遵循此处详述的步骤: https://nextjs.org/docs/advanced-features/using-mdx 互联网档案馆的存檔,存档日期2013-12-21
- 将以下软件包添加到
transpile-modules在您内部next.config.js数字 :'@bacons/mdx', '@bacons/react-views', '@expo/html-elements',
远程 MDX
从远程服务器装入并渲染 MDX 内容 。 这对CMS驱动的内容、博客文章或任何需要运行时获取的MDX都有用.
服务器侧编译
首先,在您的服务器上编译 MDX( API 路由、 边缘功能或构建脚本) :
// app/api/mdx+api.ts (Expo Router API route)
import { compileMDX } from "@bacons/mdx/server";
export async function GET(request: Request) {
const url = new URL(request.url);
const slug = url.searchParams.get("slug");
// Fetch MDX content from your CMS or file system
const mdxSource = `
# Hello World
This is **bold** text with a <CustomButton>Click me</CustomButton>.
`;
const compiled = await compileMDX(mdxSource);
return Response.json(compiled);
}
这个 compileMDX 函数接受可选的语句并重排插件 :
const compiled = await compileMDX(mdxSource, {
remarkPlugins: [remarkGfm],
rehypePlugins: [rehypeHighlight],
});
客户端渲染
使用 RemoteMDX 构成部分和 useMDXFetch 获取和渲染远程 MDX 的钩子 :
import { RemoteMDX, useMDXFetch, MDXComponents } from "@bacons/mdx";
import { Text, ActivityIndicator } from "react-native";
function BlogPost({ slug }: { slug: string }) {
const { content, loading, error } = useMDXFetch(`/api/mdx?slug=${slug}`);
if (loading) return <ActivityIndicator />;
if (error) return <Text>Error: {error.message}</Text>;
if (!content) return null;
return (
<MDXComponents
components={{
CustomButton: (props) => (
<Text {...props} style={{ color: "blue" }} />
),
}}
>
<RemoteMDX source={content} />
</MDXComponents>
);
}
您也可以亲自获取内容并直接传递:
import { RemoteMDX, type CompiledMDX } from "@bacons/mdx";
function BlogPost({ content }: { content: CompiledMDX }) {
return <RemoteMDX source={content} />;
}
如何运作
- 服务器: 将 MDX 编译为 JSON 可执行 AST 格式( 非可执行 JavaScript)
- 客户端: 获取 JSON 并使用现有的组件系统使其
- 警卫: 无
eval()或代码执行 - AST 是纯数据 - 构成部分: 自定义组件通过
MDXComponents语境或components道具 - 样式数字 :
MDXStyles完全支持上下文
前题
前题被提取出来,并可在编译的产出中找到:
const compiled = await compileMDX(`
---
title: My Post
date: 2024-01-01
---
# Content here
`, {
remarkPlugins: [remarkFrontmatter, remarkMdxFrontmatter],
});
console.log(compiled.frontmatter);
// { title: "My Post", date: "2024-01-01" }
访问客户端的前题 :
function BlogPost({ slug }: { slug: string }) {
const { content } = useMDXFetch(`/api/mdx?slug=${slug}`);
return (
<>
<Text>{content?.frontmatter?.title}</Text>
<RemoteMDX source={content} />
</>
);
}
已知问题
- 哦,LI, ul是所有buggy。 公关欢迎.
- 原生图像比例很奇怪.
关于这个项目
这是一个通用的 MDX Expo (React & Metro) 执行. 它旨在成为利用通用地铁(Expo CLI)的博览会项目的通用MDX执行.
- 测试
apps/demo项目.