# CFG-001: 配置参考

本文档是 CMTX 配置的唯一事实源。所有应用层文档(CLI、VS Code、MCP Server)的配置部分均引用本文档。 后续新增环境变量或配置字段只需修改此处 + 对应代码实现。

# 1. 环境变量

凭证优先从 YAML 配置文件中读取,未配置时回退到环境变量。

# 1.1. 阿里云 OSS

变量名 必填 默认值 说明
CMTX_ALIYUN_ACCESS_KEY_ID - RAM 用户 AccessKey ID
CMTX_ALIYUN_ACCESS_KEY_SECRET - RAM 用户 AccessKey Secret
CMTX_ALIYUN_BUCKET - OSS Bucket 名称
CMTX_ALIYUN_REGION oss-cn-hangzhou OSS 地域

# 1.2. 腾讯云 COS

变量名 必填 默认值 说明
CMTX_TENCENT_SECRET_ID - 云 API SecretId
CMTX_TENCENT_SECRET_KEY - 云 API SecretKey
CMTX_TENCENT_BUCKET - COS Bucket(格式 bucketname-appid
CMTX_TENCENT_REGION ap-guangzhou COS 地域

# 1.3. AI Provider

变量名 必填 说明
CMTX_DEEPSEEK_API_KEY DeepSeek API Key(ai.models.*.provider: deepseek 时使用)
CMTX_QWEN_API_KEY 阿里云 Qwen API Key(ai.models.*.provider: alibaba 时使用)

# 1.4. FBE 加密密钥

变量名 必填 说明
CMTX_FBE_KEY ID 生成时的 FPE 加密密钥(frontmatter-id.ff1.encryptionKey 默认值)

# 2. 凭证解析流程

1. config.accessKeyId / config.secretId(YAML 配置文件中的值)
2. CMTX_ALIYUN_ACCESS_KEY_ID / CMTX_TENCENT_SECRET_ID(环境变量)
3. 内置默认值(region 等)

当三个字段(key/secret/bucket)任一缺失时报错。

注意: 配置项 uploadresize 已废弃并从顶层移除,其配置迁移至 rules.upload-imagesrules.resize-image 下。upload.delete 配置项已移除。

# 3. YAML 配置参考

以下 YAML 展示每个 section 内部的默认值。顶级可选 section(presignedUrlsrulespresets)整块不配置时对应功能关闭。 运行 cmtx config init 生成的模板仅包含必要配置,不在此模板中的字段不会丢失默认行为。

# yaml-language-server: $schema=./config.schema.json
version: v2                       # 配置版本(当前为 v2)

# ============================
# 存储池(必需)
# ============================
storages:
  default:                        # 存储 ID,可自定义;rules.upload-images.useStorage 引用此 ID
    adapter: aliyun-oss           # aliyun-oss | tencent-cos
    provider: aliyun-oss          # 可选,存储提供商提示
    config:
      region: oss-cn-hangzhou     # 地域(如 oss-cn-hangzhou、ap-guangzhou)
      bucket: "${CMTX_ALIYUN_BUCKET}"          # Bucket 名称;支持环境变量引用
      accessKeyId: "${CMTX_ALIYUN_ACCESS_KEY_ID}"
      accessKeySecret: "${CMTX_ALIYUN_ACCESS_KEY_SECRET}"

# ============================
# 预签名 URL 配置(可选,整块不配置则禁用预签名功能)
# 各子字段仅在 presignedUrls 存在时生效
# ============================
presignedUrls:
  expire: 600                     # 签名过期时间,单位秒
  maxRetryCount: 3                # 签名失败时最大重试次数
  imageFormat: all                # 处理的图片格式范围:markdown | html | all
  domains:                        # 需要签名处理的域名列表
    - domain: example.com         # 域名,默认 example.com
      useStorage: default         # 引用 storages 中的配置(必填)
      forceHttps: false           # 强制使用 HTTPS 生成预签名 URL

# ============================
# AI 配置(可选,整块不配置则 AI 功能禁用)
# ============================
ai:
  models:
    deepseek-v4-flash:              # 自定义模型 ID,rule 中通过 useModel 引用
      provider: deepseek            # deepseek | alibaba | openai-compatible
      model: deepseek-v4-flash      # 实际模型名称
      apiKey: "${CMTX_DEEPSEEK_API_KEY}" # 支持环境变量引用
      baseURL: ""                   # 可选,自定义 API 端点(OpenAI 兼容模式)
      timeout: 30000                # 可选,超时(毫秒)
      maxRetries: 3                 # 可选,重试次数
  defaultModel: deepseek-v4-flash   # 可选,不指定时 rule 必须显式指定 useModel

# ============================
# 全局 Rules 默认参数(可选,整块不配置则所有 rule 使用代码内置默认值)
# 当 preset 中某个 rule 未指定 config 时,使用此处的默认值
# ============================
rules:
  # 文本处理
  strip-frontmatter: {}           # 移除 YAML frontmatter
  promote-headings:
    levels: 1                     # 提升 N 级标题(H2->H1, H3->H2)
  text-replace:
    match: ""                     # 正则匹配模式
    replace: ""                   # 替换文本,支持 $1 捕获组
    flags: "gm"                   # 正则标志:g(全局) m(多行) i(忽略大小写)

  # 图片处理
  convert-images:
    convertToHtml: false          # true=Markdown 转 HTML img 标签;false=反向转换

  # 图片上传(可选,整块不配置则禁用上传功能)
  upload-images:
    imageFormat: markdown         # 输出格式:markdown | html
    concurrency: 5                # 并发上传数
    namingTemplate: "{timestamp}-{name}.{ext}"  # 远程文件命名模板
    auto: false                   # 是否自动上传(监听文件变更)
    conflictStrategy: skip        # 冲突策略:skip(跳过,保留远程)| overwrite(覆盖为本地)
    useStorage: default           # 引用 storages 中的哪个存储配置
    prefix: ""                    # 远程路径前缀,如 blog/images/
    domain: ""                    # 自定义域名(可选),上传后 URL 替换为此域名,如 cdn.example.com
    replace:                      # 字段替换模板(上传后修改图片引用属性)
      fields:
        src: "{cloudSrc}"         # 替换图片路径的模板
        alt: "{originalAlt}"      # 替换 alt 文本的模板

  # 图片缩放(可选,整块不配置则禁用缩放功能)
  resize-image:
    widths: [360, 480, 640, 800, 960, 1200]   # 可用缩放宽度列表(v0.5 起从 availableWidths 重命名)
    # 服务器端缩放域名配置(可选)
    # 匹配域名时通过 URL 参数让 OSS/COS 返回缩放后图片,不匹配时使用客户端 img 属性缩放
    # provider: aliyun-oss | tencent-cos
    # 参考文档:
    #   阿里云 OSS 图片缩放: <https://help.aliyun.com/zh/oss/user-guide/resize-images-4>
    #   腾讯云 COS 图片缩放: <https://cloud.tencent.com/document/product/460/36540>
    # domains:
    #   - domain: bucket.oss-cn-hangzhou.aliyuncs.com
    #     provider: aliyun-oss

  # 图片压缩(可选,整块不配置则禁用压缩功能)
  # 需要安装 sharp: pnpm add sharp
  # CLI 独立使用: cmtx image compress ./images/ --quality 80
  # 上传时自动压缩: 上传流水线会读取此配置,在上传前自动压缩图片
  compress-image:
    quality: 80                   # 压缩质量 1-100
    format: original              # 输出格式:original(保持原格式)| jpeg | png | webp | avif
    preserveMetadata: false       # 是否保留 EXIF 元数据(false=去除,可减小体积)

  # 章节编号
  add-section-numbers:
    minLevel: 2                   # 起始标题等级
    maxLevel: 6                   # 最大标题等级
    startLevel: 2                 # 起始层级
    separator: "."                # 编号分隔符(如 "1.1.")
  remove-section-numbers: {}      # 移除章节编号

  # Metadata / Frontmatter
  frontmatter-title:
    headingLevel: 1               # 提取指定级别的标题到 frontmatter.title
  frontmatter-date:
    fieldName: date               # 日期字段名
  frontmatter-updated:
    fieldName: updated            # 更新日期字段名
  frontmatter-id:
    template: "{counter_global}"  # ID 生成模板:{counter_<id>} / {ff1} / {sha256_N} / {md5_N} / {sha1_N} / {uuid}
    fieldName: "id"              # ID 写入 frontmatter 的字段名
    prefix: ""                   # 最终 ID 前缀,追加到渲染结果头部
    counter:                     # counter 格式配置,key 为 counter id
      global:
        length: 6                # ID 位数(默认 6)
        radix: 36                # 进制 2-36(默认 36)
    ff1:                         # 仅 template 含 {ff1} 时生效
      useCounter: "global"       # 引用的 counter id
      encryptionKey: ""          # FPE 加密密钥
      withChecksum: false        # 是否添加 Luhn 校验码
      length: 6                  # 输出长度(默认继承 counter 配置)
      radix: 36                  # 进制 2-36(默认继承 counter 配置)

  # Frontmatter slug
  # 注意: transform 策略通过 [^a-z0-9-] 过滤字符,
  # CJK(中文等非 ASCII 字符)会被完全删除而非转拼音。
  # 如需处理中文标题,请使用 ai 策略或后续扩展支持。
  frontmatter-slug:
    strategy: transform            # transform | extract | ai
    transform:                     # strategy=transform 时生效
      fromField: title             # 源字段
      separator: "-"               # 分隔符
      lowercase: true              # 转为小写
      maxLength: 80                # 最大长度
    extract:                       # strategy=extract 时生效
      fromField: title             # 直接复制到 slug 的源字段
    ai:                            # strategy=ai 时生效
      useModel: deepseek-v4-flash  # AI 模型 ID(需在 ai.models 中配置)

  # Frontmatter 字段映射
  frontmatter-map:
    mappings:                      # 字段映射列表
      - from: title               # 源字段
        to: heading              # 目标字段
      - from: date
        to: created_at
    add: true                     # 是否添加缺失的字段

  # Frontmatter 验证
  frontmatter-validate:
    required: []                  # 必填字段列表
    types: {}                     # 字段类型校验

  # 文案纠正
  autocorrect:
    configPath: ".autocorrectrc"
    strict: false

  # 图片下载(可选,整块不配置则禁用下载功能)
  download-images:
    useStorage: default           # 引用 storages 中的哪个存储配置
    namingTemplate: "{name}.{ext}" # 本地保存命名模板
    concurrency: 5                # 并发下载数
    overwrite: false              # 是否覆盖已存在文件
    # domains:                  # 多源存储映射(可选)
    #   - domain: example.com
    #     useStorage: default

  # 清理未被引用的图片(可选,整块不配置则禁用清理功能)
  # 扫描 baseDirectory 下所有未被 Markdown 引用的 orphan 图片,批量清理
  cleanup-images:
    strategy: trash                # 删除策略:trash | move | hard-delete
    force: false                   # 强制删除(跳过引用检查)
    trashDir: ""                   # move 策略目标目录(可选,默认系统回收站)
    baseDirectory: ""              # 可选,默认应用层根目录
                                   # 绝对路径 /path/to/workspace
                                   # 相对路径 ./images(相对于应用层根目录)

  # 指定图片安全删除(可选,整块不配置则禁用删除功能)
  # 指定图片路径 → 安全检查(引用检测)→ 安全删除,支持批量
  delete-image:
    strategy: trash                # 删除策略:trash | move | hard-delete
    removeFromMarkdown: true       # 从引用该图片的 Markdown 中移除标记
    force: false                   # 强制删除(跳过引用检查)
    trashDir: ""                   # move 策略目标目录(可选,默认系统回收站)

  # 图片转移(可选,整块不配置则禁用转移功能)
  # 用于跨存储复制/移动图片(如从私有存储转到 CDN 存储)
  transfer-images:
    targetStorage:                # 目标存储配置
      useStorage: default         # 引用 storages 中的配置
      domain: ""                  # 自定义域名(可选),转移后 URL 替换为此域名
    sourceStorages:               # 源存储列表(可选,多源匹配)
      # - domain: old-cdn.example.com  # 源 URL 域名(用于匹配)
      #   useStorage: source-1          # 引用 storages 中的配置
    namingTemplate: "{name}.{ext}" # 目标存储命名模板
    prefix: ""                    # 目标存储路径前缀
    deleteSource: false           # 是否删除源文件(true=移动,false=复制)
    concurrency: 5                # 并发传输数
    maxConcurrentDownloads: 5     # 下载并发控制(可选)
    tempDir: ""                   # 临时目录(可选,默认系统临时目录)
    overwrite: false              # 是否覆盖目标文件(可选)

# ============================
# Presets(可选,整块不配置则无预设流程可用)
# Preset 是有序的 Rule 列表,用于一次运行多个处理步骤
# 格式:可以直接写 rule ID 列表,也可以带自定义配置
# ============================
presets:
  # 简单列表格式
  blog:
    - strip-frontmatter
    - promote-headings
    - add-section-numbers
    - upload-images

  # 带自定义配置的格式
  custom-example:
    name: "Custom Example"          # Preset 名称
    steps:                          # 规则步骤列表
      - id: text-replace
        config:
          match: 'TODO:\s*(.+)'
          replace: '[TODO] $1'
          flags: "gm"
      - id: upload-images

# 4. 配置模板

运行 cmtx config init 可生成初始配置文件。模板只包含必要配置,完整字段参考本文档。

# 5. 维护指南

# 5.1. 配置命名约定

配置文件采用分层命名约定:

层级 风格 示例
顶级 section key camelCase storages, presignedUrls, defaultModel
Rule ID(rules 下的 key) kebab-case upload-images, resize-image, add-section-numbers
Rule 内嵌字段 camelCase namingTemplate, conflictStrategy, useStorage, convertToHtml
TypeScript 接口字段 camelCase(与 YAML 字段同名) namingTemplate, conflictStrategy

设计原则:结构字段用 camelCase(映射 TypeScript 接口),Rule ID 用 kebab-case(面向用户的 YAML 标识符,可读性好)。Rule ID 由代码硬编码(rule.id),用户不可自定义。

新增 Rule 时:Rule ID 必须 kebab-case,对应 TypeScript 类型名保持同词序的 PascalCase(如 compress-imageCompressImageOptions)。

# 5.2. 新增环境变量

  1. packages/storage/src/credentials.ts 中添加读取逻辑
  2. 在本文档的环境变量表中添加条目

无需修改任何应用层文档(CLI / VS Code / MCP)。

# 5.3. 新增 YAML 配置字段

  1. packages/asset/src/config/types.ts 中添加类型定义和 DEFAULT_CONFIG 默认值
  2. 在本文档的 YAML 参考部分添加带注释的字段

无需修改任何应用层文档。

最后更新: 2026-07-31 19:58:33 +0800 在 GitHub 上编辑此页