GreenWich-art/agent-skills

Restaure la mise en forme de documents Markdown ou DOCX existants selon les normes académiques chinoises (titres en SimHei, interlignes x1.5, tableaux à trois lignes, Times New Roman pour l'anglais, italique pour les statistiques, etc.).

Qu'est-ce que agent-skills ?

Cette compétence permet à un agent IA (comme Claude Code, Cursor ou Codex) de convertir automatiquement des rapports Markdown ou des fichiers DOCX existants en documents Word respectant les normes typographiques académiques chinoises (小三黑体 pour les titres de niveau 1, 四号黑体 pour les titres de niveau 2, 小四宋体 pour le corps du texte avec un interligne de 1.5, Times New Roman pour le texte occidental et les chiffres, italique pour les statistiques comme P, β, χ², etc.). Elle exploite directement la bibliothèque python-docx pour générer un fichier DOCX en manipulant le XML sous-jacent, évitant ainsi les limitations des API qui insèrent du contenu paragraphe par paragraphe. Elle gère des détails complexes comme les tableaux à trois lignes (bordures : 1,5 pt en haut et en bas, 1,0 pt sous l'en-tête, pas de lignes verticales), le mélange chinois/anglais (définition des quatre polices : ascii, hAnsi, eastAsia, cs), l'italique fractionné pour les symboles statistiques (sans recréer les runs), et l'espacement approprié autour des symboles mathématiques. La compétence s'applique aux universités et instituts de recherche chinois, et non aux normes gouvernementales (GB/T 9704) ou aux cours universitaires, qui ont des règles différentes. Elle peut également traiter des documents déjà modifiés par l'utilisateur en effectuant des corrections in situ sur le XML, sans régénérer l'intégralité du document.

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

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Restauration de la mise en forme DOCX pour articles académiques

Quand l'utiliser

  • Lorsque vous devez convertir un rapport Markdown ou un tableau en DOCX conforme aux normes de soumission(normes académiques chinoises)
  • Lorsque vous devez appliquer en masse la mise en forme mixte chinois/occidental, les tableaux à trois lignes et l'espacement des titres à plusieurs niveaux
  • Lorsque les API d'insertion paragraphe par paragraphe ne peuvent pas contrôler les bordures des tableaux à trois lignes, les polices au niveau du run, ou le fractionnement en italique

Conversion des tailles de police chinoises → points

TaillePoints
三号16
小三15
四号14
小四12
五号10.5

Norme par défaut (peut être remplacée selon la revue ou l'école cible) : Titre de niveau 1 en 小三 SimHei, titre de niveau 2 en 四号 SimHei, corps du texte en 小四 SimSong avec interligne 1,5, texte occidental en Times New Roman, tableaux en 五号 SimSong.

Points clés de mise en œuvre (pièges rencontrés)

1. Bordures des tableaux à trois lignes

L'unité w:sz de w:tblBorders est 1/8 de point :

  • Bordure supérieure/inférieure 1,5 pt → sz=12
  • Ligne du milieu (sous l'en-tête) 1,0 pt → sz=8
  • Les lignes verticales doivent être explicitement définies à val="none", sinon Word dessine des lignes verticales par défaut

La ligne sous l'en-tête doit être définie via row.cells[i] en utilisant w:tcBorders/w:bottom sur chaque cellule. Le simple fait de définir insideH dans tblBorders n'est pas fiable avec certains rendus.

2. cell.text = '' laisse un run vide sans formatage

Pour vider une cellule, utilisez :

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

Sinon, runs[0] sera un run vide sans rPr, ce qui entraînera une erreur lors de la vérification ultérieure des polices.

3. Le mélange chinois/occidental nécessite de définir les 4 emplacements de police

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

Omettre eastAsia → le texte chinois revient à la police par défaut.

4. L'italique doit être fractionné en runs séparés

Les statistiques (P<0,001, OR=2,17, CI, β, P) doivent être divisées en runs indépendants pour pouvoir définir l'italique séparément. L'ordre des expressions régulières est important : P值 doit être capturé avec \bP(\s*值)\b ; D'abord P\s*[<>=]\s*[\d.]+ puis le P isolé, sinon P=0,06 serait divisé en P + =0,06.

5. « Une ligne vide » = espacement de paragraphe, pas un paragraphe vide

N'utilisez JAMAIS de retour à la ligne (paragraphe vide) pour créer une « ligne vide ». Les paragraphes vides dans Word causent :

  • Des lignes supplémentaires difficiles à supprimer proprement lors de l'édition ultérieure
  • Des espaces blancs imprévisibles lors de l'impression ou de la conversion en PDF
  • Un espacement incontrôlable lorsqu'il est combiné avec l'espacement avant/après

Solution correcte — utilisez space_before / space_after (en points) :

ScénarioImplémentation
Titre de niveau 1 avec « une ligne vide avant et après »space_before = Pt(taille 小四 × 1,5), space_after = même valeur
Titre de niveau 2 avec « une ligne vide avant »space_before = Pt(taille 小四 × 1,5), space_after = Pt(0)
Titres de niveau 3 et inférieursPas d'espacement
Corps du textespace_before = Pt(0), space_after = Pt(0)
Une ligne vide entre une figure/tableau et le texteDéfinir space_before/after sur le paragraphe contenant la figure/tableau ; ne pas insérer de paragraphe vide supplémentaire

Valeurs de référence : 小四(12pt) ligne vide ≈ 18 pt ; 五号(10,5pt) ligne vide ≈ 15,75 pt.

Méthode de vérification : sum(1 for p in doc.paragraphs if not p.text.strip()) == 0 —— Un document normal ne doit contenir aucun paragraphe vide.

6. Interdiction de gras automatique

N'ajoutez JAMAIS de gras au texte, sauf demande explicite de l'utilisateur.

C'est un piège très courant : **texte** en Markdown est une marque d'emphase dans le fichier source, pas une instruction de mise en page. Le rendre en gras dans Word revient à ajouter arbitrairement une emphase au texte original.

Solution correcte :

  • **texte** → ne prendre que le contenu textuel, sans gras
  • Pour les sous-titres, utilisez un paragraphe indépendant avec la police/taille cible, ne comptez pas sur le gras pour créer une hiérarchie
  • La hiérarchie ne peut provenir que de : police (SimHei/SimKai), taille, espacement avant/après le paragraphe, numérotation

Autres interdictions : italique (sauf pour les statistiques/symboles spécifiés) ; souligné, point d'insistance, texte coloré, échelle de caractères/espacement des lettres — ne modifiez rien que l'utilisateur n'a pas demandé.

Après la conversion, effectuez une auto-vérification :

# Il ne doit y avoir aucun gras non demandé par l'utilisateur
bold = [r.text for p in doc.paragraphs for r in p.runs if r.font.bold]

Voir si l'en-tête doit être en gras dépend de la demande de l'utilisateur ; par défaut, cette compétence ne met pas l'en-tête en gras (différenciation par la taille + tableau à trois lignes).

7. Pas de ligne vide pour les titres de niveau 3 et inférieurs

Seuls les titres de niveau 1 et 2 ont un espacement avant/après ; les titres de niveau 3 et inférieurs n'ont pas d'espacement ni de gras.

Scripts

ScriptUtilité
scripts/tri_line_table.pyBordures de tableau à trois lignes (inclut verify_table_borders() pour l'auto-vérification)
scripts/fmt_lib.pyBibliothèque de fonctions pour les polices, espacement, analyse des segments en gras, styles de cellule
scripts/fix_italic.pyFractionnement de l'italique pour les statistiques (modifie sur place, sans recréer les runs)
scripts/fix_spacing2.pyCorrection de l'espacement mixte chinois/anglais et des symboles (modifie sur place, sans recréer les runs)

Dépendance : pip install python-docx

fmt_lib.parse_bold_segments(text, allow_bold=False) par défaut supprime mais ne rend pas les marques ** ; Ne transmettez allow_bold=True que si l'utilisateur demande explicitement le gras.

Ordre d'exécution pour la correction de format d'un DOCX existant (ne pas inverser) :

python3 scripts/fix_italic.py  cible.docx   # d'abord fractionner l'italique
python3 scripts/fix_spacing2.py cible.docx  # ensuite corriger l'espacement

L'inversion entraînera une recombinaison erronée des symboles fractionnés par les règles d'espacement.

Liste de vérification (à effectuer après la génération)

  1. Nombre de paragraphes vides == 0 — Priorité absolue, sum(1 for p in doc.paragraphs if not p.text.strip())
  2. Nombre de runs en gras == 0 (sauf demande de l'utilisateur) — [r.text for p in doc.paragraphs for r in p.runs if r.font.bold] doit être vide ; vérifiez aussi dans les tableaux
  3. Titre de niveau 1 sz==15 et eastAsia==SimHei, space_before==space_after==18pt
  4. Titre de niveau 2 sz==14, space_before==18pt
  5. Corps du texte sz==12, eastAsia==SimSong, line_spacing==1.5
  6. Tous les runs ascii/hAnsi==Times New Roman
  7. Nombre de runs en italique >0 et contenu = statistiques (c'est le seul format spécial autorisé)
  8. Tableau à trois lignes : utilisez verify_table_borders(table) pour chaque tableau, doit retourner (True, []) pour tous
  9. Titre du tableau : centré en 五号 SimHei, pas de ponctuation en fin de phrase
  10. Tous les runs dans les tableaux : SimSong + 10,5pt
  11. Paragraphes du corps du texte : alignment == JUSTIFY, titres et titres de tableau inchangés
  12. Espace avant le signe pourcentage : 33 % et non 33%
  13. Pas d'espace entre le symbole et le caractère chinois : 30余次 ; espace entre le symbole et le chiffre : ≥ 10 小时, P < 0,05

Script d'auto-vérification unique :

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, 'Des paragraphes vides existent'
assert not [r for x in ps for r in x.runs if r.font.bold], 'Du gras existe'
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], 'Du gras existe dans les tableaux'
for i, t in enumerate(d.tables, 1):
    good, prob = verify_table_borders(t)
    assert good, f'Tableau {i} non conforme au tableau à trois lignes : {prob}'
print('Tout est ok')

En l'absence d'environnement de vérification visuelle

Sans LibreOffice / Word pour convertir en PDF et vérifier visuellement les tableaux à trois lignes, utilisez une vérification au niveau XML (points 1 à 9 de la liste), qui couvre de manière fiable la taille, la police, les bordures et l'espacement.

Complément : Spécifications précises du tableau à trois lignes

Seulement 3 lignes :

EmplacementPointsw:sz
Ligne d'en-tête (bordure supérieure)1,512
Ligne d'en-tête (bordure inférieure)1,08
Dernière ligne (bordure inférieure)1,512
Toutes les autres bordures (y compris toutes les lignes intermédiaires, lignes verticales)Videval="none"

Clé : Ne vous contentez pas de définir insideH dans tblBorders. Les bordures au niveau du tableau peuvent être écrasées par tcBorders au niveau de la cellule ; si une cellule a un bottom, c'est le niveau de la cellule qui prime. Vous devez définir explicitement chaque cellule :

  1. Définir les six éléments de tblBorders du tableau sur none
  2. Définir d'abord tous les quatre côtés de tcBorders de toutes les lignes sur none
  3. Cellules de la ligne d'en-tête : top=('single',12) + bottom=('single',8)
  4. Cellules de la dernière ligne : bottom=('single',12)

clear_row_borders() doit être appelé sur chaque ligne, pas seulement sur l'en-tête et la dernière ligne — sinon les lignes intermédiaires conserveront des traces de lignes.

Complément : Remplacement des guillemets chinois

Les " en Markdown sont des guillemets droits ; lors de la conversion en DOCX, ils doivent être remplacés par paires par “ / ” :

dq_index = 0   # Doit compter en continu à travers les runs, ne pas recommencer à 0 pour chaque run
for r in p.runs:
    for ch in r.text:
        if ch == '"':
            out.append('“' if dq_index % 2 == 0 else '”')
            dq_index += 1

Ne modifiez que r.text, pas rPr → la police/la taille/l'italique sont tous conservés. Après le remplacement, vérifiez : Nombre total de " dans le document == 0, Nombre de “ == Nombre de ”, appariement par paragraphe (l'équilibre global ne signifie pas l'équilibre par paragraphe).

Complément : L'édition Word crée des runs fragmentés

Lorsque l'utilisateur édite manuellement dans Word, les paragraphes sont divisés en plusieurs runs, dont certains (le - extrait, un seul caractère) n'ont pas rFonts et reviennent à la police par défaut. Après avoir corrigé les guillemets/bordures, passez en revue :

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:  # → doit être complété

Complétion : Prenez le premier run du paragraphe ayant déjà une police définie comme référence, héritez de ses rFonts/sz/b.

Rappel important sur le flux de travail

Si l'utilisateur a modifié manuellement le document dans Word, ne régénérez jamais l'intégralité du document — cela écraserait les modifications de l'utilisateur. Solution correcte : Lire le DOCX existant → corriger le XML sur place → enregistrer. Avant de modifier, faites une sauvegarde : cp xxx.docx /tmp/backup.docx.

Norme pour l'italique

Critère de décision unique : Ce caractère est-il une variable ou un symbole en mathématiques/statistiques ?

CatégorieItalique ?Exemple
Signification statistique PItaliqueP = 0,04, P < 0,001
Seuil αItaliqueα = 0,05
Statistiques de test F, Z, H, χ², t, rItaliqueF = 4,52, χ² = 8,31
Lettres spéciales (gènes, valeur β de méthylation, etc.)Italiqueβ
OR, CI, RR, HR, SD, SE, AUCPas italiqueOR = 3,14, 95 % CI
Abréviations multi-lettres (BMI, OGTT, FPG…)Pas italiqueBMI, OGTT
Caractères chinoisPas italique值, 为

⚠️ Erreur la plus fréquente : « P值 » seul le P est en italique

✗ Italique 'P值'         ← '值' suit en italique
✓ Italique 'P' + romain '值'
✓ Italique 'P' + romain '值为' + ...

P 值, P值, P 值为 0,07 — seul P est en italique, les caractères chinois qui le suivent sont tous en romain.

Trois règles absolues pour le fractionnement de l'italique (apprises à la dure)

  1. Ne reconstruisez jamais les runs. L'utilisation de « runs de flux de caractères » pour corriger le formatage entraîne la perte de tout rFonts/sz/b, la suppression des bordures du tableau à trois lignes et le décalage des marques d'italique en fragments. Ne modifiez que run.text, ne supprimez/créez jamais d'éléments run.
  2. Le fractionnement doit utiliser copy.deepcopy(run._element) pour conserver tous les attributs de format ; Position d'insertion parent.insert(index+1, el) (juste à côté du run d'origine). L'utilisation d'append le déplacera à la fin du paragraphe, provoquant un ordre incorrect PP. Texte de la copie = lead + rest + trail (sans stat), texte du run d'origine = lead + stat.
  3. run.text = x n'efface pas le nœud <w:t> existant, il s'ajoute à la copie deepcopy. Vous devez d'abord el.remove(child) supprimer tous les nœuds w:t/w:br/w:tab/w:cr ; Et vous devez d'abord supprimer w:i/w:iCs avant de définir le texte ; l'ordre inverse entraînera également des erreurs.

Voir l'implémentation de référence dans scripts/fix_italic.py.

Mélange chinois/anglais et espacement des symboles

Règles de base

ScénarioRègleExemple
Chinois ↔ chiffre/lettre/ponctuationPas d'espace在30余次未校正检验的背景下, 但Table 1显示
Caractère chinois ↔ caractère chinoisPas d'espace研究目的
Entre les mots anglaisEspaceTable 1
À l'intérieur d'une expression mathématiqueEspace entre chiffre/lettre et opérateurP = 0,04, BMI < 18,5
Expression mathématique ↔ chinoisEspaceP < 0,05 为阈值

Espacement entre symbole et chiffre/lettre/chinois (facile à se tromper)

CombinaisonRègleExemple
Symbole ↔ chiffreEspace33 %, 87,3 %, P = 0,04
Symbole ↔ mot/lettre anglaisEspaceTable 1 ; α = 0,05
Symbole ↔ caractère chinoisPas d'espace30余次, ≥10小时 (symbole collé au chinois)

Piège : 30 余次 (faux, espace superflu entre symbole et chinois) vs 30余次 (correct). Les symboles d'opérateur (≥ ≤ = < >) doivent être espacés des chiffres, mais pas du caractère chinois qui les suit immédiatement.

Signe pourcentage

33 % Espace entre le chiffre et %. C'est une exigence des normes des articles scientifiques ; n'écrivez pas 33%.

Voir l'implémentation de référence dans scripts/fix_spacing2.py (inclut fix_spacing_in_run).

Alignement des paragraphes du corps du texte

Les paragraphes du corps du texte doivent être justifiés — c'est-à-dire JUSTIFY dans Word (Cmd+J / Ctrl+J), et non DISTRIBUTE.

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

Ne l'appliquez qu'aux paragraphes du corps du texte, conservez l'alignement d'origine pour les éléments suivants, ne les modifiez pas :

  • Titres de tous niveaux — généralement alignés à gauche
  • Titres de tableau — centrés
  • Cellules de tableau — selon le besoin (alignées à gauche ou centrées)

⚠️ Trois règles absolues (ordre d'exécution et vérification)

Ordre d'exécution

python3 scripts/fix_italic.py  cible.docx   # d'abord fractionner l'italique
python3 scripts/fix_spacing2.py cible.docx  # ensuite corriger l'espacement

Vérification (obligatoire, aucun point ne peut être omis)

import re
norm = lambda s: re.sub(r'\s', '', s)
# ① Aucune perte de texte — éviter les caractères supprimés/répétés
assert all(norm(a.text) == norm(b.text)
           for a, b in zip(documents_original.paragraphs, nouveau_document.paragraphs))
# ② Les runs en italique ne peuvent être que des symboles statistiques eux-mêmes (P/α/β/F/Z/H/χ/t/r), ne doivent PAS contenir :
#    - Opérateurs ou chiffres : [=<>≤≥0-9]
#    - Caractères chinois ('值' dans 'P值' doit être en romain)
#    - Abréviations comme OR/CI/RR
for p in nouveau_document.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'Italique contient opérateur/chiffre/chinois : {t!r}'
            assert t.split(' ')[0] not in ('OR','CI','RR','HR','SD','SE','AUC'), f'Abréviation ne doit pas être en italique : {t!r}'
# ③ Les paragraphes du corps du texte doivent être justifiés
from docx.enum.text import WD_ALIGN_PARAGRAPH
assert any(p.alignment == WD_ALIGN_PARAGRAPH.JUSTIFY for p in nouveau_document.paragraphs)
# ④ Guillemets chinois appariés
assert sum(p.text.count('“') for p in nouveau_document.paragraphs) == \
       sum(p.text.count('”') for p in nouveau_document.paragraphs)

⚠️ Règle absolue de la plus haute priorité (enfreindre = refaire)

  1. « Une ligne vide » ne peut être créée qu'avec un espacement de paragraphe (space_before/space_after), jamais avec un retour à la ligne/paragraphe vide.
  2. N'ajoutez JAMAIS de gras au texte, sauf si l'utilisateur l'a explicitement demandé dans ses besoins. Le **texte** de Markdown est une marque d'emphase dans le fichier source, pas une instruction de mise en page — retirez la marque, n'ajoutez pas de gras.
  3. Les formats non demandés par l'utilisateur (souligné, point d'insistance, texte coloré, espacement des lettres, échelle de caractères) ne sont jamais modifiés.
  4. Si l'utilisateur a modifié manuellement le document, interdiction de régénérer l'intégralité du document, lisez uniquement le fichier existant et modifiez le XML sur place.

La hiérarchie ne peut provenir que de la police (SimHei/SimKai), de la taille, de l'espacement avant/après le paragraphe et de la numérotation — pas du gras.

Précautions lors de la simplification du texte du corps/tableau

Lors de la simplification du contenu textuel d'un DOCX déjà modifié par l'utilisateur :

Règle absolue : fusionner l'écriture dans le premier run, vider les autres

def set_paragraph_text(p, text):
    runs = p.runs
    if not runs: return False
    runs[0].text = text          # Le format est conservé dans le premier run
    for r in runs[1:]:
        r.text = ''              # ⚠️ Doit être vidé, sinon l'ancien texte persiste et cause des répétitions
    return True

Respectez également le principe de « ne pas reconstruire les runs » — ne modifiez que run.text, ne supprimez/créez jamais <w:r>.

Localisation du tableau : par ordre de flux du document, pas avec l'index doc.paragraphs

Lorsque des tableaux sont intégrés dans des paragraphes, l'index doc.paragraphs[i] ne correspond pas à l'ordre des tableaux. Vous devez parcourir le flux du 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)))

Deux pièges lors de l'ajout/suppression de lignes

  1. table.rows analyse le XML à chaque accès — après avoir supprimé une ligne, utiliser rows[ri] provoquera un débordement. Prenez d'abord un instantané rows = list(table.rows), supprimez en commençant par la fin.
  2. La ligne clonée perd la bordure inférieure de la dernière ligne — après avoir cloné la dernière ligne pour la compléter, la ligne de base du tableau à trois lignes devient nil. À la fin, vous devez rétablir la bordure bottom (sz=12) de la dernière ligne.

⚠️ Lors de la détection des bordures, ne vérifiez pas seulement none

Dans les propres tableaux à trois lignes de Word, les lignes intermédiaires utilisent w:val="nil" et non "none". Pour déterminer « sans ligne », acceptez les deux :

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

Ne vérifier que none entraînera un faux positif « bordure endommagée », alors que la logique de détection est erronée.

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.

Skills associés