@chat21/chat21-web-widget 5.1.1-rc1 โ 5.1.4
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/CHANGELOG.md +50 -0
- package/deploy_amazon_prod.sh +20 -6
- package/package.json +2 -2
- package/src/app/app.component.scss +10 -9
- package/src/app/app.component.ts +38 -10
- package/src/app/component/conversation-detail/conversation/conversation.component.scss +18 -18
- package/src/app/component/conversation-detail/conversation/conversation.component.ts +3 -1
- package/src/app/component/conversation-detail/conversation-content/conversation-content.component.scss +1 -0
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +12 -3
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +6 -6
- package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.ts +35 -13
- package/src/app/component/home/home.component.scss +5 -3
- package/src/app/component/last-message/last-message.component.ts +61 -9
- package/src/app/component/launcher-button/launcher-button.component.html +1 -1
- package/src/app/component/message/avatar/avatar.component.scss +1 -1
- package/src/app/component/message/bubble-message/bubble-message.component.scss +1 -1
- package/src/app/component/message/buttons/action-button/action-button.component.scss +19 -14
- package/src/app/component/message/buttons/link-button/link-button.component.scss +18 -11
- package/src/app/component/message/buttons/text-button/text-button.component.scss +20 -11
- package/src/app/component/message/carousel/carousel.component.scss +25 -17
- package/src/app/component/message/text/text.component.html +1 -2
- package/src/app/component/message-attachment/message-attachment.component.html +7 -3
- package/src/app/component/message-attachment/message-attachment.component.scss +3 -2
- package/src/app/component/send-button/send-button.component.html +2 -2
- package/src/app/pipe/marked.pipe.ts +120 -1
- package/src/app/sass/_variables.scss +9 -4
- package/src/app/utils/globals.ts +8 -3
- package/src/app/utils/utils.ts +71 -4
- package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +2 -2
- package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +3 -3
- package/src/chat21-core/utils/utils.ts +4 -0
- package/src/iframe-style.css +33 -7
|
@@ -3,33 +3,38 @@
|
|
|
3
3
|
--textColor: #{var(--bck-msg-sent)};
|
|
4
4
|
--hoverBackgroundColor: #{var(--bck-msg-sent)};
|
|
5
5
|
--hoverTextColor: #{var(--blue)};
|
|
6
|
-
--
|
|
6
|
+
--buttonFontSize2: #{var(--button-font-size)};
|
|
7
7
|
--max-width: #{var(--button-in-msg-max-width)};
|
|
8
8
|
--padding: #{var(--button-in-msg-padding)};
|
|
9
|
-
--
|
|
9
|
+
--font-family: #{var(--button-in-msg-font-family)};
|
|
10
|
+
--buttonBorderColor: #{var(--button-border-color)};
|
|
11
|
+
--buttonColor: #{var(--button-color)};
|
|
12
|
+
--buttonBackgroundColor: #ffffff; //#{var(--button-background-color)};
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
.button-in-msg {
|
|
13
16
|
padding: var(--padding);
|
|
14
|
-
|
|
15
|
-
// max-width: var(--max-width);
|
|
17
|
+
position: relative;
|
|
16
18
|
min-width: inherit;
|
|
17
19
|
cursor: pointer;
|
|
18
|
-
border: 1px solid var(--
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
border: 1px solid var(--buttonBorderColor);
|
|
21
|
+
background: var(--buttonBackgroundColor);
|
|
22
|
+
font-family: var(--font-family);
|
|
23
|
+
font-size: var(--buttonFontSize2);
|
|
24
|
+
color: var(--textColor);
|
|
22
25
|
overflow: hidden;
|
|
23
|
-
font-family: var(--fontFamily);
|
|
24
|
-
font-size: var(--buttonFontSize);
|
|
25
26
|
-o-text-overflow: ellipsis;
|
|
26
27
|
text-overflow: ellipsis;
|
|
27
|
-
|
|
28
|
+
white-space: nowrap;
|
|
28
29
|
word-wrap: break-word;
|
|
29
|
-
letter-spacing: -0.24px;
|
|
30
30
|
-webkit-font-smoothing: antialiased;
|
|
31
|
-
color: var(--textColor);
|
|
32
31
|
line-height: 16px;
|
|
32
|
+
font-weight: 500;
|
|
33
|
+
border-radius: 12px;
|
|
34
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
|
35
|
+
padding: 10px 16px;
|
|
36
|
+
margin: 3px;
|
|
37
|
+
transition: background-color .2s ease;
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
.action {
|
|
@@ -39,7 +44,7 @@
|
|
|
39
44
|
&:hover {
|
|
40
45
|
color: var(--hoverTextColor);
|
|
41
46
|
background: var(--hoverBackgroundColor);
|
|
42
|
-
transform: scale(1.05);
|
|
47
|
+
// transform: scale(1.05);
|
|
43
48
|
.icon-button-action {
|
|
44
49
|
svg {
|
|
45
50
|
fill: var(--hoverTextColor);
|
|
@@ -3,32 +3,39 @@
|
|
|
3
3
|
--textColor: #{var(--bck-msg-sent)};
|
|
4
4
|
--hoverBackgroundColor: #{var(--bck-msg-sent)};
|
|
5
5
|
--hoverTextColor: #{var(--blue)};
|
|
6
|
-
--
|
|
6
|
+
--buttonFontSize2: #{var(--button-font-size)};
|
|
7
7
|
--max-width: #{var(--button-in-msg-max-width)};
|
|
8
8
|
--padding: #{var(--button-in-msg-padding)};
|
|
9
9
|
--font-family: #{var(--button-in-msg-font-family)};
|
|
10
|
+
--buttonBorderColor: #{var(--button-border-color)};
|
|
11
|
+
--buttonColor: #{var(--button-color)};
|
|
12
|
+
--buttonBackgroundColor: #ffffff; //#{var(--button-background-color)};
|
|
10
13
|
}
|
|
11
14
|
|
|
15
|
+
|
|
12
16
|
.button-in-msg {
|
|
13
17
|
padding: var(--padding);
|
|
14
18
|
position: relative;
|
|
15
|
-
// max-width: var(--max-width);
|
|
16
19
|
min-width: inherit;
|
|
17
20
|
cursor: pointer;
|
|
18
|
-
border: 1px solid var(--
|
|
19
|
-
|
|
20
|
-
margin: 3px;
|
|
21
|
-
background: var(--backgroundColor);
|
|
22
|
-
overflow: hidden;
|
|
21
|
+
border: 1px solid var(--buttonBorderColor);
|
|
22
|
+
background: var(--buttonBackgroundColor);
|
|
23
23
|
font-family: var(--font-family);
|
|
24
|
-
font-size: var(--
|
|
24
|
+
font-size: var(--buttonFontSize2);
|
|
25
|
+
color: var(--textColor);
|
|
26
|
+
overflow: hidden;
|
|
25
27
|
-o-text-overflow: ellipsis;
|
|
26
28
|
text-overflow: ellipsis;
|
|
27
29
|
white-space: nowrap;
|
|
28
|
-
|
|
30
|
+
word-wrap: break-word;
|
|
29
31
|
-webkit-font-smoothing: antialiased;
|
|
30
|
-
color: var(--textColor);
|
|
31
32
|
line-height: 16px;
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
border-radius: 12px;
|
|
35
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
|
36
|
+
padding: 10px 16px;
|
|
37
|
+
margin: 3px;
|
|
38
|
+
transition: background-color .2s ease;
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
.url {
|
|
@@ -52,7 +59,7 @@
|
|
|
52
59
|
&:hover {
|
|
53
60
|
color: var(--hoverTextColor);
|
|
54
61
|
background: var(--hoverBackgroundColor);
|
|
55
|
-
transform: scale(1.05);
|
|
62
|
+
// transform: scale(1.05);
|
|
56
63
|
.icon-button-action, .icon-button-action-self {
|
|
57
64
|
svg {
|
|
58
65
|
fill: var(--hoverTextColor);
|
|
@@ -3,34 +3,43 @@
|
|
|
3
3
|
--textColor: #{var(--bck-msg-sent)};
|
|
4
4
|
--hoverBackgroundColor: #{var(--bck-msg-sent)};
|
|
5
5
|
--hoverTextColor: #{var(--blue)};
|
|
6
|
-
--
|
|
6
|
+
--buttonFontSize2: #{var(--button-font-size)};
|
|
7
7
|
--max-width: #{var(--button-in-msg-max-width)};
|
|
8
8
|
--padding: #{var(--button-in-msg-padding)};
|
|
9
9
|
--font-family: #{var(--button-in-msg-font-family)};
|
|
10
|
+
--buttonBorderColor: #{var(--button-border-color)};
|
|
11
|
+
// --buttonColor: #{var(--buttonColor)};
|
|
12
|
+
--buttonBackgroundColor: #ffffff; //#{var(--button-background-color)};
|
|
13
|
+
--buttonColor: #{var(--button-color)};
|
|
10
14
|
}
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
.button-in-msg {
|
|
14
18
|
padding: var(--padding);
|
|
15
19
|
position: relative;
|
|
16
|
-
// max-width: var(--max-width);
|
|
17
20
|
min-width: inherit;
|
|
18
21
|
cursor: pointer;
|
|
19
|
-
border: 1px solid var(--
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
background: var(--backgroundColor);
|
|
23
|
-
overflow: hidden;
|
|
22
|
+
border: 1px solid var(--buttonBorderColor);
|
|
23
|
+
background: var(--buttonBackgroundColor);
|
|
24
|
+
// background: var(--backgroundColor);
|
|
24
25
|
font-family: var(--font-family);
|
|
25
|
-
font-size: var(--
|
|
26
|
+
font-size: var(--buttonFontSize2);
|
|
27
|
+
// color: var(--buttonColor);
|
|
28
|
+
color: var(--textColor);
|
|
29
|
+
overflow: hidden;
|
|
26
30
|
-o-text-overflow: ellipsis;
|
|
27
31
|
text-overflow: ellipsis;
|
|
28
32
|
// white-space: nowrap;
|
|
29
33
|
word-wrap: break-word;
|
|
30
|
-
letter-spacing: -0.24px;
|
|
34
|
+
// letter-spacing: -0.24px;
|
|
31
35
|
-webkit-font-smoothing: antialiased;
|
|
32
|
-
color: var(--textColor); //$blue
|
|
33
36
|
line-height: 16px;
|
|
37
|
+
font-weight: 500;
|
|
38
|
+
border-radius: 12px;
|
|
39
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
|
40
|
+
padding: 10px 16px;
|
|
41
|
+
margin: 3px;
|
|
42
|
+
transition: background-color .2s ease;
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
.text {
|
|
@@ -40,7 +49,7 @@
|
|
|
40
49
|
&:hover {
|
|
41
50
|
color: var(--hoverTextColor);
|
|
42
51
|
background: var(--hoverBackgroundColor);
|
|
43
|
-
transform: scale(1.05);
|
|
52
|
+
// transform: scale(1.05);
|
|
44
53
|
.icon-button-action {
|
|
45
54
|
svg {
|
|
46
55
|
fill: var(--black);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
--textColor: #{var(--bck-msg-sent)};
|
|
4
4
|
--hoverBackgroundColor: #{var(--bck-msg-sent)};
|
|
5
5
|
--hoverTextColor: #{var(--blue)};
|
|
6
|
-
--buttonFontSize: #{var(--button-
|
|
6
|
+
--buttonFontSize: #{var(--button-font-size)};
|
|
7
7
|
--max-width: #{var(--button-in-msg-max-width)};
|
|
8
8
|
--fontFamily: #{var(--font-family)};
|
|
9
9
|
|
|
@@ -85,16 +85,15 @@
|
|
|
85
85
|
align-items: center;
|
|
86
86
|
}
|
|
87
87
|
.carousel .card {
|
|
88
|
-
// padding: 0px 5px;
|
|
89
88
|
scroll-snap-align: start;
|
|
90
89
|
width: var(--cardWidth);
|
|
91
90
|
background: rgb(255, 255, 255);
|
|
92
91
|
list-style: none;
|
|
93
92
|
cursor: pointer;
|
|
94
|
-
// padding-bottom: 15px;
|
|
95
93
|
flex-direction: column;
|
|
96
94
|
border-radius: 8px;
|
|
97
|
-
|
|
95
|
+
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
96
|
+
box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.04);
|
|
98
97
|
}
|
|
99
98
|
.carousel .card .card-image {
|
|
100
99
|
height: 150px;
|
|
@@ -143,24 +142,33 @@
|
|
|
143
142
|
display: flex;
|
|
144
143
|
-ms-flex-direction: column;
|
|
145
144
|
flex-direction: column;
|
|
146
|
-
padding:
|
|
147
|
-
|
|
145
|
+
padding: 20px 20px;
|
|
148
146
|
.card-title{
|
|
147
|
+
// word-wrap: break-word;
|
|
148
|
+
// font-size: 13px;
|
|
149
|
+
// font-weight: 600;
|
|
150
|
+
// line-height: 20px;
|
|
151
|
+
// // margin-top: 12px;
|
|
152
|
+
// white-space: pre-wrap;
|
|
153
|
+
// width: 100%;
|
|
149
154
|
word-wrap: break-word;
|
|
150
|
-
font-size:
|
|
151
|
-
font-weight:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
white-space: pre-wrap;
|
|
155
|
-
width: 100%;
|
|
155
|
+
font-size: 1.1em;
|
|
156
|
+
font-weight: 500;
|
|
157
|
+
font-family: var(--font-family);
|
|
158
|
+
color: #333;
|
|
156
159
|
}
|
|
157
160
|
|
|
158
161
|
.card-description{
|
|
162
|
+
// word-wrap: break-word;
|
|
163
|
+
// font-size: 16px;
|
|
164
|
+
// line-height: 20px;
|
|
165
|
+
// margin-top: 12px;
|
|
166
|
+
// white-space: pre-wrap;
|
|
159
167
|
word-wrap: break-word;
|
|
160
|
-
font-size:
|
|
161
|
-
|
|
162
|
-
margin-top: 12px;
|
|
168
|
+
font-size: 1.0em;
|
|
169
|
+
margin-top: 6px;
|
|
163
170
|
white-space: pre-wrap;
|
|
171
|
+
font-weight: 300;
|
|
164
172
|
}
|
|
165
173
|
|
|
166
174
|
}
|
|
@@ -190,7 +198,7 @@
|
|
|
190
198
|
-ms-flex-align: center;
|
|
191
199
|
align-items: center;
|
|
192
200
|
justify-content: center;
|
|
193
|
-
border-top: 1px
|
|
201
|
+
border-top: 1px dashed rgba(0, 0, 0, 0.08);
|
|
194
202
|
cursor: pointer;
|
|
195
203
|
display: -webkit-box;
|
|
196
204
|
display: -ms-flexbox;
|
|
@@ -218,7 +226,7 @@
|
|
|
218
226
|
&:hover {
|
|
219
227
|
color: var(--hoverTextColor);
|
|
220
228
|
background: var(--hoverBackgroundColor);
|
|
221
|
-
|
|
229
|
+
transform: scale(1.05);
|
|
222
230
|
.icon-button-action {
|
|
223
231
|
svg {
|
|
224
232
|
fill: var(--hoverTextColor);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
<p
|
|
1
|
+
<p #messageEl class="message_innerhtml marked"
|
|
2
2
|
[innerHTML]="printMessage(text, messageEl, this) | marked"
|
|
3
3
|
[style.color]="color"></p>
|
|
4
|
-
<!-- [innerHTML]="printMessage(text, messageEl, this) | htmlEntitiesEncode | marked" -->
|
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
|
|
4
4
|
<span *ngFor="let button of buttons | slice:0:limit" class="div-button">
|
|
5
5
|
|
|
6
|
+
<!--
|
|
7
|
+
// bubbleReceivedBackground
|
|
8
|
+
// buttonBackgroundColor
|
|
9
|
+
-->
|
|
6
10
|
<chat-text-button-attachment *ngIf="button.type === 'text' && isLastMessage === true" class="div-button"
|
|
7
11
|
[button]="button"
|
|
8
12
|
[isConversationArchived]="isConversationArchived"
|
|
9
13
|
[fontSize]="stylesMap.get('buttonFontSize')"
|
|
10
|
-
[backgroundColor]="stylesMap.get('
|
|
14
|
+
[backgroundColor]="stylesMap.get('bubbleReceivedBackground')"
|
|
11
15
|
[textColor]="stylesMap.get('buttonTextColor')"
|
|
12
16
|
[hoverBackgroundColor]="stylesMap.get('buttonHoverBackgroundColor')"
|
|
13
17
|
[hoverTextColor]="stylesMap.get('buttonHoverTextColor')"
|
|
@@ -17,7 +21,7 @@
|
|
|
17
21
|
<chat-link-button-attachment *ngIf="button.type === 'url'" class="div-button"
|
|
18
22
|
[button]="button"
|
|
19
23
|
[fontSize]="stylesMap.get('buttonFontSize')"
|
|
20
|
-
[backgroundColor]="stylesMap.get('
|
|
24
|
+
[backgroundColor]="stylesMap.get('bubbleReceivedBackground')"
|
|
21
25
|
[textColor]="stylesMap.get('buttonTextColor')"
|
|
22
26
|
[hoverBackgroundColor]="stylesMap.get('buttonHoverBackgroundColor')"
|
|
23
27
|
[hoverTextColor]="stylesMap.get('buttonHoverTextColor')"
|
|
@@ -28,7 +32,7 @@
|
|
|
28
32
|
[button]="button"
|
|
29
33
|
[isConversationArchived]="isConversationArchived"
|
|
30
34
|
[fontSize]="stylesMap.get('buttonFontSize')"
|
|
31
|
-
[backgroundColor]="stylesMap.get('
|
|
35
|
+
[backgroundColor]="stylesMap.get('bubbleReceivedBackground')"
|
|
32
36
|
[textColor]="stylesMap.get('buttonTextColor')"
|
|
33
37
|
[hoverBackgroundColor]="stylesMap.get('buttonHoverBackgroundColor')"
|
|
34
38
|
[hoverTextColor]="stylesMap.get('buttonHoverTextColor')"
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#buttons-in-message {
|
|
2
2
|
text-align: right;
|
|
3
3
|
display: block;
|
|
4
|
-
margin-right: 16px; //align attachment-buttons to bubble sent message
|
|
4
|
+
// margin-right: 16px; //align attachment-buttons to bubble sent message
|
|
5
5
|
height: auto;
|
|
6
6
|
// width: 85%;
|
|
7
7
|
max-width: 95%;
|
|
8
|
-
float:
|
|
8
|
+
float: left;
|
|
9
|
+
padding-left: calc(var(--avatar-width) + 10px);
|
|
9
10
|
|
|
10
11
|
.buttons-wrapper {
|
|
11
12
|
margin-top: 0px;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<button aflauncherbutton #aflauncherbutton id="c21-launcher-button" class="c21-button-clean scale-in-center c21-align-right"
|
|
4
4
|
*ngIf="g.isLogged == true"
|
|
5
|
-
[
|
|
5
|
+
[style]="{ 'background-color': g.themeColor, 'bottom': g.marginY+'px!important', 'left':(g.align==='left')?g.marginX+'px!important':'', 'right':(g.align==='right')?g.marginX+'px!important':'', 'width': g.launcherWidth, 'height': g.launcherHeight, 'border-radius': g.baloonShape}"
|
|
6
6
|
(click)="onSendPressed($event)"
|
|
7
7
|
tabindex="1000"
|
|
8
8
|
aria-label=" apri chat"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<!-- [@enterBubbleAnimation] -->
|
|
13
13
|
<div class="launcher-button rotate-center" >
|
|
14
14
|
<!-- <img *ngIf="g.baloonImage !== '' " [src]="g.baloonImage" [ngStyle]="{'width': '100%', 'height': '100%', 'margin': 'auto'}"> -->
|
|
15
|
-
<svg role="img" [
|
|
15
|
+
<svg role="img" [style]="{'fill': g.themeForegroundColor, 'display': (g.baloonImage==='')?'':'none' }" xmlns="http://www.w3.org/2000/svg" width="100%"
|
|
16
16
|
height="100%" viewBox="0 0 90 90">
|
|
17
17
|
<!-- <path fill="none" d="M0 0h24v24H0V0z" />
|
|
18
18
|
<path d="M33.57,31A4.58,4.58,0,0,0,29,35.57V58.3a1.94,1.94,0,0,0,3.32,1.38l3-3a.29.29,0,0,1,.21-.09H56.43A4.58,4.58,0,0,0,61,52V35.57A4.58,4.58,0,0,0,56.43,31Z" /> -->
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
2
|
import { marked } from 'marked';
|
|
3
|
+
import { BLOCKED_DOMAINS } from '../utils/utils';
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
@Pipe({
|
|
@@ -10,6 +11,55 @@ export class MarkedPipe implements PipeTransform {
|
|
|
10
11
|
transform(value: any): any {
|
|
11
12
|
const renderer = new marked.Renderer();
|
|
12
13
|
renderer.link = function({ href, title, tokens }) {
|
|
14
|
+
// Normalizza l'href per evitare falsi negativi
|
|
15
|
+
const normalized = (href || '').trim().toLowerCase();
|
|
16
|
+
// Pattern pericolosi da cercare nell'intero URL (non solo all'inizio)
|
|
17
|
+
const dangerousPatterns = [
|
|
18
|
+
/javascript:/i, // javascript: protocol
|
|
19
|
+
/data:/i, // data: protocol
|
|
20
|
+
/vbscript:/i, // vbscript: protocol
|
|
21
|
+
/on\w+\s*=/i, // event handlers (onclick, onload, etc.)
|
|
22
|
+
/alert\s*\(/i, // alert() function
|
|
23
|
+
/eval\s*\(/i, // eval() function
|
|
24
|
+
/document\./i, // document object access
|
|
25
|
+
/window\./i, // window object access
|
|
26
|
+
/\.appendChild\s*\(/i, // DOM manipulation
|
|
27
|
+
/\.createElement\s*\(/i, // DOM creation
|
|
28
|
+
/<script/i, // script tags
|
|
29
|
+
/<\/script>/i, // closing script tags
|
|
30
|
+
/function\s*\(/i, // function definitions
|
|
31
|
+
/\(function/i, // IIFE patterns
|
|
32
|
+
/setTimeout\s*\(/i, // setTimeout
|
|
33
|
+
/setInterval\s*\(/i, // setInterval
|
|
34
|
+
/location\./i, // location object manipulation
|
|
35
|
+
/history\./i, // history object manipulation
|
|
36
|
+
/localStorage\./i, // localStorage access
|
|
37
|
+
/sessionStorage\./i, // sessionStorage access
|
|
38
|
+
/cookie/i, // cookie manipulation
|
|
39
|
+
/fetch\s*\(/i, // fetch API
|
|
40
|
+
/XMLHttpRequest/i, // XHR
|
|
41
|
+
/FormData/i, // FormData
|
|
42
|
+
/Blob\s*\(/i, // Blob constructor
|
|
43
|
+
/FileReader/i, // FileReader
|
|
44
|
+
/crypto\./i, // crypto object
|
|
45
|
+
/btoa\s*\(/i, // base64 encoding
|
|
46
|
+
/atob\s*\(/i, // base64 decoding
|
|
47
|
+
/decodeURI/i, // URI decoding
|
|
48
|
+
/encodeURI/i, // URI encoding
|
|
49
|
+
/String\.fromCharCode/i, // character code conversion
|
|
50
|
+
/unescape\s*\(/i, // unescape function
|
|
51
|
+
/escape\s*\(/i // escape function
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
// Controlla se l'URL contiene pattern pericolosi
|
|
55
|
+
const isDangerous = dangerousPatterns.some(pattern => pattern.test(normalized));
|
|
56
|
+
if (isDangerous) {
|
|
57
|
+
// Ritorna solo il testo come stringa, niente <a>
|
|
58
|
+
return tokens ? tokens.map(token => token.raw).join('') : href || '';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// tokens = this.cleanInput(href);
|
|
62
|
+
|
|
13
63
|
const text = tokens
|
|
14
64
|
? tokens.map(token => token.raw).join('')
|
|
15
65
|
: href; // fallback se tokens non c'รจ
|
|
@@ -17,7 +67,7 @@ export class MarkedPipe implements PipeTransform {
|
|
|
17
67
|
|
|
18
68
|
return `<a href="${href}" target="_blank" rel="noopener noreferrer">${text}</a>`;
|
|
19
69
|
};
|
|
20
|
-
|
|
70
|
+
|
|
21
71
|
marked.setOptions({
|
|
22
72
|
renderer,
|
|
23
73
|
gfm: true,
|
|
@@ -35,4 +85,73 @@ export class MarkedPipe implements PipeTransform {
|
|
|
35
85
|
return value;
|
|
36
86
|
}
|
|
37
87
|
|
|
88
|
+
|
|
89
|
+
private cleanInput(input: string): string {
|
|
90
|
+
if (!input) return '';
|
|
91
|
+
let cleaned = (input || '').trim().toLowerCase();
|
|
92
|
+
|
|
93
|
+
BLOCKED_DOMAINS.forEach(domain => {
|
|
94
|
+
const escapedDomain = domain.replace(/\./g, '\\.');
|
|
95
|
+
// Pattern che copre TUTTI i casi
|
|
96
|
+
const comprehensivePattern = new RegExp(
|
|
97
|
+
`(\\[([^\\]]*)\\]\\([^)]*(?:https?://)?(?:www\\.)?${escapedDomain}(?:/[^)]*)?\\))|((?:https?://)?(?:www\\.)?${escapedDomain}(?:/\\S*)?)`,
|
|
98
|
+
'gi'
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
cleaned = cleaned.replace(comprehensivePattern, (match, p1, p2, p3) => {
|
|
102
|
+
// Se รจ un link markdown [text](url), mantieni il testo
|
|
103
|
+
if (p2) return `${p2} ๐`;
|
|
104
|
+
// Se รจ un URL diretto, sostituisci con dominio + ๐
|
|
105
|
+
if (p3) return `${domain} ๐`;
|
|
106
|
+
return match;
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
// Pattern che sostituisce i link pericolosi con solo il testo
|
|
113
|
+
const dangerousLinkPatterns = [
|
|
114
|
+
// Sostituisce [text](javascript:...) con "text"
|
|
115
|
+
/\[([^\]]*)\]\(javascript:[^)]*\)/gi,
|
|
116
|
+
/\[([^\]]*)\]\(data:[^)]*\)/gi,
|
|
117
|
+
/\[([^\]]*)\]\(vbscript:[^)]*\)/gi,
|
|
118
|
+
/\[([^\]]*)\]\([^)]*alert\([^)]*\)/gi
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
dangerousLinkPatterns.forEach(pattern => {
|
|
122
|
+
cleaned = cleaned.replace(pattern, '$1'); // $1 = il testo del link
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Pattern generali per sicurezza (rimuovono completamente)
|
|
126
|
+
const generalPatterns = [
|
|
127
|
+
/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
|
|
128
|
+
/<script[^>]*>[\s\S]*?<\/script>/gi, // Script multi-linea
|
|
129
|
+
/<script[^>]*>.*?<\/script>/gi, // Script single-line
|
|
130
|
+
/<script[^>]*>/gi, // Solo tag di apertura
|
|
131
|
+
/<\/script>/gi, // Solo tag di chiusura
|
|
132
|
+
/javascript:/gi,
|
|
133
|
+
/vbscript:/gi,
|
|
134
|
+
/data:/gi,
|
|
135
|
+
/on\w+\s*=/gi,
|
|
136
|
+
/alert\(/gi,
|
|
137
|
+
/eval\(/gi,
|
|
138
|
+
/document\./gi,
|
|
139
|
+
/window\./gi,
|
|
140
|
+
/\(function\s*\(\)\s*\{/gi,
|
|
141
|
+
/\.appendChild\(/gi,
|
|
142
|
+
/\.createElement\(/gi,
|
|
143
|
+
/\.getElementsByTagName\(/gi,
|
|
144
|
+
|
|
145
|
+
// โ
PATTERN PER FUNZIONI IIFE (Immediately Invoked Function Expression):
|
|
146
|
+
/\(function\s*\(\s*\)\s*\{[\s\S]*?\}\)\(\s*\)\s*;/gi,
|
|
147
|
+
/\(function\s*\(\)\s*\{/gi
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
generalPatterns.forEach(pattern => {
|
|
151
|
+
cleaned = cleaned.replace(pattern, '');
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return cleaned;
|
|
155
|
+
}
|
|
156
|
+
|
|
38
157
|
}
|
|
@@ -19,10 +19,14 @@
|
|
|
19
19
|
--col-msg-sent: #ffffff;
|
|
20
20
|
|
|
21
21
|
--border-radius-bubble-message: 20px;
|
|
22
|
-
--button-in-msg-font-size:
|
|
22
|
+
--button-in-msg-font-size: 13px;
|
|
23
23
|
--button-in-msg-font-family: 'Roboto','Google Sans', Helvetica, Arial, sans-serif;
|
|
24
24
|
--button-in-msg-max-width: 280px;
|
|
25
25
|
--button-in-msg-padding: 8px 16px;
|
|
26
|
+
--button-color: #5c6c73;
|
|
27
|
+
--button-background-color: #f5f5f5; // #f9fcff;
|
|
28
|
+
--button-border-color: #0000000f; //#e4ebf2;
|
|
29
|
+
--button-font-size: 13px;
|
|
26
30
|
|
|
27
31
|
--max-width-images: 230px; //change also MAX_WIDTH_IMAGES in constants.ts
|
|
28
32
|
|
|
@@ -42,15 +46,16 @@
|
|
|
42
46
|
--content-background-color: #fff;
|
|
43
47
|
--content-text-color: var(--black);
|
|
44
48
|
|
|
49
|
+
--avatar-height: 20px;
|
|
50
|
+
--avatar-width: 20px;
|
|
51
|
+
|
|
52
|
+
|
|
45
53
|
--font-family: 'Roboto','Google Sans', Helvetica, Arial, sans-serif; //Mulish, sans-serif;
|
|
46
54
|
--font-family-bubble-message: 'Roboto','Google Sans', Helvetica, Arial, sans-serif;
|
|
47
55
|
--font-family-callout: 'Helvetica Neue', 'Apple Color Emoji', Helvetica, Arial, sans-serif;
|
|
48
56
|
--font-family-powered-by: Mulish, sans-serif;
|
|
49
57
|
|
|
50
58
|
--font-size-bubble-message: 1.4em;
|
|
51
|
-
|
|
52
|
-
--avatar-height: 40px;
|
|
53
|
-
--avatar-width: 40px;
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
$trasp-black:rgba(0,0,0,0.8);
|
package/src/app/utils/globals.ts
CHANGED
|
@@ -294,6 +294,9 @@ export class Globals {
|
|
|
294
294
|
* false the WAITING_TIME_NOT_FOUND will always be displayed)
|
|
295
295
|
* is set to true for backward compatibility with old projects */
|
|
296
296
|
this.dynamicWaitTimeReply = true;
|
|
297
|
+
/** Hide the close button in the widget header. Permitted values: true,
|
|
298
|
+
false. The default value is false. */
|
|
299
|
+
this.hideHeaderCloseButton = false;
|
|
297
300
|
|
|
298
301
|
/** if it is true, the chat window is open in fullscreen mode. Permitted
|
|
299
302
|
values: true, false. Default value : false */
|
|
@@ -335,13 +338,15 @@ export class Globals {
|
|
|
335
338
|
/** set launcher balon widget shape: can set corner by corner */
|
|
336
339
|
this.baloonShape = '50%';
|
|
337
340
|
// this.parameters['isLogEnabled'] = false;
|
|
338
|
-
this.
|
|
341
|
+
this.openExternalLinkButton = true;
|
|
339
342
|
/** Hide the header conversation Permitted values: true,
|
|
340
343
|
false. The default value is false. */
|
|
341
344
|
this.hideHeaderConversation= false;
|
|
342
345
|
/** Hide the close button in the widget header. Permitted values: true,
|
|
343
346
|
false. The default value is false. */
|
|
344
347
|
this.hideHeaderCloseButton = false;
|
|
348
|
+
/** set global log. Permitted values: true, false. The default value is false. */
|
|
349
|
+
this.isLogEnabled = false;
|
|
345
350
|
/** enable to hide/show upper-right header conversation options menu */
|
|
346
351
|
this.openExternalLinkButton = true;
|
|
347
352
|
/** enable to close a conversation from upper-right header menu */
|
|
@@ -361,7 +366,7 @@ export class Globals {
|
|
|
361
366
|
/** set the text color of bubble sent message */
|
|
362
367
|
this.bubbleSentTextColor = convertColorToRGBA('#ffffff', 100); //'#ffffff'
|
|
363
368
|
/** set the background of bubble received message */
|
|
364
|
-
this.bubbleReceivedBackground= convertColorToRGBA('#
|
|
369
|
+
this.bubbleReceivedBackground= convertColorToRGBA('#f5f5f5', 100); //#f7f7f7; //#f0f2f7 //#f5f5f5
|
|
365
370
|
/** set the text color of bubble received message */
|
|
366
371
|
this.bubbleReceivedTextColor = convertColorToRGBA('#06132b', 100); //#1a1a1a
|
|
367
372
|
/** set the text size of bubble messages */
|
|
@@ -401,7 +406,7 @@ export class Globals {
|
|
|
401
406
|
/**enable user to set a telegram number to chat with */
|
|
402
407
|
this.telegramUsername = ''
|
|
403
408
|
/**enable auto disconnect from messaging after a defined amount of time (s)*/
|
|
404
|
-
this.fileUploadAccept =
|
|
409
|
+
this.fileUploadAccept = '';//image/*,.pdf,.txt,.mp3,.xls,.xlsx"
|
|
405
410
|
this.disconnetTime = 0
|
|
406
411
|
|
|
407
412
|
this.showWaitTime = true;
|