Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,59 @@
# Changelog

## 0.6.0

### Features

- **`--url` 参数**:`download` / `dl` 与 `get-titles` 支持显式传入 `--url <url>`,原位置参数仍兼容但会提示废弃,便于脚本和 Agent 统一命令形态
- **Markdown 输出行数限制**:新增 `--max-output-lines` 与 `LARK_DOCX2MD_MAX_OUTPUT_LINES`,未指定标题过滤时可限制输出规模;超限会提示先用 `get-titles` 获取标题,再补充标题过滤参数重试
- **`get-titles` text 格式说明**:text 输出文件开头增加 YAML front matter,说明标题行格式与使用 `blockId` 继续过滤的命令

### Fixed

- **`get-titles` 非文档链接提示**:对 sheets 链接提前给出明确错误,避免继续进入不适用的标题读取流程
- **飞书 URL 错误提示**:优化不支持链接的报错信息,明确支持的 wiki / docx / docs / sheets 链接类型

### Changed

- **`get-titles` 输出格式简化**:保留 `text` 与 `yaml` 两种输出格式,默认改为 `text`,减少 AI/脚本选择目标标题时的噪音
- **Agent local 输出提示增强**:`--agent local` 输出文件路径时附带 Markdown 行数,便于判断是否需要进一步按标题过滤
- **CLI 与公共库模块拆分**:将命令注册、参数解析、业务处理与 converter、client、logger、types、URL 解析、标题过滤等公共模块拆分整理,便于后续维护与测试
- **Skill 文档迁移**:将 skill 使用说明迁移至 `skills/lark-docx2md/README.md`,并同步 `--agent local` 工作流

## 0.6.0-beta.1

### Changed

- **CLI 模块拆分**:将命令注册、参数解析与业务处理拆分到 `src/cli` 模块,CLI 入口仅负责启动,便于后续维护与测试
- **公共库目录调整**:将 converter、client、logger、types、URL 解析与标题过滤等公共模块迁移到 `src/lib`,并同步更新构建入口
- **CLI 参数测试补充**:新增 CLI options 单元测试,覆盖 agent、白板格式、图片模式、标题过滤与输出行数限制等参数解析逻辑

## 0.6.0-beta.0

### Features

- **`--url` 参数**:`download` / `dl` 与 `get-titles` 支持显式传入 `--url <url>`,原位置参数仍兼容但会提示废弃,便于脚本和 Agent 统一命令形态
- **Markdown 输出行数限制**:新增 `--max-output-lines` 与 `LARK_DOCX2MD_MAX_OUTPUT_LINES`,未指定标题过滤时可限制输出规模;超限会提示先用 `get-titles` 获取标题,再补充标题过滤参数重试

### Fixed

- **`get-titles` 非文档链接提示**:对 sheets 链接提前给出明确错误,避免继续进入不适用的标题读取流程
- **飞书 URL 错误提示**:优化不支持链接的报错信息,明确支持的 wiki / docx / docs / sheets 链接类型

### Changed

- **`get-titles` 输出格式简化**:保留 `text` 与 `yaml` 两种输出格式,默认改为 `text`,减少 AI/脚本选择目标标题时的噪音
- **Agent local 输出提示增强**:`--agent local` 输出文件路径时附带 Markdown 行数,便于判断是否需要进一步按标题过滤
- **Skill 文档迁移**:将 skill 使用说明迁移至 `skills/lark-docx2md/README.md`,并同步 `--agent local` 工作流

## 0.5.3

### Features

- **`--filter-title-block-id` 精确过滤**:新增 CLI 选项与 `ConvertOptions.filterTitleBlockId`,按 heading 块 id 严格匹配目标章节,彻底规避同名标题歧义;与 `--filter-title` 互斥
- **`get-titles` 子命令**:一键列出 docx/wiki 文档全部标题(1~9 级),支持 `yaml` / `yaml-tree` / `json` / `tree` / `text` 五种输出格式与 `--max-level` 限级;不支持 sheets
- **`get-titles` 子命令**:一键列出 docx/wiki 文档全部标题(1~9 级),支持 `text` / `yaml` 两种输出格式与 `--max-level` 限级;不支持 sheets
- **`--filter-title` / `--filter-title-block-id` 注入父级标题**:命中深层标题时,自动把所有更高层级的祖先标题(仅 heading 块本身)按文档顺序一并输出,保留章节层级上下文;顶级命中不注入,跳级不伪造中间层,旁支兄弟自动排除
- **标题元信息结构化**:导出 `HeadingInfo`(`blockId` / `level` / `text`),`--filter-title` 未命中时错误信息改为与 `get-titles` 同形的 yaml 清单,AI/脚本可直接据此重选 blockId,形成错误恢复闭环
- **标题元信息结构化**:导出 `HeadingInfo`(`blockId` / `level` / `text`),`--filter-title` 未命中时错误信息改为紧凑 text 标题清单,AI/脚本可直接据此重选 blockId,形成错误恢复闭环

### Fixed

Expand Down
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,36 @@
> 命令所需权限见下 ‘飞书自创应用需要的权限’

```bash
npx -y lark-docx2md@latest download https://xxx.feishu.cn/wiki/xxx --app-id cli_xxx --app-secret xxxx
npx -y lark-docx2md@latest download --url https://xxx.feishu.cn/wiki/xxx --app-id cli_xxx --app-secret xxxx
```

> `download` 命令支持别名 `dl`,以下写法等效:
>
> ```bash
> npx -y lark-docx2md@latest dl https://xxx.feishu.cn/wiki/xxx --app-id cli_xxx --app-secret xxxx
> npx -y lark-docx2md@latest dl --url https://xxx.feishu.cn/wiki/xxx --app-id cli_xxx --app-secret xxxx
> ```

或先设置环境变量(命令行参数可省略):

```bash
export LARK_DOCX2MD_APP_ID=<APP_ID>
export LARK_DOCX2MD_APP_SECRET=<APP_SECRET>
npx -y lark-docx2md@latest download <url>
npx -y lark-docx2md@latest download --url <url>
```

## 参数

| 参数 | 说明 | 环境变量 | 默认值 |
|--------------------------|-------------------------------------------|------------------------------|-----------------------|
| `<url>` | 飞书文档链接(`https://*.feishu.cn/wiki/*` 或 `/sheets/*`,支持 `?sheet=<sheetId>` 指定子表) | — | — |
| `--url <url>` | 飞书文档链接(`https://*.feishu.cn/wiki/*` 或 `/sheets/*`,支持 `?sheet=<sheetId>` 指定子表) | — | — |
| `--app-id <id>` | 飞书应用 App ID | `LARK_DOCX2MD_APP_ID` | — |
| `--app-secret <secret>` | 飞书应用 App Secret | `LARK_DOCX2MD_APP_SECRET` | — |
| `-o, --output <dir>` | 输出目录 | `LARK_DOCX2MD_OUTPUT` | `./larkDocx2mdOutput` |
| `--agent [mode]` | Agent 模式:日志 ERROR。不传值(或 `=stdout`)为在线模式,Markdown 输出到 stdout;传 `local` 则落盘后输出引导 AI 读取的提示词 | `LARK_DOCX2MD_AGENT=stdout\|local` | `false` |
| `--image-mode <mode>` | 图片处理模式:`local`(下载到本地)或 `online`(24h 临时链接) | `LARK_DOCX2MD_IMAGE_MODE` | `local` |
| `--filter-title <title>` | 按标题过滤:仅转换匹配标题及其下级内容(匹配到同级或更高级标题时截止) | — | — |
| `--filter-title-block-id <id>` | 按 heading 块 id 精确过滤(无同名歧义),通常配合 `get-titles` 子命令获取;与 `--filter-title` 互斥 | — | — |
| `--max-output-lines <n>` | 未指定标题过滤时允许输出的最大 Markdown 行数;超过会报错并提示补充标题过滤参数 | `LARK_DOCX2MD_MAX_OUTPUT_LINES` | — |
| `--wb-format <format>` | 画板输出格式:`base64`、`inline-svg`、`svg`、`yaml` | `LARK_DOCX2MD_WB_FORMAT` | `svg`(agent 下默认 `yaml`) |
| `--wb-bg <style>` | 画板 SVG 背景:`none`、`dot` 或颜色值如 `#fff` | `LARK_DOCX2MD_WB_BG` | `none` |
| `--wb-image-mode <mode>` | 画板图片模式:`online`、`base64` 或 `local` | `LARK_DOCX2MD_WB_IMAGE_MODE` | `local` |
Expand All @@ -55,26 +56,27 @@ npx -y lark-docx2md@latest download <url>
> - `--agent`(在线):强制 `--image-mode=online`、`--wb-image-mode=online`;`--wb-format` 默认 `yaml`,仅允许 `inline-svg` / `yaml`;转换完成后 Markdown 直接通过 stdout 输出。
> - `--agent local`:强制 `--image-mode=local`、`--wb-image-mode=local`(Markdown、图片、画板中的图片均落盘);`--wb-format` 默认 `yaml`,仅允许 `inline-svg` / `yaml`;stdout 输出引导 AI 读取文件的提示词(包含绝对路径)。
> - 非 agent 模式下 `--wb-format yaml` 时:`--wb-image-mode` 强制为 `online`。
> - `--filter-title`:按标题文本精确匹配(忽略前后空格),收集该标题及其所有子级块,遇到同级或更高级标题时停止。同名标题取首个;未匹配时错误信息附全文标题 yaml 清单。
> - `--filter-title`:按标题文本精确匹配(忽略前后空格),收集该标题及其所有子级块,遇到同级或更高级标题时停止。同名标题取首个;未匹配时错误信息附全文标题 text 清单。
> - `--filter-title-block-id`:按 heading 块 id 严格相等匹配,适用于同名标题或脚本化场景;通常先用 `get-titles` 查出目标 `blockId` 再传入。与 `--filter-title` 互斥。
> - `--max-output-lines`:仅在未指定 `--filter-title` / `--filter-title-block-id` 时生效;纯 Markdown 阶段先检查一次,图片、画板、表格等解析完成后再检查一次。超过限制时直接报错,提示先用 `get-titles` 获取标题,再补充标题过滤参数重试。
> - **命中深层标题时自动注入父级标题(仅 heading 块本身)**:两个过滤参数均会按文档顺序补齐包含路径上的顶层→该标题的所有祖先标题,以保留章节层级上下文;不会引入旁支兄弟或伪造跳级。

## 子命令:`get-titles`

列出 docx/wiki 文档全部标题(不支持 sheets),配合 `--filter-title-block-id` 使用可避开同名歧义。

```bash
npx -y lark-docx2md@latest get-titles --agent <url>
npx -y lark-docx2md@latest get-titles --agent --url <url>
```

| 参数 | 说明 | 默认值 |
|-----------------------|------------------------------------------------------------------------------------------|--------|
| `<url>` | 飞书 wiki/docx URL | — |
| `--url <url>` | 飞书 wiki/docx URL | — |
| `--max-level <n>` | 仅输出 `level <= n` 的标题(1~9) | `9` |
| `--format <format>` | 输出格式:`yaml`(扁平) \| `yaml-tree`(嵌套) \| `json` \| `tree`(json 嵌套) \| `text`(缩进的 markdown 标题) | `yaml` |
| `--format <format>` | 输出格式:`text`(YAML front matter + `## [blockId] 标题`) \| `yaml`(嵌套) | `text` |
| `--agent [mode]` | 同 `dl`,降低日志级别 | — |

输出包含 `blockId` / `level` / `text`,可被 AI 直接消费用于选择目标章节(嵌套关系由 `yaml-tree` / `tree` 格式天然表达)。
`text` 格式文件开头包含 YAML front matter 格式说明;正文用 `#` 数量保留标题层级,并把 `blockId` 放在标题旁,便于 AI 直接选择目标章节。

## 功能

Expand Down Expand Up @@ -126,10 +128,10 @@ npx -y lark-docx2md@latest get-titles --agent <url>

```bash
# 直接运行(无需构建),download 可使用别名 dl
pnpm dev download --app-id <APP_ID> --app-secret <APP_SECRET> <url>
pnpm dev download --app-id <APP_ID> --app-secret <APP_SECRET> --url <url>

# 或使用环境变量
LARK_DOCX2MD_APP_ID=<APP_ID> LARK_DOCX2MD_APP_SECRET=<APP_SECRET> pnpm dev dl <url>
LARK_DOCX2MD_APP_ID=<APP_ID> LARK_DOCX2MD_APP_SECRET=<APP_SECRET> pnpm dev dl --url <url>

# 构建为 JS
pnpm build
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lark-docx2md",
"version": "0.5.3",
"version": "0.6.0",
"description": "Convert Lark/Feishu documents to Markdown",
"type": "module",
"main": "./dist/converter.js",
Expand Down
46 changes: 0 additions & 46 deletions skills/README.md

This file was deleted.

98 changes: 98 additions & 0 deletions skills/lark-docx2md/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# lark-docx2md

将飞书文档或电子表格链接转换为本地 Markdown 内容,供 AI 读取、分析与落地实现。

## 能力范围

- 支持链接:
- `https://*.feishu.cn/wiki/...`
- `https://*.feishu.cn/docx/...`
- `https://*.feishu.cn/docs/...`
- `https://*.feishu.cn/sheets/...`(可带 `?sheet=xxx`)
- 支持整篇下载,也支持按“标题/章节”精准下载(`wiki/docx/docs`)。
- 下载后可读取 Markdown 及其引用图片(含 `static/*.png` 等资源)。

## 前置条件

### 1. 环境变量

```bash
export LARK_DOCX2MD_APP_ID="cli_xxx"
export LARK_DOCX2MD_APP_SECRET="xxx"
# 可选:限制未指定标题过滤时的最大 Markdown 输出行数
export LARK_DOCX2MD_MAX_OUTPUT_LINES="800"
```

- `LARK_DOCX2MD_APP_ID`:飞书自建应用 App ID(或 Key)
- `LARK_DOCX2MD_APP_SECRET`:飞书自建应用密钥
- `LARK_DOCX2MD_MAX_OUTPUT_LINES`:可选,正整数。未指定标题过滤时限制允许输出的最大 Markdown 行数,超过限制会报错并提示先获取标题、再补充标题过滤参数重试。

### 2. 应用权限与可见范围

- 飞书应用需具备访问目标文档/表格的权限。
- 目标文档需要对该应用可见(常见做法:把应用加入可访问范围,或将文档授权给应用)。

## 使用方式

当用户输入包含飞书链接的需求时,技能会按以下流程自动执行。

### 场景 A:`/sheets/` 链接或未指定标题

直接下载整份内容:

```bash
npx -y lark-docx2md@latest dl --agent local --url "<url>"
```

### 场景 B:`wiki/docx/docs` 且指定了标题

1. 获取标题列表:

```bash
npx -y lark-docx2md@latest get-titles --agent local --url "<url>"
```

2. 匹配目标标题,拿到 `blockId`。
3. 按标题块下载:

```bash
npx -y lark-docx2md@latest dl --agent local --filter-title-block-id "<blockId>" --url "<url>"
```

## 标题识别规则(给调用方)

以下表达会被识别为“只取某章节”:

- 显式关键词:`标题/章节/小节/部分/节选/只要/其中的 ...`
- 引号包裹:`"xxx"`、`“xxx”`、`《xxx》` 等
- 介词结构:`X 中的 Y`、`关于 X 的内容`
- 多级路径:`A > B`、`A/ B`、`A → B`

以下情况会回退为整篇下载:

- 用户明确说“完整/全部/整篇”
- 无法稳定抽取到明确标题

## 最小示例

- 整篇读取:
- `根据 https://xxx.feishu.cn/wiki/abc123 输出实现方案`
- 指定章节读取:
- `基于 https://xxx.feishu.cn/docx/abc123 里“接口定义”这一节生成 TypeScript 类型`
- 读取表格:
- `分析 https://xxx.feishu.cn/sheets/abc123?sheet=xxx 并生成数据字典`

## 常见问题

- 报权限/401/403:
- 检查 `LARK_DOCX2MD_APP_ID`、`LARK_DOCX2MD_APP_SECRET` 是否正确。
- 检查飞书应用是否有文档访问权限,文档是否对应用可见。
- 指定标题没命中:
- 先执行 `get-titles` 查看可用标题,再按准确文案重试。
- 命令可执行但无内容:
- 确认链接可在当前账号/应用上下文访问,且不是失效分享链接。

## 备注

- `dl` 与 `get-titles` 均需带 `--agent local`。
- 本技能重点是“读取并结构化飞书内容”,不负责业务语义正确性校验。
Loading
Loading