UNPKG

feishu-mcp

Version:

Model Context Protocol server for Feishu integration

203 lines (202 loc) 6.35 kB
import { Logger } from '../utils/logger.js'; /** * 块类型枚举 */ export var BlockType; (function (BlockType) { BlockType["TEXT"] = "text"; BlockType["CODE"] = "code"; BlockType["HEADING"] = "heading"; BlockType["LIST"] = "list"; })(BlockType || (BlockType = {})); /** * 对齐方式枚举 */ export var AlignType; (function (AlignType) { AlignType[AlignType["LEFT"] = 1] = "LEFT"; AlignType[AlignType["CENTER"] = 2] = "CENTER"; AlignType[AlignType["RIGHT"] = 3] = "RIGHT"; })(AlignType || (AlignType = {})); /** * 块工厂类 * 提供统一接口创建不同类型的块内容 */ export class BlockFactory { constructor() { } /** * 获取块工厂实例 * @returns 块工厂实例 */ static getInstance() { if (!BlockFactory.instance) { BlockFactory.instance = new BlockFactory(); } return BlockFactory.instance; } /** * 获取默认的文本元素样式 * @returns 默认文本元素样式 */ static getDefaultTextElementStyle() { return { bold: false, inline_code: false, italic: false, strikethrough: false, underline: false }; } /** * 应用默认文本样式 * @param style 已有样式(可选) * @returns 合并后的样式 */ static applyDefaultTextStyle(style) { const defaultStyle = BlockFactory.getDefaultTextElementStyle(); return style ? { ...defaultStyle, ...style } : defaultStyle; } /** * 创建块内容 * @param type 块类型 * @param options 块选项 * @returns 块内容对象 */ createBlock(type, options) { switch (type) { case BlockType.TEXT: return this.createTextBlock(options); case BlockType.CODE: return this.createCodeBlock(options); case BlockType.HEADING: return this.createHeadingBlock(options); case BlockType.LIST: return this.createListBlock(options); default: Logger.error(`不支持的块类型: ${type}`); throw new Error(`不支持的块类型: ${type}`); } } /** * 创建文本块内容 * @param options 文本块选项 * @returns 文本块内容对象 */ createTextBlock(options) { const { textContents, align = AlignType.LEFT } = options; return { block_type: 2, // 2表示文本块 text: { elements: textContents.map(content => ({ text_run: { content: content.text, text_element_style: BlockFactory.applyDefaultTextStyle(content.style) } })), style: { align: align, // 1 居左,2 居中,3 居右 } } }; } /** * 创建代码块内容 * @param options 代码块选项 * @returns 代码块内容对象 */ createCodeBlock(options) { const { code, language = 0, wrap = false } = options; // 校验 language 合法性,飞书API只允许1~75 const safeLanguage = language >= 1 && language <= 75 ? language : 1; return { block_type: 14, // 14表示代码块 code: { elements: [ { text_run: { content: code, text_element_style: BlockFactory.getDefaultTextElementStyle() } } ], style: { language: safeLanguage, wrap: wrap } } }; } /** * 创建标题块内容 * @param options 标题块选项 * @returns 标题块内容对象 */ createHeadingBlock(options) { const { text, level = 1, align = AlignType.LEFT } = options; // 确保标题级别在有效范围内(1-9) const safeLevel = Math.max(1, Math.min(9, level)); // 根据标题级别设置block_type和对应的属性名 // 飞书API中,一级标题的block_type为3,二级标题为4,以此类推 const blockType = 2 + safeLevel; // 一级标题为3,二级标题为4,以此类推 const headingKey = `heading${safeLevel}`; // heading1, heading2, ... // 构建块内容 const blockContent = { block_type: blockType }; // 设置对应级别的标题属性 blockContent[headingKey] = { elements: [ { text_run: { content: text, text_element_style: BlockFactory.getDefaultTextElementStyle() } } ], style: { align: align, folded: false } }; return blockContent; } /** * 创建列表块内容(有序或无序) * @param options 列表块选项 * @returns 列表块内容对象 */ createListBlock(options) { const { text, isOrdered = false, align = AlignType.LEFT } = options; // 有序列表是 block_type: 13,无序列表是 block_type: 12 const blockType = isOrdered ? 13 : 12; const propertyKey = isOrdered ? "ordered" : "bullet"; // 构建块内容 const blockContent = { block_type: blockType }; // 设置列表属性 blockContent[propertyKey] = { elements: [ { text_run: { content: text, text_element_style: BlockFactory.getDefaultTextElementStyle() } } ], style: { align: align, folded: false } }; return blockContent; } /** * 创建批量块内容 * @param blocks 块配置数组 * @returns 块内容数组 */ createBatchBlocks(blocks) { return blocks.map(block => this.createBlock(block.type, block.options)); } }