feishu-mcp
Version:
Model Context Protocol server for Feishu integration
203 lines (202 loc) • 6.35 kB
JavaScript
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));
}
}