flex-html-render 1.0.1 → 1.0.2

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
@@ -82,6 +82,7 @@ console.log(JSON.stringify(flexMessage, null, 2));
82
82
 
83
83
  ### 便捷標籤 (Convenience Tags)
84
84
  這些是對常用設定的簡寫標籤:
85
+ - `<div>`, `<article>` - 等同於 `<box>`
85
86
  - `<baseline>` - 等同於 `<box layout="baseline">`
86
87
  - `<row>` - 等同於 `<box layout="horizontal">`
87
88
  - `<vertical>` - 等同於 `<box layout="vertical">`
@@ -1 +1 @@
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 f=require("htmlparser2"),h={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",DIV:"div",ARTICLE:"article",ACTION:"action",BACKGROUND:"background"},b=[e.HEADER,e.HERO,e.BODY,e.FOOTER],p=[e.BOX,e.VERTICAL,e.ROW,e.BASELINE,e.DIV,e.ARTICLE],E=[e.TEXT,e.STRONG];function T(t){const r=Number(t);return isNaN(r)?t:r}function O(t){return t==="true"?!0:t==="false"?!1:t}function A(t){return[T,O].reduce((a,l)=>l(a),t)}function d(t){const r={type:"root",children:[]},a=[r],l=new f.Parser({onopentag(n,u){const g={type:h.ELEMENT,tagName:n,attributes:Object.fromEntries(Object.entries(u).map(([m,N])=>[m,A(N)])),children:[]};a[a.length-1].children.push(g),a.push(g)},ontext(n){n.trim()&&a[a.length-1].children.push({type:h.TEXT,content:n.replace(/\n/g,"").trim()})},onclosetag(){a.pop()},onerror(n){console.error("解析錯誤:",n)}},{xmlMode:!0,lowerCaseTags:!1,lowerCaseAttributeNames:!1});return l.write(t),l.end(),r.children}const s=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}),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 B(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 C(t){!E.includes(t.tagName)&&t.children?.some(n=>n.type===h.TEXT)&&s("Span component only allowed inside Text component"),t.tagName===e.VIDEO&&t.children?.some(n=>![e.BOX,e.IMAGE].includes(n.tagName))&&s("Video component only allowed Box or Image as altContent child"),!p.includes(t.tagName)&&t.children?.some(n=>n.tagName===e.BACKGROUND)&&s("Only Box component allowed to have Background child")}function i(t){t.attributes=t.attributes||{},C(t);const r=B(t);r&&(t.attributes.action=i(r));const a=y(t);if(a&&(t.attributes.background=i(a)),t.type===h.TEXT)return c.span(t.content,t.attributes);if(t.tagName===e.BUBBLE){const l=t.children.find(o=>o.tagName===e.HEADER),n=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 c.bubble({...t.attributes,header:l?i(l):void 0,hero:n?i(n):void 0,body:u?i(u):void 0,footer:g?i(g):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"),c.carousel(t.children.map(i));if(b.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"),c.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===h.TEXT)return c.span(l.content,t.attributes);s("Span component only allowed text child")}if(t.tagName===e.TEXT)return c.text(t.children.map(i),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&&s("Video component should only has one Box or Image as altContent"),t.attributes.altContent=i(t.children[0]),c.video(t.attributes);if(t.tagName===e.ICON)return c.icon(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(i),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",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 c.uri(t.attributes);if(t.tagName===e.BACKGROUND)return t.attributes}function R(t){try{return d(t).map(i)}catch(r){throw console.error("Error converting HTML to Flex Message:",r),r}}exports.default=R;
@@ -1,5 +1,5 @@
1
1
  import { Parser as f } from "htmlparser2";
2
- const g = {
2
+ const m = {
3
3
  ELEMENT: "element",
4
4
  TEXT: "text"
5
5
  }, e = {
@@ -27,58 +27,65 @@ const g = {
27
27
  BASELINE: "baseline",
28
28
  ROW: "row",
29
29
  VERTICAL: "vertical",
30
+ DIV: "div",
31
+ ARTICLE: "article",
30
32
  // custom utils tags
31
33
  ACTION: "action",
32
34
  BACKGROUND: "background"
33
- }, b = [
35
+ }, p = [
34
36
  e.HEADER,
35
37
  e.HERO,
36
38
  e.BODY,
37
39
  e.FOOTER
38
- ], p = [
40
+ ], b = [
39
41
  e.BOX,
40
42
  e.VERTICAL,
41
43
  e.ROW,
42
- e.BASELINE
44
+ e.BASELINE,
45
+ e.DIV,
46
+ e.ARTICLE
47
+ ], E = [
48
+ e.TEXT,
49
+ e.STRONG
43
50
  ];
44
- function E(t) {
45
- const r = Number(t);
46
- return isNaN(r) ? t : r;
51
+ function T(t) {
52
+ const a = Number(t);
53
+ return isNaN(a) ? t : a;
47
54
  }
48
55
  function O(t) {
49
56
  return t === "true" ? !0 : t === "false" ? !1 : t;
50
57
  }
51
- function T(t) {
58
+ function A(t) {
52
59
  return [
53
- E,
60
+ T,
54
61
  O
55
- ].reduce((a, n) => n(a), t);
62
+ ].reduce((r, l) => l(r), t);
56
63
  }
57
- function A(t) {
58
- const r = { type: "root", children: [] }, a = [r], n = new f(
64
+ function B(t) {
65
+ const a = { type: "root", children: [] }, r = [a], l = new f(
59
66
  {
60
- onopentag(s, u) {
61
- const N = {
62
- type: g.ELEMENT,
63
- tagName: s,
67
+ onopentag(n, u) {
68
+ const g = {
69
+ type: m.ELEMENT,
70
+ tagName: n,
64
71
  attributes: Object.fromEntries(
65
- Object.entries(u).map(([h, m]) => [h, T(m)])
72
+ Object.entries(u).map(([h, N]) => [h, A(N)])
66
73
  ),
67
74
  children: []
68
75
  };
69
- a[a.length - 1].children.push(N), a.push(N);
76
+ r[r.length - 1].children.push(g), r.push(g);
70
77
  },
71
- ontext(s) {
72
- s.trim() && a[a.length - 1].children.push({
73
- type: g.TEXT,
74
- content: s.replace(/\n/g, "").trim()
78
+ ontext(n) {
79
+ n.trim() && r[r.length - 1].children.push({
80
+ type: m.TEXT,
81
+ content: n.replace(/\n/g, "").trim()
75
82
  });
76
83
  },
77
84
  onclosetag() {
78
- a.pop();
85
+ r.pop();
79
86
  },
80
- onerror(s) {
81
- console.error("解析錯誤:", s);
87
+ onerror(n) {
88
+ console.error("解析錯誤:", n);
82
89
  }
83
90
  },
84
91
  {
@@ -89,9 +96,9 @@ function A(t) {
89
96
  lowerCaseAttributeNames: !1
90
97
  }
91
98
  );
92
- return n.write(t), n.end(), r.children;
99
+ return l.write(t), l.end(), a.children;
93
100
  }
94
- const l = (t) => {
101
+ const o = (t) => {
95
102
  throw Error(`[Flex Html Render]: ${t}`);
96
103
  }, c = {
97
104
  carousel: (t) => ({
@@ -102,22 +109,22 @@ const l = (t) => {
102
109
  type: "bubble",
103
110
  ...t
104
111
  }),
105
- box: (t, r = {}) => ({
112
+ box: (t, a = {}) => ({
106
113
  type: "box",
107
114
  contents: t,
108
- ...r
115
+ ...a
109
116
  }),
110
- text: (t, r = {}) => ({
117
+ text: (t, a = {}) => ({
111
118
  type: "text",
112
119
  ...typeof t == "string" ? { text: t } : {
113
120
  contents: t
114
121
  },
115
- ...r
122
+ ...a
116
123
  }),
117
- span: (t, r = {}) => ({
124
+ span: (t, a = {}) => ({
118
125
  type: "span",
119
126
  text: t,
120
- ...r
127
+ ...a
121
128
  }),
122
129
  image: (t = {}) => ({
123
130
  type: "image",
@@ -147,54 +154,57 @@ const l = (t) => {
147
154
  ...t
148
155
  })
149
156
  };
150
- function B(t) {
157
+ function d(t) {
151
158
  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];
159
+ const a = t.children.filter((r) => r.tagName === e.BACKGROUND);
160
+ return a.length > 1 && o("A box node can only allowed with one background node inside"), t.children = t.children.filter((r) => r.tagName !== e.BACKGROUND), a[0];
154
161
  }
155
162
  return null;
156
163
  }
157
164
  function y(t) {
158
165
  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];
166
+ const a = t.children.filter((r) => r.tagName === e.ACTION);
167
+ return a.length > 1 && o("A node can only allowed with one action node inside"), t.children = t.children.filter((r) => r.tagName !== e.ACTION), a[0];
161
168
  }
162
169
  return null;
163
170
  }
171
+ function C(t) {
172
+ !E.includes(t.tagName) && t.children?.some((n) => n.type === m.TEXT) && o("Span component only allowed inside Text component"), t.tagName === e.VIDEO && t.children?.some((n) => ![e.BOX, e.IMAGE].includes(n.tagName)) && o("Video component only allowed Box or Image as altContent child"), !b.includes(t.tagName) && t.children?.some((n) => n.tagName === e.BACKGROUND) && o("Only Box component allowed to have Background child");
173
+ }
164
174
  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)
175
+ t.attributes = t.attributes || {}, C(t);
176
+ const a = y(t);
177
+ a && (t.attributes.action = i(a));
178
+ const r = d(t);
179
+ if (r && (t.attributes.background = i(r)), t.type === m.TEXT)
170
180
  return c.span(t.content, t.attributes);
171
181
  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);
182
+ const l = t.children.find((s) => s.tagName === e.HEADER), n = t.children.find((s) => s.tagName === e.HERO), u = t.children.find((s) => s.tagName === e.BODY), g = t.children.find((s) => s.tagName === e.FOOTER);
173
183
  return c.bubble({
174
184
  ...t.attributes,
175
- header: n ? i(n) : void 0,
176
- hero: s ? i(s) : void 0,
185
+ header: l ? i(l) : void 0,
186
+ hero: n ? i(n) : void 0,
177
187
  body: u ? i(u) : void 0,
178
- footer: N ? i(N) : void 0
188
+ footer: g ? i(g) : void 0
179
189
  });
180
190
  }
181
191
  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(
192
+ return t.children.some((l) => l.tagName !== e.BUBBLE) && o("Carousel can only have Bubble as children"), t.children.length > 12 && o("Carousel can have maximum 12 bubbles"), c.carousel(
183
193
  t.children.map(i)
184
194
  );
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]);
195
+ if (p.includes(t.tagName))
196
+ return t.children.length !== 1 && o(`${t.tagName} should have exactly one child node`), i(t.children[0]);
187
197
  if (t.tagName === e.BUTTON)
188
- return t.attributes.action || l("Button component should contain an action node"), c.button(t.attributes);
198
+ return t.attributes.action || o("Button component should contain an action node"), c.button(t.attributes);
189
199
  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)
200
+ t.children.length > 1 && o("Span component can only have one text child");
201
+ const l = t.children[0];
202
+ if (l && l.type === m.TEXT)
193
203
  return c.span(
194
- n.content,
204
+ l.content,
195
205
  t.attributes
196
206
  );
197
- l("Span component only allowed text child");
207
+ o("Span component only allowed text child");
198
208
  }
199
209
  if (t.tagName === e.TEXT)
200
210
  return c.text(
@@ -206,14 +216,11 @@ function i(t) {
206
216
  if (t.tagName === e.IMAGE)
207
217
  return c.image(t.attributes);
208
218
  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);
219
+ return t.children.length !== 1 && o("Video component should only has one Box or Image as altContent"), t.attributes.altContent = i(t.children[0]), c.video(t.attributes);
213
220
  if (t.tagName === e.ICON)
214
221
  return c.icon(t.attributes);
215
- if (t.tagName === e.BOX)
216
- return c.box(
222
+ if (t.tagName === e.BOX || t.tagName === e.DIV || t.tagName === e.ARTICLE)
223
+ return t.attributes.layout || (t.attributes.layout = "vertical"), c.box(
217
224
  t.children.map(i),
218
225
  t.attributes
219
226
  );
@@ -232,13 +239,13 @@ function i(t) {
232
239
  if (t.tagName === e.BACKGROUND)
233
240
  return t.attributes;
234
241
  }
235
- function C(t) {
242
+ function x(t) {
236
243
  try {
237
- return A(t).map(i);
238
- } catch (r) {
239
- console.error("Error converting HTML to Flex Message:", r);
244
+ return B(t).map(i);
245
+ } catch (a) {
246
+ throw console.error("Error converting HTML to Flex Message:", a), a;
240
247
  }
241
248
  }
242
249
  export {
243
- C as default
250
+ x as default
244
251
  };
@@ -1 +1 @@
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(u,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("htmlparser2")):typeof define=="function"&&define.amd?define(["exports","htmlparser2"],h):(u=typeof globalThis<"u"?globalThis:u||self,h(u.FlexHtmlRender={},u.htmlparser2))})(this,(function(u,h){"use strict";const m={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",DIV:"div",ARTICLE:"article",ACTION:"action",BACKGROUND:"background"},N=[e.HEADER,e.HERO,e.BODY,e.FOOTER],p=[e.BOX,e.VERTICAL,e.ROW,e.BASELINE,e.DIV,e.ARTICLE],b=[e.TEXT,e.STRONG];function E(t){const r=Number(t);return isNaN(r)?t:r}function T(t){return t==="true"?!0:t==="false"?!1:t}function d(t){return[E,T].reduce((a,l)=>l(a),t)}function O(t){const r={type:"root",children:[]},a=[r],l=new h.Parser({onopentag(n,f){const g={type:m.ELEMENT,tagName:n,attributes:Object.fromEntries(Object.entries(f).map(([R,x])=>[R,d(x)])),children:[]};a[a.length-1].children.push(g),a.push(g)},ontext(n){n.trim()&&a[a.length-1].children.push({type:m.TEXT,content:n.replace(/\n/g,"").trim()})},onclosetag(){a.pop()},onerror(n){console.error("解析錯誤:",n)}},{xmlMode:!0,lowerCaseTags:!1,lowerCaseAttributeNames:!1});return l.write(t),l.end(),r.children}const s=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}),uri:(t={})=>({type:"uri",altUri:t.altUri?{desktop:t.altUri}:void 0,...t})};function A(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 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&&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 B(t){!b.includes(t.tagName)&&t.children?.some(n=>n.type===m.TEXT)&&s("Span component only allowed inside Text component"),t.tagName===e.VIDEO&&t.children?.some(n=>![e.BOX,e.IMAGE].includes(n.tagName))&&s("Video component only allowed Box or Image as altContent child"),!p.includes(t.tagName)&&t.children?.some(n=>n.tagName===e.BACKGROUND)&&s("Only Box component allowed to have Background child")}function i(t){t.attributes=t.attributes||{},B(t);const r=y(t);r&&(t.attributes.action=i(r));const a=A(t);if(a&&(t.attributes.background=i(a)),t.type===m.TEXT)return c.span(t.content,t.attributes);if(t.tagName===e.BUBBLE){const l=t.children.find(o=>o.tagName===e.HEADER),n=t.children.find(o=>o.tagName===e.HERO),f=t.children.find(o=>o.tagName===e.BODY),g=t.children.find(o=>o.tagName===e.FOOTER);return c.bubble({...t.attributes,header:l?i(l):void 0,hero:n?i(n):void 0,body:f?i(f):void 0,footer:g?i(g):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"),c.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"),c.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===m.TEXT)return c.span(l.content,t.attributes);s("Span component only allowed text child")}if(t.tagName===e.TEXT)return c.text(t.children.map(i),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&&s("Video component should only has one Box or Image as altContent"),t.attributes.altContent=i(t.children[0]),c.video(t.attributes);if(t.tagName===e.ICON)return c.icon(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(i),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",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 c.uri(t.attributes);if(t.tagName===e.BACKGROUND)return t.attributes}function C(t){try{return O(t).map(i)}catch(r){throw console.error("Error converting HTML to Flex Message:",r),r}}u.default=C,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
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.2",
4
4
  "description": "將 HTML 字串轉換為 LINE Flex Message JSON 結構的工具",
5
5
  "type": "module",
6
6
  "main": "dist/flex-html-render.cjs.js",