@open-feishu-card/adapter 0.3.5 → 0.3.8

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.cjs CHANGED
@@ -606,6 +606,85 @@ function parseMarkdown(content) {
606
606
  return out;
607
607
  }
608
608
 
609
+ // src/expand-dsl-colors.ts
610
+ function readColorRegistry(card) {
611
+ const config = isRecord(card.config) ? card.config : void 0;
612
+ const style = config && isRecord(config.style) ? config.style : void 0;
613
+ const color = style && isRecord(style.color) ? style.color : void 0;
614
+ if (!color) return {};
615
+ const out = {};
616
+ for (const [key, value] of Object.entries(color)) {
617
+ if (!isRecord(value)) continue;
618
+ const light = typeof value.light_mode === "string" ? value.light_mode : typeof value.lightMode === "string" ? value.lightMode : void 0;
619
+ const dark = typeof value.dark_mode === "string" ? value.dark_mode : typeof value.darkMode === "string" ? value.darkMode : void 0;
620
+ if (light && dark) out[key] = { light_mode: light, dark_mode: dark };
621
+ }
622
+ return out;
623
+ }
624
+ function isCustomColorAlias(value) {
625
+ return typeof value === "string" && value.startsWith("cus-");
626
+ }
627
+ function expandBackgroundStyleAlias(style, registry) {
628
+ if (!isCustomColorAlias(style)) return void 0;
629
+ const entry = registry[style];
630
+ if (!entry) return void 0;
631
+ return { light_mode: entry.light_mode, dark_mode: entry.dark_mode };
632
+ }
633
+ function expandTextStyleColor(textStyle, registry) {
634
+ if (!textStyle) return textStyle;
635
+ const color = typeof textStyle.color === "string" ? textStyle.color.trim() : void 0;
636
+ if (!isCustomColorAlias(color)) return textStyle;
637
+ const entry = registry[color];
638
+ if (!entry) return textStyle;
639
+ const { color: _drop, ...rest } = textStyle;
640
+ return {
641
+ ...rest,
642
+ customColor: { lightMode: entry.light_mode, darkMode: entry.dark_mode }
643
+ };
644
+ }
645
+ function expandMarkdownElements(elements, registry) {
646
+ if (!Array.isArray(elements)) return elements;
647
+ return elements.map((el) => expandMarkdownNode(el, registry));
648
+ }
649
+ function expandMarkdownNode(el, registry) {
650
+ const property = el.property ? { ...el.property } : void 0;
651
+ if (!property) return el;
652
+ let changed = property !== el.property;
653
+ if (Array.isArray(property.elements)) {
654
+ const next = expandMarkdownElements(property.elements, registry);
655
+ if (next !== property.elements) {
656
+ property.elements = next;
657
+ changed = true;
658
+ }
659
+ }
660
+ if (Array.isArray(property.items)) {
661
+ property.items = property.items.map((item) => {
662
+ if (!item || typeof item !== "object") return item;
663
+ const row = item;
664
+ if (!Array.isArray(row.elements)) return item;
665
+ const next = expandMarkdownElements(row.elements, registry);
666
+ if (next === row.elements) return item;
667
+ return { ...row, elements: next };
668
+ });
669
+ changed = true;
670
+ }
671
+ if (property.textStyle) {
672
+ const expanded = expandTextStyleColor(property.textStyle, registry);
673
+ if (expanded && expanded !== property.textStyle) {
674
+ property.textStyle = expanded;
675
+ changed = true;
676
+ }
677
+ }
678
+ return changed ? { ...el, property } : el;
679
+ }
680
+ function wrapMarkdownContentWithFontColor(content, fontColor) {
681
+ if (!fontColor || !content || /<font\s+color/i.test(content)) return content;
682
+ return `<font color='${fontColor}'>${content}</font>`;
683
+ }
684
+ function isRecord(v) {
685
+ return typeof v === "object" && v !== null && !Array.isArray(v);
686
+ }
687
+
609
688
  // src/dsl-to-raw.ts
610
689
  var KEY_RENAME = {
611
690
  text_align: "textAlign",
@@ -631,14 +710,22 @@ var KEY_RENAME = {
631
710
  };
632
711
  var TEXT_LEAF_KEYS = /* @__PURE__ */ new Set(["title", "subtitle", "alt", "hover_tips", "placeholder"]);
633
712
  function dslToRaw(dsl) {
634
- const root = isRecord(dsl) ? dsl : {};
635
- const card = isRecord(root.card) ? root.card : isRecord(root.json_card) ? root.json_card : root;
713
+ const root = isRecord2(dsl) ? dsl : {};
714
+ const card = unwrapCard(root);
715
+ const colors = readColorRegistry(card);
636
716
  const out = { schema: typeof card.schema === "string" ? card.schema : "2.0" };
637
- if (isRecord(card.header)) out.header = convertHeader(card.header);
638
- if (isRecord(card.body)) out.body = convertBody(card.body);
717
+ if (isRecord2(card.config)) out.config = { ...card.config };
718
+ if (isRecord2(card.header)) out.header = convertHeader(card.header, colors);
719
+ if (isRecord2(card.body)) out.body = convertBody(card.body, colors);
639
720
  return out;
640
721
  }
641
- function convertHeader(header) {
722
+ function unwrapCard(root) {
723
+ if (isRecord2(root.dsl)) return root.dsl;
724
+ if (isRecord2(root.card)) return root.card;
725
+ if (isRecord2(root.json_card)) return root.json_card;
726
+ return root;
727
+ }
728
+ function convertHeader(header, colors) {
642
729
  const property = {};
643
730
  for (const [k, v] of Object.entries(header)) {
644
731
  if (k === "tag") continue;
@@ -650,32 +737,32 @@ function convertHeader(header) {
650
737
  property[k] = wrapTextLeaf(v);
651
738
  continue;
652
739
  }
653
- if ((k === "icon" || k === "ud_icon") && isRecord(v)) {
654
- property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v);
740
+ if ((k === "icon" || k === "ud_icon") && isRecord2(v)) {
741
+ property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v, colors);
655
742
  continue;
656
743
  }
657
744
  if (k === "text_tag_list" && Array.isArray(v)) {
658
- property.text_tag_list = v.map(convertNode);
745
+ property.text_tag_list = v.map((item) => convertNode(item, colors));
659
746
  continue;
660
747
  }
661
- property[renameKey(k)] = coerceValue(k, v);
748
+ property[renameKey(k)] = coerceValue(k, v, colors);
662
749
  }
663
750
  return { tag: "card_header", property };
664
751
  }
665
- function convertBody(body) {
666
- const property = buildProperty(body, "body");
667
- const elements = Array.isArray(body.elements) ? body.elements.map(convertNode) : [];
752
+ function convertBody(body, colors) {
753
+ const property = buildProperty(body, "body", colors);
754
+ const elements = Array.isArray(body.elements) ? body.elements.map((n) => convertNode(n, colors)) : [];
668
755
  property.elements = elements.filter(Boolean);
669
756
  return { tag: "body", property };
670
757
  }
671
- function convertNode(node) {
672
- if (isRecord(node) && typeof node.tag === "string") return convertEl(node);
758
+ function convertNode(node, colors) {
759
+ if (isRecord2(node) && typeof node.tag === "string") return convertEl(node, colors);
673
760
  return node;
674
761
  }
675
- function convertEl(el) {
762
+ function convertEl(el, colors) {
676
763
  const tag = String(el.tag);
677
764
  if (tag === "person") {
678
- const property = buildProperty(el, "person_v1");
765
+ const property = buildProperty(el, "person_v1", colors);
679
766
  if (property.style === "capsule") {
680
767
  property.pillShaped = true;
681
768
  delete property.style;
@@ -683,16 +770,22 @@ function convertEl(el) {
683
770
  return { tag: "person_v1", property };
684
771
  }
685
772
  if (tag === "markdown" || tag === "lark_md") {
686
- const property = buildProperty(el, "markdown");
687
- if (typeof el.content === "string") property.elements = parseMarkdown(el.content);
773
+ const property = buildProperty(el, "markdown", colors);
774
+ const fontColor = typeof el.font_color === "string" ? el.font_color : void 0;
775
+ let content = typeof el.content === "string" ? el.content : "";
776
+ content = wrapMarkdownContentWithFontColor(content, fontColor);
777
+ if (content) {
778
+ property.elements = expandMarkdownElements(parseMarkdown(content), colors);
779
+ }
688
780
  delete property.content;
781
+ delete property.font_color;
689
782
  return { tag: "markdown", property };
690
783
  }
691
784
  if (tag === "table") {
692
- return { tag, property: convertTableProperty(el) };
785
+ return { tag, property: convertTableProperty(el, colors) };
693
786
  }
694
787
  if (tag === "audio" || tag === "video") {
695
- const property = buildProperty(el, tag);
788
+ const property = buildProperty(el, tag, colors);
696
789
  if (tag === "audio" && el.width != null) {
697
790
  delete property.width;
698
791
  if (el.width === "fill" || el.width === "default") {
@@ -710,14 +803,14 @@ function convertEl(el) {
710
803
  }
711
804
  return { tag, property };
712
805
  }
713
- return { tag, property: buildProperty(el, tag) };
806
+ return { tag, property: buildProperty(el, tag, colors) };
714
807
  }
715
- function convertTableProperty(el) {
716
- const property = buildProperty(el, "table");
808
+ function convertTableProperty(el, colors) {
809
+ const property = buildProperty(el, "table", colors);
717
810
  const columns = Array.isArray(property.columns) ? property.columns : [];
718
811
  const mdColNames = /* @__PURE__ */ new Set();
719
812
  for (const col of columns) {
720
- if (!isRecord(col)) continue;
813
+ if (!isRecord2(col)) continue;
721
814
  const dt = col.data_type ?? col.dataType;
722
815
  if (dt === "lark_md" || dt === "markdown") {
723
816
  const name = typeof col.name === "string" ? col.name : "";
@@ -726,7 +819,7 @@ function convertTableProperty(el) {
726
819
  }
727
820
  if (!mdColNames.size || !Array.isArray(property.rows)) return property;
728
821
  property.rows = property.rows.map((row) => {
729
- if (!isRecord(row)) return row;
822
+ if (!isRecord2(row)) return row;
730
823
  const out = { ...row };
731
824
  for (const name of mdColNames) {
732
825
  const cell = out[name];
@@ -734,7 +827,10 @@ function convertTableProperty(el) {
734
827
  out[name] = {
735
828
  data: {
736
829
  tag: "markdown",
737
- property: { elements: parseMarkdown(cell), originTag: "lark_md" }
830
+ property: {
831
+ elements: expandMarkdownElements(parseMarkdown(cell), colors),
832
+ originTag: "lark_md"
833
+ }
738
834
  }
739
835
  };
740
836
  }
@@ -743,10 +839,29 @@ function convertTableProperty(el) {
743
839
  });
744
840
  return property;
745
841
  }
746
- function buildProperty(el, tag) {
842
+ function buildProperty(el, tag, colors) {
747
843
  const property = {};
748
844
  for (const [k, v] of Object.entries(el)) {
749
845
  if (k === "tag" || k === "id") continue;
846
+ if ((k === "background_style" || k === "backgroundStyle") && (tag === "column" || tag === "column_set")) {
847
+ const renamed = renameKey(k);
848
+ property[renamed] = v;
849
+ const expanded = expandBackgroundStyleAlias(v, colors);
850
+ if (expanded) property.customBackgroundStyle = expanded;
851
+ continue;
852
+ }
853
+ if ((k === "border_color" || k === "borderColor") && tag === "interactive_container") {
854
+ const renamed = renameKey(k);
855
+ property[renamed] = v;
856
+ const expanded = expandBackgroundStyleAlias(v, colors);
857
+ if (expanded) {
858
+ property.customBorderColor = {
859
+ lightMode: expanded.light_mode,
860
+ darkMode: expanded.dark_mode
861
+ };
862
+ }
863
+ continue;
864
+ }
750
865
  if (tag === "column" && k === "width" && typeof v === "string") {
751
866
  const px = pxValue(v);
752
867
  if (px != null) {
@@ -759,15 +874,15 @@ function buildProperty(el, tag) {
759
874
  continue;
760
875
  }
761
876
  if (k === "text") {
762
- if (tag === "checker" && isRecord(v) && (v.tag === "markdown" || v.tag === "lark_md")) {
763
- property.text = convertEl(v);
877
+ if (tag === "checker" && isRecord2(v) && (v.tag === "markdown" || v.tag === "lark_md")) {
878
+ property.text = convertEl(v, colors);
764
879
  } else {
765
880
  property.text = wrapTextLeaf(v);
766
881
  }
767
882
  continue;
768
883
  }
769
- if ((k === "icon" || k === "ud_icon") && isRecord(v)) {
770
- property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v);
884
+ if ((k === "icon" || k === "ud_icon") && isRecord2(v)) {
885
+ property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v, colors);
771
886
  continue;
772
887
  }
773
888
  if (k === "behaviors" && Array.isArray(v)) {
@@ -778,21 +893,21 @@ function buildProperty(el, tag) {
778
893
  property.url = normalizeUrl(v);
779
894
  continue;
780
895
  }
781
- if (k === "button_area" && isRecord(v)) {
896
+ if (k === "button_area" && isRecord2(v)) {
782
897
  const area = { ...v };
783
- if (Array.isArray(v.buttons)) area.buttons = v.buttons.map(convertNode);
898
+ if (Array.isArray(v.buttons)) area.buttons = v.buttons.map((b) => convertNode(b, colors));
784
899
  property.button_area = area;
785
900
  continue;
786
901
  }
787
- property[renameKey(k)] = coerceValue(k, v);
902
+ property[renameKey(k)] = coerceValue(k, v, colors);
788
903
  }
789
904
  return property;
790
905
  }
791
- function coerceValue(key, value) {
906
+ function coerceValue(key, value, colors) {
792
907
  if ((key === "padding" || key === "margin") && typeof value === "string") {
793
908
  return parseBox(value);
794
909
  }
795
- if (Array.isArray(value)) return value.map(convertNode);
910
+ if (Array.isArray(value)) return value.map((item) => convertNode(item, colors));
796
911
  if (key === "url") return normalizeUrl(value);
797
912
  return value;
798
913
  }
@@ -801,7 +916,7 @@ function renameKey(k) {
801
916
  }
802
917
  function wrapTextLeaf(v) {
803
918
  if (typeof v === "string") return { tag: "plain_text", property: { content: v } };
804
- if (isRecord(v)) {
919
+ if (isRecord2(v)) {
805
920
  const property = { content: typeof v.content === "string" ? v.content : "" };
806
921
  if (typeof v.text_align === "string") property.textAlign = v.text_align;
807
922
  if (typeof v.text_size === "string") property.text_size = v.text_size;
@@ -812,7 +927,7 @@ function wrapTextLeaf(v) {
812
927
  }
813
928
  function wrapHeaderText(v) {
814
929
  if (typeof v === "string") return { tag: "plain_text", property: { content: v } };
815
- if (!isRecord(v)) return { tag: "plain_text", property: { content: "" } };
930
+ if (!isRecord2(v)) return { tag: "plain_text", property: { content: "" } };
816
931
  const tag = typeof v.tag === "string" ? v.tag : "plain_text";
817
932
  const content = typeof v.content === "string" ? v.content : "";
818
933
  if (tag === "lark_md" || tag === "markdown") {
@@ -829,7 +944,7 @@ function wrapHeaderText(v) {
829
944
  function behaviorsToActions(behaviors) {
830
945
  const out = [];
831
946
  for (const b of behaviors) {
832
- if (!isRecord(b)) continue;
947
+ if (!isRecord2(b)) continue;
833
948
  const type = typeof b.type === "string" ? b.type : "open_url";
834
949
  out.push({ type, action: { url: normalizeUrl(b.default_url) } });
835
950
  }
@@ -837,7 +952,7 @@ function behaviorsToActions(behaviors) {
837
952
  }
838
953
  function normalizeUrl(v) {
839
954
  if (typeof v === "string") return v;
840
- if (isRecord(v)) return v;
955
+ if (isRecord2(v)) return v;
841
956
  return v;
842
957
  }
843
958
  function parseBox(s) {
@@ -864,24 +979,25 @@ function pxValue(s) {
864
979
  const n = Number(s);
865
980
  return Number.isFinite(n) ? n : null;
866
981
  }
867
- function isRecord(v) {
982
+ function isRecord2(v) {
868
983
  return typeof v === "object" && v !== null && !Array.isArray(v);
869
984
  }
870
985
 
871
986
  // src/normalize-stored-colors.ts
872
987
  function createColorRegistry() {
873
- return { entries: {}, keyToAlias: /* @__PURE__ */ new Map(), bgSeq: 0, textSeq: 0 };
988
+ return { entries: {}, bgKeyToAlias: /* @__PURE__ */ new Map(), textKeyToAlias: /* @__PURE__ */ new Map(), bgSeq: 0, textSeq: 0 };
874
989
  }
875
990
  function colorEntryKey(entry) {
876
991
  return `${entry.light_mode}|${entry.dark_mode}`;
877
992
  }
878
993
  function registerColorEntry(registry, entry, prefix) {
879
994
  const key = colorEntryKey(entry);
880
- const existing = registry.keyToAlias.get(key);
995
+ const map = prefix === "cus-bg" ? registry.bgKeyToAlias : registry.textKeyToAlias;
996
+ const existing = map.get(key);
881
997
  if (existing) return existing;
882
998
  const alias = prefix === "cus-bg" ? `cus-bg-${registry.bgSeq++}` : `cus-text-${registry.textSeq++}`;
883
999
  registry.entries[alias] = entry;
884
- registry.keyToAlias.set(key, alias);
1000
+ map.set(key, alias);
885
1001
  return alias;
886
1002
  }
887
1003
  function hexColorToRgba(hex) {
@@ -901,29 +1017,36 @@ function hexColorToRgba(hex) {
901
1017
  }
902
1018
  return void 0;
903
1019
  }
904
- function readCustomBackgroundStyle(node) {
905
- const raw = node.custom_background_style;
1020
+ function readThemeColorPair(raw) {
906
1021
  if (!raw || typeof raw !== "object") return void 0;
907
1022
  const o = raw;
908
- const lightRaw = typeof o.light_mode === "string" ? o.light_mode : void 0;
909
- const darkRaw = typeof o.dark_mode === "string" ? o.dark_mode : void 0;
1023
+ const lightRaw = typeof o.light_mode === "string" ? o.light_mode : typeof o.lightMode === "string" ? o.lightMode : void 0;
1024
+ const darkRaw = typeof o.dark_mode === "string" ? o.dark_mode : typeof o.darkMode === "string" ? o.darkMode : void 0;
910
1025
  if (!lightRaw || !darkRaw) return void 0;
911
1026
  const light = lightRaw.startsWith("#") ? hexColorToRgba(lightRaw) : lightRaw;
912
1027
  const dark = darkRaw.startsWith("#") ? hexColorToRgba(darkRaw) : darkRaw;
913
1028
  if (!light || !dark) return void 0;
914
1029
  return { light_mode: light, dark_mode: dark };
915
1030
  }
1031
+ function readCustomBackgroundStyle(node) {
1032
+ return readThemeColorPair(node.custom_background_style);
1033
+ }
1034
+ function readCustomBorderColor(node) {
1035
+ return readThemeColorPair(node.custom_border_color ?? node.customBorderColor);
1036
+ }
916
1037
  function normalizeStoredCardColors(dsl, preRegistered) {
917
1038
  const colorEntries = { ...preRegistered?.entries ?? {} };
918
- const keyToAlias = new Map(preRegistered?.keyToAlias ?? []);
1039
+ const bgKeyToAlias = new Map(preRegistered?.bgKeyToAlias ?? []);
1040
+ const textKeyToAlias = new Map(preRegistered?.textKeyToAlias ?? []);
919
1041
  let bgSeq = preRegistered?.bgSeq ?? 0;
920
1042
  let textSeq = preRegistered?.textSeq ?? 0;
921
1043
  const ensureAlias = (prefix, entry) => {
922
- const existing2 = keyToAlias.get(colorEntryKey(entry));
1044
+ const map = prefix === "cus-bg" ? bgKeyToAlias : textKeyToAlias;
1045
+ const existing2 = map.get(colorEntryKey(entry));
923
1046
  if (existing2) return existing2;
924
1047
  const alias = prefix === "cus-bg" ? `cus-bg-${bgSeq++}` : `cus-text-${textSeq++}`;
925
1048
  colorEntries[alias] = entry;
926
- keyToAlias.set(colorEntryKey(entry), alias);
1049
+ map.set(colorEntryKey(entry), alias);
927
1050
  return alias;
928
1051
  };
929
1052
  const walk = (node) => {
@@ -940,6 +1063,14 @@ function normalizeStoredCardColors(dsl, preRegistered) {
940
1063
  delete obj.custom_background_style;
941
1064
  }
942
1065
  }
1066
+ if (obj.tag === "interactive_container") {
1067
+ const border = readCustomBorderColor(obj);
1068
+ if (border) {
1069
+ obj.border_color = ensureAlias("cus-bg", border);
1070
+ delete obj.custom_border_color;
1071
+ delete obj.customBorderColor;
1072
+ }
1073
+ }
943
1074
  if (obj.tag === "markdown" && typeof obj.content === "string") {
944
1075
  normalizeMarkdownInlineHexColors(obj, ensureAlias, !!preRegistered);
945
1076
  }
@@ -984,11 +1115,17 @@ function normalizeStoredCardColors(dsl, preRegistered) {
984
1115
  }
985
1116
  if (!node || typeof node !== "object") return;
986
1117
  const obj = node;
987
- if (obj.tag === "markdown" && obj.font_color === void 0) {
988
- const size = obj.text_size;
989
- const content = typeof obj.content === "string" ? obj.content : "";
990
- if (size === "small") obj.font_color = "cus-muted";
991
- else if (size === "heading" || content.includes("**")) obj.font_color = "cus-accent";
1118
+ if (obj.tag === "markdown" && typeof obj.content === "string") {
1119
+ delete obj.font_color;
1120
+ const content = obj.content;
1121
+ if (!/<font\s+color=/i.test(content)) {
1122
+ const size = obj.text_size;
1123
+ if (size === "small") {
1124
+ obj.content = wrapMarkdownContentWithFontColor(content, "cus-muted");
1125
+ } else if (size === "heading" || content.includes("**")) {
1126
+ obj.content = wrapMarkdownContentWithFontColor(content, "cus-accent");
1127
+ }
1128
+ }
992
1129
  }
993
1130
  for (const value of Object.values(obj)) applyDefaultFontColors(value);
994
1131
  };
@@ -1053,8 +1190,8 @@ function normalizeMarkdownInlineHexColors(obj, ensureAlias, keepFontTags = false
1053
1190
  const entry = hexColor(single[1]);
1054
1191
  if (entry) {
1055
1192
  const alias = ensureAlias("cus-text", entry);
1056
- if (obj.font_color === void 0) obj.font_color = alias;
1057
- obj.content = single[2];
1193
+ delete obj.font_color;
1194
+ obj.content = `<font color='${alias}'>${single[2]}</font>`;
1058
1195
  return;
1059
1196
  }
1060
1197
  }
@@ -1119,6 +1256,12 @@ function resolveCustomBackgroundLight(property) {
1119
1256
  const custom = p.custom_background_style ?? p.customBackgroundStyle;
1120
1257
  return readThemeColorLight(custom);
1121
1258
  }
1259
+ function resolveCustomBorderLight(property) {
1260
+ if (!property || typeof property !== "object") return void 0;
1261
+ const p = property;
1262
+ const custom = p.custom_border_color ?? p.customBorderColor;
1263
+ return readThemeColorLight(custom);
1264
+ }
1122
1265
 
1123
1266
  // src/raw-to-dsl.ts
1124
1267
  function isRawCardEnvelope(value) {
@@ -1229,27 +1372,58 @@ var VALUE_ECHO_TARGETS = {
1229
1372
  size_value: "size"
1230
1373
  };
1231
1374
  function convertRoot(root, ctx) {
1232
- if (!isRecord2(root)) return root;
1375
+ if (!isRecord3(root)) return root;
1233
1376
  const out = {};
1234
1377
  out.schema = typeof root.schema === "string" ? root.schema : "2.0";
1235
- out.config = convertConfig(isRecord2(root.config) ? root.config : {});
1236
- if (isRecord2(root.body)) out.body = convertBody2(root.body, ctx);
1237
- if (isRecord2(root.header)) out.header = convertHeader2(root.header, ctx);
1378
+ out.config = convertConfig(isRecord3(root.config) ? root.config : {});
1379
+ if (isRecord3(root.body)) out.body = convertBody2(root.body, ctx);
1380
+ if (isRecord3(root.header)) out.header = convertHeader2(root.header, ctx);
1238
1381
  normalizeStoredCardColors(out, ctx.colors);
1239
1382
  return out;
1240
1383
  }
1241
- function convertConfig(_node) {
1242
- return { update_multi: true };
1384
+ function convertConfig(node) {
1385
+ const out = { update_multi: true };
1386
+ if (node.streamingMode === true || node.streaming_mode === true) {
1387
+ out.streaming_mode = true;
1388
+ }
1389
+ if (node.enableForwardInteraction === true || node.enable_forward_interaction === true) {
1390
+ out.enable_forward_interaction = true;
1391
+ }
1392
+ if (node.enableForward === false || node.enable_forward === false) {
1393
+ out.enable_forward = false;
1394
+ }
1395
+ if (typeof node.widthMode === "string") out.width_mode = node.widthMode;
1396
+ else if (typeof node.width_mode === "string") out.width_mode = node.width_mode;
1397
+ const summaryRaw = isRecord3(node.summary) ? node.summary : void 0;
1398
+ if (summaryRaw) {
1399
+ const summary = {};
1400
+ if (typeof summaryRaw.content === "string") summary.content = summaryRaw.content;
1401
+ if (isRecord3(summaryRaw.i18nContent)) summary.i18n_content = summaryRaw.i18nContent;
1402
+ else if (isRecord3(summaryRaw.i18n_content)) summary.i18n_content = summaryRaw.i18n_content;
1403
+ if (Object.keys(summary).length) out.summary = summary;
1404
+ }
1405
+ const streamingRaw = isRecord3(node.streamingConfig) ? node.streamingConfig : isRecord3(node.streaming_config) ? node.streaming_config : void 0;
1406
+ if (streamingRaw) {
1407
+ const sc = {};
1408
+ if (streamingRaw.printStrategy != null) sc.print_strategy = streamingRaw.printStrategy;
1409
+ else if (streamingRaw.print_strategy != null) sc.print_strategy = streamingRaw.print_strategy;
1410
+ if (streamingRaw.printFrequencyMs != null) sc.print_frequency_ms = streamingRaw.printFrequencyMs;
1411
+ else if (streamingRaw.print_frequency_ms != null) sc.print_frequency_ms = streamingRaw.print_frequency_ms;
1412
+ if (streamingRaw.printStep != null) sc.print_step = streamingRaw.printStep;
1413
+ else if (streamingRaw.print_step != null) sc.print_step = streamingRaw.print_step;
1414
+ if (Object.keys(sc).length) out.streaming_config = sc;
1415
+ }
1416
+ return out;
1243
1417
  }
1244
1418
  function convertHeader2(node, ctx) {
1245
- const property = isRecord2(node.property) ? node.property : node;
1419
+ const property = isRecord3(node.property) ? node.property : node;
1246
1420
  const out = convertProperty(property, "header", ctx);
1247
1421
  delete out.tag;
1248
1422
  return out;
1249
1423
  }
1250
1424
  function convertHeaderText(rawValue, ctx) {
1251
1425
  const tag = typeof rawValue.tag === "string" ? rawValue.tag : "";
1252
- const wrapped = isRecord2(rawValue.property);
1426
+ const wrapped = isRecord3(rawValue.property);
1253
1427
  const property = wrapped ? rawValue.property : rawValue;
1254
1428
  if (tag === "plain_text") {
1255
1429
  const content = typeof property.content === "string" ? property.content : "";
@@ -1269,12 +1443,12 @@ function convertHeaderText(rawValue, ctx) {
1269
1443
  return void 0;
1270
1444
  }
1271
1445
  function convertBody2(node, ctx) {
1272
- const property = isRecord2(node.property) ? node.property : node;
1446
+ const property = isRecord3(node.property) ? node.property : node;
1273
1447
  return convertProperty(property, "body", ctx);
1274
1448
  }
1275
1449
  function unwrap(node, ctx) {
1276
1450
  const tag = typeof node.tag === "string" ? node.tag : void 0;
1277
- const property = isRecord2(node.property) ? node.property : {};
1451
+ const property = isRecord3(node.property) ? node.property : {};
1278
1452
  if (tag === "markdown") return rebuildMarkdown(property, ctx);
1279
1453
  if (tag === "plain_text") {
1280
1454
  const content = typeof property.content === "string" ? property.content : "";
@@ -1288,7 +1462,7 @@ function unwrap(node, ctx) {
1288
1462
  const heightPx = isPixelScalar(property.heightValue) ? pixelOf(property.heightValue) : void 0;
1289
1463
  if (widthPx !== void 0 && heightPx !== void 0) {
1290
1464
  out.size = `${widthPx}px ${heightPx}px`;
1291
- } else if (isRecord2(property.size) && hasSide(property.size)) out.size = formatBox(property.size);
1465
+ } else if (isRecord3(property.size) && hasSide(property.size)) out.size = formatBox(property.size);
1292
1466
  else if (isPixelScalar(property.size)) out.size = `${pixelOf(property.size)}px`;
1293
1467
  else if (typeof property.size === "string") out.size = property.size;
1294
1468
  return out;
@@ -1310,7 +1484,7 @@ function unwrap(node, ctx) {
1310
1484
  const out = { tag: "table" };
1311
1485
  const rawColumns = Array.isArray(property.columns) ? property.columns : [];
1312
1486
  out.columns = rawColumns.map((col) => {
1313
- if (!isRecord2(col)) return {};
1487
+ if (!isRecord3(col)) return {};
1314
1488
  const c = {};
1315
1489
  if (typeof col.name === "string") c.name = col.name;
1316
1490
  const displayName = typeof col.displayName === "string" ? col.displayName : typeof col.display_name === "string" ? col.display_name : void 0;
@@ -1320,22 +1494,22 @@ function unwrap(node, ctx) {
1320
1494
  const hAlign = typeof col.horizontalAlign === "string" ? col.horizontalAlign : typeof col.horizontal_align === "string" ? col.horizontal_align : void 0;
1321
1495
  if (hAlign !== void 0) c.horizontal_align = hAlign;
1322
1496
  const wv = col.widthValue;
1323
- if (isRecord2(wv)) {
1497
+ if (isRecord3(wv)) {
1324
1498
  if (wv.type === "pixels" && typeof wv.value === "number") c.width = `${wv.value}px`;
1325
1499
  else if (typeof wv.value === "string") c.width = wv.value;
1326
1500
  } else if (typeof col.width === "string" || typeof col.width === "number") {
1327
1501
  c.width = col.width;
1328
1502
  }
1329
- if (isRecord2(col.format)) c.format = col.format;
1503
+ if (isRecord3(col.format)) c.format = col.format;
1330
1504
  return c;
1331
1505
  });
1332
1506
  const rawRows = Array.isArray(property.rows) ? property.rows : [];
1333
1507
  out.rows = rawRows.map((row) => {
1334
- if (!isRecord2(row)) return {};
1508
+ if (!isRecord3(row)) return {};
1335
1509
  const r = {};
1336
1510
  for (const [k, cell] of Object.entries(row)) {
1337
- let value = isRecord2(cell) && "data" in cell ? cell.data : cell;
1338
- if (isRecord2(value) && value.tag === "markdown" && isRecord2(value.property)) {
1511
+ let value = isRecord3(cell) && "data" in cell ? cell.data : cell;
1512
+ if (isRecord3(value) && value.tag === "markdown" && isRecord3(value.property)) {
1339
1513
  const elements = Array.isArray(value.property.elements) ? value.property.elements : [];
1340
1514
  value = renderChildren(elements, ctx).content;
1341
1515
  }
@@ -1343,13 +1517,13 @@ function unwrap(node, ctx) {
1343
1517
  }
1344
1518
  return r;
1345
1519
  });
1346
- if (isRecord2(property.headerStyle)) {
1520
+ if (isRecord3(property.headerStyle)) {
1347
1521
  const hs = {};
1348
1522
  for (const [k, v] of Object.entries(property.headerStyle)) {
1349
1523
  const sk = snake(k);
1350
1524
  if (sk === "platform_text_size") continue;
1351
1525
  if (sk === "lines_value") {
1352
- if (isRecord2(v) && typeof v.value === "number") hs.lines = v.value;
1526
+ if (isRecord3(v) && typeof v.value === "number") hs.lines = v.value;
1353
1527
  continue;
1354
1528
  }
1355
1529
  hs[sk] = v;
@@ -1357,7 +1531,7 @@ function unwrap(node, ctx) {
1357
1531
  out.header_style = hs;
1358
1532
  }
1359
1533
  const rhv = property.rowHeightValue;
1360
- if (isRecord2(rhv) && typeof rhv.value === "string") out.row_height = rhv.value;
1534
+ if (isRecord3(rhv) && typeof rhv.value === "string") out.row_height = rhv.value;
1361
1535
  else if (typeof property.rowHeight === "string") out.row_height = property.rowHeight;
1362
1536
  if (typeof property.pageSize === "number") out.page_size = property.pageSize;
1363
1537
  if (typeof property.freezeFirstColumn === "boolean") out.freeze_first_column = property.freezeFirstColumn;
@@ -1392,7 +1566,7 @@ function unwrap(node, ctx) {
1392
1566
  if (typeof property.showAvatar === "boolean") out.show_avatar = property.showAvatar;
1393
1567
  if (typeof property.showName === "boolean") out.show_name = property.showName;
1394
1568
  if (typeof property.style === "string") out.style = property.style;
1395
- if (isRecord2(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1569
+ if (isRecord3(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1396
1570
  else if (typeof property.margin === "string") out.margin = property.margin;
1397
1571
  return out;
1398
1572
  }
@@ -1404,17 +1578,17 @@ function unwrap(node, ctx) {
1404
1578
  if (typeof property.lines === "number") out.lines = property.lines;
1405
1579
  if (typeof property.dropInvalidUserID === "boolean") out.drop_invalid_user_id = property.dropInvalidUserID;
1406
1580
  else if (typeof property.drop_invalid_user_id === "boolean") out.drop_invalid_user_id = property.drop_invalid_user_id;
1407
- if (isRecord2(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1581
+ if (isRecord3(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1408
1582
  else if (typeof property.margin === "string") out.margin = property.margin;
1409
1583
  const rawPersons = Array.isArray(property.persons) ? property.persons : [];
1410
1584
  out.persons = rawPersons.map((p) => {
1411
- if (!isRecord2(p)) return void 0;
1585
+ if (!isRecord3(p)) return void 0;
1412
1586
  const id = typeof p.id === "string" ? p.id : typeof p.userID === "string" ? p.userID : void 0;
1413
1587
  return id ? { id } : void 0;
1414
1588
  }).filter((p) => p !== void 0);
1415
- const iconSrc = isRecord2(property.icon) ? property.icon : isRecord2(property.udIcon) ? property.udIcon : void 0;
1589
+ const iconSrc = isRecord3(property.icon) ? property.icon : isRecord3(property.udIcon) ? property.udIcon : void 0;
1416
1590
  if (iconSrc) {
1417
- const ip = isRecord2(iconSrc.property) ? iconSrc.property : iconSrc;
1591
+ const ip = isRecord3(iconSrc.property) ? iconSrc.property : iconSrc;
1418
1592
  const icon = {};
1419
1593
  const iconTag = typeof iconSrc.tag === "string" ? iconSrc.tag : typeof ip.tag === "string" ? ip.tag : "standard_icon";
1420
1594
  icon.tag = iconTag === "ud_icon" ? "standard_icon" : iconTag;
@@ -1426,25 +1600,25 @@ function unwrap(node, ctx) {
1426
1600
  }
1427
1601
  return out;
1428
1602
  }
1429
- if (tag === "div" && isRecord2(property.text) && property.fields === void 0) {
1603
+ if (tag === "div" && isRecord3(property.text) && property.fields === void 0) {
1430
1604
  const text = property.text;
1431
1605
  const textTag = typeof text.tag === "string" ? text.tag : "";
1432
- if ((textTag === "markdown" || textTag === "lark_md") && isRecord2(text.property)) {
1606
+ if ((textTag === "markdown" || textTag === "lark_md") && isRecord3(text.property)) {
1433
1607
  return unwrap(text, ctx);
1434
1608
  }
1435
1609
  if (textTag === "plain_text") {
1436
1610
  const out = { tag: "div" };
1437
1611
  const widthVal = property.widthValue;
1438
- if (isRecord2(widthVal) && typeof widthVal.value === "string" && typeof widthVal.type === "string" && widthVal.type.startsWith("builtin_")) {
1612
+ if (isRecord3(widthVal) && typeof widthVal.value === "string" && typeof widthVal.type === "string" && widthVal.type.startsWith("builtin_")) {
1439
1613
  out.width = widthVal.value;
1440
1614
  } else if (typeof property.width === "string") {
1441
1615
  out.width = property.width;
1442
1616
  }
1443
- const tp = isRecord2(text.property) ? text.property : {};
1617
+ const tp = isRecord3(text.property) ? text.property : {};
1444
1618
  const content = typeof tp.content === "string" ? tp.content : "";
1445
1619
  const textAlign = typeof tp.textAlign === "string" ? tp.textAlign : "left";
1446
1620
  out.text = { tag: "plain_text", content, text_align: textAlign };
1447
- if (isRecord2(property.icon)) {
1621
+ if (isRecord3(property.icon)) {
1448
1622
  out.icon = unwrap(property.icon, ctx);
1449
1623
  }
1450
1624
  return out;
@@ -1471,7 +1645,7 @@ function convertProperty(property, ownerTag, ctx) {
1471
1645
  const echoVal = out[echoKey];
1472
1646
  const enumVal = out[enumKey];
1473
1647
  delete out[echoKey];
1474
- if (!isRecord2(echoVal)) continue;
1648
+ if (!isRecord3(echoVal)) continue;
1475
1649
  const echoType = typeof echoVal.type === "string" ? echoVal.type : "";
1476
1650
  const echoValue = echoVal.value;
1477
1651
  if (echoType.includes("pixels") && typeof echoValue === "number") {
@@ -1480,7 +1654,7 @@ function convertProperty(property, ownerTag, ctx) {
1480
1654
  }
1481
1655
  continue;
1482
1656
  }
1483
- if (echoType === "aspect_ratio" && isRecord2(echoValue)) {
1657
+ if (echoType === "aspect_ratio" && isRecord3(echoValue)) {
1484
1658
  const w = echoValue.width;
1485
1659
  const h = echoValue.height;
1486
1660
  if (typeof w === "number" && typeof h === "number") {
@@ -1488,7 +1662,7 @@ function convertProperty(property, ownerTag, ctx) {
1488
1662
  }
1489
1663
  continue;
1490
1664
  }
1491
- if (echoType === "width_height_pixels" && isRecord2(echoValue)) {
1665
+ if (echoType === "width_height_pixels" && isRecord3(echoValue)) {
1492
1666
  const w = echoValue.width;
1493
1667
  const h = echoValue.height;
1494
1668
  if (typeof w === "number" && typeof h === "number") {
@@ -1528,7 +1702,7 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1528
1702
  if (key === "actions" && Array.isArray(rawValue) && rawValue.length === 0) {
1529
1703
  return DROP;
1530
1704
  }
1531
- if ((key === "padding" || key === "margin") && isRecord2(rawValue) && hasSide(rawValue)) {
1705
+ if ((key === "padding" || key === "margin") && isRecord3(rawValue) && hasSide(rawValue)) {
1532
1706
  return [key, formatBox(rawValue)];
1533
1707
  }
1534
1708
  if (key in VALUE_ECHO_TARGETS) {
@@ -1558,25 +1732,25 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1558
1732
  return DROP;
1559
1733
  }
1560
1734
  if (ownerTag === "video" && VIDEO_RAW_ONLY_FIELDS.has(key)) return DROP;
1561
- if ((key === "alt" || key === "hover_tips") && isRecord2(rawValue) && rawValue.tag === "plain_text") {
1562
- const p = isRecord2(rawValue.property) ? rawValue.property : {};
1735
+ if ((key === "alt" || key === "hover_tips") && isRecord3(rawValue) && rawValue.tag === "plain_text") {
1736
+ const p = isRecord3(rawValue.property) ? rawValue.property : {};
1563
1737
  return [key, { tag: "plain_text", content: typeof p.content === "string" ? p.content : "" }];
1564
1738
  }
1565
- if (key === "text" && isRecord2(rawValue) && rawValue.tag === "plain_text") {
1566
- const p = isRecord2(rawValue.property) ? rawValue.property : {};
1739
+ if (key === "text" && isRecord3(rawValue) && rawValue.tag === "plain_text") {
1740
+ const p = isRecord3(rawValue.property) ? rawValue.property : {};
1567
1741
  return [key, { tag: "plain_text", content: typeof p.content === "string" ? p.content : "" }];
1568
1742
  }
1569
- if (ownerTag === "header" && (key === "title" || key === "subtitle") && isRecord2(rawValue)) {
1743
+ if (ownerTag === "header" && (key === "title" || key === "subtitle") && isRecord3(rawValue)) {
1570
1744
  const headerText = convertHeaderText(rawValue, ctx);
1571
1745
  if (headerText) return [key, headerText];
1572
1746
  }
1573
- if (ownerTag === "header" && key === "ud_icon" && isRecord2(rawValue) && rawValue.tag === "ud_icon") {
1574
- const p = isRecord2(rawValue.property) ? rawValue.property : {};
1747
+ if (ownerTag === "header" && key === "ud_icon" && isRecord3(rawValue) && rawValue.tag === "ud_icon") {
1748
+ const p = isRecord3(rawValue.property) ? rawValue.property : {};
1575
1749
  const token = typeof p.token === "string" ? p.token : void 0;
1576
1750
  if (!token) return DROP;
1577
1751
  return ["icon", { tag: "standard_icon", token }];
1578
1752
  }
1579
- if (ownerTag === "collapsible_panel" && key === "header" && isRecord2(rawValue)) {
1753
+ if (ownerTag === "collapsible_panel" && key === "header" && isRecord3(rawValue)) {
1580
1754
  const cleaned = {};
1581
1755
  for (const [k, v] of Object.entries(rawValue)) {
1582
1756
  const sk = snake(k);
@@ -1593,8 +1767,8 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1593
1767
  if (ownerTag === "button" && key === "actions" && Array.isArray(rawValue)) {
1594
1768
  const openUrls = [];
1595
1769
  for (const a of rawValue) {
1596
- if (!isRecord2(a)) continue;
1597
- const inner = isRecord2(a.action) ? a.action : {};
1770
+ if (!isRecord3(a)) continue;
1771
+ const inner = isRecord3(a.action) ? a.action : {};
1598
1772
  const t = typeof a.type === "string" ? a.type : void 0;
1599
1773
  if (t === "open_url" && typeof inner.url === "string") openUrls.push(inner.url);
1600
1774
  }
@@ -1609,8 +1783,8 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1609
1783
  }
1610
1784
  if (ownerTag === "interactive_container" && key === "actions" && Array.isArray(rawValue)) {
1611
1785
  const behaviors = rawValue.map((a) => {
1612
- if (!isRecord2(a)) return void 0;
1613
- const inner = isRecord2(a.action) ? a.action : {};
1786
+ if (!isRecord3(a)) return void 0;
1787
+ const inner = isRecord3(a.action) ? a.action : {};
1614
1788
  const t = typeof a.type === "string" ? a.type : void 0;
1615
1789
  if (t === "open_url" && typeof inner.url === "string") {
1616
1790
  return { type: "open_url", default_url: inner.url };
@@ -1623,7 +1797,7 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1623
1797
  if (behaviors.length === 0) return DROP;
1624
1798
  return ["behaviors", behaviors];
1625
1799
  }
1626
- if (key === "border" && isRecord2(rawValue)) {
1800
+ if (key === "border" && isRecord3(rawValue)) {
1627
1801
  const b = rawValue;
1628
1802
  const out = {};
1629
1803
  if (typeof b.borderColor === "string") out.color = b.borderColor;
@@ -1637,7 +1811,7 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1637
1811
  }
1638
1812
  return [key, out];
1639
1813
  }
1640
- if (key === "url" && isRecord2(rawValue)) {
1814
+ if (key === "url" && isRecord3(rawValue)) {
1641
1815
  const v = rawValue;
1642
1816
  const main = typeof v.url === "string" ? v.url : "";
1643
1817
  const others = ["androidURL", "iosURL", "pcURL", "harmonyURL"].map((k) => v[k]).filter((x) => typeof x === "string" && x.length > 0);
@@ -1678,7 +1852,7 @@ function renderInlineAudio(prop) {
1678
1852
  if (bg) attrs.push(`background_color='${bg}'`);
1679
1853
  const fill = typeof prop.fillColor === "string" ? prop.fillColor : typeof prop.fill_color === "string" ? prop.fill_color : void 0;
1680
1854
  if (fill) attrs.push(`fill_color='${fill}'`);
1681
- const urlObj = isRecord2(prop.url) ? prop.url : void 0;
1855
+ const urlObj = isRecord3(prop.url) ? prop.url : void 0;
1682
1856
  if (urlObj) {
1683
1857
  if (typeof urlObj.url === "string" && urlObj.url) attrs.push(`fallback_url='${urlObj.url}'`);
1684
1858
  if (typeof urlObj.pcURL === "string" && urlObj.pcURL) attrs.push(`fallback_pc_url='${urlObj.pcURL}'`);
@@ -1692,9 +1866,9 @@ function renderInlineAudio(prop) {
1692
1866
  } else if (typeof prop.fallback_url === "string" && prop.fallback_url) {
1693
1867
  attrs.push(`fallback_url='${prop.fallback_url}'`);
1694
1868
  }
1695
- const fb = isRecord2(prop.fallbackText) ? prop.fallbackText : isRecord2(prop.fallback_text) ? prop.fallback_text : void 0;
1869
+ const fb = isRecord3(prop.fallbackText) ? prop.fallbackText : isRecord3(prop.fallback_text) ? prop.fallback_text : void 0;
1696
1870
  if (fb) {
1697
- const fbProp = isRecord2(fb.property) ? fb.property : fb;
1871
+ const fbProp = isRecord3(fb.property) ? fb.property : fb;
1698
1872
  const fbContent = typeof fbProp.content === "string" ? fbProp.content : typeof fb.content === "string" ? fb.content : "";
1699
1873
  if (fbContent) attrs.push(`fallback_text='${fbContent}'`);
1700
1874
  }
@@ -1718,7 +1892,7 @@ function rebuildMarkdown(property, ctx) {
1718
1892
  if (rawKey === "elements" || rawKey === "markdownElements" || rawKey === "originTag") continue;
1719
1893
  if (rawKey === "udIcon") continue;
1720
1894
  if (rawKey === "textStyle") {
1721
- const ts = isRecord2(rawValue) ? rawValue : {};
1895
+ const ts = isRecord3(rawValue) ? rawValue : {};
1722
1896
  const size = typeof ts.size === "string" ? ts.size : void 0;
1723
1897
  if (size) out.text_size = size;
1724
1898
  continue;
@@ -1794,7 +1968,7 @@ function renderChildren(children, ctx) {
1794
1968
  buffer = [];
1795
1969
  }
1796
1970
  for (const child of children) {
1797
- if (!isRecord2(child)) continue;
1971
+ if (!isRecord3(child)) continue;
1798
1972
  const inline = childToInlineSegment(child, ctx);
1799
1973
  if (inline) {
1800
1974
  buffer.push(inline);
@@ -1808,8 +1982,8 @@ function renderChildren(children, ctx) {
1808
1982
  }
1809
1983
  function childToInlineSegment(child, ctx) {
1810
1984
  const tag = child.tag;
1811
- const prop = isRecord2(child.property) ? child.property : {};
1812
- const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
1985
+ const prop = isRecord3(child.property) ? child.property : {};
1986
+ const ts = isRecord3(prop.textStyle) ? prop.textStyle : void 0;
1813
1987
  const { bold, color, colorKind } = resolveInlineStyle(ts, ctx);
1814
1988
  switch (tag) {
1815
1989
  case "plain_text":
@@ -1828,7 +2002,7 @@ function childToInlineSegment(child, ctx) {
1828
2002
  };
1829
2003
  case "link": {
1830
2004
  const text = typeof prop.content === "string" ? prop.content : "";
1831
- const urlObj = isRecord2(prop.url) ? prop.url : void 0;
2005
+ const urlObj = isRecord3(prop.url) ? prop.url : void 0;
1832
2006
  const url = urlObj && typeof urlObj.url === "string" ? urlObj.url : "";
1833
2007
  return { content: `[${text}](${url})`, bold, color, colorKind };
1834
2008
  }
@@ -1840,8 +2014,8 @@ function childToInlineSegment(child, ctx) {
1840
2014
  }
1841
2015
  case "text_tag": {
1842
2016
  const tagColor = typeof prop.color === "string" ? prop.color : void 0;
1843
- const inner = isRecord2(prop.text) ? prop.text : void 0;
1844
- const innerProp = inner && isRecord2(inner.property) ? inner.property : void 0;
2017
+ const inner = isRecord3(prop.text) ? prop.text : void 0;
2018
+ const innerProp = inner && isRecord3(inner.property) ? inner.property : void 0;
1845
2019
  const innerContent = innerProp && typeof innerProp.content === "string" ? innerProp.content : "";
1846
2020
  const rendered = tagColor ? `<text_tag color='${tagColor}'>${innerContent}</text_tag>` : `<text_tag>${innerContent}</text_tag>`;
1847
2021
  return { content: rendered, bold: false };
@@ -1865,11 +2039,11 @@ function childToInlineSegment(child, ctx) {
1865
2039
  }
1866
2040
  function childToMarkdown(child, ctx) {
1867
2041
  const tag = child.tag;
1868
- const prop = isRecord2(child.property) ? child.property : {};
2042
+ const prop = isRecord3(child.property) ? child.property : {};
1869
2043
  switch (tag) {
1870
2044
  case "plain_text": {
1871
2045
  const content = typeof prop.content === "string" ? prop.content : "";
1872
- const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
2046
+ const ts = isRecord3(prop.textStyle) ? prop.textStyle : void 0;
1873
2047
  const { bold, color } = resolveInlineStyle(ts, ctx);
1874
2048
  return wrapEmphasis(content, bold, color);
1875
2049
  }
@@ -1892,7 +2066,7 @@ function childToMarkdown(child, ctx) {
1892
2066
  return renderInlineAudio(prop);
1893
2067
  case "link": {
1894
2068
  const text = typeof prop.content === "string" ? prop.content : "";
1895
- const urlObj = isRecord2(prop.url) ? prop.url : void 0;
2069
+ const urlObj = isRecord3(prop.url) ? prop.url : void 0;
1896
2070
  const url = urlObj && typeof urlObj.url === "string" ? urlObj.url : "";
1897
2071
  return `[${text}](${url})`;
1898
2072
  }
@@ -1902,8 +2076,8 @@ function childToMarkdown(child, ctx) {
1902
2076
  }
1903
2077
  case "text_tag": {
1904
2078
  const color = typeof prop.color === "string" ? prop.color : void 0;
1905
- const inner = isRecord2(prop.text) ? prop.text : void 0;
1906
- const innerProp = inner && isRecord2(inner.property) ? inner.property : void 0;
2079
+ const inner = isRecord3(prop.text) ? prop.text : void 0;
2080
+ const innerProp = inner && isRecord3(inner.property) ? inner.property : void 0;
1907
2081
  const innerContent = innerProp && typeof innerProp.content === "string" ? innerProp.content : "";
1908
2082
  if (color) return `<text_tag color='${color}'>${innerContent}</text_tag>`;
1909
2083
  return `<text_tag>${innerContent}</text_tag>`;
@@ -1912,11 +2086,11 @@ function childToMarkdown(child, ctx) {
1912
2086
  const lang = typeof prop.language === "string" ? prop.language : "";
1913
2087
  const blocks = Array.isArray(prop.contents) ? prop.contents : [];
1914
2088
  const lines = blocks.map((blk) => {
1915
- if (!isRecord2(blk)) return "";
2089
+ if (!isRecord3(blk)) return "";
1916
2090
  const inner = Array.isArray(blk.contents) ? blk.contents : [];
1917
2091
  let line = "";
1918
2092
  for (const seg of inner) {
1919
- if (isRecord2(seg) && typeof seg.content === "string") line += seg.content;
2093
+ if (isRecord3(seg) && typeof seg.content === "string") line += seg.content;
1920
2094
  }
1921
2095
  return line;
1922
2096
  });
@@ -1932,14 +2106,14 @@ ${body}
1932
2106
  const lines = [];
1933
2107
  const levelCounters = [];
1934
2108
  for (const item of items) {
1935
- if (!isRecord2(item)) continue;
2109
+ if (!isRecord3(item)) continue;
1936
2110
  const level = typeof item.level === "number" ? item.level : 0;
1937
2111
  const type = typeof item.type === "string" ? item.type : "ul";
1938
2112
  const indent = " ".repeat(level);
1939
2113
  const inner = Array.isArray(item.elements) ? item.elements : [];
1940
2114
  let text = "";
1941
2115
  for (const seg of inner) {
1942
- if (!isRecord2(seg)) continue;
2116
+ if (!isRecord3(seg)) continue;
1943
2117
  text += childToMarkdown(seg, ctx);
1944
2118
  }
1945
2119
  if (type === "ol") {
@@ -1968,7 +2142,7 @@ ${lines.join("\n")}
1968
2142
  const inner = Array.isArray(prop.elements) ? prop.elements : [];
1969
2143
  let body = "";
1970
2144
  for (const seg of inner) {
1971
- if (isRecord2(seg)) body += childToMarkdown(seg, ctx);
2145
+ if (isRecord3(seg)) body += childToMarkdown(seg, ctx);
1972
2146
  }
1973
2147
  return `
1974
2148
 
@@ -1984,18 +2158,18 @@ ${"#".repeat(level)} ${body}
1984
2158
  const rows = Array.isArray(prop.rows) ? prop.rows : [];
1985
2159
  if (columns.length === 0) return "";
1986
2160
  const headers = columns.map(
1987
- (col) => isRecord2(col) && typeof col.displayName === "string" ? col.displayName : ""
2161
+ (col) => isRecord3(col) && typeof col.displayName === "string" ? col.displayName : ""
1988
2162
  );
1989
2163
  const headerLine = `| ${headers.join(" | ")} |`;
1990
2164
  const separator = `| ${columns.map(() => "--------").join(" | ")} |`;
1991
2165
  const bodyLines = rows.map((row) => {
1992
- if (!isRecord2(row)) return `| ${columns.map(() => "").join(" | ")} |`;
2166
+ if (!isRecord3(row)) return `| ${columns.map(() => "").join(" | ")} |`;
1993
2167
  const cells = columns.map((col) => {
1994
- const name = isRecord2(col) && typeof col.name === "string" ? col.name : "";
1995
- const cell = isRecord2(row[name]) ? row[name] : void 0;
1996
- const data = cell && isRecord2(cell.data) ? cell.data : void 0;
2168
+ const name = isRecord3(col) && typeof col.name === "string" ? col.name : "";
2169
+ const cell = isRecord3(row[name]) ? row[name] : void 0;
2170
+ const data = cell && isRecord3(cell.data) ? cell.data : void 0;
1997
2171
  if (!data || data.tag !== "markdown") return "";
1998
- const cellProp = isRecord2(data.property) ? data.property : {};
2172
+ const cellProp = isRecord3(data.property) ? data.property : {};
1999
2173
  const inner = Array.isArray(cellProp.elements) ? cellProp.elements : [];
2000
2174
  const { content: text } = renderChildren(inner, ctx);
2001
2175
  return text.replace(/\|/g, "\\|").replace(/\n/g, " ");
@@ -2014,7 +2188,7 @@ ${bodyLines.join("\n")}
2014
2188
  const inner = Array.isArray(prop.elements) ? prop.elements : [];
2015
2189
  let body = "";
2016
2190
  for (const seg of inner) {
2017
- if (isRecord2(seg)) body += childToMarkdown(seg, ctx);
2191
+ if (isRecord3(seg)) body += childToMarkdown(seg, ctx);
2018
2192
  }
2019
2193
  return `
2020
2194
 
@@ -2029,14 +2203,14 @@ ${bodyLines.join("\n")}
2029
2203
  function convertGeneric(value, ctx) {
2030
2204
  if (Array.isArray(value)) {
2031
2205
  return value.map((item) => {
2032
- if (isRecord2(item) && typeof item.tag === "string" && isRecord2(item.property)) {
2206
+ if (isRecord3(item) && typeof item.tag === "string" && isRecord3(item.property)) {
2033
2207
  return unwrap(item, ctx);
2034
2208
  }
2035
2209
  return convertGeneric(item, ctx);
2036
2210
  });
2037
2211
  }
2038
- if (isRecord2(value)) {
2039
- if (typeof value.tag === "string" && isRecord2(value.property)) {
2212
+ if (isRecord3(value)) {
2213
+ if (typeof value.tag === "string" && isRecord3(value.property)) {
2040
2214
  return unwrap(value, ctx);
2041
2215
  }
2042
2216
  if (hasSide(value)) {
@@ -2053,7 +2227,7 @@ function convertGeneric(value, ctx) {
2053
2227
  }
2054
2228
  return value;
2055
2229
  }
2056
- function isRecord2(v) {
2230
+ function isRecord3(v) {
2057
2231
  return typeof v === "object" && v !== null && !Array.isArray(v);
2058
2232
  }
2059
2233
  function resolveAttachmentImgKey(rawValue, ctx) {
@@ -2069,7 +2243,7 @@ function normalizeVideoCover(rawValue, ctx) {
2069
2243
  const imgKey2 = resolveAttachmentImgKey(rawValue, ctx);
2070
2244
  return imgKey2 ? { img_key: imgKey2 } : void 0;
2071
2245
  }
2072
- if (!isRecord2(rawValue)) return void 0;
2246
+ if (!isRecord3(rawValue)) return void 0;
2073
2247
  if (typeof rawValue.img_key === "string" && rawValue.img_key) {
2074
2248
  return { img_key: rawValue.img_key };
2075
2249
  }
@@ -2078,17 +2252,17 @@ function normalizeVideoCover(rawValue, ctx) {
2078
2252
  return imgKey ? { img_key: imgKey } : void 0;
2079
2253
  }
2080
2254
  function hasSide(v) {
2081
- 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);
2255
+ 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);
2082
2256
  }
2083
2257
  function formatBox(v) {
2084
2258
  return `${pixelOf(v.top)}px ${pixelOf(v.right)}px ${pixelOf(v.bottom)}px ${pixelOf(v.left)}px`;
2085
2259
  }
2086
2260
  function isPixelScalar(v) {
2087
- if (!isRecord2(v)) return false;
2261
+ if (!isRecord3(v)) return false;
2088
2262
  return typeof v.type === "string" && v.type.includes("pixels") && typeof v.value === "number";
2089
2263
  }
2090
2264
  function pixelOf(side) {
2091
- if (!isRecord2(side)) return 0;
2265
+ if (!isRecord3(side)) return 0;
2092
2266
  const v = side.value;
2093
2267
  if (typeof v === "number") return v;
2094
2268
  if (typeof v === "string") {
@@ -2109,8 +2283,8 @@ function rawToDsl(raw) {
2109
2283
  return raw;
2110
2284
  }
2111
2285
  }
2112
- if (!isRecord2(raw)) return raw;
2113
- if (typeof raw.json_card === "string" || isRecord2(raw.json_card)) {
2286
+ if (!isRecord3(raw)) return raw;
2287
+ if (typeof raw.json_card === "string" || isRecord3(raw.json_card)) {
2114
2288
  let inner = raw.json_card;
2115
2289
  if (typeof inner === "string") {
2116
2290
  try {
@@ -2119,16 +2293,16 @@ function rawToDsl(raw) {
2119
2293
  return raw;
2120
2294
  }
2121
2295
  }
2122
- const attachment = isRecord2(raw.json_attachment) ? raw.json_attachment : {};
2296
+ const attachment = isRecord3(raw.json_attachment) ? raw.json_attachment : {};
2123
2297
  const ctx = makeCtx({
2124
- images: isRecord2(attachment.images) ? attachment.images : {},
2125
- atUsers: isRecord2(attachment.at_users) ? attachment.at_users : {}
2298
+ images: isRecord3(attachment.images) ? attachment.images : {},
2299
+ atUsers: isRecord3(attachment.at_users) ? attachment.at_users : {}
2126
2300
  });
2127
2301
  return convertRoot(inner, ctx);
2128
2302
  }
2129
- if (isRecord2(raw.card)) {
2303
+ if (isRecord3(raw.card)) {
2130
2304
  const card = raw.card;
2131
- if (typeof card.json_card === "string" || isRecord2(card.json_card)) {
2305
+ if (typeof card.json_card === "string" || isRecord3(card.json_card)) {
2132
2306
  return rawToDsl(card);
2133
2307
  }
2134
2308
  return convertRoot(card, makeCtx());
@@ -2155,6 +2329,7 @@ exports.readThemeColorDark = readThemeColorDark;
2155
2329
  exports.readThemeColorLight = readThemeColorLight;
2156
2330
  exports.registerColorEntry = registerColorEntry;
2157
2331
  exports.resolveCustomBackgroundLight = resolveCustomBackgroundLight;
2332
+ exports.resolveCustomBorderLight = resolveCustomBorderLight;
2158
2333
  exports.resolveTextStyleColor = resolveTextStyleColor;
2159
2334
  exports.resolveTextStyleCustomColorPair = resolveTextStyleCustomColorPair;
2160
2335
  exports.themePairToColorEntry = themePairToColorEntry;