remark-codesandbox
🎩 一个 remark 插件,可直接从代码块创建 CodeSandbox
在 CodeSandbox 上在线试试吧!(没错,我们在 CodeSandbox 里演示 CodeSandbox,为什么不呢!?)
特性
- 🔗 直接从代码块创建 CodeSandbox URL
- ✨ 支持 3 种不同的模式:meta、iframe 和 button
- 🚀 无需创建额外的文件夹或
package.json
文件 - 🎉 支持 MDX、Gatsby、Storybook Docs、docz 等...
- 📦 支持引入自定义模板,甚至可以直接从同一个仓库引入!
- ⚡ 一行代码设置,高度可定制
- 💪 非常适合库作者直接从文档中演示用法!
示例
reaviz
文档是使用 Storybook docs 和remark-codesandbox
构建的。- 本项目的 测试用例。
安装
yarn add -D remark-codesandbox
快速入门
将 remark-codesandbox
导入到你的 remark 插件中。
const codesandbox = require('remark-codesandbox');
remark().use(codesandbox, { mode: 'button' });
mdx(mdxCode, {
remarkPlugins: [[codesandbox, { mode: 'button' }]],
});
使用 /gatsby
端点来使用 Gatsby 版本的插件。
module.exports = {
plugins: [
{
resolve: 'gatsby-plugin-mdx',
options: {
gatsbyRemarkPlugins: [
{
resolve: 'remark-codesandbox/gatsby',
options: {
mode: 'button',
},
},
],
},
},
],
};
Gatsby (gatsby-transformer-remark)
使用 /gatsby
端点来使用 Gatsby 版本的插件。
module.exports = {
plugins: [
{
resolve: 'gatsby-transformer-remark',
options: {
plugins: [
{
resolve: 'remark-codesandbox/gatsby',
options: {
mode: 'button',
},
},
],
},
},
],
};
config.module.rules.push({
test: /\.(stories|story)\.mdx$/,
use: [
{
loader: '@mdx-js/loader',
options: {
compilers: [createCompiler({})],
remarkPlugins: [[codesandbox, { mode: 'button' }]],
},
},
],
});
用法
为你的代码块添加一个特殊的元标签。
```js codesandbox=react
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
<h1>Hello remark-codesandbox!</h1>,
document.getElementById('root')
);
```
然后... 就完成了!
上面将 mode
设置为 button
的示例将在代码块后面附加一个 CodeSandbox 按钮。点击它将打开生成的沙箱。是不是很酷!
还有其他模式和额外配置,请查阅下面的文档了解更多信息。
文档
Markdown 语法
在代码块后面附加 codesandbox
元数据以启用 remark-codesandbox
。这里的值是沙箱的 id
。
```js codesandbox=new
// ...
```
有一组默认的官方沙箱模板,你可以在这里找到列表。一些例子包括 new
(react)、vanilla
(parcel)、vue
、static
等...
代码块的内容将完全替换入口文件。因此对于 new
模板,内容将完全替换 src/index.js
文件。请确保导入模板所需的包以使其正常工作。
该插件还提供了一些默认的别名。react
是 new
的别名。react-component
也是 new
的别名,但将入口文件更改为 src/App.js
。这样你就可以在代码块中只导出一个 React 组件。
```js codesandbox=react-component
import React from 'react';
export default function App() {
return <h1>Hello remark-codesandbox!</h1>;
}
```
也可以使用任何现有的沙箱。只需从 URL 中获取沙箱的 id
。id
通常是沙箱 URL 的最后 ~5 个随机字符。从 Github 导入的沙箱也受支持,其 id
通常是沙箱预览 URL 的子域名(~10 个随机字符)。
```js codesandbox=mqpp1d4r0
// ...
```
想使用自定义模板并将其与代码一同版本控制在同一个仓库中?使用 file:
方案直接从文件系统加载模板!下面的代码将从路径 ./templates/vanilla-console
加载模板,该路径是相对于 Markdown 文件而言的。文件模板是至少包含一个 package.json
文件的目录。
与前面的示例一样,代码块的内容将替换模板中的入口文件。
```js codesandbox=file:./templates/vanilla-console
console.log('this code will replace the entry file content');
```
路径太长,每次都要输入?考虑将其创建为自定义模板。这也是推荐的方式!
专业提示:你可以直接在 codesandbox.io/s 上创建文件模板,然后通过菜单栏选择
File
->Export to ZIP
下载。解压到某个地方... 神奇地!你就得到了一个文件模板!
查询参数
也可以通过附加查询参数来自定义 URL。只需将其附加在沙箱 ID 后面即可。所有选项都允许使用。
```js codesandbox=new?codemirror=1&fontsize=12
// ...
```
有几个可以内联设置的特殊查询参数。下面的所有特殊查询参数都不会传递给生成的 CodeSandbox URL,因为它们不是官方支持的。
entry
引入了一个特殊查询参数 entry
,允许你使用代码块的内容覆盖特定文件。
```js codesandbox=new?entry=src/App.js
// Override `src/App.js` rather than the default `src/index.js` with this contents of the code block
```
overrideEntry
默认情况下,代码块中的内容将覆盖入口文件中的所有内容。你可以通过设置特殊查询参数 overrideEntry
来更改此行为。
将 overrideEntry
设置为行号范围,以指定代码块要覆盖入口文件的哪一部分。下面的示例将用代码块中的内容替换 react
模板(src/index.js
)入口文件的第 4 到 12 行。
```js codesandbox=react?overrideEntry=4-12
ReactDOM.render(
<h1>Hello remark-codesandbox!</h1>,
document.getElementById('root')
);
```
通过这个技巧,你可以避免将不相关的代码放入代码块中,从而让读者专注于真正重要的内容。
还有一个便捷的快捷方式,只指定起始行而不指定结束行,就可以从指定的行号开始替换整个入口文件,而无需知道它有多长。
```js codesandbox=react?overrideEntry=4-
ReactDOM.render(
<h1>Hello remark-codesandbox!</h1>,
document.getElementById('root')
);
```
如果你想原样使用模板,不包含代码块中的任何内容,添加 ?overrideEntry=false
查询字符串即可。
```js codesandbox=file:./templates/vanilla-console?overrideEntry=false
// This code will not be added to the sandbox
```
style
你也可以覆盖在 iframe 模式中使用的默认样式。
```js codesandbox=react?style=height:1000px
// The generated iframe will have height of 1000px instead of the default 500px
```
你可以传入多个样式,用 ;
分隔。所有样式都将合并并覆盖默认样式 (width:100%; height:500px; border:0; border-radius:4px; overflow:hidden;
)。
```js codesandbox=react?style=height:1000px;width:600px;
// The result style will be: "width:600px; height:1000px; border:0; border-radius:4px; overflow:hidden;"
```
选项
该插件接受一组选项,默认值如下
{
remarkPlugins: [
codesandbox,
{
// Can be one of `meta`, `iframe`, or `button`
mode: 'meta',
// The query here will be appended to the generated url for every sandbox. Can be `string`, `object`, `URLSearchParams` instance, or `undefined`
query:
mode === 'iframe'
? {
fontsize: '14px',
hidenavigation: 1,
theme: 'dark',
}
: undefined,
// Define custom templates or override existing ones
customTemplates: {},
// Whether to automatically deploy code blocks via CodeSandbox API
autoDeploy: false,
},
];
}
mode
-
meta
:生成 CodeSandbox URL 并将其存储在 AST 中。这种模式本身不会对 markdown 产生任何视觉变化,它对于其他插件或用户介入并对沙箱 URL 执行任何操作非常有用。URL 将存储在node.data.codesandboxUrl
和node.data.hProperties.dataCodesandboxUrl
中。一个示例用法是自定义 UI 中的 CodeSandbox 按钮。 -
iframe
:这种模式将完全用生成的沙箱 iframe 标签替换代码块。iframe 带有默认的查询参数,但你可以通过iframeQuery
覆盖它们。 -
button
:这种模式将保持代码块不变,并在代码块后面立即附加一个CodeSandbox 按钮,如下所示。
query
默认情况下,除了附加到生成 URL 的 module
键之外,没有其他查询。你可以在此处为每个 URL 自定义查询。但是,当 mode
为 iframe
时,将有一组预定义的自定义查询,如下所示。
query =
mode === 'iframe'
? {
fontsize: '14px',
hidenavigation: 1,
theme: 'dark',
}
: undefined;
你可以通过将 query
传递给选项来覆盖它们。请注意,传递的对象将替换默认对象,如果你想保留默认查询,请确保再次包含它们。
customTemplates
定义在代码块中使用的自定义模板。预期一个对象,其中键是模板 ID,值是模板信息。
模板信息是一个对象,其接口如下所示。
interface TemplateInfo {
extends: string;
entry?: string;
query?: string | { [key: string]: string } | URLSearchParams;
files?: { [filePath: string]: { content: string | Object } };
}
extends
:为了让定义自定义模板更容易,插件接受一个extends
键,让你扩展任何现有模板。值可以是任何 CodeSandbox ID,或file:
路径,或任何其他自定义模板 ID。如果使用file:
路径,建议使用绝对路径。默认情况下,相对路径是相对于process.cwd()
的,这与在代码块中内联定义的相对路径不同。entry
:要在模板中显示的入口文件,也是代码块将替换到的文件。允许用户使用同一个模板/沙箱覆盖不同的文件。query
:要附加到生成 URL 的查询参数。它将合并并覆盖上面options.query
中的任何键。但是,它会被代码块元数据中内联定义的查询合并和覆盖。files
:要合并和覆盖现有文件的附加文件。其签名遵循官方 API。建议尽可能在extends
字段中使用file:
路径,因为它更容易管理和版本控制。
下面是默认的自定义模板。
{
// Alias `react` to `new`
react: {
extends: 'new',
},
// Alias `react-component` to `new`, but also override `entry` to `src/App.js`
'react-component': {
extends: 'new',
entry: 'src/App.js',
},
}
autoDeploy
默认情况下,URL 是在本地生成,而无需调用官方 API。仅当用户点击按钮或查看 iframe 时才会调用 API。这是通过在本地手动构建 parameters
并通过 lz-string
压缩它们来完成的。请注意,有通用指南建议 URL 保持在 2000 字符以内,较长的 URL 可能在某些浏览器中不起作用。
你可以通过将 autoDeploy
设置为 true
来绕过此限制。这样会得到一个带有唯一 codesandbox_id
的短 URL。缺点是生成 URL 需要更多时间。
通常的做法是在生产环境(或当结果 URL 对于你支持的浏览器来说太长时)将其设置为 true
,而在开发时保持 false
以加快重载速度。
{
autoDeploy: process.env.NODE_ENV === 'production';
}
贡献
运行 git clone
和 cd
。
yarn # Install dependencies
yarn test # Run tests
yarn example # Run build on all examples
yarn bump [patch|minor|major] # Bump version of remark-codesandbox
yarn release # Publish remark-codesandbox to npm
许可
MIT