@bcc-code/vue-bcc-chat-ui 3.4.0 → 3.5.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/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.5.0",
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,59 @@ 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
+ "img", // images
34
+ "blockquote", // indented text
35
+ "hr", // horizontal line
36
+ "pre", // constant width text
37
+ "br", // newline
38
+ "div" // newline on mobile
39
+ ]
40
+ })
41
+
42
+ return str
28
43
  }
29
44
 
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
45
  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
- });
46
+ return text.replace(/<@uid:(.*?)>/g, (_match: string, uid: string) => {
47
+ const user = (props.mentionedUsers || []).find((user) => user.getUid() === uid);
48
+ // Check if a userName exists for the given uid; if not, keep the original match
49
+ if (user) {
50
+ return `**${user.getName()}**`;
51
+ } else {
52
+ return `**@unknown**`;
53
+ }
54
+ });
51
55
  }
52
56
 
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
57
  </script>
67
58
 
68
59
  <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
- />
60
+ <div>
61
+ <div v-if="metadata && metadata.translated_message" v-html="toMarkdownHtml(metadata.translated_message)"
62
+ class="bcc-chat-msg-bubble bcc-chat-msg-bubble--translation" />
63
+ <div v-html="toMarkdownHtml(text)" class="bcc-chat-msg-bubble"
64
+ :class="{ 'bcc-chat-msg-bubble--translated': metadata && !!metadata.translated_message }" />
65
+ </div>
78
66
  </template>
79
67
 
80
68
  <style lang="scss">
@@ -88,7 +76,7 @@ function cleanUpHTML(input: string) {
88
76
 
89
77
  p {
90
78
  color: var(--cc__text-color);
91
- line-height: 1.2;
79
+ line-height: 1.2;
92
80
  word-break: break-word;
93
81
  text-align: left;
94
82
  white-space: normal;
@@ -98,6 +86,7 @@ function cleanUpHTML(input: string) {
98
86
  p:first-child {
99
87
  margin-top: 0;
100
88
  }
89
+
101
90
  p:last-child {
102
91
  margin-bottom: 0;
103
92
  }
@@ -106,14 +95,17 @@ function cleanUpHTML(input: string) {
106
95
  font-size: 1.6em;
107
96
  font-weight: 800;
108
97
  }
98
+
109
99
  h2 {
110
100
  font-size: 1.4em;
111
101
  font-weight: 700;
112
102
  }
103
+
113
104
  h3 {
114
105
  font-size: 1.2em;
115
106
  font-weight: 600;
116
107
  }
108
+
117
109
  h4 {
118
110
  font-size: 1em;
119
111
  font-weight: 500;
@@ -130,6 +122,7 @@ function cleanUpHTML(input: string) {
130
122
  list-style: disc;
131
123
  margin: 8px 0;
132
124
  }
125
+
133
126
  ol {
134
127
  padding-left: 16px;
135
128
  list-style: decimal;