Files
market/skills/guizang-ppt/references/components.md
Yige b15fce19bf feat: add guizang-ppt market skill (vendored from op7418, AGPL-3.0) (#20)
## 概述 / Summary

新增市场技能 **`guizang-ppt`**(归藏网页 PPT),vendored 自上游开源项目
[op7418/guizang-ppt-skill](https://github.com/op7418/guizang-ppt-skill)。

Add a new **market skill** `guizang-ppt` — generates single-file HTML
horizontal-swipe slide decks (web PPT) in two visual systems (editorial
"magazine × e-ink" / "Swiss International"). Vendored from the upstream
open-source project.

## 变更内容 / Changes

- `skills/guizang-ppt/`:SKILL.md(DesireCore frontmatter 覆盖层 +
上游正文)、`references/`(10)、`assets/`(2 模板 + motion.min.js + 9 张
webp)、`scripts/validate-swiss-deck.mjs`、`LICENSE`(AGPL-3.0)、`NOTICE.md`(署名与合规)
- `skills/guizang-ppt/_desirecore/`:DesireCore 维护态(不随上游覆盖)
- `frontmatter.yaml`:市场 frontmatter 覆盖层(i18n: zh-CN 源 + en-US 显示串,body
暂回退中文,留给 CI 翻译)
  - `upstream.json`:上游溯源(commit `014c572`、AGPL-3.0、作者 歸藏/op7418)
- `scripts/vendor/guizang-ppt.mjs`:可复用的 vendor 更新脚本(`--src <本地路径>` 或
`--ref <tag>`)
- `manifest.json`:`version` → `1.2.3`,`stats.totalSkills` → 25

## 定位 / Positioning

- **仅市场可选安装**:未加入 `builtin-skills.json`,不随客户端开机自动安装;用户在市场按需安装。
- 分类 `creative`;与已有 `pptx`(生成 .pptx 文件)区分:本技能生成 **HTML deck**。

## 许可与署名 / License & Attribution

上游为 **AGPL-3.0**。本技能保留原 `LICENSE` 与作者署名(`NOTICE.md` + `metadata.author`
+ `market.maintainer`),作为聚合内容分发。

## 校验 / Validation

- `python3 scripts/i18n/validate-i18n.py skills/guizang-ppt` → `OK: no
i18n issues found.`

## 手动更新流程 / Manual update

上游发版时:`node scripts/vendor/guizang-ppt.mjs --ref <tag>` → 核对 diff → 必要时
bump `_desirecore/frontmatter.yaml#version` 与 `manifest.json` → 提交。

---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-04 11:04:05 +08:00

15 KiB
Raw Blame History

组件参考 · Components

这是 guizang-ppt-skill skill 的组件手册。template.html 已经定义好了所有样式,这里只写"这个组件长什么样、怎么用"。

目录


基础 Slide 外壳

每一页都是一个 <section class="slide ...">。必须包含 data-theme 属性(lightdarkJS 翻页时会根据这个属性切换背景。

<section class="slide light" data-theme="light">   <!-- 浅色页 -->
<section class="slide dark" data-theme="dark">     <!-- 深色页 -->
<section class="slide light hero" data-theme="light">  <!-- Hero 页:浅色 + 薄遮罩透出 WebGL -->
<section class="slide dark hero" data-theme="dark">    <!-- Hero 页:深色 + 薄遮罩 -->

light vs dark 的使用:交替使用,每 2-3 页切换一次主题,避免连续超过 3 页同色。翻页时 WebGL 背景会自动在两个 shader 之间渐变过渡。

hero 类的使用:只给视觉主导的页面加(封面、金句页、章节过渡、结尾)。加 hero 后遮罩降到 12-16%WebGL 背景会大幅透出,所以不要在 hero 页上放太多文字。


字体 Typography

字体分工是本模板最重要的规则,严禁混用。

Class 用途 字体
.display 超大号英文Hero 页) Playfair Display 700, 11vw
.display-zh 超大号中文标题 Noto Serif SC 700, 7.8vw
.h1-zh 页面主标题 Noto Serif SC 700, 4.6vw
.h2-zh 副标题 Noto Serif SC 600, 3.2vw
.h3-zh 流水线步骤标题 Noto Serif SC 500, 1.9vw
.lead 引导段(比 body 大) Noto Serif SC 400, 1.9vw
.body-zh 正文/描述(非衬线) Noto Sans SC 400, 1.22vw
.body-serif 正文(衬线) Noto Serif SC 400, 1.3vw
.kicker 小节提示(标题上方) IBM Plex Mono, 12px uppercase
.meta 元信息标签 IBM Plex Mono, 0.88vw uppercase
.big-num 巨型数字 Playfair Display 800, 10vw
.mid-num 中号数字 Playfair Display 700, 5.5vw

核心规则

  • 衬线serif-zh / serif-en):标题、重点金句、数字 —— 用于"视觉重音"
  • 非衬线sans-zh):正文描述、大段阅读内容 —— 用于"信息密度"
  • 等宽monokicker、meta、foot 的英文标签 —— 用于"装饰节奏"

强调技巧

  • <em class="en">英文词</em> —— 把英文词渲染成 Playfair Display 斜体(很好看)
  • <em style="opacity:.65">短语</em> —— 让标题后半段淡出,制造节奏

Chrome & Foot

每一页的顶部和底部的元信息条。几乎所有页都应该有。

<div class="chrome">
  <div class="left">
    <span>第一幕 · 硬数据</span>
    <span class="sep"></span>
    <span>Act I</span>
  </div>
  <div class="right"><span>02 / 27</span></div>
</div>

<!-- ... 页面主体 ... -->

<div class="foot">
  <div class="title">项目名 · CodePilot | github.com/codepilot</div>
  <div>Act I · Dev Numbers</div>
</div>

规则

  • chrome.right 总是放页码 NN / TOTAL TOTAL 为总页数)
  • foot.title 是中文说明,foot.right 是英文 act 标记
  • chrome 和 foot 共同构成杂志感的"页眉页脚"

Callout 引用框

展示金句 / 关键观点 / 他人引言。

<div class="callout" style="max-width:80vw">
  <div class="q-big">"这东西在三年前,<br>需要一个十人团队做一年。"</div>
  <span class="cite">— 一个观察者的判断</span>
</div>

变体:

  • 不带 cite去掉 <span class="cite"> 即可
  • 带英文金句:<em class="en">"Thin Harness, Fat Skills."</em>
  • 在 hero 页使用:外层加 style="position:relative;z-index:2"(避免被背景遮罩盖住)

Stat 数字矩阵

展示数据指标,常与 .grid-6 / .grid-4 配合。

<div class="grid-6">
  <div class="stat">
    <span class="m">Duration</span>
    <span class="n">64<em style="font-size:.4em;opacity:.5;font-style:normal"></em></span>
    <span class="l">从 0 到现在</span>
  </div>
  <!-- ... 更多 stat ... -->
</div>

三段式结构:.m 等宽小标签 → .n 巨型数字 → .l 描述说明。数字后的单位用 <em> 缩小到 0.4emopacity 0.5。

常用布局容器

  • .grid-6 — 3×2 网格最常用6 个 stat
  • .grid-4 — 2×2 网格4 个 stat
  • .grid-3 — 3 等分单行3 个 stat / pillar

Platform 平台卡

展示社交平台 / 渠道 + 粉丝数。

<div class="plat">
  <div class="sub">Weibo</div>
  <div class="name">微博</div>
  <div class="nb">289K</div>
</div>

可选第四行(补充说明):

<div class="body-zh" style="font-size:max(11px,.8vw);opacity:.5;margin-top:.6vh">
  含小绿书同步
</div>

"Also On" 变体(补充平台):

<div class="plat" style="border-top-style:dashed;opacity:.72">
  <div class="sub">Also On</div>
  <div class="body-zh" style="font-weight:600;margin-top:.8vh">
    B 站 · 知乎
  </div>
</div>

Rowline 表格行

列表式内容,每行一个条目。

<div class="rowline">
  <div class="k">CLAUDE.md</div>
  <div class="v">你该怎么做事 —— 行为规则 + 工作偏好 + 禁止事项</div>
  <div class="m">EMPLOYEE · HANDBOOK</div>
</div>

三列结构:.k 衬线关键词 · .v 正文描述 · .m 等宽标签(右对齐)。第一个和最后一个 rowline 自动加上下边框。

变体2 列style="grid-template-columns:1fr 3fr" 去掉 .m 列。


Pillar 支柱卡

三支柱结构,常用于"概念并列"类型页面。

<div class="grid-3">
  <div class="pillar">
    <div class="ic">01</div>
    <div class="t">三层<br>文档体系</div>
    <div class="d">CLAUDE.md<br>+ 项目知识库<br>+ 护栏文件</div>
  </div>
  <!-- ... 更多 pillar ... -->
</div>

带图标的 pillar用于强调性页面

<div class="pillar" style="padding:4vh 2vw;border:1px solid currentColor;border-color:rgba(10,10,11,.2)">
  <div class="ic"><i data-lucide="compass" class="ico-lg"></i></div>
  <div class="t">判断力</div>
  <div class="d">决策和方向的权威。<br>取舍、品味、方向感。</div>
</div>

.ic 可以是序号(01 / 02 / 03A. / B. / C.),也可以是 Lucide 图标。


Tag & Kicker

Kicker 是标题上方的小提示文字(等宽、全大写、小字号):

<div class="kicker">过去 64 天 · 开发篇</div>
<div class="h1-zh">一个人,做了什么。</div>

Tag 是独立的标签胶囊(带边框):

<div style="display:flex;gap:1.6vw;flex-wrap:wrap">
  <div class="tag">早上 10 点起床</div>
  <div class="tag">周二 / 四下午健身</div>
  <div class="tag">晚上照样看剧 · 玩游戏</div>
</div>

Figure 图片框

这是本模板最容易踩坑的组件,务必遵守以下规则

基础结构

<figure class="tile">
  <div class="frame-img" style="height:26vh">
    <img src="图片素材/xxx.png" alt="说明">
  </div>
  <figcaption class="frame-cap">
    <span class="pf">推特 · Twitter</span>
    <span class="nb">137K</span>
  </figcaption>
</figure>

关键约束(血泪经验,不要违反)

  1. 图片网格必须用 height:Nvh 固定高度,不要用 aspect-ratio

    • 原因:网格里用 aspect-ratio 容易撑破父容器,导致图片堆叠。
    • 推荐尺寸:.h-16 (小型面板) / .h-18 (紧凑条形) / .h-22 (标准网格) / .h-26 (突出展示) / .h-28 (大图)。
    • 单张主图可以用模板提供的比例类:.r-16x9 / .r-16x10 / .r-4x3 / .r-3x2 / .r-3x4 / .r-1x1
    • 同一组图片必须使用同一个高度类,不要一张 25vh、一张 21vh 混用。
  2. object-position:top center(已在 CSS 里设好),只允许裁掉底部。

    • 严禁裁剪左右和顶部 —— 这是图片的核心身份信息区。
  3. 网格里多张图时,用内联 grid 而不是 grid-3

    <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:1vh 1.2vw">
      <figure class="tile">...</figure>
      <figure class="tile">...</figure>
      <figure class="tile">...</figure>
    </div>
    
  4. 图片与布局其他部分对齐:使用 .grid-2-7-5 / .grid-2-6-6 / .grid-2-8-4 的 grid 结构自然顶对齐。不要给图片加 align-self:end

  5. 信息图 / 截图再设计:给 .frame-img 同时加 .fit-contain,避免图内文字和标注被裁切。

  6. 用户原始截图比例不合适时:优先按 screenshot-framing.md 做 CleanShot X 式程序化适配;只有截图太长、太窄或需要重构信息时,才重新生成"截图再设计 / UI 情景图"。

Frame Caption 变体

<!-- 标准:左 figure 名,右数字 -->
<figcaption class="frame-cap">
  <span class="pf">推特 · Twitter</span>
  <span class="nb">137K</span>
</figcaption>

<!-- 带编号 -->
<figcaption class="frame-cap">
  <span class="idx">01</span>
  <span class="pf">AI 润色</span>
  <span>Polish</span>
</figcaption>

图片占位(设计阶段占位符)

图片还没有就位时,用虚线框占位:

<div class="img-slot r-4x3">  <!-- r-4x3 / r-16x9(default) / r-3x2 / r-1x1 -->
  <span class="plus">+</span>
  <span class="label">GitHub 截图位置</span>
</div>

Icons 图标

严禁使用 emoji。用 Lucide via CDNtemplate.html 已引入)。

<i data-lucide="compass" class="ico-lg"></i>     <!-- 大图标pillar 用) -->
<i data-lucide="target" class="ico-md"></i>      <!-- 中图标(列表项用) -->
<i data-lucide="check-circle" class="ico-sm"></i>  <!-- 小图标inline 用) -->

常用 Lucide 图标名(按含义分组):

  • 判断类:compass, target, crosshair, search-check
  • 关系类:share-2, users, network, link, handshake
  • 品牌类:crown, gem, award, star, badge-check
  • 流程类:workflow, route, arrow-right-left, repeat
  • 数据类:grid-2x2, bar-chart-3, trending-up, activity
  • 审美类:palette, brush, eye, sparkles
  • 对错类:check-circle, x-circle, check, x
  • 方向类:arrow-right, arrow-up-right, corner-down-right

图标与文字 inline 组合

<div class="h3-zh" style="display:flex;align-items:center;gap:.8em">
  <i data-lucide="target" class="ico-md"></i>
  判断 — 什么值得写
</div>

Ghost 巨型背景字

用作"装饰性背景字",极低透明度,营造杂志感。

<div class="ghost" style="right:-6vw;top:-8vh">BUT</div>
<div class="ghost" style="left:-8vw;bottom:-18vh;font-style:italic">Harness</div>
  • 字号 34vwopacity 0.06
  • 常用定位:right:-6vw;top:-8vh(右上超出)/ left:-8vw;bottom:-18vh(左下超出)
  • 内容:英文单词或数字(章节序号 01/02/03、关键词 BUT/NOW/HERE

注意:使用 ghost 的页面里,其他内容要加 position:relative;z-index:2 避免被压到下面。


Highlight 荧光标记

行内短语的"荧光笔"效果:

<span class="hi">不是</span>
<span class="hi">一次性爆发</span>

在文字底部生成一条半透明高亮条。深色主题用亮条浅色主题用暗条CSS 已处理)。

适合场景:只对关键 1-3 个词使用,不要大面积用。


Motion 动效系统

整套 deck 默认开启翻页入场动画,由 Motion One(vanilla 版 Framer Motion,约 4KB)驱动。

加载方式

assets/template.html 底部的 module script 会先尝试本地 assets/motion.min.js,失败则回落到 jsdelivr CDN,两者都失败则强制把所有带 data-anim 的元素设为 opacity:1—— 内容永远可读,演示不依赖网络。

// template 里的核心加载器(不用改)
let motion;
try { motion = await import('./assets/motion.min.js'); }
catch(e1) {
  try { motion = await import('https://cdn.jsdelivr.net/npm/motion@11.11.17/+esm'); }
  catch(e2) {
    document.querySelectorAll('[data-anim]').forEach(el=>{el.style.opacity='1';el.style.transform='none'});
  }
}

数据属性驱动

你只需要在 HTML 里加两种属性:

<!-- 1. 在 section 上选 recipe(可选,默认 cascade / hero 自动) -->
<section class="slide light" data-animate="quote">

<!-- 2. 在需要入场的元素上加 data-anim(可选值:left/right/line/step/divider) -->
<h1 class="h-xl" data-anim>大标题</h1>
<div class="stat-card" data-anim>...</div>
<div data-anim="left">左列内容</div>
<span data-anim="line" style="display:block">引用第一行</span>

5 种 recipe 一览

recipe 触发方式 行为 代表布局
cascade(默认) 不加 data-animate 即为此值 所有 data-anim 逐个 stagger 淡入,75ms/step Layout 3 / 4 / 5 / 10
hero .hero slide 自动用此值 慢节奏 stagger,仪式感更强,160ms/step Layout 1 / 2 / 7
quote data-animate="quote" 其他元素先出,data-anim="line" 的行 550ms 间隔逐句揭示 Layout 8
directional data-animate="directional" data-anim="left" 从左滑入 → divider → data-anim="right" 从右滑入 Layout 9
pipeline data-animate="pipeline" 翻到此页 step 保持 15% 透明;按 →/空格/滚轮逐个点亮,最后一步才放行翻页 Layout 6

给 slide 选 recipe 的决策树

  1. 它是 .hero slide 吗? → 不用加 data-animate,自动用 hero
  2. 它是大引用金句页?data-animate="quote",每句用 <span data-anim="line" style="display:block">
  3. 它是左右对比 Before/After?data-animate="directional",左列 data-anim="left"、右列 data-anim="right"
  4. 它是流水线分步讲解?data-animate="pipeline",每步 data-anim="step"
  5. 其他所有正文页 → 什么也不加,自动用 cascade

什么元素该加 data-anim?

  • 每一层有独立语义的块:kicker / h1 / h-xl / lead / callout / stat-card / figure / tag / rowline
  • 多列结构里每一列,让它们逐列淡入而不是一起
  • 不要在容器(.grid-6 / .frame)上加,只加给叶子元素
  • 不要在每个 <li> 上加,一般在 <ul> 层加就够
  • 如果某页不想要任何动画(比如过渡页),整页不加 data-anim 即可 — Motion One 只对带标记的元素生效

常见问题

  • 图片闪一下再出现? 这是预期行为,翻页中段(450ms 时)触发动画
  • Pipeline 页卡住翻不下页? 正确的,按 → 一步一步点亮 step,全部点亮后再按 → 才翻页
  • 内容静态时也不显示? 检查 motion.min.js 是否在 assets/ 下;或者浏览器控制台看错误信息