@locdo.tech/botiq-chat-sdk 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/{npm-D7UnWA_n.js → npm-DfSKhYCq.js} +101 -17
- package/dist/sdk/react.js +1 -1
- package/dist/sdk/vue.js +1 -1
- package/package.json +19 -2
package/dist/sdk/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as e } from "./npm-
|
|
1
|
+
import { t as e } from "./npm-DfSKhYCq.js";
|
|
2
2
|
export { e as init };
|
|
@@ -65,8 +65,10 @@ async function l(e, n) {
|
|
|
65
65
|
try {
|
|
66
66
|
let r = await fetch(`${n}/widget/meta`, {
|
|
67
67
|
headers: { "X-Api-Key": e },
|
|
68
|
+
referrerPolicy: "no-referrer-when-downgrade",
|
|
68
69
|
signal: AbortSignal.timeout(5e3)
|
|
69
70
|
});
|
|
71
|
+
if (r.status === 401 || r.status === 403) return null;
|
|
70
72
|
if (!r.ok) return t;
|
|
71
73
|
let i = await r.json();
|
|
72
74
|
if (!i?.design?.colors || !i?.design?.layout || !i?.design?.content || !c(i.design)) return t;
|
|
@@ -121,6 +123,7 @@ async function _(e, t, n, r, i, a) {
|
|
|
121
123
|
"Content-Type": "application/json",
|
|
122
124
|
"X-Api-Key": t
|
|
123
125
|
},
|
|
126
|
+
referrerPolicy: "no-referrer-when-downgrade",
|
|
124
127
|
body: JSON.stringify({
|
|
125
128
|
sessionId: n,
|
|
126
129
|
message: r,
|
|
@@ -354,21 +357,60 @@ function D(e) {
|
|
|
354
357
|
|
|
355
358
|
.message { display: flex; flex-direction: column; max-width: 82%; }
|
|
356
359
|
.message.user { align-self: flex-end; align-items: flex-end; }
|
|
357
|
-
.message.assistant { align-self: flex-start; align-items: flex-start; }
|
|
360
|
+
.message.assistant { align-self: flex-start; align-items: flex-start; max-width: 92%; }
|
|
358
361
|
|
|
359
362
|
.message-bubble {
|
|
360
363
|
padding: 10px 14px;
|
|
361
364
|
border-radius: var(--radius-msg);
|
|
362
365
|
font-size: 14px;
|
|
363
366
|
line-height: 1.5;
|
|
364
|
-
white-space:
|
|
367
|
+
white-space: normal;
|
|
365
368
|
word-break: break-word;
|
|
369
|
+
overflow-x: auto;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/* ── Markdown inline elements ───────────────────────── */
|
|
373
|
+
.message-bubble strong { font-weight: 600; }
|
|
374
|
+
.message-bubble em { font-style: italic; }
|
|
375
|
+
.message-bubble a { color: var(--color-primary); text-decoration: underline; word-break: break-all; }
|
|
376
|
+
.message-bubble code {
|
|
377
|
+
font-family: monospace;
|
|
378
|
+
font-size: 12px;
|
|
379
|
+
padding: 1px 5px;
|
|
380
|
+
border-radius: 4px;
|
|
381
|
+
background: rgba(255,255,255,.1);
|
|
382
|
+
white-space: pre-wrap;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/* ── Markdown tables ─────────────────────────────────── */
|
|
386
|
+
.message-bubble table {
|
|
387
|
+
border-collapse: collapse;
|
|
388
|
+
min-width: 100%;
|
|
389
|
+
font-size: 12.5px;
|
|
390
|
+
display: block;
|
|
391
|
+
overflow-x: auto;
|
|
392
|
+
margin: 4px 0;
|
|
393
|
+
}
|
|
394
|
+
.message-bubble th,
|
|
395
|
+
.message-bubble td {
|
|
396
|
+
border: 1px solid rgba(255,255,255,.15);
|
|
397
|
+
padding: 5px 10px;
|
|
398
|
+
text-align: left;
|
|
366
399
|
}
|
|
400
|
+
.message-bubble th { background: rgba(255,255,255,.08); font-weight: 600; white-space: nowrap; }
|
|
401
|
+
.message-bubble td { white-space: normal; }
|
|
402
|
+
.message-bubble tr:nth-child(even) td { background: rgba(255,255,255,.04); }
|
|
403
|
+
|
|
404
|
+
/* ── Markdown lists ──────────────────────────────────── */
|
|
405
|
+
.message-bubble ul,
|
|
406
|
+
.message-bubble ol { padding-left: 18px; margin: 2px 0; }
|
|
407
|
+
.message-bubble li { margin: 2px 0; }
|
|
367
408
|
|
|
368
409
|
.message.user .message-bubble {
|
|
369
410
|
background: ${h};
|
|
370
411
|
color: #fff;
|
|
371
412
|
border-bottom-right-radius: 4px;
|
|
413
|
+
white-space: pre-wrap;
|
|
372
414
|
}
|
|
373
415
|
|
|
374
416
|
.message.assistant .message-bubble {
|
|
@@ -538,13 +580,51 @@ function F(e) {
|
|
|
538
580
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
539
581
|
}
|
|
540
582
|
function I(e) {
|
|
541
|
-
let t =
|
|
542
|
-
return
|
|
583
|
+
let t = [];
|
|
584
|
+
return e = e.replace(/`([^`]+)`/g, (e, n) => (t.push(`<code>${n}</code>`), `\x00CODE${t.length - 1}\x00`)), e = e.replace(/\*\*\*(.+?)\*\*\*/g, "<strong><em>$1</em></strong>"), e = e.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>"), e = e.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<em>$1</em>"), e = e.replace(/\[([^\]]+)\]\(([^()]*(?:\([^()]*\))*[^()]*)\)/g, (e, t, n) => /^https?:\/\//.test(n) ? `<a href="${n}" target="_blank" rel="noopener noreferrer">${t}</a>` : t), e = e.replace(/\x00CODE(\d+)\x00/g, (e, n) => t[Number(n)]), e;
|
|
585
|
+
}
|
|
586
|
+
function L(e) {
|
|
587
|
+
return /^\|[\s\-:|]+\|$/.test(e);
|
|
588
|
+
}
|
|
589
|
+
function R(e) {
|
|
590
|
+
return e.replace(/^\|/, "").replace(/\|$/, "").split("|").map((e) => e.trim());
|
|
591
|
+
}
|
|
592
|
+
function z(e) {
|
|
593
|
+
let t = F(e).replace(/\x00/g, "").split("\n"), n = [], r = 0;
|
|
594
|
+
for (; r < t.length;) {
|
|
595
|
+
let e = t[r].trim();
|
|
596
|
+
if (e.startsWith("|") && e.endsWith("|")) {
|
|
597
|
+
let e = [];
|
|
598
|
+
for (; r < t.length && t[r].trim().startsWith("|") && t[r].trim().endsWith("|");) e.push(t[r].trim()), r++;
|
|
599
|
+
let i = e.findIndex(L), a = i > 0 ? e.slice(0, i) : [], o = i >= 0 ? e.slice(i + 1) : e, s = "<table>";
|
|
600
|
+
a.length > 0 && (s += "<thead>" + a.map((e) => "<tr>" + R(e).map((e) => `<th>${I(e)}</th>`).join("") + "</tr>").join("") + "</thead>"), o.length > 0 && (s += "<tbody>" + o.map((e) => "<tr>" + R(e).map((e) => `<td>${I(e)}</td>`).join("") + "</tr>").join("") + "</tbody>"), s += "</table>", n.push(s);
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
if (/^[-*]\s/.test(e)) {
|
|
604
|
+
let e = [];
|
|
605
|
+
for (; r < t.length && /^\s*[-*]\s/.test(t[r]);) e.push(t[r].trim().replace(/^[-*]\s+/, "")), r++;
|
|
606
|
+
n.push("<ul>" + e.map((e) => `<li>${I(e)}</li>`).join("") + "</ul>");
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
if (/^\d+\.\s/.test(e)) {
|
|
610
|
+
let e = [];
|
|
611
|
+
for (; r < t.length && /^\s*\d+\.\s/.test(t[r]);) e.push(t[r].trim().replace(/^\d+\.\s+/, "")), r++;
|
|
612
|
+
n.push("<ol>" + e.map((e) => `<li>${I(e)}</li>`).join("") + "</ol>");
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
if (e === "") {
|
|
616
|
+
n.push("<br>"), r++;
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
n.push(I(e)), n.push("<br>"), r++;
|
|
620
|
+
}
|
|
621
|
+
for (; n.length > 0 && n[n.length - 1] === "<br>";) n.pop();
|
|
622
|
+
return n.join("");
|
|
543
623
|
}
|
|
544
|
-
function
|
|
624
|
+
function B(e, t, n, r, i) {
|
|
545
625
|
let { name: a, design: o } = t, s, c, l, u, d, f, { content: p } = o;
|
|
546
626
|
function m(e) {
|
|
547
|
-
e.setAttribute("data-position", o.layout.position), s = e.attachShadow({ mode: "
|
|
627
|
+
e.setAttribute("data-position", o.layout.position), s = e.attachShadow({ mode: "closed" });
|
|
548
628
|
let t = document.createElement("style");
|
|
549
629
|
t.textContent = D(o), s.appendChild(t), c = document.createElement("button"), c.className = "bubble", c.setAttribute("aria-label", n.ariaOpenChat), c.innerHTML = `
|
|
550
630
|
<span class="icon-chat">${k}</span>
|
|
@@ -558,7 +638,7 @@ function L(e, t, n, r, i) {
|
|
|
558
638
|
</div>
|
|
559
639
|
<button class="close-btn" aria-label="${F(n.ariaCloseChat)}">×</button>
|
|
560
640
|
</div>
|
|
561
|
-
<div class="messages" id="messages-container"></div>
|
|
641
|
+
<div class="messages" id="messages-container" role="log" aria-live="polite" aria-atomic="false"></div>
|
|
562
642
|
<div class="chat-footer">
|
|
563
643
|
<div class="input-row">
|
|
564
644
|
<textarea
|
|
@@ -602,7 +682,7 @@ function L(e, t, n, r, i) {
|
|
|
602
682
|
}
|
|
603
683
|
let t = e.messages.map((e) => `
|
|
604
684
|
<div class="message ${e.role}">
|
|
605
|
-
<div class="message-bubble">${e.role === "assistant" ?
|
|
685
|
+
<div class="message-bubble">${e.role === "assistant" ? z(e.content) : F(e.content)}</div>
|
|
606
686
|
</div>
|
|
607
687
|
`).join(""), i = e.isLoading ? "<div class=\"typing\"><span></span><span></span><span></span></div>" : "";
|
|
608
688
|
u.innerHTML = t + i, u.scrollTop = u.scrollHeight;
|
|
@@ -617,7 +697,7 @@ function L(e, t, n, r, i) {
|
|
|
617
697
|
}
|
|
618
698
|
//#endregion
|
|
619
699
|
//#region src/i18n/vi.ts
|
|
620
|
-
var
|
|
700
|
+
var V = {
|
|
621
701
|
statusOnline: "Trực tuyến",
|
|
622
702
|
inputPlaceholder: "Nhắn tin...",
|
|
623
703
|
defaultGreeting: "Xin chào! Tôi có thể giúp gì cho bạn?",
|
|
@@ -633,7 +713,7 @@ var R = {
|
|
|
633
713
|
ariaOpenChat: "Mở khung chat",
|
|
634
714
|
ariaCloseChat: "Đóng khung chat",
|
|
635
715
|
ariaSendMessage: "Gửi tin nhắn"
|
|
636
|
-
},
|
|
716
|
+
}, H = {
|
|
637
717
|
statusOnline: "Online",
|
|
638
718
|
inputPlaceholder: "Type a message...",
|
|
639
719
|
defaultGreeting: "Hello! How can I help you?",
|
|
@@ -652,22 +732,26 @@ var R = {
|
|
|
652
732
|
};
|
|
653
733
|
//#endregion
|
|
654
734
|
//#region src/i18n/index.ts
|
|
655
|
-
function
|
|
656
|
-
return e === "en" ?
|
|
735
|
+
function U(e) {
|
|
736
|
+
return e === "en" ? H : V;
|
|
657
737
|
}
|
|
658
738
|
//#endregion
|
|
659
739
|
//#region src/builds/npm/index.ts
|
|
660
|
-
function
|
|
740
|
+
function W(e) {
|
|
661
741
|
if (!e.apiKey) return console.warn("[BotIQ] apiKey is required"), () => void 0;
|
|
662
742
|
let t = u(e), n = m();
|
|
663
743
|
x({ messages: h(n) });
|
|
664
744
|
let r = document.createElement("div");
|
|
665
745
|
document.body.appendChild(r);
|
|
666
|
-
let i = () => void 0, a = !1, o =
|
|
746
|
+
let i = () => void 0, a = !1, o = U(void 0);
|
|
667
747
|
l(t.apiKey, t.apiUrl).then((e) => {
|
|
668
748
|
if (a) return;
|
|
669
|
-
|
|
670
|
-
|
|
749
|
+
if (e === null) {
|
|
750
|
+
console.warn("[BotIQ] Widget not authorised on this origin — skipped mount"), r.remove();
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
o = U(e.widgetLanguage);
|
|
754
|
+
let n = B(t, e, o, s, c);
|
|
671
755
|
n.mount(r), i = S((e) => n.update(e)), n.update(b());
|
|
672
756
|
});
|
|
673
757
|
function s(e) {
|
|
@@ -701,4 +785,4 @@ function V(e) {
|
|
|
701
785
|
};
|
|
702
786
|
}
|
|
703
787
|
//#endregion
|
|
704
|
-
export {
|
|
788
|
+
export { W as t };
|
package/dist/sdk/react.js
CHANGED
package/dist/sdk/vue.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@locdo.tech/botiq-chat-sdk",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "BotIQ chat widget SDK — embed AI chatbot into any website with vanilla JS, React, or Vue.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"botiq",
|
|
@@ -69,15 +69,32 @@
|
|
|
69
69
|
"preview": "vite preview",
|
|
70
70
|
"test": "vitest run",
|
|
71
71
|
"test:watch": "vitest",
|
|
72
|
-
"
|
|
72
|
+
"test:bundle": "npm run build:cdn && vitest run test/bundle",
|
|
73
|
+
"test:browser": "playwright test",
|
|
74
|
+
"test:browser:ui": "playwright test --ui",
|
|
75
|
+
"test:browser:chromium": "playwright test --project=chromium",
|
|
76
|
+
"pretest:browser": "npm run build:cdn && cpx \"test/browser/fixtures/**\" dist/test-fixtures",
|
|
77
|
+
"pretest:browser:chromium": "npm run pretest:browser",
|
|
78
|
+
"test:wordpress": "playwright test --config=playwright.wordpress.config.ts",
|
|
79
|
+
"pretest:wordpress": "npm run build:cdn",
|
|
80
|
+
"test:wordpress:up": "docker compose -f test/wordpress/docker-compose.wp.yml up -d",
|
|
81
|
+
"test:wordpress:down": "docker compose -f test/wordpress/docker-compose.wp.yml down -v",
|
|
82
|
+
"test:wordpress:logs": "docker compose -f test/wordpress/docker-compose.wp.yml logs --tail=100",
|
|
83
|
+
"prepublishOnly": "npm run build:sdk",
|
|
84
|
+
"rollback:cdn": "bash scripts/rollback/cdn-rollback.sh"
|
|
73
85
|
},
|
|
74
86
|
"devDependencies": {
|
|
87
|
+
"@playwright/test": "^1.60.0",
|
|
88
|
+
"@types/node": "^25.9.1",
|
|
75
89
|
"@types/react": "^19.2.14",
|
|
76
90
|
"@types/react-dom": "^19.2.3",
|
|
77
91
|
"@vitest/coverage-v8": "^4.1.6",
|
|
92
|
+
"cpx2": "^9.0.0",
|
|
93
|
+
"gzip-size": "^7.0.0",
|
|
78
94
|
"jsdom": "^29.1.1",
|
|
79
95
|
"react": "^19.2.6",
|
|
80
96
|
"react-dom": "^19.2.6",
|
|
97
|
+
"serve": "^14.2.6",
|
|
81
98
|
"typescript": "~6.0.2",
|
|
82
99
|
"vite": "^8.0.12",
|
|
83
100
|
"vite-plugin-dts": "^5.0.0",
|