@open-feishu-card/adapter 0.3.4 → 0.3.6

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/index.js CHANGED
@@ -604,6 +604,65 @@ function parseMarkdown(content) {
604
604
  return out;
605
605
  }
606
606
 
607
+ // src/expand-dsl-colors.ts
608
+ function readColorRegistry(card) {
609
+ const config = isRecord(card.config) ? card.config : void 0;
610
+ const style = config && isRecord(config.style) ? config.style : void 0;
611
+ const color = style && isRecord(style.color) ? style.color : void 0;
612
+ if (!color) return {};
613
+ const out = {};
614
+ for (const [key, value] of Object.entries(color)) {
615
+ if (!isRecord(value)) continue;
616
+ const light = typeof value.light_mode === "string" ? value.light_mode : typeof value.lightMode === "string" ? value.lightMode : void 0;
617
+ const dark = typeof value.dark_mode === "string" ? value.dark_mode : typeof value.darkMode === "string" ? value.darkMode : void 0;
618
+ if (light && dark) out[key] = { light_mode: light, dark_mode: dark };
619
+ }
620
+ return out;
621
+ }
622
+ function isCustomColorAlias(value) {
623
+ return typeof value === "string" && value.startsWith("cus-");
624
+ }
625
+ function expandBackgroundStyleAlias(style, registry) {
626
+ if (!isCustomColorAlias(style)) return void 0;
627
+ const entry = registry[style];
628
+ if (!entry) return void 0;
629
+ return { light_mode: entry.light_mode, dark_mode: entry.dark_mode };
630
+ }
631
+ function expandTextStyleColor(textStyle, registry) {
632
+ if (!textStyle) return textStyle;
633
+ const color = typeof textStyle.color === "string" ? textStyle.color.trim() : void 0;
634
+ if (!isCustomColorAlias(color)) return textStyle;
635
+ const entry = registry[color];
636
+ if (!entry) return textStyle;
637
+ const { color: _drop, ...rest } = textStyle;
638
+ return {
639
+ ...rest,
640
+ customColor: { lightMode: entry.light_mode, darkMode: entry.dark_mode }
641
+ };
642
+ }
643
+ function expandMarkdownElements(elements, registry) {
644
+ if (!Array.isArray(elements)) return elements;
645
+ return elements.map((el) => {
646
+ const property = el.property ? { ...el.property } : void 0;
647
+ if (!property) return el;
648
+ if (Array.isArray(property.elements)) {
649
+ property.elements = expandMarkdownElements(property.elements, registry);
650
+ }
651
+ if (property.textStyle) {
652
+ const expanded = expandTextStyleColor(property.textStyle, registry);
653
+ if (expanded) property.textStyle = expanded;
654
+ }
655
+ return property === el.property ? el : { ...el, property };
656
+ });
657
+ }
658
+ function wrapMarkdownContentWithFontColor(content, fontColor) {
659
+ if (!fontColor || !content || /<font\s+color/i.test(content)) return content;
660
+ return `<font color='${fontColor}'>${content}</font>`;
661
+ }
662
+ function isRecord(v) {
663
+ return typeof v === "object" && v !== null && !Array.isArray(v);
664
+ }
665
+
607
666
  // src/dsl-to-raw.ts
608
667
  var KEY_RENAME = {
609
668
  text_align: "textAlign",
@@ -629,14 +688,22 @@ var KEY_RENAME = {
629
688
  };
630
689
  var TEXT_LEAF_KEYS = /* @__PURE__ */ new Set(["title", "subtitle", "alt", "hover_tips", "placeholder"]);
631
690
  function dslToRaw(dsl) {
632
- const root = isRecord(dsl) ? dsl : {};
633
- const card = isRecord(root.card) ? root.card : isRecord(root.json_card) ? root.json_card : root;
691
+ const root = isRecord2(dsl) ? dsl : {};
692
+ const card = unwrapCard(root);
693
+ const colors = readColorRegistry(card);
634
694
  const out = { schema: typeof card.schema === "string" ? card.schema : "2.0" };
635
- if (isRecord(card.header)) out.header = convertHeader(card.header);
636
- if (isRecord(card.body)) out.body = convertBody(card.body);
695
+ if (isRecord2(card.config)) out.config = { ...card.config };
696
+ if (isRecord2(card.header)) out.header = convertHeader(card.header, colors);
697
+ if (isRecord2(card.body)) out.body = convertBody(card.body, colors);
637
698
  return out;
638
699
  }
639
- function convertHeader(header) {
700
+ function unwrapCard(root) {
701
+ if (isRecord2(root.dsl)) return root.dsl;
702
+ if (isRecord2(root.card)) return root.card;
703
+ if (isRecord2(root.json_card)) return root.json_card;
704
+ return root;
705
+ }
706
+ function convertHeader(header, colors) {
640
707
  const property = {};
641
708
  for (const [k, v] of Object.entries(header)) {
642
709
  if (k === "tag") continue;
@@ -648,32 +715,32 @@ function convertHeader(header) {
648
715
  property[k] = wrapTextLeaf(v);
649
716
  continue;
650
717
  }
651
- if ((k === "icon" || k === "ud_icon") && isRecord(v)) {
652
- property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v);
718
+ if ((k === "icon" || k === "ud_icon") && isRecord2(v)) {
719
+ property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v, colors);
653
720
  continue;
654
721
  }
655
722
  if (k === "text_tag_list" && Array.isArray(v)) {
656
- property.text_tag_list = v.map(convertNode);
723
+ property.text_tag_list = v.map((item) => convertNode(item, colors));
657
724
  continue;
658
725
  }
659
- property[renameKey(k)] = coerceValue(k, v);
726
+ property[renameKey(k)] = coerceValue(k, v, colors);
660
727
  }
661
728
  return { tag: "card_header", property };
662
729
  }
663
- function convertBody(body) {
664
- const property = buildProperty(body, "body");
665
- const elements = Array.isArray(body.elements) ? body.elements.map(convertNode) : [];
730
+ function convertBody(body, colors) {
731
+ const property = buildProperty(body, "body", colors);
732
+ const elements = Array.isArray(body.elements) ? body.elements.map((n) => convertNode(n, colors)) : [];
666
733
  property.elements = elements.filter(Boolean);
667
734
  return { tag: "body", property };
668
735
  }
669
- function convertNode(node) {
670
- if (isRecord(node) && typeof node.tag === "string") return convertEl(node);
736
+ function convertNode(node, colors) {
737
+ if (isRecord2(node) && typeof node.tag === "string") return convertEl(node, colors);
671
738
  return node;
672
739
  }
673
- function convertEl(el) {
740
+ function convertEl(el, colors) {
674
741
  const tag = String(el.tag);
675
742
  if (tag === "person") {
676
- const property = buildProperty(el, "person_v1");
743
+ const property = buildProperty(el, "person_v1", colors);
677
744
  if (property.style === "capsule") {
678
745
  property.pillShaped = true;
679
746
  delete property.style;
@@ -681,16 +748,22 @@ function convertEl(el) {
681
748
  return { tag: "person_v1", property };
682
749
  }
683
750
  if (tag === "markdown" || tag === "lark_md") {
684
- const property = buildProperty(el, "markdown");
685
- if (typeof el.content === "string") property.elements = parseMarkdown(el.content);
751
+ const property = buildProperty(el, "markdown", colors);
752
+ const fontColor = typeof el.font_color === "string" ? el.font_color : void 0;
753
+ let content = typeof el.content === "string" ? el.content : "";
754
+ content = wrapMarkdownContentWithFontColor(content, fontColor);
755
+ if (content) {
756
+ property.elements = expandMarkdownElements(parseMarkdown(content), colors);
757
+ }
686
758
  delete property.content;
759
+ delete property.font_color;
687
760
  return { tag: "markdown", property };
688
761
  }
689
762
  if (tag === "table") {
690
- return { tag, property: convertTableProperty(el) };
763
+ return { tag, property: convertTableProperty(el, colors) };
691
764
  }
692
765
  if (tag === "audio" || tag === "video") {
693
- const property = buildProperty(el, tag);
766
+ const property = buildProperty(el, tag, colors);
694
767
  if (tag === "audio" && el.width != null) {
695
768
  delete property.width;
696
769
  if (el.width === "fill" || el.width === "default") {
@@ -708,14 +781,14 @@ function convertEl(el) {
708
781
  }
709
782
  return { tag, property };
710
783
  }
711
- return { tag, property: buildProperty(el, tag) };
784
+ return { tag, property: buildProperty(el, tag, colors) };
712
785
  }
713
- function convertTableProperty(el) {
714
- const property = buildProperty(el, "table");
786
+ function convertTableProperty(el, colors) {
787
+ const property = buildProperty(el, "table", colors);
715
788
  const columns = Array.isArray(property.columns) ? property.columns : [];
716
789
  const mdColNames = /* @__PURE__ */ new Set();
717
790
  for (const col of columns) {
718
- if (!isRecord(col)) continue;
791
+ if (!isRecord2(col)) continue;
719
792
  const dt = col.data_type ?? col.dataType;
720
793
  if (dt === "lark_md" || dt === "markdown") {
721
794
  const name = typeof col.name === "string" ? col.name : "";
@@ -724,7 +797,7 @@ function convertTableProperty(el) {
724
797
  }
725
798
  if (!mdColNames.size || !Array.isArray(property.rows)) return property;
726
799
  property.rows = property.rows.map((row) => {
727
- if (!isRecord(row)) return row;
800
+ if (!isRecord2(row)) return row;
728
801
  const out = { ...row };
729
802
  for (const name of mdColNames) {
730
803
  const cell = out[name];
@@ -732,7 +805,10 @@ function convertTableProperty(el) {
732
805
  out[name] = {
733
806
  data: {
734
807
  tag: "markdown",
735
- property: { elements: parseMarkdown(cell), originTag: "lark_md" }
808
+ property: {
809
+ elements: expandMarkdownElements(parseMarkdown(cell), colors),
810
+ originTag: "lark_md"
811
+ }
736
812
  }
737
813
  };
738
814
  }
@@ -741,10 +817,17 @@ function convertTableProperty(el) {
741
817
  });
742
818
  return property;
743
819
  }
744
- function buildProperty(el, tag) {
820
+ function buildProperty(el, tag, colors) {
745
821
  const property = {};
746
822
  for (const [k, v] of Object.entries(el)) {
747
823
  if (k === "tag" || k === "id") continue;
824
+ if ((k === "background_style" || k === "backgroundStyle") && (tag === "column" || tag === "column_set")) {
825
+ const renamed = renameKey(k);
826
+ property[renamed] = v;
827
+ const expanded = expandBackgroundStyleAlias(v, colors);
828
+ if (expanded) property.customBackgroundStyle = expanded;
829
+ continue;
830
+ }
748
831
  if (tag === "column" && k === "width" && typeof v === "string") {
749
832
  const px = pxValue(v);
750
833
  if (px != null) {
@@ -757,15 +840,15 @@ function buildProperty(el, tag) {
757
840
  continue;
758
841
  }
759
842
  if (k === "text") {
760
- if (tag === "checker" && isRecord(v) && (v.tag === "markdown" || v.tag === "lark_md")) {
761
- property.text = convertEl(v);
843
+ if (tag === "checker" && isRecord2(v) && (v.tag === "markdown" || v.tag === "lark_md")) {
844
+ property.text = convertEl(v, colors);
762
845
  } else {
763
846
  property.text = wrapTextLeaf(v);
764
847
  }
765
848
  continue;
766
849
  }
767
- if ((k === "icon" || k === "ud_icon") && isRecord(v)) {
768
- property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v);
850
+ if ((k === "icon" || k === "ud_icon") && isRecord2(v)) {
851
+ property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v, colors);
769
852
  continue;
770
853
  }
771
854
  if (k === "behaviors" && Array.isArray(v)) {
@@ -776,21 +859,21 @@ function buildProperty(el, tag) {
776
859
  property.url = normalizeUrl(v);
777
860
  continue;
778
861
  }
779
- if (k === "button_area" && isRecord(v)) {
862
+ if (k === "button_area" && isRecord2(v)) {
780
863
  const area = { ...v };
781
- if (Array.isArray(v.buttons)) area.buttons = v.buttons.map(convertNode);
864
+ if (Array.isArray(v.buttons)) area.buttons = v.buttons.map((b) => convertNode(b, colors));
782
865
  property.button_area = area;
783
866
  continue;
784
867
  }
785
- property[renameKey(k)] = coerceValue(k, v);
868
+ property[renameKey(k)] = coerceValue(k, v, colors);
786
869
  }
787
870
  return property;
788
871
  }
789
- function coerceValue(key, value) {
872
+ function coerceValue(key, value, colors) {
790
873
  if ((key === "padding" || key === "margin") && typeof value === "string") {
791
874
  return parseBox(value);
792
875
  }
793
- if (Array.isArray(value)) return value.map(convertNode);
876
+ if (Array.isArray(value)) return value.map((item) => convertNode(item, colors));
794
877
  if (key === "url") return normalizeUrl(value);
795
878
  return value;
796
879
  }
@@ -799,7 +882,7 @@ function renameKey(k) {
799
882
  }
800
883
  function wrapTextLeaf(v) {
801
884
  if (typeof v === "string") return { tag: "plain_text", property: { content: v } };
802
- if (isRecord(v)) {
885
+ if (isRecord2(v)) {
803
886
  const property = { content: typeof v.content === "string" ? v.content : "" };
804
887
  if (typeof v.text_align === "string") property.textAlign = v.text_align;
805
888
  if (typeof v.text_size === "string") property.text_size = v.text_size;
@@ -810,7 +893,7 @@ function wrapTextLeaf(v) {
810
893
  }
811
894
  function wrapHeaderText(v) {
812
895
  if (typeof v === "string") return { tag: "plain_text", property: { content: v } };
813
- if (!isRecord(v)) return { tag: "plain_text", property: { content: "" } };
896
+ if (!isRecord2(v)) return { tag: "plain_text", property: { content: "" } };
814
897
  const tag = typeof v.tag === "string" ? v.tag : "plain_text";
815
898
  const content = typeof v.content === "string" ? v.content : "";
816
899
  if (tag === "lark_md" || tag === "markdown") {
@@ -827,7 +910,7 @@ function wrapHeaderText(v) {
827
910
  function behaviorsToActions(behaviors) {
828
911
  const out = [];
829
912
  for (const b of behaviors) {
830
- if (!isRecord(b)) continue;
913
+ if (!isRecord2(b)) continue;
831
914
  const type = typeof b.type === "string" ? b.type : "open_url";
832
915
  out.push({ type, action: { url: normalizeUrl(b.default_url) } });
833
916
  }
@@ -835,7 +918,7 @@ function behaviorsToActions(behaviors) {
835
918
  }
836
919
  function normalizeUrl(v) {
837
920
  if (typeof v === "string") return v;
838
- if (isRecord(v)) return v;
921
+ if (isRecord2(v)) return v;
839
922
  return v;
840
923
  }
841
924
  function parseBox(s) {
@@ -862,7 +945,7 @@ function pxValue(s) {
862
945
  const n = Number(s);
863
946
  return Number.isFinite(n) ? n : null;
864
947
  }
865
- function isRecord(v) {
948
+ function isRecord2(v) {
866
949
  return typeof v === "object" && v !== null && !Array.isArray(v);
867
950
  }
868
951
 
@@ -939,7 +1022,7 @@ function normalizeStoredCardColors(dsl, preRegistered) {
939
1022
  }
940
1023
  }
941
1024
  if (obj.tag === "markdown" && typeof obj.content === "string") {
942
- normalizeMarkdownInlineHexColors(obj, ensureAlias);
1025
+ normalizeMarkdownInlineHexColors(obj, ensureAlias, !!preRegistered);
943
1026
  }
944
1027
  for (const value of Object.values(obj)) walk(value);
945
1028
  };
@@ -974,22 +1057,24 @@ function normalizeStoredCardColors(dsl, preRegistered) {
974
1057
  const existing = style.color && typeof style.color === "object" ? style.color : {};
975
1058
  style.color = { ...colorEntries, ...existing };
976
1059
  if (!colorEntries["cus-accent"]) return;
977
- const applyDefaultFontColors = (node) => {
978
- if (Array.isArray(node)) {
979
- for (const child of node) applyDefaultFontColors(child);
980
- return;
981
- }
982
- if (!node || typeof node !== "object") return;
983
- const obj = node;
984
- if (obj.tag === "markdown" && obj.font_color === void 0) {
985
- const size = obj.text_size;
986
- const content = typeof obj.content === "string" ? obj.content : "";
987
- if (size === "small") obj.font_color = "cus-muted";
988
- else if (size === "heading" || content.includes("**")) obj.font_color = "cus-accent";
989
- }
990
- for (const value of Object.values(obj)) applyDefaultFontColors(value);
991
- };
992
- applyDefaultFontColors(dsl.body);
1060
+ if (!preRegistered) {
1061
+ const applyDefaultFontColors = (node) => {
1062
+ if (Array.isArray(node)) {
1063
+ for (const child of node) applyDefaultFontColors(child);
1064
+ return;
1065
+ }
1066
+ if (!node || typeof node !== "object") return;
1067
+ const obj = node;
1068
+ if (obj.tag === "markdown" && obj.font_color === void 0) {
1069
+ const size = obj.text_size;
1070
+ const content = typeof obj.content === "string" ? obj.content : "";
1071
+ if (size === "small") obj.font_color = "cus-muted";
1072
+ else if (size === "heading" || content.includes("**")) obj.font_color = "cus-accent";
1073
+ }
1074
+ for (const value of Object.values(obj)) applyDefaultFontColors(value);
1075
+ };
1076
+ applyDefaultFontColors(dsl.body);
1077
+ }
993
1078
  }
994
1079
  function unifyMatchingAlias(entries, fromPrefix, to) {
995
1080
  const renames = /* @__PURE__ */ new Map();
@@ -1033,7 +1118,7 @@ function remapColorReferences(node, aliasRenames) {
1033
1118
  };
1034
1119
  walk(node);
1035
1120
  }
1036
- function normalizeMarkdownInlineHexColors(obj, ensureAlias) {
1121
+ function normalizeMarkdownInlineHexColors(obj, ensureAlias, keepFontTags = false) {
1037
1122
  const content = obj.content;
1038
1123
  const hexColor = (raw) => {
1039
1124
  const v = raw.trim();
@@ -1045,7 +1130,7 @@ function normalizeMarkdownInlineHexColors(obj, ensureAlias) {
1045
1130
  return void 0;
1046
1131
  };
1047
1132
  const single = content.match(/^<font color=['"]([^'"]+)['"]\s*>([\s\S]*)<\/font>$/);
1048
- if (single) {
1133
+ if (single && !keepFontTags) {
1049
1134
  const entry = hexColor(single[1]);
1050
1135
  if (entry) {
1051
1136
  const alias = ensureAlias("cus-text", entry);
@@ -1225,12 +1310,12 @@ var VALUE_ECHO_TARGETS = {
1225
1310
  size_value: "size"
1226
1311
  };
1227
1312
  function convertRoot(root, ctx) {
1228
- if (!isRecord2(root)) return root;
1313
+ if (!isRecord3(root)) return root;
1229
1314
  const out = {};
1230
1315
  out.schema = typeof root.schema === "string" ? root.schema : "2.0";
1231
- out.config = convertConfig(isRecord2(root.config) ? root.config : {});
1232
- if (isRecord2(root.body)) out.body = convertBody2(root.body, ctx);
1233
- if (isRecord2(root.header)) out.header = convertHeader2(root.header, ctx);
1316
+ out.config = convertConfig(isRecord3(root.config) ? root.config : {});
1317
+ if (isRecord3(root.body)) out.body = convertBody2(root.body, ctx);
1318
+ if (isRecord3(root.header)) out.header = convertHeader2(root.header, ctx);
1234
1319
  normalizeStoredCardColors(out, ctx.colors);
1235
1320
  return out;
1236
1321
  }
@@ -1238,14 +1323,14 @@ function convertConfig(_node) {
1238
1323
  return { update_multi: true };
1239
1324
  }
1240
1325
  function convertHeader2(node, ctx) {
1241
- const property = isRecord2(node.property) ? node.property : node;
1326
+ const property = isRecord3(node.property) ? node.property : node;
1242
1327
  const out = convertProperty(property, "header", ctx);
1243
1328
  delete out.tag;
1244
1329
  return out;
1245
1330
  }
1246
1331
  function convertHeaderText(rawValue, ctx) {
1247
1332
  const tag = typeof rawValue.tag === "string" ? rawValue.tag : "";
1248
- const wrapped = isRecord2(rawValue.property);
1333
+ const wrapped = isRecord3(rawValue.property);
1249
1334
  const property = wrapped ? rawValue.property : rawValue;
1250
1335
  if (tag === "plain_text") {
1251
1336
  const content = typeof property.content === "string" ? property.content : "";
@@ -1265,12 +1350,12 @@ function convertHeaderText(rawValue, ctx) {
1265
1350
  return void 0;
1266
1351
  }
1267
1352
  function convertBody2(node, ctx) {
1268
- const property = isRecord2(node.property) ? node.property : node;
1353
+ const property = isRecord3(node.property) ? node.property : node;
1269
1354
  return convertProperty(property, "body", ctx);
1270
1355
  }
1271
1356
  function unwrap(node, ctx) {
1272
1357
  const tag = typeof node.tag === "string" ? node.tag : void 0;
1273
- const property = isRecord2(node.property) ? node.property : {};
1358
+ const property = isRecord3(node.property) ? node.property : {};
1274
1359
  if (tag === "markdown") return rebuildMarkdown(property, ctx);
1275
1360
  if (tag === "plain_text") {
1276
1361
  const content = typeof property.content === "string" ? property.content : "";
@@ -1284,7 +1369,7 @@ function unwrap(node, ctx) {
1284
1369
  const heightPx = isPixelScalar(property.heightValue) ? pixelOf(property.heightValue) : void 0;
1285
1370
  if (widthPx !== void 0 && heightPx !== void 0) {
1286
1371
  out.size = `${widthPx}px ${heightPx}px`;
1287
- } else if (isRecord2(property.size) && hasSide(property.size)) out.size = formatBox(property.size);
1372
+ } else if (isRecord3(property.size) && hasSide(property.size)) out.size = formatBox(property.size);
1288
1373
  else if (isPixelScalar(property.size)) out.size = `${pixelOf(property.size)}px`;
1289
1374
  else if (typeof property.size === "string") out.size = property.size;
1290
1375
  return out;
@@ -1306,7 +1391,7 @@ function unwrap(node, ctx) {
1306
1391
  const out = { tag: "table" };
1307
1392
  const rawColumns = Array.isArray(property.columns) ? property.columns : [];
1308
1393
  out.columns = rawColumns.map((col) => {
1309
- if (!isRecord2(col)) return {};
1394
+ if (!isRecord3(col)) return {};
1310
1395
  const c = {};
1311
1396
  if (typeof col.name === "string") c.name = col.name;
1312
1397
  const displayName = typeof col.displayName === "string" ? col.displayName : typeof col.display_name === "string" ? col.display_name : void 0;
@@ -1316,22 +1401,22 @@ function unwrap(node, ctx) {
1316
1401
  const hAlign = typeof col.horizontalAlign === "string" ? col.horizontalAlign : typeof col.horizontal_align === "string" ? col.horizontal_align : void 0;
1317
1402
  if (hAlign !== void 0) c.horizontal_align = hAlign;
1318
1403
  const wv = col.widthValue;
1319
- if (isRecord2(wv)) {
1404
+ if (isRecord3(wv)) {
1320
1405
  if (wv.type === "pixels" && typeof wv.value === "number") c.width = `${wv.value}px`;
1321
1406
  else if (typeof wv.value === "string") c.width = wv.value;
1322
1407
  } else if (typeof col.width === "string" || typeof col.width === "number") {
1323
1408
  c.width = col.width;
1324
1409
  }
1325
- if (isRecord2(col.format)) c.format = col.format;
1410
+ if (isRecord3(col.format)) c.format = col.format;
1326
1411
  return c;
1327
1412
  });
1328
1413
  const rawRows = Array.isArray(property.rows) ? property.rows : [];
1329
1414
  out.rows = rawRows.map((row) => {
1330
- if (!isRecord2(row)) return {};
1415
+ if (!isRecord3(row)) return {};
1331
1416
  const r = {};
1332
1417
  for (const [k, cell] of Object.entries(row)) {
1333
- let value = isRecord2(cell) && "data" in cell ? cell.data : cell;
1334
- if (isRecord2(value) && value.tag === "markdown" && isRecord2(value.property)) {
1418
+ let value = isRecord3(cell) && "data" in cell ? cell.data : cell;
1419
+ if (isRecord3(value) && value.tag === "markdown" && isRecord3(value.property)) {
1335
1420
  const elements = Array.isArray(value.property.elements) ? value.property.elements : [];
1336
1421
  value = renderChildren(elements, ctx).content;
1337
1422
  }
@@ -1339,13 +1424,13 @@ function unwrap(node, ctx) {
1339
1424
  }
1340
1425
  return r;
1341
1426
  });
1342
- if (isRecord2(property.headerStyle)) {
1427
+ if (isRecord3(property.headerStyle)) {
1343
1428
  const hs = {};
1344
1429
  for (const [k, v] of Object.entries(property.headerStyle)) {
1345
1430
  const sk = snake(k);
1346
1431
  if (sk === "platform_text_size") continue;
1347
1432
  if (sk === "lines_value") {
1348
- if (isRecord2(v) && typeof v.value === "number") hs.lines = v.value;
1433
+ if (isRecord3(v) && typeof v.value === "number") hs.lines = v.value;
1349
1434
  continue;
1350
1435
  }
1351
1436
  hs[sk] = v;
@@ -1353,7 +1438,7 @@ function unwrap(node, ctx) {
1353
1438
  out.header_style = hs;
1354
1439
  }
1355
1440
  const rhv = property.rowHeightValue;
1356
- if (isRecord2(rhv) && typeof rhv.value === "string") out.row_height = rhv.value;
1441
+ if (isRecord3(rhv) && typeof rhv.value === "string") out.row_height = rhv.value;
1357
1442
  else if (typeof property.rowHeight === "string") out.row_height = property.rowHeight;
1358
1443
  if (typeof property.pageSize === "number") out.page_size = property.pageSize;
1359
1444
  if (typeof property.freezeFirstColumn === "boolean") out.freeze_first_column = property.freezeFirstColumn;
@@ -1388,7 +1473,7 @@ function unwrap(node, ctx) {
1388
1473
  if (typeof property.showAvatar === "boolean") out.show_avatar = property.showAvatar;
1389
1474
  if (typeof property.showName === "boolean") out.show_name = property.showName;
1390
1475
  if (typeof property.style === "string") out.style = property.style;
1391
- if (isRecord2(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1476
+ if (isRecord3(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1392
1477
  else if (typeof property.margin === "string") out.margin = property.margin;
1393
1478
  return out;
1394
1479
  }
@@ -1400,17 +1485,17 @@ function unwrap(node, ctx) {
1400
1485
  if (typeof property.lines === "number") out.lines = property.lines;
1401
1486
  if (typeof property.dropInvalidUserID === "boolean") out.drop_invalid_user_id = property.dropInvalidUserID;
1402
1487
  else if (typeof property.drop_invalid_user_id === "boolean") out.drop_invalid_user_id = property.drop_invalid_user_id;
1403
- if (isRecord2(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1488
+ if (isRecord3(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1404
1489
  else if (typeof property.margin === "string") out.margin = property.margin;
1405
1490
  const rawPersons = Array.isArray(property.persons) ? property.persons : [];
1406
1491
  out.persons = rawPersons.map((p) => {
1407
- if (!isRecord2(p)) return void 0;
1492
+ if (!isRecord3(p)) return void 0;
1408
1493
  const id = typeof p.id === "string" ? p.id : typeof p.userID === "string" ? p.userID : void 0;
1409
1494
  return id ? { id } : void 0;
1410
1495
  }).filter((p) => p !== void 0);
1411
- const iconSrc = isRecord2(property.icon) ? property.icon : isRecord2(property.udIcon) ? property.udIcon : void 0;
1496
+ const iconSrc = isRecord3(property.icon) ? property.icon : isRecord3(property.udIcon) ? property.udIcon : void 0;
1412
1497
  if (iconSrc) {
1413
- const ip = isRecord2(iconSrc.property) ? iconSrc.property : iconSrc;
1498
+ const ip = isRecord3(iconSrc.property) ? iconSrc.property : iconSrc;
1414
1499
  const icon = {};
1415
1500
  const iconTag = typeof iconSrc.tag === "string" ? iconSrc.tag : typeof ip.tag === "string" ? ip.tag : "standard_icon";
1416
1501
  icon.tag = iconTag === "ud_icon" ? "standard_icon" : iconTag;
@@ -1422,25 +1507,25 @@ function unwrap(node, ctx) {
1422
1507
  }
1423
1508
  return out;
1424
1509
  }
1425
- if (tag === "div" && isRecord2(property.text) && property.fields === void 0) {
1510
+ if (tag === "div" && isRecord3(property.text) && property.fields === void 0) {
1426
1511
  const text = property.text;
1427
1512
  const textTag = typeof text.tag === "string" ? text.tag : "";
1428
- if ((textTag === "markdown" || textTag === "lark_md") && isRecord2(text.property)) {
1513
+ if ((textTag === "markdown" || textTag === "lark_md") && isRecord3(text.property)) {
1429
1514
  return unwrap(text, ctx);
1430
1515
  }
1431
1516
  if (textTag === "plain_text") {
1432
1517
  const out = { tag: "div" };
1433
1518
  const widthVal = property.widthValue;
1434
- if (isRecord2(widthVal) && typeof widthVal.value === "string" && typeof widthVal.type === "string" && widthVal.type.startsWith("builtin_")) {
1519
+ if (isRecord3(widthVal) && typeof widthVal.value === "string" && typeof widthVal.type === "string" && widthVal.type.startsWith("builtin_")) {
1435
1520
  out.width = widthVal.value;
1436
1521
  } else if (typeof property.width === "string") {
1437
1522
  out.width = property.width;
1438
1523
  }
1439
- const tp = isRecord2(text.property) ? text.property : {};
1524
+ const tp = isRecord3(text.property) ? text.property : {};
1440
1525
  const content = typeof tp.content === "string" ? tp.content : "";
1441
1526
  const textAlign = typeof tp.textAlign === "string" ? tp.textAlign : "left";
1442
1527
  out.text = { tag: "plain_text", content, text_align: textAlign };
1443
- if (isRecord2(property.icon)) {
1528
+ if (isRecord3(property.icon)) {
1444
1529
  out.icon = unwrap(property.icon, ctx);
1445
1530
  }
1446
1531
  return out;
@@ -1467,7 +1552,7 @@ function convertProperty(property, ownerTag, ctx) {
1467
1552
  const echoVal = out[echoKey];
1468
1553
  const enumVal = out[enumKey];
1469
1554
  delete out[echoKey];
1470
- if (!isRecord2(echoVal)) continue;
1555
+ if (!isRecord3(echoVal)) continue;
1471
1556
  const echoType = typeof echoVal.type === "string" ? echoVal.type : "";
1472
1557
  const echoValue = echoVal.value;
1473
1558
  if (echoType.includes("pixels") && typeof echoValue === "number") {
@@ -1476,7 +1561,7 @@ function convertProperty(property, ownerTag, ctx) {
1476
1561
  }
1477
1562
  continue;
1478
1563
  }
1479
- if (echoType === "aspect_ratio" && isRecord2(echoValue)) {
1564
+ if (echoType === "aspect_ratio" && isRecord3(echoValue)) {
1480
1565
  const w = echoValue.width;
1481
1566
  const h = echoValue.height;
1482
1567
  if (typeof w === "number" && typeof h === "number") {
@@ -1484,7 +1569,7 @@ function convertProperty(property, ownerTag, ctx) {
1484
1569
  }
1485
1570
  continue;
1486
1571
  }
1487
- if (echoType === "width_height_pixels" && isRecord2(echoValue)) {
1572
+ if (echoType === "width_height_pixels" && isRecord3(echoValue)) {
1488
1573
  const w = echoValue.width;
1489
1574
  const h = echoValue.height;
1490
1575
  if (typeof w === "number" && typeof h === "number") {
@@ -1524,7 +1609,7 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1524
1609
  if (key === "actions" && Array.isArray(rawValue) && rawValue.length === 0) {
1525
1610
  return DROP;
1526
1611
  }
1527
- if ((key === "padding" || key === "margin") && isRecord2(rawValue) && hasSide(rawValue)) {
1612
+ if ((key === "padding" || key === "margin") && isRecord3(rawValue) && hasSide(rawValue)) {
1528
1613
  return [key, formatBox(rawValue)];
1529
1614
  }
1530
1615
  if (key in VALUE_ECHO_TARGETS) {
@@ -1554,25 +1639,25 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1554
1639
  return DROP;
1555
1640
  }
1556
1641
  if (ownerTag === "video" && VIDEO_RAW_ONLY_FIELDS.has(key)) return DROP;
1557
- if ((key === "alt" || key === "hover_tips") && isRecord2(rawValue) && rawValue.tag === "plain_text") {
1558
- const p = isRecord2(rawValue.property) ? rawValue.property : {};
1642
+ if ((key === "alt" || key === "hover_tips") && isRecord3(rawValue) && rawValue.tag === "plain_text") {
1643
+ const p = isRecord3(rawValue.property) ? rawValue.property : {};
1559
1644
  return [key, { tag: "plain_text", content: typeof p.content === "string" ? p.content : "" }];
1560
1645
  }
1561
- if (key === "text" && isRecord2(rawValue) && rawValue.tag === "plain_text") {
1562
- const p = isRecord2(rawValue.property) ? rawValue.property : {};
1646
+ if (key === "text" && isRecord3(rawValue) && rawValue.tag === "plain_text") {
1647
+ const p = isRecord3(rawValue.property) ? rawValue.property : {};
1563
1648
  return [key, { tag: "plain_text", content: typeof p.content === "string" ? p.content : "" }];
1564
1649
  }
1565
- if (ownerTag === "header" && (key === "title" || key === "subtitle") && isRecord2(rawValue)) {
1650
+ if (ownerTag === "header" && (key === "title" || key === "subtitle") && isRecord3(rawValue)) {
1566
1651
  const headerText = convertHeaderText(rawValue, ctx);
1567
1652
  if (headerText) return [key, headerText];
1568
1653
  }
1569
- if (ownerTag === "header" && key === "ud_icon" && isRecord2(rawValue) && rawValue.tag === "ud_icon") {
1570
- const p = isRecord2(rawValue.property) ? rawValue.property : {};
1654
+ if (ownerTag === "header" && key === "ud_icon" && isRecord3(rawValue) && rawValue.tag === "ud_icon") {
1655
+ const p = isRecord3(rawValue.property) ? rawValue.property : {};
1571
1656
  const token = typeof p.token === "string" ? p.token : void 0;
1572
1657
  if (!token) return DROP;
1573
1658
  return ["icon", { tag: "standard_icon", token }];
1574
1659
  }
1575
- if (ownerTag === "collapsible_panel" && key === "header" && isRecord2(rawValue)) {
1660
+ if (ownerTag === "collapsible_panel" && key === "header" && isRecord3(rawValue)) {
1576
1661
  const cleaned = {};
1577
1662
  for (const [k, v] of Object.entries(rawValue)) {
1578
1663
  const sk = snake(k);
@@ -1589,8 +1674,8 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1589
1674
  if (ownerTag === "button" && key === "actions" && Array.isArray(rawValue)) {
1590
1675
  const openUrls = [];
1591
1676
  for (const a of rawValue) {
1592
- if (!isRecord2(a)) continue;
1593
- const inner = isRecord2(a.action) ? a.action : {};
1677
+ if (!isRecord3(a)) continue;
1678
+ const inner = isRecord3(a.action) ? a.action : {};
1594
1679
  const t = typeof a.type === "string" ? a.type : void 0;
1595
1680
  if (t === "open_url" && typeof inner.url === "string") openUrls.push(inner.url);
1596
1681
  }
@@ -1605,8 +1690,8 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1605
1690
  }
1606
1691
  if (ownerTag === "interactive_container" && key === "actions" && Array.isArray(rawValue)) {
1607
1692
  const behaviors = rawValue.map((a) => {
1608
- if (!isRecord2(a)) return void 0;
1609
- const inner = isRecord2(a.action) ? a.action : {};
1693
+ if (!isRecord3(a)) return void 0;
1694
+ const inner = isRecord3(a.action) ? a.action : {};
1610
1695
  const t = typeof a.type === "string" ? a.type : void 0;
1611
1696
  if (t === "open_url" && typeof inner.url === "string") {
1612
1697
  return { type: "open_url", default_url: inner.url };
@@ -1619,7 +1704,7 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1619
1704
  if (behaviors.length === 0) return DROP;
1620
1705
  return ["behaviors", behaviors];
1621
1706
  }
1622
- if (key === "border" && isRecord2(rawValue)) {
1707
+ if (key === "border" && isRecord3(rawValue)) {
1623
1708
  const b = rawValue;
1624
1709
  const out = {};
1625
1710
  if (typeof b.borderColor === "string") out.color = b.borderColor;
@@ -1633,7 +1718,7 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1633
1718
  }
1634
1719
  return [key, out];
1635
1720
  }
1636
- if (key === "url" && isRecord2(rawValue)) {
1721
+ if (key === "url" && isRecord3(rawValue)) {
1637
1722
  const v = rawValue;
1638
1723
  const main = typeof v.url === "string" ? v.url : "";
1639
1724
  const others = ["androidURL", "iosURL", "pcURL", "harmonyURL"].map((k) => v[k]).filter((x) => typeof x === "string" && x.length > 0);
@@ -1674,7 +1759,7 @@ function renderInlineAudio(prop) {
1674
1759
  if (bg) attrs.push(`background_color='${bg}'`);
1675
1760
  const fill = typeof prop.fillColor === "string" ? prop.fillColor : typeof prop.fill_color === "string" ? prop.fill_color : void 0;
1676
1761
  if (fill) attrs.push(`fill_color='${fill}'`);
1677
- const urlObj = isRecord2(prop.url) ? prop.url : void 0;
1762
+ const urlObj = isRecord3(prop.url) ? prop.url : void 0;
1678
1763
  if (urlObj) {
1679
1764
  if (typeof urlObj.url === "string" && urlObj.url) attrs.push(`fallback_url='${urlObj.url}'`);
1680
1765
  if (typeof urlObj.pcURL === "string" && urlObj.pcURL) attrs.push(`fallback_pc_url='${urlObj.pcURL}'`);
@@ -1688,9 +1773,9 @@ function renderInlineAudio(prop) {
1688
1773
  } else if (typeof prop.fallback_url === "string" && prop.fallback_url) {
1689
1774
  attrs.push(`fallback_url='${prop.fallback_url}'`);
1690
1775
  }
1691
- const fb = isRecord2(prop.fallbackText) ? prop.fallbackText : isRecord2(prop.fallback_text) ? prop.fallback_text : void 0;
1776
+ const fb = isRecord3(prop.fallbackText) ? prop.fallbackText : isRecord3(prop.fallback_text) ? prop.fallback_text : void 0;
1692
1777
  if (fb) {
1693
- const fbProp = isRecord2(fb.property) ? fb.property : fb;
1778
+ const fbProp = isRecord3(fb.property) ? fb.property : fb;
1694
1779
  const fbContent = typeof fbProp.content === "string" ? fbProp.content : typeof fb.content === "string" ? fb.content : "";
1695
1780
  if (fbContent) attrs.push(`fallback_text='${fbContent}'`);
1696
1781
  }
@@ -1708,14 +1793,13 @@ function resolveAtUserId(prop, ctx) {
1708
1793
  function rebuildMarkdown(property, ctx) {
1709
1794
  const out = { tag: "markdown" };
1710
1795
  const elements = Array.isArray(property.elements) ? property.elements : [];
1711
- const { content, uniformFontColor } = renderChildren(elements, ctx);
1796
+ const { content } = renderChildren(elements, ctx);
1712
1797
  if (content) out.content = content;
1713
- if (uniformFontColor) out.font_color = uniformFontColor;
1714
1798
  for (const [rawKey, rawValue] of Object.entries(property)) {
1715
1799
  if (rawKey === "elements" || rawKey === "markdownElements" || rawKey === "originTag") continue;
1716
1800
  if (rawKey === "udIcon") continue;
1717
1801
  if (rawKey === "textStyle") {
1718
- const ts = isRecord2(rawValue) ? rawValue : {};
1802
+ const ts = isRecord3(rawValue) ? rawValue : {};
1719
1803
  const size = typeof ts.size === "string" ? ts.size : void 0;
1720
1804
  if (size) out.text_size = size;
1721
1805
  continue;
@@ -1728,7 +1812,7 @@ function rebuildMarkdown(property, ctx) {
1728
1812
  }
1729
1813
  return out;
1730
1814
  }
1731
- function wrapEmphasis(text, bold, color, colorKind, inlineCustomFont = false) {
1815
+ function wrapEmphasis(text, bold, color) {
1732
1816
  if (!bold && !color) return text;
1733
1817
  const lead = text.match(/^\s*/)[0];
1734
1818
  const trail = text.match(/\s*$/)[0];
@@ -1736,10 +1820,7 @@ function wrapEmphasis(text, bold, color, colorKind, inlineCustomFont = false) {
1736
1820
  if (core.length === 0) return text;
1737
1821
  let wrapped = core;
1738
1822
  if (bold) wrapped = `**${wrapped}**`;
1739
- if (color) {
1740
- if (colorKind === "enum") wrapped = `<font color='${color}'>${wrapped}</font>`;
1741
- else if (colorKind === "custom" && inlineCustomFont) wrapped = `<font color='${color}'>${wrapped}</font>`;
1742
- }
1823
+ if (color) wrapped = `<font color='${color}'>${wrapped}</font>`;
1743
1824
  return lead + wrapped + trail;
1744
1825
  }
1745
1826
  function resolveInlineStyle(ts, ctx) {
@@ -1767,20 +1848,14 @@ function resolveInlineStyle(ts, ctx) {
1767
1848
  function renderChildren(children, ctx) {
1768
1849
  let out = "";
1769
1850
  let buffer = [];
1770
- let uniformFontColor;
1771
1851
  function flushBuffer() {
1772
1852
  if (buffer.length === 0) return;
1773
- const customColors = buffer.filter((s) => s.colorKind === "custom" && s.color).map((s) => s.color);
1774
- const hasEnumColor = buffer.some((s) => s.colorKind === "enum" && s.color);
1775
- const uniformCustom = customColors.length > 0 && !hasEnumColor && customColors.every((c) => c === customColors[0]) ? customColors[0] : void 0;
1776
- if (uniformCustom) uniformFontColor = uniformCustom;
1777
1853
  let group = [];
1778
1854
  function emitGroup() {
1779
1855
  if (group.length === 0) return;
1780
1856
  const inner = group.map((s) => s.content).join("");
1781
- const { bold, color, colorKind } = group[0];
1782
- const inlineCustomFont = colorKind === "custom" && !!color && color !== uniformCustom;
1783
- out += wrapEmphasis(inner, bold, color, colorKind, inlineCustomFont);
1857
+ const { bold, color } = group[0];
1858
+ out += wrapEmphasis(inner, bold, color);
1784
1859
  group = [];
1785
1860
  }
1786
1861
  for (const seg of buffer) {
@@ -1800,7 +1875,7 @@ function renderChildren(children, ctx) {
1800
1875
  buffer = [];
1801
1876
  }
1802
1877
  for (const child of children) {
1803
- if (!isRecord2(child)) continue;
1878
+ if (!isRecord3(child)) continue;
1804
1879
  const inline = childToInlineSegment(child, ctx);
1805
1880
  if (inline) {
1806
1881
  buffer.push(inline);
@@ -1810,12 +1885,12 @@ function renderChildren(children, ctx) {
1810
1885
  out += childToMarkdown(child, ctx);
1811
1886
  }
1812
1887
  flushBuffer();
1813
- return { content: out, uniformFontColor };
1888
+ return { content: out };
1814
1889
  }
1815
1890
  function childToInlineSegment(child, ctx) {
1816
1891
  const tag = child.tag;
1817
- const prop = isRecord2(child.property) ? child.property : {};
1818
- const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
1892
+ const prop = isRecord3(child.property) ? child.property : {};
1893
+ const ts = isRecord3(prop.textStyle) ? prop.textStyle : void 0;
1819
1894
  const { bold, color, colorKind } = resolveInlineStyle(ts, ctx);
1820
1895
  switch (tag) {
1821
1896
  case "plain_text":
@@ -1834,7 +1909,7 @@ function childToInlineSegment(child, ctx) {
1834
1909
  };
1835
1910
  case "link": {
1836
1911
  const text = typeof prop.content === "string" ? prop.content : "";
1837
- const urlObj = isRecord2(prop.url) ? prop.url : void 0;
1912
+ const urlObj = isRecord3(prop.url) ? prop.url : void 0;
1838
1913
  const url = urlObj && typeof urlObj.url === "string" ? urlObj.url : "";
1839
1914
  return { content: `[${text}](${url})`, bold, color, colorKind };
1840
1915
  }
@@ -1846,8 +1921,8 @@ function childToInlineSegment(child, ctx) {
1846
1921
  }
1847
1922
  case "text_tag": {
1848
1923
  const tagColor = typeof prop.color === "string" ? prop.color : void 0;
1849
- const inner = isRecord2(prop.text) ? prop.text : void 0;
1850
- const innerProp = inner && isRecord2(inner.property) ? inner.property : void 0;
1924
+ const inner = isRecord3(prop.text) ? prop.text : void 0;
1925
+ const innerProp = inner && isRecord3(inner.property) ? inner.property : void 0;
1851
1926
  const innerContent = innerProp && typeof innerProp.content === "string" ? innerProp.content : "";
1852
1927
  const rendered = tagColor ? `<text_tag color='${tagColor}'>${innerContent}</text_tag>` : `<text_tag>${innerContent}</text_tag>`;
1853
1928
  return { content: rendered, bold: false };
@@ -1871,13 +1946,13 @@ function childToInlineSegment(child, ctx) {
1871
1946
  }
1872
1947
  function childToMarkdown(child, ctx) {
1873
1948
  const tag = child.tag;
1874
- const prop = isRecord2(child.property) ? child.property : {};
1949
+ const prop = isRecord3(child.property) ? child.property : {};
1875
1950
  switch (tag) {
1876
1951
  case "plain_text": {
1877
1952
  const content = typeof prop.content === "string" ? prop.content : "";
1878
- const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
1879
- const { bold, color, colorKind } = resolveInlineStyle(ts, ctx);
1880
- return wrapEmphasis(content, bold, color, colorKind, colorKind === "custom");
1953
+ const ts = isRecord3(prop.textStyle) ? prop.textStyle : void 0;
1954
+ const { bold, color } = resolveInlineStyle(ts, ctx);
1955
+ return wrapEmphasis(content, bold, color);
1881
1956
  }
1882
1957
  case "br":
1883
1958
  return "\n";
@@ -1898,7 +1973,7 @@ function childToMarkdown(child, ctx) {
1898
1973
  return renderInlineAudio(prop);
1899
1974
  case "link": {
1900
1975
  const text = typeof prop.content === "string" ? prop.content : "";
1901
- const urlObj = isRecord2(prop.url) ? prop.url : void 0;
1976
+ const urlObj = isRecord3(prop.url) ? prop.url : void 0;
1902
1977
  const url = urlObj && typeof urlObj.url === "string" ? urlObj.url : "";
1903
1978
  return `[${text}](${url})`;
1904
1979
  }
@@ -1908,8 +1983,8 @@ function childToMarkdown(child, ctx) {
1908
1983
  }
1909
1984
  case "text_tag": {
1910
1985
  const color = typeof prop.color === "string" ? prop.color : void 0;
1911
- const inner = isRecord2(prop.text) ? prop.text : void 0;
1912
- const innerProp = inner && isRecord2(inner.property) ? inner.property : void 0;
1986
+ const inner = isRecord3(prop.text) ? prop.text : void 0;
1987
+ const innerProp = inner && isRecord3(inner.property) ? inner.property : void 0;
1913
1988
  const innerContent = innerProp && typeof innerProp.content === "string" ? innerProp.content : "";
1914
1989
  if (color) return `<text_tag color='${color}'>${innerContent}</text_tag>`;
1915
1990
  return `<text_tag>${innerContent}</text_tag>`;
@@ -1918,11 +1993,11 @@ function childToMarkdown(child, ctx) {
1918
1993
  const lang = typeof prop.language === "string" ? prop.language : "";
1919
1994
  const blocks = Array.isArray(prop.contents) ? prop.contents : [];
1920
1995
  const lines = blocks.map((blk) => {
1921
- if (!isRecord2(blk)) return "";
1996
+ if (!isRecord3(blk)) return "";
1922
1997
  const inner = Array.isArray(blk.contents) ? blk.contents : [];
1923
1998
  let line = "";
1924
1999
  for (const seg of inner) {
1925
- if (isRecord2(seg) && typeof seg.content === "string") line += seg.content;
2000
+ if (isRecord3(seg) && typeof seg.content === "string") line += seg.content;
1926
2001
  }
1927
2002
  return line;
1928
2003
  });
@@ -1938,14 +2013,14 @@ ${body}
1938
2013
  const lines = [];
1939
2014
  const levelCounters = [];
1940
2015
  for (const item of items) {
1941
- if (!isRecord2(item)) continue;
2016
+ if (!isRecord3(item)) continue;
1942
2017
  const level = typeof item.level === "number" ? item.level : 0;
1943
2018
  const type = typeof item.type === "string" ? item.type : "ul";
1944
2019
  const indent = " ".repeat(level);
1945
2020
  const inner = Array.isArray(item.elements) ? item.elements : [];
1946
2021
  let text = "";
1947
2022
  for (const seg of inner) {
1948
- if (!isRecord2(seg)) continue;
2023
+ if (!isRecord3(seg)) continue;
1949
2024
  text += childToMarkdown(seg, ctx);
1950
2025
  }
1951
2026
  if (type === "ol") {
@@ -1974,7 +2049,7 @@ ${lines.join("\n")}
1974
2049
  const inner = Array.isArray(prop.elements) ? prop.elements : [];
1975
2050
  let body = "";
1976
2051
  for (const seg of inner) {
1977
- if (isRecord2(seg)) body += childToMarkdown(seg, ctx);
2052
+ if (isRecord3(seg)) body += childToMarkdown(seg, ctx);
1978
2053
  }
1979
2054
  return `
1980
2055
 
@@ -1990,18 +2065,18 @@ ${"#".repeat(level)} ${body}
1990
2065
  const rows = Array.isArray(prop.rows) ? prop.rows : [];
1991
2066
  if (columns.length === 0) return "";
1992
2067
  const headers = columns.map(
1993
- (col) => isRecord2(col) && typeof col.displayName === "string" ? col.displayName : ""
2068
+ (col) => isRecord3(col) && typeof col.displayName === "string" ? col.displayName : ""
1994
2069
  );
1995
2070
  const headerLine = `| ${headers.join(" | ")} |`;
1996
2071
  const separator = `| ${columns.map(() => "--------").join(" | ")} |`;
1997
2072
  const bodyLines = rows.map((row) => {
1998
- if (!isRecord2(row)) return `| ${columns.map(() => "").join(" | ")} |`;
2073
+ if (!isRecord3(row)) return `| ${columns.map(() => "").join(" | ")} |`;
1999
2074
  const cells = columns.map((col) => {
2000
- const name = isRecord2(col) && typeof col.name === "string" ? col.name : "";
2001
- const cell = isRecord2(row[name]) ? row[name] : void 0;
2002
- const data = cell && isRecord2(cell.data) ? cell.data : void 0;
2075
+ const name = isRecord3(col) && typeof col.name === "string" ? col.name : "";
2076
+ const cell = isRecord3(row[name]) ? row[name] : void 0;
2077
+ const data = cell && isRecord3(cell.data) ? cell.data : void 0;
2003
2078
  if (!data || data.tag !== "markdown") return "";
2004
- const cellProp = isRecord2(data.property) ? data.property : {};
2079
+ const cellProp = isRecord3(data.property) ? data.property : {};
2005
2080
  const inner = Array.isArray(cellProp.elements) ? cellProp.elements : [];
2006
2081
  const { content: text } = renderChildren(inner, ctx);
2007
2082
  return text.replace(/\|/g, "\\|").replace(/\n/g, " ");
@@ -2020,7 +2095,7 @@ ${bodyLines.join("\n")}
2020
2095
  const inner = Array.isArray(prop.elements) ? prop.elements : [];
2021
2096
  let body = "";
2022
2097
  for (const seg of inner) {
2023
- if (isRecord2(seg)) body += childToMarkdown(seg, ctx);
2098
+ if (isRecord3(seg)) body += childToMarkdown(seg, ctx);
2024
2099
  }
2025
2100
  return `
2026
2101
 
@@ -2035,14 +2110,14 @@ ${bodyLines.join("\n")}
2035
2110
  function convertGeneric(value, ctx) {
2036
2111
  if (Array.isArray(value)) {
2037
2112
  return value.map((item) => {
2038
- if (isRecord2(item) && typeof item.tag === "string" && isRecord2(item.property)) {
2113
+ if (isRecord3(item) && typeof item.tag === "string" && isRecord3(item.property)) {
2039
2114
  return unwrap(item, ctx);
2040
2115
  }
2041
2116
  return convertGeneric(item, ctx);
2042
2117
  });
2043
2118
  }
2044
- if (isRecord2(value)) {
2045
- if (typeof value.tag === "string" && isRecord2(value.property)) {
2119
+ if (isRecord3(value)) {
2120
+ if (typeof value.tag === "string" && isRecord3(value.property)) {
2046
2121
  return unwrap(value, ctx);
2047
2122
  }
2048
2123
  if (hasSide(value)) {
@@ -2059,7 +2134,7 @@ function convertGeneric(value, ctx) {
2059
2134
  }
2060
2135
  return value;
2061
2136
  }
2062
- function isRecord2(v) {
2137
+ function isRecord3(v) {
2063
2138
  return typeof v === "object" && v !== null && !Array.isArray(v);
2064
2139
  }
2065
2140
  function resolveAttachmentImgKey(rawValue, ctx) {
@@ -2075,7 +2150,7 @@ function normalizeVideoCover(rawValue, ctx) {
2075
2150
  const imgKey2 = resolveAttachmentImgKey(rawValue, ctx);
2076
2151
  return imgKey2 ? { img_key: imgKey2 } : void 0;
2077
2152
  }
2078
- if (!isRecord2(rawValue)) return void 0;
2153
+ if (!isRecord3(rawValue)) return void 0;
2079
2154
  if (typeof rawValue.img_key === "string" && rawValue.img_key) {
2080
2155
  return { img_key: rawValue.img_key };
2081
2156
  }
@@ -2084,17 +2159,17 @@ function normalizeVideoCover(rawValue, ctx) {
2084
2159
  return imgKey ? { img_key: imgKey } : void 0;
2085
2160
  }
2086
2161
  function hasSide(v) {
2087
- return ("top" in v || "bottom" in v || "left" in v || "right" in v) && Object.values(v).some((side) => isRecord2(side) && "type" in side && "value" in side);
2162
+ return ("top" in v || "bottom" in v || "left" in v || "right" in v) && Object.values(v).some((side) => isRecord3(side) && "type" in side && "value" in side);
2088
2163
  }
2089
2164
  function formatBox(v) {
2090
2165
  return `${pixelOf(v.top)}px ${pixelOf(v.right)}px ${pixelOf(v.bottom)}px ${pixelOf(v.left)}px`;
2091
2166
  }
2092
2167
  function isPixelScalar(v) {
2093
- if (!isRecord2(v)) return false;
2168
+ if (!isRecord3(v)) return false;
2094
2169
  return typeof v.type === "string" && v.type.includes("pixels") && typeof v.value === "number";
2095
2170
  }
2096
2171
  function pixelOf(side) {
2097
- if (!isRecord2(side)) return 0;
2172
+ if (!isRecord3(side)) return 0;
2098
2173
  const v = side.value;
2099
2174
  if (typeof v === "number") return v;
2100
2175
  if (typeof v === "string") {
@@ -2115,8 +2190,8 @@ function rawToDsl(raw) {
2115
2190
  return raw;
2116
2191
  }
2117
2192
  }
2118
- if (!isRecord2(raw)) return raw;
2119
- if (typeof raw.json_card === "string" || isRecord2(raw.json_card)) {
2193
+ if (!isRecord3(raw)) return raw;
2194
+ if (typeof raw.json_card === "string" || isRecord3(raw.json_card)) {
2120
2195
  let inner = raw.json_card;
2121
2196
  if (typeof inner === "string") {
2122
2197
  try {
@@ -2125,16 +2200,16 @@ function rawToDsl(raw) {
2125
2200
  return raw;
2126
2201
  }
2127
2202
  }
2128
- const attachment = isRecord2(raw.json_attachment) ? raw.json_attachment : {};
2203
+ const attachment = isRecord3(raw.json_attachment) ? raw.json_attachment : {};
2129
2204
  const ctx = makeCtx({
2130
- images: isRecord2(attachment.images) ? attachment.images : {},
2131
- atUsers: isRecord2(attachment.at_users) ? attachment.at_users : {}
2205
+ images: isRecord3(attachment.images) ? attachment.images : {},
2206
+ atUsers: isRecord3(attachment.at_users) ? attachment.at_users : {}
2132
2207
  });
2133
2208
  return convertRoot(inner, ctx);
2134
2209
  }
2135
- if (isRecord2(raw.card)) {
2210
+ if (isRecord3(raw.card)) {
2136
2211
  const card = raw.card;
2137
- if (typeof card.json_card === "string" || isRecord2(card.json_card)) {
2212
+ if (typeof card.json_card === "string" || isRecord3(card.json_card)) {
2138
2213
  return rawToDsl(card);
2139
2214
  }
2140
2215
  return convertRoot(card, makeCtx());