@open-feishu-card/renderer 0.1.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/all.css +609 -0
- package/dist/emoji.css +1 -0
- package/dist/icon-font.css +1 -0
- package/dist/index.cjs +5702 -0
- package/dist/index.d.cts +546 -0
- package/dist/index.d.ts +546 -0
- package/dist/index.js +5668 -0
- package/dist/styles.css +605 -0
- package/package.json +52 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
export { dslToRaw } from '@open-feishu-card/adapter';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 飞书 Universal Card「RAW」格式的类型定义。
|
|
5
|
+
* RAW = 飞书服务端归一化后下发的渲染数据(card.raw.json 里的 json_card)。
|
|
6
|
+
*/
|
|
7
|
+
/** 文本样式属性 */
|
|
8
|
+
type TextAttribute = 'bold' | 'italic' | 'strikethrough';
|
|
9
|
+
/** 命名颜色(飞书 12 色板 + 中性色) */
|
|
10
|
+
type NamedColor = 'blue' | 'wathet' | 'turquoise' | 'green' | 'yellow' | 'orange' | 'red' | 'carmine' | 'violet' | 'purple' | 'indigo' | 'grey' | 'neutral' | 'lime' | 'sunflower';
|
|
11
|
+
/** header 模板色 */
|
|
12
|
+
type HeaderTemplate = NamedColor | 'default';
|
|
13
|
+
/** 对齐方式 */
|
|
14
|
+
type TextAlign = 'left' | 'center' | 'right';
|
|
15
|
+
/** 字号枚举名(含 markdown text_size / RAW textStyle.size 全量) */
|
|
16
|
+
type SizeName = 'x-small' | 'small' | 'normal' | 'medium' | 'large' | 'x-large' | 'xx-large' | 'xxx-large' | 'xxxx-large' | 'notation' | 'heading' | 'heading-0' | 'heading-1' | 'heading-2' | 'heading-3' | 'heading-4';
|
|
17
|
+
/** 文本样式 */
|
|
18
|
+
interface TextStyle {
|
|
19
|
+
attributes?: TextAttribute[];
|
|
20
|
+
color?: NamedColor | string;
|
|
21
|
+
size?: SizeName | string;
|
|
22
|
+
platformSize?: {
|
|
23
|
+
pc?: SizeName | string;
|
|
24
|
+
mobile?: SizeName | string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 通用元素:{ tag, id, property }。
|
|
29
|
+
* property 的具体形状随 tag 不同,这里用宽松索引;常见字段单独标注。
|
|
30
|
+
*/
|
|
31
|
+
interface CardElement {
|
|
32
|
+
tag: string;
|
|
33
|
+
id?: string;
|
|
34
|
+
property?: ElementProperty;
|
|
35
|
+
/** 降级渲染:引擎渲不出该元素时改渲 fallback(如 person_list 取不到人员数据时的纯文本姓名) */
|
|
36
|
+
fallback?: CardElement;
|
|
37
|
+
}
|
|
38
|
+
/** 元素 property(并集:不同 tag 用到不同子集) */
|
|
39
|
+
interface ElementProperty {
|
|
40
|
+
/** 子元素(markdown / body / div / column / heading / blockquote 等) */
|
|
41
|
+
elements?: CardElement[];
|
|
42
|
+
/** 纯文本内容(plain_text / link / code_span 等) */
|
|
43
|
+
content?: string;
|
|
44
|
+
/** 文本样式 */
|
|
45
|
+
textStyle?: TextStyle;
|
|
46
|
+
/** 段落对齐 */
|
|
47
|
+
textAlign?: TextAlign;
|
|
48
|
+
originTag?: string;
|
|
49
|
+
template?: HeaderTemplate;
|
|
50
|
+
title?: CardElement;
|
|
51
|
+
subtitle?: CardElement;
|
|
52
|
+
/** 标题右侧的彩色标签(每项 text_tag 元素)。DSL 用 snake_case,兼容 camelCase */
|
|
53
|
+
text_tag_list?: CardElement[];
|
|
54
|
+
textTagList?: CardElement[];
|
|
55
|
+
columns?: CardElement[];
|
|
56
|
+
horizontal_spacing?: number | string;
|
|
57
|
+
horizontal_align?: 'left' | 'center' | 'right';
|
|
58
|
+
flex_mode?: string;
|
|
59
|
+
width?: 'weighted' | 'auto' | number | string;
|
|
60
|
+
weight?: number;
|
|
61
|
+
vertical_align?: 'top' | 'center' | 'bottom';
|
|
62
|
+
vertical_spacing?: number | string;
|
|
63
|
+
widthValue?: {
|
|
64
|
+
type?: string;
|
|
65
|
+
value?: number | string;
|
|
66
|
+
};
|
|
67
|
+
horizontalSpacingValue?: {
|
|
68
|
+
type?: string;
|
|
69
|
+
value?: number | string;
|
|
70
|
+
};
|
|
71
|
+
verticalSpacingValue?: {
|
|
72
|
+
type?: string;
|
|
73
|
+
value?: number | string;
|
|
74
|
+
};
|
|
75
|
+
horizontalAlign?: 'left' | 'center' | 'right';
|
|
76
|
+
verticalAlign?: 'top' | 'center' | 'bottom';
|
|
77
|
+
flexMode?: string;
|
|
78
|
+
backgroundStyle?: string;
|
|
79
|
+
padding?: BoxSpacing;
|
|
80
|
+
margin?: BoxSpacing;
|
|
81
|
+
hoverTips?: CardElement;
|
|
82
|
+
hasBorder?: boolean;
|
|
83
|
+
imageID?: string;
|
|
84
|
+
origin_key?: string;
|
|
85
|
+
src?: string;
|
|
86
|
+
url?: string | LinkURL;
|
|
87
|
+
img_url?: string;
|
|
88
|
+
/** RAW 里 alt 常为 plain_text 元素而非字符串 */
|
|
89
|
+
alt?: CardElement | string;
|
|
90
|
+
scale_type?: string;
|
|
91
|
+
scaleType?: string;
|
|
92
|
+
mode?: string;
|
|
93
|
+
corner_radius?: number | string;
|
|
94
|
+
type?: string;
|
|
95
|
+
text?: CardElement;
|
|
96
|
+
disabled?: boolean;
|
|
97
|
+
behaviors?: Array<{
|
|
98
|
+
default_url?: {
|
|
99
|
+
url?: string;
|
|
100
|
+
};
|
|
101
|
+
}>;
|
|
102
|
+
actions?: CardElement[];
|
|
103
|
+
layout?: string;
|
|
104
|
+
userID?: string;
|
|
105
|
+
/** person_list:人员引用列表(每项 { id, type }),id 即 persons 表的 key(ou_...) */
|
|
106
|
+
persons?: Array<{
|
|
107
|
+
id?: string;
|
|
108
|
+
type?: string;
|
|
109
|
+
}>;
|
|
110
|
+
/** 展示头像(person_v1 默认 true;person_list 按真值,与 showName 组合出四态) */
|
|
111
|
+
showAvatar?: boolean;
|
|
112
|
+
/** 展示姓名(person_v1 默认 true;person_list 按真值) */
|
|
113
|
+
showName?: boolean;
|
|
114
|
+
/** 胶囊样式(DSL style:"capsule" 会转成此字段) */
|
|
115
|
+
pillShaped?: boolean;
|
|
116
|
+
multiURL?: LinkURL;
|
|
117
|
+
color?: NamedColor | string;
|
|
118
|
+
tagStyle?: NamedColor | string;
|
|
119
|
+
backgroundColor?: string;
|
|
120
|
+
level?: number;
|
|
121
|
+
items?: ListItem[];
|
|
122
|
+
contents?: Array<{
|
|
123
|
+
contents?: Array<{
|
|
124
|
+
content?: string;
|
|
125
|
+
}>;
|
|
126
|
+
}>;
|
|
127
|
+
language?: string;
|
|
128
|
+
key?: string;
|
|
129
|
+
code?: string;
|
|
130
|
+
emoji_type?: string;
|
|
131
|
+
/** 图标名,形如 "warning_outlined",拼成 class="ud-icon_<token>" */
|
|
132
|
+
token?: string;
|
|
133
|
+
style?: {
|
|
134
|
+
color?: string;
|
|
135
|
+
size?: string;
|
|
136
|
+
[key: string]: unknown;
|
|
137
|
+
};
|
|
138
|
+
icon?: CardElement;
|
|
139
|
+
udIcon?: CardElement;
|
|
140
|
+
/** VChart 规格对象(原样透传给 VChart 构造) */
|
|
141
|
+
chart_spec?: Record<string, unknown>;
|
|
142
|
+
chartSpec?: Record<string, unknown>;
|
|
143
|
+
/**
|
|
144
|
+
* 宽高比,形如 "16:9"(决定容器 aspect-ratio)。
|
|
145
|
+
* 缺省且 height 为 auto 时按飞书默认 "16:9";height 为像素值时此字段失效。
|
|
146
|
+
*/
|
|
147
|
+
aspect_ratio?: string;
|
|
148
|
+
aspectRatio?: string;
|
|
149
|
+
/**
|
|
150
|
+
* 图表高度。飞书 JSON 2.0:`auto`(默认,按宽高比计算)或 `[1,999]px`(固定高度,此时忽略 aspect_ratio)。
|
|
151
|
+
* RAW 形态也可能是 heightValue: { type:'pixels', value:number }。
|
|
152
|
+
*/
|
|
153
|
+
height?: string;
|
|
154
|
+
heightValue?: {
|
|
155
|
+
type?: string;
|
|
156
|
+
value?: number | string;
|
|
157
|
+
};
|
|
158
|
+
/** 行数据:每行是 { 列name: 值 } */
|
|
159
|
+
rows?: Array<Record<string, unknown>>;
|
|
160
|
+
/** 表头样式 */
|
|
161
|
+
header_style?: TableHeaderStyle;
|
|
162
|
+
headerStyle?: TableHeaderStyle;
|
|
163
|
+
/** 行高枚举 low/middle/high */
|
|
164
|
+
row_height?: string;
|
|
165
|
+
rowHeight?: string;
|
|
166
|
+
/** 每页行数(预览里仅用于「显示前 N 行」,不做真实分页控件) */
|
|
167
|
+
page_size?: number;
|
|
168
|
+
pageSize?: number;
|
|
169
|
+
/** 冻结首列(预览里不做横向滚动,仅保留字段兼容透传) */
|
|
170
|
+
freeze_first_column?: boolean;
|
|
171
|
+
/** 其它未显式声明的字段 */
|
|
172
|
+
[key: string]: unknown;
|
|
173
|
+
}
|
|
174
|
+
/** 表格列定义 */
|
|
175
|
+
interface TableColumn {
|
|
176
|
+
/** 列 key,对应每行数据的字段名 */
|
|
177
|
+
name: string;
|
|
178
|
+
/** 表头显示名(缺省用 name) */
|
|
179
|
+
display_name?: string;
|
|
180
|
+
/** 列宽:"auto" / "120px" / 数字 */
|
|
181
|
+
width?: string | number;
|
|
182
|
+
/** 单元格数据类型:text / number / options / markdown / lark_md / persons / date… */
|
|
183
|
+
data_type?: string;
|
|
184
|
+
/** 单元格水平对齐 */
|
|
185
|
+
horizontal_align?: 'left' | 'center' | 'right';
|
|
186
|
+
/** number 类型的格式(precision 小数位) */
|
|
187
|
+
format?: {
|
|
188
|
+
precision?: number;
|
|
189
|
+
symbol?: string;
|
|
190
|
+
separator?: boolean;
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/** 表头样式 */
|
|
194
|
+
interface TableHeaderStyle {
|
|
195
|
+
text_align?: 'left' | 'center' | 'right';
|
|
196
|
+
text_size?: string;
|
|
197
|
+
background_style?: string;
|
|
198
|
+
text_color?: string;
|
|
199
|
+
bold?: boolean;
|
|
200
|
+
lines?: number;
|
|
201
|
+
}
|
|
202
|
+
/** RAW 的内/外边距:四向 { type:'pixels', value } */
|
|
203
|
+
interface BoxSpacing {
|
|
204
|
+
top?: {
|
|
205
|
+
type?: string;
|
|
206
|
+
value?: number;
|
|
207
|
+
};
|
|
208
|
+
right?: {
|
|
209
|
+
type?: string;
|
|
210
|
+
value?: number;
|
|
211
|
+
};
|
|
212
|
+
bottom?: {
|
|
213
|
+
type?: string;
|
|
214
|
+
value?: number;
|
|
215
|
+
};
|
|
216
|
+
left?: {
|
|
217
|
+
type?: string;
|
|
218
|
+
value?: number;
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/** 链接地址:可为直链字符串,或多端地址对象 */
|
|
222
|
+
interface LinkURL {
|
|
223
|
+
url?: string;
|
|
224
|
+
pcURL?: string;
|
|
225
|
+
iosURL?: string;
|
|
226
|
+
androidURL?: string;
|
|
227
|
+
harmonyURL?: string;
|
|
228
|
+
}
|
|
229
|
+
/** 列表项 */
|
|
230
|
+
interface ListItem {
|
|
231
|
+
type?: 'ul' | 'ol' | string;
|
|
232
|
+
ordered?: boolean;
|
|
233
|
+
level?: number;
|
|
234
|
+
order?: number;
|
|
235
|
+
elements?: CardElement[];
|
|
236
|
+
}
|
|
237
|
+
/** 卡片根对象(json_card) */
|
|
238
|
+
interface JsonCard {
|
|
239
|
+
schema?: string;
|
|
240
|
+
header?: CardElement;
|
|
241
|
+
body?: CardElement;
|
|
242
|
+
newBody?: CardElement;
|
|
243
|
+
config?: Record<string, unknown>;
|
|
244
|
+
[key: string]: unknown;
|
|
245
|
+
}
|
|
246
|
+
/** 渲染器可接受的输入:json_card 本身,或带外层包装的 card.raw.json */
|
|
247
|
+
type CardInput = JsonCard | {
|
|
248
|
+
json_card: JsonCard;
|
|
249
|
+
[key: string]: unknown;
|
|
250
|
+
} | {
|
|
251
|
+
card: {
|
|
252
|
+
json_card: JsonCard;
|
|
253
|
+
};
|
|
254
|
+
[key: string]: unknown;
|
|
255
|
+
};
|
|
256
|
+
/** 渲染选项 */
|
|
257
|
+
interface RenderOptions {
|
|
258
|
+
/** 浏览器环境的 document(默认取全局 document) */
|
|
259
|
+
document?: Document;
|
|
260
|
+
/** 遇到未注册的 tag 时打印警告 */
|
|
261
|
+
warnOnUnknownTag?: boolean;
|
|
262
|
+
/** 自定义图片地址解析:返回最终 src */
|
|
263
|
+
resolveImage?: (property: ElementProperty) => string | null | undefined;
|
|
264
|
+
/** 图片地址前缀:最终 src = imageBaseURL + imageID */
|
|
265
|
+
imageBaseURL?: string;
|
|
266
|
+
/**
|
|
267
|
+
* 人员表(open_id -> { content 姓名, avatar_key 头像 })。
|
|
268
|
+
* person_v1 / person_list 元素只带 ID,姓名/头像在此反查。
|
|
269
|
+
* 异步渲染(renderCardToStringAsync)会自动从 json_attachment.persons 填入;
|
|
270
|
+
* 同步渲染若想出名字/头像,需手动传入。缺省时人员降级为固定头像 +「赵天雄」。
|
|
271
|
+
*/
|
|
272
|
+
persons?: Record<string, PersonInfo>;
|
|
273
|
+
/**
|
|
274
|
+
* 头像图地址前缀:最终 src = avatarBaseURL + avatar_key + avatarURLSuffix。
|
|
275
|
+
* 飞书头像 key 公开可取(无需鉴权),默认走 PERSON_AVATAR_BASE。
|
|
276
|
+
*/
|
|
277
|
+
avatarBaseURL?: string;
|
|
278
|
+
/** 头像 URL 后缀(默认含 image_size/format 查询串,见 PERSON_AVATAR_SUFFIX) */
|
|
279
|
+
avatarURLSuffix?: string;
|
|
280
|
+
/** 自定义头像地址解析:入参为命中的 PersonInfo,返回最终 src(优先级最高) */
|
|
281
|
+
resolvePersonAvatar?: (person: PersonInfo) => string | null | undefined;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* 人员信息:person_v1 / person_list 元素只带 ID,姓名与头像 key 在这里。
|
|
285
|
+
* 取自飞书消息 content 的 json_attachment.persons(按 open_id「ou_...」索引)。
|
|
286
|
+
* avatar_key 是公开可访问的头像图 key(无需鉴权,见 PERSON_AVATAR_BASE)。
|
|
287
|
+
*/
|
|
288
|
+
interface PersonInfo {
|
|
289
|
+
person_id?: string;
|
|
290
|
+
/** 显示名 */
|
|
291
|
+
content?: string;
|
|
292
|
+
type?: number;
|
|
293
|
+
/** 头像图 key(形如 v3_00te_...),拼 avatarBaseURL 取图 */
|
|
294
|
+
avatar_key?: string;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* 消息附件表:把卡片里 img 元素的局部序号(property.imageID,如 "19")
|
|
298
|
+
* 映射到飞书图床真实 key(origin_key,形如 img_v3_...)。
|
|
299
|
+
* 取自飞书消息 content 的 json_attachment 字段。
|
|
300
|
+
*/
|
|
301
|
+
interface JsonAttachment {
|
|
302
|
+
images?: Record<string, {
|
|
303
|
+
origin_key?: string;
|
|
304
|
+
}>;
|
|
305
|
+
/** 人员表:open_id(ou_...) -> { content 姓名, avatar_key 头像 } */
|
|
306
|
+
persons?: Record<string, PersonInfo>;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* 异步渲染选项:在同步 RenderOptions 基础上,支持用 access token 自动拉取图片。
|
|
310
|
+
* accessToken 为可选——传了就把卡片图片拉取并内联(data URI);不传则渲染成占位图。
|
|
311
|
+
*/
|
|
312
|
+
interface AsyncRenderOptions extends RenderOptions {
|
|
313
|
+
/** 飞书 access token(去掉 "Bearer " 前缀)。可选:有则拉图内联,无则占位。 */
|
|
314
|
+
accessToken?: string;
|
|
315
|
+
/** 消息 ID(om_...)。当输入是卡片对象而非 messageId 时,用它拼接图片接口 URL。 */
|
|
316
|
+
messageId?: string;
|
|
317
|
+
/** 注入自定义 fetch(默认用全局 fetch)。便于浏览器走代理或单测注入 mock。 */
|
|
318
|
+
fetch?: typeof fetch;
|
|
319
|
+
/** 接口基址,默认 https://open.feishu.cn/open-apis/im/v1 */
|
|
320
|
+
apiBaseURL?: string;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* 异步渲染的输入:
|
|
324
|
+
* - 字符串 → 当作 messageId,渲染器先拉整条消息(需 accessToken);
|
|
325
|
+
* - 卡片对象 → 直接渲染;带 json_attachment + token + messageId 时内联图片。
|
|
326
|
+
*/
|
|
327
|
+
type CardMessageInput = string | CardInput | {
|
|
328
|
+
json_card: JsonCard;
|
|
329
|
+
json_attachment?: JsonAttachment;
|
|
330
|
+
messageId?: string;
|
|
331
|
+
[key: string]: unknown;
|
|
332
|
+
};
|
|
333
|
+
/** 渲染上下文(传给每个组件) */
|
|
334
|
+
interface RenderContext {
|
|
335
|
+
options: RenderOptions;
|
|
336
|
+
kernel: {
|
|
337
|
+
getComponent: (tag: string) => ComponentFn | null;
|
|
338
|
+
renderElement: (el: CardElement | null | undefined, ctx: RenderContext) => VNode | null;
|
|
339
|
+
renderElements: (arr: CardElement[] | undefined, ctx: RenderContext) => VNode[];
|
|
340
|
+
};
|
|
341
|
+
/**
|
|
342
|
+
* markdown 父级注入的正文字号(飞书对内联 Person 设 avatarFollowFontSize)。
|
|
343
|
+
* 有此字段时,person_v1 按正文字号缩放,而非独立组件的 size 枚举(默认 medium)。
|
|
344
|
+
*/
|
|
345
|
+
textMetrics?: {
|
|
346
|
+
fontSize: number;
|
|
347
|
+
lineHeight: number;
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
/** 组件渲染函数 */
|
|
351
|
+
type ComponentFn = (el: CardElement, ctx: RenderContext) => VNode | null;
|
|
352
|
+
/** 轻量虚拟节点 */
|
|
353
|
+
interface VNode {
|
|
354
|
+
tag: string;
|
|
355
|
+
props: VNodeProps;
|
|
356
|
+
children: VNodeChild[];
|
|
357
|
+
}
|
|
358
|
+
interface VNodeProps {
|
|
359
|
+
className?: string;
|
|
360
|
+
style?: Record<string, string | number | null | undefined>;
|
|
361
|
+
dangerouslySetInnerHTML?: {
|
|
362
|
+
__html: string;
|
|
363
|
+
};
|
|
364
|
+
[key: string]: unknown;
|
|
365
|
+
}
|
|
366
|
+
type VNodeChild = VNode | string | null | false;
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* 组件注册表(仿飞书引擎 kernel.getComponent(tag))+ 元素遍历 + 样式辅助。
|
|
370
|
+
*/
|
|
371
|
+
|
|
372
|
+
/** 注册(或覆盖)一个 tag 的渲染组件 */
|
|
373
|
+
declare function registerComponent(tag: string, fn: ComponentFn): void;
|
|
374
|
+
/** 取某 tag 的组件 */
|
|
375
|
+
declare function getComponent(tag: string): ComponentFn | null;
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* 把一段(可能含软换行 \n)行内文本解析成子元素数组。
|
|
379
|
+
* 逐字符扫描,维护加粗/斜体/删除线/颜色状态;状态切换或遇到特殊构造时,
|
|
380
|
+
* 把累积的纯文本冲刷为一个 plain_text 段(对称于 rebuildMarkdown 的分段模型)。
|
|
381
|
+
*/
|
|
382
|
+
declare function parseInline(text: string): CardElement[];
|
|
383
|
+
/**
|
|
384
|
+
* markdown 字符串 → 子元素数组(块级 + 行内)。
|
|
385
|
+
* 逐行扫描识别块构造;连续的普通文本行合并为一段,用 br 承载软换行。
|
|
386
|
+
*/
|
|
387
|
+
declare function parseMarkdown(content: string | undefined | null): CardElement[];
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* 轻量「虚拟节点」模型:让同一套渲染逻辑既能输出 HTML 字符串(Node/SSR),
|
|
391
|
+
* 又能输出真实 DOM(浏览器)。无 React 依赖。
|
|
392
|
+
*/
|
|
393
|
+
|
|
394
|
+
/** 创建 VNode。children 可为 VNode / string / null / false / 数组(自动扁平+去空) */
|
|
395
|
+
declare function h(tag: string, props?: VNodeProps | null, ...children: Array<VNodeChild | VNodeChild[]>): VNode;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* 飞书 Universal Card header 高光纹理(半透明白 PNG,1200x280)。
|
|
399
|
+
* 从网页版飞书原版资源提取并内联为 base64 data URI,使本包零外部资源依赖。
|
|
400
|
+
* - HEADER_BG_LIGHT: 亮色主题 (原 04a33f514b.png)
|
|
401
|
+
* - HEADER_BG_DARK : 暗色主题 (原 c16649b557.png)
|
|
402
|
+
*/
|
|
403
|
+
declare const HEADER_BG_LIGHT: string;
|
|
404
|
+
declare const HEADER_BG_DARK: string;
|
|
405
|
+
|
|
406
|
+
/** 图标名 -> Unicode 私有区码点(十六进制字符串,如 "fa0c") */
|
|
407
|
+
declare const ICON_CODEPOINTS: Record<string, string>;
|
|
408
|
+
/**
|
|
409
|
+
* 注入用的完整图标字体 CSS:@font-face(内联 base64)+ 基础类 + 每图标 content 规则。
|
|
410
|
+
* 浏览器端首次渲染图标时注入 <style>;Node/SSR 端引入 open-feishu-card/icon-font.css。
|
|
411
|
+
*/
|
|
412
|
+
declare const ICON_FONT_CSS: string;
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* 飞书 emoji 短码(:KEY:)-> 雪碧图名映射 + 完整雪碧 CSS。
|
|
416
|
+
* 由 scripts/gen-emoji.mjs 从网页版飞书资源生成,请勿手改。
|
|
417
|
+
*
|
|
418
|
+
* 渲染机制:<i class="larkw-emoji__img--emoji-<name>"> 靠单张雪碧图 CDN + background-position
|
|
419
|
+
* 画出表情(与网页版飞书一致)。雪碧图走 CDN 不内联。详见 README 的「Emoji」一节。
|
|
420
|
+
*
|
|
421
|
+
* 共 270 个短码,291 个雪碧定位。
|
|
422
|
+
*/
|
|
423
|
+
/** emoji 短码(大小写敏感,如 "Fire" / "OK")-> 雪碧图名(如 "fire" / "ok_v2") */
|
|
424
|
+
declare const EMOJI_KEY_TO_NAME: Record<string, string>;
|
|
425
|
+
/**
|
|
426
|
+
* 完整 emoji 雪碧 CSS(含 CDN 背景图 + 每表情 background-position)。
|
|
427
|
+
* 浏览器端首次渲染 emoji 时注入 <style>;Node/SSR 端引入 open-feishu-card/emoji.css。
|
|
428
|
+
*/
|
|
429
|
+
declare const EMOJI_SPRITE_CSS: string;
|
|
430
|
+
|
|
431
|
+
/** 全部卡片样式(布局 + 图标字体 @font-face/glyph + emoji 雪碧定位)拼成的一份字符串 */
|
|
432
|
+
declare const ALL_CSS: string;
|
|
433
|
+
/**
|
|
434
|
+
* 便捷:返回可直接插进页面 <head> 的 <style> 标签(含全部卡片样式)。
|
|
435
|
+
* 一页多张卡片时只需注入一次。
|
|
436
|
+
*/
|
|
437
|
+
declare function feishuCardStyleTag(): string;
|
|
438
|
+
|
|
439
|
+
/** 挂载容器上承载 spec 的属性名 */
|
|
440
|
+
declare const CHART_SPEC_ATTR = "data-feishu-chart-spec";
|
|
441
|
+
/** 已水合标记属性(避免重复 render) */
|
|
442
|
+
declare const CHART_HYDRATED_ATTR = "data-feishu-chart-hydrated";
|
|
443
|
+
/**
|
|
444
|
+
* 水合单张图:把 VChart 规格画进给定挂载节点。
|
|
445
|
+
* @param mount 挂载 DOM 节点(chart 组件里的 __vchart 容器)
|
|
446
|
+
* @param spec VChart 规格对象
|
|
447
|
+
* @param VChart VChart 构造器(调用方注入:import { VChart } from '@visactor/vchart',或 CDN 全局)
|
|
448
|
+
* @returns VChart 实例(可 release());失败返回 null
|
|
449
|
+
*/
|
|
450
|
+
declare function renderFeishuChart(mount: Element, spec: Record<string, unknown>, VChart: unknown): unknown;
|
|
451
|
+
/**
|
|
452
|
+
* 扫描 root 下所有未水合的图表容器并逐个画图(幂等:跳过已水合的)。
|
|
453
|
+
* @param root 根节点(默认 document);传卡片根或页面 body 皆可
|
|
454
|
+
* @param VChart VChart 构造器(浏览器 CDN 场景可传 window.VChart)
|
|
455
|
+
* @returns 成功水合的图表数量
|
|
456
|
+
*/
|
|
457
|
+
declare function hydrateFeishuCharts(root?: ParentNode | null, VChart?: unknown): number;
|
|
458
|
+
/**
|
|
459
|
+
* SSR 用:返回一段自执行 <script>,页面加载后自动扫描并画出全部图表。
|
|
460
|
+
* 依赖页面已载入 VChart(全局 window.VChart,典型是 CDN <script>)。
|
|
461
|
+
* @param opts.vchartGlobal VChart 全局变量名(默认 'VChart')
|
|
462
|
+
*/
|
|
463
|
+
declare function feishuChartHydrateScript(opts?: {
|
|
464
|
+
vchartGlobal?: string;
|
|
465
|
+
}): string;
|
|
466
|
+
/**
|
|
467
|
+
* SSR 用:hydrate 脚本正文(不含 <script> 包裹),便于自行拼装/加 nonce。
|
|
468
|
+
* 内联了扫描逻辑(不引用打包产物),只依赖页面里的全局 VChart。
|
|
469
|
+
*/
|
|
470
|
+
declare function feishuChartHydrateJs(vchartGlobal?: string): string;
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* 渲染常量。颜色/字号等规则均从网页版飞书引擎 (be8b738f.js) 与
|
|
474
|
+
* edbaaa5b.css 中逆向抽取,详见 README 的「渲染规则」一节。
|
|
475
|
+
*/
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* 图表(chart)默认序列色板。取自 VChart 官方默认主题的分类色序列,
|
|
479
|
+
* 与网页版飞书卡片图表观感一致。hydrate 时若 spec 未显式给 color,注入此序列。
|
|
480
|
+
*/
|
|
481
|
+
declare const CHART_PALETTE: string[];
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* 异步渲染:用飞书 access token 自动拉取卡片图片并内联(data URI),
|
|
485
|
+
* 或直接按 message_id 把整条消息拉回来再渲染。
|
|
486
|
+
*
|
|
487
|
+
* 网络层单独成文件,使同步核心(index.ts)保持零依赖、可被 tree-shake。
|
|
488
|
+
* 所有渲染仍复用同步的 renderCardToString / renderCard——这里只负责把图片
|
|
489
|
+
* 预取成 data URI,再通过生成好的 resolveImage 钩子喂进去。
|
|
490
|
+
*/
|
|
491
|
+
|
|
492
|
+
/** ArrayBuffer -> base64(Node 用 Buffer,浏览器用 btoa;保持零依赖、双端可用) */
|
|
493
|
+
declare function arrayBufferToBase64(buf: ArrayBuffer): string;
|
|
494
|
+
/**
|
|
495
|
+
* 拉取单条卡片消息并解包成 { json_card, json_attachment, messageId }。
|
|
496
|
+
* 必须带 card_msg_content_type=raw_card_content,否则拿不到 json_card。
|
|
497
|
+
* 注意接口里的 json_card 是被字符串化的 JSON(双重编码),需再解一层。
|
|
498
|
+
*/
|
|
499
|
+
declare function fetchCardMessage(messageId: string, options: AsyncRenderOptions): Promise<{
|
|
500
|
+
json_card: JsonCard;
|
|
501
|
+
json_attachment?: JsonAttachment;
|
|
502
|
+
messageId: string;
|
|
503
|
+
}>;
|
|
504
|
+
/**
|
|
505
|
+
* 拉取单张图片二进制,转成 base64 data URI。
|
|
506
|
+
* 端点:GET /messages/{messageId}/resources/{origin_key}?type=image
|
|
507
|
+
*/
|
|
508
|
+
declare function fetchImageDataUri(messageId: string, originKey: string, options: AsyncRenderOptions): Promise<string>;
|
|
509
|
+
/**
|
|
510
|
+
* 预取卡片实际用到的图片,返回 { [imageID]: dataUri }。
|
|
511
|
+
* 只拉卡片里 img 元素引用过的 imageID;缺 token / 缺 messageId / 缺附件表则返回空表。
|
|
512
|
+
* 单张失败只 warn 并跳过(后续 resolveImage 拿不到 src -> 占位图)。
|
|
513
|
+
*/
|
|
514
|
+
declare function prefetchImages(jsonCard: JsonCard, jsonAttachment: JsonAttachment | undefined, messageId: string | undefined, options: AsyncRenderOptions): Promise<Record<string, string>>;
|
|
515
|
+
/**
|
|
516
|
+
* 异步渲染为 HTML 字符串。
|
|
517
|
+
* @param input messageId 字符串,或卡片对象 { json_card, json_attachment?, messageId? }
|
|
518
|
+
* @param options 含可选 accessToken:传了就内联图片,不传则图片渲染成占位图。
|
|
519
|
+
*/
|
|
520
|
+
declare function renderCardToStringAsync(input: CardMessageInput, options?: AsyncRenderOptions): Promise<string>;
|
|
521
|
+
/**
|
|
522
|
+
* 异步渲染为真实 DOM 节点(浏览器)。Node 端请用 renderCardToStringAsync。
|
|
523
|
+
* 注意:浏览器直连 open.feishu.cn 会被 CORS 拦截,需经服务端代理(见 README)。
|
|
524
|
+
*/
|
|
525
|
+
declare function renderCardAsync(input: CardMessageInput, options?: AsyncRenderOptions): Promise<Node>;
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* open-feishu-card
|
|
529
|
+
* 独立、零依赖的飞书 Universal Card 渲染器(RAW 格式输入)。
|
|
530
|
+
* 同时适用于 Node/SSR(renderCardToString)与浏览器(renderCard)。
|
|
531
|
+
*/
|
|
532
|
+
|
|
533
|
+
/** 渲染为 HTML 字符串(Node / SSR / 邮件 / 截图等) */
|
|
534
|
+
declare function renderCardToString(card: CardInput, options?: RenderOptions): string;
|
|
535
|
+
/** 渲染为真实 DOM 节点(浏览器)。Node 端请用 renderCardToString */
|
|
536
|
+
declare function renderCard(card: CardInput, options?: RenderOptions): Node;
|
|
537
|
+
/**
|
|
538
|
+
* 输入公开 DSL(JSON Schema 2.0 卡片),渲染为 HTML 字符串。
|
|
539
|
+
* = renderCardToString(dslToRaw(dsl))。DSL 里 markdown 写字符串、字段用 snake_case,
|
|
540
|
+
* 内部转成 RAW 再渲染,无需真发一遍卡片。
|
|
541
|
+
*/
|
|
542
|
+
declare function renderDslToString(dsl: unknown, options?: RenderOptions): string;
|
|
543
|
+
/** 输入公开 DSL,渲染为真实 DOM 节点(浏览器)。= renderCard(dslToRaw(dsl)) */
|
|
544
|
+
declare function renderDsl(dsl: unknown, options?: RenderOptions): Node;
|
|
545
|
+
|
|
546
|
+
export { ALL_CSS, type AsyncRenderOptions, type BoxSpacing, CHART_HYDRATED_ATTR, CHART_PALETTE, CHART_SPEC_ATTR, type CardElement, type CardInput, type CardMessageInput, type ComponentFn, EMOJI_KEY_TO_NAME, EMOJI_SPRITE_CSS, type ElementProperty, HEADER_BG_DARK, HEADER_BG_LIGHT, type HeaderTemplate, ICON_CODEPOINTS, ICON_FONT_CSS, type JsonAttachment, type JsonCard, type LinkURL, type ListItem, type NamedColor, type PersonInfo, type RenderContext, type RenderOptions, type SizeName, type TableColumn, type TableHeaderStyle, type TextAlign, type TextAttribute, type TextStyle, type VNode, type VNodeChild, type VNodeProps, arrayBufferToBase64, feishuCardStyleTag, feishuChartHydrateJs, feishuChartHydrateScript, fetchCardMessage, fetchImageDataUri, getComponent, h, hydrateFeishuCharts, parseInline, parseMarkdown, prefetchImages, registerComponent, renderCard, renderCardAsync, renderCardToString, renderCardToStringAsync, renderDsl, renderDslToString, renderFeishuChart };
|