{"slug":"wshuyi-x-article-publisher-9a5929","title":"Markdown\u53d1\u5e03\u5230X Articles","description":"\u5c06Markdown\u6587\u7ae0\u89e3\u6790\u4e3a\u5bcc\u6587\u672c\u5e76\u7c98\u8d34\u5230X Articles\u7f16\u8f91\u5668\uff0c\u5904\u7406\u5c01\u9762\u3001\u5185\u5bb9\u56fe\u3001\u8868\u683c\u8f6c\u56fe\u4e0e\u5206\u5272\u7ebf\u63d2\u5165\uff0c\u6700\u7ec8\u53ea\u4fdd\u5b58\u8349\u7a3f\u4f9b\u4eba\u5de5\u53d1\u5e03\u3002\u4f9d\u8d56Playwright MCP\u3001\u5df2\u767b\u5f55\u7684X Premium\u8d26\u53f7\u53ca\u672c\u5730Python\u73af\u5883\uff0c\u811a\u672c\u672a\u5728\u672c\u6b21\u5ba1\u9605\u4e2d\u8fd0\u884c\u3002","category":"\u53d1\u5e03\u4e0e\u8fd0\u8425","tags":["wshuyi","\u53d1\u5e03\u4e0e\u8fd0\u8425"],"author":"wshuyi","source_url":"https://github.com/wshuyi/x-article-publisher-skill/blob/eb3197d1d8579556aea5018d5c0b141d55fc2df6/skills/x-article-publisher/SKILL.md","license":"MIT","status":"published","verification":"source_reviewed","verification_notes":"\u5df2\u6838\u5bf9\u539f\u59cb\u4ed3\u5e93\u3001\u56fa\u5b9a\u63d0\u4ea4\u3001\u8bb8\u53ef\u3001\u6280\u80fd\u6b63\u6587\u4e0e\u5305\u7ed3\u6784\uff0c\u5e76\u8865\u5145\u4e2d\u6587\u6267\u884c\u9a8c\u6536\u8bf4\u660e\uff1b\u672a\u8fd0\u884c\u5305\u5185\u811a\u672c\u3002","revision":"c1250aa7d76b4245b6544f6cad2f58a6","created_at":"2026-11-02T14:47:08+00:00","updated_at":"2026-11-02T14:47:08+00:00","source_repo":"wshuyi/x-article-publisher-skill","source_path":"skills/x-article-publisher/SKILL.md","source_commit":"eb3197d1d8579556aea5018d5c0b141d55fc2df6","source_updated_at":"2026-11-02T14:46:04+00:00","stars":0,"proxy_score":null,"score":null,"grade":null,"dimensions":{},"evaluation":{},"installs":0,"platforms":[],"formats":[],"category_slug":"publishing","category_name":"\u53d1\u5e03\u4e0e\u8fd0\u8425","quality":{"review_type":"text_and_package_review","readiness":"requires_setup","reviewed_at":"2026-11-02T14:46:04+00:00","review_summary":"\u53d1\u5e03\u6d41\u7a0b\u4e0e\u811a\u672c\u914d\u5957\u8f83\u5b8c\u6574\uff0c\u4f46\u811a\u672c\u672a\u8fd0\u884c\u9a8c\u8bc1\uff0c\u5b9a\u4f4d\u7b56\u7565\u8bf4\u660e\u524d\u540e\u4e0d\u4e00\u81f4\uff0c\u8def\u5f84\u5199\u6b7b\u9700\u6309\u5b9e\u9645\u5b89\u88c5\u4f4d\u7f6e\u8c03\u6574\u3002","cost_notes":"X Premium\u8ba2\u9605\u4e3a\u7b2c\u4e09\u65b9\u4ed8\u8d39\u670d\u52a1\uff0c\u8d39\u7528\u9700\u7528\u6237\u81ea\u884c\u786e\u8ba4\uff1b\u672c\u6280\u80fd\u4e0d\u4ee3\u62a5\u4ef7\u3002","source_sha256":"66b99b20fe37a0455d5360f0dd4b3300ebeae347a852c6c7f899c586a9b8ed6a","prerequisites":["Playwright MCP\u6d4f\u89c8\u5668\u81ea\u52a8\u5316\u5de5\u5177","\u7528\u6237\u5df2\u767b\u5f55\u4e14\u5177\u5907X Premium Plus\u8ba2\u9605\u7684\u8d26\u53f7","Python 3.9+\uff0cmacOS\u9700Pillow\u4e0epyobjc-framework-Cocoa\uff0cWindows\u9700Pillow\u3001pywin32\u3001clip-util","\u53ef\u9009\uff1aNode\u73af\u5883\u4e0e@mermaid-js/mermaid-cli\u7528\u4e8eMermaid\u8f6c\u56fe"],"checks":["\u89e3\u6790JSON\u662f\u5426\u5217\u51fatitle\u3001cover_image\u3001content_images\u3001dividers\u4e0emissing_images","\u8349\u7a3f\u6807\u9898\u4e0eH1\u4e00\u81f4\uff0c\u6b63\u6587\u4e0d\u542b\u91cd\u590dH1","\u5185\u5bb9\u56fe\u4e0e\u5206\u5272\u7ebf\u662f\u5426\u6309block_index\u4ece\u5927\u5230\u5c0f\u63d2\u5165\u4e14\u4f4d\u7f6e\u6b63\u786e","\u8868\u683c\u4e0eMermaid\u662f\u5426\u5df2\u8f6c\u4e3aPNG\u518d\u63d2\u5165","\u6700\u7ec8\u72b6\u6001\u662f\u5426\u4e3a\u8349\u7a3f\u800c\u975e\u5df2\u53d1\u5e03"],"limitations":["\u672c\u6b21\u4ec5\u505a\u6587\u672c\u4e0e\u5305\u7ed3\u6784\u5ba1\u9605\uff0c\u4e09\u4e2aPython\u811a\u672c\u5747\u672a\u8fd0\u884c\uff0c\u65e0\u6cd5\u786e\u8ba4\u8de8\u5e73\u53f0\u526a\u8d34\u677f\u4e0e\u89e3\u6790\u884c\u4e3a","\u4f9d\u8d56X Articles\u7f16\u8f91\u5668\u5f53\u524d\u754c\u9762\uff0c\u5e73\u53f0\u6539\u7248\u53ef\u80fd\u5bfc\u81f4\u9009\u62e9\u5668\u5931\u6548","\u65e0\u6cd5\u4fdd\u8bc1\u56fe\u7247\u4e0a\u4f20\u6210\u529f\u6216\u683c\u5f0f\u5b8c\u5168\u4fdd\u771f","\u4e0d\u81ea\u52a8\u53d1\u5e03\uff0c\u53d1\u5e03\u52a8\u4f5c\u9700\u7528\u6237\u4eba\u5de5\u5b8c\u6210"],"issues":["SKILL.md\u4e2dStep 6\u6807\u9898\u5199\u201c\u6587\u5b57\u641c\u7d22\u5b9a\u4f4d\u201d\uff0c\u6b63\u6587\u4e0eCritical Rules\u53c8\u4e3b\u5f20block_index\u5b9a\u4f4d\uff0c\u4e24\u5957\u5b9a\u4f4d\u8bf4\u660e\u5e76\u5b58\u6613\u6df7\u6dc6","\u811a\u672c\u8def\u5f84\u5199\u6b7b\u4e3a~/.claude/skills/x-article-publisher/scripts/\uff0c\u4e0e\u5305\u5185scripts/\u76ee\u5f55\u4e0d\u4e00\u81f4\uff0c\u5b89\u88c5\u4f4d\u7f6e\u4e0d\u540c\u4f1a\u5931\u8d25","Step 6.5\u5206\u5272\u7ebf\u63d2\u5165\u4f9d\u8d56\u201cInsert/\u6dfb\u52a0\u5a92\u4f53\u201d\u83dc\u5355\uff0c\u672a\u7ed9\u51fa\u53ef\u6838\u5bf9\u7684\u5143\u7d20\u5f15\u7528\uff0c\u5e73\u53f0UI\u53d8\u5316\u65f6\u6613\u5361\u4f4f","\u672a\u8bf4\u660eX Premium\u4e0ePremium Plus\u5728Articles\u6743\u9650\u4e0a\u7684\u5dee\u5f02\uff0c\u524d\u7f6e\u6761\u4ef6\u8868\u8ff0\u5f85\u6838\u5b9e"],"missing_files":[]},"quality_url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/SHILIU-QUALITY.md","usage_guide":{"task":"\u628a\u672c\u5730Markdown\u6587\u7ae0\u6309\u683c\u5f0f\u53d1\u5e03\u5230X Articles\u7f16\u8f91\u5668\uff0c\u4fdd\u7559\u6807\u9898\u3001\u5bcc\u6587\u672c\u3001\u56fe\u7247\u4e0e\u5206\u5272\u7ebf\u4f4d\u7f6e\uff0c\u5e76\u505c\u5728\u8349\u7a3f\u72b6\u6001\u3002","inputs":"\u5fc5\u9700\uff1aMarkdown\u6587\u4ef6\u8def\u5f84\uff08\u542bH1\u6807\u9898\u4e0e\u56fe\u7247\u5f15\u7528\uff09\uff1b\u5df2\u767b\u5f55X Premium/Premium Plus\u7684\u6d4f\u89c8\u5668\u4f1a\u8bdd\uff1bPlaywright MCP\u53ef\u7528\uff1bPython 3.9+\u53caPillow\u7b49\u4f9d\u8d56\u3002\u53ef\u9009\uff1aMermaid CLI\u7528\u4e8e\u56fe\u8868\u8f6c\u56fe\u3002","outputs":"X Articles\u8349\u7a3f\uff1a\u6807\u9898\u3001\u5c01\u9762\u56fe\u3001\u5bcc\u6587\u672c\u6b63\u6587\u3001\u6309block_index\u63d2\u5165\u7684\u5185\u5bb9\u56fe\u4e0e\u5206\u5272\u7ebf\uff1b\u4ee5\u53ca\u89e3\u6790JSON\u4e2d\u7684title\u3001cover_image\u3001content_images\u3001dividers\u3001missing_images\u7b49\u5b57\u6bb5\u4f9b\u6838\u5bf9\u3002","example_input":"\u8bf7\u628a /Users/me/article.md \u53d1\u5e03\u5230 X Articles\uff0c\u5148\u8f6c\u8868\u683c\u4e3a\u56fe\u7247\uff0c\u63d2\u597d\u5206\u5272\u7ebf\uff0c\u6700\u540e\u53ea\u4fdd\u5b58\u8349\u7a3f\u4e0d\u8981\u53d1\u5e03\u3002","example_output":"\u793a\u610f\u4ea4\u4ed8\uff08\u975e\u771f\u5b9e\u6267\u884c\u7ed3\u679c\uff09\uff1a\u89e3\u6790JSON\u5217\u51fa\u6807\u9898\u3001\u5c01\u9762\u8def\u5f84\u3001\u5185\u5bb9\u56fe\u53cablock_index\u3001\u5206\u5272\u7ebf\u4f4d\u7f6e\u3001\u7f3a\u5931\u56fe\u7247\u6570\uff1b\u6d4f\u89c8\u5668\u64cd\u4f5c\u540e\u62a5\u544a\u201c\u8349\u7a3f\u5df2\u4fdd\u5b58\uff0c\u8bf7\u4eba\u5de5\u9884\u89c8\u5e76\u53d1\u5e03\u201d\uff0c\u5e76\u5217\u51fa\u5df2\u63d2\u5165\u56fe\u7247\u4e0e\u5206\u5272\u7ebf\u6570\u91cf\u3002"},"read_url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929","skill_url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/SKILL.md","download_url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/download","install_url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/install","files":[{"path":"LICENSE","bytes":1063,"url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/LICENSE"},{"path":"SHILIU-QUALITY.md","bytes":1957,"url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/SHILIU-QUALITY.md"},{"path":"SKILL.md","bytes":18742,"url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/SKILL.md"},{"path":"scripts/copy_to_clipboard.py","bytes":9356,"url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/scripts/copy_to_clipboard.py"},{"path":"scripts/parse_markdown.py","bytes":12717,"url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/scripts/parse_markdown.py"},{"path":"scripts/table_to_image.py","bytes":8538,"url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/scripts/table_to_image.py"},{"path":"shiliu-quality.json","bytes":1958,"url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/shiliu-quality.json"},{"path":"shiliu-source.json","bytes":288,"url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/shiliu-source.json"},{"path":"usage.json","bytes":1042,"url":"https://shiliuai.cn/api/v2/skills/wshuyi-x-article-publisher-9a5929/files/usage.json"}],"content":"---\nname: x-article-publisher\ndescription: |\n  Publish Markdown articles to X (Twitter) Articles editor with proper formatting. Use when user wants to publish a Markdown file/URL to X Articles, or mentions \"publish to X\", \"post article to Twitter\", \"X article\", or wants help with X Premium article publishing. Handles cover image upload and converts Markdown to rich text automatically.\n---\n\n# X Article Publisher\n\nPublish Markdown content to X (Twitter) Articles editor, preserving formatting with rich text conversion.\n\n## Prerequisites\n\n- Playwright MCP for browser automation\n- User logged into X with Premium Plus subscription\n- Python 3.9+ with dependencies:\n  - macOS: `pip install Pillow pyobjc-framework-Cocoa`\n  - Windows: `pip install Pillow pywin32 clip-util`\n- For Mermaid diagrams: `npm install -g @mermaid-js/mermaid-cli`\n\n## Scripts\n\nLocated in `~/.claude/skills/x-article-publisher/scripts/`:\n\n### parse_markdown.py\nParse Markdown and extract structured data:\n```bash\npython parse_markdown.py <markdown_file> [--output json|html] [--html-only]\n```\nReturns JSON with: title, cover_image, content_images, **dividers** (with block_index for positioning), html, total_blocks\n\n### copy_to_clipboard.py\nCopy image or HTML to system clipboard (cross-platform):\n```bash\n# Copy image (with optional compression)\npython copy_to_clipboard.py image /path/to/image.jpg [--quality 80]\n\n# Copy HTML for rich text paste\npython copy_to_clipboard.py html --file /path/to/content.html\n```\n\n### table_to_image.py\nConvert Markdown table to PNG image:\n```bash\npython table_to_image.py <input.md> <output.png> [--scale 2]\n```\nUse when X Articles doesn't support native table rendering or for consistent styling.\n\n## Pre-Processing (Optional)\n\nBefore publishing, scan the Markdown for elements that need conversion:\n\n### Tables \u2192 PNG\n```bash\n# Extract table to temp file, then convert\npython ~/.claude/skills/x-article-publisher/scripts/table_to_image.py /tmp/table.md /tmp/table.png\n# Replace table in markdown with: ![Table](/tmp/table.png)\n```\n\n### Mermaid Diagrams \u2192 PNG\n```bash\n# Extract mermaid block to .mmd file, then convert\nmmdc -i /tmp/diagram.mmd -o /tmp/diagram.png -b white -s 2\n# Replace mermaid block with: ![Diagram](/tmp/diagram.png)\n```\n\n### Dividers (---)\nDividers are automatically detected by `parse_markdown.py` and output in the `dividers` array. They must be inserted via X Articles' **Insert > Divider** menu (HTML `<hr>` tags are ignored by X).\n\n## Workflow\n\n**Strategy: \"\u5148\u6587\u540e\u56fe\u540e\u5206\u5272\u7ebf\" (Text First, Images Second, Dividers Last)**\n\nFor articles with images and dividers, paste ALL text content first, then insert images and dividers at correct positions using block index.\n\n1. **(Optional)** Pre-process: Convert tables/mermaid to images\n2. Parse Markdown with Python script \u2192 get title, images, **dividers** with block_index, HTML\n3. Navigate to X Articles editor\n4. Upload cover image (first image)\n5. Fill title\n6. Copy HTML to clipboard (Python) \u2192 Paste with Cmd+V\n7. Insert content images at positions specified by block_index\n8. **Insert dividers at positions specified by block_index** (via Insert > Divider menu)\n9. Save as draft (NEVER auto-publish)\n\n## \u9ad8\u6548\u6267\u884c\u539f\u5219 (Efficiency Guidelines)\n\n**\u76ee\u6807**: \u6700\u5c0f\u5316\u64cd\u4f5c\u4e4b\u95f4\u7684\u7b49\u5f85\u65f6\u95f4\uff0c\u5b9e\u73b0\u6d41\u7545\u7684\u81ea\u52a8\u5316\u4f53\u9a8c\u3002\n\n### 1. \u907f\u514d\u4e0d\u5fc5\u8981\u7684 browser_snapshot\n\n\u5927\u591a\u6570\u6d4f\u89c8\u5668\u64cd\u4f5c\uff08click, type, press_key \u7b49\uff09\u90fd\u4f1a\u5728\u8fd4\u56de\u7ed3\u679c\u4e2d\u5305\u542b\u9875\u9762\u72b6\u6001\u3002**\u4e0d\u8981**\u5728\u6bcf\u6b21\u64cd\u4f5c\u540e\u5355\u72ec\u8c03\u7528 `browser_snapshot`\uff0c\u76f4\u63a5\u4f7f\u7528\u64cd\u4f5c\u8fd4\u56de\u7684\u9875\u9762\u72b6\u6001\u5373\u53ef\u3002\n\n```\n\u274c \u9519\u8bef\u505a\u6cd5\uff1a\nbrowser_click \u2192 browser_snapshot \u2192 \u5206\u6790 \u2192 browser_click \u2192 browser_snapshot \u2192 ...\n\n\u2705 \u6b63\u786e\u505a\u6cd5\uff1a\nbrowser_click \u2192 \u4ece\u8fd4\u56de\u7ed3\u679c\u4e2d\u83b7\u53d6\u9875\u9762\u72b6\u6001 \u2192 browser_click \u2192 ...\n```\n\n### 2. \u907f\u514d\u4e0d\u5fc5\u8981\u7684 browser_wait_for\n\n\u53ea\u5728\u4ee5\u4e0b\u60c5\u51b5\u4f7f\u7528 `browser_wait_for`\uff1a\n- \u7b49\u5f85\u56fe\u7247\u4e0a\u4f20\u5b8c\u6210\uff08`textGone=\"\u6b63\u5728\u4e0a\u4f20\u5a92\u4f53\"`\uff09\n- \u7b49\u5f85\u9875\u9762\u521d\u59cb\u52a0\u8f7d\uff08\u6781\u5c11\u6570\u60c5\u51b5\uff09\n\n**\u4e0d\u8981**\u4f7f\u7528 `browser_wait_for` \u6765\u7b49\u5f85\u6309\u94ae\u6216\u8f93\u5165\u6846\u51fa\u73b0 - \u5b83\u4eec\u5728\u9875\u9762\u52a0\u8f7d\u5b8c\u6210\u540e\u7acb\u5373\u53ef\u7528\u3002\n\n### 3. \u5e76\u884c\u6267\u884c\u72ec\u7acb\u64cd\u4f5c\n\n\u5f53\u4e24\u4e2a\u64cd\u4f5c\u6ca1\u6709\u4f9d\u8d56\u5173\u7cfb\u65f6\uff0c\u53ef\u4ee5\u5728\u540c\u4e00\u4e2a\u6d88\u606f\u4e2d\u5e76\u884c\u8c03\u7528\u591a\u4e2a\u5de5\u5177\uff1a\n\n```\n\u2705 \u53ef\u4ee5\u5e76\u884c\uff1a\n- \u586b\u5199\u6807\u9898 (browser_type) + \u590d\u5236HTML\u5230\u526a\u8d34\u677f (Bash)\n- \u89e3\u6790Markdown\u751f\u6210JSON + \u751f\u6210HTML\u6587\u4ef6\n\n\u274c \u4e0d\u80fd\u5e76\u884c\uff08\u6709\u4f9d\u8d56\uff09\uff1a\n- \u5fc5\u987b\u5148\u70b9\u51fbcreate\u624d\u80fd\u4e0a\u4f20\u5c01\u9762\u56fe\n- \u5fc5\u987b\u5148\u7c98\u8d34\u5185\u5bb9\u624d\u80fd\u63d2\u5165\u56fe\u7247\n```\n\n### 4. \u8fde\u7eed\u6267\u884c\u6d4f\u89c8\u5668\u64cd\u4f5c\n\n\u6bcf\u4e2a\u6d4f\u89c8\u5668\u64cd\u4f5c\u8fd4\u56de\u7684\u9875\u9762\u72b6\u6001\u5305\u542b\u6240\u6709\u9700\u8981\u7684\u5143\u7d20\u5f15\u7528\u3002\u76f4\u63a5\u4f7f\u7528\u8fd9\u4e9b\u5f15\u7528\u8fdb\u884c\u4e0b\u4e00\u6b65\u64cd\u4f5c\uff1a\n\n```\n# \u7406\u60f3\u6d41\u7a0b\uff08\u6bcf\u6b65\u76f4\u63a5\u6267\u884c\uff0c\u4e0d\u989d\u5916\u7b49\u5f85\uff09\uff1a\nbrowser_navigate \u2192 \u4ece\u8fd4\u56de\u72b6\u6001\u627ecreate\u6309\u94ae \u2192 browser_click(create)\n\u2192 \u4ece\u8fd4\u56de\u72b6\u6001\u627e\u4e0a\u4f20\u6309\u94ae \u2192 browser_click(\u4e0a\u4f20) \u2192 browser_file_upload\n\u2192 \u4ece\u8fd4\u56de\u72b6\u6001\u627e\u5e94\u7528\u6309\u94ae \u2192 browser_click(\u5e94\u7528)\n\u2192 \u4ece\u8fd4\u56de\u72b6\u6001\u627e\u6807\u9898\u6846 \u2192 browser_type(\u6807\u9898)\n\u2192 \u70b9\u51fb\u7f16\u8f91\u5668 \u2192 browser_press_key(Meta+v)\n\u2192 ...\n```\n\n### 5. \u51c6\u5907\u5de5\u4f5c\u524d\u7f6e\n\n\u5728\u5f00\u59cb\u6d4f\u89c8\u5668\u64cd\u4f5c\u4e4b\u524d\uff0c\u5148\u5b8c\u6210\u6240\u6709\u51c6\u5907\u5de5\u4f5c\uff1a\n1. \u89e3\u6790 Markdown \u83b7\u53d6 JSON \u6570\u636e\n2. \u751f\u6210 HTML \u6587\u4ef6\u5230 /tmp/\n3. \u8bb0\u5f55 title\u3001cover_image\u3001content_images \u7b49\u4fe1\u606f\n\n\u8fd9\u6837\u6d4f\u89c8\u5668\u64cd\u4f5c\u9636\u6bb5\u53ef\u4ee5\u8fde\u7eed\u6267\u884c\uff0c\u4e0d\u9700\u8981\u4e2d\u9014\u505c\u4e0b\u6765\u5904\u7406\u6570\u636e\u3002\n\n## Step 1: Parse Markdown (Python)\n\nUse `parse_markdown.py` to extract all structured data:\n\n```bash\npython ~/.claude/skills/x-article-publisher/scripts/parse_markdown.py /path/to/article.md\n```\n\nOutput JSON:\n```json\n{\n  \"title\": \"Article Title\",\n  \"cover_image\": \"/path/to/first-image.jpg\",\n  \"cover_exists\": true,\n  \"content_images\": [\n    {\"path\": \"/path/to/img2.jpg\", \"original_path\": \"/md/dir/assets/img2.jpg\", \"exists\": true, \"block_index\": 5, \"after_text\": \"context...\"},\n    {\"path\": \"/path/to/img3.jpg\", \"original_path\": \"/md/dir/assets/img3.jpg\", \"exists\": true, \"block_index\": 12, \"after_text\": \"another...\"}\n  ],\n  \"html\": \"<p>Content...</p><h2>Section</h2>...\",\n  \"total_blocks\": 45,\n  \"missing_images\": 0\n}\n```\n\n**Key fields:**\n- `block_index`: The image should be inserted AFTER block element at this index (0-indexed)\n- `total_blocks`: Total number of block elements in the HTML\n- `after_text`: Kept for reference/debugging only, NOT for positioning\n- `exists`: Whether the image file was found (if false, upload will fail)\n- `original_path`: The path resolved from Markdown (before auto-search)\n- `path`: The actual path to use (may differ from original_path if auto-searched)\n- `missing_images`: Count of images not found anywhere\n\nSave HTML to temp file for clipboard:\n```bash\npython parse_markdown.py article.md --html-only > /tmp/article_html.html\n```\n\n## Step 2: Open X Articles Editor\n\n### \u6d4f\u89c8\u5668\u9519\u8bef\u5904\u7406\n\n\u5982\u679c\u9047\u5230 `Error: Browser is already in use` \u9519\u8bef\uff1a\n\n```\n# \u65b9\u68481\uff1a\u5148\u5173\u95ed\u6d4f\u89c8\u5668\u518d\u91cd\u65b0\u6253\u5f00\nbrowser_close\nbrowser_navigate: https://x.com/compose/articles\n\n# \u65b9\u68482\uff1a\u5982\u679c browser_close \u65e0\u6548\uff08\u9501\u5b9a\uff09\uff0c\u63d0\u793a\u7528\u6237\u624b\u52a8\u5173\u95ed Chrome\n\n# \u65b9\u68483\uff1a\u4f7f\u7528\u5df2\u6709\u6807\u7b7e\u9875\uff0c\u76f4\u63a5\u5bfc\u822a\nbrowser_tabs action=list  # \u67e5\u770b\u73b0\u6709\u6807\u7b7e\nbrowser_navigate: https://x.com/compose/articles  # \u5728\u5f53\u524d\u6807\u7b7e\u5bfc\u822a\n```\n\n**\u6700\u4f73\u5b9e\u8df5**\uff1a\u6bcf\u6b21\u5f00\u59cb\u524d\u5148\u7528 `browser_tabs action=list` \u68c0\u67e5\u72b6\u6001\uff0c\u907f\u514d\u521b\u5efa\u591a\u4f59\u7a7a\u767d\u6807\u7b7e\u3002\n\n### \u5bfc\u822a\u5230\u7f16\u8f91\u5668\n\n```\nbrowser_navigate: https://x.com/compose/articles\n```\n\n**\u91cd\u8981**: \u9875\u9762\u52a0\u8f7d\u540e\u4f1a\u663e\u793a\u8349\u7a3f\u5217\u8868\uff0c\u4e0d\u662f\u7f16\u8f91\u5668\u3002\u9700\u8981\uff1a\n\n1. **\u7b49\u5f85\u9875\u9762\u52a0\u8f7d\u5b8c\u6210**: \u4f7f\u7528 `browser_snapshot` \u68c0\u67e5\u9875\u9762\u72b6\u6001\n2. **\u7acb\u5373\u70b9\u51fb \"create\" \u6309\u94ae**: \u4e0d\u8981\u7b49\u5f85 \"\u6dfb\u52a0\u6807\u9898\" \u7b49\u7f16\u8f91\u5668\u5143\u7d20\uff0c\u5b83\u4eec\u53ea\u6709\u70b9\u51fb create \u540e\u624d\u51fa\u73b0\n3. **\u7b49\u5f85\u7f16\u8f91\u5668\u52a0\u8f7d**: \u70b9\u51fb create \u540e\uff0c\u7b49\u5f85\u7f16\u8f91\u5668\u5143\u7d20\u51fa\u73b0\n\n```\n# 1. \u5bfc\u822a\u5230\u9875\u9762\nbrowser_navigate: https://x.com/compose/articles\n\n# 2. \u83b7\u53d6\u9875\u9762\u5feb\u7167\uff0c\u627e\u5230 create \u6309\u94ae\nbrowser_snapshot\n\n# 3. \u70b9\u51fb create \u6309\u94ae\uff08\u901a\u5e38 ref \u7c7b\u4f3c \"create\" \u6216\u5e26\u6709 create \u6807\u7b7e\uff09\nbrowser_click: element=\"create button\", ref=<create_button_ref>\n\n# 4. \u73b0\u5728\u7f16\u8f91\u5668\u5e94\u8be5\u6253\u5f00\u4e86\uff0c\u53ef\u4ee5\u7ee7\u7eed\u4e0a\u4f20\u5c01\u9762\u56fe\u7b49\u64cd\u4f5c\n```\n\n**\u6ce8\u610f**: \u4e0d\u8981\u4f7f\u7528 `browser_wait_for text=\"\u6dfb\u52a0\u6807\u9898\"` \u6765\u7b49\u5f85\u9875\u9762\u52a0\u8f7d\uff0c\u56e0\u4e3a\u8fd9\u4e2a\u6587\u672c\u53ea\u6709\u5728\u70b9\u51fb create \u540e\u624d\u51fa\u73b0\uff0c\u4f1a\u5bfc\u81f4\u8d85\u65f6\u3002\n\nIf login needed, prompt user to log in manually.\n\n## Step 3: Upload Cover Image\n\n1. Click \"\u6dfb\u52a0\u7167\u7247\u6216\u89c6\u9891\" button\n2. Use browser_file_upload with the cover image path (from JSON output)\n3. Verify image uploaded\n\n## Step 4: Fill Title\n\n- Find textbox with \"\u6dfb\u52a0\u6807\u9898\" placeholder\n- Use browser_type to input title (from JSON output)\n\n## Step 5: Paste Text Content (Python Clipboard)\n\nCopy HTML to system clipboard using Python, then paste:\n\n```bash\n# Copy HTML to clipboard\npython ~/.claude/skills/x-article-publisher/scripts/copy_to_clipboard.py html --file /tmp/article_html.html\n```\n\nThen in browser:\n```\nbrowser_click on editor textbox\nbrowser_press_key: Meta+v\n```\n\nThis preserves all rich text formatting (H2, bold, links, lists).\n\n## Step 6: Insert Content Images (Text Search Positioning)\n\n**\u63a8\u8350\u65b9\u6cd5**: \u4f7f\u7528 `after_text` \u6587\u5b57\u641c\u7d22\u5b9a\u4f4d\uff0c\u6bd4 `block_index` \u66f4\u76f4\u89c2\u53ef\u9760\u3002\n\n### \u5b9a\u4f4d\u539f\u7406\n\n\u6bcf\u5f20\u56fe\u7247\u7684 `after_text` \u5b57\u6bb5\u8bb0\u5f55\u4e86\u5b83\u524d\u4e00\u4e2a\u6bb5\u843d\u7684\u672b\u5c3e\u6587\u5b57\uff08\u6700\u591a80\u5b57\u7b26\uff09\u3002\u5728\u7f16\u8f91\u5668\u4e2d\u641c\u7d22\u5305\u542b\u8be5\u6587\u5b57\u7684\u6bb5\u843d\uff0c\u70b9\u51fb\u540e\u63d2\u5165\u56fe\u7247\u3002\n\n### \u64cd\u4f5c\u6b65\u9aa4\n\nFor each content image (from `content_images` array), **\u6309 block_index \u4ece\u5927\u5230\u5c0f\u7684\u987a\u5e8f**\uff1a\n\n```bash\n# 1. Copy image to clipboard (with compression)\npython ~/.claude/skills/x-article-publisher/scripts/copy_to_clipboard.py image /path/to/img.jpg --quality 85\n```\n\n```\n# 2. \u5728 browser_snapshot \u4e2d\u641c\u7d22\u5305\u542b after_text \u7684\u6bb5\u843d\n#    \u627e\u5230\u8be5\u6bb5\u843d\u7684 ref\n\n# 3. Click the paragraph containing after_text\nbrowser_click: element=\"paragraph with target text\", ref=<paragraph_ref>\n\n# 4. **\u5173\u952e\u6b65\u9aa4**: \u6309 End \u952e\u79fb\u52a8\u5149\u6807\u5230\u884c\u5c3e\n#    \u8fd9\u4e00\u6b65\u975e\u5e38\u91cd\u8981\uff01\u907f\u514d\u70b9\u51fb\u5230\u6bb5\u843d\u4e2d\u7684\u94fe\u63a5\u5bfc\u81f4\u4f4d\u7f6e\u504f\u79fb\nbrowser_press_key: End\n\n# 5. Paste image\nbrowser_press_key: Meta+v\n\n# 6. Wait for upload (only use textGone, no time parameter)\nbrowser_wait_for textGone=\"\u6b63\u5728\u4e0a\u4f20\u5a92\u4f53\"\n```\n\n### \u4e3a\u4ec0\u4e48\u9700\u8981\u6309 End \u952e\uff1f\n\n**\u95ee\u9898**: \u5f53\u6bb5\u843d\u5305\u542b\u94fe\u63a5\u65f6\uff08\u5982 `[\u94fe\u63a5\u6587\u5b57](url)`\uff09\uff0c\u70b9\u51fb\u6bb5\u843d\u53ef\u80fd\u4f1a\uff1a\n- \u89e6\u53d1\u94fe\u63a5\u7f16\u8f91\u5f39\u7a97\n- \u5c06\u5149\u6807\u5b9a\u4f4d\u5728\u94fe\u63a5\u5185\u90e8\u800c\u975e\u6bb5\u843d\u672b\u5c3e\n\n**\u89e3\u51b3\u65b9\u6848**: \u70b9\u51fb\u6bb5\u843d\u540e\u7acb\u5373\u6309 `End` \u952e\uff1a\n- \u786e\u4fdd\u5149\u6807\u79fb\u52a8\u5230\u6bb5\u843d\u672b\u5c3e\n- \u907f\u514d\u94fe\u63a5\u5e72\u6270\n- \u56fe\u7247\u5c06\u6b63\u786e\u63d2\u5165\u5728\u8be5\u6bb5\u843d\u4e4b\u540e\n\n### \u5b9a\u4f4d\u7b56\u7565\n\n\u5728 browser_snapshot \u8fd4\u56de\u7684\u7ed3\u6784\u4e2d\uff0c\u641c\u7d22 `after_text` \u7684\u5173\u952e\u8bcd\uff1a\n\n```yaml\ntextbox [ref=editor]:\n  generic [ref=p1]:\n    - StaticText: \"\u5143\u65e6\u5047\u671f\u6211\u5728\u5bb6\u91cc\u7ffb\u624b\u673a\u76f8\u518c...\"  # \u5982\u679c after_text \u5305\u542b\u8fd9\u6bb5\u6587\u5b57\uff0c\u70b9\u51fb p1\n  heading [ref=h1]:\n    - StaticText: \"\u6f14\u793a\"\n  generic [ref=p2]:\n    - StaticText: \"\u8fd9\u4e1c\u897f\u5230\u5e95\u6709\u591a\u7701\u4e8b\u513f\uff1f\"\n    - link [ref=link1]: \"Claude Code\"  # \u6ce8\u610f\uff1a\u6bb5\u843d\u53ef\u80fd\u5305\u542b\u94fe\u63a5\n  ...\n```\n\n### \u53cd\u5411\u63d2\u5165\u793a\u4f8b\n\n\u5982\u679c\u67093\u5f20\u56fe\u7247\uff0cblock_index \u5206\u522b\u4e3a 5, 12, 27\uff1a\n1. \u5148\u63d2\u5165 block_index=27 \u7684\u56fe\u7247\uff08after_text \u641c\u7d22 + End + \u7c98\u8d34\uff09\n2. \u518d\u63d2\u5165 block_index=12 \u7684\u56fe\u7247\n3. \u6700\u540e\u63d2\u5165 block_index=5 \u7684\u56fe\u7247\n\n**\u4ece\u5927\u5230\u5c0f\u63d2\u5165**\u53ef\u4ee5\u907f\u514d\u4f4d\u7f6e\u504f\u79fb\u95ee\u9898\u3002\n\n## Step 6.5: Insert Dividers (Via Menu)\n\n**\u91cd\u8981**: Markdown \u4e2d\u7684 `---` \u5206\u5272\u7ebf\u4e0d\u80fd\u901a\u8fc7 HTML `<hr>` \u6807\u7b7e\u7c98\u8d34\uff08X Articles \u4f1a\u5ffd\u7565\u5b83\uff09\u3002\u5fc5\u987b\u901a\u8fc7 X Articles \u7684 Insert \u83dc\u5355\u63d2\u5165\u3002\n\n### \u64cd\u4f5c\u6b65\u9aa4\n\nFor each divider (from `dividers` array), in **reverse order of block_index**:\n\n```\n# 1. Click the block element at block_index position\nbrowser_click on the element at position block_index in the editor\n\n# 2. Open Insert menu (Add Media button)\nbrowser_click on \"Insert\" or \"\u6dfb\u52a0\u5a92\u4f53\" button\n\n# 3. Click Divider menu item\nbrowser_click on \"Divider\" or \"\u5206\u5272\u7ebf\" menuitem\n\n# Divider is inserted at cursor position\n```\n\n### \u4e0e\u56fe\u7247\u7684\u63d2\u5165\u987a\u5e8f\n\n\u5efa\u8bae\u5148\u63d2\u5165\u6240\u6709\u56fe\u7247\uff0c\u518d\u63d2\u5165\u6240\u6709\u5206\u5272\u7ebf\u3002\u4e24\u8005\u90fd\u6309 block_index **\u4ece\u5927\u5230\u5c0f**\u7684\u987a\u5e8f\uff1a\n\n1. \u63d2\u5165\u6240\u6709\u56fe\u7247\uff08\u4ece\u6700\u5927 block_index \u5f00\u59cb\uff09\n2. \u63d2\u5165\u6240\u6709\u5206\u5272\u7ebf\uff08\u4ece\u6700\u5927 block_index \u5f00\u59cb\uff09\n\n## Step 7: Save Draft\n\n1. Verify content pasted (check word count indicator)\n2. Draft auto-saves, or click Save button if needed\n3. Click \"\u9884\u89c8\" to verify formatting\n4. Report: \"Draft saved. Review and publish manually.\"\n\n## Critical Rules\n\n1. **NEVER publish** - Only save draft\n2. **First image = cover** - Upload first image as cover image\n3. **Rich text conversion** - Always convert Markdown to HTML before pasting\n4. **Use clipboard API** - Paste via clipboard for proper formatting\n5. **Block index positioning** - Use block_index for precise image/divider placement\n6. **Reverse order insertion** - Insert images and dividers from highest to lowest block_index\n7. **H1 title handling** - H1 is used as title only, not included in body\n8. **Dividers via menu** - Markdown `---` must be inserted via Insert > Divider menu (HTML `<hr>` is ignored)\n\n## Supported Formatting\n\n| Element | Support | Notes |\n|---------|---------|-------|\n| H2 (`##`) | Native | Section headers |\n| Bold (`**`) | Native | Strong emphasis |\n| Italic (`*`) | Native | Emphasis |\n| Links (`[](url)`) | Native | Hyperlinks |\n| Ordered lists | Native | 1. 2. 3. |\n| Unordered lists | Native | - bullets |\n| Blockquotes (`>`) | Native | Quoted text |\n| Code blocks | Converted | \u2192 Blockquotes |\n| Tables | Converted | \u2192 PNG images (use table_to_image.py) |\n| Mermaid | Converted | \u2192 PNG images (use mmdc) |\n| Dividers (`---`) | Menu insert | \u2192 Insert > Divider |\n\n## Example Flow\n\nUser: \"Publish /path/to/article.md to X\"\n\n```bash\n# Step 1: Parse Markdown\npython ~/.claude/skills/x-article-publisher/scripts/parse_markdown.py /path/to/article.md > /tmp/article.json\npython ~/.claude/skills/x-article-publisher/scripts/parse_markdown.py /path/to/article.md --html-only > /tmp/article_html.html\n```\n\n2. Navigate to https://x.com/compose/articles\n3. Upload cover image (browser_file_upload for cover only)\n4. Fill title (from JSON: `title`)\n5. Copy & paste HTML:\n   ```bash\n   python ~/.claude/skills/x-article-publisher/scripts/copy_to_clipboard.py html --file /tmp/article_html.html\n   ```\n   Then: browser_press_key Meta+v\n6. For each content image, **in reverse order of block_index**:\n   ```bash\n   python copy_to_clipboard.py image /path/to/img.jpg --quality 85\n   ```\n   - Click block element at `block_index` position\n   - browser_press_key Meta+v\n   - Wait until upload complete\n7. Verify in preview\n8. \"Draft saved. Please review and publish manually.\"\n\n## Best Practices\n\n### \u4e3a\u4ec0\u4e48\u7528 block_index \u800c\u975e\u6587\u5b57\u5339\u914d\uff1f\n\n1. **\u7cbe\u786e\u5b9a\u4f4d**: \u4e0d\u4f9d\u8d56\u6587\u5b57\u5185\u5bb9\uff0c\u5373\u4f7f\u591a\u5904\u6587\u5b57\u76f8\u4f3c\u4e5f\u80fd\u6b63\u786e\u5b9a\u4f4d\n2. **\u53ef\u9760\u6027**: \u7d22\u5f15\u662f\u786e\u5b9a\u6027\u7684\uff0c\u4e0d\u4f1a\u56e0\u4e3a\u6587\u5b57\u76f8\u4f3c\u800c\u6df7\u6dc6\n3. **\u8c03\u8bd5\u65b9\u4fbf**: `after_text` \u4ecd\u4fdd\u7559\u7528\u4e8e\u4eba\u5de5\u6838\u9a8c\n\n### \u4e3a\u4ec0\u4e48\u7528 Python \u800c\u975e\u6d4f\u89c8\u5668\u5185 JavaScript\uff1f\n\n1. **\u672c\u5730\u5904\u7406\u66f4\u53ef\u9760**: Python \u76f4\u63a5\u64cd\u4f5c\u7cfb\u7edf\u526a\u8d34\u677f\uff0c\u4e0d\u53d7\u6d4f\u89c8\u5668\u6c99\u76d2\u9650\u5236\n2. **\u56fe\u7247\u538b\u7f29**: \u4e0a\u4f20\u524d\u538b\u7f29\u56fe\u7247 (--quality 85)\uff0c\u51cf\u5c11\u4e0a\u4f20\u65f6\u95f4\n3. **\u4ee3\u7801\u590d\u7528**: \u811a\u672c\u56fa\u5b9a\u4e0d\u53d8\uff0c\u65e0\u9700\u6bcf\u6b21\u91cd\u65b0\u7f16\u5199\u8f6c\u6362\u903b\u8f91\n4. **\u8c03\u8bd5\u65b9\u4fbf**: \u811a\u672c\u53ef\u5355\u72ec\u6d4b\u8bd5\uff0c\u95ee\u9898\u6613\u5b9a\u4f4d\n\n### \u7b49\u5f85\u7b56\u7565\n\n**\u91cd\u8981\u53d1\u73b0**: Playwright MCP \u7684 `browser_wait_for` \u5b9e\u9645\u884c\u4e3a\u662f **\u5148\u7b49\u5f85 time \u79d2\uff0c\u518d\u68c0\u67e5\u6761\u4ef6**\uff0c\u800c\u975e\u8f6e\u8be2\uff01\n\n```javascript\n// \u5b9e\u9645\u6267\u884c\u7684\u4ee3\u7801\uff1a\nawait new Promise(f => setTimeout(f, time * 1000));  // \u5148\u56fa\u5b9a\u7b49\u5f85\nawait page.getByText(\"xxx\").waitFor({ state: 'hidden' });  // \u518d\u68c0\u67e5\n```\n\n**\u6b63\u786e\u7528\u6cd5**:\n- \u2705 \u53ea\u7528 `textGone`\uff0c\u4e0d\u8bbe `time`\uff1a\u8ba9 Playwright \u81ea\u5df1\u8f6e\u8be2\u7b49\u5f85\n- \u2705 \u53ea\u7528 `time`\uff1a\u56fa\u5b9a\u7b49\u5f85\u6307\u5b9a\u79d2\u6570\n- \u274c \u540c\u65f6\u7528 `textGone` + `time`\uff1a\u4f1a\u5148\u7b49 time \u79d2\u518d\u68c0\u67e5\uff0c\u6d6a\u8d39\u65f6\u95f4\n\n```\n# \u63a8\u8350\uff1a\u53ea\u7528 textGone\uff0c\u8ba9\u5b83\u81ea\u52a8\u7b49\u5f85\u6761\u4ef6\u6ee1\u8db3\nbrowser_wait_for textGone=\"\u6b63\u5728\u4e0a\u4f20\u5a92\u4f53\"\n\n# \u6216\u8005\uff1a\u7528 browser_snapshot \u8f6e\u8be2\u68c0\u67e5\u72b6\u6001\n# \u6bcf\u6b21\u64cd\u4f5c\u540e\u68c0\u67e5\u8fd4\u56de\u7684\u9875\u9762\u72b6\u6001\uff0c\u65e0\u9700\u989d\u5916\u7b49\u5f85\n```\n\n### \u56fe\u7247\u63d2\u5165\u6548\u7387\n\n\u6bcf\u5f20\u56fe\u7247\u7684\u6d4f\u89c8\u5668\u64cd\u4f5c\u4ece5\u6b65\u51cf\u5c11\u52302\u6b65\uff1a\n- \u65e7: \u70b9\u51fb \u2192 \u6dfb\u52a0\u5a92\u4f53 \u2192 \u5a92\u4f53 \u2192 \u6dfb\u52a0\u7167\u7247 \u2192 file_upload\n- \u65b0: \u70b9\u51fb\u6bb5\u843d \u2192 Meta+v\n\n### \u5c01\u9762\u56fe vs \u5185\u5bb9\u56fe\n\n- **\u5c01\u9762\u56fe**: \u4f7f\u7528 browser_file_upload\uff08\u56e0\u4e3a\u6709\u4e13\u95e8\u7684\u4e0a\u4f20\u6309\u94ae\uff09\n- **\u5185\u5bb9\u56fe**: \u4f7f\u7528 Python \u526a\u8d34\u677f + \u7c98\u8d34\uff08\u66f4\u9ad8\u6548\uff09\n\n## \u6545\u969c\u6392\u9664\n\n### MCP \u8fde\u63a5\u95ee\u9898\n\n\u5982\u679c Playwright MCP \u5de5\u5177\u4e0d\u53ef\u7528\uff08\u62a5\u9519 `No such tool available` \u6216 `Not connected`\uff09\uff1a\n\n**\u65b9\u68481\uff1a\u91cd\u65b0\u8fde\u63a5 MCP\uff08\u63a8\u8350\uff09**\n```\n\u6267\u884c /mcp \u547d\u4ee4\uff0c\u9009\u62e9 playwright\uff0c\u9009\u62e9 Restart\n```\n\n**\u65b9\u68482\uff1a\u6e05\u7406\u6b8b\u7559\u8fdb\u7a0b\u540e\u91cd\u8fde**\n```bash\n# \u6740\u6389\u6240\u6709\u6b8b\u7559\u7684 playwright \u8fdb\u7a0b\npkill -f \"mcp-server-playwright\"\npkill -f \"@playwright/mcp\"\n\n# \u7136\u540e\u6267\u884c /mcp \u91cd\u65b0\u8fde\u63a5\n```\n\n**\u914d\u7f6e\u6587\u4ef6\u4f4d\u7f6e**: `~/.claude/mcp_servers.json`\n\n### \u6d4f\u89c8\u5668\u9519\u8bef\u5904\u7406\n\n\u5982\u679c\u9047\u5230 `Error: Browser is already in use` \u9519\u8bef\uff1a\n\n```bash\n# \u65b9\u68481\uff1a\u5148\u5173\u95ed\u6d4f\u89c8\u5668\u518d\u91cd\u65b0\u6253\u5f00\nbrowser_close\nbrowser_navigate: https://x.com/compose/articles\n\n# \u65b9\u68482\uff1a\u6740\u6389 Chrome \u8fdb\u7a0b\npkill -f \"Chrome.*--remote-debugging\"\n# \u7136\u540e\u91cd\u65b0 navigate\n```\n\n### \u56fe\u7247\u4f4d\u7f6e\u504f\u79fb\n\n\u5982\u679c\u56fe\u7247\u63d2\u5165\u4f4d\u7f6e\u4e0d\u6b63\u786e\uff08\u7279\u522b\u662f\u70b9\u51fb\u542b\u94fe\u63a5\u7684\u6bb5\u843d\u65f6\uff09\uff1a\n\n**\u539f\u56e0**: \u70b9\u51fb\u6bb5\u843d\u65f6\u53ef\u80fd\u8bef\u89e6\u94fe\u63a5\uff0c\u5bfc\u81f4\u5149\u6807\u4f4d\u7f6e\u9519\u8bef\n\n**\u89e3\u51b3\u65b9\u6848**: \u70b9\u51fb\u540e**\u5fc5\u987b\u6309 End \u952e**\u79fb\u52a8\u5149\u6807\u5230\u884c\u5c3e\n\n```\n# \u6b63\u786e\u6d41\u7a0b\n1. browser_click \u70b9\u51fb\u76ee\u6807\u6bb5\u843d\n2. browser_press_key: End        # \u5173\u952e\u6b65\u9aa4\uff01\n3. browser_press_key: Meta+v     # \u7c98\u8d34\u56fe\u7247\n4. browser_wait_for textGone=\"\u6b63\u5728\u4e0a\u4f20\u5a92\u4f53\"\n```\n\n### \u56fe\u7247\u8def\u5f84\u627e\u4e0d\u5230\n\n\u5982\u679c Markdown \u4e2d\u7684\u76f8\u5bf9\u8def\u5f84\u56fe\u7247\u627e\u4e0d\u5230\uff08\u5982 `./assets/image.png` \u5b9e\u9645\u5728\u5176\u4ed6\u4f4d\u7f6e\uff09\uff1a\n\n**\u81ea\u52a8\u641c\u7d22**: `parse_markdown.py` \u4f1a\u81ea\u52a8\u5728\u4ee5\u4e0b\u76ee\u5f55\u641c\u7d22\u540c\u540d\u6587\u4ef6\uff1a\n- `~/Downloads`\n- `~/Desktop`\n- `~/Pictures`\n\n**stderr \u8f93\u51fa\u793a\u4f8b**:\n```\n[parse_markdown] Image not found at '/path/to/assets/img.png', using '/Users/xxx/Downloads/img.png' instead\n```\n\n**JSON \u5b57\u6bb5\u8bf4\u660e**:\n- `original_path`: Markdown \u4e2d\u6307\u5b9a\u7684\u8def\u5f84\uff08\u89e3\u6790\u540e\u7684\u7edd\u5bf9\u8def\u5f84\uff09\n- `path`: \u5b9e\u9645\u4f7f\u7528\u7684\u8def\u5f84\uff08\u5982\u679c\u81ea\u52a8\u641c\u7d22\u6210\u529f\uff0c\u4f1a\u4e0d\u540c\u4e8e original_path\uff09\n- `exists`: `true` \u8868\u793a\u627e\u5230\u6587\u4ef6\uff0c`false` \u8868\u793a\u672a\u627e\u5230\uff08\u4e0a\u4f20\u4f1a\u5931\u8d25\uff09\n\n**\u5982\u679c\u4ecd\u7136\u627e\u4e0d\u5230**:\n1. \u68c0\u67e5 JSON \u8f93\u51fa\u4e2d\u7684 `missing_images` \u5b57\u6bb5\n2. \u624b\u52a8\u5c06\u56fe\u7247\u590d\u5236\u5230 Markdown \u6587\u4ef6\u540c\u76ee\u5f55\u7684 `assets/` \u5b50\u76ee\u5f55\n3. \u6216\u4fee\u6539 Markdown \u4e2d\u7684\u56fe\u7247\u8def\u5f84\u4e3a\u7edd\u5bf9\u8def\u5f84\n","usage":"\u8bfb\u53d6 SKILL.md\uff0c\u5e76\u6309\u9700\u8bfb\u53d6\u914d\u5957\u6587\u4ef6\uff1b\u4e0b\u8f7d ZIP \u83b7\u53d6\u5b8c\u6574\u5305\u3002\u6280\u80fd\u662f\u4efb\u52a1\u65b9\u6cd5\uff0c\u4e0d\u6388\u4e88\u65b0\u589e\u8d26\u6237\u3001\u4ed8\u8d39\u6216\u7cfb\u7edf\u6743\u9650\u3002"}
