Skill: yangchao228/wx-md-article (version 1.0.0)

# WeChat Article Generator Skill 自动生成微信公众号文章并上传到草稿箱。 ## 设计规范 ### 色彩规范 - **小标题**: 绿色 `#07c160`，带左边框 - **正文**: 黑色 `#333` - **重点词**: 加粗 `<strong>`，不使用额外颜色 - **禁用**: emoji、花里胡哨的背景色、多种颜色混用 ### 排版规范 - 简洁专业，避免过度设计 - 列表使用 `·` 或数字，不使用 emoji - 引用居中斜体，不使用彩色背景 - 标签统一绿色圆角 ## 使用方法 ```bash # 生成文章并上传 ./wechat-article.sh <input.md> <title> [author] [thumb_media_id] # 示例 ./wechat-article.sh article.md "文章标题" "超哥" --upload ``` ## 支持的 Markdown 语法 ```markdown # 一级标题 → 绿色小标题带边框 ## 二级标题 → 加粗小标题 ### 三级标题 → 普通加粗 - 列表项 → · 列表项 * 列表项 → · 列表项 1. 列表项 → 1. 列表项 > 引用 → 居中斜体引用框 **强调** → <strong>强调</strong>（黑色加粗） *斜体* → <em>斜体</em> 普通段落 → 黑色正文 ``` ## 配置 在 `config.json` 中配置： ```json { "appid": "your_appid", "appsecret": "your_appsecret", "default_author": "超哥", "style": { "primary_color": "#07c160", "text_color": "#333" }, "formatting_rules": { "use_emoji": false, "max_colors": 2 } } ``` ## 文件结构 ``` skills/wechat-article/ ├── SKILL.md # 本文件 ├── wechat-article.sh # 主脚本 ├── template.html # 文章模板（简洁版） ├── config.json # 配置文件 └── lib/ └── wechat-api.sh # 微信API封装 ``` ## 依赖 - curl - jq - sed/awk ## 版本 v1.1.0 - 更新为简洁专业风格，移除emoji，统一色彩

path: _meta.json
content: {
  "id": "wechat-md-publish",
  "name": "微信MD发布器",
  "version": "1.0.0",
  "description": "Markdown转微信公众号HTML并上传草稿箱",
  "author": "yangchao228",
  "tags": ["wechat", "markdown", "article"],
  "acceptLicenseTerms": true
}


path: config.json
content: {
  "appid": "wx5ef520c59474d914",
  "appsecret": "a0784a1b1ade054bcbfc66f3a85db09f",
  "default_author": "超哥",
  "default_thumb_media_id": [REDACTED_SECRET],
  "style": {
    "primary_color": "#07c160",
    "text_color": "#333",
    "secondary_text": "#666",
    "light_bg": "#f8f9fa",
    "border_color": "#eee"
  },
  "formatting_rules": {
    "heading_style": "green_left_border",
    "text_color": "black",
    "emphasis_style": "bold_only",
    "use_emoji": false,
    "max_colors": 2
  }
}


path: package.json
content: {
  "name": "wechat-article",
  "version": "1.0.0",
  "description": "微信公众号文章生成器 - Markdown转微信HTML并上传草稿箱",
  "main": "wechat-article.sh",
  "author": "超哥",
  "license": "MIT",
  "keywords": [
    "wechat",
    "weixin",
    "公众号",
    "markdown",
    "文章生成"
  ],
  "repository": {
    "type": "git",
    "url": ""
  },
  "bin": {
    "wechat-article": "./wechat-article.sh"
  },
  "scripts": {
    "test": "./wechat-article.sh --help"
  },
  "dependencies": {
    "curl": "*",
    "jq": "*"
  }
}


path: template.html
content: <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{TITLE}}</title>
</head>
<body style="margin:0;padding:0;background:#f7f7f7;font-family:-apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif;">

<div style="max-width:680px;margin:0 auto;background:#fff;padding:20px 15px;">

<!-- 标题区 -->
<div style="text-align:center;padding:30px 0;border-bottom:2px solid #07c160;margin-bottom:25px;">
    <h1 style="font-size:22px;color:#1a1a1a;margin:0 0 10px 0;font-weight:bold;line-height:1.4;">{{TITLE}}</h1>
    <p style="font-size:14px;color:#666;margin:0;">{{SUBTITLE}}</p>
    <p style="font-size:12px;color:#999;margin-top:10px;">{{DATE}}</p>
</div>

<!-- 正文 -->
<div style="font-size:16px;line-height:1.8;color:#333;">
{{CONTENT}}
</div>

<!-- 标签 -->
<div style="margin-top:30px;padding-top:20px;border-top:1px solid #eee;text-align:center;">
{{TAGS}}
</div>

</div>
</body>
</html>


path: wechat-article.sh
content: #!/bin/bash
# 微信公众号文章生成器 - 简洁专业版

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/lib/wechat-api.sh"

# 显示帮助
show_help() {
    cat << EOF
微信公众号文章生成器

设计规范:
- 小标题: 绿色 #07c160，带左边框
- 正文: 黑色 #333
- 重点: 加粗，不使用额外颜色
- 禁用: emoji、花里胡哨的背景色

用法:
    $0 <input_file> [选项]

参数:
    input_file          输入文件 (Markdown 或 HTML)

选项:
    -t, --title         文章标题
    -s, --subtitle      副标题
    -a, --author        作者名 (默认: 超哥)
    -d, --digest        文章摘要
    -i, --image         封面图片路径 (可选)
    -o, --output        输出HTML文件路径
    --upload            上传到微信公众号草稿箱
    -h, --help          显示帮助

示例:
    $0 article.md -t "文章标题" -s "副标题" --upload
EOF
}

# 转换 Markdown 到 HTML（简洁版）
convert_markdown() {
    local input=$1
    
    # 简洁版转换规则
    # 一级标题 → 绿色小标题带边框
    sed 's/^# \(.*\)/<div style="margin:30px 0 15px 0;padding-left:12px;border-left:3px solid #07c160;"><h2 style="font-size:17px;color:#07c160;margin:0;font-weight:bold;">\1<\/h2><\/div>/g' "$input" | \
    # 二级标题 → 加粗小标题
    sed 's/^## \(.*\)/<p style="margin:20px 0 10px 0;"><strong>\1<\/strong><\/p>/g' | \
    # 三级标题 → 普通加粗
    sed 's/^### \(.*\)/<p style="margin:15px 0 10px 0;"><strong>\1<\/strong><\/p>/g' | \
    # 列表（使用 · 代替 emoji）
    sed 's/^[-*] \(.*\)/<p style="margin:0 0 5px 0;">· \1<\/p>/g' | \
    sed 's/^[0-9]\+\. \(.*\)/<p style="margin:0 0 5px 0;">\0<\/p>/g' | \
    # 引用 → 居中斜体
    sed 's/^> \(.*\)/<p style="margin:15px 0;text-align:center;font-size:15px;color:#666;font-style:italic;"><strong>\1<\/strong><\/p>/g' | \
    # 强调 → 仅加粗，不添加颜色
    sed 's/\*\*\([^*]*\)\*\*/<strong>\1<\/strong>/g' | \
    sed 's/\*\([^*]*\)\*/<em>\1<\/em>/g' | \
    # 段落
    sed 's/^\([^<].*\)$/<p style="margin:0 0 15px 0;">\1<\/p>/g' | \
    # 移除 emoji（常见范围）
    sed 's/[😀-🿿]//g' | \
    sed 's/[🀀-🃏]//g' | \
    sed 's/[🄀-🇿]//g'
}

# 生成标签HTML（简洁版）
generate_tags() {
    local tags=$1
    local html=""
    for tag in $tags; do
        # 移除标签中的 emoji
        tag=$(echo "$tag" | sed 's/[😀-🿿]//g; s/[🀀-🃏]//g; s/[🄀-🇿]//g')
        html="${html}<span style=\"display:inline-block;padding:5px 12px;background:#07c160;color:#fff;border-radius:15px;font-size:12px;margin:3px;\">$tag<\/span>"
    done
    echo "$html"
}

# 主函数
main() {
    local input_file=""
    local title=""
    local subtitle=""
    local author="超哥"
    local digest=""
    local image_path=""
    local output_file=""
    local upload=false
    local tags=""
    
    # 解析参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -t|--title)
                title="$2"
                shift 2
                ;;
            -s|--subtitle)
                subtitle="$2"
                shift 2
                ;;
            -a|--author)
                author="$2"
                shift 2
                ;;
            -d|--digest)
                digest="$2"
                shift 2
                ;;
            -i|--image)
                image_path="$2"
                shift 2
                ;;
            -o|--output)
                output_file="$2"
                shift 2
                ;;
            --tags)
                tags="$2"
                shift 2
                ;;
            --upload)
                upload=true
                shift
                ;;
            -h|--help)
                show_help
                exit 0
                ;;
            -*)
                echo "未知选项: $1"
                show_help
                exit 1
                ;;
            *)
                input_file="$1"
                shift
                ;;
        esac
    done
    
    # 检查输入文件
    if [[ -z "$input_file" ]]; then
        echo "错误: 请指定输入文件"
        show_help
        exit 1
    fi
    
    if [[ ! -f "$input_file" ]]; then
        echo "错误: 文件不存在: $input_file"
        exit 1
    fi
    
    # 从文件名提取标题（如果没有指定）
    if [[ -z "$title" ]]; then
        title=$(basename "$input_file" | sed 's/\.[^.]*$//')
    fi
    
    # 从内容提取摘要（如果没有指定）
    if [[ -z "$digest" ]]; then
        digest=$(head -n 5 "$input_file" | grep -v "^#" | head -n 1 | cut -c 1-100)
    fi
    
    # 转换内容
    echo "正在转换内容..."
    local content=$(convert_markdown "$input_file")
    
    # 生成标签
    local tags_html=$(generate_tags "$tags")
    
    # 读取模板并替换变量
    echo "正在生成HTML..."
    local date=$(date +"%Y-%m-%d")
    local html=$(cat "$SCRIPT_DIR/template.html" | \
        sed "s/{{TITLE}}/$title/g" | \
        sed "s/{{SUBTITLE}}/$subtitle/g" | \
        sed "s/{{DATE}}/$date/g" | \
        sed "s/{{FOOTER_TEXT}}/本文是养虾日记系列/g" | \
        sed "s/{{TAGS}}/$tags_html/g")
    
    # 替换内容（特殊处理）
    html=$(echo "$html" | awk -v content="$content" '{gsub(/{{CONTENT}}/, content)} 1')
    
    # 保存输出
    if [[ -z "$output_file" ]]; then
        output_file="/tmp/wechat_article_$(date +%s).html"
    fi
    
    echo "$html" > "$output_file"
    echo "HTML已生成: $output_file"
    
    # 上传到微信
    if $upload; then
        echo "正在上传到微信公众号..."
        
        # 获取 access_token
        local access_token=$(get_access_token)
        echo "Access [REDACTED_SECRET]"
        
        # 上传封面图（如果指定）
        local thumb_media_id=$(get_config "default_thumb_media_id")
        if [[ -n "$image_path" && -f "$image_path" ]]; then
            echo "正在上传封面图片..."
            local upload_response=$(upload_image "$access_token" "$image_path")
            thumb_media_id=$(echo "$upload_response" | jq -r '.media_id')
            echo "封面图片ID: $thumb_media_id"
        fi
        
        # 准备JSON数据
        local json_file="/tmp/wechat_article_$(date +%s).json"
        cat > "$json_file" << EOF
{
  "articles": [
    {
      "title": "$title",
      "author": "$author",
      "digest": "$digest",
      "content": $(echo "$html" | jq -Rs '.'),
      "thumb_media_id": "$thumb_media_id",
      "need_open_comment": 1,
      "only_fans_can_comment": 0
    }
  ]
}
EOF
        
        # 上传草稿
        local response=$(add_draft "$access_token" "$json_file")
        local media_id=$(echo "$response" | jq -r '.media_id')
        
        if [[ "$media_id" != "null" && -n "$media_id" ]]; then
            echo "✓ 上传成功!"
            echo "草稿ID: $media_id"
            echo "请在微信公众号后台「草稿箱」中查看"
        else
            echo "✗ 上传失败"
            echo "响应: $response"
            exit 1
        fi
        
        # 清理临时文件
        rm -f "$json_file"
    fi
    
    echo "完成!"
}

main "$@"


path: lib/wechat-api.sh
content: #!/bin/bash
# 微信API封装

CONFIG_FILE="$(dirname "$0")/../config.json"

# 读取配置
get_config() {
    local key=$1
    jq -r ".$key" "$CONFIG_FILE"
}

# 获取 access_token
get_access_token() {
    local appid=$(get_config "appid")
    local appsecret=$(get_config "appsecret")
    
    local response=$(curl -s "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&[REDACTED_SECRET]")
    echo "$response" | jq -r '.access_token'
}

# 上传图片素材
upload_image() {
    local access_token=$1
    local image_path=$2
    
    curl -s "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=$access_token&type=image" \
        -F "media=@$image_path"
}

# 添加草稿
add_draft() {
    local access_token=$1
    local json_file=$2
    
    curl -s -X POST "https://api.weixin.qq.com/cgi-bin/draft/add?access_token=$access_token" \
        -H "Content-Type: application/json" \
        --data-binary @"$json_file"
}

# 删除草稿
delete_draft() {
    local access_token=$1
    local media_id=$2
    
    curl -s -X POST "https://api.weixin.qq.com/cgi-bin/draft/delete?access_token=$access_token" \
        -H "Content-Type: application/json" \
        -d "{\"media_id\":\"$media_id\"}"
}


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)