@open-feishu-card/adapter 0.3.5 → 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.cjs CHANGED
@@ -606,6 +606,65 @@ 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) => {
648
+ const property = el.property ? { ...el.property } : void 0;
649
+ if (!property) return el;
650
+ if (Array.isArray(property.elements)) {
651
+ property.elements = expandMarkdownElements(property.elements, registry);
652
+ }
653
+ if (property.textStyle) {
654
+ const expanded = expandTextStyleColor(property.textStyle, registry);
655
+ if (expanded) property.textStyle = expanded;
656
+ }
657
+ return property === el.property ? el : { ...el, property };
658
+ });
659
+ }
660
+ function wrapMarkdownContentWithFontColor(content, fontColor) {
661
+ if (!fontColor || !content || /<font\s+color/i.test(content)) return content;
662
+ return `<font color='${fontColor}'>${content}</font>`;
663
+ }
664
+ function isRecord(v) {
665
+ return typeof v === "object" && v !== null && !Array.isArray(v);
666
+ }
667
+
609
668
  // src/dsl-to-raw.ts
610
669
  var KEY_RENAME = {
611
670
  text_align: "textAlign",
@@ -631,14 +690,22 @@ var KEY_RENAME = {
631
690
  };
632
691
  var TEXT_LEAF_KEYS = /* @__PURE__ */ new Set(["title", "subtitle", "alt", "hover_tips", "placeholder"]);
633
692
  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;
693
+ const root = isRecord2(dsl) ? dsl : {};
694
+ const card = unwrapCard(root);
695
+ const colors = readColorRegistry(card);
636
696
  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);
697
+ if (isRecord2(card.config)) out.config = { ...card.config };
698
+ if (isRecord2(card.header)) out.header = convertHeader(card.header, colors);
699
+ if (isRecord2(card.body)) out.body = convertBody(card.body, colors);
639
700
  return out;
640
701
  }
641
- function convertHeader(header) {
702
+ function unwrapCard(root) {
703
+ if (isRecord2(root.dsl)) return root.dsl;
704
+ if (isRecord2(root.card)) return root.card;
705
+ if (isRecord2(root.json_card)) return root.json_card;
706
+ return root;
707
+ }
708
+ function convertHeader(header, colors) {
642
709
  const property = {};
643
710
  for (const [k, v] of Object.entries(header)) {
644
711
  if (k === "tag") continue;
@@ -650,32 +717,32 @@ function convertHeader(header) {
650
717
  property[k] = wrapTextLeaf(v);
651
718
  continue;
652
719
  }
653
- if ((k === "icon" || k === "ud_icon") && isRecord(v)) {
654
- property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v);
720
+ if ((k === "icon" || k === "ud_icon") && isRecord2(v)) {
721
+ property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v, colors);
655
722
  continue;
656
723
  }
657
724
  if (k === "text_tag_list" && Array.isArray(v)) {
658
- property.text_tag_list = v.map(convertNode);
725
+ property.text_tag_list = v.map((item) => convertNode(item, colors));
659
726
  continue;
660
727
  }
661
- property[renameKey(k)] = coerceValue(k, v);
728
+ property[renameKey(k)] = coerceValue(k, v, colors);
662
729
  }
663
730
  return { tag: "card_header", property };
664
731
  }
665
- function convertBody(body) {
666
- const property = buildProperty(body, "body");
667
- const elements = Array.isArray(body.elements) ? body.elements.map(convertNode) : [];
732
+ function convertBody(body, colors) {
733
+ const property = buildProperty(body, "body", colors);
734
+ const elements = Array.isArray(body.elements) ? body.elements.map((n) => convertNode(n, colors)) : [];
668
735
  property.elements = elements.filter(Boolean);
669
736
  return { tag: "body", property };
670
737
  }
671
- function convertNode(node) {
672
- if (isRecord(node) && typeof node.tag === "string") return convertEl(node);
738
+ function convertNode(node, colors) {
739
+ if (isRecord2(node) && typeof node.tag === "string") return convertEl(node, colors);
673
740
  return node;
674
741
  }
675
- function convertEl(el) {
742
+ function convertEl(el, colors) {
676
743
  const tag = String(el.tag);
677
744
  if (tag === "person") {
678
- const property = buildProperty(el, "person_v1");
745
+ const property = buildProperty(el, "person_v1", colors);
679
746
  if (property.style === "capsule") {
680
747
  property.pillShaped = true;
681
748
  delete property.style;
@@ -683,16 +750,22 @@ function convertEl(el) {
683
750
  return { tag: "person_v1", property };
684
751
  }
685
752
  if (tag === "markdown" || tag === "lark_md") {
686
- const property = buildProperty(el, "markdown");
687
- if (typeof el.content === "string") property.elements = parseMarkdown(el.content);
753
+ const property = buildProperty(el, "markdown", colors);
754
+ const fontColor = typeof el.font_color === "string" ? el.font_color : void 0;
755
+ let content = typeof el.content === "string" ? el.content : "";
756
+ content = wrapMarkdownContentWithFontColor(content, fontColor);
757
+ if (content) {
758
+ property.elements = expandMarkdownElements(parseMarkdown(content), colors);
759
+ }
688
760
  delete property.content;
761
+ delete property.font_color;
689
762
  return { tag: "markdown", property };
690
763
  }
691
764
  if (tag === "table") {
692
- return { tag, property: convertTableProperty(el) };
765
+ return { tag, property: convertTableProperty(el, colors) };
693
766
  }
694
767
  if (tag === "audio" || tag === "video") {
695
- const property = buildProperty(el, tag);
768
+ const property = buildProperty(el, tag, colors);
696
769
  if (tag === "audio" && el.width != null) {
697
770
  delete property.width;
698
771
  if (el.width === "fill" || el.width === "default") {
@@ -710,14 +783,14 @@ function convertEl(el) {
710
783
  }
711
784
  return { tag, property };
712
785
  }
713
- return { tag, property: buildProperty(el, tag) };
786
+ return { tag, property: buildProperty(el, tag, colors) };
714
787
  }
715
- function convertTableProperty(el) {
716
- const property = buildProperty(el, "table");
788
+ function convertTableProperty(el, colors) {
789
+ const property = buildProperty(el, "table", colors);
717
790
  const columns = Array.isArray(property.columns) ? property.columns : [];
718
791
  const mdColNames = /* @__PURE__ */ new Set();
719
792
  for (const col of columns) {
720
- if (!isRecord(col)) continue;
793
+ if (!isRecord2(col)) continue;
721
794
  const dt = col.data_type ?? col.dataType;
722
795
  if (dt === "lark_md" || dt === "markdown") {
723
796
  const name = typeof col.name === "string" ? col.name : "";
@@ -726,7 +799,7 @@ function convertTableProperty(el) {
726
799
  }
727
800
  if (!mdColNames.size || !Array.isArray(property.rows)) return property;
728
801
  property.rows = property.rows.map((row) => {
729
- if (!isRecord(row)) return row;
802
+ if (!isRecord2(row)) return row;
730
803
  const out = { ...row };
731
804
  for (const name of mdColNames) {
732
805
  const cell = out[name];
@@ -734,7 +807,10 @@ function convertTableProperty(el) {
734
807
  out[name] = {
735
808
  data: {
736
809
  tag: "markdown",
737
- property: { elements: parseMarkdown(cell), originTag: "lark_md" }
810
+ property: {
811
+ elements: expandMarkdownElements(parseMarkdown(cell), colors),
812
+ originTag: "lark_md"
813
+ }
738
814
  }
739
815
  };
740
816
  }
@@ -743,10 +819,17 @@ function convertTableProperty(el) {
743
819
  });
744
820
  return property;
745
821
  }
746
- function buildProperty(el, tag) {
822
+ function buildProperty(el, tag, colors) {
747
823
  const property = {};
748
824
  for (const [k, v] of Object.entries(el)) {
749
825
  if (k === "tag" || k === "id") continue;
826
+ if ((k === "background_style" || k === "backgroundStyle") && (tag === "column" || tag === "column_set")) {
827
+ const renamed = renameKey(k);
828
+ property[renamed] = v;
829
+ const expanded = expandBackgroundStyleAlias(v, colors);
830
+ if (expanded) property.customBackgroundStyle = expanded;
831
+ continue;
832
+ }
750
833
  if (tag === "column" && k === "width" && typeof v === "string") {
751
834
  const px = pxValue(v);
752
835
  if (px != null) {
@@ -759,15 +842,15 @@ function buildProperty(el, tag) {
759
842
  continue;
760
843
  }
761
844
  if (k === "text") {
762
- if (tag === "checker" && isRecord(v) && (v.tag === "markdown" || v.tag === "lark_md")) {
763
- property.text = convertEl(v);
845
+ if (tag === "checker" && isRecord2(v) && (v.tag === "markdown" || v.tag === "lark_md")) {
846
+ property.text = convertEl(v, colors);
764
847
  } else {
765
848
  property.text = wrapTextLeaf(v);
766
849
  }
767
850
  continue;
768
851
  }
769
- if ((k === "icon" || k === "ud_icon") && isRecord(v)) {
770
- property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v);
852
+ if ((k === "icon" || k === "ud_icon") && isRecord2(v)) {
853
+ property[k === "ud_icon" ? "udIcon" : "icon"] = convertEl(v, colors);
771
854
  continue;
772
855
  }
773
856
  if (k === "behaviors" && Array.isArray(v)) {
@@ -778,21 +861,21 @@ function buildProperty(el, tag) {
778
861
  property.url = normalizeUrl(v);
779
862
  continue;
780
863
  }
781
- if (k === "button_area" && isRecord(v)) {
864
+ if (k === "button_area" && isRecord2(v)) {
782
865
  const area = { ...v };
783
- if (Array.isArray(v.buttons)) area.buttons = v.buttons.map(convertNode);
866
+ if (Array.isArray(v.buttons)) area.buttons = v.buttons.map((b) => convertNode(b, colors));
784
867
  property.button_area = area;
785
868
  continue;
786
869
  }
787
- property[renameKey(k)] = coerceValue(k, v);
870
+ property[renameKey(k)] = coerceValue(k, v, colors);
788
871
  }
789
872
  return property;
790
873
  }
791
- function coerceValue(key, value) {
874
+ function coerceValue(key, value, colors) {
792
875
  if ((key === "padding" || key === "margin") && typeof value === "string") {
793
876
  return parseBox(value);
794
877
  }
795
- if (Array.isArray(value)) return value.map(convertNode);
878
+ if (Array.isArray(value)) return value.map((item) => convertNode(item, colors));
796
879
  if (key === "url") return normalizeUrl(value);
797
880
  return value;
798
881
  }
@@ -801,7 +884,7 @@ function renameKey(k) {
801
884
  }
802
885
  function wrapTextLeaf(v) {
803
886
  if (typeof v === "string") return { tag: "plain_text", property: { content: v } };
804
- if (isRecord(v)) {
887
+ if (isRecord2(v)) {
805
888
  const property = { content: typeof v.content === "string" ? v.content : "" };
806
889
  if (typeof v.text_align === "string") property.textAlign = v.text_align;
807
890
  if (typeof v.text_size === "string") property.text_size = v.text_size;
@@ -812,7 +895,7 @@ function wrapTextLeaf(v) {
812
895
  }
813
896
  function wrapHeaderText(v) {
814
897
  if (typeof v === "string") return { tag: "plain_text", property: { content: v } };
815
- if (!isRecord(v)) return { tag: "plain_text", property: { content: "" } };
898
+ if (!isRecord2(v)) return { tag: "plain_text", property: { content: "" } };
816
899
  const tag = typeof v.tag === "string" ? v.tag : "plain_text";
817
900
  const content = typeof v.content === "string" ? v.content : "";
818
901
  if (tag === "lark_md" || tag === "markdown") {
@@ -829,7 +912,7 @@ function wrapHeaderText(v) {
829
912
  function behaviorsToActions(behaviors) {
830
913
  const out = [];
831
914
  for (const b of behaviors) {
832
- if (!isRecord(b)) continue;
915
+ if (!isRecord2(b)) continue;
833
916
  const type = typeof b.type === "string" ? b.type : "open_url";
834
917
  out.push({ type, action: { url: normalizeUrl(b.default_url) } });
835
918
  }
@@ -837,7 +920,7 @@ function behaviorsToActions(behaviors) {
837
920
  }
838
921
  function normalizeUrl(v) {
839
922
  if (typeof v === "string") return v;
840
- if (isRecord(v)) return v;
923
+ if (isRecord2(v)) return v;
841
924
  return v;
842
925
  }
843
926
  function parseBox(s) {
@@ -864,7 +947,7 @@ function pxValue(s) {
864
947
  const n = Number(s);
865
948
  return Number.isFinite(n) ? n : null;
866
949
  }
867
- function isRecord(v) {
950
+ function isRecord2(v) {
868
951
  return typeof v === "object" && v !== null && !Array.isArray(v);
869
952
  }
870
953
 
@@ -1229,12 +1312,12 @@ var VALUE_ECHO_TARGETS = {
1229
1312
  size_value: "size"
1230
1313
  };
1231
1314
  function convertRoot(root, ctx) {
1232
- if (!isRecord2(root)) return root;
1315
+ if (!isRecord3(root)) return root;
1233
1316
  const out = {};
1234
1317
  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);
1318
+ out.config = convertConfig(isRecord3(root.config) ? root.config : {});
1319
+ if (isRecord3(root.body)) out.body = convertBody2(root.body, ctx);
1320
+ if (isRecord3(root.header)) out.header = convertHeader2(root.header, ctx);
1238
1321
  normalizeStoredCardColors(out, ctx.colors);
1239
1322
  return out;
1240
1323
  }
@@ -1242,14 +1325,14 @@ function convertConfig(_node) {
1242
1325
  return { update_multi: true };
1243
1326
  }
1244
1327
  function convertHeader2(node, ctx) {
1245
- const property = isRecord2(node.property) ? node.property : node;
1328
+ const property = isRecord3(node.property) ? node.property : node;
1246
1329
  const out = convertProperty(property, "header", ctx);
1247
1330
  delete out.tag;
1248
1331
  return out;
1249
1332
  }
1250
1333
  function convertHeaderText(rawValue, ctx) {
1251
1334
  const tag = typeof rawValue.tag === "string" ? rawValue.tag : "";
1252
- const wrapped = isRecord2(rawValue.property);
1335
+ const wrapped = isRecord3(rawValue.property);
1253
1336
  const property = wrapped ? rawValue.property : rawValue;
1254
1337
  if (tag === "plain_text") {
1255
1338
  const content = typeof property.content === "string" ? property.content : "";
@@ -1269,12 +1352,12 @@ function convertHeaderText(rawValue, ctx) {
1269
1352
  return void 0;
1270
1353
  }
1271
1354
  function convertBody2(node, ctx) {
1272
- const property = isRecord2(node.property) ? node.property : node;
1355
+ const property = isRecord3(node.property) ? node.property : node;
1273
1356
  return convertProperty(property, "body", ctx);
1274
1357
  }
1275
1358
  function unwrap(node, ctx) {
1276
1359
  const tag = typeof node.tag === "string" ? node.tag : void 0;
1277
- const property = isRecord2(node.property) ? node.property : {};
1360
+ const property = isRecord3(node.property) ? node.property : {};
1278
1361
  if (tag === "markdown") return rebuildMarkdown(property, ctx);
1279
1362
  if (tag === "plain_text") {
1280
1363
  const content = typeof property.content === "string" ? property.content : "";
@@ -1288,7 +1371,7 @@ function unwrap(node, ctx) {
1288
1371
  const heightPx = isPixelScalar(property.heightValue) ? pixelOf(property.heightValue) : void 0;
1289
1372
  if (widthPx !== void 0 && heightPx !== void 0) {
1290
1373
  out.size = `${widthPx}px ${heightPx}px`;
1291
- } else if (isRecord2(property.size) && hasSide(property.size)) out.size = formatBox(property.size);
1374
+ } else if (isRecord3(property.size) && hasSide(property.size)) out.size = formatBox(property.size);
1292
1375
  else if (isPixelScalar(property.size)) out.size = `${pixelOf(property.size)}px`;
1293
1376
  else if (typeof property.size === "string") out.size = property.size;
1294
1377
  return out;
@@ -1310,7 +1393,7 @@ function unwrap(node, ctx) {
1310
1393
  const out = { tag: "table" };
1311
1394
  const rawColumns = Array.isArray(property.columns) ? property.columns : [];
1312
1395
  out.columns = rawColumns.map((col) => {
1313
- if (!isRecord2(col)) return {};
1396
+ if (!isRecord3(col)) return {};
1314
1397
  const c = {};
1315
1398
  if (typeof col.name === "string") c.name = col.name;
1316
1399
  const displayName = typeof col.displayName === "string" ? col.displayName : typeof col.display_name === "string" ? col.display_name : void 0;
@@ -1320,22 +1403,22 @@ function unwrap(node, ctx) {
1320
1403
  const hAlign = typeof col.horizontalAlign === "string" ? col.horizontalAlign : typeof col.horizontal_align === "string" ? col.horizontal_align : void 0;
1321
1404
  if (hAlign !== void 0) c.horizontal_align = hAlign;
1322
1405
  const wv = col.widthValue;
1323
- if (isRecord2(wv)) {
1406
+ if (isRecord3(wv)) {
1324
1407
  if (wv.type === "pixels" && typeof wv.value === "number") c.width = `${wv.value}px`;
1325
1408
  else if (typeof wv.value === "string") c.width = wv.value;
1326
1409
  } else if (typeof col.width === "string" || typeof col.width === "number") {
1327
1410
  c.width = col.width;
1328
1411
  }
1329
- if (isRecord2(col.format)) c.format = col.format;
1412
+ if (isRecord3(col.format)) c.format = col.format;
1330
1413
  return c;
1331
1414
  });
1332
1415
  const rawRows = Array.isArray(property.rows) ? property.rows : [];
1333
1416
  out.rows = rawRows.map((row) => {
1334
- if (!isRecord2(row)) return {};
1417
+ if (!isRecord3(row)) return {};
1335
1418
  const r = {};
1336
1419
  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)) {
1420
+ let value = isRecord3(cell) && "data" in cell ? cell.data : cell;
1421
+ if (isRecord3(value) && value.tag === "markdown" && isRecord3(value.property)) {
1339
1422
  const elements = Array.isArray(value.property.elements) ? value.property.elements : [];
1340
1423
  value = renderChildren(elements, ctx).content;
1341
1424
  }
@@ -1343,13 +1426,13 @@ function unwrap(node, ctx) {
1343
1426
  }
1344
1427
  return r;
1345
1428
  });
1346
- if (isRecord2(property.headerStyle)) {
1429
+ if (isRecord3(property.headerStyle)) {
1347
1430
  const hs = {};
1348
1431
  for (const [k, v] of Object.entries(property.headerStyle)) {
1349
1432
  const sk = snake(k);
1350
1433
  if (sk === "platform_text_size") continue;
1351
1434
  if (sk === "lines_value") {
1352
- if (isRecord2(v) && typeof v.value === "number") hs.lines = v.value;
1435
+ if (isRecord3(v) && typeof v.value === "number") hs.lines = v.value;
1353
1436
  continue;
1354
1437
  }
1355
1438
  hs[sk] = v;
@@ -1357,7 +1440,7 @@ function unwrap(node, ctx) {
1357
1440
  out.header_style = hs;
1358
1441
  }
1359
1442
  const rhv = property.rowHeightValue;
1360
- if (isRecord2(rhv) && typeof rhv.value === "string") out.row_height = rhv.value;
1443
+ if (isRecord3(rhv) && typeof rhv.value === "string") out.row_height = rhv.value;
1361
1444
  else if (typeof property.rowHeight === "string") out.row_height = property.rowHeight;
1362
1445
  if (typeof property.pageSize === "number") out.page_size = property.pageSize;
1363
1446
  if (typeof property.freezeFirstColumn === "boolean") out.freeze_first_column = property.freezeFirstColumn;
@@ -1392,7 +1475,7 @@ function unwrap(node, ctx) {
1392
1475
  if (typeof property.showAvatar === "boolean") out.show_avatar = property.showAvatar;
1393
1476
  if (typeof property.showName === "boolean") out.show_name = property.showName;
1394
1477
  if (typeof property.style === "string") out.style = property.style;
1395
- if (isRecord2(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1478
+ if (isRecord3(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1396
1479
  else if (typeof property.margin === "string") out.margin = property.margin;
1397
1480
  return out;
1398
1481
  }
@@ -1404,17 +1487,17 @@ function unwrap(node, ctx) {
1404
1487
  if (typeof property.lines === "number") out.lines = property.lines;
1405
1488
  if (typeof property.dropInvalidUserID === "boolean") out.drop_invalid_user_id = property.dropInvalidUserID;
1406
1489
  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);
1490
+ if (isRecord3(property.margin) && hasSide(property.margin)) out.margin = formatBox(property.margin);
1408
1491
  else if (typeof property.margin === "string") out.margin = property.margin;
1409
1492
  const rawPersons = Array.isArray(property.persons) ? property.persons : [];
1410
1493
  out.persons = rawPersons.map((p) => {
1411
- if (!isRecord2(p)) return void 0;
1494
+ if (!isRecord3(p)) return void 0;
1412
1495
  const id = typeof p.id === "string" ? p.id : typeof p.userID === "string" ? p.userID : void 0;
1413
1496
  return id ? { id } : void 0;
1414
1497
  }).filter((p) => p !== void 0);
1415
- const iconSrc = isRecord2(property.icon) ? property.icon : isRecord2(property.udIcon) ? property.udIcon : void 0;
1498
+ const iconSrc = isRecord3(property.icon) ? property.icon : isRecord3(property.udIcon) ? property.udIcon : void 0;
1416
1499
  if (iconSrc) {
1417
- const ip = isRecord2(iconSrc.property) ? iconSrc.property : iconSrc;
1500
+ const ip = isRecord3(iconSrc.property) ? iconSrc.property : iconSrc;
1418
1501
  const icon = {};
1419
1502
  const iconTag = typeof iconSrc.tag === "string" ? iconSrc.tag : typeof ip.tag === "string" ? ip.tag : "standard_icon";
1420
1503
  icon.tag = iconTag === "ud_icon" ? "standard_icon" : iconTag;
@@ -1426,25 +1509,25 @@ function unwrap(node, ctx) {
1426
1509
  }
1427
1510
  return out;
1428
1511
  }
1429
- if (tag === "div" && isRecord2(property.text) && property.fields === void 0) {
1512
+ if (tag === "div" && isRecord3(property.text) && property.fields === void 0) {
1430
1513
  const text = property.text;
1431
1514
  const textTag = typeof text.tag === "string" ? text.tag : "";
1432
- if ((textTag === "markdown" || textTag === "lark_md") && isRecord2(text.property)) {
1515
+ if ((textTag === "markdown" || textTag === "lark_md") && isRecord3(text.property)) {
1433
1516
  return unwrap(text, ctx);
1434
1517
  }
1435
1518
  if (textTag === "plain_text") {
1436
1519
  const out = { tag: "div" };
1437
1520
  const widthVal = property.widthValue;
1438
- if (isRecord2(widthVal) && typeof widthVal.value === "string" && typeof widthVal.type === "string" && widthVal.type.startsWith("builtin_")) {
1521
+ if (isRecord3(widthVal) && typeof widthVal.value === "string" && typeof widthVal.type === "string" && widthVal.type.startsWith("builtin_")) {
1439
1522
  out.width = widthVal.value;
1440
1523
  } else if (typeof property.width === "string") {
1441
1524
  out.width = property.width;
1442
1525
  }
1443
- const tp = isRecord2(text.property) ? text.property : {};
1526
+ const tp = isRecord3(text.property) ? text.property : {};
1444
1527
  const content = typeof tp.content === "string" ? tp.content : "";
1445
1528
  const textAlign = typeof tp.textAlign === "string" ? tp.textAlign : "left";
1446
1529
  out.text = { tag: "plain_text", content, text_align: textAlign };
1447
- if (isRecord2(property.icon)) {
1530
+ if (isRecord3(property.icon)) {
1448
1531
  out.icon = unwrap(property.icon, ctx);
1449
1532
  }
1450
1533
  return out;
@@ -1471,7 +1554,7 @@ function convertProperty(property, ownerTag, ctx) {
1471
1554
  const echoVal = out[echoKey];
1472
1555
  const enumVal = out[enumKey];
1473
1556
  delete out[echoKey];
1474
- if (!isRecord2(echoVal)) continue;
1557
+ if (!isRecord3(echoVal)) continue;
1475
1558
  const echoType = typeof echoVal.type === "string" ? echoVal.type : "";
1476
1559
  const echoValue = echoVal.value;
1477
1560
  if (echoType.includes("pixels") && typeof echoValue === "number") {
@@ -1480,7 +1563,7 @@ function convertProperty(property, ownerTag, ctx) {
1480
1563
  }
1481
1564
  continue;
1482
1565
  }
1483
- if (echoType === "aspect_ratio" && isRecord2(echoValue)) {
1566
+ if (echoType === "aspect_ratio" && isRecord3(echoValue)) {
1484
1567
  const w = echoValue.width;
1485
1568
  const h = echoValue.height;
1486
1569
  if (typeof w === "number" && typeof h === "number") {
@@ -1488,7 +1571,7 @@ function convertProperty(property, ownerTag, ctx) {
1488
1571
  }
1489
1572
  continue;
1490
1573
  }
1491
- if (echoType === "width_height_pixels" && isRecord2(echoValue)) {
1574
+ if (echoType === "width_height_pixels" && isRecord3(echoValue)) {
1492
1575
  const w = echoValue.width;
1493
1576
  const h = echoValue.height;
1494
1577
  if (typeof w === "number" && typeof h === "number") {
@@ -1528,7 +1611,7 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1528
1611
  if (key === "actions" && Array.isArray(rawValue) && rawValue.length === 0) {
1529
1612
  return DROP;
1530
1613
  }
1531
- if ((key === "padding" || key === "margin") && isRecord2(rawValue) && hasSide(rawValue)) {
1614
+ if ((key === "padding" || key === "margin") && isRecord3(rawValue) && hasSide(rawValue)) {
1532
1615
  return [key, formatBox(rawValue)];
1533
1616
  }
1534
1617
  if (key in VALUE_ECHO_TARGETS) {
@@ -1558,25 +1641,25 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1558
1641
  return DROP;
1559
1642
  }
1560
1643
  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 : {};
1644
+ if ((key === "alt" || key === "hover_tips") && isRecord3(rawValue) && rawValue.tag === "plain_text") {
1645
+ const p = isRecord3(rawValue.property) ? rawValue.property : {};
1563
1646
  return [key, { tag: "plain_text", content: typeof p.content === "string" ? p.content : "" }];
1564
1647
  }
1565
- if (key === "text" && isRecord2(rawValue) && rawValue.tag === "plain_text") {
1566
- const p = isRecord2(rawValue.property) ? rawValue.property : {};
1648
+ if (key === "text" && isRecord3(rawValue) && rawValue.tag === "plain_text") {
1649
+ const p = isRecord3(rawValue.property) ? rawValue.property : {};
1567
1650
  return [key, { tag: "plain_text", content: typeof p.content === "string" ? p.content : "" }];
1568
1651
  }
1569
- if (ownerTag === "header" && (key === "title" || key === "subtitle") && isRecord2(rawValue)) {
1652
+ if (ownerTag === "header" && (key === "title" || key === "subtitle") && isRecord3(rawValue)) {
1570
1653
  const headerText = convertHeaderText(rawValue, ctx);
1571
1654
  if (headerText) return [key, headerText];
1572
1655
  }
1573
- if (ownerTag === "header" && key === "ud_icon" && isRecord2(rawValue) && rawValue.tag === "ud_icon") {
1574
- const p = isRecord2(rawValue.property) ? rawValue.property : {};
1656
+ if (ownerTag === "header" && key === "ud_icon" && isRecord3(rawValue) && rawValue.tag === "ud_icon") {
1657
+ const p = isRecord3(rawValue.property) ? rawValue.property : {};
1575
1658
  const token = typeof p.token === "string" ? p.token : void 0;
1576
1659
  if (!token) return DROP;
1577
1660
  return ["icon", { tag: "standard_icon", token }];
1578
1661
  }
1579
- if (ownerTag === "collapsible_panel" && key === "header" && isRecord2(rawValue)) {
1662
+ if (ownerTag === "collapsible_panel" && key === "header" && isRecord3(rawValue)) {
1580
1663
  const cleaned = {};
1581
1664
  for (const [k, v] of Object.entries(rawValue)) {
1582
1665
  const sk = snake(k);
@@ -1593,8 +1676,8 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1593
1676
  if (ownerTag === "button" && key === "actions" && Array.isArray(rawValue)) {
1594
1677
  const openUrls = [];
1595
1678
  for (const a of rawValue) {
1596
- if (!isRecord2(a)) continue;
1597
- const inner = isRecord2(a.action) ? a.action : {};
1679
+ if (!isRecord3(a)) continue;
1680
+ const inner = isRecord3(a.action) ? a.action : {};
1598
1681
  const t = typeof a.type === "string" ? a.type : void 0;
1599
1682
  if (t === "open_url" && typeof inner.url === "string") openUrls.push(inner.url);
1600
1683
  }
@@ -1609,8 +1692,8 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1609
1692
  }
1610
1693
  if (ownerTag === "interactive_container" && key === "actions" && Array.isArray(rawValue)) {
1611
1694
  const behaviors = rawValue.map((a) => {
1612
- if (!isRecord2(a)) return void 0;
1613
- const inner = isRecord2(a.action) ? a.action : {};
1695
+ if (!isRecord3(a)) return void 0;
1696
+ const inner = isRecord3(a.action) ? a.action : {};
1614
1697
  const t = typeof a.type === "string" ? a.type : void 0;
1615
1698
  if (t === "open_url" && typeof inner.url === "string") {
1616
1699
  return { type: "open_url", default_url: inner.url };
@@ -1623,7 +1706,7 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1623
1706
  if (behaviors.length === 0) return DROP;
1624
1707
  return ["behaviors", behaviors];
1625
1708
  }
1626
- if (key === "border" && isRecord2(rawValue)) {
1709
+ if (key === "border" && isRecord3(rawValue)) {
1627
1710
  const b = rawValue;
1628
1711
  const out = {};
1629
1712
  if (typeof b.borderColor === "string") out.color = b.borderColor;
@@ -1637,7 +1720,7 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1637
1720
  }
1638
1721
  return [key, out];
1639
1722
  }
1640
- if (key === "url" && isRecord2(rawValue)) {
1723
+ if (key === "url" && isRecord3(rawValue)) {
1641
1724
  const v = rawValue;
1642
1725
  const main = typeof v.url === "string" ? v.url : "";
1643
1726
  const others = ["androidURL", "iosURL", "pcURL", "harmonyURL"].map((k) => v[k]).filter((x) => typeof x === "string" && x.length > 0);
@@ -1678,7 +1761,7 @@ function renderInlineAudio(prop) {
1678
1761
  if (bg) attrs.push(`background_color='${bg}'`);
1679
1762
  const fill = typeof prop.fillColor === "string" ? prop.fillColor : typeof prop.fill_color === "string" ? prop.fill_color : void 0;
1680
1763
  if (fill) attrs.push(`fill_color='${fill}'`);
1681
- const urlObj = isRecord2(prop.url) ? prop.url : void 0;
1764
+ const urlObj = isRecord3(prop.url) ? prop.url : void 0;
1682
1765
  if (urlObj) {
1683
1766
  if (typeof urlObj.url === "string" && urlObj.url) attrs.push(`fallback_url='${urlObj.url}'`);
1684
1767
  if (typeof urlObj.pcURL === "string" && urlObj.pcURL) attrs.push(`fallback_pc_url='${urlObj.pcURL}'`);
@@ -1692,9 +1775,9 @@ function renderInlineAudio(prop) {
1692
1775
  } else if (typeof prop.fallback_url === "string" && prop.fallback_url) {
1693
1776
  attrs.push(`fallback_url='${prop.fallback_url}'`);
1694
1777
  }
1695
- const fb = isRecord2(prop.fallbackText) ? prop.fallbackText : isRecord2(prop.fallback_text) ? prop.fallback_text : void 0;
1778
+ const fb = isRecord3(prop.fallbackText) ? prop.fallbackText : isRecord3(prop.fallback_text) ? prop.fallback_text : void 0;
1696
1779
  if (fb) {
1697
- const fbProp = isRecord2(fb.property) ? fb.property : fb;
1780
+ const fbProp = isRecord3(fb.property) ? fb.property : fb;
1698
1781
  const fbContent = typeof fbProp.content === "string" ? fbProp.content : typeof fb.content === "string" ? fb.content : "";
1699
1782
  if (fbContent) attrs.push(`fallback_text='${fbContent}'`);
1700
1783
  }
@@ -1718,7 +1801,7 @@ function rebuildMarkdown(property, ctx) {
1718
1801
  if (rawKey === "elements" || rawKey === "markdownElements" || rawKey === "originTag") continue;
1719
1802
  if (rawKey === "udIcon") continue;
1720
1803
  if (rawKey === "textStyle") {
1721
- const ts = isRecord2(rawValue) ? rawValue : {};
1804
+ const ts = isRecord3(rawValue) ? rawValue : {};
1722
1805
  const size = typeof ts.size === "string" ? ts.size : void 0;
1723
1806
  if (size) out.text_size = size;
1724
1807
  continue;
@@ -1794,7 +1877,7 @@ function renderChildren(children, ctx) {
1794
1877
  buffer = [];
1795
1878
  }
1796
1879
  for (const child of children) {
1797
- if (!isRecord2(child)) continue;
1880
+ if (!isRecord3(child)) continue;
1798
1881
  const inline = childToInlineSegment(child, ctx);
1799
1882
  if (inline) {
1800
1883
  buffer.push(inline);
@@ -1808,8 +1891,8 @@ function renderChildren(children, ctx) {
1808
1891
  }
1809
1892
  function childToInlineSegment(child, ctx) {
1810
1893
  const tag = child.tag;
1811
- const prop = isRecord2(child.property) ? child.property : {};
1812
- const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
1894
+ const prop = isRecord3(child.property) ? child.property : {};
1895
+ const ts = isRecord3(prop.textStyle) ? prop.textStyle : void 0;
1813
1896
  const { bold, color, colorKind } = resolveInlineStyle(ts, ctx);
1814
1897
  switch (tag) {
1815
1898
  case "plain_text":
@@ -1828,7 +1911,7 @@ function childToInlineSegment(child, ctx) {
1828
1911
  };
1829
1912
  case "link": {
1830
1913
  const text = typeof prop.content === "string" ? prop.content : "";
1831
- const urlObj = isRecord2(prop.url) ? prop.url : void 0;
1914
+ const urlObj = isRecord3(prop.url) ? prop.url : void 0;
1832
1915
  const url = urlObj && typeof urlObj.url === "string" ? urlObj.url : "";
1833
1916
  return { content: `[${text}](${url})`, bold, color, colorKind };
1834
1917
  }
@@ -1840,8 +1923,8 @@ function childToInlineSegment(child, ctx) {
1840
1923
  }
1841
1924
  case "text_tag": {
1842
1925
  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;
1926
+ const inner = isRecord3(prop.text) ? prop.text : void 0;
1927
+ const innerProp = inner && isRecord3(inner.property) ? inner.property : void 0;
1845
1928
  const innerContent = innerProp && typeof innerProp.content === "string" ? innerProp.content : "";
1846
1929
  const rendered = tagColor ? `<text_tag color='${tagColor}'>${innerContent}</text_tag>` : `<text_tag>${innerContent}</text_tag>`;
1847
1930
  return { content: rendered, bold: false };
@@ -1865,11 +1948,11 @@ function childToInlineSegment(child, ctx) {
1865
1948
  }
1866
1949
  function childToMarkdown(child, ctx) {
1867
1950
  const tag = child.tag;
1868
- const prop = isRecord2(child.property) ? child.property : {};
1951
+ const prop = isRecord3(child.property) ? child.property : {};
1869
1952
  switch (tag) {
1870
1953
  case "plain_text": {
1871
1954
  const content = typeof prop.content === "string" ? prop.content : "";
1872
- const ts = isRecord2(prop.textStyle) ? prop.textStyle : void 0;
1955
+ const ts = isRecord3(prop.textStyle) ? prop.textStyle : void 0;
1873
1956
  const { bold, color } = resolveInlineStyle(ts, ctx);
1874
1957
  return wrapEmphasis(content, bold, color);
1875
1958
  }
@@ -1892,7 +1975,7 @@ function childToMarkdown(child, ctx) {
1892
1975
  return renderInlineAudio(prop);
1893
1976
  case "link": {
1894
1977
  const text = typeof prop.content === "string" ? prop.content : "";
1895
- const urlObj = isRecord2(prop.url) ? prop.url : void 0;
1978
+ const urlObj = isRecord3(prop.url) ? prop.url : void 0;
1896
1979
  const url = urlObj && typeof urlObj.url === "string" ? urlObj.url : "";
1897
1980
  return `[${text}](${url})`;
1898
1981
  }
@@ -1902,8 +1985,8 @@ function childToMarkdown(child, ctx) {
1902
1985
  }
1903
1986
  case "text_tag": {
1904
1987
  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;
1988
+ const inner = isRecord3(prop.text) ? prop.text : void 0;
1989
+ const innerProp = inner && isRecord3(inner.property) ? inner.property : void 0;
1907
1990
  const innerContent = innerProp && typeof innerProp.content === "string" ? innerProp.content : "";
1908
1991
  if (color) return `<text_tag color='${color}'>${innerContent}</text_tag>`;
1909
1992
  return `<text_tag>${innerContent}</text_tag>`;
@@ -1912,11 +1995,11 @@ function childToMarkdown(child, ctx) {
1912
1995
  const lang = typeof prop.language === "string" ? prop.language : "";
1913
1996
  const blocks = Array.isArray(prop.contents) ? prop.contents : [];
1914
1997
  const lines = blocks.map((blk) => {
1915
- if (!isRecord2(blk)) return "";
1998
+ if (!isRecord3(blk)) return "";
1916
1999
  const inner = Array.isArray(blk.contents) ? blk.contents : [];
1917
2000
  let line = "";
1918
2001
  for (const seg of inner) {
1919
- if (isRecord2(seg) && typeof seg.content === "string") line += seg.content;
2002
+ if (isRecord3(seg) && typeof seg.content === "string") line += seg.content;
1920
2003
  }
1921
2004
  return line;
1922
2005
  });
@@ -1932,14 +2015,14 @@ ${body}
1932
2015
  const lines = [];
1933
2016
  const levelCounters = [];
1934
2017
  for (const item of items) {
1935
- if (!isRecord2(item)) continue;
2018
+ if (!isRecord3(item)) continue;
1936
2019
  const level = typeof item.level === "number" ? item.level : 0;
1937
2020
  const type = typeof item.type === "string" ? item.type : "ul";
1938
2021
  const indent = " ".repeat(level);
1939
2022
  const inner = Array.isArray(item.elements) ? item.elements : [];
1940
2023
  let text = "";
1941
2024
  for (const seg of inner) {
1942
- if (!isRecord2(seg)) continue;
2025
+ if (!isRecord3(seg)) continue;
1943
2026
  text += childToMarkdown(seg, ctx);
1944
2027
  }
1945
2028
  if (type === "ol") {
@@ -1968,7 +2051,7 @@ ${lines.join("\n")}
1968
2051
  const inner = Array.isArray(prop.elements) ? prop.elements : [];
1969
2052
  let body = "";
1970
2053
  for (const seg of inner) {
1971
- if (isRecord2(seg)) body += childToMarkdown(seg, ctx);
2054
+ if (isRecord3(seg)) body += childToMarkdown(seg, ctx);
1972
2055
  }
1973
2056
  return `
1974
2057
 
@@ -1984,18 +2067,18 @@ ${"#".repeat(level)} ${body}
1984
2067
  const rows = Array.isArray(prop.rows) ? prop.rows : [];
1985
2068
  if (columns.length === 0) return "";
1986
2069
  const headers = columns.map(
1987
- (col) => isRecord2(col) && typeof col.displayName === "string" ? col.displayName : ""
2070
+ (col) => isRecord3(col) && typeof col.displayName === "string" ? col.displayName : ""
1988
2071
  );
1989
2072
  const headerLine = `| ${headers.join(" | ")} |`;
1990
2073
  const separator = `| ${columns.map(() => "--------").join(" | ")} |`;
1991
2074
  const bodyLines = rows.map((row) => {
1992
- if (!isRecord2(row)) return `| ${columns.map(() => "").join(" | ")} |`;
2075
+ if (!isRecord3(row)) return `| ${columns.map(() => "").join(" | ")} |`;
1993
2076
  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;
2077
+ const name = isRecord3(col) && typeof col.name === "string" ? col.name : "";
2078
+ const cell = isRecord3(row[name]) ? row[name] : void 0;
2079
+ const data = cell && isRecord3(cell.data) ? cell.data : void 0;
1997
2080
  if (!data || data.tag !== "markdown") return "";
1998
- const cellProp = isRecord2(data.property) ? data.property : {};
2081
+ const cellProp = isRecord3(data.property) ? data.property : {};
1999
2082
  const inner = Array.isArray(cellProp.elements) ? cellProp.elements : [];
2000
2083
  const { content: text } = renderChildren(inner, ctx);
2001
2084
  return text.replace(/\|/g, "\\|").replace(/\n/g, " ");
@@ -2014,7 +2097,7 @@ ${bodyLines.join("\n")}
2014
2097
  const inner = Array.isArray(prop.elements) ? prop.elements : [];
2015
2098
  let body = "";
2016
2099
  for (const seg of inner) {
2017
- if (isRecord2(seg)) body += childToMarkdown(seg, ctx);
2100
+ if (isRecord3(seg)) body += childToMarkdown(seg, ctx);
2018
2101
  }
2019
2102
  return `
2020
2103
 
@@ -2029,14 +2112,14 @@ ${bodyLines.join("\n")}
2029
2112
  function convertGeneric(value, ctx) {
2030
2113
  if (Array.isArray(value)) {
2031
2114
  return value.map((item) => {
2032
- if (isRecord2(item) && typeof item.tag === "string" && isRecord2(item.property)) {
2115
+ if (isRecord3(item) && typeof item.tag === "string" && isRecord3(item.property)) {
2033
2116
  return unwrap(item, ctx);
2034
2117
  }
2035
2118
  return convertGeneric(item, ctx);
2036
2119
  });
2037
2120
  }
2038
- if (isRecord2(value)) {
2039
- if (typeof value.tag === "string" && isRecord2(value.property)) {
2121
+ if (isRecord3(value)) {
2122
+ if (typeof value.tag === "string" && isRecord3(value.property)) {
2040
2123
  return unwrap(value, ctx);
2041
2124
  }
2042
2125
  if (hasSide(value)) {
@@ -2053,7 +2136,7 @@ function convertGeneric(value, ctx) {
2053
2136
  }
2054
2137
  return value;
2055
2138
  }
2056
- function isRecord2(v) {
2139
+ function isRecord3(v) {
2057
2140
  return typeof v === "object" && v !== null && !Array.isArray(v);
2058
2141
  }
2059
2142
  function resolveAttachmentImgKey(rawValue, ctx) {
@@ -2069,7 +2152,7 @@ function normalizeVideoCover(rawValue, ctx) {
2069
2152
  const imgKey2 = resolveAttachmentImgKey(rawValue, ctx);
2070
2153
  return imgKey2 ? { img_key: imgKey2 } : void 0;
2071
2154
  }
2072
- if (!isRecord2(rawValue)) return void 0;
2155
+ if (!isRecord3(rawValue)) return void 0;
2073
2156
  if (typeof rawValue.img_key === "string" && rawValue.img_key) {
2074
2157
  return { img_key: rawValue.img_key };
2075
2158
  }
@@ -2078,17 +2161,17 @@ function normalizeVideoCover(rawValue, ctx) {
2078
2161
  return imgKey ? { img_key: imgKey } : void 0;
2079
2162
  }
2080
2163
  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);
2164
+ 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
2165
  }
2083
2166
  function formatBox(v) {
2084
2167
  return `${pixelOf(v.top)}px ${pixelOf(v.right)}px ${pixelOf(v.bottom)}px ${pixelOf(v.left)}px`;
2085
2168
  }
2086
2169
  function isPixelScalar(v) {
2087
- if (!isRecord2(v)) return false;
2170
+ if (!isRecord3(v)) return false;
2088
2171
  return typeof v.type === "string" && v.type.includes("pixels") && typeof v.value === "number";
2089
2172
  }
2090
2173
  function pixelOf(side) {
2091
- if (!isRecord2(side)) return 0;
2174
+ if (!isRecord3(side)) return 0;
2092
2175
  const v = side.value;
2093
2176
  if (typeof v === "number") return v;
2094
2177
  if (typeof v === "string") {
@@ -2109,8 +2192,8 @@ function rawToDsl(raw) {
2109
2192
  return raw;
2110
2193
  }
2111
2194
  }
2112
- if (!isRecord2(raw)) return raw;
2113
- if (typeof raw.json_card === "string" || isRecord2(raw.json_card)) {
2195
+ if (!isRecord3(raw)) return raw;
2196
+ if (typeof raw.json_card === "string" || isRecord3(raw.json_card)) {
2114
2197
  let inner = raw.json_card;
2115
2198
  if (typeof inner === "string") {
2116
2199
  try {
@@ -2119,16 +2202,16 @@ function rawToDsl(raw) {
2119
2202
  return raw;
2120
2203
  }
2121
2204
  }
2122
- const attachment = isRecord2(raw.json_attachment) ? raw.json_attachment : {};
2205
+ const attachment = isRecord3(raw.json_attachment) ? raw.json_attachment : {};
2123
2206
  const ctx = makeCtx({
2124
- images: isRecord2(attachment.images) ? attachment.images : {},
2125
- atUsers: isRecord2(attachment.at_users) ? attachment.at_users : {}
2207
+ images: isRecord3(attachment.images) ? attachment.images : {},
2208
+ atUsers: isRecord3(attachment.at_users) ? attachment.at_users : {}
2126
2209
  });
2127
2210
  return convertRoot(inner, ctx);
2128
2211
  }
2129
- if (isRecord2(raw.card)) {
2212
+ if (isRecord3(raw.card)) {
2130
2213
  const card = raw.card;
2131
- if (typeof card.json_card === "string" || isRecord2(card.json_card)) {
2214
+ if (typeof card.json_card === "string" || isRecord3(card.json_card)) {
2132
2215
  return rawToDsl(card);
2133
2216
  }
2134
2217
  return convertRoot(card, makeCtx());