PicoBot/skills/lark-mail/references/lark-mail-lint-html.md
ooodc a7883dbed9 refactor(todo): 重构待办事项管理逻辑及更新状态规则
- 移除 TodoItem 中的 priority、created_at 和 updated_at 字段
- 强制每个任务都必须有唯一 id,且由用户负责生成
- 修改合并模式逻辑,merge=true 下保留未提及的旧任务
- 支持已完成和已取消任务重新激活(状态改回 pending 或 in_progress)
- 禁止 in_progress 状态退回到 pending,必须标记为 completed 或 cancelled
- 优化状态转换校验,允许特定状态间合法切换
- 简化任务变更消息,移除详细的新增/更新/移除统计
- 更新文档和示例,明确 id 必须由用户生成和使用
- 修复和补充测试,增强状态转换和合并模式验证
- 调整任务时间戳生成逻辑,统一使用当前时间及索引
- 该变更提供更合理的任务状态机械及管理模式,提升稳定性和易用性
2026-06-13 09:22:33 +08:00

7.3 KiB
Raw Blame History

mail +lint-html

前置条件: 先阅读 ../../lark-shared/SKILL.md 了解通用安全规则。

作用

+lint-html 是邮件 HTML 正文的本地预检工具read-only无网络 IO

  • 校验 HTML 是否符合飞书邮箱的兼容性 / 安全 / 原生写法要求;
  • 自动修复非法或不规范写法autofix 始终启用),输出 cleaned_html
  • 不写入任何邮箱状态,不调用任何 OAPI。

写信链路(+send / +draft-create / +reply / +reply-all / +forward / +draft-edit body op强制内置同一份 lint提交前会自动净化 HTML。默认 envelope 不携带任何 lint 字段以保持响应小巧;加 --show-lint-details 可拿到完整 lint_applied[] / original_blocked[] 两个 Finding 数组(不再返回任何 *_count 字段,调用方需要 count 时 len(arr) 即可,详见 邮件 HTML 写法指南)。本命令是写信链路 lint 的预览版,行为一致,调用更轻量,适合:

  • AI / 用户在创建草稿前自检 HTML 会被怎么改写;
  • CI 流水线把 HTML 模板当作产物校验。

命令

# 直接传 HTML
lark-cli mail +lint-html --body '<p>正文</p>'

# 从文件读 HTML路径必须在 cwd 子树内)
lark-cli mail +lint-html --body-file ./template.html

# 查看完整 lint 详情
lark-cli mail +lint-html --body-file ./template.html --show-lint-details

参数

参数 必填 说明
--body <html> 二选一 待检查的 HTML 内容
--body-file <path> 二选一 从文件读取 HTML仅支持 cwd 子树(绝对路径 / .. 越出 cwd 会被拒)
--show-lint-details 默认 falsetrue 时 envelope 同时返回 warnings[] / errors[] 完整 Finding 数组;默认仅返回 cleaned_html,避免复杂模板触发数十条装饰性 warning 把响应撑大几千 token
--format <fmt> json(默认)/ pretty / table / csv / ndjson
--jq <expr> 对返回 JSON 用 jq 表达式过滤
--dry-run 不执行 lint仅返回 dry-run 描述

返回值

默认 envelope(仅 cleaned_htmltoken-frugal

{
  "ok": true,
  "data": {
    "cleaned_html": "<p>...</p>"
  }
}

--show-lint-details

{
  "ok": true,
  "data": {
    "cleaned_html": "<p>...</p>",
    "warnings": [
      { "rule_id": "...", "severity": "warning", "tag_or_attr": "...", "excerpt": "...", "hint": "..." }
    ],
    "errors": [
      { "rule_id": "...", "severity": "error", "tag_or_attr": "...", "excerpt": "...", "hint": "..." }
    ]
  }
}
字段 说明
cleaned_html 修复后的 HTMLautofix 始终启用warning 已自动改写error 已删除
warnings[] 警告级 finding 数组(--show-lint-details 时返回)。无违规时输出 []
errors[] 错误级 finding 数组(--show-lint-details 时返回)。无违规时输出 []

每条 finding 含:

字段 说明
rule_id 规则编号UPPER_SNAKE_CASE
severity "warning""error"
tag_or_attr 触发规则的 tag / attribute / style.<property>
excerpt HTML 片段(最多 200 字节,超出截断)
hint 可读的修复说明

调用示例

下面是用 lark-cli mail +lint-html --body '<INPUT>' --show-lint-details 实跑得到的典型 case--show-lint-details 才能看到 finding默认只返回 cleaned_html),覆盖 error 类(强制删)和 warning 类(自动修复)。

Error 类(强制删除,写信链路也会拒)

1. <script> 整段删除

输入:

<script>alert(1)</script>正文

输出:

正文

原因:<script> 有 XSS 风险,整段丢弃。

2. javascript: URL 删除

输入:

<a href="javascript:void(0)">click</a>

输出:

<a class="not-doclink" style="cursor:pointer;text-decoration:none;color:rgb(20,86,240)">click</a>

原因:javascript: scheme 是 XSS 入口,href 属性被剥。

3. on* 事件 handler 删除

输入:

<p onclick="alert(1)">hi</p>

输出:

<div style="margin-top:4px;margin-bottom:4px;line-height:1.6"><div dir="auto" style="font-size:14px">hi</div></div>

原因inline event handleronclick / onerror 等)是脚本注入入口,属性被剥。

Warning 类(自动修复,视觉无差异)

4. <font><span style>

输入:

<font color="red" size="3"></font>

输出:

<span style="color:red; font-size:16px"></span>

原因:<font> 是 HTML4 过时标签,飞书 mail-editor 用 inline style 表达字号 / 颜色。

5. <p> 段落容器原生化

输入:

<p>正文</p>

输出:

<div style="margin-top:4px;margin-bottom:4px;line-height:1.6"><div dir="auto" style="font-size:14px">正文</div></div>

原因:飞书 mail-editor 段落实际是双层 div外层定 margin / line-height内层定 font-size

6. <ul>/<li> 列表原生化

输入:

<ul><li>第一项</li></ul>

输出:

<ul style="margin-top:0px;margin-bottom:0px;margin-left:0px;padding-left:0px;list-style-position:inside" data-list-bullet="true"><li class="temp-li bullet1" data-li-line="true" data-list="bullet1" style="line-height:1.6;margin-top:0px;margin-bottom:0px;padding-left:0px;display:list-item;list-style-type:disc;font-family:inherit;font-size:14px;margin-left:0px;list-style-position:inside" dir="auto"><span style="font-family:inherit"><span style="color:rgb(0,0,0)">第一项</span></span></li></ul>

原因:飞书 native list-block 要求 <ul> / <li> 补全 class + data marker + 双层 span 包裹,否则 li 之间会出现可见空行。

7. <blockquote> 加灰边 + 灰文字

输入:

<blockquote>引用</blockquote>

输出:

<blockquote style="padding-left:0px;color:rgb(100,106,115);border-left:2px solid rgb(187,191,196);margin:0px">引用</blockquote>

原因:补飞书原生引用样式(左侧 2px 灰边 + 灰色文字)。

输入:

<a href="https://example.com">link</a>

输出:

<a href="https://example.com" class="not-doclink" style="cursor:pointer;text-decoration:none;color:rgb(20,86,240)">link</a>

原因:补 not-doclink class防误识为内部 doc share+ LarkSuite 品牌蓝 + 无下划线。

9. 非白名单 CSS property 删除

输入:

<p style="position:absolute;color:red">x</p>

输出:

<div style="color:red;margin-top:4px;margin-bottom:4px;line-height:1.6"><div dir="auto" style="font-size:14px">x</div></div>

原因:position 不在 inline style 白名单内被剔除,color 保留。

相关命令