扩展
Markdown 增强
GemBook 在服务端使用 marked 渲染 Markdown,默认支持 CommonMark 和 GitHub Flavored Markdown,GemBook 扩展了 Markdown 语法。
代码块信息
```<语言>? <文件名>? <状态>? <高亮>?
...
```语言:语法高亮的语言,构建时高亮文件名:显示在代码上方,也是 的标签名和<gbp-code-group> 的文件名<gbp-sandpack>状态:在代码组中,active默认显示,hidden不显示在标签中高亮:高亮的行,例如1,3-5,负数从末尾计算
例如使用高亮:
# 代码块信息
```md 1
# 代码块信息
```固定标题锚点 Hash
默认会根据标题文本字段生成 hash,但有时你需要固定 hash,比如国际化时。
### 固定标题锚 Hash {#fixed-hash}高亮引用块
> [!NOTE]
> 这是 [高亮引用块](https://github.com/orgs/community/discussions/16925)NOTE
这是
[!NOTE]
TIP
这是
[!TIP]
IMPORTANT
这是
[!IMPORTANT]
WARNING
这是
[!WARNING]
CAUTION
这是
[!CAUTION]
页面区域
在文档中使用 <gbp-content>
nav-inside:导航栏中sidebar-before:侧边栏顶部main-before:文档前面main-after:文档后面
<gbp-content slot="main-before">
<p>该文档已废弃。</p>
</gbp-content>插件
GemBook 使用自定义元素作为插件系统,
<gbp-raw src="package.json"></gbp-raw>部分插件在构建时由服务端渲染(例如 <gbp-raw>、<gbp-include>、<gbp-api>),不会在浏览器中加载任何代码,
其他插件由服务端渲染,在浏览器中工作(例如 <gbp-code-group>、<gbp-sandpack>)。
TIP
插件的开始标签写在一行中,否则 Markdown 可能把它当成文本
VSCode 默认不能在 Markdown 文件中使用 Emmet,可以通过设置开启:
"emmet.excludeLanguages": [], "emmet.includeLanguages": {"markdown": "html"},
自定义元素
使用自定义元素编写你自己的插件,例如使用 Gem:
import { adoptedStyle, css, customElement, GemElement, html, mounted, template } from '@mantou/gem';
// 从 esm.sh 加载,版本由 `<gbp-import>` 的 `dependencies` 指定
// @ts-expect-error
import confetti from 'canvas-confetti';
const style = css`
:scope {
display: block;
padding: 1rem;
border-radius: 0.5rem;
background: rgb(from currentColor r g b / 0.05);
}
`;
@customElement('my-plugin-hello')
@adoptedStyle(style)
export class MyPluginHelloElement extends GemElement {
@mounted()
#init = () => {
const observer = new IntersectionObserver(([entry]) => {
if (!entry.isIntersecting) return;
confetti({ particleCount: 50, origin: { x: 0.5, y: 0.5 } });
observer.disconnect();
});
observer.observe(this);
return () => observer.disconnect();
};
@template()
#content = () => html`Hello, <code>${'<gbp-import>'}</code>`;
}<gbp-import name="my-plugin-hello" dependencies="canvas-confetti" src="docs/hello.ts"></gbp-import>或者添加到配置文件的 plugins
<my-plugin-hello></my-plugin-hello>插件 API
打包的插件(全站插件和本地的 <gbp-import>gem-book/plugin,项目中没有安装 gem-book 时也可以使用(例如使用 npx):
import { adoptedStyle, connectStore, css, customElement, GemElement, html, template } from '@mantou/gem';
import { bookStore, getGlobal, theme } from 'gem-book/plugin';
const style = css`
:scope {
color: ${theme.primaryColor};
}
`;
@customElement('my-page-info')
@adoptedStyle(style)
@connectStore(bookStore)
export class MyPageInfoElement extends GemElement {
@template()
#content = () => html`${bookStore.doc?.title} (${bookStore.lang}) v${getGlobal('version')}`;
}bookStore:网站和当前页面的数据,服务端渲染时也可以使用,切换页面时更新config:网站配置lang:当前语言path:当前页面的路径,不包括语言前缀,例如/v1/guideversion:当前页面所在的旧版本,最新版本为空site:网站的导航和侧边栏,包括旧版本的doc:当前文档(标题、目录等),其他页面(例如 404)为空
theme:主题的 ,例如CSS 变量 theme.primaryColorgetGlobal(name): 中的值,globalname可以是路径,例如pkg.versionhtmlTemplate(html):将 HTML 字符串作为模版渲染,其中的自定义元素也会在服务端渲染
gem-book/plugin/server 用于只在服务端执行的代码,例如使用 @server() 的服务端元素,当前文档是当前页面的文档:
import fs from 'node:fs';
import { createState, customElement, GemElement, html, mounted, template } from '@mantou/gem';
import { server } from '@mantou/gemkit';
import { htmlTemplate } from 'gem-book/plugin';
import { renderMarkdown, resolveSrc } from 'gem-book/plugin/server';
// 只输出 HTML,浏览器中不会加载代码
@customElement('my-changelog')
@server()
export class MyChangelogElement extends GemElement {
#state = createState({ html: '' });
@server()
@mounted()
#init = async () => {
const resolved = resolveSrc(this.getAttribute('src') || '');
if ('file' in resolved) this.#state({ html: await renderMarkdown(fs.readFileSync(resolved.file, 'utf8')) });
};
@template()
#content = () => htmlTemplate(this.#state.html);
}