@bcc-code/vue-bcc-chat-ui 3.4.0 → 3.4.1

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@bcc-code/vue-bcc-chat-ui",
3
3
  "author": "bcc-code",
4
4
  "license": "Apache-2.0",
5
- "version": "3.4.0",
5
+ "version": "3.4.1",
6
6
  "type": "module",
7
7
  "private": false,
8
8
  "files": [
@@ -22,21 +22,23 @@
22
22
  "vue": "^3.0.0"
23
23
  },
24
24
  "devDependencies": {
25
+ "@types/dompurify": "^3.0.5",
25
26
  "@types/markdown-it": "^13.0.7",
26
- "@types/node": "^20.11.30",
27
+ "@types/node": "^20.12.4",
27
28
  "@vitejs/plugin-vue": "^4.6.2",
28
29
  "path": "^0.12.7",
29
- "sass": "^1.72.0",
30
- "typescript": "^5.4.3",
31
- "vite": "^5.2.6",
32
- "vite-plugin-dts": "^3.7.3",
30
+ "sass": "^1.74.1",
31
+ "typescript": "^5.4.4",
32
+ "vite": "^5.2.8",
33
+ "vite-plugin-dts": "^3.8.1",
33
34
  "vue": "^3.4.21"
34
35
  },
35
36
  "dependencies": {
36
37
  "@cometchat/chat-sdk-javascript": "^4.0.4",
37
- "@cometchat/chat-uikit-vue": "^4.3.1",
38
- "@cometchat/uikit-resources": "^4.3.1",
39
- "@cometchat/uikit-shared": "^4.3.2",
38
+ "@cometchat/chat-uikit-vue": "^4.3.2",
39
+ "@cometchat/uikit-resources": "^4.3.2",
40
+ "@cometchat/uikit-shared": "^4.3.3",
41
+ "dompurify": "^3.0.11",
40
42
  "jwt-decode": "^4.0.0",
41
43
  "markdown-it": "^14.1.0"
42
44
  },
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import MarkdownIt from 'markdown-it'
3
3
  import { User } from '@cometchat/chat-sdk-javascript'
4
+ import DOMPurify from 'dompurify';
4
5
 
5
6
  const props = defineProps<{
6
7
  text: string,
@@ -9,72 +10,55 @@ const props = defineProps<{
9
10
  }>()
10
11
 
11
12
  function toMarkdownHtml(str: string) {
12
- // Regex to match URLs that may or may not start with "www." and are not already part of a Markdown link
13
- const urlRegex = /([^\]]\(|[^\(]|^\(?)((?:https?|ftp):\/\/[^\s\]\)]*|www\.[^\s\]\)]+)(?=[\s\]\)](?!\()|$)/g;
14
-
15
- // Replacing URLs in the string with Markdown links
16
- let outStr = str.replace(urlRegex, formatUrlToMarkdown);
17
-
18
- outStr = formatMentionsInText(outStr);
19
-
20
- outStr = cleanUpHTML(outStr);
13
+ str = formatMentionsInText(str);
21
14
 
22
15
  const md = new MarkdownIt({
23
16
  breaks: true,
24
17
  typographer: true,
18
+ linkify: true,
19
+ html: true
25
20
  });
26
21
 
27
- return md.render(outStr);
22
+ str = md.render(str);
23
+
24
+ str = DOMPurify.sanitize(str, {
25
+ ALLOWED_TAGS: [
26
+ "a", // links
27
+ "ul", "ol", "li", // lists
28
+ "p", // paragraphs
29
+ "b", "strong", // bold
30
+ "i", "em", // italics
31
+ "u", // underline
32
+ "s", // strikethrough
33
+ "br", // newline
34
+ "div" // newline on mobile
35
+ ]
36
+ })
37
+
38
+ return str
28
39
  }
29
40
 
30
- // Function to format a URL into a Markdown link
31
- function formatUrlToMarkdown(_match: string, group1: string, group2: string) {
32
- let url = group2;
33
- // Prepend "http://" to URLs starting with "www."
34
- if (url.startsWith('www.')) {
35
- url = 'http://' + url;
36
- }
37
- const hostname = new URL(url).hostname;
38
- return `${group1}[${hostname}](${url})`;
39
- };
40
-
41
41
  function formatMentionsInText(text: string) {
42
- return text.replace(/<@uid:(.*?)>/g, (_match: string, uid: string) => {
43
- const user = (props.mentionedUsers || []).find((user) => user.getUid() === uid);
44
- // Check if a userName exists for the given uid; if not, keep the original match
45
- if (user) {
46
- return `**${user.getName()}**`;
47
- } else {
48
- return `**@unknown**`;
49
- }
50
- });
42
+ return text.replace(/<@uid:(.*?)>/g, (_match: string, uid: string) => {
43
+ const user = (props.mentionedUsers || []).find((user) => user.getUid() === uid);
44
+ // Check if a userName exists for the given uid; if not, keep the original match
45
+ if (user) {
46
+ return `**${user.getName()}**`;
47
+ } else {
48
+ return `**@unknown**`;
49
+ }
50
+ });
51
51
  }
52
52
 
53
- // Due to how mobile adds line breaks we need to remove them
54
- function cleanUpHTML(input: string) {
55
- // Step 1: Replace <div><br></div> with <br>
56
- let cleaned = input.replace(/<div><br><\/div>/g, '\n');
57
-
58
- // Step 2: Replace opening <div> that follows any content or at the start with <br>
59
- cleaned = cleaned.replace(/(^|<\/div>)(<div>)/g, '$1\n');
60
-
61
- // Step 3: Remove all remaining <div> and </div> tags
62
- cleaned = cleaned.replace(/<\/?div>/g, '');
63
-
64
- return cleaned;
65
- }
66
53
  </script>
67
54
 
68
55
  <template>
69
- <div v-if="metadata && metadata.translated_message"
70
- v-html="toMarkdownHtml(metadata.translated_message)"
71
- class="bcc-chat-msg-bubble bcc-chat-msg-bubble--translation"
72
- />
73
- <div
74
- v-html="toMarkdownHtml(text)"
75
- class="bcc-chat-msg-bubble"
76
- :class="{'bcc-chat-msg-bubble--translated': metadata && !!metadata.translated_message}"
77
- />
56
+ <div>
57
+ <div v-if="metadata && metadata.translated_message" v-html="toMarkdownHtml(metadata.translated_message)"
58
+ class="bcc-chat-msg-bubble bcc-chat-msg-bubble--translation" />
59
+ <div v-html="toMarkdownHtml(text)" class="bcc-chat-msg-bubble"
60
+ :class="{ 'bcc-chat-msg-bubble--translated': metadata && !!metadata.translated_message }" />
61
+ </div>
78
62
  </template>
79
63
 
80
64
  <style lang="scss">
@@ -88,7 +72,7 @@ function cleanUpHTML(input: string) {
88
72
 
89
73
  p {
90
74
  color: var(--cc__text-color);
91
- line-height: 1.2;
75
+ line-height: 1.2;
92
76
  word-break: break-word;
93
77
  text-align: left;
94
78
  white-space: normal;
@@ -98,6 +82,7 @@ function cleanUpHTML(input: string) {
98
82
  p:first-child {
99
83
  margin-top: 0;
100
84
  }
85
+
101
86
  p:last-child {
102
87
  margin-bottom: 0;
103
88
  }
@@ -106,14 +91,17 @@ function cleanUpHTML(input: string) {
106
91
  font-size: 1.6em;
107
92
  font-weight: 800;
108
93
  }
94
+
109
95
  h2 {
110
96
  font-size: 1.4em;
111
97
  font-weight: 700;
112
98
  }
99
+
113
100
  h3 {
114
101
  font-size: 1.2em;
115
102
  font-weight: 600;
116
103
  }
104
+
117
105
  h4 {
118
106
  font-size: 1em;
119
107
  font-weight: 500;
@@ -130,6 +118,7 @@ function cleanUpHTML(input: string) {
130
118
  list-style: disc;
131
119
  margin: 8px 0;
132
120
  }
121
+
133
122
  ol {
134
123
  padding-left: 16px;
135
124
  list-style: decimal;