# 内容组件

> OINK 新增的本地、可复用内容组件

---

LLMS index: [llms.txt](/llms.txt)

---

OINK 把已经在多个 PGSTY 站点证明具有复用价值的内容组件纳入主题。每个组件都有稳定的作者接口、唯一实例 ID、本地资源和明确的安全边界。站点专用的数据控件仍然留在主题之外。

## 加载模型 {#loading-model}

交互式短代码会标记页面实际使用的功能。OINK 随后为每个所需样式或运行时只加入一次，即使页面中存在多个组件实例也不例外。普通页面不会下载从未使用的组件代码。

相对资源与链接参数会经过 Hugo URL 处理，因此部署到 `baseURL`
子路径时仍然正确。在适用情况下，组件标记还覆盖打印、深色模式、移动端、键盘操作与减少动态效果偏好。

## Asciinema {#asciinema}

使用 `asciinema` 播放保存在本地的 `.cast` 终端录像：

```go-html-template
{{< asciinema
  file="oink/demo.cast"
  speed="1.5"
  markers="0:开始,1:完成"
>}}
```

<div id="td-asciinema-bbf537a5dde5ac2757c19efb946c0686-0" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-timer-label="播放时间">
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":false,"fit":"width","loop":false,"markers":[0,"开始",1,"完成"],"preload":false,"speed":1.5,"startAt":0},"src":"/oink/demo.cast","theme":"auto"}</script>
</div>


`file` 是必填参数，也可以作为第一个位置参数传入。支持的选项包括
`theme`、`fit`（`width`、`height`、`both` 或 `none`）、`autoplay`、`loop`、
`preload`、`speed`、`startAt`、`poster`、`cols`、`rows`、`idleTimeLimit`、
`pauseOnMarkers`，以及逗号分隔的 `markers`。

为了离线使用，请把 cast 文件保存在本地。只有作者显式提供远程 URL 时，组件才会访问远端。

## ECharts {#echarts}

默认安全模式接受 JSON 或 YAML，并把解析后的值序列化到 `application/json`
元素中：

```go-html-template
{{< echarts height="280px" >}}
xAxis: { type: category, data: [源码, 构建, 发布] }
yAxis: { type: value }
series: [{ type: bar, data: [1, 2, 3] }]
{{< /echarts >}}
```

<!-- prettier-ignore-start -->


<div id="td-echarts-bbf537a5dde5ac2757c19efb946c0686-1" class="td-echarts td-max-width-on-larger-screens"
  data-td-echarts>
  <div data-td-echarts-canvas style="height: 280px"></div>
  <script type="application/json" data-td-echarts-options>{"series":[{"data":[1,2,3],"type":"bar"}],"xAxis":{"data":["源码","构建","发布"],"type":"category"},"yAxis":{"type":"value"}}</script>
</div>


<!-- prettier-ignore-end -->

`height` 默认为 `400px`，并且必须使用安全的 CSS 长度单位。`theme`
用来选择 ECharts 主题，`full=true` 则移除通常的正文宽度限制。

旧页面可能包含 JavaScript 围栏代码块与 `$fn:name` 引用。除非短代码设置
`unsafe=true`，或站点临时启用以下开关，否则 OINK 会拒绝这种可执行形式：

```yaml
params:
  content:
    echarts_unsafe: true
```

该开关只能用于经过审查的迁移过程。新图表应始终采用结构化 JSON/YAML 模式。

## Infographic {#infographic}

`infographic` 使用本地运行时渲染 AntV Infographic DSL：

```go-html-template
{{< infographic >}}
infographic list-row-simple-horizontal-arrow
data
  items
    - label 源码
      desc Markdown 与配置
    - label 构建
      desc Hugo Extended
    - label 发布
      desc 静态文件
{{< /infographic >}}
```

<!-- prettier-ignore-start -->

<div id="td-infographic-bbf537a5dde5ac2757c19efb946c0686-2" class="td-infographic td-max-width-on-larger-screens"
  data-td-infographic data-height="auto">
  <div id="td-infographic-bbf537a5dde5ac2757c19efb946c0686-2-canvas" data-td-infographic-canvas></div>
  <script type="application/json" data-td-infographic-syntax>"infographic list-row-simple-horizontal-arrow\ndata\n  items\n    - label 源码\n      desc Markdown 与配置\n    - label 构建\n      desc Hugo Extended\n    - label 发布\n      desc 静态文件"</script>
</div>


<!-- prettier-ignore-end -->

`height` 接受 `auto` 或安全 CSS 长度；`full=true`
会移除通常的正文宽度限制。DSL 会作为数据序列化，而不是作为可执行脚本插入页面。

## 卡片与轮播 {#cards-and-carousel}

`doc-card` 与 `nav-card` 共用同一套卡片实现；`doc-cards` 与 `nav-cards`
可以创建一至四列的响应式卡片组。这些别名让现有站点内容继续使用语义最贴切的名称，同时避免复制标记与样式。

```go-html-template
{{< nav-cards cols="3" >}}
  {{< nav-card
    title="架构"
    link="/zh/docs/oink/architecture/"
    icon="fa-solid fa-diagram-project"
    desc="了解构建与运行时边界。"
  >}}
  {{< nav-card
    title="部署"
    link="/zh/docs/oink/deployment/"
    badge="仅依赖 Hugo"
  >}}发布静态输出。{{< /nav-card >}}
{{< /nav-cards >}}
```

<!-- prettier-ignore-start -->

<div id="td-nav-cards-bbf537a5dde5ac2757c19efb946c0686-3" class="td-content-cards" style="--td-card-columns: 3">
<article id="td-nav-card-bbf537a5dde5ac2757c19efb946c0686-nav-cards-3-0" class="td-content-card">
  <div class="td-content-card__body">
    <div class="td-content-card__head"><i class="fa-solid fa-diagram-project td-content-card__icon" aria-hidden="true"></i><a class="td-content-card__title" href="/zh/docs/oink/architecture/">架构</a></div><p class="td-content-card__description">了解构建与运行时边界。</p>
  </div>
</article>

<article id="td-nav-card-bbf537a5dde5ac2757c19efb946c0686-nav-cards-3-1" class="td-content-card">
  <div class="td-content-card__body">
    <div class="td-content-card__head"><a class="td-content-card__title" href="/zh/docs/oink/deployment/">部署</a><span class="td-content-card__badge">仅依赖 Hugo</span></div>
    <div class="td-content-card__links">发布静态输出。</div>
  </div>
</article>

</div>


<!-- prettier-ignore-end -->

卡片接受 `title`、`link`、`image`、`alt`、`icon`、`desc`、`accent` 与
`badge`。卡片正文可以包含 Markdown 链接。`desc` 中的 `{version}`
之类 token，在站点参数存在同名值时会被替换。

把文档卡片放进 `doc-carousel`，即可生成无障碍横向轮播：

```go-html-template
{{< doc-carousel label="OINK 工作流" >}}
  {{< doc-card title="编写" >}}创建成对内容。{{< /doc-card >}}
  {{< doc-card title="构建" >}}运行 Hugo Extended。{{< /doc-card >}}
  {{< doc-card title="验证" >}}检查静态站点。{{< /doc-card >}}
{{< /doc-carousel >}}
```

<!-- prettier-ignore-start -->

<section id="td-carousel-bbf537a5dde5ac2757c19efb946c0686-4" class="td-doc-carousel" data-td-carousel role="region"
  aria-roledescription="carousel" aria-label="OINK 工作流">
  <button class="td-doc-carousel__button" type="button" data-td-carousel-action="previous"
    aria-controls="td-carousel-bbf537a5dde5ac2757c19efb946c0686-4-track" aria-label="上一张卡片">‹</button>
  <div id="td-carousel-bbf537a5dde5ac2757c19efb946c0686-4-track" class="td-doc-carousel__track" data-td-carousel-track tabindex="0">
<article id="td-doc-card-bbf537a5dde5ac2757c19efb946c0686-doc-carousel-4-0" class="td-content-card">
  <div class="td-content-card__body">
    <div class="td-content-card__head"><strong class="td-content-card__title">编写</strong></div>
    <div class="td-content-card__links">创建成对内容。</div>
  </div>
</article>

<article id="td-doc-card-bbf537a5dde5ac2757c19efb946c0686-doc-carousel-4-1" class="td-content-card">
  <div class="td-content-card__body">
    <div class="td-content-card__head"><strong class="td-content-card__title">构建</strong></div>
    <div class="td-content-card__links">运行 Hugo Extended。</div>
  </div>
</article>

<article id="td-doc-card-bbf537a5dde5ac2757c19efb946c0686-doc-carousel-4-2" class="td-content-card">
  <div class="td-content-card__body">
    <div class="td-content-card__head"><strong class="td-content-card__title">验证</strong></div>
    <div class="td-content-card__links">检查静态站点。</div>
  </div>
</article>

</div>
  <button class="td-doc-carousel__button" type="button" data-td-carousel-action="next"
    aria-controls="td-carousel-bbf537a5dde5ac2757c19efb946c0686-4-track" aria-label="下一张卡片">›</button>
</section>


<!-- prettier-ignore-end -->

`label`
提供轮播的无障碍名称。方向键与可见的上一个/下一个按钮都能移动轨道；启用减少动态效果偏好时，不必要的动画会被禁用。

## 折叠块 {#details}

`details` 输出原生 `details` 与 `summary` 元素：

```go-html-template
{{% details title="为什么只依赖 Hugo？" closed="false" %}}
已经提交的浏览器资源让消费端构建保持可复现。
{{% /details %}}
```

<!-- prettier-ignore-start -->

<details id="td-details-bbf537a5dde5ac2757c19efb946c0686-5" class="td-details" open>
  <summary>为什么只依赖 Hugo？</summary>
  <div class="td-details__body">
已经提交的浏览器资源让消费端构建保持可复现。
</div>
</details>


<!-- prettier-ignore-end -->

`title` 设置摘要。折叠块默认关闭；设置 `closed=false` 可让它初始展开。

## 标签页 {#tabs}

OINK 沿用 Docsy 的 `tabpane` 与 `tab` 创作模型，同时保留导入站点依赖的
`selected=true` 与空白处理行为：

```go-html-template
{{< tabpane text=true >}}
  {{< tab header="本地" selected=true >}}
  使用完整本地主题构建。
  {{< /tab >}}
  {{< tab header="Cloudflare" >}}
  从源分支运行同一条 Hugo 命令。
  {{< /tab >}}
{{< /tabpane >}}
```

<!-- prettier-ignore-start -->




<ul class="nav nav-tabs" id="tabs-6" role="tablist"><li class="nav-item"><button class="nav-link active" id="tabs-06-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-06-00" role="tab" data-td-tp-persist="本地" aria-controls="tabs-06-00" aria-selected="true">本地</button></li><li class="nav-item"><button class="nav-link" id="tabs-06-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-06-01" role="tab" data-td-tp-persist="cloudflare" aria-controls="tabs-06-01" aria-selected="false">Cloudflare</button></li></ul>

<div class="tab-content" id="tabs-6-content"><div class="tab-body tab-pane fade show active" id="tabs-06-00" role="tabpanel" aria-labelledby="tabs-06-00-tab" tabindex="0">
使用完整本地主题构建。
</div><div class="tab-body tab-pane fade" id="tabs-06-01" role="tabpanel" aria-labelledby="tabs-06-01-tab" tabindex="0">
从源分支运行同一条 Hugo 命令。
</div>
</div>


<!-- prettier-ignore-end -->

Markdown 内容应设置
`text=true`；否则标签页会按代码进行语法高亮。标签页还支持按语言保存选择、禁用标签，以及右对齐条目。生成的标签与面板 ID 会形成正确的 ARIA 对应关系。

## 参数 {#parameters}

`param` 输出页面参数；页面没有该参数时，会回退到同名站点参数：

```go-html-template
当前版本：{{< param version >}}
```

当前版本：`v0.16.0`

指定参数不存在时，短代码会让构建失败。这是有意设计：缺少发布版本或仓库信息时，不应悄悄生成误导性文档。

## 现有富内容能力 {#existing-rich-content}

OINK 也为继承而来的内容功能提供本地运行时：

- `mermaid`、`math` 与 `markmap` 围栏代码块；
- `swaggerui` 与 `redoc` API 文档短代码；
- Docsy blocks、alert、image、include、readfile、cards 等既有短代码。

完整创作参考详见[短代码](/zh/docs/content/shortcodes/)与[图表和公式](/zh/docs/content/diagrams-and-formulae/)。

## 创作规则 {#authoring-rules}

- 优先使用结构化数据，而不是可执行内容。
- 为图片编写有意义的 `alt` 文本，并为轮播设置清晰的 `label`。
- 除非内容确实需要，否则不要启用自动播放。
- 创建新包装组件时，要在同一页测试多个完全相同的实例。
- 检查键盘导航、焦点可见性、深浅色主题、移动布局、打印输出与减少动态效果行为。
- 把带有业务语义的数据组件留在消费站点。
