关于 glmv-pdf-to-web
glmv-pdf-to-web 是将论文或技术文档 PDF 转为单页学术项目网站的技能。它在本地转换页面、规划网站章节、裁剪选定图像,并生成引用本地图像的 HTML。
主要功能
- 01将 PDF 页面转换为图像
- 02创建结构化网站大纲
- 03裁剪本地页面中的图像
- 04生成单页 HTML 网站
- 05使用本地图像素材
适用场景
- 01为研究论文创建项目主页
- 02将技术 PDF 转成网站
- 03在线展示论文图表与结果
- 04根据本地或链接 PDF 制作学术页面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zai-org/ glm-skills --skill glmv-pdf-to-web安装后在 Claude Code 中输入/glmv-pdf-to-web确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.DS_Storescripts/crop.pygenerate_web.pypdf_to_images.py详细介绍
PDF → 学术项目网站技能
将研究论文或技术文档 PDF 转换为精美的单页项目网站——类似于 NeurIPS/CVPR/ICLR 论文发布时使用的网站。页面以 120 DPI 在本地转换,保存结构化的 outline.json,在本地裁剪图像,并使用 generate_web.py 保存最终页面。
脚本位于: {SKILL_DIR}/scripts/
依赖项
Python 软件包(安装一次即可):
pip install pymupdf pillow
系统工具:curl(macOS/Linux 已预装)。
使用时机
当用户要求根据 PDF 创建网页或项目页面时触发——例如: “make a project page from a PDF”、“create a paper website”、“build an academic website for this paper”、“论文主页”、“做项目主页”、“根据pdf做网页”、“把论文做成主页”,或任何类似的中文或英文意图。
输出目录约定
所有输出均放在 {WORKSPACE}/web/<pdf_stem>_<timestamp>/ 下:
web/
└── <pdf_stem>_<timestamp>/
├── outline.json ← structured web plan (WebPlan schema)
├── crops/ ← locally-saved cropped images
│ ├── fig_arch_crop.png
│ ├── table_results_crop.png
│ └── ...
└── index.html ← the website
<pdf_stem>= 不含扩展名的 PDF 文件名<timestamp>= 格式为YYYYMMDD_HHMMSS- HTML 通过相对路径
crops/<name>_crop.png引用图像
输入
$ARGUMENTS 是 PDF 文件的路径(本地路径)或 HTTP/HTTPS URL。
- 如果用户提供 URL:先使用 curl 下载,再转换
- 如果用户提供 本地 PDF 路径:直接转换
工作流
阶段 0 — 创建输出目录
import os, datetime
pdf_stem = os.path.splitext(os.path.basename(pdf_path))[0]
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
out_dir = os.path.join(workspace, "web", f"{pdf_stem}_{timestamp}")
mkdir -p "<out_dir>/crops"
阶段 1 — 将 PDF 页面转换为图像(120 DPI)
如果输入是 URL,先下载:
pdf_stem=$(basename "$ARGUMENTS" .pdf)
curl -L -o "/tmp/${pdf_stem}.pdf" "$ARGUMENTS"
然后转换(传入下载后的路径或原始本地路径):
python {SKILL_DIR}/scripts/pdf_to_images.py "<pdf_path>" --dpi 120
将 JSON 输出到标准输出:
[{"page": 1, "path": "/abs/path/page_001.png"}, ...]
解析并保存完整的 page → path 映射。
阶段 2 — 按顺序阅读所有页面
在规划之前,依次查看所有页面图像。目标是全面理解文档的内容、图表和结构。
阅读时,记录:
- 标题、作者、所属机构、会议或期刊、年份
- 摘要文本(逐字)
- 主要贡献
- 论文/代码/数据集链接(arXiv、GitHub 等)
- 图、表、示意图——所在页码及大致区域
- 如果有预览图/主视觉图,记录下来
暂时不要规划章节——先阅读全部内容。
阶段 3 — 规划章节并保存 outline.json
规划网站章节。学术论文的标准结构如下(可按需调整):
section_id | 用途 |
|---|---|
hero | 标题、作者、会议或期刊徽章、链接按钮 |
abstract | 完整摘要文本 |
contributions | 3–5 个主要贡献卡片 |
method | 架构图 + 方法说明 |
results | 定量表格 + 定性图表 |
conclusion | 简要结论 |
citation | BibTeX 内容块 |
对于每个需要图像的章节,请确定:
- 图像来自哪一页(阶段 1 中的本地页面路径)
- 对视觉内容的描述,以及它为何适合该章节
将文件保存为 <out_dir>/outline.json,并严格使用以下架构:
{
"project_title": "Paper Title",
"lang": "English",
"authors": ["Author One", "Author Two"],
"sections_plan": [
{
"section_index": 1,
"section_id": "hero",
"title": "Hero",
"content": "Title, authors, venue, teaser figure description",
"required_images": [
{
"url": "<local_page_path_from_phase1>",
"visual_description": "Figure 1: teaser showing input-output examples",
"usage_reason": "Hero section visual to immediately show the paper's output"
}
]
}
]
}
字段说明:
lang:"Chinese"或"English"——与 PDF 语言保持一致required_images:如果章节不需要图像,则为空数组[]url:源页面的本地文件路径(来自阶段 1 的path字段)- 对于需要裁剪的图像,注明大致区域——精确裁剪框将在阶段 4 确定
使用 Write 工具将 outline.json 写入 <out_dir>/outline.json。
阶段 4 — 裁剪所需图像(定位 + 子 Agent)
重要:你必须使用 Agent 工具,将所有裁剪工作委托给一个全新的子 Agent。 到此阶段,你的上下文已经很长(包含所有页面图像和大纲),这会降低视觉坐标的准确性。只接收目标图像的全新子 Agent 能生成精确得多的坐标。
重要:你必须使用提供的 {SKILL_DIR}/scripts/crop.py 脚本裁剪所有图像。切勿编写自己的裁剪代码、直接使用 PIL/Pillow,或采用任何其他方法。
读取 outline.json。收集所有需要裁剪的内容,然后针对每个源页面启动一个子 Agent(如果页面不同,也可以每个裁剪启动一个子 Agent)。子 Agent 使用定位式定位方法——查看图像、找到目标元素,并以归一化的 0–999 坐标输出精确边界框。
像这样使用 Agent 工具:
Agent tool call:
description: "Grounding crop page N"
prompt: |
You are a visual grounding and cropping assistant. Your task is to precisely
locate specified visual elements in a page image and crop them out.
## Grounding method
Use visual grounding to locate each target:
1. Read the source image using the Read tool to view it
2. Identify the target element described below
3. Determine its bounding box as normalized coordinates in the 0–999 range:
- 0 = left/top edge of the image
- 999 = right/bottom edge of the image
- These are thousandths, NOT pixels, NOT percentages (0–100)
- Format: [x1, y1, x2, y2] where (x1,y1) is top-left, (x2,y2) is bottom-right
- Example: [0, 0, 500, 500] = top-left quarter of the image
4. Be precise: tightly bound the target element with a small margin (~10–20 units)
around it. Do NOT crop too wide or too narrow.
## Source image
<page_image_path>
## Crops needed
For each crop below, first do grounding (locate the element), then crop:
1. Name: "<descriptive_name>"
Target: "<visual_description from outline.json>"
Context: "<usage_reason from outline.json>"
## Crop command
After determining the bounding box [X1, Y1, X2, Y2] for each target, run:
```bash
python <SKILL_DIR>/scripts/crop.py \
--path "<page_image_path>" \
--box X1 Y1 X2 Y2 \
--name "<crop_name>" \
--out-dir "<out_dir>/crops"
```
## Verification
After each crop, READ the output image to visually verify the correct region
was captured. If the crop missed the target or is too wide/narrow, adjust the
coordinates and re-run crop.py.
## Output
Report the final results as a list:
- crop_name: <name>, file: <output_filename>, box: [X1, Y1, X2, Y2]
将 <page_image_path>、<SKILL_DIR>、<out_dir> 和裁剪详情替换为上下文中的实际值。
crop.py 脚本会输出 JSON:{"path": "/abs/path/<name>_crop.png"}
收集所有子 Agent 的结果,并建立映射:section_id → [crop filename, ...],以便在 HTML 中引用。
尽可能并行启动处理不同页面的子 Agent。 等待所有任务完成后再继续。
阶段 5 — 测量裁剪图像尺寸
python3 -c "
from PIL import Image; import os, json
d = '<out_dir>/crops'
sizes = {}
for f in sorted(os.listdir(d)):
if f.endswith('.png'):
w, h = Image.open(os.path.join(d, f)).size
sizes[f] = {'width': w, 'height': h, 'aspect': round(w/h, 2)}
print(json.dumps(sizes, indent=2))
"
| 宽高比 | 布局建议 |
|---|---|
| < 0.7(高而窄) | max-width: 400–500px,居中 |
| 0.7 – 1.3(接近正方形) | max-width: 600–700px |
| > 1.3(较宽) | 全宽,max-width: 100% |
| > 2.0(很宽,例如表格) | 全宽,并提供水平滚动作为备用方案 |
阶段 6 — 生成单页 HTML
步骤 A — 编写 HTML 到 /tmp/website.html
- 所有
<img src="...">都必须使用相对路径:crops/<name>_crop.png - 切勿使用绝对路径
步骤 B — 保存:
python {SKILL_DIR}/scripts/generate_web.py \
--html-file /tmp/website.html \
--title "<paper title>" \
--out-dir "<out_dir>/"
HTML 规范
一个自包含的单个 HTML 文件——内嵌 CSS,仅使用最精简的原生 JS。不使用外部 JS 框架。可以使用 Google Fonts CDN。
页面布局:
- 内容最大宽度:
900px,居中,侧边留出舒适的内边距 - 顶部导航栏固定,包含各章节的锚点链接,并支持平滑滚动
- 在 1200px 宽度下显示效果良好;在 768px 下易于阅读
排版:
- 使用两种 Google Fonts:一种用于标题,一种用于正文和 UI
- 正文:17–18px,行高 1.7
- 标题层级清晰(h1 >> h2 >> h3)
视觉风格:
- 如果用户指定了风格,请严格遵循
- 否则,根据论文的领域和语气推断合适的美学风格(例如,CV/ML 论文采用现代简洁的学术风格;系统论文采用深色技术风格;人文类论文采用温暖的编辑风格,并使用衬线字体)
- 将颜色和字体定义为 CSS 变量;无需固定调色板或字体选择
章节指南:
hero:
- 大标题(2–3rem),作者列表附带上标形式的单位标注,以及胶囊样式的会议徽标
- 链接按钮:
[📄 Paper] [💻 Code] [🗄️ Dataset]——无 URL 时显示为灰色 - 下方放置引导图(如有)
abstract:
- 原文文本,配以低调的左侧边框强调
contributions:
- 使用 2–3 列 CSS 网格布局的卡片,每张卡片包含一个 Unicode 符号、标题和说明
method:
- 全宽架构图(
<figure><img><figcaption>)+ 文字说明
results:
- 定量表格使用真正的
<table>——采用 PDF 中的实际数字,并将最佳数字加粗 - 定性图像以网格布局展示(2–4 张图像,附带说明)
conclusion:
- 2–3 段
citation:
- 使用从 PDF 元数据重建的 BibTeX,放在
<pre><code>区块中 - 使用
navigator.clipboard原生 JS 实现“复制”按钮
图像:
- 所有
<img>都使用相对路径:crops/<name>_crop.png - 添加
loading="lazy"和描述性alt - 使用
<figure>包裹,并添加<figcaption>
动画(仅限微妙效果):
- 通过
IntersectionObserver和 CSS transitions 实现滚动淡入效果 - 为按钮和卡片添加悬停状态
质量检查清单
- 输出目录命名为
<pdf_stem>_<timestamp>/ -
outline.json已保存,且符合有效的 WebPlan 架构 - 所有裁剪图均已保存到
crops/(仅本地) - 所有元数据(标题、作者、出版物、年份)均来自 PDF
- 摘要为原文
- 定量表格中的数字均来自论文
- 所有裁剪图像均通过
crops/<name>_crop.png引用 - BibTeX 区块准确且可复制
- 导航锚点可滚动到正确的章节
- 已调用
generate_web.py并确认成功
语言
与 PDF 语言保持一致。英文论文 → 英文网站。中文论文 → 中文网站。不要混用。