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