lark-docx2md 0.1.1 → 0.2.0

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/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","names":[],"sources":["../src/client.ts","../src/parser.ts","../src/logger.ts","../src/cli.ts"],"sourcesContent":["import * as lark from '@larksuiteoapi/node-sdk';\nimport { LoggerLevel } from '@larksuiteoapi/node-sdk';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport type DocxBlock = NonNullable<NonNullable<\n Awaited<ReturnType<lark.Client['docx']['v1']['documentBlock']['list']>>['data']\n>['items']>[number];\n\nexport type TextBody = NonNullable<DocxBlock['text']>;\nexport type TextElement = TextBody['elements'][number];\n\nexport interface DocInfo {\n documentId: string;\n title: string;\n}\n\nexport function createClient (appId: string, appSecret: string, loggerLevel: LoggerLevel = LoggerLevel.warn) {\n const client = new lark.Client({ appId, appSecret, loggerLevel });\n\n async function call<T> (name: string, fn: () => Promise<{ code?: number; msg?: string; data?: T }>): Promise<T> {\n let res;\n try {\n res = await fn();\n } catch (e: any) {\n const error = e.response?.data?.error;\n const code = e.response?.data?.code;\n const msg = e.response?.data?.msg;\n if (error) {\n throw new Error(`${name} failed: [${code}] ${msg}: \\n${JSON.stringify(error, null, 2)}`);\n }\n throw e;\n }\n if (res.code !== 0) {\n throw new Error(`${name} failed: [${res.code}] ${res.msg}`);\n }\n return res.data!;\n }\n\n async function getWikiNodeInfo (token: string) {\n const data = await call('getWikiNodeInfo', () =>\n client.wiki.v2.space.getNode({ params: { token } }),\n );\n return data.node!;\n }\n\n async function getDocxDocument (docToken: string): Promise<DocInfo> {\n const data = await call('getDocxDocument', () =>\n client.docx.v1.document.get({ path: { document_id: docToken } }),\n );\n const doc = data.document!;\n return { documentId: doc.document_id!, title: doc.title! };\n }\n\n async function getDocxBlocks (docToken: string): Promise<DocxBlock[]> {\n const blocks: DocxBlock[] = [];\n let pageToken: string | undefined;\n for (; ;) {\n const data = await call('getDocxBlocks', () =>\n client.docx.v1.documentBlock.list({\n path: { document_id: docToken },\n params: { page_size: 500, document_revision_id: -1, page_token: pageToken },\n }),\n );\n if (data.items) blocks.push(...data.items);\n if (!data.has_more) break;\n pageToken = data.page_token;\n }\n return blocks;\n }\n\n /**\n *\n * @param fileTokens 一次最多可传递 5 个素材的 token\n * @return {Record<string, string>} Record<token, downloadLink>\n */\n async function batchGetTmpDownloadUrl (fileTokens: string[]): Promise<Record<string, string>> {\n const data = await call('batchGetTmpDownloadUrl', () =>\n client.drive.v1.media.batchGetTmpDownloadUrl({ params: { file_tokens: fileTokens } }),\n );\n const list = data.tmp_download_urls ?? [];\n const result: Record<string, string> = {};\n for (const { file_token, tmp_download_url } of list) {\n result[file_token] = tmp_download_url;\n }\n return result;\n }\n\n async function downloadImage (imgToken: string, outDir: string): Promise<string> {\n try {\n const resp = await client.drive.v1.media.download({ path: { file_token: imgToken } });\n fs.mkdirSync(outDir, { recursive: true });\n const ext = (resp.headers?.['content-type'] as string)?.includes('png') ? '.png' : '.jpg';\n const filename = path.join(outDir, `${imgToken}${ext}`);\n await resp.writeFile(filename);\n return filename;\n } catch (error: any) {\n if ([400, 401, 403].includes(error.status)) {\n throw new Error(`下载图片[${imgToken}]异常, 检查是否有接口 https://open.feishu.cn/document/server-docs/docs/drive-v1/media/download 的权限。`);\n }\n throw error;\n }\n }\n\n return { getWikiNodeInfo, getDocxDocument, getDocxBlocks, downloadImage, batchGetTmpDownloadUrl };\n}\n\nexport type LarkClient = ReturnType<typeof createClient>;\n","import type { DocInfo, DocxBlock, TextBody, TextElement } from './client.js';\n\nconst BlockType = {\n Page: 1, Text: 2,\n Heading1: 3, Heading2: 4, Heading3: 5, Heading4: 6, Heading5: 7, Heading6: 8,\n Heading7: 9, Heading8: 10, Heading9: 11,\n Bullet: 12, Ordered: 13, Code: 14, Quote: 15, Equation: 16, Todo: 17,\n Callout: 19, Divider: 22, Grid: 24, GridColumn: 25, Image: 27,\n Table: 31, TableCell: 32, QuoteContainer: 34,\n} as const;\n\nconst codeLangMap: Record<number, string> = {\n 1: '', 2: 'abap', 3: 'ada', 4: 'apache', 5: 'apex', 6: 'assembly', 7: 'bash', 8: 'csharp',\n 9: 'cpp', 10: 'c', 11: 'cobol', 12: 'css', 13: 'coffeescript', 14: 'd', 15: 'dart',\n 16: 'delphi', 17: 'django', 18: 'dockerfile', 19: 'erlang', 20: 'fortran', 21: 'foxpro',\n 22: 'go', 23: 'groovy', 24: 'html', 25: 'htmlbars', 26: 'http', 27: 'haskell', 28: 'json',\n 29: 'java', 30: 'javascript', 31: 'julia', 32: 'kotlin', 33: 'latex', 34: 'lisp',\n 35: 'logo', 36: 'lua', 37: 'matlab', 38: 'makefile', 39: 'markdown', 40: 'nginx',\n 41: 'objectivec', 42: 'openedge-abl', 43: 'php', 44: 'perl', 45: 'postscript',\n 46: 'powershell', 47: 'prolog', 48: 'protobuf', 49: 'python', 50: 'r', 51: 'rpg',\n 52: 'ruby', 53: 'rust', 54: 'sas', 55: 'scss', 56: 'sql', 57: 'scala', 58: 'scheme',\n 59: 'scratch', 60: 'shell', 61: 'swift', 62: 'thrift', 63: 'typescript', 64: 'vbscript',\n 65: 'vbnet', 66: 'xml', 67: 'yaml',\n};\n\nexport class Parser {\n imgTokens: string[] = [];\n private blockMap = new Map<string, DocxBlock>();\n\n parseDocxContent (doc: DocInfo, blocks: DocxBlock[]): string {\n for (const b of blocks) {\n if (b.block_id) this.blockMap.set(b.block_id, b);\n }\n const entry = this.blockMap.get(doc.documentId);\n if (!entry) return '';\n return this.parseBlock(entry, 0);\n }\n\n private parseBlock (b: DocxBlock, indent: number): string {\n const prefix = '\\t'.repeat(indent);\n const bt = b.block_type;\n\n if (bt === BlockType.Page) return this.parsePage(b);\n if (bt === BlockType.Text) return prefix + this.parseText(b.text!) + '\\n';\n if (bt >= BlockType.Heading1 && bt <= BlockType.Heading9) return prefix + this.parseHeading(b, bt - 2);\n if (bt === BlockType.Bullet) return prefix + this.parseBullet(b, indent);\n if (bt === BlockType.Ordered) return prefix + this.parseOrdered(b, indent);\n if (bt === BlockType.Code) return prefix + this.parseCode(b);\n if (bt === BlockType.Quote) return prefix + '> ' + this.parseText(b.quote!) + '\\n';\n if (bt === BlockType.Equation) return prefix + '$$\\n' + this.parseText(b.equation!) + '$$\\n\\n';\n if (bt === BlockType.Todo) return prefix + this.parseTodo(b);\n if (bt === BlockType.Callout) return this.parseCallout(b);\n if (bt === BlockType.Divider) return prefix + '---\\n\\n';\n if (bt === BlockType.Image) return prefix + this.parseImage(b) + '\\n';\n if (bt === BlockType.Table) return prefix + this.parseTable(b);\n if (bt === BlockType.TableCell) return this.parseTableCell(b);\n if (bt === BlockType.QuoteContainer) return this.parseQuoteContainer(b);\n if (bt === BlockType.Grid) return this.parseGrid(b, indent);\n\n return '';\n }\n\n private parsePage (b: DocxBlock): string {\n let s = '# ' + this.parseText(b.page!) + '\\n';\n for (const id of b.children ?? []) {\n const child = this.blockMap.get(id);\n if (child) s += this.parseBlock(child, 0) + '\\n';\n }\n return s;\n }\n\n private parseText (body: TextBody): string {\n const inline = body.elements.length > 1;\n return body.elements.map(e => this.parseElement(e, inline)).join('') + '\\n';\n }\n\n private parseElement (e: TextElement, inline: boolean): string {\n if (e.text_run) return this.parseTextRun(e.text_run);\n if (e.mention_user) return e.mention_user.user_id;\n if (e.mention_doc) {\n const url = e.mention_doc.url ? decodeURIComponent(e.mention_doc.url) : '';\n return `[${e.mention_doc.title ?? ''}](${url})`;\n }\n if (e.equation) {\n const sym = inline ? '$' : '$$';\n return sym + e.equation.content.replace(/\\n$/, '') + sym;\n }\n return '';\n }\n\n private parseTextRun (tr: NonNullable<TextElement['text_run']>): string {\n const s = tr.text_element_style;\n let pre = '', post = '';\n if (s) {\n if (s.bold) {\n pre = '**';\n post = '**';\n } else if (s.italic) {\n pre = '_';\n post = '_';\n } else if (s.strikethrough) {\n pre = '~~';\n post = '~~';\n } else if (s.underline) {\n pre = '<u>';\n post = '</u>';\n } else if (s.inline_code) {\n pre = '`';\n post = '`';\n } else if (s.link) {\n pre = '[';\n post = `](${decodeURIComponent(s.link.url)})`;\n }\n }\n return pre + tr.content + post;\n }\n\n private parseHeading (b: DocxBlock, level: number): string {\n const headingKey = `heading${level}` as keyof DocxBlock;\n const body = b[headingKey] as TextBody | undefined;\n let s = '#'.repeat(level) + ' ' + (body ? this.parseText(body) : '\\n');\n for (const id of b.children ?? []) {\n const child = this.blockMap.get(id);\n if (child) s += this.parseBlock(child, 0);\n }\n return s;\n }\n\n private parseBullet (b: DocxBlock, indent: number): string {\n let s = '- ' + this.parseText(b.bullet!);\n for (const id of b.children ?? []) {\n const child = this.blockMap.get(id);\n if (child) s += this.parseBlock(child, indent + 1);\n }\n return s;\n }\n\n private parseOrdered (b: DocxBlock, indent: number): string {\n const parent = this.blockMap.get(b.parent_id!);\n let order = 1;\n if (parent?.children) {\n const idx = parent.children.indexOf(b.block_id!);\n for (let i = idx - 1; i >= 0; i--) {\n const sib = this.blockMap.get(parent.children[i]!);\n if (sib?.block_type === BlockType.Ordered) order++;\n else break;\n }\n }\n let s = `${order}. ` + this.parseText(b.ordered!);\n for (const id of b.children ?? []) {\n const child = this.blockMap.get(id);\n if (child) s += this.parseBlock(child, indent + 1);\n }\n return s;\n }\n\n private parseCode (b: DocxBlock): string {\n const lang = codeLangMap[b.code?.style?.language ?? 1] ?? '';\n const text = this.parseText(b.code!).trim();\n return '```' + lang + '\\n' + text + '\\n```\\n';\n }\n\n private parseTodo (b: DocxBlock): string {\n const checked = b.todo?.style?.done ? 'x' : ' ';\n return `- [${checked}] ` + this.parseText(b.todo!) + '\\n';\n }\n\n private parseCallout (b: DocxBlock): string {\n let s = '>[!TIP] \\n';\n for (const id of b.children ?? []) {\n const child = this.blockMap.get(id);\n if (child) s += this.parseBlock(child, 0);\n }\n return s;\n }\n\n private parseImage (b: DocxBlock): string {\n const token = b.image?.token;\n if (token) {\n this.imgTokens.push(token);\n return `![图片-${token}](${token})\\n`;\n }\n return '';\n }\n\n private parseTableCell (b: DocxBlock): string {\n let s = '';\n for (const id of b.children ?? []) {\n const child = this.blockMap.get(id);\n if (child) s += this.parseBlock(child, 0).replace(/\\n/g, '') + '<br/>';\n }\n return s;\n }\n\n private parseTable (b: DocxBlock): string {\n const t = b.table!;\n const cols = t.property.column_size;\n const rows: string[][] = [];\n const mergeInfos = t.property.merge_info ?? [];\n\n for (let i = 0; i < (t.cells?.length ?? 0); i++) {\n const cellId = t.cells![i]!;\n const cell = this.blockMap.get(cellId);\n const content = cell ? this.parseBlock(cell, 0).replace(/\\n/g, '') : '';\n const row = Math.floor(i / cols);\n const col = i % cols;\n if (!rows[row]) rows[row] = [];\n rows[row]![col] = content;\n }\n\n const mergeMap = new Map<string, { rowSpan: number; colSpan: number }>();\n for (let i = 0; i < mergeInfos.length; i++) {\n const m = mergeInfos[i]!;\n const row = Math.floor(i / cols);\n const col = i % cols;\n mergeMap.set(`${row}-${col}`, { rowSpan: m.row_span ?? 1, colSpan: m.col_span ?? 1 });\n }\n\n const processed = new Set<string>();\n let buf = '<table>\\n';\n for (let r = 0; r < rows.length; r++) {\n buf += '<tr>\\n';\n for (let c = 0; c < (rows[r]?.length ?? 0); c++) {\n const key = `${r}-${c}`;\n if (processed.has(key)) continue;\n const merge = mergeMap.get(key);\n let attrs = '';\n if (merge) {\n if (merge.rowSpan > 1) attrs += ` rowspan=\"${merge.rowSpan}\"`;\n if (merge.colSpan > 1) attrs += ` colspan=\"${merge.colSpan}\"`;\n for (let mr = r; mr < r + merge.rowSpan; mr++) {\n for (let mc = c; mc < c + merge.colSpan; mc++) {\n processed.add(`${mr}-${mc}`);\n }\n }\n }\n buf += `<td${attrs}>${rows[r]![c] ?? ''}</td>`;\n }\n buf += '</tr>\\n';\n }\n buf += '</table>\\n';\n return buf;\n }\n\n private parseQuoteContainer (b: DocxBlock): string {\n let s = '';\n for (const id of b.children ?? []) {\n const child = this.blockMap.get(id);\n if (child) s += '> ' + this.parseBlock(child, 0);\n }\n return s;\n }\n\n private parseGrid (b: DocxBlock, indent: number): string {\n let s = '';\n for (const colId of b.children ?? []) {\n const col = this.blockMap.get(colId);\n if (!col) continue;\n for (const id of col.children ?? []) {\n const child = this.blockMap.get(id);\n if (child) s += this.parseBlock(child, indent);\n }\n }\n return s;\n }\n}\n","import { LoggerLevel } from '@larksuiteoapi/node-sdk';\n\nconst COLORS: Record<number, string> = {\n [LoggerLevel.fatal]: '\\x1b[35m', // magenta\n [LoggerLevel.error]: '\\x1b[31m', // red\n [LoggerLevel.warn]: '\\x1b[33m', // yellow\n [LoggerLevel.info]: '\\x1b[36m', // cyan\n [LoggerLevel.debug]: '\\x1b[32m', // green\n [LoggerLevel.trace]: '\\x1b[90m', // gray\n};\nconst RESET = '\\x1b[0m';\nconst LEVEL_NAMES = ['FATAL', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE'];\nlet minLogLevel = LoggerLevel.trace;\n\nfunction log (level: LoggerLevel, module: string, ...args: unknown[]) {\n if (level > minLogLevel) return;\n const time = new Date().toISOString();\n const color = COLORS[level] ?? '';\n const name = LEVEL_NAMES[level] ?? 'INFO';\n process.stderr.write(`${time} ${color}[${name}]${RESET} [${module}] ${args.map(String).join(' ')}\\n`);\n}\n\nexport function setLogLevel (level: LoggerLevel) {\n minLogLevel = level;\n}\n\nexport function createLogger (module: string) {\n return {\n fatal: (...args: unknown[]) => log(LoggerLevel.fatal, module, ...args),\n error: (...args: unknown[]) => log(LoggerLevel.error, module, ...args),\n warn: (...args: unknown[]) => log(LoggerLevel.warn, module, ...args),\n info: (...args: unknown[]) => log(LoggerLevel.info, module, ...args),\n debug: (...args: unknown[]) => log(LoggerLevel.debug, module, ...args),\n trace: (...args: unknown[]) => log(LoggerLevel.trace, module, ...args),\n };\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { LoggerLevel } from '@larksuiteoapi/node-sdk';\nimport { createClient } from './client.js';\nimport { Parser } from './parser.js';\nimport { createLogger, setLogLevel } from './logger.js';\n\nconst logger = createLogger('cli');\n\nfunction parseWikiUrl (url: string): { docType: string; docToken: string } {\n const m = url.match(/^https:\\/\\/[\\w.-]+\\/(docs|docx|wiki)\\/([a-zA-Z0-9]+)/);\n if (!m) throw new Error('Invalid feishu document URL');\n return { docType: m[1]!, docToken: m[2]! };\n}\n\nconst program = new Command();\nprogram.name('larkDocx2md').description('Download Lark/Feishu documents to markdown');\n\nprogram\n .command('download')\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', './larkDocx2mdOutput')\n .option('--agent', 'Enable agent mode: ERROR log level, and AI prompt output')\n .option('--image-mode <mode>', 'Image handling mode: \"local\" (download) or \"online\" (temp URL)', 'local')\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; imageMode: string }) => {\n if (opts.agent) {\n setLogLevel(LoggerLevel.error);\n opts.imageMode = 'online';\n } else if (opts.imageMode && !['local', 'online'].includes(opts.imageMode)) {\n program.error(`Invalid --image-mode \"${opts.imageMode}\", must be \"local\" or \"online\"`);\n }\n\n const { docType, docToken: rawToken } = parseWikiUrl(url);\n logger.info('Captured document token:', rawToken);\n\n const appId = opts.appId ?? process.env.LARK_DOCX2MD_APP_ID!;\n const appSecret = opts.appSecret ?? process.env.LARK_DOCX2MD_APP_SECRET!;\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 sdkLoggerLevel = opts.agent ? LoggerLevel.error : LoggerLevel.warn;\n const client = createClient(appId, appSecret, sdkLoggerLevel);\n let docToken = rawToken;\n\n if (docType === 'wiki') {\n const node = await client.getWikiNodeInfo(docToken);\n docToken = node.obj_token!;\n logger.info('Resolved docx token:', docToken);\n }\n\n const doc = await client.getDocxDocument(docToken);\n const blocks = await client.getDocxBlocks(docToken);\n logger.info(`Fetched ${blocks.length} blocks`);\n\n const parser = new Parser();\n let markdown = parser.parseDocxContent(doc, blocks);\n\n if (opts.imageMode === 'online') {\n // batch: max 5 tokens per request\n for (let i = 0; i < parser.imgTokens.length; i += 5) {\n const batch = parser.imgTokens.slice(i, i + 5);\n const urlMap = await client.batchGetTmpDownloadUrl(batch);\n for (const token of batch) {\n const onlineUrl = urlMap[token];\n if (onlineUrl) {\n markdown = markdown.replace(`(${token})`, `(${onlineUrl})`);\n logger.info('Replaced image with online URL:', token);\n }\n }\n }\n } else {\n const imgDir = path.join(opts.output, 'static');\n for (const imgToken of parser.imgTokens) {\n let localPath = await client.downloadImage(imgToken, imgDir);\n localPath = path.relative(opts.output, localPath);\n markdown = markdown.replace(`(${imgToken})`, `(${localPath})`);\n logger.info('Downloaded image:', localPath);\n }\n }\n\n if (opts.agent) {\n process.stdout.write(markdown);\n } else {\n fs.mkdirSync(opts.output, { recursive: true });\n const mdPath = path.join(opts.output, `${docToken}.md`);\n fs.writeFileSync(mdPath, markdown);\n logger.info('Downloaded markdown file to', mdPath);\n }\n });\n\nprogram.parse();\n"],"mappings":"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"}
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 .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', 'Enable agent mode: ERROR log level, and AI prompt output (or LARK_DOCX2MD_AGENT=true)')\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; 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 opts.agent = opts.agent ?? (process.env.LARK_DOCX2MD_AGENT === 'true');\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 状态)\n if (!opts.wbFormat) {\n opts.wbFormat = opts.agent ? 'yaml' : 'svg';\n }\n\n if (opts.agent) {\n setLogLevel(LoggerLevel.error);\n opts.imageMode = 'online';\n opts.wbImageMode = 'online';\n // agent 模式下画板仅支持内嵌形式\n if (!['inline-svg', 'yaml'].includes(opts.wbFormat)) {\n program.error(`Agent mode only supports \"inline-svg\" or \"yaml\" for --wb-format`);\n }\n opts.wbImageMode = 'online';\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 // yaml 格式 图片仅支持 online\n if (opts.wbFormat === 'yaml') {\n opts.wbImageMode = 'online';\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: opts.agent,\n });\n\n if (opts.agent) {\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,YAAY,uCAAuC,CACnD,OAAO,iBAAiB,mDAAmD,CAC3E,OAAO,yBAAyB,2DAA2D,CAC3F,OAAO,sBAAsB,4CAA4C,CACzE,OAAO,WAAW,wFAAwF,CAC1G,OAAO,wBAAwB,yGAAiG,CAChI,OAAO,mBAAmB,iGAA2F,CACrH,OAAO,0BAA0B,8FAAwF,CACzH,OAAO,uBAAuB,4EAAwE,CACtG,SAAS,SAAS,uDAAuD,CACzE,OAAO,OAAO,KAAa,SAAsK;AAEhM,MAAK,QAAQ,KAAK,SAAS,QAAQ,IAAI;AACvC,MAAK,YAAY,KAAK,aAAa,QAAQ,IAAI;AAC/C,MAAK,SAAS,KAAK,UAAU,QAAQ,IAAI,uBAAuB;AAChE,MAAK,QAAQ,KAAK,SAAU,QAAQ,IAAI,uBAAuB;AAC/D,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,KAAK,QAAQ,SAAS;AAGxC,KAAI,KAAK,OAAO;AACd,cAAY,YAAY,MAAM;AAC9B,OAAK,YAAY;AACjB,OAAK,cAAc;AAEnB,MAAI,CAAC,CAAC,cAAc,OAAO,CAAC,SAAS,KAAK,SAAS,CACjD,SAAQ,MAAM,kEAAkE;AAElF,OAAK,cAAc;;AAGrB,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;AAG3G,KAAI,KAAK,aAAa,OACpB,MAAK,cAAc;AAErB,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,KAAK;EACb,CAAC;AAEF,KAAI,KAAK,MACP,SAAQ,OAAO,MAAM,OAAO,SAAS;EAEvC;AAEJ,QAAQ,OAAO"}