Imported from mykcs/myk-skills (
content2html/SKILL.md). Install upstream withnpx skills add mykcs/myk-skills --skill content2html. Copyright stays with the author (MIT).
content2html Skill
内容 → HTML 4 产物自动生成。Astro + Tailwind v4 + guizang Style B fork。
1. 4 产物 (按场景)
| 产物 | URL pattern | 用途 | 阅读模式 |
|---|---|---|---|
paper-slide |
/{lang}/paper/{arxiv-id}/slide/ |
学术组会 paper-reading 演讲 | 横向翻页 + 键盘导航 |
paper-summary |
/{lang}/paper/{arxiv-id}/summary/ |
异步阅读 paper 摘要 | 单栏 long-form (滚动) |
progress-slide |
/{lang}/progress/{date}/slide/ |
周报 / 工作进展演讲 | 横向翻页 + 键盘导航 |
progress-report |
/{lang}/progress/{date}/report/ |
周报 long-form 归档 | 单栏 long-form (滚动) |
2. 架构 (11 个决策 — 9 轮 grill-with-docs 收敛)
| 维度 | 决定 | ADR |
|---|---|---|
| Skill 数量 | 1 个 skill (合并 paper + progress) | — |
| Trigger | 单一 /content2html (智能 dispatch) |
ADR-0005 |
| 输入 | arxiv URL / DOI / PDF / 本地 path | — |
| 视觉 | 4 产物统一 fork guizang Style B | ADR-0004 |
| Astro | 独立 project (mykcs/content2html) |
ADR-0002 |
| 部署 | GitHub Pages → mykcs.github.io/content2html/ | — |
| i18n | 双语 (zh 默认 + en 切换) | ADR-0003 |
| 1 slide / page, 297×167mm, 1:1 slide ↔ PDF | ADR-0006 |
完整决策历史见 CASE-SKILL-CONTENT2HTML-DESIGN-20260617.md。
3. 项目结构 (独立 Astro project)
mykcs/content2html/
├── astro.config.mjs # Astro v6 + Tailwind v4 (@tailwindcss/vite)
├── package.json # tailwindcss 4.1.18 + @tailwindcss/vite
├── src/
│ ├── styles/
│ │ ├── global.css # @theme design tokens + @utility typography
│ │ ├── print.css # 独立 print template (@media print scoped)
│ │ └── README.md # styles/ 架构 + 加新元素指引
│ ├── layouts/BaseLayout.astro # 共享 header / slide nav
│ ├── components/ # SlideNav / PageNumber / Kicker / ...
│ ├── content/
│ │ └── papers/{arxiv-id}.json # paper content (zod schema)
│ └── pages/
│ ├── [lang]/
│ │ ├── paper/{arxiv-id}/ # paper-slide.html + paper-summary.html
│ │ └── progress/{date}/ # progress-slide.html + progress-report.html
│ └── 404.astro
├── scripts/
│ ├── verify-print-e2e.mjs # E2E verifier (5 layers + page count + no trailing)
│ └── diag-print.mjs # 诊断脚本 (Playwright + pdftoppm)
├── public/
│ ├── figures/{arxiv-id}/ # paper figures (git submodule or copy)
│ └── 404.html
└── .github/workflows/deploy.yml # push to main → GitHub Pages
4. 关键约定 (locked in print.css 模板)
4.1 Print template — 新加 paper 不需改 print.css
/* @media print { } — 7 sections */
@media print {
@page { size: 297mm 167mm; margin: 0; } /* §1: 1:1 slide ↔ PDF */
html, body { background: white !important; } /* §2: 去除 dark frame */
.slide-deck { display: contents !important; } /* §2: 解除 deck 约束 */
.slide-page { /* §3: 全套 sizing */
width: 297mm !important;
height: 167mm !important;
padding: 35px 40px !important;
display: grid !important;
grid-template-columns: repeat(12, 1fr) !important;
visibility: visible !important; opacity: 1 !important;
page-break-after: auto !important; break-after: auto !important;
}
.slide-page + .slide-page { /* §3b: 关键 — adjacent sibling */
page-break-before: always !important;
break-before: page !important;
}
/* §4-§7: 绝对定位装饰 + figures + per-element px + UI hide */
}
关键 fix 模式:
- ❌
.slide-page { break-after: page }→ real browser 加 trailing blank - ✅
.slide-page + .slide-page { break-before: page }→ 1:1 slide ↔ PDF - ❌
transform: scale()/zoom:在 print 管线不生效 - ✅ mm + em + px 显式缩放 (跨浏览器兼容)
4.2 Tailwind v4 directives (CSS-first config)
@import "tailwindcss";
@source "../pages/**/*.astro"; /* A.3: 显式 scan paths */
@source "../layouts/**/*.astro";
@source "../components/**/*.{astro,ts,tsx}";
@custom-variant dark (&:where(.dark, .dark *)); /* A.2: dark mode infra (CLAUDE.md 要求) */
@theme { /* 设计 token */
--color-ikb-blue: #002FA7; ... /* IKB blue, lemon yellow, ... */
--text-display: 5rem; --text-headline: 3.5rem; ... /* 字号层级 */
--print-scale: 0.5846; /* C.1: print 缩放因子 */
}
@utility text-kicker { ... } /* A.1: typography utility */
@utility text-caption { ... }
@utility text-meta-page { ... }
4.3 4-layer print page count root cause (锁定的根因)
| Layer | 症状 | 修复 |
|---|---|---|
1. transform: scale() 在 print 管线不生效 |
13 slides → 26 pages (× 2) | mm + em + px 显式缩放 |
2. rem 引用 root <html>, 非 .slide-page |
font-size 撑爆 | html { font-size: 9.37px } 让 rem 同步缩 0.585× |
3. break-after: page on all slides |
real browser trailing blank | break-before: page on adjacent siblings |
4. :last-child selector 不匹配 |
slide 13 不是 last-child | adjacent sibling + 替代 |
4.4 CSS var 命名规则 (跨 context 必须前缀)
/* ❌ 错的命名 — 跨 context 冲突 (后定义者赢) */
:root { --scale: 1; } /* screen */
@theme { --scale: 0.585; } /* print 期望值 — 被 screen :root 覆盖 */
/* ✅ 对的命名 — context 前缀 */
:root { --screen-scale: 1; } /* screen 媒体 */
@theme { --print-scale: 0.585; } /* print 媒体 */
永远加 context 前缀: --print-* (print) / --screen-* (screen) / --theme-* (cross-context tokens)。
5. E2E Verifier (5 layers)
SLIDE_COUNT=N URL=http://localhost:4321/content2html/{lang}/paper/{arxiv-id}/slide/ \
node scripts/verify-print-e2e.mjs
5 layer checks (全 PASS 必满足):
mm_based— slide width = 1122.52px (297mm @ 96 DPI)rem_scaling— html font-size = 9.37px (0.585× of 16px base)break_before— slide 2 break-before = page (adjacent sibling)no_trailing— last slide break-after = auto (无 trailing blank)takeaway_scaled—.takeaway-itemfont-size < 25px (≈ 18.74px, not 32px screen)
Page count check: pdfinfo dist.pdf should equal SLIDE_COUNT (no trailing blank in real browser).
6. 加新元素的 step-by-step
6.1 加新 paper
- 写
src/content/papers/{arxiv-id}.json(zod schema 验证) - 加 figures 到
public/figures/{arxiv-id}/(或 submodule) - 跑
npm run build(Astro 自动 detect 新 page route) - 跑
SLIDE_COUNT=N node scripts/verify-print-e2e.mjs(5/5 PASS?) git add + smart-push推送 → GitHub Pages 自动 deploy
6.2 加新 progress
类似 paper, 但 src/content/progress/{date}.json + src/pages/{lang}/progress/{date}/。
6.3 加新 design token (e.g. 新的 accent color)
src/styles/global.css@theme {}块加--color-accent-new: #...- (optional)
@utility text-accent-new包装 typography 模式 - 在 components / .astro 用
class="text-accent-new"或style="color: var(--color-accent-new)" - print 自动 follow (不需改 print.css — em 缩放机制覆盖)
6.4 加新 absolute 装饰 (e.g. 新的 logo)
- screen CSS 加
.slide-page .logo { top: 32px; left: 100px; } - print.css §4 加 override:
.slide-page .logo { top: 19px; left: 58px; }(× 0.585) - 跑 verifier 验证 page count + visibility 仍 PASS
6.5 加新 figure aspect (e.g. r-3x4)
- screen CSS 加
.frame-img.r-3x4 { aspect-ratio: 3/4; max-height: 56vh; } - print.css §5 append
.slide-page .frame-img.r-3x4到现有 frame-img 规则列表 - 跑 verifier
6.6 加 paper slide 公式 (paper-slide-template v3.3, 2026-06-23)
适用: 用户报告 "Q3 缺公式" / "公式不显示" / "想让 AS/BT/L̃ 等核心公式突出显示". 完整 SOP 见
docs/paper-slide-template.md. 5 轮反馈闭环演化见 caseCASE-PAPER-SLIDE-TEMPLATE-EVOLUTION-20260623.
5 步接入流程 (适用任何 paper):
- 写
src/content/papers/{arxiv-id}.json(基础字段: title / authors / sections / key_takeaways) - 选 1-5 个核心公式 (paper body 里识别): 如
z_t^Q ∈ {−1, 0, +1},Ψ_t ∈ [0, 1],L̃(ω; τ) := ... - paper JSON 加
key_formulas数组, shape:{ section_index, label, formula (LaTeX), context } - slide.astro 改用
<PaperSlideSection>替换手动 section (1 formula 1 slide 原则) - build + Playwright 验证 (公式渲染 = 0 errors, slide 不溢出)
关键陷阱 (踩过的 5 个硬规则):
- KaTeX
ignoredTagsoption 名: 必须ignoredTags: [...].exclude("code"), 不是ignoredElements .slide-page { overflow: hidden }必须: clamp 兜底- 链式 dict replace: placeholder 2-pass, 否则链执行链 bug
- 1 formula 1 slide: display mode (1.8rem) + body 全文 + 1 行 context
- worktree
git reset --hard不 checkout 文件: 需git checkout HEAD -- .强制 checkout
已接入 papers:
| ArXiv ID | key_formulas | 公式数 | commit |
|---|---|---|---|
| 2603.12109 | 4 (Q3.1-3.4 AS/BT/L̃/Ã_t) | 4 | 2035fd6 |
| 2606.18246 | 1 (Q2 method width fn) | 1 | 2035fd6 |
7. 验证 checklist (commit 前必跑)
# 1. E2E verifier (3 个产物 × 各自的 SLIDE_COUNT)
for n in 16 4 5; do
case $n in 16) P="zh/paper/2603.12109/slide/";; 4) P="zh/paper/2606.18246/slide/";; 5) P="zh/progress/2026-06-17/slide/";; esac
SLIDE_COUNT=$n URL=http://localhost:4321/content2html/$P node scripts/verify-print-e2e.mjs
done
# 期望: 3/3 PASS, 5/5 layers each
# 2. 9-point Astro regression
npm run build && \
ls -d dist/ && \
npx astro check && \
grep -r "astro-route-announcer" dist/ && \
grep -r "application/ld+json" dist/ && \
grep -r "navigator.serviceWorker.register" dist/ || true && \
(grep -r "@fontsource" dist/ || grep -rE "\-\-color\-" dist/_astro/*.css) && \
grep -rE 'class="[^"]*bg-[^"]*"' dist/ | head -5 && \
(test -z "$(grep -r 'is:inline' dist/ | grep -v 'third-party')" && echo OK) && \
grep -r "og:image" dist/
# 3. 5-command verification gate (CLAUDE.local.md §5.2)
git log -1 && git log --oneline -5 && git status --short && git remote -v | head -2 && gh api repos/mykcs/content2html/commits/HEAD/status
8. 已知限制 (写在 README.md / ADR-0006)
- 4 figure overflow on slide 6/10 (4-panel chart 2x2 grid, content 太长) — source layout 限制
transform: scale()/zoom:在 print 管线不生效 (CSS spec 限制) — 用 mm/em 替代- Playwright
page.pdf()不复制 trailing blank (Chromium internal API) — real browser 多 1 page - single-line HTML grep 漏数 (always use
grep -oE 'tagname[^>]*' | wc -l)
9. Quick reference — 常用命令
# 开发
cd ~/Repo/mykcs/content2html/ && npm run dev # localhost:4321
# 构建 + 部署
cd ~/Repo/mykcs/content2html/ && npm run build # dist/
# 验证 print
SLIDE_COUNT=N URL=... node scripts/verify-print-e2e.mjs
# 推 GitHub Pages
cd ~/Repo/mykcs/content2html/ && git add -A && git commit -m "..." && git push
# CI auto-deploys to https://mykcs.github.io/content2html/
# 加新 paper (arxiv-id = 1234.56789)
$EDITOR src/content/papers/1234.56789.json
cp -r figures/ public/figures/1234.56789/
npm run build && SLIDE_COUNT=N node scripts/verify-print-e2e.mjs
git add . && git commit -m "feat(paper): add 1234.56789" && git push
10. 双账号隔离铁律 (from CLAUDE.md)
- content2html 仓库是
mykcs/content2html(主账号) - 禁止 push 到
wangrui2025/*(双账号隔离 4+ 次历史污染教训) - smart-push.sh 内部 git remote 检查 + CLAUDE.local.md kill switch 自动约束
11. 相关文档
- Design 决策:
~/.claude/docs/adr/000{1,2,3,4,5}-*.md(5 个 ADR) +~/.claude/knowledge/cases/wiki/CASE-SKILL-CONTENT2HTML-DESIGN-20260617.md - Print 根因 (4-layer):
~/.claude/docs/adr/0006-content2html-print-strategy.md(4 个 Update) +~/.claude/knowledge/cases/wiki/CASE-CONTENT2HTML-PRINT-PAGE-COUNT-DVR-20260622.md - CSS var 命名 lesson:
~/.claude/knowledge/cases/wiki/CASE-CONTENT2HTML-CSS-VAR-NAMING-COLLISION-20260622.md - Verifier 强制 5-command gate:
~/.claude/CLAUDE.local.md§5.2