244 lines
11 KiB
Markdown
244 lines
11 KiB
Markdown
# easy-slides engine
|
||
|
||
easy-slides 是一个独立的 Markdown 演示引擎,而不是演示内容仓库。它的关系更接近 GitBook:引擎可以通过 Git tag/commit 或 npm 包进行版本化,使用者在自己的 Git 仓库中维护配置、幻灯片和资源。
|
||
|
||
```text
|
||
easy-slides engine repo
|
||
├─ @easy-slides/cli
|
||
└─ slidev-theme-easy-jyy
|
||
│ Git or npm dependency
|
||
▼
|
||
slides content repo
|
||
├─ easy-slides.config.mjs
|
||
├─ slides/<slug>/slides.md
|
||
└─ .github/workflows/deploy-pages.yml
|
||
│ easy-slides build
|
||
▼
|
||
static dist/
|
||
```
|
||
|
||
本仓库只包含引擎、主题、测试和一个消费端示例。真正的课程、分享或博客演示应放在其他仓库。
|
||
|
||
## 在内容仓库中使用
|
||
|
||
创建新内容项目:
|
||
|
||
```bash
|
||
pnpm dlx @easy-slides/cli init my-slides
|
||
cd my-slides
|
||
pnpm install
|
||
pnpm dev -- welcome
|
||
```
|
||
|
||
已有仓库可以直接安装 CLI:
|
||
|
||
```bash
|
||
pnpm add -D @easy-slides/cli
|
||
```
|
||
|
||
不从 npm 发布或下载 easy-slides 包时,可以直接固定到引擎仓库的 tag 或 commit:
|
||
|
||
```bash
|
||
pnpm add -D '@easy-slides/cli@git+https://github.com/OWNER/easy-slides.git#v0.2.0'
|
||
```
|
||
|
||
私有仓库可以使用 SSH:
|
||
|
||
```bash
|
||
pnpm add -D '@easy-slides/cli@git+ssh://[email protected]/OWNER/easy-slides.git#COMMIT_SHA'
|
||
```
|
||
|
||
初始化一个同样使用 Git 依赖的内容仓库:
|
||
|
||
```bash
|
||
pnpm dlx 'git+https://github.com/OWNER/easy-slides.git#v0.2.0' \
|
||
init my-slides \
|
||
--engine 'git+https://github.com/OWNER/easy-slides.git#v0.2.0'
|
||
```
|
||
|
||
建议固定 tag 或完整 commit SHA,不要让生产部署长期跟随 `main`。引擎仓库会提交已经编译好的 `dist-cli/`,其中包含匹配版本的 JYY 主题;因此 Git 安装不需要运行 `prepare`,也不会再访问 npm 获取主题包。这同时避开了 pnpm 10/11 默认禁止 Git 依赖运行构建脚本的限制。
|
||
|
||
这里替代的是 easy-slides 自身的 npm 发布渠道。Slidev、Vue 等第三方依赖仍由 pnpm 按 lockfile 从 npm registry 安装;如果部署环境完全不能访问 registry,还需要配置镜像、缓存或额外做依赖 vendoring。
|
||
|
||
如果引擎仓库是私有的,Cloudflare Pages 或 GitHub Actions 还需要具备读取该 Git 仓库的 deploy key 或 access token。
|
||
|
||
推荐的 `package.json`:
|
||
|
||
```json
|
||
{
|
||
"private": true,
|
||
"scripts": {
|
||
"dev": "easy-slides dev",
|
||
"present": "easy-slides present",
|
||
"build": "easy-slides build",
|
||
"check": "easy-slides check",
|
||
"export": "easy-slides export"
|
||
},
|
||
"devDependencies": {
|
||
"@easy-slides/cli": "^0.2.0"
|
||
}
|
||
}
|
||
```
|
||
|
||
内容仓库目录结构:
|
||
|
||
```text
|
||
my-slides/
|
||
├─ easy-slides.config.mjs
|
||
├─ package.json
|
||
├─ slides/
|
||
│ ├─ operating-systems/
|
||
│ │ ├─ slides.md
|
||
│ │ └─ assets/
|
||
│ └─ concurrency/
|
||
│ ├─ slides.md
|
||
│ └─ assets/
|
||
└─ .github/workflows/deploy-pages.yml
|
||
```
|
||
|
||
可运行的完整消费端示例见 [examples/content-repo](./examples/content-repo)。
|
||
|
||
## 项目配置
|
||
|
||
内容仓库根目录使用 `easy-slides.config.mjs`:
|
||
|
||
```js
|
||
export default {
|
||
title: 'Course Slides',
|
||
description: '公开课程与技术分享',
|
||
slidesDir: 'slides',
|
||
outDir: 'dist',
|
||
exportDir: 'exports',
|
||
}
|
||
```
|
||
|
||
配置、`slides/` 和部署 Secret 都属于内容仓库。引擎升级只需要更新 `@easy-slides/cli` 版本。
|
||
|
||
每套演示位于 `<slidesDir>/<slug>/slides.md`。首页 frontmatter 的 `title` 必填,还支持 `description`、`author`、`date`、`tags`、`cover` 和 `draft`。
|
||
|
||
## 内容仓库命令
|
||
|
||
```bash
|
||
pnpm dev -- <slug|slides.md>
|
||
pnpm present -- <slug>
|
||
pnpm check
|
||
pnpm exec easy-slides install-browser
|
||
pnpm build
|
||
pnpm export -- <slug> --format pdf
|
||
pnpm export -- <slug> --format png
|
||
pnpm export -- <slug> --format pptx
|
||
```
|
||
|
||
`dev` 提供 VS Code/浏览器实时预览。`present` 监听局域网,打印观众地址、带同步密码的演示者二维码和手机遥控入口。`build` 扫描全部非 draft 演示,生成博客式首页与 `/<slug>/` 静态站点。
|
||
|
||
`build` 的最终排版检查会启动引擎版本匹配的 Chromium。首次构建前运行 `pnpm exec easy-slides install-browser`;Linux CI 建议运行 `pnpm exec easy-slides install-browser --with-deps`,同时安装 Chromium 所需的系统依赖。`easy-slides init` 生成的 GitHub Pages workflow 已自动包含这一步,内容仓库不需要直接依赖或调用 `playwright-chromium`。
|
||
|
||
## 主题与演示能力
|
||
|
||
CLI 会自动加载其版本匹配的 `slidev-theme-easy-jyy`,内容仓库不需要复制主题源码。
|
||
|
||
主题提供 `default`、`cover`、`center`、`section`、`quote`、`two-cols`、`image-auto`、`image-left`、`image-right` 和 `image-full` 布局,并统一处理代码、表格、引用、KaTeX、Mermaid、绘图和录制界面。
|
||
|
||
主题也内置课程与技术课件常用的内容样式:`compact`、`outline`、`current`、`lead`、`muted`、`course-table`、`source-figure`、`v-word` 和 `cover-identity`。内容仓库可直接使用这些类,不需要为每套演示复制相同的 `style.css`;只有真正属于单套演示的视觉差异才应放在演示目录的局部样式中。
|
||
|
||
`image-auto` 会在图片加载后读取真实宽高比:宽高比不小于 `1.6` 的图片采用“正文在上、图片在下”,其余图片采用“正文在左、图片在右”。需要锁定方向时使用 `imagePlacement: left|right|top|bottom`:
|
||
|
||
```md
|
||
---
|
||
layout: image-auto
|
||
image: ./assets/architecture.png
|
||
imagePlacement: auto
|
||
imageFit: contain
|
||
---
|
||
```
|
||
|
||
Markdown 图片默认保持比例并限制在内容区,也可以显式覆盖:
|
||
|
||
```md
|
||
{fit="cover" position="50% 30%" max-height="65vh"}
|
||
```
|
||
|
||
主题默认使用 `1024 × 768` 的 4:3 画布。表格默认字号为 `30px`;代码默认字号为 `28px`,未指定高度时会按照内容使用自然高度,并根据前后正文自动限制在所在内容区内,长行会正常换行,超出后只上下滚动。需要按页调整时,在该页 frontmatter 中添加尺寸类:
|
||
|
||
```md
|
||
---
|
||
class: easy-table-lg easy-code-sm easy-code-height-md
|
||
---
|
||
```
|
||
|
||
表格提供 `easy-table-sm`、`easy-table-md`、`easy-table-lg` 三档,字号与单元格留白会同步变化。代码字号提供 `easy-code-sm`、`easy-code-md`、`easy-code-lg` 三档;需要固定高度时可使用 `easy-code-height-sm`(180px)、`easy-code-height-md`(300px)、`easy-code-height-lg`(420px)。代码始终软换行并仅上下滚动。
|
||
|
||
只调整单个内容块时,可以使用 `<div>` 包裹 Markdown 内容:
|
||
|
||
````md
|
||
<div class="easy-code-lg easy-code-height-sm">
|
||
|
||
```ts
|
||
const slides = await discover('slides')
|
||
```
|
||
|
||
</div>
|
||
````
|
||
|
||
同样的包裹方式也适用于表格,例如 `<div class="easy-table-sm">`。不添加固定高度类时,代码框保持内容的自然高度;内容较长时会自动扣除前后正文占用的空间并限制在内容区内。同一区域有多个代码框时也遵循这一规则。
|
||
|
||
公开放映页和演示者预览中的图片可以点击进入全屏预览,也可以聚焦图片后按 `Enter` 或空格打开;通过关闭按钮、点击背景或按 `Esc` 返回幻灯片。预览底部提供 `− / 百分比 / +` 工具栏,100% 对应图片原始像素尺寸;还可以使用鼠标滚轮、触控板或触屏双指缩放,并在放大后拖动查看细节,缩放范围为 10%–400%。
|
||
|
||
演示者点击图片时会优先在已连接的放映页打开;没有放映页确认时,图片在约半秒后回退到演示者页打开。演示者发起的同一轮预览会在所有放映页之间同步缩放、拖动和关闭;放映页自行点击打开的图片仍只影响本机。`present` 模式支持局域网跨设备联动,静态站点支持同一浏览器标签页联动。该交互不改变图片原始布局,也不会进入导出文件。
|
||
|
||
表格和代码块会在悬停或键盘聚焦时显示 `− / 百分比 / +` 缩放工具栏,可在 `60%–160%` 之间按 `10%` 调整;同一课件的放映页与演示者标签页会实时同步。代码缩放只改变字号,不改变高度或滚动位置。缩放只保存在当前页面内存中,刷新即恢复默认,也不会进入导出文件。
|
||
|
||
当一页内容超过 4:3 画布高度时,交互式放映页和演示者预览允许在幻灯片内部上下滚动,避免内容完全不可访问。滚动仅是兼容性兜底:`pnpm dev` 和 `pnpm check` 会直接解析 Slidev Markdown,在终端快速提示明显的静态溢出风险;开发期文件变化后只重新分析发生变化的页面,不启动浏览器,也不逐页访问预览路由。静态检查会按照 easy-jyy 的画布、布局、字号、表格、图片和显式代码高度估算容量,但不会伪造溢出像素;字体、异步组件、Mermaid、KaTeX 和自定义 CSS 的最终尺寸仍以 `pnpm build` 的浏览器渲染检查为准。构建检查会按课件、页码和标题打印真实纵向或横向溢出像素,发现问题也不会阻断构建。Web 页面本身不显示排版质量提示,导出、概览和打印仍保持固定画布;看到终端警告时应优先拆页、精简内容或调整字号。
|
||
|
||
动画、逐步显示、代码高亮和逐页演讲备注继续使用 Slidev 原生语法。
|
||
|
||
## 演示者 Token
|
||
|
||
Token 在内容仓库或部署平台中配置:
|
||
|
||
```bash
|
||
PRESENTER_TOKEN=a-long-non-obvious-token pnpm build
|
||
```
|
||
|
||
构建只写入 SHA-256 哈希。普通放映页不显示演示者入口;演示者通过 `/presenter/` 或 `easy-slides present` 输出的专用地址进入。演示者页面未解锁时使用全局模态锁屏,背景控件、翻页快捷键和焦点均不可操作;正确 token 解锁后,状态保存在当前标签页的 `sessionStorage`,刷新保持,锁定或关闭标签页后失效。未设置 token 时,`check` 会提示警告。
|
||
|
||
这只是静态站点的便利门槛,不是服务端安全边界。备注和演示者代码仍可被技术用户分析。
|
||
|
||
## 部署内容仓库
|
||
|
||
Cloudflare Pages:
|
||
|
||
- Build command:`pnpm build`
|
||
- Build output:`dist`
|
||
- Environment variable:`PRESENTER_TOKEN`
|
||
- 根路径部署不设置 `SITE_BASE`
|
||
|
||
GitHub Pages:在内容仓库中加入示例里的 workflow,把 `PRESENTER_TOKEN` 保存为 Actions Secret。工作流将 `SITE_BASE` 设置为仓库名子路径。
|
||
|
||
## 开发引擎
|
||
|
||
本仓库使用 pnpm workspace,包含 CLI 根包和主题包:
|
||
|
||
```bash
|
||
pnpm install
|
||
pnpm build
|
||
pnpm test
|
||
pnpm test:e2e
|
||
pnpm demo:dev -- getting-started
|
||
pnpm verify
|
||
```
|
||
|
||
- CLI 源码:[scripts](./scripts)
|
||
- JYY 主题:[packages/slidev-theme-easy-jyy](./packages/slidev-theme-easy-jyy)
|
||
- 外部内容仓库示例:[examples/content-repo](./examples/content-repo)
|
||
|
||
推送 `v*` tag 会由引擎仓库的 release workflow 先发布主题、再发布 CLI;仓库 Secret `NPM_TOKEN` 仅属于引擎项目,与任何 slides 内容仓库无关。
|
||
|
||
发布 Git tag 前必须先运行 `pnpm build` 并提交生成的 `dist-cli/`。CI 会验证源码与这些预编译产物保持一致;这样内容仓库只需读取 Git 仓库,不需要在安装依赖时编译引擎。
|
||
|
||
视觉语言参考蒋炎岩老师的公开课程幻灯片,以及 MIT 许可的 [jyyslide-md](https://github.com/zweix123/jyyslide-md)。
|
||
|
||
## License
|
||
|
||
MIT
|