feishu-raw-card-to-dsl 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/LICENSE +21 -0
- package/README.md +104 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +803 -0
- package/dist/index.js.map +1 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ztx4215_123136
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# feishu-raw-card-to-dsl
|
|
2
|
+
|
|
3
|
+
把飞书 `im.message.get` 用 `card_msg_content_type: "raw_card_content"` 拉到的**编辑器内部 envelope**,转换成公开 [JSON Schema 2.0 卡片 DSL](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/feishu-cards/card-json-v2-structure)。
|
|
4
|
+
|
|
5
|
+
零依赖,纯函数。
|
|
6
|
+
|
|
7
|
+
## 为什么需要它
|
|
8
|
+
|
|
9
|
+
飞书发送卡片用公开 DSL(JSON Schema 2.0),但同样的卡片用 `im.message.get` 拉回来时,飞书有两种内容形态可选:
|
|
10
|
+
|
|
11
|
+
| 模式 | 字段完整度 | 适合做什么 |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `user_card_content`(默认/常用) | **有损**:等于服务端默认值的字段被剥掉 | 只读展示 |
|
|
14
|
+
| `raw_card_content` | 完整:保留每个原始字段 | 改完重发 |
|
|
15
|
+
|
|
16
|
+
最痛的丢字段案例:`column.padding`。当 column 带非默认 `background_style`(比如 `red-50`、`grey-50`)时,飞书渲染会自动给 12px 内边距,但这个 12px 在 `user_card_content` 返回里**没了**。把这种 DSL 重新发出去,彩色块紧贴边缘,看起来全坏。
|
|
17
|
+
|
|
18
|
+
`raw_card_content` 解决了字段完整性问题,**但代价是返回的不是公开 DSL**:
|
|
19
|
+
|
|
20
|
+
- 每个 element 包成 `{id, tag, property: {...}}`
|
|
21
|
+
- 字段名是 camelCase(`textAlign` / `imageID` / `widthValue` / ...)
|
|
22
|
+
- padding/margin 是对象 `{top:{type:"pixels",value:12}, ...}` 而不是 `"12px ..."` 字符串
|
|
23
|
+
- img 用 `imageID` 指向旁路的 `json_attachment.images` 表
|
|
24
|
+
- markdown 内容拆成 plain_text / br / list / heading / link / text_tag / code_span / code_block / at_all / blockquote 等子元素,需要重新拼回 inline markdown 字符串
|
|
25
|
+
- header 包成 `tag:'card_header'`,带 `udIcon` 而不是 `icon`
|
|
26
|
+
- chart_spec 内部用 vega/vchart 的 camelCase(不能 snake_case)
|
|
27
|
+
- 大量编辑器内部字段(`disabled:false` / `actions:[]` / `showCount` / `pillShaped` / `min_lib_version` / ...)公开 schema 不接受,重发会被飞书拒
|
|
28
|
+
|
|
29
|
+
这个库专门处理 raw envelope → 公开 DSL 的转换。基于 250+ 张真实归档卡片做回归对齐。
|
|
30
|
+
|
|
31
|
+
## 安装
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install feishu-raw-card-to-dsl
|
|
35
|
+
# 或
|
|
36
|
+
pnpm add feishu-raw-card-to-dsl
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 用法
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { rawCardToDsl, isRawCardEnvelope } from "feishu-raw-card-to-dsl";
|
|
43
|
+
import * as lark from "@larksuiteoapi/node-sdk";
|
|
44
|
+
|
|
45
|
+
const client = new lark.Client({ appId, appSecret });
|
|
46
|
+
|
|
47
|
+
const response = await client.im.message.get({
|
|
48
|
+
path: { message_id: "om_xxx" },
|
|
49
|
+
params: {
|
|
50
|
+
// @ts-expect-error SDK 类型滞后;raw_card_content 是文档化的合法值
|
|
51
|
+
card_msg_content_type: "raw_card_content",
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const item = response.data?.items?.[0];
|
|
56
|
+
const rawContent = item?.body?.content;
|
|
57
|
+
if (typeof rawContent !== "string") throw new Error("not a card message");
|
|
58
|
+
|
|
59
|
+
const envelope = JSON.parse(rawContent);
|
|
60
|
+
if (!isRawCardEnvelope(envelope)) {
|
|
61
|
+
// 老消息 / 模板卡 / 非 raw 形态:直接用原解析结果或 fall back 到 user_card_content
|
|
62
|
+
console.log(envelope);
|
|
63
|
+
} else {
|
|
64
|
+
const dsl = rawCardToDsl(envelope);
|
|
65
|
+
// dsl 现在是 { schema:"2.0", config:{update_multi:true}, body:{...}, header:{...} },
|
|
66
|
+
// 可以直接用 im.message.create / patch_card / 写 .card 文件等所有标准发送路径。
|
|
67
|
+
console.log(JSON.stringify(dsl, null, 2));
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 已覆盖的元素 / 字段
|
|
72
|
+
|
|
73
|
+
读端转换(raw → 公开 DSL)已对照真实归档对齐过的:
|
|
74
|
+
|
|
75
|
+
- **结构**:body / column_set / column / hr
|
|
76
|
+
- **文本**:markdown(含 plain_text / br / list / heading / blockquote / link / code_span / code_block / text_tag / at_all 子元素的 inline 还原)
|
|
77
|
+
- **媒体**:img(`imageID` 还原为 `img_key`、`width_height_pixels` size_value 还原为 `"Wpx Hpx"`、`aspect_ratio` 还原为 `"W:H"`)
|
|
78
|
+
- **header**:title / subtitle / template / padding / udIcon → standard_icon
|
|
79
|
+
- **互动**:button(`actionType:"link"` → `multi_url`,`actionType:"multi"` → `behaviors[]`,`action_request` callback 丢弃)、interactive_container
|
|
80
|
+
- **图表**:chart(`chart_spec` 子树原样保留 camelCase)
|
|
81
|
+
- **数据视图**:person(`userID` → `user_id`,`pillShaped` 丢弃)、input(白名单字段,editor-only 字段全丢)
|
|
82
|
+
- **可折叠面板**:collapsible_panel(header 的 raw 端 layout 残留 position/width/vertical_align 全丢)
|
|
83
|
+
- **配置**:config 强制输出 `{update_multi: true}`(cardkit 发送链路要求)
|
|
84
|
+
- **box 字段**:padding / margin / corner_radius / icon size 全部从对象形态转回字符串
|
|
85
|
+
|
|
86
|
+
## 已知限制
|
|
87
|
+
|
|
88
|
+
- 转换器只管"读端":把 raw envelope 项目回公开 DSL。**不**反向:从公开 DSL 生成 raw envelope。
|
|
89
|
+
- 罕见 element(table、form 嵌套等)只走 generic 递归 + camelCase→snake_case,没专门处理。如果遇到飞书校验失败的字段,欢迎 issue / PR。
|
|
90
|
+
- `action_request` 类型的按钮 callback(cardkit entity 层的概念)在公开 DSL 里没有对应表达,会被丢弃。
|
|
91
|
+
|
|
92
|
+
## 开发
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pnpm install
|
|
96
|
+
pnpm test # vitest 单测
|
|
97
|
+
pnpm build # 输出 dist/
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
测试基于真实 raw envelope fixture(`tests/fixtures/*.raw.json`),覆盖 padding / img / markdown / chart / person / input / button / header 各路径。
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert the editor-internal "raw_card_content" payload returned by
|
|
3
|
+
* `im.message.get?card_msg_content_type=raw_card_content` into the public
|
|
4
|
+
* JSON Schema 2.0 DSL we author and send.
|
|
5
|
+
*
|
|
6
|
+
* The raw payload differs from the public DSL in several ways:
|
|
7
|
+
* 1. Every node is wrapped as { id, tag, property: { ...real fields... } }.
|
|
8
|
+
* 2. Field names are camelCase (textAlign, backgroundStyle, imageID, ...).
|
|
9
|
+
* 3. Box fields (padding/margin) are objects { bottom:{type,value}, ... }
|
|
10
|
+
* instead of "Tpx Rpx Bpx Lpx" strings; scalar pixels (corner_radius,
|
|
11
|
+
* icon size) are similarly objectified.
|
|
12
|
+
* 4. Images carry imageID (numeric) which indexes into a separate
|
|
13
|
+
* json_attachment.images table to recover the real img_key.
|
|
14
|
+
* 5. Markdown is split into per-segment children (plain_text / link / br /
|
|
15
|
+
* at_all / text_tag / code_span / ...) under a wrapper element with
|
|
16
|
+
* originTag:'markdown'; we re-stitch them back into a single content
|
|
17
|
+
* string with inline markers.
|
|
18
|
+
* 6. Header is wrapped as `tag: 'card_header'` and its icon shows up as a
|
|
19
|
+
* sibling `udIcon` wrapper around an inner `ud_icon` element.
|
|
20
|
+
* 7. Editor mirrors the same value twice — a coarse enum (width:'auto')
|
|
21
|
+
* alongside a precise echo (widthValue:{type:'pixels',value:72}). We
|
|
22
|
+
* project the precise echo back onto the enum when it disagrees.
|
|
23
|
+
* 8. Most nodes carry editor defaults (disabled:false, vertical_align:
|
|
24
|
+
* 'top', flex_mode:'none', background_style:'default') that the public
|
|
25
|
+
* DSL omits. We strip them.
|
|
26
|
+
* 9. The whole thing is double-stringified into body.content as
|
|
27
|
+
* { json_card: "<stringified card>", json_attachment: { images, at_users? } }.
|
|
28
|
+
*
|
|
29
|
+
* Why we do this: the documented user_card_content path drops fields whose
|
|
30
|
+
* values match a server-side default (notably `column.padding` on a column
|
|
31
|
+
* with `background_style`), which silently breaks layouts on round-trip.
|
|
32
|
+
* The raw payload preserves them. We project raw -> public DSL on the read
|
|
33
|
+
* path so downstream code (patch_lark_card, archives, the model's mental
|
|
34
|
+
* model) keeps working against the only format that has a public spec.
|
|
35
|
+
*
|
|
36
|
+
* No public spec exists for the raw payload. The mapping below is sample-
|
|
37
|
+
* driven, derived from diffing rawCardToDsl(raw) against archived public DSL
|
|
38
|
+
* for ~250 cards we previously sent. When the converter encounters something
|
|
39
|
+
* it does not recognize, it keeps the original key/value (snake-cased) so
|
|
40
|
+
* downstream sees an unknown field rather than silently losing data.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isRawCardEnvelope(value: unknown): boolean;
|
|
43
|
+
export declare function rawCardToDsl(envelope: unknown): unknown;
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAWH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAIzD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAcvD"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,803 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert the editor-internal "raw_card_content" payload returned by
|
|
3
|
+
* `im.message.get?card_msg_content_type=raw_card_content` into the public
|
|
4
|
+
* JSON Schema 2.0 DSL we author and send.
|
|
5
|
+
*
|
|
6
|
+
* The raw payload differs from the public DSL in several ways:
|
|
7
|
+
* 1. Every node is wrapped as { id, tag, property: { ...real fields... } }.
|
|
8
|
+
* 2. Field names are camelCase (textAlign, backgroundStyle, imageID, ...).
|
|
9
|
+
* 3. Box fields (padding/margin) are objects { bottom:{type,value}, ... }
|
|
10
|
+
* instead of "Tpx Rpx Bpx Lpx" strings; scalar pixels (corner_radius,
|
|
11
|
+
* icon size) are similarly objectified.
|
|
12
|
+
* 4. Images carry imageID (numeric) which indexes into a separate
|
|
13
|
+
* json_attachment.images table to recover the real img_key.
|
|
14
|
+
* 5. Markdown is split into per-segment children (plain_text / link / br /
|
|
15
|
+
* at_all / text_tag / code_span / ...) under a wrapper element with
|
|
16
|
+
* originTag:'markdown'; we re-stitch them back into a single content
|
|
17
|
+
* string with inline markers.
|
|
18
|
+
* 6. Header is wrapped as `tag: 'card_header'` and its icon shows up as a
|
|
19
|
+
* sibling `udIcon` wrapper around an inner `ud_icon` element.
|
|
20
|
+
* 7. Editor mirrors the same value twice — a coarse enum (width:'auto')
|
|
21
|
+
* alongside a precise echo (widthValue:{type:'pixels',value:72}). We
|
|
22
|
+
* project the precise echo back onto the enum when it disagrees.
|
|
23
|
+
* 8. Most nodes carry editor defaults (disabled:false, vertical_align:
|
|
24
|
+
* 'top', flex_mode:'none', background_style:'default') that the public
|
|
25
|
+
* DSL omits. We strip them.
|
|
26
|
+
* 9. The whole thing is double-stringified into body.content as
|
|
27
|
+
* { json_card: "<stringified card>", json_attachment: { images, at_users? } }.
|
|
28
|
+
*
|
|
29
|
+
* Why we do this: the documented user_card_content path drops fields whose
|
|
30
|
+
* values match a server-side default (notably `column.padding` on a column
|
|
31
|
+
* with `background_style`), which silently breaks layouts on round-trip.
|
|
32
|
+
* The raw payload preserves them. We project raw -> public DSL on the read
|
|
33
|
+
* path so downstream code (patch_lark_card, archives, the model's mental
|
|
34
|
+
* model) keeps working against the only format that has a public spec.
|
|
35
|
+
*
|
|
36
|
+
* No public spec exists for the raw payload. The mapping below is sample-
|
|
37
|
+
* driven, derived from diffing rawCardToDsl(raw) against archived public DSL
|
|
38
|
+
* for ~250 cards we previously sent. When the converter encounters something
|
|
39
|
+
* it does not recognize, it keeps the original key/value (snake-cased) so
|
|
40
|
+
* downstream sees an unknown field rather than silently losing data.
|
|
41
|
+
*/
|
|
42
|
+
export function isRawCardEnvelope(value) {
|
|
43
|
+
if (typeof value !== "object" || value === null)
|
|
44
|
+
return false;
|
|
45
|
+
const v = value;
|
|
46
|
+
return typeof v.json_card === "string" && typeof v.card_schema === "number";
|
|
47
|
+
}
|
|
48
|
+
export function rawCardToDsl(envelope) {
|
|
49
|
+
if (!isRawCardEnvelope(envelope))
|
|
50
|
+
return envelope;
|
|
51
|
+
const env = envelope;
|
|
52
|
+
let inner;
|
|
53
|
+
try {
|
|
54
|
+
inner = JSON.parse(env.json_card ?? "");
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return envelope;
|
|
58
|
+
}
|
|
59
|
+
const ctx = {
|
|
60
|
+
images: env.json_attachment?.images ?? {},
|
|
61
|
+
atUsers: env.json_attachment?.at_users ?? {},
|
|
62
|
+
};
|
|
63
|
+
return convertRoot(inner, ctx);
|
|
64
|
+
}
|
|
65
|
+
/* ------------------------------------------------------------------ *
|
|
66
|
+
* Defaults / known editor-only fields
|
|
67
|
+
* ------------------------------------------------------------------ */
|
|
68
|
+
/**
|
|
69
|
+
* Confirmed editor residue by diffing the raw payload against ~250 archived
|
|
70
|
+
* public-DSL cards we authored. These have no slot in the public schema,
|
|
71
|
+
* either because they're editor metadata or because they duplicate a sibling
|
|
72
|
+
* enum (the precise *_value echo is reconciled separately).
|
|
73
|
+
*/
|
|
74
|
+
const RAW_ONLY_FIELDS = new Set([
|
|
75
|
+
"new_body",
|
|
76
|
+
"source",
|
|
77
|
+
]);
|
|
78
|
+
/**
|
|
79
|
+
* Tag-scoped raw-only fields. The remaining img fields (preview, transparent,
|
|
80
|
+
* size, corner_radius, scale_type) are kept; archive samples show authors
|
|
81
|
+
* write them explicitly.
|
|
82
|
+
*/
|
|
83
|
+
const IMG_RAW_ONLY_FIELDS = new Set([
|
|
84
|
+
"compact_width",
|
|
85
|
+
"mode",
|
|
86
|
+
]);
|
|
87
|
+
/**
|
|
88
|
+
* Per-tag default values that the public DSL routinely omits even though raw
|
|
89
|
+
* always emits them. Confirmed by diffing rawCardToDsl(raw) against archives
|
|
90
|
+
* we authored: cards either left these out entirely or wrote a different
|
|
91
|
+
* value, so dropping the noisy defaults closes the gap. Other ostensibly
|
|
92
|
+
* "default-looking" fields (direction, vertical_align, horizontal_align)
|
|
93
|
+
* are kept verbatim — many of our archived cards write them explicitly even
|
|
94
|
+
* when they match the editor default, and dropping them would produce
|
|
95
|
+
* spurious "missing field" diffs.
|
|
96
|
+
*/
|
|
97
|
+
/**
|
|
98
|
+
* Per-tag editor-default drops. We only list fields the public DSL definitely
|
|
99
|
+
* never reads back. Layout fields (text_align / vertical_align / flex_mode /
|
|
100
|
+
* background_style) look defaultable but archive convention varies — some
|
|
101
|
+
* card vintages write the default explicitly. We pass them through verbatim
|
|
102
|
+
* because, from a patch-link perspective, an extra field on the projected
|
|
103
|
+
* working copy is harmless (Read sees more, find/replace doesn't fail),
|
|
104
|
+
* whereas a missing field that the archived snapshot expected would break
|
|
105
|
+
* downstream comparisons or surprise a model that authored against the
|
|
106
|
+
* complete shape.
|
|
107
|
+
*
|
|
108
|
+
* collapsible_panel.header carries raw editor-only layout fields (position,
|
|
109
|
+
* width, vertical_align) the archived public DSL never writes; those are
|
|
110
|
+
* dropped under their explicit owner tag below.
|
|
111
|
+
*/
|
|
112
|
+
const TAG_DEFAULT_DROPS = {
|
|
113
|
+
column: {
|
|
114
|
+
disabled: false,
|
|
115
|
+
},
|
|
116
|
+
column_set: {
|
|
117
|
+
disabled: false,
|
|
118
|
+
horizontal_spacing: "default",
|
|
119
|
+
},
|
|
120
|
+
button: {
|
|
121
|
+
disabled: false,
|
|
122
|
+
},
|
|
123
|
+
interactive_container: {
|
|
124
|
+
disabled: false,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Maps a `*_value` echo field to the sibling enum it should reconcile with.
|
|
129
|
+
* Both are dropped after reconciliation; the public DSL keeps only the enum
|
|
130
|
+
* field with a string-pixel value when the echo disagreed with the enum.
|
|
131
|
+
*/
|
|
132
|
+
const VALUE_ECHO_TARGETS = {
|
|
133
|
+
horizontal_spacing_value: "horizontal_spacing",
|
|
134
|
+
vertical_spacing_value: "vertical_spacing",
|
|
135
|
+
width_value: "width",
|
|
136
|
+
height_value: "height",
|
|
137
|
+
corner_radius_value: "corner_radius",
|
|
138
|
+
size_value: "size",
|
|
139
|
+
};
|
|
140
|
+
/* ------------------------------------------------------------------ *
|
|
141
|
+
* Entry points
|
|
142
|
+
* ------------------------------------------------------------------ */
|
|
143
|
+
function convertRoot(root, ctx) {
|
|
144
|
+
if (!isRecord(root))
|
|
145
|
+
return root;
|
|
146
|
+
const out = {};
|
|
147
|
+
if (typeof root.schema === "string")
|
|
148
|
+
out.schema = root.schema;
|
|
149
|
+
out.config = convertConfig(isRecord(root.config) ? root.config : {});
|
|
150
|
+
if (isRecord(root.body))
|
|
151
|
+
out.body = convertBody(root.body, ctx);
|
|
152
|
+
if (isRecord(root.header))
|
|
153
|
+
out.header = convertHeader(root.header, ctx);
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Public DSL config the cardkit send path expects: { update_multi: true }.
|
|
158
|
+
* Raw carries editor-only flags (convertVersion / enableForwardInteraction /
|
|
159
|
+
* streamingMode) that the public schema doesn't read; we drop them and
|
|
160
|
+
* synthesize update_multi:true, which is the invariant the cardkit entity
|
|
161
|
+
* create/update path requires (see card-actions.ts:194-198 lint rule).
|
|
162
|
+
*
|
|
163
|
+
* Some archived cards happen to record the editor flags instead of
|
|
164
|
+
* update_multi — that's a quirk of how those cards were saved, not what the
|
|
165
|
+
* public DSL means. The projection above matches what we'd send today.
|
|
166
|
+
*/
|
|
167
|
+
function convertConfig(_node) {
|
|
168
|
+
return { update_multi: true };
|
|
169
|
+
}
|
|
170
|
+
function convertHeader(node, ctx) {
|
|
171
|
+
const property = isRecord(node.property) ? node.property : {};
|
|
172
|
+
const out = convertProperty(property, "header", ctx);
|
|
173
|
+
// Raw stashes the header icon as `udIcon` (an editor-only wrapper around
|
|
174
|
+
// a standard_icon). Projection happens via convertField; here we just
|
|
175
|
+
// verify the rename landed correctly.
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
function convertBody(node, ctx) {
|
|
179
|
+
const property = isRecord(node.property) ? node.property : {};
|
|
180
|
+
return convertProperty(property, "body", ctx);
|
|
181
|
+
}
|
|
182
|
+
function unwrap(node, ctx) {
|
|
183
|
+
const tag = typeof node.tag === "string" ? node.tag : undefined;
|
|
184
|
+
const property = isRecord(node.property) ? node.property : {};
|
|
185
|
+
if (tag === "markdown")
|
|
186
|
+
return rebuildMarkdown(property, ctx);
|
|
187
|
+
// plain_text leaf used inside title/subtitle/alt/hover_tips/button.text/etc.
|
|
188
|
+
// The public DSL keeps only { tag:'plain_text', content }; everything else
|
|
189
|
+
// is editor metadata for layout.
|
|
190
|
+
if (tag === "plain_text") {
|
|
191
|
+
const content = typeof property.content === "string" ? property.content : "";
|
|
192
|
+
return { tag: "plain_text", content };
|
|
193
|
+
}
|
|
194
|
+
// standard_icon used inside button / header / column action.
|
|
195
|
+
// Public shape: { tag:'standard_icon', token, color?, size? }.
|
|
196
|
+
// Raw also ships imageID (fallback render asset, drop), horizontalPadding
|
|
197
|
+
// (editor-only), and a precise widthValue+heightValue pair the public DSL
|
|
198
|
+
// collapses into a single "Wpx Hpx" size string.
|
|
199
|
+
if (tag === "standard_icon") {
|
|
200
|
+
const out = { tag: "standard_icon" };
|
|
201
|
+
if (typeof property.token === "string")
|
|
202
|
+
out.token = property.token;
|
|
203
|
+
if (typeof property.color === "string")
|
|
204
|
+
out.color = property.color;
|
|
205
|
+
const widthPx = isPixelScalar(property.widthValue)
|
|
206
|
+
? pixelOf(property.widthValue)
|
|
207
|
+
: undefined;
|
|
208
|
+
const heightPx = isPixelScalar(property.heightValue)
|
|
209
|
+
? pixelOf(property.heightValue)
|
|
210
|
+
: undefined;
|
|
211
|
+
if (widthPx !== undefined && heightPx !== undefined) {
|
|
212
|
+
out.size = `${widthPx}px ${heightPx}px`;
|
|
213
|
+
}
|
|
214
|
+
else if (isRecord(property.size) && hasSide(property.size))
|
|
215
|
+
out.size = formatBox(property.size);
|
|
216
|
+
else if (isPixelScalar(property.size))
|
|
217
|
+
out.size = `${pixelOf(property.size)}px`;
|
|
218
|
+
else if (typeof property.size === "string")
|
|
219
|
+
out.size = property.size;
|
|
220
|
+
return out;
|
|
221
|
+
}
|
|
222
|
+
// ud_icon is the editor's wrapper for header icons. The public DSL
|
|
223
|
+
// reads it back as a standard_icon — only the token survives.
|
|
224
|
+
if (tag === "ud_icon") {
|
|
225
|
+
const token = typeof property.token === "string" ? property.token : undefined;
|
|
226
|
+
const out = { tag: "standard_icon" };
|
|
227
|
+
if (token)
|
|
228
|
+
out.token = token;
|
|
229
|
+
return out;
|
|
230
|
+
}
|
|
231
|
+
// chart tag. Public shape: { tag:'chart', color_theme?, preview?, chart_spec }.
|
|
232
|
+
// chart_spec is a vchart/vega specification whose field names (xField,
|
|
233
|
+
// yField, bandWidth, cornerRadius, ...) MUST stay camelCase — vega is the
|
|
234
|
+
// chart engine, not flexible cardspec. Raw also carries minLibVersion which
|
|
235
|
+
// the public schema rejects.
|
|
236
|
+
if (tag === "chart") {
|
|
237
|
+
const out = { tag: "chart" };
|
|
238
|
+
if (typeof property.colorTheme === "string")
|
|
239
|
+
out.color_theme = property.colorTheme;
|
|
240
|
+
if (typeof property.preview === "boolean")
|
|
241
|
+
out.preview = property.preview;
|
|
242
|
+
if (property.chartSpec !== undefined)
|
|
243
|
+
out.chart_spec = property.chartSpec;
|
|
244
|
+
// minLibVersion / preview defaults / etc. drop intentionally.
|
|
245
|
+
return out;
|
|
246
|
+
}
|
|
247
|
+
// input tag. The public schema is strict — many editor-only fields
|
|
248
|
+
// (actions, autoResize, disabled:false, showCount, showIcon) cause
|
|
249
|
+
// "unknown property" errors. We allowlist the fields we've seen on
|
|
250
|
+
// archived cards. `required:false` is the editor default and the public
|
|
251
|
+
// schema rejects it on input outside a form context, so we drop the
|
|
252
|
+
// default and keep only an explicit true.
|
|
253
|
+
if (tag === "input") {
|
|
254
|
+
const allow = new Set(["name", "placeholder", "default_value", "value",
|
|
255
|
+
"label", "label_position", "margin", "max_length", "input_type", "width"]);
|
|
256
|
+
const out = { tag: "input" };
|
|
257
|
+
const converted = convertProperty(property, "input", ctx);
|
|
258
|
+
for (const [k, v] of Object.entries(converted)) {
|
|
259
|
+
if (allow.has(k))
|
|
260
|
+
out[k] = v;
|
|
261
|
+
}
|
|
262
|
+
if (converted.required === true)
|
|
263
|
+
out.required = true;
|
|
264
|
+
return out;
|
|
265
|
+
}
|
|
266
|
+
// person tag (used inside columns to render a user avatar/name).
|
|
267
|
+
// Public shape: { tag:'person', user_id, size?, show_avatar?, show_name?, style? }.
|
|
268
|
+
// Raw also ships pillShaped which the public schema rejects ("unknown
|
|
269
|
+
// property pill_shaped"), so we drop it.
|
|
270
|
+
if (tag === "person") {
|
|
271
|
+
const out = { tag: "person" };
|
|
272
|
+
if (typeof property.userID === "string")
|
|
273
|
+
out.user_id = property.userID;
|
|
274
|
+
else if (typeof property.user_id === "string")
|
|
275
|
+
out.user_id = property.user_id;
|
|
276
|
+
if (typeof property.size === "string")
|
|
277
|
+
out.size = property.size;
|
|
278
|
+
if (typeof property.showAvatar === "boolean")
|
|
279
|
+
out.show_avatar = property.showAvatar;
|
|
280
|
+
if (typeof property.showName === "boolean")
|
|
281
|
+
out.show_name = property.showName;
|
|
282
|
+
if (typeof property.style === "string")
|
|
283
|
+
out.style = property.style;
|
|
284
|
+
return out;
|
|
285
|
+
}
|
|
286
|
+
const converted = convertProperty(property, tag, ctx);
|
|
287
|
+
return tag ? { tag, ...converted } : converted;
|
|
288
|
+
}
|
|
289
|
+
/* ------------------------------------------------------------------ *
|
|
290
|
+
* Per-property walker
|
|
291
|
+
* ------------------------------------------------------------------ */
|
|
292
|
+
const DROP = Symbol("drop");
|
|
293
|
+
function convertProperty(property, ownerTag, ctx) {
|
|
294
|
+
const out = {};
|
|
295
|
+
// Capture sibling-disambiguation fields up-front so per-field rules can use
|
|
296
|
+
// them (button.actions needs button.actionType to decide multi_url vs
|
|
297
|
+
// behaviors; the value is then dropped by the regular `action_type` rule).
|
|
298
|
+
const siblings = {
|
|
299
|
+
buttonActionType: ownerTag === "button" && typeof property.actionType === "string"
|
|
300
|
+
? property.actionType
|
|
301
|
+
: undefined,
|
|
302
|
+
};
|
|
303
|
+
// First pass: convert each field individually.
|
|
304
|
+
for (const [rawKey, rawValue] of Object.entries(property)) {
|
|
305
|
+
const result = convertField(rawKey, rawValue, ownerTag, ctx, siblings);
|
|
306
|
+
if (result === DROP)
|
|
307
|
+
continue;
|
|
308
|
+
const [outKey, outValue] = result;
|
|
309
|
+
if (outValue === DROP)
|
|
310
|
+
continue;
|
|
311
|
+
out[outKey] = outValue;
|
|
312
|
+
}
|
|
313
|
+
// Reconcile *_value echoes onto the sibling enum, then drop the echo.
|
|
314
|
+
// The editor mirrors a precise value next to a coarse enum:
|
|
315
|
+
// - widthValue:{type:'pixels',value:72} alongside width:'auto'
|
|
316
|
+
// - widthValue:{type:'builtin_width',value:'default'} (no enum sibling)
|
|
317
|
+
// - horizontalSpacingValue:{type:'pixels',value:6} alongside horizontal_spacing:'default'
|
|
318
|
+
// Public DSL keeps just the enum slot, holding a string-pixel ("6px") or a
|
|
319
|
+
// keyword ("default"). When the echo carries genuinely new info (a pixel
|
|
320
|
+
// count, or a builtin keyword the enum doesn't yet hold), fold it in.
|
|
321
|
+
for (const [echoKey, enumKey] of Object.entries(VALUE_ECHO_TARGETS)) {
|
|
322
|
+
if (!(echoKey in out))
|
|
323
|
+
continue;
|
|
324
|
+
const echoVal = out[echoKey];
|
|
325
|
+
const enumVal = out[enumKey];
|
|
326
|
+
delete out[echoKey];
|
|
327
|
+
if (!isRecord(echoVal))
|
|
328
|
+
continue;
|
|
329
|
+
const echoType = typeof echoVal.type === "string" ? echoVal.type : "";
|
|
330
|
+
const echoValue = echoVal.value;
|
|
331
|
+
// Pixel echo: project as "Npx" when the enum slot is missing or coarse.
|
|
332
|
+
if (echoType.includes("pixels") && typeof echoValue === "number") {
|
|
333
|
+
if (enumVal === undefined ||
|
|
334
|
+
enumVal === "default" ||
|
|
335
|
+
enumVal === "auto" ||
|
|
336
|
+
enumVal === "weighted") {
|
|
337
|
+
out[enumKey] = `${echoValue}px`;
|
|
338
|
+
}
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
// Aspect-ratio echo (img.size_value): { type:'aspect_ratio', value:{height,width} }.
|
|
342
|
+
// Public DSL writes "W:H" verbatim on img.size.
|
|
343
|
+
if (echoType === "aspect_ratio" && isRecord(echoValue)) {
|
|
344
|
+
const w = echoValue.width;
|
|
345
|
+
const h = echoValue.height;
|
|
346
|
+
if (typeof w === "number" && typeof h === "number") {
|
|
347
|
+
out["size"] = `${w}:${h}`;
|
|
348
|
+
}
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
// Width/height pixel pair (img.size_value): { type:'width_height_pixels', value:{width,height} }.
|
|
352
|
+
// Public DSL writes "Wpx Hpx" on img.size — load-bearing for grid layouts;
|
|
353
|
+
// when these images are dropped to "no explicit size" the renderer auto-sizes
|
|
354
|
+
// each cell independently and the grid loses its row alignment.
|
|
355
|
+
if (echoType === "width_height_pixels" && isRecord(echoValue)) {
|
|
356
|
+
const w = echoValue.width;
|
|
357
|
+
const h = echoValue.height;
|
|
358
|
+
if (typeof w === "number" && typeof h === "number") {
|
|
359
|
+
out["size"] = `${w}px ${h}px`;
|
|
360
|
+
}
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
// Builtin keyword echo (e.g. builtin_width:"default"): use the value
|
|
364
|
+
// verbatim when the enum slot is missing. img.size_value of
|
|
365
|
+
// "builtin_image_size:stretch" is the editor default that archives
|
|
366
|
+
// never write — drop it instead of synthesizing size:"stretch".
|
|
367
|
+
if (echoType === "builtin_image_size")
|
|
368
|
+
continue;
|
|
369
|
+
if (echoType.startsWith("builtin_") && typeof echoValue === "string") {
|
|
370
|
+
if (enumVal === undefined)
|
|
371
|
+
out[enumKey] = echoValue;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
// column_width_weighted echoes are redundant with width:'weighted' / weight, drop.
|
|
375
|
+
}
|
|
376
|
+
// Drop per-tag editor defaults.
|
|
377
|
+
if (ownerTag && TAG_DEFAULT_DROPS[ownerTag]) {
|
|
378
|
+
const defaults = TAG_DEFAULT_DROPS[ownerTag];
|
|
379
|
+
for (const [k, defVal] of Object.entries(defaults)) {
|
|
380
|
+
if (out[k] === defVal)
|
|
381
|
+
delete out[k];
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return out;
|
|
385
|
+
}
|
|
386
|
+
function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
|
|
387
|
+
if (rawKey === "originTag" || rawKey === "markdownElements")
|
|
388
|
+
return DROP;
|
|
389
|
+
const key = snake(rawKey);
|
|
390
|
+
if (RAW_ONLY_FIELDS.has(key))
|
|
391
|
+
return DROP;
|
|
392
|
+
// `actions: []` is the raw editor's "no click action wired up" placeholder.
|
|
393
|
+
// The public DSL omits it. Non-empty actions arrays are kept and remapped
|
|
394
|
+
// by per-tag rules below.
|
|
395
|
+
if (key === "actions" && Array.isArray(rawValue) && rawValue.length === 0) {
|
|
396
|
+
return DROP;
|
|
397
|
+
}
|
|
398
|
+
// Box fields (padding / margin): { top, right, bottom, left } → "Tpx Rpx Bpx Lpx".
|
|
399
|
+
if ((key === "padding" || key === "margin") && isRecord(rawValue) && hasSide(rawValue)) {
|
|
400
|
+
return [key, formatBox(rawValue)];
|
|
401
|
+
}
|
|
402
|
+
// *_value echo fields: keep the raw object until reconciliation can fold
|
|
403
|
+
// it back onto the sibling enum. Reconciliation runs in convertProperty
|
|
404
|
+
// after every field has been visited.
|
|
405
|
+
if (key in VALUE_ECHO_TARGETS) {
|
|
406
|
+
return [key, rawValue];
|
|
407
|
+
}
|
|
408
|
+
// Other scalar pixel objects (corner_radius, icon size, etc.) get folded
|
|
409
|
+
// into a "Npx" string immediately.
|
|
410
|
+
if (isPixelScalar(rawValue)) {
|
|
411
|
+
return [key, `${pixelOf(rawValue)}px`];
|
|
412
|
+
}
|
|
413
|
+
// img: imageID -> img_key (resolve via attachment table).
|
|
414
|
+
if (ownerTag === "img" && key === "image_id") {
|
|
415
|
+
const id = typeof rawValue === "string" || typeof rawValue === "number" ? String(rawValue) : undefined;
|
|
416
|
+
const origin = id !== undefined ? ctx.images[id]?.origin_key : undefined;
|
|
417
|
+
if (origin)
|
|
418
|
+
return ["img_key", origin];
|
|
419
|
+
return [key, rawValue];
|
|
420
|
+
}
|
|
421
|
+
if (ownerTag === "img" && IMG_RAW_ONLY_FIELDS.has(key))
|
|
422
|
+
return DROP;
|
|
423
|
+
// alt / hover_tips / button.text / column header text: nested plain_text.
|
|
424
|
+
if ((key === "alt" || key === "hover_tips") && isRecord(rawValue) && rawValue.tag === "plain_text") {
|
|
425
|
+
const p = isRecord(rawValue.property) ? rawValue.property : {};
|
|
426
|
+
return [key, { tag: "plain_text", content: typeof p.content === "string" ? p.content : "" }];
|
|
427
|
+
}
|
|
428
|
+
// button.text, interactive_container hover_tips: same plain_text leaf treatment.
|
|
429
|
+
if (key === "text" && isRecord(rawValue) && rawValue.tag === "plain_text") {
|
|
430
|
+
const p = isRecord(rawValue.property) ? rawValue.property : {};
|
|
431
|
+
return [key, { tag: "plain_text", content: typeof p.content === "string" ? p.content : "" }];
|
|
432
|
+
}
|
|
433
|
+
// header.udIcon → header.icon (rebuilt as standard_icon). The udIcon
|
|
434
|
+
// wrapper in raw is { id, tag:'ud_icon', property:{ imageID, token, style } };
|
|
435
|
+
// in public DSL this lives at header.icon as { tag:'standard_icon', token }.
|
|
436
|
+
if (ownerTag === "header" && key === "ud_icon" && isRecord(rawValue) && rawValue.tag === "ud_icon") {
|
|
437
|
+
const p = isRecord(rawValue.property) ? rawValue.property : {};
|
|
438
|
+
const token = typeof p.token === "string" ? p.token : undefined;
|
|
439
|
+
if (!token)
|
|
440
|
+
return DROP;
|
|
441
|
+
return ["icon", { tag: "standard_icon", token }];
|
|
442
|
+
}
|
|
443
|
+
// collapsible_panel.header is a plain bag (not tag/property wrapped). Its
|
|
444
|
+
// raw shape carries layout fields the public DSL never reads — drop them.
|
|
445
|
+
if (ownerTag === "collapsible_panel" && key === "header" && isRecord(rawValue)) {
|
|
446
|
+
const cleaned = {};
|
|
447
|
+
for (const [k, v] of Object.entries(rawValue)) {
|
|
448
|
+
const sk = snake(k);
|
|
449
|
+
// editor-only layout residue inside a collapsible_panel header.
|
|
450
|
+
if (sk === "position" || sk === "width" || sk === "vertical_align")
|
|
451
|
+
continue;
|
|
452
|
+
const sub = convertField(k, v, "collapsible_panel_header", ctx, siblings);
|
|
453
|
+
if (sub === DROP)
|
|
454
|
+
continue;
|
|
455
|
+
const [subKey, subVal] = sub;
|
|
456
|
+
if (subVal === DROP)
|
|
457
|
+
continue;
|
|
458
|
+
cleaned[subKey] = subVal;
|
|
459
|
+
}
|
|
460
|
+
return [key, cleaned];
|
|
461
|
+
}
|
|
462
|
+
// button.actions → behaviors / multi_url. Raw distinguishes:
|
|
463
|
+
// actionType:"multi" + actions:[{action:{url},type:"open_url"}]
|
|
464
|
+
// -> behaviors:[{type:"open_url", default_url:url, pc_url, ios_url, android_url}]
|
|
465
|
+
// actionType:"link" + actions:[{action:{url},type:"open_url"}]
|
|
466
|
+
// -> multi_url:{url, pc_url, ios_url, android_url}
|
|
467
|
+
// action_request callbacks live above the DSL (cardkit entity handles
|
|
468
|
+
// them via card_id-stamped buttons); we drop them.
|
|
469
|
+
// The `actionType` field is editor-internal, dropped after dispatch.
|
|
470
|
+
if (ownerTag === "button" && key === "action_type")
|
|
471
|
+
return DROP;
|
|
472
|
+
if (ownerTag === "button" && key === "actions" && Array.isArray(rawValue)) {
|
|
473
|
+
const openUrls = [];
|
|
474
|
+
for (const a of rawValue) {
|
|
475
|
+
if (!isRecord(a))
|
|
476
|
+
continue;
|
|
477
|
+
const inner = isRecord(a.action) ? a.action : {};
|
|
478
|
+
const t = typeof a.type === "string" ? a.type : undefined;
|
|
479
|
+
if (t === "open_url" && typeof inner.url === "string")
|
|
480
|
+
openUrls.push(inner.url);
|
|
481
|
+
// action_request callbacks belong to the cardkit entity layer; drop.
|
|
482
|
+
}
|
|
483
|
+
if (openUrls.length === 0)
|
|
484
|
+
return DROP;
|
|
485
|
+
if (siblings.buttonActionType === "link") {
|
|
486
|
+
return ["multi_url", { url: openUrls[0] }];
|
|
487
|
+
}
|
|
488
|
+
// Default to behaviors (matches actionType:"multi" and the more common shape).
|
|
489
|
+
return [
|
|
490
|
+
"behaviors",
|
|
491
|
+
openUrls.map((url) => ({ type: "open_url", default_url: url })),
|
|
492
|
+
];
|
|
493
|
+
}
|
|
494
|
+
// interactive_container.actions: { action:{ url }, type:'open_url' }
|
|
495
|
+
// -> [{ type:'open_url', url }] (matches the public DSL on interactive_container).
|
|
496
|
+
if (ownerTag === "interactive_container" && key === "actions" && Array.isArray(rawValue)) {
|
|
497
|
+
const acts = rawValue.map((a) => {
|
|
498
|
+
if (!isRecord(a))
|
|
499
|
+
return a;
|
|
500
|
+
const inner = isRecord(a.action) ? a.action : {};
|
|
501
|
+
const t = typeof a.type === "string" ? a.type : undefined;
|
|
502
|
+
if (t === "open_url" && typeof inner.url === "string") {
|
|
503
|
+
return { type: "open_url", url: inner.url };
|
|
504
|
+
}
|
|
505
|
+
return convertGeneric(a, ctx);
|
|
506
|
+
});
|
|
507
|
+
return [key, acts];
|
|
508
|
+
}
|
|
509
|
+
// border: { borderColor, cornerRadius:{type,value} } -> { color, corner_radius:"Npx" }
|
|
510
|
+
if (key === "border" && isRecord(rawValue)) {
|
|
511
|
+
const b = rawValue;
|
|
512
|
+
const out = {};
|
|
513
|
+
if (typeof b.borderColor === "string")
|
|
514
|
+
out.color = b.borderColor;
|
|
515
|
+
else if (typeof b.color === "string")
|
|
516
|
+
out.color = b.color;
|
|
517
|
+
if (isPixelScalar(b.cornerRadius))
|
|
518
|
+
out.corner_radius = `${pixelOf(b.cornerRadius)}px`;
|
|
519
|
+
else if (typeof b.cornerRadius === "string")
|
|
520
|
+
out.corner_radius = b.cornerRadius;
|
|
521
|
+
else if (b.cornerRadius !== undefined)
|
|
522
|
+
out.corner_radius = b.cornerRadius;
|
|
523
|
+
// Pass through other border keys verbatim (snake_cased) for forward-compat.
|
|
524
|
+
for (const [bk, bv] of Object.entries(b)) {
|
|
525
|
+
if (bk === "borderColor" || bk === "cornerRadius" || bk === "color")
|
|
526
|
+
continue;
|
|
527
|
+
out[snake(bk)] = convertGeneric(bv, ctx);
|
|
528
|
+
}
|
|
529
|
+
return [key, out];
|
|
530
|
+
}
|
|
531
|
+
// url object on link / open_url: { url, androidURL, iosURL, pcURL, harmonyURL }.
|
|
532
|
+
if (key === "url" && isRecord(rawValue)) {
|
|
533
|
+
const v = rawValue;
|
|
534
|
+
const main = typeof v.url === "string" ? v.url : "";
|
|
535
|
+
const others = ["androidURL", "iosURL", "pcURL", "harmonyURL"]
|
|
536
|
+
.map((k) => v[k])
|
|
537
|
+
.filter((x) => typeof x === "string" && x.length > 0);
|
|
538
|
+
if (others.length === 0)
|
|
539
|
+
return [key, main];
|
|
540
|
+
return [
|
|
541
|
+
key,
|
|
542
|
+
{
|
|
543
|
+
url: main,
|
|
544
|
+
android_url: typeof v.androidURL === "string" ? v.androidURL : "",
|
|
545
|
+
ios_url: typeof v.iosURL === "string" ? v.iosURL : "",
|
|
546
|
+
pc_url: typeof v.pcURL === "string" ? v.pcURL : "",
|
|
547
|
+
},
|
|
548
|
+
];
|
|
549
|
+
}
|
|
550
|
+
// markdown.icon (in form columns) lives under a column.markdown wrapper —
|
|
551
|
+
// generic recursion handles it via unwrap.
|
|
552
|
+
// Generic recursion for everything else.
|
|
553
|
+
return [key, convertGeneric(rawValue, ctx)];
|
|
554
|
+
}
|
|
555
|
+
/* ------------------------------------------------------------------ *
|
|
556
|
+
* Markdown re-stitch
|
|
557
|
+
* ------------------------------------------------------------------ */
|
|
558
|
+
/**
|
|
559
|
+
* Markdown elements in raw split the original source string across multiple
|
|
560
|
+
* children: plain_text segments (optionally with bold/color), at_all, br,
|
|
561
|
+
* link, code_span, text_tag, etc. We re-stitch them into a single content
|
|
562
|
+
* string with inline markdown markers — bold (asterisk asterisk), font tag,
|
|
563
|
+
* link, code span, br -> newline, at -> at-tag.
|
|
564
|
+
*/
|
|
565
|
+
function rebuildMarkdown(property, ctx) {
|
|
566
|
+
const out = { tag: "markdown" };
|
|
567
|
+
const elements = Array.isArray(property.elements) ? property.elements : [];
|
|
568
|
+
let content = "";
|
|
569
|
+
for (const child of elements) {
|
|
570
|
+
if (!isRecord(child))
|
|
571
|
+
continue;
|
|
572
|
+
content += childToMarkdown(child, ctx);
|
|
573
|
+
}
|
|
574
|
+
if (content)
|
|
575
|
+
out.content = content;
|
|
576
|
+
for (const [rawKey, rawValue] of Object.entries(property)) {
|
|
577
|
+
if (rawKey === "elements" || rawKey === "markdownElements" || rawKey === "originTag")
|
|
578
|
+
continue;
|
|
579
|
+
// Raw markdown ships both `icon` (standard_icon) and `udIcon` (ud_icon)
|
|
580
|
+
// pointing at the same token. The public DSL keeps only `icon`. Drop the
|
|
581
|
+
// udIcon shadow.
|
|
582
|
+
if (rawKey === "udIcon")
|
|
583
|
+
continue;
|
|
584
|
+
if (rawKey === "textStyle") {
|
|
585
|
+
// Project textStyle.size onto a flat text_size field. raw mirrors it
|
|
586
|
+
// as platformSize too, but size is the canonical anchor.
|
|
587
|
+
const ts = isRecord(rawValue) ? rawValue : {};
|
|
588
|
+
const size = typeof ts.size === "string" ? ts.size : undefined;
|
|
589
|
+
if (size)
|
|
590
|
+
out.text_size = size;
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
const result = convertField(rawKey, rawValue, "markdown", ctx);
|
|
594
|
+
if (result === DROP)
|
|
595
|
+
continue;
|
|
596
|
+
const [outKey, outValue] = result;
|
|
597
|
+
if (outValue === DROP)
|
|
598
|
+
continue;
|
|
599
|
+
out[outKey] = outValue;
|
|
600
|
+
}
|
|
601
|
+
return out;
|
|
602
|
+
}
|
|
603
|
+
function childToMarkdown(child, ctx) {
|
|
604
|
+
const tag = child.tag;
|
|
605
|
+
const prop = isRecord(child.property) ? child.property : {};
|
|
606
|
+
switch (tag) {
|
|
607
|
+
case "plain_text": {
|
|
608
|
+
let out = typeof prop.content === "string" ? prop.content : "";
|
|
609
|
+
const ts = isRecord(prop.textStyle) ? prop.textStyle : undefined;
|
|
610
|
+
const color = ts && typeof ts.color === "string" ? ts.color : undefined;
|
|
611
|
+
const attrs = ts && Array.isArray(ts.attributes) ? ts.attributes : [];
|
|
612
|
+
if (attrs.includes("bold"))
|
|
613
|
+
out = `**${out}**`;
|
|
614
|
+
if (color)
|
|
615
|
+
out = `<font color='${color}'>${out}</font>`;
|
|
616
|
+
return out;
|
|
617
|
+
}
|
|
618
|
+
case "br":
|
|
619
|
+
return "\n";
|
|
620
|
+
case "at_all":
|
|
621
|
+
// @-all in raw uses an at_users entry keyed "all". The public mention
|
|
622
|
+
// syntax for everyone is <at id=all></at>.
|
|
623
|
+
return "<at id=all></at>";
|
|
624
|
+
case "at": {
|
|
625
|
+
// Single-user @: raw stores user_id under the property; if it
|
|
626
|
+
// references the at_users attachment table, pull it from there.
|
|
627
|
+
const userId = typeof prop.userId === "string" ? prop.userId
|
|
628
|
+
: typeof prop.user_id === "string" ? prop.user_id
|
|
629
|
+
: (() => {
|
|
630
|
+
const key = typeof prop.atUserKey === "string" ? prop.atUserKey : undefined;
|
|
631
|
+
if (key && ctx.atUsers[key])
|
|
632
|
+
return ctx.atUsers[key].user_id;
|
|
633
|
+
return undefined;
|
|
634
|
+
})();
|
|
635
|
+
return userId ? `<at id=${userId}></at>` : "<at></at>";
|
|
636
|
+
}
|
|
637
|
+
case "link": {
|
|
638
|
+
const text = typeof prop.content === "string" ? prop.content : "";
|
|
639
|
+
const urlObj = isRecord(prop.url) ? prop.url : undefined;
|
|
640
|
+
const url = urlObj && typeof urlObj.url === "string" ? urlObj.url : "";
|
|
641
|
+
return `[${text}](${url})`;
|
|
642
|
+
}
|
|
643
|
+
case "code_span": {
|
|
644
|
+
const text = typeof prop.content === "string" ? prop.content : "";
|
|
645
|
+
return `\`${text}\``;
|
|
646
|
+
}
|
|
647
|
+
case "text_tag": {
|
|
648
|
+
const color = typeof prop.color === "string" ? prop.color : undefined;
|
|
649
|
+
const inner = isRecord(prop.text) ? prop.text : undefined;
|
|
650
|
+
const innerProp = inner && isRecord(inner.property) ? inner.property : undefined;
|
|
651
|
+
const innerContent = innerProp && typeof innerProp.content === "string" ? innerProp.content : "";
|
|
652
|
+
if (color)
|
|
653
|
+
return `<text_tag color='${color}'>${innerContent}</text_tag>`;
|
|
654
|
+
return `<text_tag>${innerContent}</text_tag>`;
|
|
655
|
+
}
|
|
656
|
+
case "code_block": {
|
|
657
|
+
const lang = typeof prop.language === "string" ? prop.language : "";
|
|
658
|
+
const blocks = Array.isArray(prop.contents) ? prop.contents : [];
|
|
659
|
+
let body = "";
|
|
660
|
+
for (const blk of blocks) {
|
|
661
|
+
if (!isRecord(blk))
|
|
662
|
+
continue;
|
|
663
|
+
const inner = Array.isArray(blk.contents) ? blk.contents : [];
|
|
664
|
+
for (const seg of inner) {
|
|
665
|
+
if (isRecord(seg) && typeof seg.content === "string")
|
|
666
|
+
body += seg.content;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
return `\n\`\`\`${lang}\n${body}\`\`\`\n`;
|
|
670
|
+
}
|
|
671
|
+
case "list": {
|
|
672
|
+
// raw list: { items: [{ elements:[plain_text...], level:0|1|..., type:'ul'|'ol' }] }
|
|
673
|
+
// Project to inline markdown bullets / numbers, level*2-space indent.
|
|
674
|
+
// We emit a leading "\n" only — the upstream br/plain_text in the
|
|
675
|
+
// sibling stream contributes its own newline, which stacks to the
|
|
676
|
+
// archived convention of "...prev_line\n\n- bullet".
|
|
677
|
+
const items = Array.isArray(prop.items) ? prop.items : [];
|
|
678
|
+
const lines = [];
|
|
679
|
+
let counter = 0;
|
|
680
|
+
let lastType;
|
|
681
|
+
for (const item of items) {
|
|
682
|
+
if (!isRecord(item))
|
|
683
|
+
continue;
|
|
684
|
+
const level = typeof item.level === "number" ? item.level : 0;
|
|
685
|
+
const type = typeof item.type === "string" ? item.type : "ul";
|
|
686
|
+
if (type !== lastType)
|
|
687
|
+
counter = 0;
|
|
688
|
+
lastType = type;
|
|
689
|
+
const indent = " ".repeat(level);
|
|
690
|
+
const inner = Array.isArray(item.elements) ? item.elements : [];
|
|
691
|
+
let text = "";
|
|
692
|
+
for (const seg of inner) {
|
|
693
|
+
if (!isRecord(seg))
|
|
694
|
+
continue;
|
|
695
|
+
text += childToMarkdown(seg, ctx);
|
|
696
|
+
}
|
|
697
|
+
if (type === "ol") {
|
|
698
|
+
counter += 1;
|
|
699
|
+
lines.push(`${indent}${counter}. ${text}`);
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
lines.push(`${indent}- ${text}`);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return `\n${lines.join("\n")}`;
|
|
706
|
+
}
|
|
707
|
+
case "heading": {
|
|
708
|
+
// raw heading: { property: { elements:[plain_text...], level:1|2|3|... } }
|
|
709
|
+
// Public DSL writes "# " / "## " / "### " inline.
|
|
710
|
+
const level = typeof prop.level === "number" ? prop.level : 1;
|
|
711
|
+
const inner = Array.isArray(prop.elements) ? prop.elements : [];
|
|
712
|
+
let body = "";
|
|
713
|
+
for (const seg of inner) {
|
|
714
|
+
if (isRecord(seg))
|
|
715
|
+
body += childToMarkdown(seg, ctx);
|
|
716
|
+
}
|
|
717
|
+
return `${"#".repeat(level)} ${body}`;
|
|
718
|
+
}
|
|
719
|
+
case "blockquote": {
|
|
720
|
+
const inner = Array.isArray(prop.elements) ? prop.elements : [];
|
|
721
|
+
let body = "";
|
|
722
|
+
for (const seg of inner) {
|
|
723
|
+
if (isRecord(seg))
|
|
724
|
+
body += childToMarkdown(seg, ctx);
|
|
725
|
+
}
|
|
726
|
+
// archive convention: blockquote sits on its own paragraph, with a "> "
|
|
727
|
+
// prefix on every line and blank lines on both sides. Raw doesn't emit
|
|
728
|
+
// br around blockquote, so we supply both breaks ourselves.
|
|
729
|
+
return `\n\n> ${body.replace(/\n/g, "\n> ")}\n\n`;
|
|
730
|
+
}
|
|
731
|
+
default:
|
|
732
|
+
// Unknown leaf — render its `content` if any, else nothing. We don't
|
|
733
|
+
// throw, since raw may add new inline element types.
|
|
734
|
+
return typeof prop.content === "string" ? prop.content : "";
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
/* ------------------------------------------------------------------ *
|
|
738
|
+
* Generic recursion + helpers
|
|
739
|
+
* ------------------------------------------------------------------ */
|
|
740
|
+
function convertGeneric(value, ctx) {
|
|
741
|
+
if (Array.isArray(value)) {
|
|
742
|
+
return value.map((item) => {
|
|
743
|
+
if (isRecord(item) && typeof item.tag === "string" && isRecord(item.property)) {
|
|
744
|
+
return unwrap(item, ctx);
|
|
745
|
+
}
|
|
746
|
+
return convertGeneric(item, ctx);
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
if (isRecord(value)) {
|
|
750
|
+
if (typeof value.tag === "string" && isRecord(value.property)) {
|
|
751
|
+
return unwrap(value, ctx);
|
|
752
|
+
}
|
|
753
|
+
// Box-shaped object at a generic depth: format it.
|
|
754
|
+
if (hasSide(value)) {
|
|
755
|
+
return formatBox(value);
|
|
756
|
+
}
|
|
757
|
+
if (isPixelScalar(value)) {
|
|
758
|
+
return `${pixelOf(value)}px`;
|
|
759
|
+
}
|
|
760
|
+
const out = {};
|
|
761
|
+
for (const [k, v] of Object.entries(value)) {
|
|
762
|
+
out[snake(k)] = convertGeneric(v, ctx);
|
|
763
|
+
}
|
|
764
|
+
return out;
|
|
765
|
+
}
|
|
766
|
+
return value;
|
|
767
|
+
}
|
|
768
|
+
function isRecord(v) {
|
|
769
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
770
|
+
}
|
|
771
|
+
function hasSide(v) {
|
|
772
|
+
return ("top" in v || "bottom" in v || "left" in v || "right" in v) &&
|
|
773
|
+
Object.values(v).some((side) => isRecord(side) && "type" in side && "value" in side);
|
|
774
|
+
}
|
|
775
|
+
function formatBox(v) {
|
|
776
|
+
return `${pixelOf(v.top)}px ${pixelOf(v.right)}px ${pixelOf(v.bottom)}px ${pixelOf(v.left)}px`;
|
|
777
|
+
}
|
|
778
|
+
function isPixelScalar(v) {
|
|
779
|
+
if (!isRecord(v))
|
|
780
|
+
return false;
|
|
781
|
+
return typeof v.type === "string" && v.type.includes("pixels") && typeof v.value === "number";
|
|
782
|
+
}
|
|
783
|
+
function pixelOf(side) {
|
|
784
|
+
if (!isRecord(side))
|
|
785
|
+
return 0;
|
|
786
|
+
const v = side.value;
|
|
787
|
+
if (typeof v === "number")
|
|
788
|
+
return v;
|
|
789
|
+
if (typeof v === "string") {
|
|
790
|
+
const n = Number(v);
|
|
791
|
+
return Number.isFinite(n) ? n : 0;
|
|
792
|
+
}
|
|
793
|
+
return 0;
|
|
794
|
+
}
|
|
795
|
+
function snake(key) {
|
|
796
|
+
return key
|
|
797
|
+
.replace(/ID$/g, "_id")
|
|
798
|
+
.replace(/URL$/g, "_url")
|
|
799
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2")
|
|
800
|
+
.replace(/([a-z\d])([A-Z])/g, "$1_$2")
|
|
801
|
+
.toLowerCase();
|
|
802
|
+
}
|
|
803
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "feishu-raw-card-to-dsl",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "把飞书 im.message.get 的 raw_card_content 编辑器内部 envelope 转换为公开 JSON Schema 2.0 DSL,规避 user_card_content 丢失 column.padding 等字段的问题",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"feishu",
|
|
7
|
+
"lark",
|
|
8
|
+
"card",
|
|
9
|
+
"im",
|
|
10
|
+
"card-dsl"
|
|
11
|
+
],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.json",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"prepublishOnly": "pnpm build && pnpm test"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/<TODO>/feishu-raw-card-to-dsl.git"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"typescript": "^5.8.3",
|
|
42
|
+
"vitest": "^2.1.8"
|
|
43
|
+
}
|
|
44
|
+
}
|