flex-html-render 1.0.1 → 1.0.3

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/README.md CHANGED
@@ -41,6 +41,12 @@ console.log(JSON.stringify(flexMessage, null, 2));
41
41
  ### `convertHtmlToFlexMessage(htmlString)`
42
42
  - **參數**:`htmlString` (string) - Flex Message 對應的 HTML 字串
43
43
  - **回傳**:Flex Message JSON 物件陣列
44
+ - **說明**:此函數將 Flex Message HTML 字串轉為 JSON 結構,可用於編輯或顯示目的
45
+
46
+ ### `convertJsonToHtml(json)`
47
+ - **參數**:`json` (object) - Flex Message JSON 物件
48
+ - **回傳**:對應的格式化 HTML 字串
49
+ - **說明**:此函數將 Flex Message JSON 結構轉為 HTML 字串,可用於編輯或顯示目的
44
50
 
45
51
 
46
52
  ## 支援的 Flex Message 元素
@@ -82,6 +88,7 @@ console.log(JSON.stringify(flexMessage, null, 2));
82
88
 
83
89
  ### 便捷標籤 (Convenience Tags)
84
90
  這些是對常用設定的簡寫標籤:
91
+ - `<div>`, `<article>` - 等同於 `<box>`
85
92
  - `<baseline>` - 等同於 `<box layout="baseline">`
86
93
  - `<row>` - 等同於 `<box layout="horizontal">`
87
94
  - `<vertical>` - 等同於 `<box layout="vertical">`
@@ -1 +1,6 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const f=require("htmlparser2"),N={ELEMENT:"element",TEXT:"text"},e={CAROUSEL:"carousel",BUBBLE:"bubble",HEADER:"header",HERO:"hero",BODY:"body",FOOTER:"footer",BOX:"box",TEXT:"text",SPAN:"span",IMAGE:"image",VIDEO:"video",ICON:"icon",SEPARATOR:"separator",BUTTON:"button",SPACE:"space",STRONG:"strong",BASELINE:"baseline",ROW:"row",VERTICAL:"vertical",ACTION:"action",BACKGROUND:"background"},b=[e.HEADER,e.HERO,e.BODY,e.FOOTER],p=[e.BOX,e.VERTICAL,e.ROW,e.BASELINE];function E(t){const r=Number(t);return isNaN(r)?t:r}function O(t){return t==="true"?!0:t==="false"?!1:t}function T(t){return[E,O].reduce((a,n)=>n(a),t)}function A(t){const r={type:"root",children:[]},a=[r],n=new f.Parser({onopentag(s,u){const g={type:N.ELEMENT,tagName:s,attributes:Object.fromEntries(Object.entries(u).map(([h,m])=>[h,T(m)])),children:[]};a[a.length-1].children.push(g),a.push(g)},ontext(s){s.trim()&&a[a.length-1].children.push({type:N.TEXT,content:s.replace(/\n/g,"").trim()})},onclosetag(){a.pop()},onerror(s){console.error("解析錯誤:",s)}},{xmlMode:!0,lowerCaseTags:!1,lowerCaseAttributeNames:!1});return n.write(t),n.end(),r.children}const c=t=>{throw Error(`[Flex Html Render]: ${t}`)},l={carousel:t=>({type:"carousel",contents:t}),bubble:(t={})=>({type:"bubble",...t}),box:(t,r={})=>({type:"box",contents:t,...r}),text:(t,r={})=>({type:"text",...typeof t=="string"?{text:t}:{contents:t},...r}),span:(t,r={})=>({type:"span",text:t,...r}),image:(t={})=>({type:"image",...t}),video:(t={})=>({type:"video",...t}),icon:(t={})=>({type:"icon",...t}),button:(t={})=>({type:"button",...t}),separator:(t={color:"#E0E3EA"})=>({type:"separator",...t}),uri:(t={})=>({type:"uri",altUri:t.altUri?{desktop:t.altUri}:void 0,...t})};function B(t){if(t.tagName!==e.BACKGROUND&&t.children&&t.children.length>0){const r=t.children.filter(a=>a.tagName===e.BACKGROUND);return r.length>1&&c("A box node can only allowed with one background node inside"),t.children=t.children.filter(a=>a.tagName!==e.BACKGROUND),r[0]}return null}function y(t){if(t.tagName!==e.ACTION&&t.children&&t.children.length>0){const r=t.children.filter(a=>a.tagName===e.ACTION);return r.length>1&&c("A node can only allowed with one action node inside"),t.children=t.children.filter(a=>a.tagName!==e.ACTION),r[0]}return null}function i(t){t.attributes=t.attributes||{};const r=y(t);r&&(t.attributes.action=i(r));const a=B(t);if(a&&p.includes(t.tagName)&&(t.attributes.background=i(a)),t.type===N.TEXT)return l.span(t.content,t.attributes);if(t.tagName===e.BUBBLE){const n=t.children.find(o=>o.tagName===e.HEADER),s=t.children.find(o=>o.tagName===e.HERO),u=t.children.find(o=>o.tagName===e.BODY),g=t.children.find(o=>o.tagName===e.FOOTER);return l.bubble({...t.attributes,header:n?i(n):void 0,hero:s?i(s):void 0,body:u?i(u):void 0,footer:g?i(g):void 0})}if(t.tagName===e.CAROUSEL)return t.children.some(n=>n.tagName!==e.BUBBLE)&&c("Carousel can only have Bubble as children"),t.children.length>12&&c("Carousel can have maximum 12 bubbles"),l.carousel(t.children.map(i));if(b.includes(t.tagName))return t.children.length!==1&&c(`${t.tagName} should have exactly one child node`),i(t.children[0]);if(t.tagName===e.BUTTON)return t.attributes.action||c("Button component should contain an action node"),l.button(t.attributes);if(t.tagName===e.SPAN){t.children.length>1&&c("Span component can only have one text child");const n=t.children[0];if(n&&n.type===N.TEXT)return l.span(n.content,t.attributes);c("Span component only allowed text child")}if(t.tagName===e.TEXT)return l.text(t.children.map(i),t.attributes);if(t.tagName===e.SEPARATOR)return l.separator(t.attributes);if(t.tagName===e.IMAGE)return l.image(t.attributes);if(t.tagName===e.VIDEO)return t.children.length!==1&&c("Video component should only has one Box or Image as altContent"),[e.BOX,e.IMAGE].includes(t.children[0]?.tagName)||c("Video component should only has Box or Image child as altContent"),t.attributes.altContent=i(t.children[0]),l.video(t.attributes);if(t.tagName===e.ICON)return l.icon(t.attributes);if(t.tagName===e.BOX)return l.box(t.children.map(i),t.attributes);if(t.tagName===e.SPACE)return l.span(" ".repeat(t.attributes.size||1));if(t.tagName===e.STRONG)return t.tagName=e.TEXT,t.attributes.weight="bold",i(t);if(t.tagName===e.BASELINE)return t.tagName=e.BOX,t.attributes.layout="baseline",i(t);if(t.tagName===e.ROW)return t.tagName=e.BOX,t.attributes.layout="horizontal",i(t);if(t.tagName===e.VERTICAL)return t.tagName=e.BOX,t.attributes.layout="vertical",i(t);if(t.tagName===e.ACTION&&t.attributes.type==="uri")return l.uri(t.attributes);if(t.tagName===e.BACKGROUND)return t.attributes}function R(t){try{return A(t).map(i)}catch(r){console.error("Error converting HTML to Flex Message:",r)}}exports.default=R;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const J=require("htmlparser2"),E={ELEMENT:"element",TEXT:"text"},e={CAROUSEL:"carousel",BUBBLE:"bubble",HEADER:"header",HERO:"hero",BODY:"body",FOOTER:"footer",BOX:"box",TEXT:"text",SPAN:"span",IMAGE:"image",VIDEO:"video",ICON:"icon",SEPARATOR:"separator",BUTTON:"button",FILLER:"filler",SPACE:"space",STRONG:"strong",BASELINE:"baseline",ROW:"row",VERTICAL:"vertical",DIV:"div",ARTICLE:"article",ACTION:"action",BACKGROUND:"background"},Y=[e.HEADER,e.HERO,e.BODY,e.FOOTER],W=[e.BOX,e.VERTICAL,e.ROW,e.BASELINE,e.DIV,e.ARTICLE],q=[e.TEXT,e.STRONG];function z(t){const r=Number(t);return isNaN(r)?t:r}function _(t){return t==="true"?!0:t==="false"?!1:t}function Q(t){return[z,_].reduce((n,s)=>s(n),t)}function Z(t){const r={type:"root",children:[]},n=[r],s=new J.Parser({onopentag(l,i){const a={type:E.ELEMENT,tagName:l,attributes:Object.fromEntries(Object.entries(i).map(([p,f])=>[p,Q(f)])),children:[]};n[n.length-1].children.push(a),n.push(a)},ontext(l){const i=n[n.length-1];if(i.tagName==="span"){i.children.push({type:E.TEXT,content:l});return}l.trim()&&i.children.push({type:E.TEXT,content:l.replace(/\n/g,"").trim()})},onclosetag(){n.pop()},onerror(l){console.error("解析錯誤:",l)}},{xmlMode:!0,lowerCaseTags:!1,lowerCaseAttributeNames:!1});return s.write(t),s.end(),r.children}const h=t=>{throw Error(`[Flex Html Render]: ${t}`)},c={carousel:t=>({type:"carousel",contents:t}),bubble:(t={})=>({type:"bubble",...t}),box:(t,r={})=>({type:"box",contents:t,...r}),text:(t,r={})=>({type:"text",...typeof t=="string"?{text:t}:{contents:t},...r}),span:(t,r={})=>({type:"span",text:t,...r}),image:(t={})=>({type:"image",...t}),video:(t={})=>({type:"video",...t}),icon:(t={})=>({type:"icon",...t}),button:(t={})=>({type:"button",...t}),separator:(t={color:"#E0E3EA"})=>({type:"separator",...t}),filler:(t={})=>({type:"filler",...t}),uri:(t={})=>({type:"uri",altUri:t.altUri?{desktop:t.altUri}:void 0,...t}),postback:(t={})=>({type:"postback",...t}),message:(t={})=>({type:"message",...t}),datetimepicker:(t={})=>({type:"datetimepicker",...t}),camera:(t={})=>({type:"camera",...t}),cameraRoll:(t={})=>({type:"cameraRoll",...t}),location:(t={})=>({type:"location",...t}),richmenuswitch:(t={})=>({type:"richmenuswitch",...t}),clipboard:(t={})=>({type:"clipboard",...t})};function tt(t){if(t.tagName!==e.BACKGROUND&&t.children&&t.children.length>0){const r=t.children.filter(n=>n.tagName===e.BACKGROUND);return r.length>1&&h("A box node can only allowed with one background node inside"),t.children=t.children.filter(n=>n.tagName!==e.BACKGROUND),r[0]}return null}function et(t){if(t.tagName!==e.ACTION&&t.children&&t.children.length>0){const r=t.children.filter(n=>n.tagName===e.ACTION);return r.length>1&&h("A node can only allowed with one action node inside"),t.children=t.children.filter(n=>n.tagName!==e.ACTION),r[0]}return null}function rt(t){![...q,e.SPAN].includes(t.tagName)&&t.children?.some(l=>l.type===E.TEXT)&&(console.log(t),h("Span component only allowed inside Text component")),t.tagName===e.VIDEO&&t.children?.some(l=>![e.BOX,e.IMAGE].includes(l.tagName))&&h("Video component only allowed Box or Image as altContent child"),!W.includes(t.tagName)&&t.children?.some(l=>l.tagName===e.BACKGROUND)&&h("Only Box component allowed to have Background child")}function m(t){t.attributes=t.attributes||{},rt(t);const r=et(t);r&&(t.attributes.action=m(r));const n=tt(t);if(n&&(t.attributes.background=m(n)),t.type===E.TEXT)return c.span(t.content,t.attributes);if(t.tagName===e.BUBBLE){const s=t.children.find(u=>u.tagName===e.HEADER),l=t.children.find(u=>u.tagName===e.HERO),i=t.children.find(u=>u.tagName===e.BODY),a=t.children.find(u=>u.tagName===e.FOOTER);return c.bubble({...t.attributes,header:s?m(s):void 0,hero:l?m(l):void 0,body:i?m(i):void 0,footer:a?m(a):void 0})}if(t.tagName===e.CAROUSEL)return t.children.some(s=>s.tagName!==e.BUBBLE)&&h("Carousel can only have Bubble as children"),t.children.length>12&&h("Carousel can have maximum 12 bubbles"),c.carousel(t.children.map(m));if(Y.includes(t.tagName))return t.children.length!==1&&h(`${t.tagName} should have exactly one child node`),m(t.children[0]);if(t.tagName===e.BUTTON)return t.attributes.action||h("Button component should contain an action node"),c.button(t.attributes);if(t.tagName===e.SPAN){t.children.length>1&&h("Span component can only have one text child");const s=t.children[0];if(s&&s.type===E.TEXT)return c.span(s.content,t.attributes);h(s?"Span component only allowed text child":"Span component can not be empty")}if(t.tagName===e.TEXT)return c.text(t.children.map(m),t.attributes);if(t.tagName===e.SEPARATOR)return c.separator(t.attributes);if(t.tagName===e.IMAGE)return c.image(t.attributes);if(t.tagName===e.VIDEO)return t.children.length!==1&&h("Video component should only has one Box or Image as altContent"),t.attributes.altContent=m(t.children[0]),c.video(t.attributes);if(t.tagName===e.ICON)return c.icon(t.attributes);if(t.tagName===e.FILLER)return c.filler(t.attributes);if(t.tagName===e.BOX||t.tagName===e.DIV||t.tagName===e.ARTICLE)return t.attributes.layout||(t.attributes.layout="vertical"),c.box(t.children.map(m),t.attributes);if(t.tagName===e.SPACE)return c.span(" ".repeat(t.attributes.size||1));if(t.tagName===e.STRONG)return t.tagName=e.TEXT,t.attributes.weight="bold",m(t);if(t.tagName===e.BASELINE)return t.tagName=e.BOX,t.attributes.layout="baseline",m(t);if(t.tagName===e.ROW)return t.tagName=e.BOX,t.attributes.layout="horizontal",m(t);if(t.tagName===e.VERTICAL)return t.tagName=e.BOX,t.attributes.layout="vertical",m(t);if(t.tagName===e.ACTION){const s=t.attributes.type;switch(s){case"uri":return c.uri(t.attributes);case"postback":return c.postback(t.attributes);case"message":return c.message(t.attributes);case"datetimepicker":return c.datetimepicker(t.attributes);case"camera":return c.camera(t.attributes);case"cameraRoll":return c.cameraRoll(t.attributes);case"location":return c.location(t.attributes);case"richmenuswitch":return c.richmenuswitch(t.attributes);case"clipboard":return c.clipboard(t.attributes);default:h(`Unsupported action type: ${s}`)}}if(t.tagName===e.BACKGROUND)return t.attributes}const o={createElement:(t,r={},n=[],s=0)=>{const i=Object.entries(r).filter(([u,p])=>p!=null).map(([u,p])=>typeof p=="object"?`${u}="${JSON.stringify(p).replace(/"/g,"&quot;")}"`:`${u}="${p}"`).join(" "),a=i?` ${i}`:"";if(n.length===0)return` <${t}${a} />`;{const u=n.map(p=>typeof p=="string"?p.split(`
2
+ `).map(f=>f?" "+f:"").join(`
3
+ `):p).join(`
4
+ `);return` <${t}${a}>
5
+ ${u}
6
+ </${t}>`}},createText:t=>t};function b(t,r=0){if(!t||typeof t!="object")return"";const{type:n,...s}=t,{action:l,...i}=s,a=l?b(l,r+1):"";switch(n){case"carousel":const{contents:u,...p}=i,f=u.map(N=>b(N,r+1));return a&&f.unshift(a),o.createElement(e.CAROUSEL,p,f,r);case"bubble":const{header:A,hero:C,body:R,footer:B,...L}=i,g=[];return a&&g.push(a),A&&g.push(o.createElement(e.HEADER,{},[b(A,r+1)],r+1)),C&&g.push(o.createElement(e.HERO,{},[b(C,r+1)],r+1)),R&&g.push(o.createElement(e.BODY,{},[b(R,r+1)],r+1)),B&&g.push(o.createElement(e.FOOTER,{},[b(B,r+1)],r+1)),o.createElement(e.BUBBLE,L,g,r);case"box":const{contents:w,background:d,...O}=i;O.layout||(O.layout="vertical");const T=[];return a&&T.push(a),d&&T.push(b({type:"background",...d},r+1)),T.push(...(w||[]).map(N=>b(N,r+1))),o.createElement(e.BOX,O,T,r);case"text":const{text:U,contents:y,...k}=i,x=y&&y.length>0?y.map(N=>b(N,r+1)):[U||""];return a&&x.unshift(a),o.createElement(e.TEXT,k,x,r);case"span":const{text:D,...X}=i,S=[D||""];return a&&S.unshift(a),o.createElement(e.SPAN,X,S,r);case"image":const{...$}=i,H=a?[a]:[];return o.createElement(e.IMAGE,$,H,r);case"video":const{altContent:I,...G}=i,v=I?[b(I,r+1)]:[];return a&&v.unshift(a),o.createElement(e.VIDEO,G,v,r);case"icon":const{...M}=i,F=a?[a]:[];return o.createElement(e.ICON,M,F,r);case"button":const{...P}=i,V=a?[a]:[];return o.createElement(e.BUTTON,P,V,r);case"separator":const j=a?[a]:[];return o.createElement(e.SEPARATOR,i,j,r);case"filler":const K=a?[a]:[];return o.createElement(e.FILLER,i,K,r);case"uri":case"message":case"postback":case"datetimepicker":case"camera":case"cameraRoll":case"location":case"richmenuswitch":case"clipboard":return o.createElement(e.ACTION,{type:n,...i},[],r);case"background":return o.createElement(e.BACKGROUND,i,[],r);default:return""}}function at(t){try{return Z(t).map(m)}catch(r){throw console.error("Error converting HTML to Flex Message:",r),r}}exports.convertJsonToHtml=b;exports.default=at;
@@ -1,5 +1,5 @@
1
- import { Parser as f } from "htmlparser2";
2
- const g = {
1
+ import { Parser as Y } from "htmlparser2";
2
+ const E = {
3
3
  ELEMENT: "element",
4
4
  TEXT: "text"
5
5
  }, e = {
@@ -20,6 +20,7 @@ const g = {
20
20
  ICON: "icon",
21
21
  SEPARATOR: "separator",
22
22
  BUTTON: "button",
23
+ FILLER: "filler",
23
24
  // custom render tags
24
25
  SPACE: "space",
25
26
  STRONG: "strong",
@@ -27,58 +28,73 @@ const g = {
27
28
  BASELINE: "baseline",
28
29
  ROW: "row",
29
30
  VERTICAL: "vertical",
31
+ DIV: "div",
32
+ ARTICLE: "article",
30
33
  // custom utils tags
31
34
  ACTION: "action",
32
35
  BACKGROUND: "background"
33
- }, b = [
36
+ }, J = [
34
37
  e.HEADER,
35
38
  e.HERO,
36
39
  e.BODY,
37
40
  e.FOOTER
38
- ], p = [
41
+ ], W = [
39
42
  e.BOX,
40
43
  e.VERTICAL,
41
44
  e.ROW,
42
- e.BASELINE
45
+ e.BASELINE,
46
+ e.DIV,
47
+ e.ARTICLE
48
+ ], z = [
49
+ e.TEXT,
50
+ e.STRONG
43
51
  ];
44
- function E(t) {
52
+ function q(t) {
45
53
  const r = Number(t);
46
54
  return isNaN(r) ? t : r;
47
55
  }
48
- function O(t) {
56
+ function Q(t) {
49
57
  return t === "true" ? !0 : t === "false" ? !1 : t;
50
58
  }
51
- function T(t) {
59
+ function Z(t) {
52
60
  return [
53
- E,
54
- O
55
- ].reduce((a, n) => n(a), t);
61
+ q,
62
+ Q
63
+ ].reduce((n, s) => s(n), t);
56
64
  }
57
- function A(t) {
58
- const r = { type: "root", children: [] }, a = [r], n = new f(
65
+ function _(t) {
66
+ const r = { type: "root", children: [] }, n = [r], s = new Y(
59
67
  {
60
- onopentag(s, u) {
61
- const N = {
62
- type: g.ELEMENT,
63
- tagName: s,
68
+ onopentag(l, i) {
69
+ const a = {
70
+ type: E.ELEMENT,
71
+ tagName: l,
64
72
  attributes: Object.fromEntries(
65
- Object.entries(u).map(([h, m]) => [h, T(m)])
73
+ Object.entries(i).map(([p, f]) => [p, Z(f)])
66
74
  ),
67
75
  children: []
68
76
  };
69
- a[a.length - 1].children.push(N), a.push(N);
77
+ n[n.length - 1].children.push(a), n.push(a);
70
78
  },
71
- ontext(s) {
72
- s.trim() && a[a.length - 1].children.push({
73
- type: g.TEXT,
74
- content: s.replace(/\n/g, "").trim()
79
+ ontext(l) {
80
+ const i = n[n.length - 1];
81
+ if (i.tagName === "span") {
82
+ i.children.push({
83
+ type: E.TEXT,
84
+ content: l
85
+ });
86
+ return;
87
+ }
88
+ l.trim() && i.children.push({
89
+ type: E.TEXT,
90
+ content: l.replace(/\n/g, "").trim()
75
91
  });
76
92
  },
77
93
  onclosetag() {
78
- a.pop();
94
+ n.pop();
79
95
  },
80
- onerror(s) {
81
- console.error("解析錯誤:", s);
96
+ onerror(l) {
97
+ console.error("解析錯誤:", l);
82
98
  }
83
99
  },
84
100
  {
@@ -89,9 +105,9 @@ function A(t) {
89
105
  lowerCaseAttributeNames: !1
90
106
  }
91
107
  );
92
- return n.write(t), n.end(), r.children;
108
+ return s.write(t), s.end(), r.children;
93
109
  }
94
- const l = (t) => {
110
+ const h = (t) => {
95
111
  throw Error(`[Flex Html Render]: ${t}`);
96
112
  }, c = {
97
113
  carousel: (t) => ({
@@ -139,66 +155,105 @@ const l = (t) => {
139
155
  type: "separator",
140
156
  ...t
141
157
  }),
158
+ filler: (t = {}) => ({
159
+ type: "filler",
160
+ ...t
161
+ }),
142
162
  uri: (t = {}) => ({
143
163
  type: "uri",
144
164
  altUri: t.altUri ? {
145
165
  desktop: t.altUri
146
166
  } : void 0,
147
167
  ...t
168
+ }),
169
+ postback: (t = {}) => ({
170
+ type: "postback",
171
+ ...t
172
+ }),
173
+ message: (t = {}) => ({
174
+ type: "message",
175
+ ...t
176
+ }),
177
+ datetimepicker: (t = {}) => ({
178
+ type: "datetimepicker",
179
+ ...t
180
+ }),
181
+ camera: (t = {}) => ({
182
+ type: "camera",
183
+ ...t
184
+ }),
185
+ cameraRoll: (t = {}) => ({
186
+ type: "cameraRoll",
187
+ ...t
188
+ }),
189
+ location: (t = {}) => ({
190
+ type: "location",
191
+ ...t
192
+ }),
193
+ richmenuswitch: (t = {}) => ({
194
+ type: "richmenuswitch",
195
+ ...t
196
+ }),
197
+ clipboard: (t = {}) => ({
198
+ type: "clipboard",
199
+ ...t
148
200
  })
149
201
  };
150
- function B(t) {
202
+ function tt(t) {
151
203
  if (t.tagName !== e.BACKGROUND && t.children && t.children.length > 0) {
152
- const r = t.children.filter((a) => a.tagName === e.BACKGROUND);
153
- return r.length > 1 && l("A box node can only allowed with one background node inside"), t.children = t.children.filter((a) => a.tagName !== e.BACKGROUND), r[0];
204
+ const r = t.children.filter((n) => n.tagName === e.BACKGROUND);
205
+ return r.length > 1 && h("A box node can only allowed with one background node inside"), t.children = t.children.filter((n) => n.tagName !== e.BACKGROUND), r[0];
154
206
  }
155
207
  return null;
156
208
  }
157
- function y(t) {
209
+ function et(t) {
158
210
  if (t.tagName !== e.ACTION && t.children && t.children.length > 0) {
159
- const r = t.children.filter((a) => a.tagName === e.ACTION);
160
- return r.length > 1 && l("A node can only allowed with one action node inside"), t.children = t.children.filter((a) => a.tagName !== e.ACTION), r[0];
211
+ const r = t.children.filter((n) => n.tagName === e.ACTION);
212
+ return r.length > 1 && h("A node can only allowed with one action node inside"), t.children = t.children.filter((n) => n.tagName !== e.ACTION), r[0];
161
213
  }
162
214
  return null;
163
215
  }
164
- function i(t) {
165
- t.attributes = t.attributes || {};
166
- const r = y(t);
167
- r && (t.attributes.action = i(r));
168
- const a = B(t);
169
- if (a && p.includes(t.tagName) && (t.attributes.background = i(a)), t.type === g.TEXT)
216
+ function rt(t) {
217
+ ![...z, e.SPAN].includes(t.tagName) && t.children?.some((l) => l.type === E.TEXT) && (console.log(t), h("Span component only allowed inside Text component")), t.tagName === e.VIDEO && t.children?.some((l) => ![e.BOX, e.IMAGE].includes(l.tagName)) && h("Video component only allowed Box or Image as altContent child"), !W.includes(t.tagName) && t.children?.some((l) => l.tagName === e.BACKGROUND) && h("Only Box component allowed to have Background child");
218
+ }
219
+ function m(t) {
220
+ t.attributes = t.attributes || {}, rt(t);
221
+ const r = et(t);
222
+ r && (t.attributes.action = m(r));
223
+ const n = tt(t);
224
+ if (n && (t.attributes.background = m(n)), t.type === E.TEXT)
170
225
  return c.span(t.content, t.attributes);
171
226
  if (t.tagName === e.BUBBLE) {
172
- const n = t.children.find((o) => o.tagName === e.HEADER), s = t.children.find((o) => o.tagName === e.HERO), u = t.children.find((o) => o.tagName === e.BODY), N = t.children.find((o) => o.tagName === e.FOOTER);
227
+ const s = t.children.find((u) => u.tagName === e.HEADER), l = t.children.find((u) => u.tagName === e.HERO), i = t.children.find((u) => u.tagName === e.BODY), a = t.children.find((u) => u.tagName === e.FOOTER);
173
228
  return c.bubble({
174
229
  ...t.attributes,
175
- header: n ? i(n) : void 0,
176
- hero: s ? i(s) : void 0,
177
- body: u ? i(u) : void 0,
178
- footer: N ? i(N) : void 0
230
+ header: s ? m(s) : void 0,
231
+ hero: l ? m(l) : void 0,
232
+ body: i ? m(i) : void 0,
233
+ footer: a ? m(a) : void 0
179
234
  });
180
235
  }
181
236
  if (t.tagName === e.CAROUSEL)
182
- return t.children.some((n) => n.tagName !== e.BUBBLE) && l("Carousel can only have Bubble as children"), t.children.length > 12 && l("Carousel can have maximum 12 bubbles"), c.carousel(
183
- t.children.map(i)
237
+ return t.children.some((s) => s.tagName !== e.BUBBLE) && h("Carousel can only have Bubble as children"), t.children.length > 12 && h("Carousel can have maximum 12 bubbles"), c.carousel(
238
+ t.children.map(m)
184
239
  );
185
- if (b.includes(t.tagName))
186
- return t.children.length !== 1 && l(`${t.tagName} should have exactly one child node`), i(t.children[0]);
240
+ if (J.includes(t.tagName))
241
+ return t.children.length !== 1 && h(`${t.tagName} should have exactly one child node`), m(t.children[0]);
187
242
  if (t.tagName === e.BUTTON)
188
- return t.attributes.action || l("Button component should contain an action node"), c.button(t.attributes);
243
+ return t.attributes.action || h("Button component should contain an action node"), c.button(t.attributes);
189
244
  if (t.tagName === e.SPAN) {
190
- t.children.length > 1 && l("Span component can only have one text child");
191
- const n = t.children[0];
192
- if (n && n.type === g.TEXT)
245
+ t.children.length > 1 && h("Span component can only have one text child");
246
+ const s = t.children[0];
247
+ if (s && s.type === E.TEXT)
193
248
  return c.span(
194
- n.content,
249
+ s.content,
195
250
  t.attributes
196
251
  );
197
- l("Span component only allowed text child");
252
+ h(s ? "Span component only allowed text child" : "Span component can not be empty");
198
253
  }
199
254
  if (t.tagName === e.TEXT)
200
255
  return c.text(
201
- t.children.map(i),
256
+ t.children.map(m),
202
257
  t.attributes
203
258
  );
204
259
  if (t.tagName === e.SEPARATOR)
@@ -206,39 +261,136 @@ function i(t) {
206
261
  if (t.tagName === e.IMAGE)
207
262
  return c.image(t.attributes);
208
263
  if (t.tagName === e.VIDEO)
209
- return t.children.length !== 1 && l("Video component should only has one Box or Image as altContent"), [
210
- e.BOX,
211
- e.IMAGE
212
- ].includes(t.children[0]?.tagName) || l("Video component should only has Box or Image child as altContent"), t.attributes.altContent = i(t.children[0]), c.video(t.attributes);
264
+ return t.children.length !== 1 && h("Video component should only has one Box or Image as altContent"), t.attributes.altContent = m(t.children[0]), c.video(t.attributes);
213
265
  if (t.tagName === e.ICON)
214
266
  return c.icon(t.attributes);
215
- if (t.tagName === e.BOX)
216
- return c.box(
217
- t.children.map(i),
267
+ if (t.tagName === e.FILLER)
268
+ return c.filler(t.attributes);
269
+ if (t.tagName === e.BOX || t.tagName === e.DIV || t.tagName === e.ARTICLE)
270
+ return t.attributes.layout || (t.attributes.layout = "vertical"), c.box(
271
+ t.children.map(m),
218
272
  t.attributes
219
273
  );
220
274
  if (t.tagName === e.SPACE)
221
275
  return c.span(" ".repeat(t.attributes.size || 1));
222
276
  if (t.tagName === e.STRONG)
223
- return t.tagName = e.TEXT, t.attributes.weight = "bold", i(t);
277
+ return t.tagName = e.TEXT, t.attributes.weight = "bold", m(t);
224
278
  if (t.tagName === e.BASELINE)
225
- return t.tagName = e.BOX, t.attributes.layout = "baseline", i(t);
279
+ return t.tagName = e.BOX, t.attributes.layout = "baseline", m(t);
226
280
  if (t.tagName === e.ROW)
227
- return t.tagName = e.BOX, t.attributes.layout = "horizontal", i(t);
281
+ return t.tagName = e.BOX, t.attributes.layout = "horizontal", m(t);
228
282
  if (t.tagName === e.VERTICAL)
229
- return t.tagName = e.BOX, t.attributes.layout = "vertical", i(t);
230
- if (t.tagName === e.ACTION && t.attributes.type === "uri")
231
- return c.uri(t.attributes);
283
+ return t.tagName = e.BOX, t.attributes.layout = "vertical", m(t);
284
+ if (t.tagName === e.ACTION) {
285
+ const s = t.attributes.type;
286
+ switch (s) {
287
+ case "uri":
288
+ return c.uri(t.attributes);
289
+ case "postback":
290
+ return c.postback(t.attributes);
291
+ case "message":
292
+ return c.message(t.attributes);
293
+ case "datetimepicker":
294
+ return c.datetimepicker(t.attributes);
295
+ case "camera":
296
+ return c.camera(t.attributes);
297
+ case "cameraRoll":
298
+ return c.cameraRoll(t.attributes);
299
+ case "location":
300
+ return c.location(t.attributes);
301
+ case "richmenuswitch":
302
+ return c.richmenuswitch(t.attributes);
303
+ case "clipboard":
304
+ return c.clipboard(t.attributes);
305
+ default:
306
+ h(`Unsupported action type: ${s}`);
307
+ }
308
+ }
232
309
  if (t.tagName === e.BACKGROUND)
233
310
  return t.attributes;
234
311
  }
235
- function C(t) {
312
+ const o = {
313
+ createElement: (t, r = {}, n = [], s = 0) => {
314
+ const i = Object.entries(r).filter(([u, p]) => p != null).map(([u, p]) => typeof p == "object" ? `${u}="${JSON.stringify(p).replace(/"/g, "&quot;")}"` : `${u}="${p}"`).join(" "), a = i ? ` ${i}` : "";
315
+ if (n.length === 0)
316
+ return ` <${t}${a} />`;
317
+ {
318
+ const u = n.map((p) => typeof p == "string" ? p.split(`
319
+ `).map((f) => f ? " " + f : "").join(`
320
+ `) : p).join(`
321
+ `);
322
+ return ` <${t}${a}>
323
+ ${u}
324
+ </${t}>`;
325
+ }
326
+ },
327
+ createText: (t) => t
328
+ };
329
+ function b(t, r = 0) {
330
+ if (!t || typeof t != "object")
331
+ return "";
332
+ const { type: n, ...s } = t, { action: l, ...i } = s, a = l ? b(l, r + 1) : "";
333
+ switch (n) {
334
+ case "carousel":
335
+ const { contents: u, ...p } = i, f = u.map((N) => b(N, r + 1));
336
+ return a && f.unshift(a), o.createElement(e.CAROUSEL, p, f, r);
337
+ case "bubble":
338
+ const { header: y, hero: C, body: R, footer: B, ...L } = i, g = [];
339
+ return a && g.push(a), y && g.push(o.createElement(e.HEADER, {}, [b(y, r + 1)], r + 1)), C && g.push(o.createElement(e.HERO, {}, [b(C, r + 1)], r + 1)), R && g.push(o.createElement(e.BODY, {}, [b(R, r + 1)], r + 1)), B && g.push(o.createElement(e.FOOTER, {}, [b(B, r + 1)], r + 1)), o.createElement(e.BUBBLE, L, g, r);
340
+ case "box":
341
+ const { contents: w, background: d, ...O } = i;
342
+ O.layout || (O.layout = "vertical");
343
+ const T = [];
344
+ return a && T.push(a), d && T.push(b({ type: "background", ...d }, r + 1)), T.push(...(w || []).map((N) => b(N, r + 1))), o.createElement(e.BOX, O, T, r);
345
+ case "text":
346
+ const { text: U, contents: A, ...k } = i, x = A && A.length > 0 ? A.map((N) => b(N, r + 1)) : [U || ""];
347
+ return a && x.unshift(a), o.createElement(e.TEXT, k, x, r);
348
+ case "span":
349
+ const { text: D, ...X } = i, I = [D || ""];
350
+ return a && I.unshift(a), o.createElement(e.SPAN, X, I, r);
351
+ case "image":
352
+ const { ...$ } = i, G = a ? [a] : [];
353
+ return o.createElement(e.IMAGE, $, G, r);
354
+ case "video":
355
+ const { altContent: S, ...H } = i, v = S ? [b(S, r + 1)] : [];
356
+ return a && v.unshift(a), o.createElement(e.VIDEO, H, v, r);
357
+ case "icon":
358
+ const { ...F } = i, V = a ? [a] : [];
359
+ return o.createElement(e.ICON, F, V, r);
360
+ case "button":
361
+ const { ...M } = i, P = a ? [a] : [];
362
+ return o.createElement(e.BUTTON, M, P, r);
363
+ case "separator":
364
+ const K = a ? [a] : [];
365
+ return o.createElement(e.SEPARATOR, i, K, r);
366
+ case "filler":
367
+ const j = a ? [a] : [];
368
+ return o.createElement(e.FILLER, i, j, r);
369
+ // Action types
370
+ case "uri":
371
+ case "message":
372
+ case "postback":
373
+ case "datetimepicker":
374
+ case "camera":
375
+ case "cameraRoll":
376
+ case "location":
377
+ case "richmenuswitch":
378
+ case "clipboard":
379
+ return o.createElement(e.ACTION, { type: n, ...i }, [], r);
380
+ case "background":
381
+ return o.createElement(e.BACKGROUND, i, [], r);
382
+ default:
383
+ return "";
384
+ }
385
+ }
386
+ function nt(t) {
236
387
  try {
237
- return A(t).map(i);
388
+ return _(t).map(m);
238
389
  } catch (r) {
239
- console.error("Error converting HTML to Flex Message:", r);
390
+ throw console.error("Error converting HTML to Flex Message:", r), r;
240
391
  }
241
392
  }
242
393
  export {
243
- C as default
394
+ b as convertJsonToHtml,
395
+ nt as default
244
396
  };
@@ -1 +1,6 @@
1
- (function(u,f){typeof exports=="object"&&typeof module<"u"?f(exports,require("htmlparser2")):typeof define=="function"&&define.amd?define(["exports","htmlparser2"],f):(u=typeof globalThis<"u"?globalThis:u||self,f(u.FlexHtmlRender={},u.htmlparser2))})(this,(function(u,f){"use strict";const g={ELEMENT:"element",TEXT:"text"},e={CAROUSEL:"carousel",BUBBLE:"bubble",HEADER:"header",HERO:"hero",BODY:"body",FOOTER:"footer",BOX:"box",TEXT:"text",SPAN:"span",IMAGE:"image",VIDEO:"video",ICON:"icon",SEPARATOR:"separator",BUTTON:"button",SPACE:"space",STRONG:"strong",BASELINE:"baseline",ROW:"row",VERTICAL:"vertical",ACTION:"action",BACKGROUND:"background"},N=[e.HEADER,e.HERO,e.BODY,e.FOOTER],p=[e.BOX,e.VERTICAL,e.ROW,e.BASELINE];function b(t){const r=Number(t);return isNaN(r)?t:r}function E(t){return t==="true"?!0:t==="false"?!1:t}function T(t){return[b,E].reduce((a,l)=>l(a),t)}function O(t){const r={type:"root",children:[]},a=[r],l=new f.Parser({onopentag(c,h){const m={type:g.ELEMENT,tagName:c,attributes:Object.fromEntries(Object.entries(h).map(([B,R])=>[B,T(R)])),children:[]};a[a.length-1].children.push(m),a.push(m)},ontext(c){c.trim()&&a[a.length-1].children.push({type:g.TEXT,content:c.replace(/\n/g,"").trim()})},onclosetag(){a.pop()},onerror(c){console.error("解析錯誤:",c)}},{xmlMode:!0,lowerCaseTags:!1,lowerCaseAttributeNames:!1});return l.write(t),l.end(),r.children}const s=t=>{throw Error(`[Flex Html Render]: ${t}`)},n={carousel:t=>({type:"carousel",contents:t}),bubble:(t={})=>({type:"bubble",...t}),box:(t,r={})=>({type:"box",contents:t,...r}),text:(t,r={})=>({type:"text",...typeof t=="string"?{text:t}:{contents:t},...r}),span:(t,r={})=>({type:"span",text:t,...r}),image:(t={})=>({type:"image",...t}),video:(t={})=>({type:"video",...t}),icon:(t={})=>({type:"icon",...t}),button:(t={})=>({type:"button",...t}),separator:(t={color:"#E0E3EA"})=>({type:"separator",...t}),uri:(t={})=>({type:"uri",altUri:t.altUri?{desktop:t.altUri}:void 0,...t})};function y(t){if(t.tagName!==e.BACKGROUND&&t.children&&t.children.length>0){const r=t.children.filter(a=>a.tagName===e.BACKGROUND);return r.length>1&&s("A box node can only allowed with one background node inside"),t.children=t.children.filter(a=>a.tagName!==e.BACKGROUND),r[0]}return null}function A(t){if(t.tagName!==e.ACTION&&t.children&&t.children.length>0){const r=t.children.filter(a=>a.tagName===e.ACTION);return r.length>1&&s("A node can only allowed with one action node inside"),t.children=t.children.filter(a=>a.tagName!==e.ACTION),r[0]}return null}function i(t){t.attributes=t.attributes||{};const r=A(t);r&&(t.attributes.action=i(r));const a=y(t);if(a&&p.includes(t.tagName)&&(t.attributes.background=i(a)),t.type===g.TEXT)return n.span(t.content,t.attributes);if(t.tagName===e.BUBBLE){const l=t.children.find(o=>o.tagName===e.HEADER),c=t.children.find(o=>o.tagName===e.HERO),h=t.children.find(o=>o.tagName===e.BODY),m=t.children.find(o=>o.tagName===e.FOOTER);return n.bubble({...t.attributes,header:l?i(l):void 0,hero:c?i(c):void 0,body:h?i(h):void 0,footer:m?i(m):void 0})}if(t.tagName===e.CAROUSEL)return t.children.some(l=>l.tagName!==e.BUBBLE)&&s("Carousel can only have Bubble as children"),t.children.length>12&&s("Carousel can have maximum 12 bubbles"),n.carousel(t.children.map(i));if(N.includes(t.tagName))return t.children.length!==1&&s(`${t.tagName} should have exactly one child node`),i(t.children[0]);if(t.tagName===e.BUTTON)return t.attributes.action||s("Button component should contain an action node"),n.button(t.attributes);if(t.tagName===e.SPAN){t.children.length>1&&s("Span component can only have one text child");const l=t.children[0];if(l&&l.type===g.TEXT)return n.span(l.content,t.attributes);s("Span component only allowed text child")}if(t.tagName===e.TEXT)return n.text(t.children.map(i),t.attributes);if(t.tagName===e.SEPARATOR)return n.separator(t.attributes);if(t.tagName===e.IMAGE)return n.image(t.attributes);if(t.tagName===e.VIDEO)return t.children.length!==1&&s("Video component should only has one Box or Image as altContent"),[e.BOX,e.IMAGE].includes(t.children[0]?.tagName)||s("Video component should only has Box or Image child as altContent"),t.attributes.altContent=i(t.children[0]),n.video(t.attributes);if(t.tagName===e.ICON)return n.icon(t.attributes);if(t.tagName===e.BOX)return n.box(t.children.map(i),t.attributes);if(t.tagName===e.SPACE)return n.span(" ".repeat(t.attributes.size||1));if(t.tagName===e.STRONG)return t.tagName=e.TEXT,t.attributes.weight="bold",i(t);if(t.tagName===e.BASELINE)return t.tagName=e.BOX,t.attributes.layout="baseline",i(t);if(t.tagName===e.ROW)return t.tagName=e.BOX,t.attributes.layout="horizontal",i(t);if(t.tagName===e.VERTICAL)return t.tagName=e.BOX,t.attributes.layout="vertical",i(t);if(t.tagName===e.ACTION&&t.attributes.type==="uri")return n.uri(t.attributes);if(t.tagName===e.BACKGROUND)return t.attributes}function d(t){try{return O(t).map(i)}catch(r){console.error("Error converting HTML to Flex Message:",r)}}u.default=d,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
1
+ (function(b,T){typeof exports=="object"&&typeof module<"u"?T(exports,require("htmlparser2")):typeof define=="function"&&define.amd?define(["exports","htmlparser2"],T):(b=typeof globalThis<"u"?globalThis:b||self,T(b.FlexHtmlRender={},b.htmlparser2))})(this,(function(b,T){"use strict";const E={ELEMENT:"element",TEXT:"text"},e={CAROUSEL:"carousel",BUBBLE:"bubble",HEADER:"header",HERO:"hero",BODY:"body",FOOTER:"footer",BOX:"box",TEXT:"text",SPAN:"span",IMAGE:"image",VIDEO:"video",ICON:"icon",SEPARATOR:"separator",BUTTON:"button",FILLER:"filler",SPACE:"space",STRONG:"strong",BASELINE:"baseline",ROW:"row",VERTICAL:"vertical",DIV:"div",ARTICLE:"article",ACTION:"action",BACKGROUND:"background"},U=[e.HEADER,e.HERO,e.BODY,e.FOOTER],k=[e.BOX,e.VERTICAL,e.ROW,e.BASELINE,e.DIV,e.ARTICLE],D=[e.TEXT,e.STRONG];function X(t){const r=Number(t);return isNaN(r)?t:r}function $(t){return t==="true"?!0:t==="false"?!1:t}function H(t){return[X,$].reduce((n,s)=>s(n),t)}function G(t){const r={type:"root",children:[]},n=[r],s=new T.Parser({onopentag(l,i){const a={type:E.ELEMENT,tagName:l,attributes:Object.fromEntries(Object.entries(i).map(([h,g])=>[h,H(g)])),children:[]};n[n.length-1].children.push(a),n.push(a)},ontext(l){const i=n[n.length-1];if(i.tagName==="span"){i.children.push({type:E.TEXT,content:l});return}l.trim()&&i.children.push({type:E.TEXT,content:l.replace(/\n/g,"").trim()})},onclosetag(){n.pop()},onerror(l){console.error("解析錯誤:",l)}},{xmlMode:!0,lowerCaseTags:!1,lowerCaseAttributeNames:!1});return s.write(t),s.end(),r.children}const p=t=>{throw Error(`[Flex Html Render]: ${t}`)},c={carousel:t=>({type:"carousel",contents:t}),bubble:(t={})=>({type:"bubble",...t}),box:(t,r={})=>({type:"box",contents:t,...r}),text:(t,r={})=>({type:"text",...typeof t=="string"?{text:t}:{contents:t},...r}),span:(t,r={})=>({type:"span",text:t,...r}),image:(t={})=>({type:"image",...t}),video:(t={})=>({type:"video",...t}),icon:(t={})=>({type:"icon",...t}),button:(t={})=>({type:"button",...t}),separator:(t={color:"#E0E3EA"})=>({type:"separator",...t}),filler:(t={})=>({type:"filler",...t}),uri:(t={})=>({type:"uri",altUri:t.altUri?{desktop:t.altUri}:void 0,...t}),postback:(t={})=>({type:"postback",...t}),message:(t={})=>({type:"message",...t}),datetimepicker:(t={})=>({type:"datetimepicker",...t}),camera:(t={})=>({type:"camera",...t}),cameraRoll:(t={})=>({type:"cameraRoll",...t}),location:(t={})=>({type:"location",...t}),richmenuswitch:(t={})=>({type:"richmenuswitch",...t}),clipboard:(t={})=>({type:"clipboard",...t})};function F(t){if(t.tagName!==e.BACKGROUND&&t.children&&t.children.length>0){const r=t.children.filter(n=>n.tagName===e.BACKGROUND);return r.length>1&&p("A box node can only allowed with one background node inside"),t.children=t.children.filter(n=>n.tagName!==e.BACKGROUND),r[0]}return null}function M(t){if(t.tagName!==e.ACTION&&t.children&&t.children.length>0){const r=t.children.filter(n=>n.tagName===e.ACTION);return r.length>1&&p("A node can only allowed with one action node inside"),t.children=t.children.filter(n=>n.tagName!==e.ACTION),r[0]}return null}function P(t){![...D,e.SPAN].includes(t.tagName)&&t.children?.some(l=>l.type===E.TEXT)&&(console.log(t),p("Span component only allowed inside Text component")),t.tagName===e.VIDEO&&t.children?.some(l=>![e.BOX,e.IMAGE].includes(l.tagName))&&p("Video component only allowed Box or Image as altContent child"),!k.includes(t.tagName)&&t.children?.some(l=>l.tagName===e.BACKGROUND)&&p("Only Box component allowed to have Background child")}function u(t){t.attributes=t.attributes||{},P(t);const r=M(t);r&&(t.attributes.action=u(r));const n=F(t);if(n&&(t.attributes.background=u(n)),t.type===E.TEXT)return c.span(t.content,t.attributes);if(t.tagName===e.BUBBLE){const s=t.children.find(m=>m.tagName===e.HEADER),l=t.children.find(m=>m.tagName===e.HERO),i=t.children.find(m=>m.tagName===e.BODY),a=t.children.find(m=>m.tagName===e.FOOTER);return c.bubble({...t.attributes,header:s?u(s):void 0,hero:l?u(l):void 0,body:i?u(i):void 0,footer:a?u(a):void 0})}if(t.tagName===e.CAROUSEL)return t.children.some(s=>s.tagName!==e.BUBBLE)&&p("Carousel can only have Bubble as children"),t.children.length>12&&p("Carousel can have maximum 12 bubbles"),c.carousel(t.children.map(u));if(U.includes(t.tagName))return t.children.length!==1&&p(`${t.tagName} should have exactly one child node`),u(t.children[0]);if(t.tagName===e.BUTTON)return t.attributes.action||p("Button component should contain an action node"),c.button(t.attributes);if(t.tagName===e.SPAN){t.children.length>1&&p("Span component can only have one text child");const s=t.children[0];if(s&&s.type===E.TEXT)return c.span(s.content,t.attributes);p(s?"Span component only allowed text child":"Span component can not be empty")}if(t.tagName===e.TEXT)return c.text(t.children.map(u),t.attributes);if(t.tagName===e.SEPARATOR)return c.separator(t.attributes);if(t.tagName===e.IMAGE)return c.image(t.attributes);if(t.tagName===e.VIDEO)return t.children.length!==1&&p("Video component should only has one Box or Image as altContent"),t.attributes.altContent=u(t.children[0]),c.video(t.attributes);if(t.tagName===e.ICON)return c.icon(t.attributes);if(t.tagName===e.FILLER)return c.filler(t.attributes);if(t.tagName===e.BOX||t.tagName===e.DIV||t.tagName===e.ARTICLE)return t.attributes.layout||(t.attributes.layout="vertical"),c.box(t.children.map(u),t.attributes);if(t.tagName===e.SPACE)return c.span(" ".repeat(t.attributes.size||1));if(t.tagName===e.STRONG)return t.tagName=e.TEXT,t.attributes.weight="bold",u(t);if(t.tagName===e.BASELINE)return t.tagName=e.BOX,t.attributes.layout="baseline",u(t);if(t.tagName===e.ROW)return t.tagName=e.BOX,t.attributes.layout="horizontal",u(t);if(t.tagName===e.VERTICAL)return t.tagName=e.BOX,t.attributes.layout="vertical",u(t);if(t.tagName===e.ACTION){const s=t.attributes.type;switch(s){case"uri":return c.uri(t.attributes);case"postback":return c.postback(t.attributes);case"message":return c.message(t.attributes);case"datetimepicker":return c.datetimepicker(t.attributes);case"camera":return c.camera(t.attributes);case"cameraRoll":return c.cameraRoll(t.attributes);case"location":return c.location(t.attributes);case"richmenuswitch":return c.richmenuswitch(t.attributes);case"clipboard":return c.clipboard(t.attributes);default:p(`Unsupported action type: ${s}`)}}if(t.tagName===e.BACKGROUND)return t.attributes}const o={createElement:(t,r={},n=[],s=0)=>{const i=Object.entries(r).filter(([m,h])=>h!=null).map(([m,h])=>typeof h=="object"?`${m}="${JSON.stringify(h).replace(/"/g,"&quot;")}"`:`${m}="${h}"`).join(" "),a=i?` ${i}`:"";if(n.length===0)return` <${t}${a} />`;{const m=n.map(h=>typeof h=="string"?h.split(`
2
+ `).map(g=>g?" "+g:"").join(`
3
+ `):h).join(`
4
+ `);return` <${t}${a}>
5
+ ${m}
6
+ </${t}>`}},createText:t=>t};function f(t,r=0){if(!t||typeof t!="object")return"";const{type:n,...s}=t,{action:l,...i}=s,a=l?f(l,r+1):"";switch(n){case"carousel":const{contents:m,...h}=i,g=m.map(O=>f(O,r+1));return a&&g.unshift(a),o.createElement(e.CAROUSEL,h,g,r);case"bubble":const{header:d,hero:R,body:B,footer:x,...j}=i,N=[];return a&&N.push(a),d&&N.push(o.createElement(e.HEADER,{},[f(d,r+1)],r+1)),R&&N.push(o.createElement(e.HERO,{},[f(R,r+1)],r+1)),B&&N.push(o.createElement(e.BODY,{},[f(B,r+1)],r+1)),x&&N.push(o.createElement(e.FOOTER,{},[f(x,r+1)],r+1)),o.createElement(e.BUBBLE,j,N,r);case"box":const{contents:K,background:S,...A}=i;A.layout||(A.layout="vertical");const y=[];return a&&y.push(a),S&&y.push(f({type:"background",...S},r+1)),y.push(...(K||[]).map(O=>f(O,r+1))),o.createElement(e.BOX,A,y,r);case"text":const{text:J,contents:C,...Y}=i,I=C&&C.length>0?C.map(O=>f(O,r+1)):[J||""];return a&&I.unshift(a),o.createElement(e.TEXT,Y,I,r);case"span":const{text:W,...q}=i,v=[W||""];return a&&v.unshift(a),o.createElement(e.SPAN,q,v,r);case"image":const{...z}=i,_=a?[a]:[];return o.createElement(e.IMAGE,z,_,r);case"video":const{altContent:L,...Q}=i,w=L?[f(L,r+1)]:[];return a&&w.unshift(a),o.createElement(e.VIDEO,Q,w,r);case"icon":const{...Z}=i,tt=a?[a]:[];return o.createElement(e.ICON,Z,tt,r);case"button":const{...et}=i,rt=a?[a]:[];return o.createElement(e.BUTTON,et,rt,r);case"separator":const at=a?[a]:[];return o.createElement(e.SEPARATOR,i,at,r);case"filler":const nt=a?[a]:[];return o.createElement(e.FILLER,i,nt,r);case"uri":case"message":case"postback":case"datetimepicker":case"camera":case"cameraRoll":case"location":case"richmenuswitch":case"clipboard":return o.createElement(e.ACTION,{type:n,...i},[],r);case"background":return o.createElement(e.BACKGROUND,i,[],r);default:return""}}function V(t){try{return G(t).map(u)}catch(r){throw console.error("Error converting HTML to Flex Message:",r),r}}b.convertJsonToHtml=f,b.default=V,Object.defineProperties(b,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
package/index.d.ts CHANGED
@@ -3,9 +3,4 @@
3
3
  * @param htmlString - Flex Message 對應的 HTML 字串
4
4
  * @returns Flex Message JSON 物件陣列
5
5
  */
6
- export default function convertHtmlToFlexMessage(htmlString: string): any[];
7
-
8
- /**
9
- * 官方範例 HTML 字串
10
- */
11
- export const officialDemoString: string;
6
+ export default function convertHtmlToFlexMessage(htmlString: string): any[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flex-html-render",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "將 HTML 字串轉換為 LINE Flex Message JSON 結構的工具",
5
5
  "type": "module",
6
6
  "main": "dist/flex-html-render.cjs.js",