Publish Substack Article 是一个把 Markdown 文章发布到 Substack 草稿箱的技能,属于 sugarforever/01coder-agent-skills 集合。它的核心目标是将 Markdown 内容送入 Substack 的文章编辑器,转换为 HTML 后以富文本形式粘贴,并保存为草稿,等待用户自行预览后再手动发布。
【用途】 当用户希望把某个 Markdown 文件发布到 Substack,或提到“发布到 Substack”“Substack article”等需求时使用。技能本身只负责创建和填充草稿,不代替用户执行正式发布。
【前置条件】 需要满足以下条件:
- 浏览器自动化 MCP,二选一:Chrome DevTools MCP(mcp__chrome-devtools__)或 Playwright MCP(mcp__playwright__)。
- 用户已登录 Substack。
- 安装 Python 3 及 markdown 包(pip install markdown)。
- copy_to_clipboard.py 脚本(来自 publish-zsxq-article 技能共享)。
【浏览器 MCP 工具映射与优先级】 技能同时兼容两套 MCP,并给出对应动作映射:导航(Chrome DevTools MCP 为 navigate_page,Playwright MCP 为 browser_navigate)、快照(take_snapshot / browser_snapshot)、截图(take_screenshot / browser_take_screenshot)、点击(click / browser_click)、填入文本(fill / browser_type)、上传文件(upload_file / browser_file_upload)、按键(press_key / browser_press_key)、执行 JS(evaluate_script / browser_evaluate)。优先级为默认使用 Playwright MCP,仅在其不可用时改用 Chrome DevTools MCP;运行时优先尝试 mcp__playwright__browser_navigate,只有在 Playwright 工具不可用时才回退到 mcp__chrome-devtools__navigate_page。
【关键 URL】 Substack 仪表盘:https://{publication}.substack.com/publish;文章编辑器:https://{publication}.substack.com/publish/post/{postId}。
【Publication 解析】 导航前必须解析 Substack 出版物子域名(例如 verysmallwoods.substack.com 中的 verysmallwoods),不得硬编码默认值。解析顺序为:技能参数、环境变量 SUBSTACK_PUBLICATION(可选,供重复向同一出版物发布的用户使用)、若两者都不可用则提示用户提供。未解析出子域名前不得进入导航步骤。
【编辑器界面】 Substack 文章编辑器使用基于 ProseMirror 的 Tiptap WYSIWYG 编辑器。关键元素包括:标题输入框 textbox "title"(占位符 Title)、副标题输入框 textbox "Add a subtitle…"、内容区域 .ProseMirror(Tiptap 编辑器,提示 Start writing...)、保存状态按钮 "Saved"(自动保存)、预览按钮 "Preview"、继续按钮 "Continue"(属于发布流程,禁止使用)、设置侧栏按钮 "Settings"。设置侧栏打开时包含标题输入框 "Add a title..."、描述输入框 "Add a description..."、缩略图上传按钮(3:2 比例)。工具栏包含加粗、斜体、删除线、代码、链接、图片、音频、视频、引用、列表(无序/有序)、按钮、更多(代码块、分隔线、脚注、LaTeX 等)。
【内容插入方式(关键)】 必须使用带 HTML 内容的剪贴板粘贴,而不是直接 fill 或粘贴纯 Markdown。Tiptap 编辑器原生处理 HTML 粘贴并渲染为富文本。流程为:用 Python markdown 库把 Markdown 转为 HTML;用 copy_to_clipboard.py html 把 HTML 复制到系统剪贴板;聚焦编辑器内容区域;按 Cmd+V(macOS)或 Ctrl+V(Windows/Linux)粘贴。原因:fill 工具会把内容当纯文本,无格式;纯 Markdown 粘贴时 Tiptap 不会解析 Markdown;只有 HTML 粘贴能让 Tiptap 渲染为富内容(标题、代码块、链接、加粗等)。已知限制:Substack 编辑器不支持 HTML 表格,表格会被折叠为纯文本。
【主要工作流程】 第 0 步:预处理——将表格转为图片。Substack 不渲染 HTML 表格。需检测 Markdown 中的表格(由 | 构成的行),用 diagram-to-image 技能把每个表格转为 PNG(例如 node ~/.claude/skills/diagram-to-image/scripts/diagram-to-image.mjs /tmp/table1.md -o /tmp/table1.png),记录每个表格在文章中的位置(位于哪个标题/段落之后),并在 HTML 转换前从内容中移除表格 Markdown。图片上传在粘贴正文后于第 7 步进行。 第 1 步:准备内容。读取 Markdown 文件并提取标题(来自 YAML frontmatter 的 title 字段、或 H1 标题、或文件名)、副标题(来自 frontmatter 的 excerpt 或 description 字段)、正文(去掉 YAML frontmatter 和交叉引用链接)。 第 2 步:Markdown 转 HTML。使用 Python markdown 库并启用 tables 与 fenced_code 扩展。示例代码:import markdown 与 import re;读取文件后,用 re.sub 去掉 YAML frontmatter,去掉交叉引用链接,执行 markdown.markdown(content, extensions=['tables', 'fenced_code']),写入 /tmp/substack_article.html。注意不要使用 nl2br 扩展,因为它会把单个换行转成 <br>,导致编辑器出现多余换行。 第 3 步:导航到 Substack。前往 https://{publication}.substack.com/publish;若未登录则提示用户先登录。 第 4 步:创建新文章。在侧栏点击 "Create new",选择 "Text post"(或直接进入新文章 URL);若编辑器已打开且为空,可直接继续。 第 5 步:填写标题和副标题。点击标题输入框并输入标题,点击副标题输入框并输入副标题。 第 6 步:插入 HTML 内容(剪贴板粘贴)。不要用 fill 工具。执行 python3 /path/to/copy_to_clipboard.py html --file /tmp/substack_article.html,点击编辑器内容区域(.ProseMirror 或其内部段落),按 Cmd+V(press_key: Meta+v,macOS)或 Control+v(Windows/Linux),触发 Tiptap 的 HTML 粘贴处理。 第 7 步:插入表格图片。定位到表格应出现的位置,点击图片工具栏按钮 "Image",在下拉菜单中点击 "Image" 菜单项,通过文件选择器上传图片(Playwright MCP 用 browser_file_upload,Chrome DevTools MCP 用 upload_file)。注意:Playwright MCP 只允许从允许的根目录(项目目录)上传文件,若图片在 /tmp/ 需先复制到项目目录;每个表格重复此操作;若表格内容已被粘贴为纯文本,需全选该段落删除后再插入图片。 第 8 步:验证草稿。检查 "Saved" 状态指示(绿点 + Saved 文本),拍摄快照验证内容结构,可选截图做可视化验证。编辑器自动保存,无需显式保存。 第 9 步:报告完成。提示“草稿已保存到 Substack。请在 Substack 中预览并手动发布。”并给出文章 URL:https://{publication}.substack.com/publish/post/{postId}。
【关键规则】 绝不点击 "Continue"(会启动发布流程),只保存为草稿(自动保存负责)。必须先把内容转换为 HTML,纯 Markdown 不会被 Tiptap 解析。使用剪贴板粘贴,这是插入带格式内容的唯一可靠方式。检查登录状态,必要时提示用户登录。保留原始文件,绝不修改源 Markdown。完成后告知用户草稿已保存、需人工审阅。不要使用 nl2br 扩展。表格先转图片再粘贴内容、粘贴后上传图片。Playwright 文件路径受允许根目录限制。先解析 publication,绝不硬编码子域名。优先使用 Playwright MCP。
【故障排查】 内容显示为纯文本(无格式):原因是使用了 fill 工具而非剪贴板粘贴,解决方法是改用 copy_to_clipboard.py + Cmd+V。表格不渲染(显示为纯文本):Tiptap 不支持 HTML 表格,解决方法是先用 diagram-to-image 技能把表格转为 PNG 再作为图片上传(简易表格可改为列表),若已粘贴为纯文本可三击选中该段落后按 Backspace 删除再插入图片。需要登录:页面出现登录提示时,请用户先登录 Substack 并告知。编辑器未加载:等待页面完全加载、重新拍摄快照,必要时刷新。剪贴板复制失败:确保依赖 pip install pyobjc-framework-Cocoa(macOS),检查 HTML 文件存在且可读,可先复制较小测试字符串。
【支持与不支持的格式】 经 HTML 转换和粘贴后可正确渲染的元素包括:H2-H6 标题(不推荐 H1,标题单独存在)、加粗/斜体、行内代码、代码块(语法高亮可能因情况而异)、链接、引用、无序列表、有序列表、分隔线。表格在 Substack 中不受支持,需转为图片;图片需手动通过 Image 工具栏按钮的文件选择器上传。