Skip to content

dsh-patent-number-stamp

Verified

dsh-patent-number-stamp · v1.3.0 · MIT

DSH 插件:从 PDF 文件名里提取设定范围内的字符(「涉案专利」/「D数字」/「D数字-数字」/「证据数字」/「证据数字-数字」),以正红大字标到首页页眉空白处(顶部居右,右侧被占自动左让),原地改写并默认留备份;提不到字符报错跳过;文件名出现多个不同数字时不直接加注、报错列候选,待询问用户后用 label 消歧;可选用 label 参数手写指定(与文件名不一致时回显 filenameMismatch 告警);页眉已有同一字符视为已标注不重复盖;落盘前逐像素自检。

Install

dsh plugin add dsh-patent-number-stamp

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Readme

dsh-patent-number-stamp · 专利文件序号标注

DSH 插件:从 PDF 文件名里提取设定范围内的字符,以正红大字盖到 PDF 首页页眉空白处(顶部居右),原地改写原文件。

  • 中文名:专利文件序号标注
  • 插件名(Loader id / npm 包名):dsh-patent-number-stamp
  • 注册的工具:patent_number_stamp(只有一个)
  • 注册的技能:patent-number-stamp(skills/patent-number-stamp/SKILL.md,model/user 均可调起,与同族专利插件同一套注册方式)

它做什么

D1-CN1291282A.pdf          → 首页页眉右上角盖红色「D1」
D1-2-对比文件.pdf           → 盖「D1-2」
涉案专利-固态照明装置.pdf     → 盖「涉案专利」
证据1-中文译文.pdf           → 盖「证据1」
证据6-1的中文译文.pdf        → 盖「证据6-1」
  • 顶部居右:标注右缘对齐 页宽 - rightMargin。
  • 有字自动左让:右侧被既有文字/墨迹占住时,横向往左让,直到刚好放下且不压到原字;整行放不下就往下挪一行(仍在页眉搜索深度内),全都放不下才报错。
  • 原地改写:直接写回原路径;写回前默认留一份 原名.bak-YYYYMMDD-Hhmmss.pdf 备份(backup: false 可关)。
  • 落盘前逐像素自检:页数不变、文字层能在计划位置读到该字、计划框内有足量正红像素、标注框外零差异——任一项不过就不写盘,原文件分毫不动。
  • 幂等:页眉文字层里已有同一字符时判为「已标注」,不重复盖。

文件名提取规则(lib/extract.js)

只认这五种形式,且只看文件名(不含目录名):

形式 例 提取结果
涉案专利 涉案专利-固态照明装置.pdf 涉案专利
D数字 D1-CN1291282A.pdf、d5-us2006….pdf D1、D5
D数字-数字 D1-2-对比文件.pdf D1-2
证据数字 证据1-中文译文.pdf 证据1
证据数字-数字 证据6-1的中文译文.pdf 证据6-1

细则:

  • 在文件名任意位置搜索,D 不区分大小写(d12-3 → D12-3),并归一到大写 D。
  • 长格式优先:D1-2、证据6-1 是一个整体,不会拆成 D1、证据6。- 后面不是纯数字时退回短格式(D1-对比文件.pdf → D1)。
  • 前向后顾:D 前面紧贴字母/数字时不算(USD100、MD5、2024D1 都不提取);中文、连字符、下划线之后的 D 算(图D1、-D4、D1_备份)。「证据」不受此限:前面紧贴字母/数字也算(D1证据2 会命中两者,不会吞掉 证据2)。
  • 提不到 → 报错跳过,不写任何文件。
  • 命中多个不同标注 → 不写任何文件,报错里列出全部候选(同一标注重复出现不算多命中)——调用方不要自行选择、不要直接加注,先询问用户要标哪一个(「不懂就问」),确认后用 label 参数消歧。每份文件、每次都要重新询问,不得沿用以往的选择(不同案件详情不同,选择未必相同)。

可选手动指定(label 后门)

文件名不方便改的场合(网络盘、只读目录、批量脚本)、或多数字歧义询问用户后的消歧,可以用 label 参数直接指定要标的字符:

  • 必须过同一套五形式校验(涉案专利 / D数字 / D数字-数字 / 证据数字 / 证据数字-数字,整串匹配,D 不分大小写)——后门只放宽「来路」,不放宽「合法性」;
  • 给出时优先于文件名提取;
  • 用文件名印证:一致 → 正常标;不一致(或文件名提不到)→ 照标,但结果里 filenameMismatch: true,detail 与工具输出里都会带 ⚠ 告警,点名手写值与文件名值;
  • 多命中消歧不算不一致(2026-10-23 口径):文件名同时含多个候选(如「证据6-证据1的中文译文」含 证据6、证据1)、经询问用户后选定其中之一时,文件名可印证 → filenameMismatch: false,回显带「消歧:文件名同时含:证据6、证据1,已确认标「证据6」(消歧)」(filenameNote);选定值不在候选里才算 filenameMismatch: true。
情形 结果
不给 label,文件名合规 labelSource: filename,照标
不给 label,文件名提不到 报错,不写文件
不给 label,文件名多命中 报错列候选,不写文件 → 先询问用户,再用 label 消歧
label 与文件名一致 labelSource: argument,filenameMismatch: false
label 是多命中候选之一(询问后消歧) labelSource: argument,filenameMismatch: false + filenameNote 注明消歧
label 与文件名不同 / 提不到 / 不在候选里 labelSource: argument,filenameMismatch: true + ⚠ 告警
label 形式不合法 报错,不写文件

工具

工具 作用
patent_number_stamp 从文件名提取字符(或用 label 手写指定)→ 首页页眉落笔(顶部居右 / 自动左让)→ 内存中自检 → 原地写回(默认留备份)。dryRun: true 只计划+自检、不落盘;previewPath 可把标注后首页渲成 PNG 供肉眼核验。

参数

参数 类型 说明
path string(必填) PDF 路径;相对路径按会话工作目录解析。文件名需含五种形式之一(除非用 label 指定);出现多个不同数字时不直接加注,先询问用户再用 label 指定。
label string 可选:手写指定字符(涉案专利/D数字/D数字-数字/证据数字/证据数字-数字 之一)。给出时优先于文件名;是文件名候选之一(询问后消歧)→ filenameMismatch: false + filenameNote 注明;与文件名对不上则 filenameMismatch: true + 告警。省略则完全从文件名提取。
dryRun boolean 只计划+自检,不写任何文件。默认 false。
previewPath string 可选:标注后首页渲染成 PNG 存到这里。

返回要点

label(最终所标字符)、labelSource(filename/argument)、filenameMismatch(与文件名是否对不上)、filenameLabel(文件名提取出的字符,提不到/多命中时为 null)、filenameNote(消歧备注:多命中候选清单与确认结果)、applied、alreadyStamped、movedLeft(因被占而左让的距离,0=顶部居右)、stamp.x/y(落点,渲染坐标 pt)、verified(自检明细:redPixels/outsideDiffering 等)、backupPath、font。

技能

skills/patent-number-stamp/SKILL.md 随插件一起注册(source: 'bundled',inject 为 ['tools', 'skills'],与 dsh-patent-draft-revision 等同族插件同一模式)。在 DSH 技能列表里可直接调起,内容涵盖:

  • 铁律:字符只来自文件名或用户明确给的 label(不自行发明/改写)、文件名出现多个不同数字时不直接加注、先询问用户(不懂就问)、这是原地改写需先确认、不要用 Acrobat/脚本替代(本插件带逐像素自检)、label 后门不一致必须告知用户。
  • 工作流程:先确认范围与授权 → 核对文件名能否提出字符(五种形式)→ 多数字歧义先询问用户、再用 label 消歧 → 逐个调用(建议先 dryRun 一个确认落点)→ 交付时说明落点/自检/备份/消歧。
  • 常见情形表:提不到、多数字歧义(询问消歧)、同数字重复、想指定别的字符、右侧被占、需改字号颜色分别怎么办。
  • 边界:只处理首页、/Rotate ≠ 0 与加密 PDF 报错、自检不过则整体放弃。

配置(cordis.patch.yml)

color: '#FF0000'        # 标注色(正红)
fontSize: 16            # 字号 pt;相对页眉正文明显大
topInset: 10            # 页面顶部内缩,标注行起点
rightMargin: 24         # 不避让时右缘对齐 页宽-rightMargin
leftMargin: 24          # 左让不越过它
headerZoneHeight: 64    # 页眉搜索深度(pt)
rowGap: 4               # 换行间隔
padH: 6                 # 与相邻墨迹的横向安全间隙
padV: 2                 # 纵向安全间隙
mergeGap: 4             # 墨迹游程合并阈值
fontPath: ''            # 留空自动挑单体 TTF(黑体优先);不要填 .ttc
backup: true            # 写回前留 .bak-时间戳 备份

fontPath 不能填 .ttc(TrueType 集合):pdf-lib 的 embedFont 内部只调 fontkit.create(buffer),吃不了集合。留空即可,会自动选 simhei.ttf(黑体)→ 华文宋体 → 仿宋 → 等线 → 楷体,并在缺字形时自动退让。

安装(本机 = 本地 link)

已在桌面 profile 装好:

  • C:\Users\hanch\.dsh\profiles\desktop\package.json
    • dependencies 加 "dsh-patent-number-stamp": "link:D:/Dgit/Dplugins/dsh-patent-number-stamp"
    • dsh.profile.bundles 数组里加 "dsh-patent-number-stamp"
  • node_modules\dsh-patent-number-stamp → junction 指向插件目录
  • 插件目录内 node_modules 下是逐包 junction(pdf-lib / pdfjs-dist / @pdf-lib/fontkit / @napi-rs/canvas / @deepseek-ai/schemastery),指向 profile 的 node_modules。不要换成「整个 node_modules 一条 junction」:profile 里 node_modules\dsh-patent-number-stamp 又指回本目录,会形成无限递归,任何 -Recurse 扫描都会被绕进去。
  • @deepseek-ai/dsh-tools / @deepseek-ai/dsh-skill 不建 junction:宿主由 loader 的解析钩子把它重定向到 app.asar 内部;独立 node 跑测试时用 scripts/_register-dsh-tools-stub.mjs 补桩(它会一并接管这两个模块名)。

装完重启 DSH。改代码后同样必须重启:host 进程按模块 URL 缓存已加载的插件,切换开关/重装都不会重新导入。

测试

node scripts/test-extract.mjs   # 提取规则 38 例 + label 后门决策 27 例(纯逻辑,无外部依赖)
node scripts/test-stamp.mjs     # 落笔端到端 7 组断言(合成 PDF:贴右/左让/幂等/旋转报错/dryRun/备份/错误提示)
node --import ./scripts/_register-dsh-tools-stub.mjs scripts/test-module.mjs   # 模块契约(导出/工具注册/技能注册/render content 形状/来源与不一致告警)

或一次性 npm test(等价跑齐上面三条)。

卸载

# 在 profile 目录执行
pnpm remove dsh-patent-number-stamp
# 再删掉 profile 的 cordis.patch.yml 里 id 为 patent-number-stamp 的那条,然后重启 DSH

已知边界

  • 页面 /Rotate ≠ 0 会直接报错(不做而非做错):旋转会让「顶部居右」的几何失效。先用阅读器把页面旋转拍平再标注。
  • 加密 PDF 报错,需先解密。
  • 只处理首页;页眉搜索深度默认 64pt,超出该范围的既有内容不参与避让判定(但逐像素自检仍会兜底发现误改)。
  • 原地写回前会留备份;若目标正被 PDF 阅读器占用导致写回失败,会报错并保留原文件。