GreenWich-art/agent-skills

重整 Markdown 或 docx 的格式以符合学术论文规范(小三黑体一级标题、四号黑体二级、小四宋体正文 1.5 倍行距、三线表、中西文混排 Times New Roman、统计量斜体)。基于 python-docx 直接生成 docx,不做逐段插入。

O que é agent-skills?

该技能专为需要将 Markdown 分析报告或表格批量转换为符合学术论文投稿规范的 docx 文档而设计。它自动处理中文字号到磅值的映射、三线表边框、中西文混排时的字体设置(如 Times New Roman 和宋体)、以及统计量(如 P 值、α、F、χ²)的斜体拆分。技能基于 python-docx 库直接在 XML 层操作,避免逐段插入 API 无法控制表格边框和 run 级字体的问题。核心要点包括:使用段落间距替代空段落实现“空一行”;禁止自动加粗 Markdown 中的强调标记;严格执行三线表只有三条线的规范;以及通过字符流重组而非重建 run 的方式修改格式,以保留用户手工编辑的内容。技能同时提供了详细的校验清单和一次性自检脚本,确保生成的文档无空段落、无多余加粗、格式合规。

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/GreenWich-art/agent-skills/tree/HEAD/skills/docx-academic-format

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

学术论文 docx 格式重整

何时用

  • 需要把 Markdown 分析报告/表格转成符合投稿规范的 docx
  • 需要批量设置中西文混排、三线表、多级标题字号间距
  • 逐段插入类 API 无法控制三线表边框、run 级 rFonts、斜体拆分时,用本 skill

中文字号 → 磅值

字号磅
三号16
小三15
四号14
小四12
五号10.5

默认规范(可按目标期刊/学校要求覆盖):一级标题小三黑体、二级四号黑体、 正文小四宋体 1.5 倍行距、西文一律 Times New Roman、表格五号宋体。

关键实现要点(踩过的坑)

1. 三线表边框

w:tblBorders 的 w:sz 单位是 1/8 磅:

  • 顶/底 1.5 磅 → sz=12
  • 中间线(表头下方)1.0 磅 → sz=8
  • 竖线必须显式 val="none",否则 Word 会画默认竖线

表头下方那条线要靠 row.cells[i] 逐格设 w:tcBorders/w:bottom,只设 tblBorders 的 insideH 在某些渲染器下不可靠。

2. cell.text = '' 会留下无格式空 run

清空单元格要用:

p = cell.paragraphs[0]
for r in list(p.runs):
    r._element.getparent().remove(r._element)

否则 runs[0] 是一个无 rPr 的空 run,后续校验字体时会误判。

3. 中西文混排必须同时设 4 个字体槽位

rFonts.set(qn('w:ascii'), 'Times New Roman')
rFonts.set(qn('w:hAnsi'), 'Times New Roman')
rFonts.set(qn('w:eastAsia'), '宋体')   # 中文字体
rFonts.set(qn('w:cs'), 'Times New Roman')

漏设 eastAsia → 中文回落到默认字体。

4. 斜体要拆 run

统计量(P<0.001、OR=2.17、CI、β、P 值)必须拆成独立 run 才能单独设 italic。 正则顺序有讲究:P值 要用 \bP(\s*值)\b 整体匹配; 先匹配 P\s*[<>=]\s*[\d.]+ 再匹配孤立的 P,否则 P=0.06 会被拆成 P + =0.06。

5. 「空一行」= 段落间距,不是空段落

绝对不要用回车(空段落)实现"空一行"。 空段落会在 Word 里造成:

  • 后续编辑时多出空行、无法干净删除
  • 打印/转 PDF 时出现不确定的空白
  • 与段前段后间距叠加后间距失控

正确做法——用 space_before / space_after(单位磅):

场景实现
一级标题「上下各空一行」space_before = Pt(小四字号×1.5)、space_after = 同值
二级标题「上面空一行」space_before = Pt(小四字号×1.5)、space_after = Pt(0)
三级及以下标题不设间距
正文space_before = Pt(0)、space_after = Pt(0)
图/表与正文之间空一行在图/表所在段落上设 space_before/after,不另插空段

参考值:小四(12pt) 空一行 ≈ 18 磅;五号(10.5pt) 空一行 ≈ 15.75 磅。

校验方式:sum(1 for p in doc.paragraphs if not p.text.strip()) == 0 ——正常文档不应存在任何空段落。

6. 禁止自动加粗

任何时候都不要给文字加粗,除非用户明确要求。

这条极易踩坑:Markdown 里的 **文字** 是源文件的强调标记,不是排版指令。 把它渲染成 Word 加粗,等于擅自给原文加重点。

正确做法:

  • **文字** → 只取文字内容,不加粗
  • 需要分小标题时,用独立段落 + 目标字体/字号,不要靠加粗实现层级
  • 层级感只能来自:字体(黑体/楷体)、字号、段前段后间距、编号

同样禁止的还有:斜体除指定的统计量/符号外不要用;下划线、着重号、 彩色字、字符缩放/字间距——用户没要求的一律不动。

转换完成后应自检:

# 不应出现任何非用户要求的 bold
bold = [r.text for p in doc.paragraphs for r in p.runs if r.font.bold]

表头是否加粗看用户要求;本 skill 默认表头不加粗(靠字号+三线表区分)。

7. 三级及以下标题不空行

只有 1、2 级标题设段前段后间距;3 级及以下不加间距、不加粗。

脚本

脚本用途
scripts/tri_line_table.py三线表边框(含 verify_table_borders() 自检)
scripts/fmt_lib.py字体/间距/加粗段解析/单元格样式 工具函数库
scripts/fix_italic.py统计量斜体拆分(原地改,不重建 run)
scripts/fix_spacing2.py中英文混排与符号间距修正(原地改,不重建 run)

依赖:pip install python-docx

fmt_lib.parse_bold_segments(text, allow_bold=False) 默认丢弃但不渲染 ** 标记; 只有用户明确要求加粗时才传 allow_bold=True。

对已有 docx 做格式修正时的执行顺序(不可反序):

python3 scripts/fix_italic.py  目标.docx   # 先拆斜体
python3 scripts/fix_spacing2.py 目标.docx  # 后修间距

反序会被间距规则把已拆开的符号重新拼错。

校验清单(生成后必查)

  1. 空段落数 == 0 —— 最高优先级,sum(1 for p in doc.paragraphs if not p.text.strip())
  2. 加粗 run == 0(除非用户要求)——[r.text for p in doc.paragraphs for r in p.runs if r.font.bold] 必须为空;表格内同样检查
  3. 一级标题 sz==15 且 eastAsia==黑体,space_before==space_after==18pt
  4. 二级标题 sz==14,space_before==18pt
  5. 正文 sz==12、eastAsia==宋体、line_spacing==1.5
  6. 所有 run 的 ascii/hAnsi==Times New Roman
  7. 斜体 run 数量 >0 且内容是统计量(这是唯一允许的特殊格式)
  8. 三线表:用 verify_table_borders(table) 逐表校验,应全部返回 (True, [])
  9. 表题:五号黑体居中、句末无标点
  10. 表格内所有 run: 宋体 + 10.5pt
  11. 正文段落 alignment == JUSTIFY,标题与表题保持原样
  12. 百分号前有空格:33 % 而非 33%
  13. 符号与汉字间无空格:30余次;符号与数字间有空格:≥ 10 小时、P < 0.05

一次性自检脚本:

import sys; sys.path.insert(0, '<skill>/scripts')
from tri_line_table import verify_table_borders
from docx import Document
d = Document('out.docx'); ps = d.paragraphs
assert sum(1 for x in ps if not x.text.strip()) == 0, '存在空段落'
assert not [r for x in ps for r in x.runs if r.font.bold], '存在加粗'
assert not [r for t in d.tables for row in t.rows for c in row.cells
            for r in c.paragraphs[0].runs if r.font.bold], '表格存在加粗'
for i, t in enumerate(d.tables, 1):
    good, prob = verify_table_borders(t)
    assert good, f'表{i} 三线表不合规: {prob}'
print('全部通过')

无可视化验证环境时

没有 LibreOffice / Word 可转 PDF 目视验证三线表时, 改用 XML 层校验(清单第 1–9 项),能可靠覆盖字号、字体、边框、间距。

补充:三线表的精确规范

只有 3 条线:

位置磅值w:sz
表头行(上框线)1.512
表头行(下框线)1.08
末行(下框线)1.512
其余所有框线(含所有中间行、竖线)空val="none"

关键:不能只在 tblBorders 设 insideH。表级边框会被单元格级 tcBorders 覆盖, 一旦某单元格写了 bottom,就以单元格级为准。必须逐单元格显式设置:

  1. 表级 tblBorders 六项全设 none
  2. 所有行 tcBorders 四边先全设 none
  3. 表头行单元格:top=('single',12) + bottom=('single',8)
  4. 末行单元格:bottom=('single',12)

clear_row_borders() 要对每一行调用,不能只清表头和末行——否则中间行残留线条。

补充:中文引号替换

Markdown 里的 " 是直引号,转 docx 后必须成对替换为 “ / ”:

dq_index = 0   # 必须跨 run 连续计数,不能每个 run 从 0 开始
for r in p.runs:
    for ch in r.text:
        if ch == '"':
            out.append('“' if dq_index % 2 == 0 else '”')
            dq_index += 1

只改 r.text,不动 rPr → 字体/字号/斜体全部保留。 替换后必须验证:全文 " 计数 == 0、“ 计数 == ” 计数、逐段左右配对 (整篇平衡不代表逐段平衡)。

补充:Word 编辑会产生碎片 run

用户在 Word 里手工编辑后,段落会被拆成多个 run,其中部分(被拆出的 -、单字) 不带 rFonts,会回落到默认字体。修完引号/边框后应扫一遍:

rf = r._element.rPr.rFonts if r._element.rPr is not None else None
if rf is None or rf.get(qn('w:eastAsia')) is None:  # → 需补齐

补齐方式:取段内第一个已设定字体的 run 作参照,继承其 rFonts/sz/b。

重要工作流提醒

用户在 Word 中手工修改过文档后,绝不能重新生成整份文档——会覆盖用户改动。 正确做法:读取现有 docx → 原地定点修 XML → 保存。 修前先备份:cp xxx.docx /tmp/backup.docx。

斜体规范

唯一判定标准:该字符在数学/统计学中是否是变量或符号

类别是否斜体示例
统计学显著性 P斜体P = 0.04、P < 0.001
检验水准 α斜体α = 0.05
检验统计量 F、Z、H、χ²、t、r斜体F = 4.52、χ² = 8.31
特殊字母(基因符号、甲基化 β 值等)斜体β
OR、CI、RR、HR、SD、SE、AUC不斜体OR = 3.14、95% CI
多字母缩写(BMI、OGTT、FPG…)不斜体BMI、OGTT
中文文字不斜体值、为

⚠️ 最易错:「P值」只有 P 斜体

✗ 斜体 'P值'         ← "值" 跟着斜了
✓ 斜体 'P' + 正体 '值'
✓ 斜体 'P' + 正体 '值为' + ...

P 值、P值、P 值为 0.07 ——一律只有 P 斜体,紧跟的汉字全部正体。

斜体拆分的三条铁律(踩过血)

  1. 绝不重建 run。用"字符流重组 run"修格式会导致 rFonts/sz/b 全丢、 三线表边框被清空、斜体标记错位成碎片。只能改 run.text,绝不删/建 run 元素。
  2. 拆分必须用 copy.deepcopy(run._element) 保留全部格式属性; 插入位置 parent.insert(index+1, el)(紧邻原 run)。用 append 会跑到段末、 顺序错乱出现 PP。 副本文本 = lead + rest + trail(不含 stat),原 run 文本 = lead + stat。
  3. run.text = x 不会清空已有 <w:t> 节点,在 deepcopy 副本上会追加。 必须先 el.remove(child) 删掉所有 w:t/w:br/w:tab/w:cr; 且要先移除 w:i/w:iCs 再设文本,顺序反了也会错。

参考实现见 scripts/fix_italic.py。

中英文混排与符号间距

基本规则

场景规则示例
中文 ↔ 数字/字母/标点不加空格在30余次未校正检验的背景下、但Table 1显示
汉字 ↔ 汉字不加空格研究目的
英文单词之间加空格Table 1
数学表达式内部字母/数字 与 运算符 之间加空格P = 0.04、BMI < 18.5
数学表达式 ↔ 中文加空格P < 0.05 为阈值

符号与数字/字母/汉字的间距(易错)

组合规则示例
符号 ↔ 数字加空格33 %、87.3 %、P = 0.04
符号 ↔ 英文单词/字母加空格Table 1;α = 0.05
符号 ↔ 汉字不加空格30余次、≥10小时(符号紧贴汉字)

易错点:30 余次(错,符号与汉字间多空格) vs 30余次(对)。 运算符类符号(≥ ≤ = < >)与数字之间要空格,但符号与紧随的汉字之间不补空格。

百分号

33 % 数字与 % 之间加空格。这是科技论文规范的要求,不要写成 33%。

参考实现见 scripts/fix_spacing2.py(含 fix_spacing_in_run)。

正文段落对齐

正文段落用两端对齐——即 Word 的 JUSTIFY(Cmd+J / Ctrl+J), 注意不是 DISTRIBUTE。

from docx.enum.text import WD_ALIGN_PARAGRAPH
p.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY

只应用到正文段落,以下保持各自原有对齐,不要改动:

  • 各级标题——通常左对齐
  • 表题——居中
  • 表格内单元格——按需(左对齐或居中)

⚠️ 三条铁律(执行顺序与校验)

执行顺序

python3 scripts/fix_italic.py  目标.docx   # 先拆斜体
python3 scripts/fix_spacing2.py 目标.docx  # 后修间距

校验(必做,缺一不可)

import re
norm = lambda s: re.sub(r'\s', '', s)
# ① 文字零丢失——防吞字/重复字
assert all(norm(a.text) == norm(b.text)
           for a, b in zip(原文档.paragraphs, 新文档.paragraphs))
# ② 斜体 run 只能是统计符号本身(P/α/β/F/Z/H/χ/t/r),不得含:
#    - 运算符或数字:[=<>≤≥0-9]
#    - 汉字('P值' 的 '值' 必须是正体)
#    - OR/CI/RR 等缩写
for p in 新文档.paragraphs:
    for r in p.runs:
        if r.font.italic and r.text.strip():
            t = r.text.strip()
            assert not re.search(r'[=<>≤≥0-9\u4e00-\u9fff]', t), f'斜体含运算符/数字/汉字: {t!r}'
            assert t.split(' ')[0] not in ('OR','CI','RR','HR','SD','SE','AUC'), f'缩写不应斜体: {t!r}'
# ③ 正文段落必须两端对齐
from docx.enum.text import WD_ALIGN_PARAGRAPH
assert any(p.alignment == WD_ALIGN_PARAGRAPH.JUSTIFY for p in 新文档.paragraphs)
# ④ 中文引号成对
assert sum(p.text.count('“') for p in 新文档.paragraphs) == \
       sum(p.text.count('”') for p in 新文档.paragraphs)

⚠️ 最高优先级铁律(违反即返工)

  1. 「空一行」只能用段落间距(space_before/space_after),绝不能用回车/空段落。
  2. 任何时候都不要给文字加粗,除非用户在需求里明确说了要加粗。 Markdown 的 **文字** 是源文件的强调记号,不是排版指令——只去标记、不加粗。
  3. 用户没要求的格式(下划线、着重号、彩色字、字间距、字符缩放)一律不动。
  4. 用户手工改过文档后,禁止重新生成整份文档,只能读现有文件原地改 XML。

层级感只能来自字体(黑体/楷体)、字号、段前段后间距、编号——不是加粗。

精简正文/表格文字时的注意事项

在用户已修改的 docx 上精简文字内容时:

铁律:合并写入第一个 run,其余置空

def set_paragraph_text(p, text):
    runs = p.runs
    if not runs: return False
    runs[0].text = text          # 格式保留在第一个 run
    for r in runs[1:]:
        r.text = ''              # ⚠️ 必须置空,否则残留旧文字造成重复
    return True

同样遵守「不重建 run」原则——只改 run.text,绝不删/建 <w:r>。

定位表格:按文档流顺序,不能用 doc.paragraphs 索引

段落里嵌着表格时,doc.paragraphs[i] 的序号与表格不对应。必须走 body 流:

from docx.table import Table
from docx.text.paragraph import Paragraph
W = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
seq = []
for c in doc.element.body.iterchildren():
    if c.tag == W+'p':   seq.append(('p', Paragraph(c, doc)))
    elif c.tag == W+'tbl': seq.append(('t', Table(c, doc)))

增删行的两个坑

  1. table.rows 每次访问都重新解析 XML —— 删行后再用 rows[ri] 会越界。 先 rows = list(table.rows) 快照,从后往前删。
  2. 克隆出来的行会丢末行下框线 —— 克隆末行补齐后,三线表的底线会变成 nil。 收尾必须重新补末行 bottom 边框(sz=12)。

⚠️ 检测边框时不要只认 none

Word 自己的三线表,中间行写的是 w:val="nil" 而非 "none"。 判定"无线"要同时接受两者:

assert tv in ('nil','none') and bv in ('nil','none')

只认 none 会误报"边框损坏",实际是检测逻辑错。

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

GreenWich-art/agent-skills

桌面 GUI 操作的统一编排入口。当用户要求操作一个只有图形界面的应用(改设置、点按钮、填表单、操作无 CLI/连接器的软件)时使用此 skill。提供四级能力:①路由决策——判断任务该走连接器、浏览器控制、Office 技能、命令行还是 computer use 桌面接管;②授权引导——检测并引导用户完成 macOS 辅助功能/屏幕录制权限授权,处理授权不生效等常见坑;③任务派发与验证——按目标/边界/失败处理三段式描述派发 GUI 任务,并以最终截图为准确认结果;④AX 兜底层——内置 axctl 工具做元素级无障碍读写(AXPress 语义点击,不碰鼠标不抢焦点),适用于 computer use 不可用或轻量场景。台前调度全场景实测(macOS 15 + 27.0.1 复检)。触发词:操控电脑、操作某个软件、点某个按钮、GUI 操作、电脑设置。

GreenWich-art/agent-skills

参考文献的 GB/T 7714-2015 著录规范化,以及 URL / DOI / PMID / PMC 链接的 可访问性批量核验与"假失效"识别。 触发场景: - 论文 / 综述 / 作业要交,需要核对参考文献格式 - "帮我按国标改一下参考文献" - 要交付一份文献清单,需要确认链接没死 - 已经有一堆 links,要批量验证哪些还能打开 含一个可复用脚本 `scripts/check_refs.py`,能自动判别 URL / DOI / PMID / PMC 并并发核验,且能区分「真死」与「被反爬」——后者不该判为失效。 不适用:从零生成一份带引文的正文(那是写作任务); Zotero 样式定制(见正文第六节,按需手工改 CSL)。

GreenWich-art/agent-skills

Local OCR using the macOS Vision framework. Triggers: OCR, 识别图片文字, 提取截图内容, 扫描件转文字, 图片转文字, 扫描版PDF转文字, read text from image/screenshot/photo/scanned PDF. Local-first and offline; prefer it over cloud OCR whenever data is sensitive or the machine is offline.

GreenWich-art/agent-skills

Download open-access biomedical article PDFs from PMC with offline Proof-of-Work solving. Triggers: 下载文献PDF, PMC PDF, 403/404 on PDF link, Preparing to download, reCAPTCHA page, OA full text, supplementary files, download paper PDF.

Habilidades Relacionadas