ask-junkie 1.0.0
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 +864 -0
- package/dist/ask-junkie.css +485 -0
- package/dist/ask-junkie.esm.js +1847 -0
- package/dist/ask-junkie.esm.js.map +1 -0
- package/dist/ask-junkie.min.js +1858 -0
- package/dist/ask-junkie.min.js.map +1 -0
- package/dist/junkie-icon.png +0 -0
- package/package.json +43 -0
- package/src/ai/AIProviderFactory.js +43 -0
- package/src/ai/BaseProvider.js +68 -0
- package/src/ai/GeminiProvider.js +58 -0
- package/src/ai/GroqProvider.js +51 -0
- package/src/ai/OpenAIProvider.js +51 -0
- package/src/ai/OpenRouterProvider.js +53 -0
- package/src/analytics/FirebaseLogger.js +115 -0
- package/src/core/AskJunkie.js +585 -0
- package/src/core/EventEmitter.js +52 -0
- package/src/index.js +19 -0
- package/src/ui/ChatWidget.js +611 -0
- package/src/ui/styles.css +485 -0
- package/src/utils/DOMUtils.js +69 -0
- package/src/utils/StorageManager.js +80 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ask Junkie SDK Styles
|
|
3
|
+
* Modern, responsive chatbot widget - Matching WordPress Plugin Design
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* Container */
|
|
7
|
+
.ask-junkie-container {
|
|
8
|
+
position: fixed;
|
|
9
|
+
z-index: 999999;
|
|
10
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
11
|
+
font-size: 14px;
|
|
12
|
+
line-height: 1.5;
|
|
13
|
+
--ask-junkie-primary: #6366f1;
|
|
14
|
+
--ask-junkie-secondary: #ec4899;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Toggle Button */
|
|
18
|
+
.ask-junkie-toggle {
|
|
19
|
+
width: 65px;
|
|
20
|
+
height: 65px;
|
|
21
|
+
border-radius: 50%;
|
|
22
|
+
background: transparent;
|
|
23
|
+
border: none;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
justify-content: center;
|
|
28
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
29
|
+
transition: all 0.3s ease;
|
|
30
|
+
padding: 0;
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.ask-junkie-toggle:hover {
|
|
35
|
+
transform: scale(1.1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.ask-junkie-toggle img.icon-chat {
|
|
39
|
+
width: 100%;
|
|
40
|
+
height: 100%;
|
|
41
|
+
object-fit: cover;
|
|
42
|
+
border-radius: 50%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.ask-junkie-toggle svg {
|
|
46
|
+
width: 28px;
|
|
47
|
+
height: 28px;
|
|
48
|
+
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.ask-junkie-toggle svg.icon-close {
|
|
52
|
+
position: absolute;
|
|
53
|
+
background: linear-gradient(135deg, var(--ask-junkie-primary), var(--ask-junkie-secondary));
|
|
54
|
+
border-radius: 50%;
|
|
55
|
+
padding: 18px;
|
|
56
|
+
width: 65px;
|
|
57
|
+
height: 65px;
|
|
58
|
+
box-sizing: border-box;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Chat Window */
|
|
62
|
+
.ask-junkie-window {
|
|
63
|
+
position: absolute;
|
|
64
|
+
width: 380px;
|
|
65
|
+
max-width: calc(100vw - 48px);
|
|
66
|
+
height: 500px;
|
|
67
|
+
max-height: calc(100vh - 150px);
|
|
68
|
+
background: #0f172a;
|
|
69
|
+
border-radius: 20px;
|
|
70
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
71
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
|
|
72
|
+
display: flex;
|
|
73
|
+
flex-direction: column;
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
animation: askJunkieSlideUp 0.3s ease;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@keyframes askJunkieSlideUp {
|
|
79
|
+
from {
|
|
80
|
+
opacity: 0;
|
|
81
|
+
transform: translateY(20px);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
to {
|
|
85
|
+
opacity: 1;
|
|
86
|
+
transform: translateY(0);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Position the window based on container position */
|
|
91
|
+
.ask-junkie-container[data-position="bottom-right"] .ask-junkie-window {
|
|
92
|
+
bottom: 80px;
|
|
93
|
+
right: 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.ask-junkie-container[data-position="bottom-left"] .ask-junkie-window {
|
|
97
|
+
bottom: 80px;
|
|
98
|
+
left: 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.ask-junkie-container[data-position="top-right"] .ask-junkie-window {
|
|
102
|
+
top: 80px;
|
|
103
|
+
right: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.ask-junkie-container[data-position="top-left"] .ask-junkie-window {
|
|
107
|
+
top: 80px;
|
|
108
|
+
left: 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Header */
|
|
112
|
+
.ask-junkie-header {
|
|
113
|
+
display: flex;
|
|
114
|
+
align-items: center;
|
|
115
|
+
gap: 12px;
|
|
116
|
+
padding: 16px 20px;
|
|
117
|
+
background: linear-gradient(135deg, var(--ask-junkie-primary), var(--ask-junkie-secondary));
|
|
118
|
+
color: white;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.ask-junkie-avatar {
|
|
122
|
+
width: 40px;
|
|
123
|
+
height: 40px;
|
|
124
|
+
background: rgba(255, 255, 255, 0.2);
|
|
125
|
+
border-radius: 50%;
|
|
126
|
+
display: flex;
|
|
127
|
+
align-items: center;
|
|
128
|
+
justify-content: center;
|
|
129
|
+
overflow: hidden;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.ask-junkie-avatar img {
|
|
133
|
+
width: 100%;
|
|
134
|
+
height: 100%;
|
|
135
|
+
object-fit: cover;
|
|
136
|
+
border-radius: 50%;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.ask-junkie-avatar svg {
|
|
140
|
+
width: 24px;
|
|
141
|
+
height: 24px;
|
|
142
|
+
color: white;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.ask-junkie-info {
|
|
146
|
+
display: flex;
|
|
147
|
+
flex-direction: column;
|
|
148
|
+
flex: 1;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.ask-junkie-name {
|
|
152
|
+
font-weight: 600;
|
|
153
|
+
font-size: 16px;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.ask-junkie-status {
|
|
157
|
+
font-size: 12px;
|
|
158
|
+
opacity: 0.9;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.ask-junkie-clear {
|
|
162
|
+
width: 32px;
|
|
163
|
+
height: 32px;
|
|
164
|
+
border: none;
|
|
165
|
+
border-radius: 50%;
|
|
166
|
+
background: rgba(255, 255, 255, 0.2);
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
display: flex;
|
|
169
|
+
align-items: center;
|
|
170
|
+
justify-content: center;
|
|
171
|
+
color: white;
|
|
172
|
+
transition: all 0.2s ease;
|
|
173
|
+
opacity: 0.8;
|
|
174
|
+
padding: 6px;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.ask-junkie-clear:hover {
|
|
178
|
+
opacity: 1;
|
|
179
|
+
background: rgba(255, 255, 255, 0.3);
|
|
180
|
+
transform: scale(1.1);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* Messages */
|
|
184
|
+
.ask-junkie-messages {
|
|
185
|
+
flex: 1;
|
|
186
|
+
overflow-y: auto;
|
|
187
|
+
padding: 20px;
|
|
188
|
+
display: flex;
|
|
189
|
+
flex-direction: column;
|
|
190
|
+
gap: 16px;
|
|
191
|
+
background: #0f172a;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.ask-junkie-message {
|
|
195
|
+
display: flex;
|
|
196
|
+
max-width: 85%;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.ask-junkie-message.user {
|
|
200
|
+
align-self: flex-end;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.ask-junkie-message.bot {
|
|
204
|
+
align-self: flex-start;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.ask-junkie-message .message-content {
|
|
208
|
+
padding: 12px 16px;
|
|
209
|
+
border-radius: 16px;
|
|
210
|
+
font-size: 14px;
|
|
211
|
+
line-height: 1.5;
|
|
212
|
+
word-break: break-word;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.ask-junkie-message.user .message-content {
|
|
216
|
+
background: linear-gradient(135deg, var(--ask-junkie-primary), #8b5cf6);
|
|
217
|
+
color: white;
|
|
218
|
+
border-bottom-right-radius: 4px;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.ask-junkie-message.bot .message-content {
|
|
222
|
+
background: rgba(255, 255, 255, 0.1);
|
|
223
|
+
color: #e2e8f0;
|
|
224
|
+
border-bottom-left-radius: 4px;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.ask-junkie-message.bot .message-content a {
|
|
228
|
+
color: #818cf8;
|
|
229
|
+
text-decoration: underline;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.ask-junkie-message.bot .message-content strong {
|
|
233
|
+
color: #f1f5f9;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* Typing Indicator */
|
|
237
|
+
.ask-junkie-message.typing .message-content {
|
|
238
|
+
display: flex;
|
|
239
|
+
gap: 4px;
|
|
240
|
+
padding: 16px 20px;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.typing-dots {
|
|
244
|
+
display: flex;
|
|
245
|
+
gap: 4px;
|
|
246
|
+
padding: 4px 0;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.typing-dots span {
|
|
250
|
+
width: 8px;
|
|
251
|
+
height: 8px;
|
|
252
|
+
background: #6366f1;
|
|
253
|
+
border-radius: 50%;
|
|
254
|
+
animation: askJunkieBounce 1.4s infinite ease-in-out both;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.typing-dots span:nth-child(1) {
|
|
258
|
+
animation-delay: -0.32s;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.typing-dots span:nth-child(2) {
|
|
262
|
+
animation-delay: -0.16s;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@keyframes askJunkieBounce {
|
|
266
|
+
|
|
267
|
+
0%,
|
|
268
|
+
80%,
|
|
269
|
+
100% {
|
|
270
|
+
transform: scale(0);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
40% {
|
|
274
|
+
transform: scale(1);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/* Input Area */
|
|
279
|
+
.ask-junkie-input-area {
|
|
280
|
+
display: flex;
|
|
281
|
+
flex-direction: column;
|
|
282
|
+
align-items: center;
|
|
283
|
+
gap: 8px;
|
|
284
|
+
padding: 12px 16px;
|
|
285
|
+
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
|
286
|
+
background: #1e293b;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.ask-junkie-suggestions {
|
|
290
|
+
display: flex;
|
|
291
|
+
gap: 8px;
|
|
292
|
+
overflow-x: auto;
|
|
293
|
+
padding-bottom: 8px;
|
|
294
|
+
width: 100%;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.ask-junkie-suggestions::-webkit-scrollbar {
|
|
298
|
+
display: none;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.ask-junkie-chip {
|
|
302
|
+
flex-shrink: 0;
|
|
303
|
+
padding: 6px 14px;
|
|
304
|
+
background: rgba(255, 255, 255, 0.1);
|
|
305
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
306
|
+
border-radius: 20px;
|
|
307
|
+
color: #e2e8f0;
|
|
308
|
+
font-size: 12px;
|
|
309
|
+
cursor: pointer;
|
|
310
|
+
transition: all 0.2s;
|
|
311
|
+
white-space: nowrap;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.ask-junkie-chip:hover {
|
|
315
|
+
background: rgba(255, 255, 255, 0.2);
|
|
316
|
+
border-color: rgba(255, 255, 255, 0.4);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/* Animated Marquee Suggestions */
|
|
320
|
+
.ask-junkie-suggestions.animated {
|
|
321
|
+
overflow: hidden;
|
|
322
|
+
padding-bottom: 4px;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.ask-junkie-marquee-wrapper {
|
|
326
|
+
overflow: hidden;
|
|
327
|
+
width: 100%;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.ask-junkie-marquee-content {
|
|
331
|
+
display: flex;
|
|
332
|
+
gap: 8px;
|
|
333
|
+
animation: askJunkieMarquee 15s linear infinite;
|
|
334
|
+
width: max-content;
|
|
335
|
+
padding: 4px 0;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.ask-junkie-marquee-content:hover {
|
|
339
|
+
animation-play-state: paused;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
@keyframes askJunkieMarquee {
|
|
343
|
+
from {
|
|
344
|
+
transform: translateX(0);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
to {
|
|
348
|
+
transform: translateX(-50%);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* Resize Handle */
|
|
353
|
+
.ask-junkie-resize-handle {
|
|
354
|
+
position: absolute;
|
|
355
|
+
top: 0;
|
|
356
|
+
left: 0;
|
|
357
|
+
width: 20px;
|
|
358
|
+
height: 20px;
|
|
359
|
+
cursor: nwse-resize;
|
|
360
|
+
z-index: 10;
|
|
361
|
+
display: flex;
|
|
362
|
+
align-items: center;
|
|
363
|
+
justify-content: center;
|
|
364
|
+
color: rgba(255, 255, 255, 0.3);
|
|
365
|
+
transition: color 0.2s;
|
|
366
|
+
transform: rotate(180deg);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.ask-junkie-resize-handle:hover {
|
|
370
|
+
color: rgba(255, 255, 255, 0.6);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.ask-junkie-input-row {
|
|
374
|
+
display: flex;
|
|
375
|
+
gap: 8px;
|
|
376
|
+
align-items: center;
|
|
377
|
+
width: 100%;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.ask-junkie-input-row input {
|
|
381
|
+
flex: 1;
|
|
382
|
+
padding: 12px 16px;
|
|
383
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
384
|
+
border-radius: 12px;
|
|
385
|
+
background: #0f172a;
|
|
386
|
+
color: white;
|
|
387
|
+
font-size: 14px;
|
|
388
|
+
outline: none;
|
|
389
|
+
transition: border-color 0.3s;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.ask-junkie-input-row input:focus {
|
|
393
|
+
border-color: var(--ask-junkie-primary);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.ask-junkie-input-row input::placeholder {
|
|
397
|
+
color: #64748b;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.ask-junkie-mic,
|
|
401
|
+
.ask-junkie-send {
|
|
402
|
+
width: 44px;
|
|
403
|
+
height: 44px;
|
|
404
|
+
border: none;
|
|
405
|
+
border-radius: 12px;
|
|
406
|
+
cursor: pointer;
|
|
407
|
+
display: flex;
|
|
408
|
+
align-items: center;
|
|
409
|
+
justify-content: center;
|
|
410
|
+
transition: all 0.2s;
|
|
411
|
+
padding: 8px;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.ask-junkie-mic {
|
|
415
|
+
background: rgba(255, 255, 255, 0.15);
|
|
416
|
+
border-radius: 50%;
|
|
417
|
+
color: #e2e8f0;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.ask-junkie-mic:hover {
|
|
421
|
+
background: rgba(255, 255, 255, 0.2);
|
|
422
|
+
transform: scale(1.05);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.ask-junkie-mic.listening {
|
|
426
|
+
background: #ef4444;
|
|
427
|
+
animation: pulse 1s infinite;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
@keyframes pulse {
|
|
431
|
+
|
|
432
|
+
0%,
|
|
433
|
+
100% {
|
|
434
|
+
transform: scale(1);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
50% {
|
|
438
|
+
transform: scale(1.1);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.ask-junkie-send {
|
|
443
|
+
background: linear-gradient(135deg, var(--ask-junkie-primary), var(--ask-junkie-secondary));
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.ask-junkie-send:hover {
|
|
447
|
+
transform: scale(1.05);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* Scrollbar */
|
|
451
|
+
.ask-junkie-messages::-webkit-scrollbar {
|
|
452
|
+
width: 6px;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
.ask-junkie-messages::-webkit-scrollbar-track {
|
|
456
|
+
background: transparent;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.ask-junkie-messages::-webkit-scrollbar-thumb {
|
|
460
|
+
background: rgba(255, 255, 255, 0.2);
|
|
461
|
+
border-radius: 3px;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.ask-junkie-messages::-webkit-scrollbar-thumb:hover {
|
|
465
|
+
background: rgba(255, 255, 255, 0.3);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/* Mobile Responsiveness */
|
|
469
|
+
@media (max-width: 480px) {
|
|
470
|
+
.ask-junkie-container {
|
|
471
|
+
bottom: 16px !important;
|
|
472
|
+
right: 16px !important;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.ask-junkie-window {
|
|
476
|
+
width: calc(100vw - 32px);
|
|
477
|
+
height: calc(100vh - 120px);
|
|
478
|
+
max-height: none;
|
|
479
|
+
position: fixed;
|
|
480
|
+
left: 16px !important;
|
|
481
|
+
right: 16px !important;
|
|
482
|
+
bottom: 80px !important;
|
|
483
|
+
top: auto !important;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM Utility Functions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Escape HTML to prevent XSS
|
|
7
|
+
*/
|
|
8
|
+
export function escapeHtml(text) {
|
|
9
|
+
const div = document.createElement('div');
|
|
10
|
+
div.textContent = text;
|
|
11
|
+
return div.innerHTML;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create an element with attributes and children
|
|
16
|
+
*/
|
|
17
|
+
export function createElement(tag, attributes = {}, children = []) {
|
|
18
|
+
const element = document.createElement(tag);
|
|
19
|
+
|
|
20
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
21
|
+
if (key === 'className') {
|
|
22
|
+
element.className = value;
|
|
23
|
+
} else if (key === 'style' && typeof value === 'object') {
|
|
24
|
+
Object.assign(element.style, value);
|
|
25
|
+
} else if (key.startsWith('on') && typeof value === 'function') {
|
|
26
|
+
element.addEventListener(key.substring(2).toLowerCase(), value);
|
|
27
|
+
} else {
|
|
28
|
+
element.setAttribute(key, value);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
children.forEach(child => {
|
|
33
|
+
if (typeof child === 'string') {
|
|
34
|
+
element.appendChild(document.createTextNode(child));
|
|
35
|
+
} else if (child instanceof Node) {
|
|
36
|
+
element.appendChild(child);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return element;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Parse markdown-style links [text](url) to HTML
|
|
45
|
+
*/
|
|
46
|
+
export function parseLinks(text) {
|
|
47
|
+
return text.replace(
|
|
48
|
+
/\[([^\]]+)\]\(([^)]+)\)/g,
|
|
49
|
+
'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Parse markdown bold **text** to HTML
|
|
55
|
+
*/
|
|
56
|
+
export function parseBold(text) {
|
|
57
|
+
return text.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Format bot response with basic markdown
|
|
62
|
+
*/
|
|
63
|
+
export function formatBotResponse(text) {
|
|
64
|
+
let formatted = escapeHtml(text);
|
|
65
|
+
formatted = parseLinks(formatted);
|
|
66
|
+
formatted = parseBold(formatted);
|
|
67
|
+
formatted = formatted.replace(/\n/g, '<br>');
|
|
68
|
+
return formatted;
|
|
69
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Manager
|
|
3
|
+
* Handles localStorage operations with prefix and session management
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class StorageManager {
|
|
7
|
+
constructor(prefix = 'ask_junkie_') {
|
|
8
|
+
this.prefix = prefix;
|
|
9
|
+
this.sessionId = null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get a value from storage
|
|
14
|
+
*/
|
|
15
|
+
get(key) {
|
|
16
|
+
try {
|
|
17
|
+
const item = localStorage.getItem(this.prefix + key);
|
|
18
|
+
return item ? JSON.parse(item) : null;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.warn('[AskJunkie] Storage get error:', e);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Set a value in storage
|
|
27
|
+
*/
|
|
28
|
+
set(key, value) {
|
|
29
|
+
try {
|
|
30
|
+
localStorage.setItem(this.prefix + key, JSON.stringify(value));
|
|
31
|
+
return true;
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.warn('[AskJunkie] Storage set error:', e);
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Remove a value from storage
|
|
40
|
+
*/
|
|
41
|
+
remove(key) {
|
|
42
|
+
try {
|
|
43
|
+
localStorage.removeItem(this.prefix + key);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
console.warn('[AskJunkie] Storage remove error:', e);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get or create a unique session ID
|
|
51
|
+
*/
|
|
52
|
+
getSessionId() {
|
|
53
|
+
if (this.sessionId) return this.sessionId;
|
|
54
|
+
|
|
55
|
+
this.sessionId = this.get('session_id');
|
|
56
|
+
|
|
57
|
+
if (!this.sessionId) {
|
|
58
|
+
this.sessionId = 'sess_' +
|
|
59
|
+
Math.random().toString(36).substring(2, 10) +
|
|
60
|
+
'_' + Date.now().toString(36);
|
|
61
|
+
this.set('session_id', this.sessionId);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return this.sessionId;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Check if storage is available
|
|
69
|
+
*/
|
|
70
|
+
isAvailable() {
|
|
71
|
+
try {
|
|
72
|
+
const test = '__storage_test__';
|
|
73
|
+
localStorage.setItem(test, test);
|
|
74
|
+
localStorage.removeItem(test);
|
|
75
|
+
return true;
|
|
76
|
+
} catch (e) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|