@open-feishu-card/adapter 0.3.15 → 0.3.17

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
@@ -768,6 +768,14 @@ function convertNode(node, colors) {
768
768
  if (isRecord2(node) && typeof node.tag === "string") return convertEl(node, colors);
769
769
  return node;
770
770
  }
771
+ var PUBLIC_ELEMENT_ID_RE = /^[A-Za-z][A-Za-z0-9_]{0,19}$/;
772
+ function withRawElementId(el, raw) {
773
+ const eid = typeof el.element_id === "string" ? el.element_id : void 0;
774
+ if (eid && PUBLIC_ELEMENT_ID_RE.test(eid)) {
775
+ raw.id = eid;
776
+ }
777
+ return raw;
778
+ }
771
779
  function convertEl(el, colors) {
772
780
  const tag = String(el.tag);
773
781
  if (tag === "person") {
@@ -776,13 +784,16 @@ function convertEl(el, colors) {
776
784
  property.pillShaped = true;
777
785
  delete property.style;
778
786
  }
779
- return { tag: "person_v1", property };
787
+ return withRawElementId(el, { tag: "person_v1", property });
780
788
  }
781
789
  if (tag === "avatar") {
782
- return { tag: "avatar", property: buildProperty(el, "avatar", colors) };
790
+ return withRawElementId(el, { tag: "avatar", property: buildProperty(el, "avatar", colors) });
783
791
  }
784
792
  if (tag === "picker_date") {
785
- return { tag: "date_picker", property: buildProperty(el, "date_picker", colors) };
793
+ return withRawElementId(el, {
794
+ tag: "date_picker",
795
+ property: buildProperty(el, "date_picker", colors)
796
+ });
786
797
  }
787
798
  if (tag === "markdown" || tag === "lark_md") {
788
799
  const property = buildProperty(el, "markdown", colors);
@@ -794,10 +805,10 @@ function convertEl(el, colors) {
794
805
  }
795
806
  delete property.content;
796
807
  delete property.font_color;
797
- return { tag: "markdown", property };
808
+ return withRawElementId(el, { tag: "markdown", property });
798
809
  }
799
810
  if (tag === "table") {
800
- return { tag, property: convertTableProperty(el, colors) };
811
+ return withRawElementId(el, { tag, property: convertTableProperty(el, colors) });
801
812
  }
802
813
  if (tag === "audio" || tag === "video") {
803
814
  const property = buildProperty(el, tag, colors);
@@ -816,9 +827,9 @@ function convertEl(el, colors) {
816
827
  delete property.image_key;
817
828
  delete property.cover_image_key;
818
829
  }
819
- return { tag, property };
830
+ return withRawElementId(el, { tag, property });
820
831
  }
821
- return { tag, property: buildProperty(el, tag, colors) };
832
+ return withRawElementId(el, { tag, property: buildProperty(el, tag, colors) });
822
833
  }
823
834
  function convertTableProperty(el, colors) {
824
835
  const property = buildProperty(el, "table", colors);
@@ -857,7 +868,14 @@ function convertTableProperty(el, colors) {
857
868
  function buildProperty(el, tag, colors) {
858
869
  const property = {};
859
870
  for (const [k, v] of Object.entries(el)) {
860
- if (k === "tag" || k === "id") continue;
871
+ if (k === "tag" || k === "id" || k === "element_id") continue;
872
+ if ((tag === "column_set" || tag === "column") && k === "action" && isRecord2(v)) {
873
+ const multi = isRecord2(v.multi_url) ? v.multi_url : void 0;
874
+ if (multi && (typeof multi.url === "string" || typeof multi.default_url === "string")) {
875
+ property.actions = [multiUrlToOpenUrlAction(multi)];
876
+ }
877
+ continue;
878
+ }
861
879
  if ((k === "background_style" || k === "backgroundStyle") && (tag === "column" || tag === "column_set" || tag === "interactive_container")) {
862
880
  const renamed = renameKey(k);
863
881
  property[renamed] = v;
@@ -999,6 +1017,10 @@ function behaviorsToActions(behaviors) {
999
1017
  for (const b of behaviors) {
1000
1018
  if (!isRecord2(b)) continue;
1001
1019
  const type = typeof b.type === "string" ? b.type : "open_url";
1020
+ if (type === "callback") {
1021
+ out.push({ type: "callback", action: { value: isRecord2(b.value) ? b.value : {} } });
1022
+ continue;
1023
+ }
1002
1024
  const action = { url: normalizeUrl(b.default_url) };
1003
1025
  if (typeof b.pc_url === "string" && b.pc_url) action.pcURL = b.pc_url;
1004
1026
  if (typeof b.ios_url === "string" && b.ios_url) action.iosURL = b.ios_url;
@@ -1007,6 +1029,16 @@ function behaviorsToActions(behaviors) {
1007
1029
  }
1008
1030
  return out;
1009
1031
  }
1032
+ function multiUrlToOpenUrlAction(multi) {
1033
+ const url = typeof multi.url === "string" ? multi.url : typeof multi.default_url === "string" ? multi.default_url : "";
1034
+ const action = { url };
1035
+ if (typeof multi.pc_url === "string" && multi.pc_url) action.pcURL = multi.pc_url;
1036
+ if (typeof multi.ios_url === "string" && multi.ios_url) action.iosURL = multi.ios_url;
1037
+ if (typeof multi.android_url === "string" && multi.android_url) {
1038
+ action.androidURL = multi.android_url;
1039
+ }
1040
+ return { type: "open_url", action };
1041
+ }
1010
1042
  function normalizeUrl(v) {
1011
1043
  if (typeof v === "string") return v;
1012
1044
  if (isRecord2(v)) return v;
@@ -1492,7 +1524,23 @@ function convertBody2(node, ctx) {
1492
1524
  const property = isRecord3(node.property) ? node.property : node;
1493
1525
  return convertProperty(property, "body", ctx);
1494
1526
  }
1527
+ var PUBLIC_ELEMENT_ID_RE2 = /^[A-Za-z][A-Za-z0-9_]{0,19}$/;
1528
+ function isPublicElementId(id) {
1529
+ return PUBLIC_ELEMENT_ID_RE2.test(id);
1530
+ }
1531
+ function attachPublicElementId(node, result) {
1532
+ if (!isRecord3(result)) return result;
1533
+ if (typeof result.element_id === "string" && isPublicElementId(result.element_id)) {
1534
+ return result;
1535
+ }
1536
+ const rawId = typeof node.id === "string" ? node.id : typeof node.element_id === "string" ? node.element_id : void 0;
1537
+ if (!rawId || !isPublicElementId(rawId)) return result;
1538
+ return { ...result, element_id: rawId };
1539
+ }
1495
1540
  function unwrap(node, ctx) {
1541
+ return attachPublicElementId(node, unwrapInner(node, ctx));
1542
+ }
1543
+ function unwrapInner(node, ctx) {
1496
1544
  const tag = typeof node.tag === "string" ? node.tag : void 0;
1497
1545
  const property = isRecord3(node.property) ? node.property : {};
1498
1546
  if (tag === "markdown") return rebuildMarkdown(property, ctx);
@@ -1879,23 +1927,26 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1879
1927
  }
1880
1928
  if (ownerTag === "button" && key === "action_type") return DROP;
1881
1929
  if (ownerTag === "button" && key === "actions" && Array.isArray(rawValue)) {
1882
- const openUrls = [];
1930
+ const behaviors = [];
1883
1931
  for (const a of rawValue) {
1884
1932
  if (!isRecord3(a)) continue;
1885
1933
  const inner = isRecord3(a.action) ? a.action : {};
1886
1934
  const t = typeof a.type === "string" ? a.type : void 0;
1935
+ if (t === "callback") {
1936
+ behaviors.push({ type: "callback", value: isRecord3(inner.value) ? inner.value : {} });
1937
+ continue;
1938
+ }
1887
1939
  if (t !== "open_url") continue;
1888
1940
  const fields = projectOpenUrlFields(inner);
1889
- if (fields) openUrls.push(fields);
1941
+ if (fields) behaviors.push({ type: "open_url", ...fields });
1890
1942
  }
1891
- if (openUrls.length === 0) return DROP;
1892
- if (siblings.buttonActionType === "link") {
1893
- return ["multi_url", openUrlFieldsToMultiUrl(openUrls[0])];
1943
+ if (behaviors.length === 0) return DROP;
1944
+ if (siblings.buttonActionType === "link" && behaviors.length === 1 && behaviors[0]?.type === "open_url") {
1945
+ const only = behaviors[0];
1946
+ const { type: _type, ...fields } = only;
1947
+ return ["multi_url", openUrlFieldsToMultiUrl(fields)];
1894
1948
  }
1895
- return [
1896
- "behaviors",
1897
- openUrls.map((fields) => ({ type: "open_url", ...fields }))
1898
- ];
1949
+ return ["behaviors", behaviors];
1899
1950
  }
1900
1951
  if (ownerTag === "interactive_container" && key === "actions" && Array.isArray(rawValue)) {
1901
1952
  const behaviors = rawValue.map((a) => {
@@ -1914,6 +1965,17 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1914
1965
  if (behaviors.length === 0) return DROP;
1915
1966
  return ["behaviors", behaviors];
1916
1967
  }
1968
+ if ((ownerTag === "column_set" || ownerTag === "column") && key === "actions" && Array.isArray(rawValue)) {
1969
+ for (const a of rawValue) {
1970
+ if (!isRecord3(a)) continue;
1971
+ if (a.type !== "open_url") continue;
1972
+ const inner = isRecord3(a.action) ? a.action : {};
1973
+ const fields = projectOpenUrlFields(inner);
1974
+ if (!fields) continue;
1975
+ return ["action", { multi_url: openUrlFieldsToMultiUrl(fields) }];
1976
+ }
1977
+ return DROP;
1978
+ }
1917
1979
  if (key === "border" && isRecord3(rawValue)) {
1918
1980
  const b = rawValue;
1919
1981
  const out = {};
package/dist/index.js CHANGED
@@ -766,6 +766,14 @@ function convertNode(node, colors) {
766
766
  if (isRecord2(node) && typeof node.tag === "string") return convertEl(node, colors);
767
767
  return node;
768
768
  }
769
+ var PUBLIC_ELEMENT_ID_RE = /^[A-Za-z][A-Za-z0-9_]{0,19}$/;
770
+ function withRawElementId(el, raw) {
771
+ const eid = typeof el.element_id === "string" ? el.element_id : void 0;
772
+ if (eid && PUBLIC_ELEMENT_ID_RE.test(eid)) {
773
+ raw.id = eid;
774
+ }
775
+ return raw;
776
+ }
769
777
  function convertEl(el, colors) {
770
778
  const tag = String(el.tag);
771
779
  if (tag === "person") {
@@ -774,13 +782,16 @@ function convertEl(el, colors) {
774
782
  property.pillShaped = true;
775
783
  delete property.style;
776
784
  }
777
- return { tag: "person_v1", property };
785
+ return withRawElementId(el, { tag: "person_v1", property });
778
786
  }
779
787
  if (tag === "avatar") {
780
- return { tag: "avatar", property: buildProperty(el, "avatar", colors) };
788
+ return withRawElementId(el, { tag: "avatar", property: buildProperty(el, "avatar", colors) });
781
789
  }
782
790
  if (tag === "picker_date") {
783
- return { tag: "date_picker", property: buildProperty(el, "date_picker", colors) };
791
+ return withRawElementId(el, {
792
+ tag: "date_picker",
793
+ property: buildProperty(el, "date_picker", colors)
794
+ });
784
795
  }
785
796
  if (tag === "markdown" || tag === "lark_md") {
786
797
  const property = buildProperty(el, "markdown", colors);
@@ -792,10 +803,10 @@ function convertEl(el, colors) {
792
803
  }
793
804
  delete property.content;
794
805
  delete property.font_color;
795
- return { tag: "markdown", property };
806
+ return withRawElementId(el, { tag: "markdown", property });
796
807
  }
797
808
  if (tag === "table") {
798
- return { tag, property: convertTableProperty(el, colors) };
809
+ return withRawElementId(el, { tag, property: convertTableProperty(el, colors) });
799
810
  }
800
811
  if (tag === "audio" || tag === "video") {
801
812
  const property = buildProperty(el, tag, colors);
@@ -814,9 +825,9 @@ function convertEl(el, colors) {
814
825
  delete property.image_key;
815
826
  delete property.cover_image_key;
816
827
  }
817
- return { tag, property };
828
+ return withRawElementId(el, { tag, property });
818
829
  }
819
- return { tag, property: buildProperty(el, tag, colors) };
830
+ return withRawElementId(el, { tag, property: buildProperty(el, tag, colors) });
820
831
  }
821
832
  function convertTableProperty(el, colors) {
822
833
  const property = buildProperty(el, "table", colors);
@@ -855,7 +866,14 @@ function convertTableProperty(el, colors) {
855
866
  function buildProperty(el, tag, colors) {
856
867
  const property = {};
857
868
  for (const [k, v] of Object.entries(el)) {
858
- if (k === "tag" || k === "id") continue;
869
+ if (k === "tag" || k === "id" || k === "element_id") continue;
870
+ if ((tag === "column_set" || tag === "column") && k === "action" && isRecord2(v)) {
871
+ const multi = isRecord2(v.multi_url) ? v.multi_url : void 0;
872
+ if (multi && (typeof multi.url === "string" || typeof multi.default_url === "string")) {
873
+ property.actions = [multiUrlToOpenUrlAction(multi)];
874
+ }
875
+ continue;
876
+ }
859
877
  if ((k === "background_style" || k === "backgroundStyle") && (tag === "column" || tag === "column_set" || tag === "interactive_container")) {
860
878
  const renamed = renameKey(k);
861
879
  property[renamed] = v;
@@ -997,6 +1015,10 @@ function behaviorsToActions(behaviors) {
997
1015
  for (const b of behaviors) {
998
1016
  if (!isRecord2(b)) continue;
999
1017
  const type = typeof b.type === "string" ? b.type : "open_url";
1018
+ if (type === "callback") {
1019
+ out.push({ type: "callback", action: { value: isRecord2(b.value) ? b.value : {} } });
1020
+ continue;
1021
+ }
1000
1022
  const action = { url: normalizeUrl(b.default_url) };
1001
1023
  if (typeof b.pc_url === "string" && b.pc_url) action.pcURL = b.pc_url;
1002
1024
  if (typeof b.ios_url === "string" && b.ios_url) action.iosURL = b.ios_url;
@@ -1005,6 +1027,16 @@ function behaviorsToActions(behaviors) {
1005
1027
  }
1006
1028
  return out;
1007
1029
  }
1030
+ function multiUrlToOpenUrlAction(multi) {
1031
+ const url = typeof multi.url === "string" ? multi.url : typeof multi.default_url === "string" ? multi.default_url : "";
1032
+ const action = { url };
1033
+ if (typeof multi.pc_url === "string" && multi.pc_url) action.pcURL = multi.pc_url;
1034
+ if (typeof multi.ios_url === "string" && multi.ios_url) action.iosURL = multi.ios_url;
1035
+ if (typeof multi.android_url === "string" && multi.android_url) {
1036
+ action.androidURL = multi.android_url;
1037
+ }
1038
+ return { type: "open_url", action };
1039
+ }
1008
1040
  function normalizeUrl(v) {
1009
1041
  if (typeof v === "string") return v;
1010
1042
  if (isRecord2(v)) return v;
@@ -1490,7 +1522,23 @@ function convertBody2(node, ctx) {
1490
1522
  const property = isRecord3(node.property) ? node.property : node;
1491
1523
  return convertProperty(property, "body", ctx);
1492
1524
  }
1525
+ var PUBLIC_ELEMENT_ID_RE2 = /^[A-Za-z][A-Za-z0-9_]{0,19}$/;
1526
+ function isPublicElementId(id) {
1527
+ return PUBLIC_ELEMENT_ID_RE2.test(id);
1528
+ }
1529
+ function attachPublicElementId(node, result) {
1530
+ if (!isRecord3(result)) return result;
1531
+ if (typeof result.element_id === "string" && isPublicElementId(result.element_id)) {
1532
+ return result;
1533
+ }
1534
+ const rawId = typeof node.id === "string" ? node.id : typeof node.element_id === "string" ? node.element_id : void 0;
1535
+ if (!rawId || !isPublicElementId(rawId)) return result;
1536
+ return { ...result, element_id: rawId };
1537
+ }
1493
1538
  function unwrap(node, ctx) {
1539
+ return attachPublicElementId(node, unwrapInner(node, ctx));
1540
+ }
1541
+ function unwrapInner(node, ctx) {
1494
1542
  const tag = typeof node.tag === "string" ? node.tag : void 0;
1495
1543
  const property = isRecord3(node.property) ? node.property : {};
1496
1544
  if (tag === "markdown") return rebuildMarkdown(property, ctx);
@@ -1877,23 +1925,26 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1877
1925
  }
1878
1926
  if (ownerTag === "button" && key === "action_type") return DROP;
1879
1927
  if (ownerTag === "button" && key === "actions" && Array.isArray(rawValue)) {
1880
- const openUrls = [];
1928
+ const behaviors = [];
1881
1929
  for (const a of rawValue) {
1882
1930
  if (!isRecord3(a)) continue;
1883
1931
  const inner = isRecord3(a.action) ? a.action : {};
1884
1932
  const t = typeof a.type === "string" ? a.type : void 0;
1933
+ if (t === "callback") {
1934
+ behaviors.push({ type: "callback", value: isRecord3(inner.value) ? inner.value : {} });
1935
+ continue;
1936
+ }
1885
1937
  if (t !== "open_url") continue;
1886
1938
  const fields = projectOpenUrlFields(inner);
1887
- if (fields) openUrls.push(fields);
1939
+ if (fields) behaviors.push({ type: "open_url", ...fields });
1888
1940
  }
1889
- if (openUrls.length === 0) return DROP;
1890
- if (siblings.buttonActionType === "link") {
1891
- return ["multi_url", openUrlFieldsToMultiUrl(openUrls[0])];
1941
+ if (behaviors.length === 0) return DROP;
1942
+ if (siblings.buttonActionType === "link" && behaviors.length === 1 && behaviors[0]?.type === "open_url") {
1943
+ const only = behaviors[0];
1944
+ const { type: _type, ...fields } = only;
1945
+ return ["multi_url", openUrlFieldsToMultiUrl(fields)];
1892
1946
  }
1893
- return [
1894
- "behaviors",
1895
- openUrls.map((fields) => ({ type: "open_url", ...fields }))
1896
- ];
1947
+ return ["behaviors", behaviors];
1897
1948
  }
1898
1949
  if (ownerTag === "interactive_container" && key === "actions" && Array.isArray(rawValue)) {
1899
1950
  const behaviors = rawValue.map((a) => {
@@ -1912,6 +1963,17 @@ function convertField(rawKey, rawValue, ownerTag, ctx, siblings = {}) {
1912
1963
  if (behaviors.length === 0) return DROP;
1913
1964
  return ["behaviors", behaviors];
1914
1965
  }
1966
+ if ((ownerTag === "column_set" || ownerTag === "column") && key === "actions" && Array.isArray(rawValue)) {
1967
+ for (const a of rawValue) {
1968
+ if (!isRecord3(a)) continue;
1969
+ if (a.type !== "open_url") continue;
1970
+ const inner = isRecord3(a.action) ? a.action : {};
1971
+ const fields = projectOpenUrlFields(inner);
1972
+ if (!fields) continue;
1973
+ return ["action", { multi_url: openUrlFieldsToMultiUrl(fields) }];
1974
+ }
1975
+ return DROP;
1976
+ }
1915
1977
  if (key === "border" && isRecord3(rawValue)) {
1916
1978
  const b = rawValue;
1917
1979
  const out = {};
@@ -1 +1 @@
1
- {"version":3,"file":"raw-to-dsl.d.ts","sourceRoot":"","sources":["../src/raw-to-dsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAwBH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAIzD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAcvD;AA8rDD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CA8C9C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGnF"}
1
+ {"version":3,"file":"raw-to-dsl.d.ts","sourceRoot":"","sources":["../src/raw-to-dsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAwBH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAIzD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAcvD;AA2vDD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CA8C9C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGnF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-feishu-card/adapter",
3
- "version": "0.3.15",
3
+ "version": "0.3.17",
4
4
  "description": "公开 DSL 与飞书内部 RAW JSON 的双向适配器;raw→DSL 对齐 feishu-raw-card-to-dsl",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -22,7 +22,7 @@
22
22
  "tsx": "^4.19.3",
23
23
  "typescript": "^7.0.2",
24
24
  "vitest": "^2.1.9",
25
- "@open-feishu-card/schema": "0.1.5"
25
+ "@open-feishu-card/schema": "0.1.6"
26
26
  },
27
27
  "license": "MIT",
28
28
  "publishConfig": {