flex-html-render 1.1.2 → 1.1.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.
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const Q=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",STYLE:"style"},D=[e.HEADER,e.HERO,e.BODY,e.FOOTER],k=[e.BOX,e.VERTICAL,e.ROW,e.BASELINE,e.DIV,e.ARTICLE],Z=[e.TEXT,e.STRONG];function tt(t,r){if(new Set(["flex","maxLines"]).has(t)){const i=Number(r);return isNaN(i)?r:i}return r}function et(t,r){return r==="true"?!0:r==="false"?!1:r}function rt(t,r){return[tt,et].reduce((i,o)=>o(t,i),r)}function at(t){const r={type:"root",children:[]},n=[r],i=new Q.Parser({onopentag(o,s){const a={type:E.ELEMENT,tagName:o,attributes:Object.fromEntries(Object.entries(s).map(([c,b])=>[c,rt(c,b)])),children:[]};n[n.length-1].children.push(a),n.push(a)},ontext(o){const s=n[n.length-1];if(s.tagName==="span"){s.children.push({type:E.TEXT,content:o});return}o.trim()&&s.children.push({type:E.TEXT,content:o.replace(/\n/g,"").trim()})},onclosetag(){n.pop()},onerror(o){console.error("解析錯誤:",o)}},{xmlMode:!0,lowerCaseTags:!1,lowerCaseAttributeNames:!1});return i.write(t),i.end(),r.children}const m=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}),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 nt(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&&m("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 it(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&&m("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 st(t){![...Z,e.SPAN].includes(t.tagName)&&t.children?.some(a=>a.type===E.TEXT)&&m("Span component only allowed inside Text component"),t.tagName===e.VIDEO&&t.children?.some(a=>![e.BOX,e.IMAGE].includes(a.tagName))&&m("Video component only allowed Box or Image as altContent child"),!k.includes(t.tagName)&&t.children?.some(a=>a.tagName===e.BACKGROUND)&&m("Only Box component allowed to have Background child"),!k.includes(t.tagName)&&Object.keys(t.attributes||{}).some(a=>a.startsWith("padding"))&&m(`Padding property is not supported in ${t.tagName} component`),!D.includes(t.tagName)&&t.children?.filter(a=>a.tagName===e.STYLE).length>=1&&m("Only top-level section(header, hero, body, footer) can have Style child")}function d(t){if(t){const r=t.children.find(n=>n.tagName===e.STYLE);if(r)return t.children=t.children.filter(n=>n.tagName!==e.STYLE),r.attributes}}function u(t){t.attributes=t.attributes||{},st(t);const r=it(t);r&&(t.attributes.action=u(r));const n=nt(t);if(n&&(t.attributes.background=u(n)),t.type===E.TEXT)return l.span(t.content,t.attributes);if(t.tagName===e.BUBBLE){const i=t.children.find(c=>c.tagName===e.HEADER),o=t.children.find(c=>c.tagName===e.HERO),s=t.children.find(c=>c.tagName===e.BODY),a=t.children.find(c=>c.tagName===e.FOOTER),p={header:d(i),hero:d(o),body:d(s),footer:d(a)};return l.bubble({...t.attributes,header:i?u(i):void 0,hero:o?u(o):void 0,body:s?u(s):void 0,footer:a?u(a):void 0,styles:Object.values(p).some(c=>c!==void 0)?p:void 0})}if(t.tagName===e.CAROUSEL)return t.children.some(i=>i.tagName!==e.BUBBLE)&&m("Carousel can only have Bubble as children"),t.children.length>12&&m("Carousel can have maximum 12 bubbles"),l.carousel(t.children.map(u));if(D.includes(t.tagName))return t.children.length!==1&&m(`${t.tagName} should have exactly one child node`),u(t.children[0]);if(t.tagName===e.BUTTON)return t.attributes.action||m("Button component should contain an action node"),l.button(t.attributes);if(t.tagName===e.SPAN){t.children.length>1&&m("Span component can only have one text child");const i=t.children[0];if(i&&i.type===E.TEXT)return l.span(i.content,t.attributes);m(i?"Span component only allowed text child":"Span component can not be empty")}if(t.tagName===e.TEXT)return l.text(t.children.map(u),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&&m("Video component should only has one Box or Image as altContent"),t.attributes.altContent=u(t.children[0]),l.video(t.attributes);if(t.tagName===e.ICON)return l.icon(t.attributes);if(t.tagName===e.FILLER)return l.filler(t.attributes);if(t.tagName===e.BOX||t.tagName===e.DIV||t.tagName===e.ARTICLE)return t.attributes.layout||(t.attributes.layout="vertical"),l.box(t.children.map(u),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",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 i=t.attributes.type;switch(i){case"uri":return l.uri(t.attributes);case"postback":return l.postback(t.attributes);case"message":return l.message(t.attributes);case"datetimepicker":return l.datetimepicker(t.attributes);case"camera":return l.camera(t.attributes);case"cameraRoll":return l.cameraRoll(t.attributes);case"location":return l.location(t.attributes);case"richmenuswitch":return l.richmenuswitch(t.attributes);case"clipboard":return l.clipboard(t.attributes);default:m(`Unsupported action type: ${i}`)}}if(t.tagName===e.BACKGROUND)return t.attributes}const h={createElement:(t,r={},n=[],i=0)=>{const s=Object.entries(r).filter(([p,c])=>c!=null).map(([p,c])=>typeof c=="object"?`${p}="${JSON.stringify(c).replace(/"/g,""")}"`:`${p}="${c}"`).join(" "),a=s?` ${s}`:"";if(n.length===0)return` <${t}${a} />`;{const p=n.map(c=>typeof c=="string"?c.split(`
|
|
2
2
|
`).map(b=>b?" "+b:"").join(`
|
|
3
|
-
`):
|
|
4
|
-
`);return` <${t}${
|
|
3
|
+
`):c).join(`
|
|
4
|
+
`);return` <${t}${a}>
|
|
5
5
|
${p}
|
|
6
|
-
</${t}>`}},createText:t=>t},
|
|
6
|
+
</${t}>`}},createText:t=>t},O=(t,r,n,i)=>{const o=[f(r,i+1)];return n&&Object.keys(n).length>0&&o.unshift(f(X("style",n),i+1)),h.createElement(t,{},o,i)},X=(t,r)=>({...r,type:t});function f(t,r=0){if(!t||typeof t!="object")return"";const{type:n,...i}=t,{action:o,...s}=i,a=o?f(o,r+1):"";switch(n){case"carousel":const{contents:p,...c}=s,b=p.map(N=>f(N,r+1));return a&&b.unshift(a),h.createElement(e.CAROUSEL,c,b,r);case"bubble":const{header:R,hero:B,body:S,footer:x,styles:y={},...$}=s,g=[];return a&&g.push(a),R&&g.push(O(e.HEADER,R,y.header,r+1)),B&&g.push(O(e.HERO,B,y.hero,r+1)),S&&g.push(O(e.BODY,S,y.body,r+1)),x&&g.push(O(e.FOOTER,x,y.footer,r+1)),h.createElement(e.BUBBLE,$,g,r);case"box":const{contents:P,background:v,...A}=s;A.layout||(A.layout="vertical");const T=[];return a&&T.push(a),v&&T.push(f(X("background",v),r+1)),T.push(...(P||[]).map(N=>f(N,r+1))),h.createElement(e.BOX,A,T,r);case"text":const{text:H,contents:C,...G}=s,I=C&&C.length>0?C.map(N=>f(N,r+1)):[H||""];return a&&I.unshift(a),h.createElement(e.TEXT,G,I,r);case"span":const{text:M,...F}=s,L=[M||""];return a&&L.unshift(a),h.createElement(e.SPAN,F,L,r);case"image":const{...V}=s,j=a?[a]:[];return h.createElement(e.IMAGE,V,j,r);case"video":const{altContent:w,...K}=s,U=w?[f(w,r+1)]:[];return a&&U.unshift(a),h.createElement(e.VIDEO,K,U,r);case"icon":const{...Y}=s,W=a?[a]:[];return h.createElement(e.ICON,Y,W,r);case"button":const{...J}=s,q=a?[a]:[];return h.createElement(e.BUTTON,J,q,r);case"separator":const z=a?[a]:[];return h.createElement(e.SEPARATOR,s,z,r);case"filler":const _=a?[a]:[];return h.createElement(e.FILLER,s,_,r);case"uri":case"message":case"postback":case"datetimepicker":case"camera":case"cameraRoll":case"location":case"richmenuswitch":case"clipboard":return h.createElement(e.ACTION,{type:n,...s},[],r);case"background":return h.createElement(e.BACKGROUND,s,[],r);case"style":return h.createElement(e.STYLE,s,[],r);default:return""}}function ct(t){try{return at(t).map(u)}catch(r){throw console.error("Error converting HTML to Flex Message:",r),r}}exports.convertJsonToHtml=f;exports.default=ct;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Parser as
|
|
1
|
+
import { Parser as Z } from "htmlparser2";
|
|
2
2
|
const E = {
|
|
3
3
|
ELEMENT: "element",
|
|
4
4
|
TEXT: "text"
|
|
@@ -39,7 +39,7 @@ const E = {
|
|
|
39
39
|
e.HERO,
|
|
40
40
|
e.BODY,
|
|
41
41
|
e.FOOTER
|
|
42
|
-
],
|
|
42
|
+
], k = [
|
|
43
43
|
e.BOX,
|
|
44
44
|
e.VERTICAL,
|
|
45
45
|
e.ROW,
|
|
@@ -50,43 +50,46 @@ const E = {
|
|
|
50
50
|
e.TEXT,
|
|
51
51
|
e.STRONG
|
|
52
52
|
];
|
|
53
|
-
function tt(t) {
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
function tt(t, r) {
|
|
54
|
+
if ((/* @__PURE__ */ new Set(["flex", "maxLines"])).has(t)) {
|
|
55
|
+
const i = Number(r);
|
|
56
|
+
return isNaN(i) ? r : i;
|
|
57
|
+
}
|
|
58
|
+
return r;
|
|
56
59
|
}
|
|
57
|
-
function et(t) {
|
|
58
|
-
return
|
|
60
|
+
function et(t, r) {
|
|
61
|
+
return r === "true" ? !0 : r === "false" ? !1 : r;
|
|
59
62
|
}
|
|
60
|
-
function rt(t) {
|
|
63
|
+
function rt(t, r) {
|
|
61
64
|
return [
|
|
62
65
|
tt,
|
|
63
66
|
et
|
|
64
|
-
].reduce((
|
|
67
|
+
].reduce((i, o) => o(t, i), r);
|
|
65
68
|
}
|
|
66
69
|
function at(t) {
|
|
67
|
-
const r = { type: "root", children: [] }, n = [r],
|
|
70
|
+
const r = { type: "root", children: [] }, n = [r], i = new Z(
|
|
68
71
|
{
|
|
69
|
-
onopentag(o,
|
|
70
|
-
const
|
|
72
|
+
onopentag(o, c) {
|
|
73
|
+
const a = {
|
|
71
74
|
type: E.ELEMENT,
|
|
72
75
|
tagName: o,
|
|
73
76
|
attributes: Object.fromEntries(
|
|
74
|
-
Object.entries(
|
|
77
|
+
Object.entries(c).map(([s, b]) => [s, rt(s, b)])
|
|
75
78
|
),
|
|
76
79
|
children: []
|
|
77
80
|
};
|
|
78
|
-
n[n.length - 1].children.push(
|
|
81
|
+
n[n.length - 1].children.push(a), n.push(a);
|
|
79
82
|
},
|
|
80
83
|
ontext(o) {
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
+
const c = n[n.length - 1];
|
|
85
|
+
if (c.tagName === "span") {
|
|
86
|
+
c.children.push({
|
|
84
87
|
type: E.TEXT,
|
|
85
88
|
content: o
|
|
86
89
|
});
|
|
87
90
|
return;
|
|
88
91
|
}
|
|
89
|
-
o.trim() &&
|
|
92
|
+
o.trim() && c.children.push({
|
|
90
93
|
type: E.TEXT,
|
|
91
94
|
content: o.replace(/\n/g, "").trim()
|
|
92
95
|
});
|
|
@@ -106,9 +109,9 @@ function at(t) {
|
|
|
106
109
|
lowerCaseAttributeNames: !1
|
|
107
110
|
}
|
|
108
111
|
);
|
|
109
|
-
return
|
|
112
|
+
return i.write(t), i.end(), r.children;
|
|
110
113
|
}
|
|
111
|
-
const
|
|
114
|
+
const m = (t) => {
|
|
112
115
|
throw Error(`[Flex Html Render]: ${t}`);
|
|
113
116
|
}, l = {
|
|
114
117
|
carousel: (t) => ({
|
|
@@ -203,21 +206,21 @@ const h = (t) => {
|
|
|
203
206
|
function nt(t) {
|
|
204
207
|
if (t.tagName !== e.BACKGROUND && t.children && t.children.length > 0) {
|
|
205
208
|
const r = t.children.filter((n) => n.tagName === e.BACKGROUND);
|
|
206
|
-
return r.length > 1 &&
|
|
209
|
+
return r.length > 1 && m("A box node can only allowed with one background node inside"), t.children = t.children.filter((n) => n.tagName !== e.BACKGROUND), r[0];
|
|
207
210
|
}
|
|
208
211
|
return null;
|
|
209
212
|
}
|
|
210
213
|
function it(t) {
|
|
211
214
|
if (t.tagName !== e.ACTION && t.children && t.children.length > 0) {
|
|
212
215
|
const r = t.children.filter((n) => n.tagName === e.ACTION);
|
|
213
|
-
return r.length > 1 &&
|
|
216
|
+
return r.length > 1 && m("A node can only allowed with one action node inside"), t.children = t.children.filter((n) => n.tagName !== e.ACTION), r[0];
|
|
214
217
|
}
|
|
215
218
|
return null;
|
|
216
219
|
}
|
|
217
220
|
function ct(t) {
|
|
218
|
-
![..._, e.SPAN].includes(t.tagName) && t.children?.some((a) => a.type === E.TEXT) &&
|
|
221
|
+
![..._, e.SPAN].includes(t.tagName) && t.children?.some((a) => a.type === E.TEXT) && m("Span component only allowed inside Text component"), t.tagName === e.VIDEO && t.children?.some((a) => ![e.BOX, e.IMAGE].includes(a.tagName)) && m("Video component only allowed Box or Image as altContent child"), !k.includes(t.tagName) && t.children?.some((a) => a.tagName === e.BACKGROUND) && m("Only Box component allowed to have Background child"), !k.includes(t.tagName) && Object.keys(t.attributes || {}).some((a) => a.startsWith("padding")) && m(`Padding property is not supported in ${t.tagName} component`), !D.includes(t.tagName) && t.children?.filter((a) => a.tagName === e.STYLE).length >= 1 && m("Only top-level section(header, hero, body, footer) can have Style child");
|
|
219
222
|
}
|
|
220
|
-
function
|
|
223
|
+
function d(t) {
|
|
221
224
|
if (t) {
|
|
222
225
|
const r = t.children.find((n) => n.tagName === e.STYLE);
|
|
223
226
|
if (r)
|
|
@@ -232,38 +235,38 @@ function u(t) {
|
|
|
232
235
|
if (n && (t.attributes.background = u(n)), t.type === E.TEXT)
|
|
233
236
|
return l.span(t.content, t.attributes);
|
|
234
237
|
if (t.tagName === e.BUBBLE) {
|
|
235
|
-
const
|
|
236
|
-
header:
|
|
237
|
-
hero:
|
|
238
|
-
body:
|
|
239
|
-
footer:
|
|
238
|
+
const i = t.children.find((s) => s.tagName === e.HEADER), o = t.children.find((s) => s.tagName === e.HERO), c = t.children.find((s) => s.tagName === e.BODY), a = t.children.find((s) => s.tagName === e.FOOTER), p = {
|
|
239
|
+
header: d(i),
|
|
240
|
+
hero: d(o),
|
|
241
|
+
body: d(c),
|
|
242
|
+
footer: d(a)
|
|
240
243
|
};
|
|
241
244
|
return l.bubble({
|
|
242
245
|
...t.attributes,
|
|
243
|
-
header:
|
|
246
|
+
header: i ? u(i) : void 0,
|
|
244
247
|
hero: o ? u(o) : void 0,
|
|
245
|
-
body:
|
|
246
|
-
footer:
|
|
248
|
+
body: c ? u(c) : void 0,
|
|
249
|
+
footer: a ? u(a) : void 0,
|
|
247
250
|
styles: Object.values(p).some((s) => s !== void 0) ? p : void 0
|
|
248
251
|
});
|
|
249
252
|
}
|
|
250
253
|
if (t.tagName === e.CAROUSEL)
|
|
251
|
-
return t.children.some((
|
|
254
|
+
return t.children.some((i) => i.tagName !== e.BUBBLE) && m("Carousel can only have Bubble as children"), t.children.length > 12 && m("Carousel can have maximum 12 bubbles"), l.carousel(
|
|
252
255
|
t.children.map(u)
|
|
253
256
|
);
|
|
254
257
|
if (D.includes(t.tagName))
|
|
255
|
-
return t.children.length !== 1 &&
|
|
258
|
+
return t.children.length !== 1 && m(`${t.tagName} should have exactly one child node`), u(t.children[0]);
|
|
256
259
|
if (t.tagName === e.BUTTON)
|
|
257
|
-
return t.attributes.action ||
|
|
260
|
+
return t.attributes.action || m("Button component should contain an action node"), l.button(t.attributes);
|
|
258
261
|
if (t.tagName === e.SPAN) {
|
|
259
|
-
t.children.length > 1 &&
|
|
260
|
-
const
|
|
261
|
-
if (
|
|
262
|
+
t.children.length > 1 && m("Span component can only have one text child");
|
|
263
|
+
const i = t.children[0];
|
|
264
|
+
if (i && i.type === E.TEXT)
|
|
262
265
|
return l.span(
|
|
263
|
-
|
|
266
|
+
i.content,
|
|
264
267
|
t.attributes
|
|
265
268
|
);
|
|
266
|
-
|
|
269
|
+
m(i ? "Span component only allowed text child" : "Span component can not be empty");
|
|
267
270
|
}
|
|
268
271
|
if (t.tagName === e.TEXT)
|
|
269
272
|
return l.text(
|
|
@@ -275,7 +278,7 @@ function u(t) {
|
|
|
275
278
|
if (t.tagName === e.IMAGE)
|
|
276
279
|
return l.image(t.attributes);
|
|
277
280
|
if (t.tagName === e.VIDEO)
|
|
278
|
-
return t.children.length !== 1 &&
|
|
281
|
+
return t.children.length !== 1 && m("Video component should only has one Box or Image as altContent"), t.attributes.altContent = u(t.children[0]), l.video(t.attributes);
|
|
279
282
|
if (t.tagName === e.ICON)
|
|
280
283
|
return l.icon(t.attributes);
|
|
281
284
|
if (t.tagName === e.FILLER)
|
|
@@ -296,8 +299,8 @@ function u(t) {
|
|
|
296
299
|
if (t.tagName === e.VERTICAL)
|
|
297
300
|
return t.tagName = e.BOX, t.attributes.layout = "vertical", u(t);
|
|
298
301
|
if (t.tagName === e.ACTION) {
|
|
299
|
-
const
|
|
300
|
-
switch (
|
|
302
|
+
const i = t.attributes.type;
|
|
303
|
+
switch (i) {
|
|
301
304
|
case "uri":
|
|
302
305
|
return l.uri(t.attributes);
|
|
303
306
|
case "postback":
|
|
@@ -317,72 +320,72 @@ function u(t) {
|
|
|
317
320
|
case "clipboard":
|
|
318
321
|
return l.clipboard(t.attributes);
|
|
319
322
|
default:
|
|
320
|
-
|
|
323
|
+
m(`Unsupported action type: ${i}`);
|
|
321
324
|
}
|
|
322
325
|
}
|
|
323
326
|
if (t.tagName === e.BACKGROUND)
|
|
324
327
|
return t.attributes;
|
|
325
328
|
}
|
|
326
|
-
const
|
|
327
|
-
createElement: (t, r = {}, n = [],
|
|
328
|
-
const
|
|
329
|
+
const h = {
|
|
330
|
+
createElement: (t, r = {}, n = [], i = 0) => {
|
|
331
|
+
const c = Object.entries(r).filter(([p, s]) => s != null).map(([p, s]) => typeof s == "object" ? `${p}="${JSON.stringify(s).replace(/"/g, """)}"` : `${p}="${s}"`).join(" "), a = c ? ` ${c}` : "";
|
|
329
332
|
if (n.length === 0)
|
|
330
|
-
return ` <${t}${
|
|
333
|
+
return ` <${t}${a} />`;
|
|
331
334
|
{
|
|
332
335
|
const p = n.map((s) => typeof s == "string" ? s.split(`
|
|
333
336
|
`).map((b) => b ? " " + b : "").join(`
|
|
334
337
|
`) : s).join(`
|
|
335
338
|
`);
|
|
336
|
-
return ` <${t}${
|
|
339
|
+
return ` <${t}${a}>
|
|
337
340
|
${p}
|
|
338
341
|
</${t}>`;
|
|
339
342
|
}
|
|
340
343
|
},
|
|
341
344
|
createText: (t) => t
|
|
342
|
-
},
|
|
343
|
-
const o = [f(r,
|
|
344
|
-
return n && Object.keys(n).length > 0 && o.unshift(f(
|
|
345
|
-
},
|
|
345
|
+
}, O = (t, r, n, i) => {
|
|
346
|
+
const o = [f(r, i + 1)];
|
|
347
|
+
return n && Object.keys(n).length > 0 && o.unshift(f(X("style", n), i + 1)), h.createElement(t, {}, o, i);
|
|
348
|
+
}, X = (t, r) => ({ ...r, type: t });
|
|
346
349
|
function f(t, r = 0) {
|
|
347
350
|
if (!t || typeof t != "object")
|
|
348
351
|
return "";
|
|
349
|
-
const { type: n, ...
|
|
352
|
+
const { type: n, ...i } = t, { action: o, ...c } = i, a = o ? f(o, r + 1) : "";
|
|
350
353
|
switch (n) {
|
|
351
354
|
case "carousel":
|
|
352
|
-
const { contents: p, ...s } =
|
|
353
|
-
return
|
|
355
|
+
const { contents: p, ...s } = c, b = p.map((N) => f(N, r + 1));
|
|
356
|
+
return a && b.unshift(a), h.createElement(e.CAROUSEL, s, b, r);
|
|
354
357
|
case "bubble":
|
|
355
|
-
const { header: R, hero: B, body: S, footer: x, styles:
|
|
356
|
-
return
|
|
358
|
+
const { header: R, hero: B, body: S, footer: x, styles: y = {}, ...$ } = c, g = [];
|
|
359
|
+
return a && g.push(a), R && g.push(O(e.HEADER, R, y.header, r + 1)), B && g.push(O(e.HERO, B, y.hero, r + 1)), S && g.push(O(e.BODY, S, y.body, r + 1)), x && g.push(O(e.FOOTER, x, y.footer, r + 1)), h.createElement(e.BUBBLE, $, g, r);
|
|
357
360
|
case "box":
|
|
358
|
-
const { contents:
|
|
359
|
-
|
|
360
|
-
const
|
|
361
|
-
return
|
|
361
|
+
const { contents: P, background: I, ...A } = c;
|
|
362
|
+
A.layout || (A.layout = "vertical");
|
|
363
|
+
const T = [];
|
|
364
|
+
return a && T.push(a), I && T.push(f(X("background", I), r + 1)), T.push(...(P || []).map((N) => f(N, r + 1))), h.createElement(e.BOX, A, T, r);
|
|
362
365
|
case "text":
|
|
363
|
-
const { text: G, contents: C, ...H } =
|
|
364
|
-
return
|
|
366
|
+
const { text: G, contents: C, ...H } = c, v = C && C.length > 0 ? C.map((N) => f(N, r + 1)) : [G || ""];
|
|
367
|
+
return a && v.unshift(a), h.createElement(e.TEXT, H, v, r);
|
|
365
368
|
case "span":
|
|
366
|
-
const { text: F, ...V } =
|
|
367
|
-
return
|
|
369
|
+
const { text: F, ...V } = c, L = [F || ""];
|
|
370
|
+
return a && L.unshift(a), h.createElement(e.SPAN, V, L, r);
|
|
368
371
|
case "image":
|
|
369
|
-
const { ...M } =
|
|
370
|
-
return
|
|
372
|
+
const { ...M } = c, j = a ? [a] : [];
|
|
373
|
+
return h.createElement(e.IMAGE, M, j, r);
|
|
371
374
|
case "video":
|
|
372
|
-
const { altContent: w, ...
|
|
373
|
-
return
|
|
375
|
+
const { altContent: w, ...K } = c, U = w ? [f(w, r + 1)] : [];
|
|
376
|
+
return a && U.unshift(a), h.createElement(e.VIDEO, K, U, r);
|
|
374
377
|
case "icon":
|
|
375
|
-
const { ...
|
|
376
|
-
return
|
|
378
|
+
const { ...Y } = c, W = a ? [a] : [];
|
|
379
|
+
return h.createElement(e.ICON, Y, W, r);
|
|
377
380
|
case "button":
|
|
378
|
-
const { ...
|
|
379
|
-
return
|
|
381
|
+
const { ...J } = c, z = a ? [a] : [];
|
|
382
|
+
return h.createElement(e.BUTTON, J, z, r);
|
|
380
383
|
case "separator":
|
|
381
|
-
const
|
|
382
|
-
return
|
|
384
|
+
const q = a ? [a] : [];
|
|
385
|
+
return h.createElement(e.SEPARATOR, c, q, r);
|
|
383
386
|
case "filler":
|
|
384
|
-
const
|
|
385
|
-
return
|
|
387
|
+
const Q = a ? [a] : [];
|
|
388
|
+
return h.createElement(e.FILLER, c, Q, r);
|
|
386
389
|
// Action types
|
|
387
390
|
case "uri":
|
|
388
391
|
case "message":
|
|
@@ -393,11 +396,11 @@ function f(t, r = 0) {
|
|
|
393
396
|
case "location":
|
|
394
397
|
case "richmenuswitch":
|
|
395
398
|
case "clipboard":
|
|
396
|
-
return
|
|
399
|
+
return h.createElement(e.ACTION, { type: n, ...c }, [], r);
|
|
397
400
|
case "background":
|
|
398
|
-
return
|
|
401
|
+
return h.createElement(e.BACKGROUND, c, [], r);
|
|
399
402
|
case "style":
|
|
400
|
-
return
|
|
403
|
+
return h.createElement(e.STYLE, c, [], r);
|
|
401
404
|
default:
|
|
402
405
|
return "";
|
|
403
406
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
(function(b,
|
|
1
|
+
(function(b,y){typeof exports=="object"&&typeof module<"u"?y(exports,require("htmlparser2")):typeof define=="function"&&define.amd?define(["exports","htmlparser2"],y):(b=typeof globalThis<"u"?globalThis:b||self,y(b.FlexHtmlRender={},b.htmlparser2))})(this,(function(b,y){"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",STYLE:"style"},S=[e.HEADER,e.HERO,e.BODY,e.FOOTER],x=[e.BOX,e.VERTICAL,e.ROW,e.BASELINE,e.DIV,e.ARTICLE],H=[e.TEXT,e.STRONG];function G(t,r){if(new Set(["flex","maxLines"]).has(t)){const i=Number(r);return isNaN(i)?r:i}return r}function F(t,r){return r==="true"?!0:r==="false"?!1:r}function M(t,r){return[G,F].reduce((i,o)=>o(t,i),r)}function V(t){const r={type:"root",children:[]},n=[r],i=new y.Parser({onopentag(o,s){const a={type:E.ELEMENT,tagName:o,attributes:Object.fromEntries(Object.entries(s).map(([c,g])=>[c,M(c,g)])),children:[]};n[n.length-1].children.push(a),n.push(a)},ontext(o){const s=n[n.length-1];if(s.tagName==="span"){s.children.push({type:E.TEXT,content:o});return}o.trim()&&s.children.push({type:E.TEXT,content:o.replace(/\n/g,"").trim()})},onclosetag(){n.pop()},onerror(o){console.error("解析錯誤:",o)}},{xmlMode:!0,lowerCaseTags:!1,lowerCaseAttributeNames:!1});return i.write(t),i.end(),r.children}const u=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}),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 j(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&&u("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 K(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&&u("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 Y(t){![...H,e.SPAN].includes(t.tagName)&&t.children?.some(a=>a.type===E.TEXT)&&u("Span component only allowed inside Text component"),t.tagName===e.VIDEO&&t.children?.some(a=>![e.BOX,e.IMAGE].includes(a.tagName))&&u("Video component only allowed Box or Image as altContent child"),!x.includes(t.tagName)&&t.children?.some(a=>a.tagName===e.BACKGROUND)&&u("Only Box component allowed to have Background child"),!x.includes(t.tagName)&&Object.keys(t.attributes||{}).some(a=>a.startsWith("padding"))&&u(`Padding property is not supported in ${t.tagName} component`),!S.includes(t.tagName)&&t.children?.filter(a=>a.tagName===e.STYLE).length>=1&&u("Only top-level section(header, hero, body, footer) can have Style child")}function T(t){if(t){const r=t.children.find(n=>n.tagName===e.STYLE);if(r)return t.children=t.children.filter(n=>n.tagName!==e.STYLE),r.attributes}}function m(t){t.attributes=t.attributes||{},Y(t);const r=K(t);r&&(t.attributes.action=m(r));const n=j(t);if(n&&(t.attributes.background=m(n)),t.type===E.TEXT)return l.span(t.content,t.attributes);if(t.tagName===e.BUBBLE){const i=t.children.find(c=>c.tagName===e.HEADER),o=t.children.find(c=>c.tagName===e.HERO),s=t.children.find(c=>c.tagName===e.BODY),a=t.children.find(c=>c.tagName===e.FOOTER),p={header:T(i),hero:T(o),body:T(s),footer:T(a)};return l.bubble({...t.attributes,header:i?m(i):void 0,hero:o?m(o):void 0,body:s?m(s):void 0,footer:a?m(a):void 0,styles:Object.values(p).some(c=>c!==void 0)?p:void 0})}if(t.tagName===e.CAROUSEL)return t.children.some(i=>i.tagName!==e.BUBBLE)&&u("Carousel can only have Bubble as children"),t.children.length>12&&u("Carousel can have maximum 12 bubbles"),l.carousel(t.children.map(m));if(S.includes(t.tagName))return t.children.length!==1&&u(`${t.tagName} should have exactly one child node`),m(t.children[0]);if(t.tagName===e.BUTTON)return t.attributes.action||u("Button component should contain an action node"),l.button(t.attributes);if(t.tagName===e.SPAN){t.children.length>1&&u("Span component can only have one text child");const i=t.children[0];if(i&&i.type===E.TEXT)return l.span(i.content,t.attributes);u(i?"Span component only allowed text child":"Span component can not be empty")}if(t.tagName===e.TEXT)return l.text(t.children.map(m),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&&u("Video component should only has one Box or Image as altContent"),t.attributes.altContent=m(t.children[0]),l.video(t.attributes);if(t.tagName===e.ICON)return l.icon(t.attributes);if(t.tagName===e.FILLER)return l.filler(t.attributes);if(t.tagName===e.BOX||t.tagName===e.DIV||t.tagName===e.ARTICLE)return t.attributes.layout||(t.attributes.layout="vertical"),l.box(t.children.map(m),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",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 i=t.attributes.type;switch(i){case"uri":return l.uri(t.attributes);case"postback":return l.postback(t.attributes);case"message":return l.message(t.attributes);case"datetimepicker":return l.datetimepicker(t.attributes);case"camera":return l.camera(t.attributes);case"cameraRoll":return l.cameraRoll(t.attributes);case"location":return l.location(t.attributes);case"richmenuswitch":return l.richmenuswitch(t.attributes);case"clipboard":return l.clipboard(t.attributes);default:u(`Unsupported action type: ${i}`)}}if(t.tagName===e.BACKGROUND)return t.attributes}const h={createElement:(t,r={},n=[],i=0)=>{const s=Object.entries(r).filter(([p,c])=>c!=null).map(([p,c])=>typeof c=="object"?`${p}="${JSON.stringify(c).replace(/"/g,""")}"`:`${p}="${c}"`).join(" "),a=s?` ${s}`:"";if(n.length===0)return` <${t}${a} />`;{const p=n.map(c=>typeof c=="string"?c.split(`
|
|
2
2
|
`).map(g=>g?" "+g:"").join(`
|
|
3
|
-
`):
|
|
4
|
-
`);return` <${t}${
|
|
5
|
-
${
|
|
6
|
-
</${t}>`}},createText:t=>t},O=(t,r,n,
|
|
3
|
+
`):c).join(`
|
|
4
|
+
`);return` <${t}${a}>
|
|
5
|
+
${p}
|
|
6
|
+
</${t}>`}},createText:t=>t},O=(t,r,n,i)=>{const o=[f(r,i+1)];return n&&Object.keys(n).length>0&&o.unshift(f(v("style",n),i+1)),h.createElement(t,{},o,i)},v=(t,r)=>({...r,type:t});function f(t,r=0){if(!t||typeof t!="object")return"";const{type:n,...i}=t,{action:o,...s}=i,a=o?f(o,r+1):"";switch(n){case"carousel":const{contents:p,...c}=s,g=p.map(d=>f(d,r+1));return a&&g.unshift(a),h.createElement(e.CAROUSEL,c,g,r);case"bubble":const{header:I,hero:L,body:w,footer:U,styles:A={},...J}=s,N=[];return a&&N.push(a),I&&N.push(O(e.HEADER,I,A.header,r+1)),L&&N.push(O(e.HERO,L,A.hero,r+1)),w&&N.push(O(e.BODY,w,A.body,r+1)),U&&N.push(O(e.FOOTER,U,A.footer,r+1)),h.createElement(e.BUBBLE,J,N,r);case"box":const{contents:q,background:k,...R}=s;R.layout||(R.layout="vertical");const C=[];return a&&C.push(a),k&&C.push(f(v("background",k),r+1)),C.push(...(q||[]).map(d=>f(d,r+1))),h.createElement(e.BOX,R,C,r);case"text":const{text:z,contents:B,..._}=s,D=B&&B.length>0?B.map(d=>f(d,r+1)):[z||""];return a&&D.unshift(a),h.createElement(e.TEXT,_,D,r);case"span":const{text:Q,...Z}=s,X=[Q||""];return a&&X.unshift(a),h.createElement(e.SPAN,Z,X,r);case"image":const{...tt}=s,et=a?[a]:[];return h.createElement(e.IMAGE,tt,et,r);case"video":const{altContent:$,...rt}=s,P=$?[f($,r+1)]:[];return a&&P.unshift(a),h.createElement(e.VIDEO,rt,P,r);case"icon":const{...at}=s,nt=a?[a]:[];return h.createElement(e.ICON,at,nt,r);case"button":const{...it}=s,st=a?[a]:[];return h.createElement(e.BUTTON,it,st,r);case"separator":const ct=a?[a]:[];return h.createElement(e.SEPARATOR,s,ct,r);case"filler":const lt=a?[a]:[];return h.createElement(e.FILLER,s,lt,r);case"uri":case"message":case"postback":case"datetimepicker":case"camera":case"cameraRoll":case"location":case"richmenuswitch":case"clipboard":return h.createElement(e.ACTION,{type:n,...s},[],r);case"background":return h.createElement(e.BACKGROUND,s,[],r);case"style":return h.createElement(e.STYLE,s,[],r);default:return""}}function W(t){try{return V(t).map(m)}catch(r){throw console.error("Error converting HTML to Flex Message:",r),r}}b.convertJsonToHtml=f,b.default=W,Object.defineProperties(b,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|