lark-docx2md 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/{converter-Bxdyw2k9.d.ts → converter-C_2JDVY1.d.ts} +2 -1
- package/dist/converter-C_2JDVY1.d.ts.map +1 -0
- package/dist/{converter-C5Nrkvfa.js → converter-jW2Zu4Pb.js} +29 -25
- package/dist/converter-jW2Zu4Pb.js.map +1 -0
- package/dist/converter.js +1 -1
- package/package.json +7 -8
- package/dist/converter-Bxdyw2k9.d.ts.map +0 -1
- package/dist/converter-C5Nrkvfa.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
将飞书文档转换为 Markdown 文件的命令行工具。
|
|
6
6
|
|
|
7
|
-
> 支持的飞书文档链接格式:`https://*.feishu.cn/wiki/*`、`https://*.feishu.cn/sheets
|
|
7
|
+
> 支持的飞书文档链接格式:`https://*.feishu.cn/wiki/*`、`https://*.feishu.cn/sheets/*`(支持 `?sheet=<sheetId>` 指定子表)
|
|
8
8
|
|
|
9
9
|
## 使用
|
|
10
10
|
|
|
@@ -32,7 +32,7 @@ npx -y lark-docx2md@latest download <url>
|
|
|
32
32
|
|
|
33
33
|
| 参数 | 说明 | 环境变量 | 默认值 |
|
|
34
34
|
|--------------------------|-------------------------------------------|------------------------------|-----------------------|
|
|
35
|
-
| `<url>` | 飞书文档链接(`https://*.feishu.cn/wiki/*` 或 `/sheets
|
|
35
|
+
| `<url>` | 飞书文档链接(`https://*.feishu.cn/wiki/*` 或 `/sheets/*`,支持 `?sheet=<sheetId>` 指定子表) | — | — |
|
|
36
36
|
| `--app-id <id>` | 飞书应用 App ID | `LARK_DOCX2MD_APP_ID` | — |
|
|
37
37
|
| `--app-secret <secret>` | 飞书应用 App Secret | `LARK_DOCX2MD_APP_SECRET` | — |
|
|
38
38
|
| `-o, --output <dir>` | 输出目录 | `LARK_DOCX2MD_OUTPUT` | `./larkDocx2mdOutput` |
|
|
@@ -55,7 +55,7 @@ npx -y lark-docx2md@latest download <url>
|
|
|
55
55
|
- 输出标准 Markdown 文件
|
|
56
56
|
- 支持飞书画板,输出格式:`base64`(data URI 内嵌)、`inline-svg`(SVG 标签内嵌)、`svg`(独立文件)、`yaml`(AI
|
|
57
57
|
友好结构化数据)。详见 [画板支持说明](./WHITEBOARD.md)
|
|
58
|
-
- 支持飞书电子表格(独立 sheet URL 或 docx 内嵌 sheet 块),输出 GFM
|
|
58
|
+
- 支持飞书电子表格(独立 sheet URL 或 docx 内嵌 sheet 块),输出 GFM 表格,自动展开合并单元格;支持 `?sheet=<sheetId>` 仅处理指定子表。详见 [电子表格支持说明](./SHEET.md)
|
|
59
59
|
|
|
60
60
|
### 支持的内容块类型
|
|
61
61
|
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { r as setLogLevel, t as convert } from "./converter-
|
|
2
|
+
import { r as setLogLevel, t as convert } from "./converter-jW2Zu4Pb.js";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import { LoggerLevel } from "@larksuiteoapi/node-sdk";
|
|
5
5
|
//#region src/cli.ts
|
|
@@ -59,7 +59,7 @@ program.command("download").alias("dl").description("Download a wiki document to
|
|
|
59
59
|
wbFormat: opts.wbFormat,
|
|
60
60
|
agent: agentLocal ? "local" : opts.agent === true
|
|
61
61
|
});
|
|
62
|
-
if (agentLocal) process.stdout.write(
|
|
62
|
+
if (agentLocal) process.stdout.write(`**The Feishu document has been downloaded to the following absolute path:**\n\n\`${result.filePath}\`\n\n**Read this file to access the full markdown content.**\n`);
|
|
63
63
|
else if (opts.agent === true) process.stdout.write(result.markdown);
|
|
64
64
|
});
|
|
65
65
|
program.parse();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { LoggerLevel } from '@larksuiteoapi/node-sdk';\nimport { convert } from './converter.js';\nimport { setLogLevel } from './logger.js';\nimport type { SvgBackground, WbFormat, WbImageMode } from './types.js';\n\nconst program = new Command();\nprogram.name('larkDocx2md').description('Download Lark/Feishu documents to markdown');\n\nprogram\n .command('download')\n .alias('dl')\n .description('Download a wiki document to markdown')\n .option('--app-id <id>', 'Feishu app ID (or read from LARK_DOCX2MD_APP_ID)')\n .option('--app-secret <secret>', 'Feishu app secret (or read from LARK_DOCX2MD_APP_SECRET)')\n .option('-o, --output <dir>', 'Output directory (or LARK_DOCX2MD_OUTPUT)')\n .option('--agent [mode]', 'Enable agent mode: ERROR log level, and AI-oriented stdout. Pass \"local\" to save markdown/images/whiteboards to disk and print a read-file prompt (or LARK_DOCX2MD_AGENT=true|local)')\n .option('--wb-format <format>', 'Whiteboard output format: \"base64\", \"inline-svg\", \"svg\", or \"yaml\" (or LARK_DOCX2MD_WB_FORMAT)')\n .option('--wb-bg <style>', 'Whiteboard SVG background: \"none\", \"dot\", or a color like \"#fff\" (or LARK_DOCX2MD_WB_BG)')\n .option('--wb-image-mode <mode>', 'Whiteboard image mode: \"online\", \"base64\", or \"local\" (or LARK_DOCX2MD_WB_IMAGE_MODE)')\n .option('--image-mode <mode>', 'Image handling mode: \"local\" or \"online\" (or LARK_DOCX2MD_IMAGE_MODE)')\n .argument('<url>', 'Feishu wiki document URL: https://*.feishu.cn/wiki/*')\n .action(async (url: string, opts: { appId?: string; appSecret?: string; output?: string; agent?: boolean | string; imageMode?: string; wbImageMode?: string; wbBg?: SvgBackground; wbFormat?: string }) => {\n // ─── 环境变量默认值(直接指定 > 环境变量 > 内置默认值)────────────────\n opts.appId = opts.appId ?? process.env.LARK_DOCX2MD_APP_ID;\n opts.appSecret = opts.appSecret ?? process.env.LARK_DOCX2MD_APP_SECRET;\n opts.output = opts.output ?? process.env.LARK_DOCX2MD_OUTPUT ?? './larkDocx2mdOutput';\n // 解析 --agent:可能为 undefined | true | 'local' | 其他字符串\n if (opts.agent === undefined) {\n const envAgent = process.env.LARK_DOCX2MD_AGENT;\n if (envAgent === 'true') opts.agent = true;\n else if (envAgent === 'local') opts.agent = 'local';\n else opts.agent = false;\n } else if (typeof opts.agent === 'string' && opts.agent !== 'local') {\n program.error(`Invalid --agent value \"${opts.agent}\", only \"local\" is supported (or omit the value)`);\n }\n const agentEnabled = opts.agent === true || opts.agent === 'local';\n const agentLocal = opts.agent === 'local';\n\n opts.imageMode = opts.imageMode ?? process.env.LARK_DOCX2MD_IMAGE_MODE ?? 'local';\n opts.wbFormat = opts.wbFormat ?? process.env.LARK_DOCX2MD_WB_FORMAT;\n opts.wbBg = opts.wbBg ?? process.env.LARK_DOCX2MD_WB_BG ?? 'none';\n opts.wbImageMode = opts.wbImageMode ?? process.env.LARK_DOCX2MD_WB_IMAGE_MODE ?? 'local';\n\n // 设置 wb-format 默认值:--agent local 默认 inline-svg(兼容本地画板图片),--agent(在线)默认 yaml,其余 svg\n if (!opts.wbFormat) {\n opts.wbFormat = agentEnabled ? 'yaml' : 'svg';\n }\n\n if (agentEnabled) {\n setLogLevel(LoggerLevel.error);\n if (agentLocal) {\n // --agent local:图片/画板图片均落盘\n opts.imageMode = 'local';\n opts.wbImageMode = 'local';\n } else {\n // --agent(在线):一律在线,且画板仅支持内嵌形式\n opts.imageMode = 'online';\n opts.wbImageMode = 'online';\n }\n if (!['inline-svg', 'yaml'].includes(opts.wbFormat)) {\n program.error(`Agent mode only supports \"inline-svg\" or \"yaml\" for --wb-format`);\n }\n } else {\n // yaml 格式图片仅支持 online\n if (opts.wbFormat === 'yaml') {\n opts.wbImageMode = 'online';\n }\n }\n\n if (opts.imageMode && !['local', 'online'].includes(opts.imageMode)) {\n program.error(`Invalid --image-mode \"${opts.imageMode}\", must be \"local\" or \"online\"`);\n }\n if (!['base64', 'inline-svg', 'svg', 'yaml'].includes(opts.wbFormat)) {\n program.error(`Invalid --wb-format \"${opts.wbFormat}\", must be \"base64\", \"inline-svg\", \"svg\", or \"yaml\"`);\n }\n if (!['online', 'base64', 'local'].includes(opts.wbImageMode)) {\n program.error(`Invalid --wb-image-mode \"${opts.wbImageMode}\", must be \"online\", \"base64\", or \"local\"`);\n }\n\n const appId = opts.appId!;\n const appSecret = opts.appSecret!;\n if (!appId || !appSecret) {\n program.error('Missing credentials: pass --app-id/--app-secret or set LARK_DOCX2MD_APP_ID/LARK_DOCX2MD_APP_SECRET');\n }\n\n const result = await convert({\n appId,\n appSecret,\n url,\n output: opts.output,\n imageMode: opts.imageMode as 'local' | 'online',\n wbImageMode: opts.wbImageMode as WbImageMode,\n wbBg: opts.wbBg,\n wbFormat: opts.wbFormat as WbFormat,\n agent: agentLocal ? 'local' : (opts.agent === true),\n });\n\n if (agentLocal) {\n // 本地模式:输出引导 AI 读取文件的提示词(绝对路径)\n process.stdout.write(\n
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { LoggerLevel } from '@larksuiteoapi/node-sdk';\nimport { convert } from './converter.js';\nimport { setLogLevel } from './logger.js';\nimport type { SvgBackground, WbFormat, WbImageMode } from './types.js';\n\nconst program = new Command();\nprogram.name('larkDocx2md').description('Download Lark/Feishu documents to markdown');\n\nprogram\n .command('download')\n .alias('dl')\n .description('Download a wiki document to markdown')\n .option('--app-id <id>', 'Feishu app ID (or read from LARK_DOCX2MD_APP_ID)')\n .option('--app-secret <secret>', 'Feishu app secret (or read from LARK_DOCX2MD_APP_SECRET)')\n .option('-o, --output <dir>', 'Output directory (or LARK_DOCX2MD_OUTPUT)')\n .option('--agent [mode]', 'Enable agent mode: ERROR log level, and AI-oriented stdout. Pass \"local\" to save markdown/images/whiteboards to disk and print a read-file prompt (or LARK_DOCX2MD_AGENT=true|local)')\n .option('--wb-format <format>', 'Whiteboard output format: \"base64\", \"inline-svg\", \"svg\", or \"yaml\" (or LARK_DOCX2MD_WB_FORMAT)')\n .option('--wb-bg <style>', 'Whiteboard SVG background: \"none\", \"dot\", or a color like \"#fff\" (or LARK_DOCX2MD_WB_BG)')\n .option('--wb-image-mode <mode>', 'Whiteboard image mode: \"online\", \"base64\", or \"local\" (or LARK_DOCX2MD_WB_IMAGE_MODE)')\n .option('--image-mode <mode>', 'Image handling mode: \"local\" or \"online\" (or LARK_DOCX2MD_IMAGE_MODE)')\n .argument('<url>', 'Feishu wiki document URL: https://*.feishu.cn/wiki/*')\n .action(async (url: string, opts: { appId?: string; appSecret?: string; output?: string; agent?: boolean | string; imageMode?: string; wbImageMode?: string; wbBg?: SvgBackground; wbFormat?: string }) => {\n // ─── 环境变量默认值(直接指定 > 环境变量 > 内置默认值)────────────────\n opts.appId = opts.appId ?? process.env.LARK_DOCX2MD_APP_ID;\n opts.appSecret = opts.appSecret ?? process.env.LARK_DOCX2MD_APP_SECRET;\n opts.output = opts.output ?? process.env.LARK_DOCX2MD_OUTPUT ?? './larkDocx2mdOutput';\n // 解析 --agent:可能为 undefined | true | 'local' | 其他字符串\n if (opts.agent === undefined) {\n const envAgent = process.env.LARK_DOCX2MD_AGENT;\n if (envAgent === 'true') opts.agent = true;\n else if (envAgent === 'local') opts.agent = 'local';\n else opts.agent = false;\n } else if (typeof opts.agent === 'string' && opts.agent !== 'local') {\n program.error(`Invalid --agent value \"${opts.agent}\", only \"local\" is supported (or omit the value)`);\n }\n const agentEnabled = opts.agent === true || opts.agent === 'local';\n const agentLocal = opts.agent === 'local';\n\n opts.imageMode = opts.imageMode ?? process.env.LARK_DOCX2MD_IMAGE_MODE ?? 'local';\n opts.wbFormat = opts.wbFormat ?? process.env.LARK_DOCX2MD_WB_FORMAT;\n opts.wbBg = opts.wbBg ?? process.env.LARK_DOCX2MD_WB_BG ?? 'none';\n opts.wbImageMode = opts.wbImageMode ?? process.env.LARK_DOCX2MD_WB_IMAGE_MODE ?? 'local';\n\n // 设置 wb-format 默认值:--agent local 默认 inline-svg(兼容本地画板图片),--agent(在线)默认 yaml,其余 svg\n if (!opts.wbFormat) {\n opts.wbFormat = agentEnabled ? 'yaml' : 'svg';\n }\n\n if (agentEnabled) {\n setLogLevel(LoggerLevel.error);\n if (agentLocal) {\n // --agent local:图片/画板图片均落盘\n opts.imageMode = 'local';\n opts.wbImageMode = 'local';\n } else {\n // --agent(在线):一律在线,且画板仅支持内嵌形式\n opts.imageMode = 'online';\n opts.wbImageMode = 'online';\n }\n if (!['inline-svg', 'yaml'].includes(opts.wbFormat)) {\n program.error(`Agent mode only supports \"inline-svg\" or \"yaml\" for --wb-format`);\n }\n } else {\n // yaml 格式图片仅支持 online\n if (opts.wbFormat === 'yaml') {\n opts.wbImageMode = 'online';\n }\n }\n\n if (opts.imageMode && !['local', 'online'].includes(opts.imageMode)) {\n program.error(`Invalid --image-mode \"${opts.imageMode}\", must be \"local\" or \"online\"`);\n }\n if (!['base64', 'inline-svg', 'svg', 'yaml'].includes(opts.wbFormat)) {\n program.error(`Invalid --wb-format \"${opts.wbFormat}\", must be \"base64\", \"inline-svg\", \"svg\", or \"yaml\"`);\n }\n if (!['online', 'base64', 'local'].includes(opts.wbImageMode)) {\n program.error(`Invalid --wb-image-mode \"${opts.wbImageMode}\", must be \"online\", \"base64\", or \"local\"`);\n }\n\n const appId = opts.appId!;\n const appSecret = opts.appSecret!;\n if (!appId || !appSecret) {\n program.error('Missing credentials: pass --app-id/--app-secret or set LARK_DOCX2MD_APP_ID/LARK_DOCX2MD_APP_SECRET');\n }\n\n const result = await convert({\n appId,\n appSecret,\n url,\n output: opts.output,\n imageMode: opts.imageMode as 'local' | 'online',\n wbImageMode: opts.wbImageMode as WbImageMode,\n wbBg: opts.wbBg,\n wbFormat: opts.wbFormat as WbFormat,\n agent: agentLocal ? 'local' : (opts.agent === true),\n });\n\n if (agentLocal) {\n // 本地模式:输出引导 AI 读取文件的提示词(绝对路径)\n process.stdout.write(\n `**The Feishu document has been downloaded to the following absolute path:**\\n\\n` +\n `\\`${result.filePath}\\`\\n\\n` +\n `**Read this file to access the full markdown content.**\\n`,\n );\n } else if (opts.agent === true) {\n process.stdout.write(result.markdown);\n }\n });\n\nprogram.parse();\n"],"mappings":";;;;;AAOA,MAAM,UAAU,IAAI,SAAS;AAC7B,QAAQ,KAAK,cAAc,CAAC,YAAY,6CAA6C;AAErF,QACG,QAAQ,WAAW,CACnB,MAAM,KAAK,CACX,YAAY,uCAAuC,CACnD,OAAO,iBAAiB,mDAAmD,CAC3E,OAAO,yBAAyB,2DAA2D,CAC3F,OAAO,sBAAsB,4CAA4C,CACzE,OAAO,kBAAkB,yLAAuL,CAChN,OAAO,wBAAwB,yGAAiG,CAChI,OAAO,mBAAmB,iGAA2F,CACrH,OAAO,0BAA0B,8FAAwF,CACzH,OAAO,uBAAuB,4EAAwE,CACtG,SAAS,SAAS,uDAAuD,CACzE,OAAO,OAAO,KAAa,SAA+K;AAEzM,MAAK,QAAQ,KAAK,SAAS,QAAQ,IAAI;AACvC,MAAK,YAAY,KAAK,aAAa,QAAQ,IAAI;AAC/C,MAAK,SAAS,KAAK,UAAU,QAAQ,IAAI,uBAAuB;AAEhE,KAAI,KAAK,UAAU,KAAA,GAAW;EAC5B,MAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,aAAa,OAAQ,MAAK,QAAQ;WAC7B,aAAa,QAAS,MAAK,QAAQ;MACvC,MAAK,QAAQ;YACT,OAAO,KAAK,UAAU,YAAY,KAAK,UAAU,QAC1D,SAAQ,MAAM,0BAA0B,KAAK,MAAM,kDAAkD;CAEvG,MAAM,eAAe,KAAK,UAAU,QAAQ,KAAK,UAAU;CAC3D,MAAM,aAAa,KAAK,UAAU;AAElC,MAAK,YAAY,KAAK,aAAa,QAAQ,IAAI,2BAA2B;AAC1E,MAAK,WAAW,KAAK,YAAY,QAAQ,IAAI;AAC7C,MAAK,OAAO,KAAK,QAAQ,QAAQ,IAAI,sBAAsB;AAC3D,MAAK,cAAc,KAAK,eAAe,QAAQ,IAAI,8BAA8B;AAGjF,KAAI,CAAC,KAAK,SACR,MAAK,WAAW,eAAe,SAAS;AAG1C,KAAI,cAAc;AAChB,cAAY,YAAY,MAAM;AAC9B,MAAI,YAAY;AAEd,QAAK,YAAY;AACjB,QAAK,cAAc;SACd;AAEL,QAAK,YAAY;AACjB,QAAK,cAAc;;AAErB,MAAI,CAAC,CAAC,cAAc,OAAO,CAAC,SAAS,KAAK,SAAS,CACjD,SAAQ,MAAM,kEAAkE;YAI9E,KAAK,aAAa,OACpB,MAAK,cAAc;AAIvB,KAAI,KAAK,aAAa,CAAC,CAAC,SAAS,SAAS,CAAC,SAAS,KAAK,UAAU,CACjE,SAAQ,MAAM,yBAAyB,KAAK,UAAU,gCAAgC;AAExF,KAAI,CAAC;EAAC;EAAU;EAAc;EAAO;EAAO,CAAC,SAAS,KAAK,SAAS,CAClE,SAAQ,MAAM,wBAAwB,KAAK,SAAS,qDAAqD;AAE3G,KAAI,CAAC;EAAC;EAAU;EAAU;EAAQ,CAAC,SAAS,KAAK,YAAY,CAC3D,SAAQ,MAAM,4BAA4B,KAAK,YAAY,2CAA2C;CAGxG,MAAM,QAAQ,KAAK;CACnB,MAAM,YAAY,KAAK;AACvB,KAAI,CAAC,SAAS,CAAC,UACb,SAAQ,MAAM,qGAAqG;CAGrH,MAAM,SAAS,MAAM,QAAQ;EAC3B;EACA;EACA;EACA,QAAQ,KAAK;EACb,WAAW,KAAK;EAChB,aAAa,KAAK;EAClB,MAAM,KAAK;EACX,UAAU,KAAK;EACf,OAAO,aAAa,UAAW,KAAK,UAAU;EAC/C,CAAC;AAEF,KAAI,WAEF,SAAQ,OAAO,MACb,oFACK,OAAO,SAAS,iEAEtB;UACQ,KAAK,UAAU,KACxB,SAAQ,OAAO,MAAM,OAAO,SAAS;EAEvC;AAEJ,QAAQ,OAAO"}
|
|
@@ -28,10 +28,11 @@ interface ConvertResult {
|
|
|
28
28
|
declare function parseWikiUrl(url: string): {
|
|
29
29
|
docType: string;
|
|
30
30
|
docToken: string;
|
|
31
|
+
sheetId?: string;
|
|
31
32
|
};
|
|
32
33
|
declare function convert(opts: ConvertOptions): Promise<ConvertResult>;
|
|
33
34
|
//# sourceMappingURL=converter.d.ts.map
|
|
34
35
|
|
|
35
36
|
//#endregion
|
|
36
37
|
export { convert, parseWikiUrl };
|
|
37
|
-
//# sourceMappingURL=converter-
|
|
38
|
+
//# sourceMappingURL=converter-C_2JDVY1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converter-C_2JDVY1.d.ts","names":[],"sources":["../src/types.ts","../src/converter.ts"],"mappings":";;;;AAsCa,KAhBD,SAAA,GAgBC,OAAA,GAAA,QAAA;AACE,KAdH,WAAA,GAcG,QAAA,GAAA,QAAA,GAAA,OAAA;AACP,KAZI,QAAA,GAYJ,QAAA,GAAA,YAAA,GAAA,KAAA,GAAA,MAAA;AACI,KAVA,aAAA,GAUA,MAAA,GAAA,KAAA,GAAA,CAAA,MAAA,GAAA,CAAA,CAAA,CAAA;AAAQ,UARH,cAAA,CAQG;EASH,KAAA,EAAA,MAAA;;;;ECnCD,SAAA,EDuBH,SCvBe;EAUN,WAAO,EDcd,WCdc;EAAA,IAAA,EDerB,aCfqB;UAAQ,EDgBzB,QChByB;OAAyB,CAAA,EAAA,OAAA,GAAA,OAAA;;AAAD,UDyB5C,aAAA,CCzB4C;;;;;;;;iBAV7C,YAAA;;EDOJ,QAAA,EAAA,MAAS;EAGT,OAAA,CAAA,EAAA,MAAW;AAGvB,CAAA;AAGY,iBCNU,OAAA,CDMG,IAAA,ECNY,cDMZ,CAAA,ECN6B,ODM7B,CCNqC,aDMrC,CAAA;AAEzB"}
|
|
@@ -644,8 +644,9 @@ var MdSerializer = class {
|
|
|
644
644
|
register(serializer) {
|
|
645
645
|
this.registry.register(serializer.type, serializer);
|
|
646
646
|
}
|
|
647
|
-
serialize(root) {
|
|
647
|
+
serialize(root, options = {}) {
|
|
648
648
|
const ctx = {
|
|
649
|
+
sourceType: options.sourceType ?? "docx",
|
|
649
650
|
serialize: (node, indent = 0) => {
|
|
650
651
|
const serializer = this.registry.get(node.type);
|
|
651
652
|
if (serializer) return serializer.serialize(node, ctx);
|
|
@@ -831,11 +832,11 @@ const htmlSerializer = {
|
|
|
831
832
|
};
|
|
832
833
|
const sheetResolvedSerializer = {
|
|
833
834
|
type: "sheetResolved",
|
|
834
|
-
serialize(node) {
|
|
835
|
+
serialize(node, ctx) {
|
|
835
836
|
if (node.type !== "sheetResolved") return "";
|
|
836
837
|
let out = "";
|
|
837
838
|
for (const s of node.sheets) {
|
|
838
|
-
if (
|
|
839
|
+
if (ctx.sourceType === "sheet") out += `## ${node.title}-${s.title}\n\n`;
|
|
839
840
|
if (s.error) {
|
|
840
841
|
out += `> ${s.error}\n\n`;
|
|
841
842
|
continue;
|
|
@@ -2823,7 +2824,7 @@ var MdTransformer = class {
|
|
|
2823
2824
|
try {
|
|
2824
2825
|
const info = await this.client.getSpreadsheetInfo(spreadsheetToken);
|
|
2825
2826
|
const list = await this.client.listSheets(spreadsheetToken);
|
|
2826
|
-
const sheetsToProcess = this.sourceType === "sheet" ? list : list.filter((s) => s.sheet_id === sheetId);
|
|
2827
|
+
const sheetsToProcess = this.sourceType === "sheet" && !sheetId ? list : list.filter((s) => s.sheet_id === sheetId);
|
|
2827
2828
|
const resolved = [];
|
|
2828
2829
|
for (const s of sheetsToProcess) {
|
|
2829
2830
|
if (s.hidden) continue;
|
|
@@ -2868,16 +2869,14 @@ var MdTransformer = class {
|
|
|
2868
2869
|
map.set(raw, {
|
|
2869
2870
|
type: "sheetResolved",
|
|
2870
2871
|
title: info.title ?? "",
|
|
2871
|
-
sheets: resolved
|
|
2872
|
-
showTitle: this.sourceType === "sheet"
|
|
2872
|
+
sheets: resolved
|
|
2873
2873
|
});
|
|
2874
2874
|
} catch (e) {
|
|
2875
2875
|
logger$1.warn(`Failed to resolve sheet ${raw}:`, e.message);
|
|
2876
2876
|
map.set(raw, {
|
|
2877
2877
|
type: "sheetResolved",
|
|
2878
2878
|
title: "",
|
|
2879
|
-
sheets: []
|
|
2880
|
-
showTitle: false
|
|
2879
|
+
sheets: []
|
|
2881
2880
|
});
|
|
2882
2881
|
}
|
|
2883
2882
|
}
|
|
@@ -2960,14 +2959,16 @@ const logger = createLogger("converter");
|
|
|
2960
2959
|
function parseWikiUrl(url) {
|
|
2961
2960
|
const m = url.match(/^https:\/\/[\w.-]+\/(docs|docx|wiki|sheets)\/([a-zA-Z0-9]+)/);
|
|
2962
2961
|
if (!m) throw new Error("Invalid feishu document URL");
|
|
2962
|
+
const sheetId = new URL(url).searchParams.get("sheet") ?? void 0;
|
|
2963
2963
|
return {
|
|
2964
2964
|
docType: m[1],
|
|
2965
|
-
docToken: m[2]
|
|
2965
|
+
docToken: m[2],
|
|
2966
|
+
sheetId
|
|
2966
2967
|
};
|
|
2967
2968
|
}
|
|
2968
2969
|
async function convert(opts) {
|
|
2969
|
-
const { docType, docToken: rawToken } = parseWikiUrl(opts.url);
|
|
2970
|
-
logger.info("Captured document token:", rawToken);
|
|
2970
|
+
const { docType, docToken: rawToken, sheetId } = parseWikiUrl(opts.url);
|
|
2971
|
+
logger.info("Captured document token:", rawToken, sheetId ? `sheetId: ${sheetId}` : "");
|
|
2971
2972
|
const sdkLoggerLevel = opts.agent ? LoggerLevel.error : LoggerLevel.warn;
|
|
2972
2973
|
const client = createClient(opts.appId, opts.appSecret, sdkLoggerLevel);
|
|
2973
2974
|
let docToken = rawToken;
|
|
@@ -2979,18 +2980,21 @@ async function convert(opts) {
|
|
|
2979
2980
|
logger.info("Resolved wiki node:", objType, docToken);
|
|
2980
2981
|
} else if (docType === "sheets") objType = "sheet";
|
|
2981
2982
|
let ast;
|
|
2982
|
-
if (objType === "sheet")
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2983
|
+
if (objType === "sheet") {
|
|
2984
|
+
const info = await client.getSpreadsheetInfo(docToken);
|
|
2985
|
+
const sheetToken = sheetId ? `${docToken}_${sheetId}` : docToken;
|
|
2986
|
+
ast = {
|
|
2987
|
+
type: "page",
|
|
2988
|
+
title: [{
|
|
2989
|
+
type: "text",
|
|
2990
|
+
content: info.title ?? ""
|
|
2991
|
+
}],
|
|
2992
|
+
children: [{
|
|
2993
|
+
type: "sheet",
|
|
2994
|
+
token: sheetToken
|
|
2995
|
+
}]
|
|
2996
|
+
};
|
|
2997
|
+
} else {
|
|
2994
2998
|
const doc = await client.getDocxDocument(docToken);
|
|
2995
2999
|
const blocks = await client.getDocxBlocks(docToken);
|
|
2996
3000
|
logger.info(`Fetched ${blocks.length} blocks`);
|
|
@@ -3001,7 +3005,7 @@ async function convert(opts) {
|
|
|
3001
3005
|
await new MdTransformer(client, opts, objType === "sheet" ? "sheet" : "docx").transform(ast);
|
|
3002
3006
|
const serializer = new MdSerializer();
|
|
3003
3007
|
registerBuiltinSerializers(serializer);
|
|
3004
|
-
const markdown = serializer.serialize(ast);
|
|
3008
|
+
const markdown = serializer.serialize(ast, { sourceType: objType === "sheet" ? "sheet" : "docx" });
|
|
3005
3009
|
let filePath;
|
|
3006
3010
|
if (!opts.agent || opts.agent === "local") {
|
|
3007
3011
|
fs.mkdirSync(opts.output, { recursive: true });
|
|
@@ -3018,4 +3022,4 @@ async function convert(opts) {
|
|
|
3018
3022
|
//#endregion
|
|
3019
3023
|
export { parseWikiUrl as n, setLogLevel as r, convert as t };
|
|
3020
3024
|
|
|
3021
|
-
//# sourceMappingURL=converter-
|
|
3025
|
+
//# sourceMappingURL=converter-jW2Zu4Pb.js.map
|