跳到主要内容

Live 指南 · ARC 2.0.0-beta.32

编写并嵌入 Markdown Slides

把一份 Markdown 内容对象写成可阅读的 slides,用 named layout 挂载播放器,并作为同站 16:9 播放器嵌入——本页含源代码与 live 播放器。

当一段说明既要作为文档阅读、又要作为短讲展示时,使用 Slides。每一页仍是由 Web Device 渲染的普通 Markdown 内容;Slides 只按明确的分隔线分页,并在页面中加入播放器,不引入独立 canvas、component 集合或内容类型。

本页是 feature live 指南(如何写、挂载、嵌入 deck,下方有可运行样例)。原子结构合同在 Markdown unit 页:slides: true front matter、thematic break / HR、::embed。unit 页是 reference;本页是可运行的 how-to。

此功能需要包含 Web Device slides widget 的 ARC build。本页描述的 segment 阅读形态——slide 卡片配解说、分节标题、slidesLayout——还需要包含 article-segment 文字稿的 build;在更早的 build 上,这些 deck 仍以旧的线性文字稿渲染。这里的目标 runtime 指实际承载该站点的 ARC 服务。不要从旧文档页面使用的版本号推断它是否可用;发布 deck 前先核验该服务。证据边界见版本兼容性。

Sample 合同

字段值
用途一份 Markdown 对象同时作为可读文字稿与可选 16 播放器
边界无 presenter view、PDF 导出 skill、自由定位 canvas 或内置 slide theme;播放器控制不写入文档
作者入口front matter slides: true + layout: slides(+ 可选 slidesLayout)· named layouts/slides.aup · 同站 ::embed
表面slides / document 文字稿;document 页上的 embed 播放器
公共状态承载站点的 ARC 含 slides widget 时为 released
Fallback / 失败无 widget:仅 server-rendered 文字稿;无 slides: true:普通文章;错误 --- 下划线导致 build 失败;未知 slidesLayout 导致 build 失败
验证下列 demo 路由 · 写作机 arc --version = 2.0.0-beta.32;服务端 runtime 仍须包含 slides widget

写一个 deck 内容对象

在要做成 deck 的 Markdown 内容文件开头 YAML front matter 中设置 slides: true。这个字段会把顶层 thematic break 读成 slide 分页。再单独设置 layout: slides,选择负责挂载播放器的 named layout。

源代码:

markdown
---
title: A short technical explanation
slides: true
layout: slides
---

## 从一个观点开始

第一张 slide 就是一段普通 Markdown 正文。

---

## 继续下一张 slide

- 一个列表
- 一张表格
- 一段代码

slides: true 与 layout: slides 回答的是不同问题。前者把正文变成 deck,后者选择 layouts/slides.aup。没有 widget 的 deck 仍会以 server-rendered 的可读文字稿出现,但不会有播放器控制。对象已经有自己的 layout.aup 时,不要再写 layout: slides:一个对象只能选择一种 object layout。

一次挂载播放器

在站点根目录加入 named layout。所有选择 layout: slides 的对象都会通过它获得播放器。

源代码:layouts/slides.aup

aup
page slides {
  view root {
    detail-content body slot=content
    widget deck name=slides target=".aup-deck"
  }
}

detail-content 会让文字稿留在正常的可阅读内容区域。slides widget 会在它上方插入一个 16 播放器。播放器读取站点已有的视觉 token(颜色、字体与间距等),不携带独立的 slide theme,因此不需要在这份 deck 内容中另配样式。

允许同站嵌入(页内播放器必需)

ARC 默认安全头是 Content-Security-Policy: frame-ancestors 'none'。这会拦截所有 iframe,包括同站 deck embed。使用 ::embed 嵌入 deck 的站点必须为本站放开 framing。

源代码:.web/security

yaml
# 允许本站 iframe 嵌自己的页面(Markdown Slides embed、站内 frame)
frame-ancestors: "'self'"

没有这份配置时,deck 的独立页面仍可打开,但文章/文档中的 embed 会显示为空白 frame。本站已带该覆盖;在其他站点启用 Slides 时复制同一形状。

查看一个真实 deck

在需要展示 deck 的页面 Markdown 文件中加入下面的 directive,并把 url 换成你已发布 deck 的同站绝对路径。下面这个同站内容对象就是本指南使用的 demo source。

源代码:

markdown
::embed{url="/zh/docs/web-device/slides-demo/"}

渲染结果:

Slides widget 完成客户端初始化前,iframe 内仍会保留 server-rendered 的文字稿;初始化后,固定的 16 frame 会把播放器作为可见表面呈现。打开独立 demo 页面,可以查看默认的播放器和可阅读文字稿。文档与 source 仍然只读;播放器控制只会改变浏览器本地的呈现状态,绝不会写入文档或 source。

在一页中放入两个 deck

一页不限制只能嵌入一个 deck。为每个同站页面地址各写一条 directive 即可。本指南同时放入了一个简短的交互 demo 与另一份概览 deck,因此两个播放器的内容和页数都不同。

源代码:

markdown
::embed{url="/zh/docs/web-device/slides-demo/"}

::embed{url="/zh/docs/web-device/slides-overview/"}

渲染结果:

每条 directive 都会建立自己的同站 frame。翻动第一个播放器不会改变第二个播放器。每个 deck 的 slide fragment 与 ?full 演示模式都属于它自己的 frame,因此可以操作或全屏打开任意一个播放器,而不会让另一个播放器翻页或进入演示模式。这个 directive 没有“一页只能放一个 deck”的限制。每个嵌入的播放器仍会加载一份真实页面,因此每个页面地址都应有明确用途。

添加 speaker note 与分页

单独占一个 Markdown block 的 HTML comment 会成为 speaker note。在阅读形态中,note 就是文章正文:每张 slide 渲染成一张缩放的 slide 卡片,note 作为解说文字排在卡片旁边或下方。note 内的空行会成为段落分隔。note 不会显示在投影的 slide 中。把 note 写成你讲这一页时要说的话,文字稿读起来就像一篇演讲整理稿。

源代码:

markdown
## 解释边界

<!--
展示例子前停一下。

空行之后是第二个段落。
-->

---

## 展示例子

---、***、___ 与 - - - 都可以作为 slide 边界。deck 不能把这些顶层 thematic break 当作装饰性的 horizontal rule。--- 前必须留一个空行;否则 Markdown 可能把横线读成 heading underline,build 会拒绝这个 deck。fenced code block 内的 ruler 仍是代码,不会分页。

用分节页拆开长 deck

内容只有一个 #(一级 heading)的页面是分节页(divider)。在播放器中它是一张普通的标题页;在阅读形态中它渲染为 segment 之间的节标题,而不是 slide 卡片。只把 # 用于分节、## 用于普通 slide 标题,长 deck 就不再是一整列刻板的格式。# heading 之外还有其他内容的页面(副标题段落、图片)仍是普通 slide。分节页也可以带 speaker note;该 note 会以全宽显示在节标题下方。

源代码:

markdown
# 第一部分:为什么

---

## 问题

选择阅读形态的板式

front matter 中的 slidesLayout 决定每个 segment 里 slide 卡片与 note 的排布。一个 deck 一个值。无论有没有 note,每张卡片的尺寸都相同,页面保持工整。

slidesLayout排布
side(默认)卡片在左 · note 在右
side-reversenote 在左 · 卡片在右
stacked全宽卡片 · note 在下
stacked-reversenote 在前 · 全宽卡片在下

源代码:

markdown
---
title: A short technical explanation
slides: true
layout: slides
slidesLayout: stacked
---

窄屏上,两个 side 板式会自动落为上下排布,并保留作者定义的次序:side 卡片在前,side-reverse note 在前。slidesLayout 拼写错误会导致 build 失败并列出有效值;绝不静默回退。

阅读、播放与分享

默认页面会把 inline player 放在文字稿上方。用前后控制按钮只移动播放器,不会改变页面形态。每张文字稿卡片本身就是控制:点击卡片——或指针悬停在卡片上时显示的 Play from here 按钮(键盘 focus 时同样显示)——会让播放器跳到那张 slide,并把播放器滚动到可见位置,不会切换到 presentation mode。在 inline reading mode 中,只有播放器获得 focus 时,箭头键、PageUp/PageDown、Space、Home 与 End 才控制它;阅读文字稿时这些按键不会被劫持。在 presentation mode 中,deck 会接管这些按键,直到退出该模式。触屏设备上,可以在 stage 上 swipe 切换 slide。

使用全屏控制、播放器获得 focus 时的 f,或 URL 中的 ?full 进入 presentation mode。有 heading 的 slide 会从第一个 heading 得到 fragment;没有 heading 的 slide 回退到从 1 开始的页码,重复 heading 则获得稳定的数字后缀。例如 demo 中的 ## 让播放器留在页面里 会得到 #slide-让播放器留在页面里,因此 /zh/docs/web-device/slides-demo/?full#slide-让播放器留在页面里 可以直接打开 presentation mode 的指定 slide。也可以先导航到某张 slide,再复制浏览器地址。首次打开页面时,未知 fragment 会从第一张开始;已打开播放器后把 URL 改成未知 fragment,会保留当前 slide。

本页只记录当前播放器与文字稿的合同。它不提供 presenter view、PDF export workflow、authoring skill、自由定位 canvas 或内置 presentation theme。

失败与限制

情况预期结果
slides: true 但承载 ARC 无 slides widget可读文字稿;无播放器外壳
有 slides: true 但缺 layout: slides可能有 deck 语义但无 named player 挂载
slidesLayout 值未知build 拒绝 deck,并列出有效值
heading 后 --- 前无空行被读成 setext 下划线;build 拒绝 deck
fenced code block 内的 thematic break仍是代码,不是分页
外部 ::embed URL不是同站 deck 播放器;遵循嵌入拒绝规则
同站 embed 且默认 frame-ancestors 'none'空白 iframe;设置 .web/security 中 frame-ancestors: "'self'"

单元合同(reference)

主题unit 页
slides: trueslides front matter
分页(---)thematic break / HR
::embedembed
Markdown 全索引Markdown units hub

验证证据

项值
基线(写作 CLI)2026-08-12 · arc --version → 2.0.0-beta.32
能力行docs/aup/capability-matrix.md (internal, non-routed) · slides: true · deck widget
实现providers/runtime/web-device/src/slides.ts;widgets/slides/;站点 layouts/slides.aup
站点 framing.web/security → frame-ancestors: "'self'"(embed 必需)
指南路由/zh/docs/web-device/markdown-slides/ · /en/docs/web-device/markdown-slides/
Live deck 路由/zh/docs/web-device/slides-demo/ · /zh/docs/web-device/slides-overview/ · AUP capability tour(及 en 对应路由)
本地运行arc service start --blocklet blocklets/arcblock --port 4900 · 打开指南 embed 与 demo;试窄屏与 ?full
验收embed 在 widget 加载后显示播放器(不是空白 frame);控制仅浏览器本地;无文档写入

要用本 slides 宿主做一整圈 document 表面的 AUP 漫步(18 个 primitive、Markdown 表面、deck 媒体宿主),见 AUP capability tour。嵌入 directive 的精确边界见嵌入外部和内部内容。Slides 以外的 named-layout 约定见组合页面与布局和目录参考。