mcpField
G
glmv-pdf-to-web

glmv-pdf-to-web

github.com/zai-org设计与 UI47538 次安装28 周前更新
代码仓库

关于 glmv-pdf-to-web

glmv-pdf-to-web 是将论文或技术文档 PDF 转为单页学术项目网站的技能。它在本地转换页面、规划网站章节、裁剪选定图像,并生成引用本地图像的 HTML。

主要功能

  1. 01将 PDF 页面转换为图像
  2. 02创建结构化网站大纲
  3. 03裁剪本地页面中的图像
  4. 04生成单页 HTML 网站
  5. 05使用本地图像素材

适用场景

  1. 01为研究论文创建项目主页
  2. 02将技术 PDF 转成网站
  3. 03在线展示论文图表与结果
  4. 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_Store
scripts/
crop.py
generate_web.py
pdf_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完整摘要文本
contributions3–5 个主要贡献卡片
method架构图 + 方法说明
results定量表格 + 定性图表
conclusion简要结论
citationBibTeX 内容块

对于每个需要图像的章节,请确定:

  • 图像来自哪一页(阶段 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 语言保持一致。英文论文 → 英文网站。中文论文 → 中文网站。不要混用。

评论

支持 Markdown