Skip to content

feat(mail): HTML lint lib + Feishu-native autofix + lark-mail skill#3

Closed
bubbmon233 wants to merge 1 commit into
mainfrom
feat/lark-mail-bundle
Closed

feat(mail): HTML lint lib + Feishu-native autofix + lark-mail skill#3
bubbmon233 wants to merge 1 commit into
mainfrom
feat/lark-mail-bundle

Conversation

@bubbmon233
Copy link
Copy Markdown
Owner

@bubbmon233 bubbmon233 commented May 8, 2026

Summary

为 lark-cli mail 写信路径添加完整的 HTML 防御 + 飞书原生 autofix lint 体系,并立起 skills/lark-mail/ 一整套(5 个模板 / 2 篇 references / SKILL.md 入口)。

Changes

Lint library (shortcuts/mail/lint/)

新增 lint 包 + +lint-html shortcut + 写信路径强制 lint。

安全 / 兼容 / 飞书原生 三档 rule

  • error(删除):<script> / <iframe> / <form> / <input> / <link> / <object> / <embed>on* event handlers、javascript: / vbscript: / file: URL
  • warning + 自动修复:HTML4 过时标签 <font><span style><center><div text-align><marquee> / <blink><span>
  • inline style allowlist 过滤:保留 color / font-* / margin-* / padding-* / border-* / background-color / list-style-* / text-* / line-height / letter-spacing / vertical-align / cursor / opacity / transition / display / box-sizing / width-* / height-*

<style> tag passthrough:飞书 mail 服务端渲染时加 CSS scope 前缀(.msg-XXX <selector>),class 隔离不污染整体页面。

飞书原生 autofix pass(~550 行):

  • <p> → mail-editor 双层 div(外层 margin:4px 0;line-height:1.6 + 内层 dir="auto" style="font-size:14px"
  • <ul> / <ol> / <li>data-list-bullet/data-list-number marker + 5 件套 inline style + 内容双层 span 包裹
  • <blockquote> 灰边样式(padding-left:0px;color:rgb(100,106,115);border-left:2px solid rgb(187,191,196);margin:0px
  • <a>not-doclink class + 飞书蓝 rgb(20,86,240) + 无下划线
  • ol/ul 直接子节点 whitespace text node strip(pretty-print 缩进 / 换行不渲染为可见空行)

hasInlineStyleProp shorthand 识别:margin / padding shorthand margin:0 0 0 24px 视为已声明 margin-left,避免 autofix 误追加 margin-left:0 覆盖嵌套列表 24px 缩进。

写信路径强制 lint+send / +draft-create / +reply / +reply-all / +forward / +draft-edit body op 自动 autofix;新增 +lint-html shortcut 支持 --strict(0 finding 才返回成功)。

Lint 适用范围+reply / +reply-all / +forward 仅 lint 用户撰写的 body + signature 部分,原始邮件 quote 区(adit-html-block / history-quote-* / lark-mail-doc-quote 等飞书原生 markup)原样保留,避免 double-sanitize 破坏合法引用结构。

skills/lark-mail/ (parallel to skills/lark-slides/)

5 MVP 模板(pre-rendered 飞书原生,lint --strict 0 error):

  • newsletter--weekly-brief.html — 资讯周报(gradient banner / section 标签 / 文章卡)
  • weekly--personal-report.html — 个人周报(3 段 + <div padding-left:24px> 包 ul 缩进)
  • weekly--team-report.html — 团队周报(顶层 ol + 3 级嵌套 ul/ol shorthand margin + 共享 data-ol-id 跨 list 接续编号 + mention chips + 黄色高亮)
  • research--market-report.html — 市场调研报告(gradient header / 4 stat cards / 8 章节卡 + Bug 风险清单)
  • job-application--resume.html — 求职简历(9 sections / 技能 chip / table 个人信息 / 工作-项目 ol+ul 嵌套)

2 篇 references

  • lark-mail-html.md — 邮件 HTML 写法指南:文风规范 + LarkSuite 原生写法 7 铁律 + 4 档处理表 + tag/attr/CSS 白名单 + 可复制片段速查 + 错误示例 + 3 套场景模板
  • lark-mail-lint-html.md+lint-html 用法

入口SKILL.md HTML quickstart + assets/templates/README.md 列出 5 个预制模板,直接遍历目录选用即可,不附检索脚本(模板数量较少)

Conventions sealed

1. 飞书原生 HTML 7 铁律(lint autofix 实现,AI 写最简陋 HTML 即可,autofix 自动补全):

  • 段落用双层 div 嵌套(外层 4px margin + 内层 14px font-size),不用 <p>
  • <ul>/<ol> 必带 data-list-* marker + 5 件套 inline style;<ol> 必带 start="1"
  • <li> 必带 class(temp-li bullet1/number1) + data marker + 内容双层 span 包裹(<span style="font-family:inherit"><span style="color:rgb(0,0,0)">…</span></span>
  • ol/ul 直接子节点不能有空白 text node(lint 自动 strip pretty-print 缩进)
  • <blockquote> 左侧 2px 灰边样式
  • <a>class="not-doclink" + 飞书蓝 + 无下划线
  • HTML4 过时标签 <font>/<center>/<marquee>/<blink> 自动现代化

2. 多级缩进:lark-cli mail 写信路径推荐 <div style="padding-left:24px"> 包 ul/ol(lint 不动 div padding,最稳);mail-editor 原生 wrapper + inner shorthand margin:0 0 0 24px 也支持(lint shorthand 识别已修复)。子层 li class 降一级(bullet1bullet2bullet3 / number1number2),list-style-type 同步降级(disccirclesquare / decimallower-alpha

3. 父项加粗一致性:父项要么都加粗、要么都不加粗(hierarchy 靠 ol 数字编号 + ul circle 子项自然形成)。如需强调具体字段,用文字高亮替代加粗,避免破坏一致性

4. 状态文字嵌入式:参考徐龙 0613 周报样例 — 状态文字嵌入 li 末尾「,已完成 / 进行中 / 评审中 / 阻塞 / 待启动」,不用 badge / chip 标签(保持纯文本流,避免视觉碎片)

5. <style> 块透传:飞书 mail 服务端渲染时加 CSS scope 前缀,inline style allowlist 不支持的属性(gradient / box-shadow / flex / gap)放 <style> 块即可(research--market-report.html 即用此方案实现 gradient header + stat cards 视觉)

6. @用户 mention chip

<a id="at-user-N" href="mailto:user@bytedance.com"
   style="cursor:pointer;color:rgb(20,86,240);padding:2px;text-decoration:none;border-radius:999em;margin:0px 2px"
   rel="nofollow noopener noreferrer">@姓名</a>

id="at-user-N" 是唯一硬要求(飞书客户端 isAtUserDOM 只查 id?.startsWith('at-user'))。data-user-id 不写(OAPI 没合法路径拿真实 user-id)。业务方只填 mailto:@姓名 两处;OAPI 写信路径不触发 IM 通知 — mention chip 仅作客户端识别 + 视觉一致

7. 文字高亮(荧光笔风格):统一黑字 rgb(31,35,41) / 不加粗 / 不带 padding / 不带 border-radius。3 色 palette 按语义:

颜色 RGB 适用场景
粉色 rgb(255,200,220) 关键里程碑 / 重要数据
黄色 rgb(255,225,140) 待关注 / 阻塞 / 需跟进
浅绿 rgb(190,230,200) 已完成 / 关键成果

Test Plan

  • go test ./shortcuts/mail/lint/... ./shortcuts/mail/... 全绿(含 TestRun_FeishuListShorthandMarginPreserved 守护 nested-list 24px 缩进不被 autofix 覆盖)
  • 5 模板 lark-cli mail +lint-html --strict 0 error
  • 5 模板 lark-cli mail +draft-create smoke test 飞书 mail 视觉验收

Related Issues

  • None

@bubbmon233 bubbmon233 force-pushed the feat/lark-mail-bundle branch 16 times, most recently from ba31a8f to 4965946 Compare May 8, 2026 12:52
为 lark-cli mail 写信路径添加完整的 HTML 防御 + LarkSuite mail-editor 原生 autofix lint 体系,并立起 skills/lark-mail/ 一整套(5 个模板 / 2 篇 references / SKILL.md 入口)。

新增 lint 包 + `+lint-html` shortcut + 写信路径强制 lint。

安全 / 兼容 / 飞书原生 三档 rule:

- error(删除): <script> / <iframe> / <form> / <input> / <link> / <object> / <embed>、on* event handlers、javascript: / vbscript: / file: URL
- warning + 自动修复: HTML4 过时标签 <font> → <span style>、<center> → <div text-align>、<marquee> / <blink> → <span>
- inline style allowlist 过滤: 保留 color / font-* / margin-* / padding-* / border-* / background-color / list-style-* / text-* / line-height / letter-spacing / vertical-align / cursor / opacity / transition / display / box-sizing / width-* / height-*

<style> tag passthrough: 飞书 mail 服务端渲染时加 CSS scope 前缀(`.msg-XXX <selector>`),class 隔离不污染整体页面。

飞书原生 autofix pass (~550 lines):

- <p> → mail-editor 双层 div(外层 `margin:4px 0;line-height:1.6` + 内层 `dir="auto" style="font-size:14px"`)
- <ul> / <ol> / <li> 补 `data-list-bullet/data-list-number` marker + 5 件套 inline style + 内容双层 span 包裹(`<span style="font-family:inherit"><span style="color:rgb(0,0,0)">…</span></span>`)
- <blockquote> 灰边样式(`padding-left:0px;color:rgb(100,106,115);border-left:2px solid rgb(187,191,196);margin:0px`)
- <a> → `not-doclink` class + 飞书蓝 `rgb(20,86,240)` + 无下划线
- ol/ul 直接子节点 whitespace text node strip(pretty-print 缩进 / 换行不渲染为可见空行)

hasInlineStyleProp shorthand 识别: margin / padding shorthand `margin:0 0 0 24px` 视为已声明 margin-left,避免 autofix 误追加 `margin-left:0` 覆盖嵌套列表 24px 缩进。

写信路径强制 lint: `+send` / `+draft-create` / `+reply` / `+reply-all` / `+forward` / `+draft-edit` body op 自动 autofix;新增 `+lint-html` shortcut 支持 `--strict`(0 finding 才返回成功)。

5 MVP templates (pre-rendered Feishu-native, lint --strict 0 error):

- newsletter--weekly-brief.html — 资讯周报(gradient banner / section 标签 / 文章卡)
- weekly--personal-report.html — 个人周报(3 段 + `<div padding-left:24px>` 包 ul 缩进)
- weekly--team-report.html — 团队周报(顶层 ol + 3 级嵌套 ul/ol shorthand margin + 共享 `data-ol-id` 跨 list 接续编号 + mention chips + 黄色高亮)
- research--market-report.html — 市场调研报告(gradient header / 4 stat cards / 8 章节卡 + Bug 风险清单)
- job-application--resume.html — 求职简历(9 sections / 技能 chip / table 个人信息 / 工作-项目 ol+ul 嵌套)

2 篇 references:

- lark-mail-html.md — 邮件 HTML 写法指南:文风规范 + LarkSuite 原生写法 7 铁律 + 4 档处理表 + tag/attr/CSS 白名单 + 可复制片段速查 + 错误示例 + 3 套场景模板
- lark-mail-lint-html.md — `+lint-html` 用法

入口:SKILL.md HTML quickstart + assets/templates/README.md 列出 5 个预制模板。模板数量较少,AI 直接遍历 templates/ 目录选用即可,不附检索脚本。

@用户 mention chip:

  <a id="at-user-N" href="mailto:user@bytedance.com"
     style="cursor:pointer;color:rgb(20,86,240);padding:2px;text-decoration:none;border-radius:999em;margin:0px 2px"
     rel="nofollow noopener noreferrer">@姓名</a>

`id="at-user-N"` 是唯一硬要求(飞书客户端 isAtUserDOM 只查 `id?.startsWith('at-user')`)。`data-user-id` 不写(OAPI 没合法路径拿真实 user-id)。业务方只填 `mailto:` 和 `@姓名` 两处。

文字高亮(荧光笔风格): 统一黑字 `rgb(31,35,41)` / 不加粗 / 不带 padding / 不带 border-radius。3 色 palette 按语义:

- 粉色 `rgb(255,200,220)`: 关键里程碑 / 重要数据
- 黄色 `rgb(255,225,140)`: 待关注 / 阻塞 / 需跟进
- 浅绿 `rgb(190,230,200)`: 已完成 / 关键成果

- shortcuts/mail/lint/linter_test.go: 涵盖每条 rule 的 error / autofix / strict 模式 + cleaned HTML 对比断言;TestRun_FeishuListShorthandMarginPreserved 守护 nested-list 24px 缩进不被 autofix 覆盖
- shortcuts/mail/mail_lint_html_test.go + mail_lint_writepath_test.go: shortcut 端到端 + 写信路径强制 lint
- 5 个模板 lark-cli mail +lint-html --strict 0 error
- 5 个模板 lark-cli mail +draft-create smoke test 飞书 mail 视觉验收

`go test ./shortcuts/mail/lint/... ./shortcuts/mail/...` 全绿。

Change-Id: Ie1e54d6b4029526951a9f785547c8b93b6a6cb81
@bubbmon233 bubbmon233 force-pushed the feat/lark-mail-bundle branch from 4965946 to bd26efa Compare May 8, 2026 13:05
@bubbmon233
Copy link
Copy Markdown
Owner Author

Superseded by #4 (clean history, single commit, refreshed PR description). Closing.

@bubbmon233 bubbmon233 closed this May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant