Help us improve
Share bugs, ideas, or general feedback.
From tangseng
根据用户提供的 PPT 文字稿(markdown 格式),生成琥珀色机密文档风格的幻灯片网站。 当用户提供演讲/演示文字稿、PPT 内容、幻灯片大纲,或请求创建幻灯片网站时触发。 支持封面页、目录页、内容页(列表/卡片/数据/对比/时间线/引用)等多种幻灯片类型。 **风格**:深暖黑背景 + 琥珀橙强调色 + 机密文档分类条 + Space Grotesk/Archivo Black 字体。
npx claudepluginhub wukongnotnull/wk-plugin-store-private --plugin tangsengHow this skill is triggered — by the user, by Claude, or both
Slash command
/tangseng:wk-html-slides-amber-classifiedThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
根据 PPT 文字稿生成幻灯片网站。样式必须与 `index.html` 保持完全一致。
Creates p5.js generative art with seeded randomness, noise fields, and interactive parameter exploration. Use for algorithmic art, flow fields, or particle systems.
Share bugs, ideas, or general feedback.
根据 PPT 文字稿生成幻灯片网站。样式必须与 index.html 保持完全一致。
用户提供 PPT 文字稿(markdown 格式),应包含:
## 第1页:封面)生成单个 index.html 文件,包含:
html { overflow: hidden; }place-items: center:root {
--bg: #0d0b08; /* 深暖黑背景 */
--accent: #ff8c32; /* 琥珀橙主强调色 */
--accent-dark: #ff6600; /* 深橙次强调色 */
--text: #ffffff;
--text-muted: rgba(255,255,255,0.5);
--text-dim: rgba(255,255,255,0.35);
}
<link href="https://fonts.googleapis.com/css2?family=Archivo+Black&family=Space+Grotesk:wght@300;400;500;700&display=swap" rel="stylesheet">
font-family: 'Archivo Black', sans-seriffont-family: 'Space Grotesk', sans-serif<div class="classified-bar"></div>
<div class="classified-bar-bottom"></div>
<section class="slide active">
<div class="content">
<div class="left-border"></div>
<div class="doc-id">DOC-ID</div>
<div class="eyebrow">眉毛标题</div>
<h1>主标题 <span class="accent">强调词</span></h1>
<div class="divider"></div>
<!-- 内容区域 -->
</div>
</section>
.slide {
height: 100dvh;
display: none;
grid-template-rows: 1fr;
place-items: center;
padding: 2rem clamp(2rem, 8vw, 6rem);
}
.slide.active { display: grid; }
.content {
position: relative; z-index: 2;
max-width: 900px; width: 100%;
text-align: left;
padding-left: clamp(2rem, 4vw, 3rem);
}
ul > li当内容是要点列表、步骤、条目时,使用 .card > ul > li:
<div class="card">
<ul>
<li>第一点内容</li>
<li>第二点内容</li>
<li>第三点内容</li>
</ul>
</div>
.card { background: rgba(255,140,50,0.03); border: 1px solid rgba(255,140,50,0.12); border-radius: 8px; padding: clamp(1.25rem, 2.5vw, 2rem); }
.card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px; background: linear-gradient(90deg, var(--accent), var(--accent-dark), transparent); }
ul { list-style: none; }
ul li { position: relative; padding-left: clamp(1.5rem, 3vw, 2rem); margin-bottom: clamp(0.75rem, 1.5vh, 1rem); }
ul li::before { content: ''; position: absolute; left: 0; top: 0.6em; width: 8px; height: 8px; background: var(--accent); transform: rotate(45deg); }
何时使用:Q1-Q4业绩、要点清单、步骤列表、功能列表
.feature-grid > .feature-card当有多个并列的特性、功能、成就需要突出展示时:
<div class="feature-grid">
<div class="feature-card">
<span class="number">01</span>
<div class="title">特性名称</div>
<div class="desc">特性描述</div>
</div>
<div class="feature-card">
<span class="number">02</span>
<div class="title">特性名称</div>
<div class="desc">特性描述</div>
</div>
</div>
.feature-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(1rem, 2vw, 1.5rem); }
.feature-card { background: rgba(255,140,50,0.04); border: 1px solid rgba(255,140,50,0.1); border-radius: 8px; padding: clamp(1rem, 2vw, 1.5rem); position: relative; overflow: hidden; }
.feature-card .number { font-family: 'Archivo Black', sans-serif; font-size: clamp(2rem, 4vw, 3rem); color: rgba(255,140,50,0.15); position: absolute; top: -0.5rem; right: 0.5rem; }
.feature-card .title { font-family: 'Archivo Black', sans-serif; font-size: clamp(0.85rem, 1.3vw, 1rem); color: var(--accent); margin-bottom: 0.5rem; }
.feature-card .desc { font-size: clamp(0.75rem, 1.1vw, 0.9rem); color: var(--text-muted); line-height: 1.6; }
何时使用:核心功能展示、产品特性、优势对比
.data-grid > .data-card当有数值、数据、统计指标需要突出时:
<div class="data-grid">
<div class="data-card">
<div class="icon">📊</div>
<div class="value">83.1%</div>
<div class="label">漏洞利用</div>
</div>
</div>
.data-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: clamp(1rem, 2vw, 1.5rem); }
.data-card { background: rgba(255,140,50,0.05); border: 1px solid rgba(255,140,50,0.15); border-radius: 4px; padding: clamp(1rem, 2vw, 1.5rem); position: relative; }
.data-card::before { content: ''; position: absolute; top: 0; left: 0; width: 3px; height: 100%; background: var(--accent); border-radius: 4px 0 0 4px; }
.data-card .icon { font-size: clamp(1.5rem, 2.5vw, 2rem); margin-bottom: 0.75rem; }
.data-card .value { font-family: 'Archivo Black', sans-serif; font-size: clamp(1.5rem, 3vw, 2.2rem); color: var(--accent); line-height: 1; }
.data-card .label { font-size: clamp(0.7rem, 1vw, 0.85rem); color: var(--text-muted); margin-top: 0.5rem; }
何时使用:百分比、金额、用户数、增长率等量化数据
.timeline > .timeline-card当内容涉及时间顺序、阶段、历程时:
<div class="timeline">
<div class="timeline-card">
<div class="year">💰 $1亿</div>
<div class="event">事件描述</div>
</div>
</div>
.timeline { position: relative; padding-left: 2rem; }
.timeline::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: linear-gradient(to bottom, var(--accent), transparent); }
.timeline-card { position: relative; margin-bottom: clamp(0.75rem, 1.5vh, 1rem); padding: clamp(0.75rem, 1.5vw, 1rem) clamp(1rem, 2vw, 1.25rem); background: rgba(255,140,50,0.04); border: 1px solid rgba(255,140,50,0.1); border-radius: 6px; }
.timeline-card::before { content: ''; position: absolute; left: -2rem; top: 50%; transform: translateY(-50%) rotate(45deg); width: 10px; height: 10px; background: var(--accent); box-shadow: 0 0 15px rgba(255, 140, 50, 0.5); }
.timeline-card .year { font-family: 'Archivo Black', sans-serif; font-size: clamp(0.9rem, 1.3vw, 1.1rem); color: var(--accent); display: flex; align-items: center; gap: 0.5rem; }
.timeline-card .event { font-size: clamp(0.75rem, 1.1vw, 0.9rem); color: var(--text-muted); margin-top: 0.25rem; padding-left: 1.25rem; }
.stats-row > .stat当只有少量关键数字需要展示时(用于封面页等):
<div class="stats-row">
<div class="stat">
<div class="num">83.1%</div>
<div class="unit">漏洞利用</div>
</div>
</div>
.stats-row { display: flex; flex-wrap: wrap; gap: clamp(1.5rem, 4vw, 3rem); margin-top: clamp(1.5rem, 3vh, 2.5rem); }
.stat .num { font-family: 'Archivo Black', sans-serif; font-size: clamp(1.8rem, 4vw, 3rem); color: var(--accent); line-height: 1; }
.stat .unit { font-size: clamp(0.6rem, 1vw, 0.75rem); color: var(--text-dim); letter-spacing: 0.1em; text-transform: uppercase; margin-top: 0.25rem; }
.quote<div class="quote">引用内容</div>
.quote { font-size: clamp(1.1rem, 2vw, 1.4rem); color: var(--text); font-style: italic; padding-left: 1.5rem; border-left: 3px solid var(--accent); margin: clamp(1.5rem, 3vh, 2rem) 0; }
.reveal { opacity: 0; transform: translateY(30px); transition: opacity 0.6s ease, transform 0.6s ease; }
.reveal.visible { opacity: 1; transform: translateY(0); }
.reveal-delay-1 { transition-delay: 0.1s; }
.reveal-delay-2 { transition-delay: 0.2s; }
.reveal-delay-3 { transition-delay: 0.3s; }
.reveal-delay-4 { transition-delay: 0.4s; }
let currentSlide = 0;
const slides = document.querySelectorAll('.slide');
const totalSlides = slides.length;
function showSlide(index) {
if (index < 0) index = 0;
if (index >= totalSlides) index = totalSlides - 1;
slides.forEach((slide, i) => {
slide.classList.remove('active');
if (i === index) {
slide.classList.add('active');
slide.querySelectorAll('.reveal').forEach(el => {
el.classList.remove('visible');
void el.offsetWidth;
setTimeout(() => el.classList.add('visible'), 50);
});
}
});
currentSlide = index;
}
document.addEventListener('keydown', (e) => {
if (e.code === 'Space') { e.preventDefault(); showSlide(currentSlide + 1); }
if (e.code === 'ArrowRight' || e.code === 'ArrowDown') { e.preventDefault(); showSlide(currentSlide + 1); }
if (e.code === 'ArrowLeft' || e.code === 'ArrowUp') { e.preventDefault(); showSlide(currentSlide - 1); }
});
showSlide(0);
解析内容 → 判断类型 → 选择组件
1. 是要点/步骤列表吗?
→ YES: 使用 ul > li (在 .card 内)
2. 是2-4个并列特性吗?
→ YES: 使用 .feature-grid > .feature-card
3. 有具体数值/统计数据吗?
→ YES: 使用 .data-grid > .data-card
4. 涉及时间顺序吗?
→ YES: 使用 .timeline > .timeline-card
5. 是名人名言/结论吗?
→ YES: 使用 .quote
6. 只有少量关键数字(封面用)?
→ YES: 使用 .stats-row > .stat
| 错误 | 正确做法 |
|---|---|
| Q1/Q2/Q3/Q4 业绩用 feature-card | 应该用 .card > ul > li 展示列表 |
| 数字指标用 feature-card | 应该用 .data-card |
| 步骤流程用 data-card | 应该用 .card > ul > li |
忘记添加 .reveal 类 | 所有可见元素添加 .reveal 和延迟类 |
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>幻灯片标题</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Archivo+Black&family=Space+Grotesk:wght@300;400;500;700&display=swap" rel="stylesheet">
<style>
/* 所有 CSS 样式 */
</style>
</head>
<body>
<div class="classified-bar"></div>
<div class="classified-bar-bottom"></div>
<!-- 幻灯片内容 -->
<script>
/* 导航脚本 */
</script>
</body>
</html>
用户请求将幻灯片导出为图片时,使用以下脚本:
# 创建虚拟环境
python3 -m venv venv
source venv/bin/activate
# 安装 Playwright
pip install playwright
playwright install chromium
#!/usr/bin/env python3
"""将 HTML 幻灯片截图为 PNG 图片"""
import asyncio
from playwright.async_api import async_playwright
import os
import sys
# 配置
HTML_FILE = sys.argv[1] if len(sys.argv) > 1 else "index.html"
OUTPUT_DIR = sys.argv[2] if len(sys.argv) > 2 else "slides"
SCALE = int(sys.argv[3]) if len(sys.argv) > 3 else 2 # 默认2倍清晰度
async def capture_slides():
os.makedirs(OUTPUT_DIR, exist_ok=True)
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page(
viewport={"width": 1920, "height": 1080},
device_scale_factor=SCALE # 2=4K, 3=8K
)
await page.goto(f"file://{os.path.abspath(HTML_FILE)}")
await page.wait_for_timeout(1500) # 等待字体加载
slide_count = await page.locator(".slide").count()
print(f"共 {slide_count} 张幻灯片")
for i in range(slide_count):
if i > 0:
await page.keyboard.press("Space")
await page.wait_for_timeout(800) # 等待动画
filename = f"{OUTPUT_DIR}/slide-{i+1:02d}.png"
await page.screenshot(path=filename, full_page=False)
print(f"已保存: {filename}")
await browser.close()
print("完成!")
if __name__ == "__main__":
asyncio.run(capture_slides())
# 基本用法
source venv/bin/activate
python scripts/capture_slides.py index.html slides/
# 高清模式 (4K)
python scripts/capture_slides.py index.html slides/ 2
# 超高清模式 (8K)
python scripts/capture_slides.py index.html slides/ 3
slides/slide-01.png, slides/slide-02.png, ...