diff --git a/package-lock.json b/package-lock.json
index e68166a..0ba03bf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1784,6 +1784,12 @@
"@types/react": "*"
}
},
+ "@types/showdown": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/@types/showdown/-/showdown-1.9.3.tgz",
+ "integrity": "sha512-akvzSmrvY4J5d3tHzUUiQr0xpjd4Nb3uzWW6dtwzYJ+qW/KdWw5F8NLatnor5q/1LURHnzDA1ReEwCVqcatRnw==",
+ "dev": true
+ },
"@types/styled-components": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-4.4.2.tgz",
@@ -2889,8 +2895,7 @@
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"camelcase-keys": {
"version": "4.2.0",
@@ -3179,7 +3184,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
- "dev": true,
"requires": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
@@ -3189,20 +3193,17 @@
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
- "dev": true
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
@@ -3213,7 +3214,6 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
- "dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
@@ -3739,8 +3739,7 @@
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
- "dev": true
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"decamelize-keys": {
"version": "1.1.0",
@@ -4779,7 +4778,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
"requires": {
"locate-path": "^3.0.0"
}
@@ -5605,8 +5603,7 @@
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-own-enumerable-property-symbols": {
"version": "3.0.2",
@@ -7154,7 +7151,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
@@ -8109,7 +8105,6 @@
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
"integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
- "dev": true,
"requires": {
"p-try": "^2.0.0"
}
@@ -8118,7 +8113,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
"requires": {
"p-limit": "^2.0.0"
}
@@ -8141,8 +8135,7 @@
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
},
"pako": {
"version": "1.0.10",
@@ -8227,8 +8220,7 @@
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
},
"path-is-absolute": {
"version": "1.0.1",
@@ -8957,14 +8949,12 @@
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
- "dev": true
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
- "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
- "dev": true
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
},
"requires-port": {
"version": "1.0.0",
@@ -9319,8 +9309,7 @@
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
- "dev": true
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"set-value": {
"version": "2.0.1",
@@ -9416,6 +9405,63 @@
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
"dev": true
},
+ "showdown": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/showdown/-/showdown-1.9.1.tgz",
+ "integrity": "sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA==",
+ "requires": {
+ "yargs": "^14.2"
+ },
+ "dependencies": {
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "yargs": {
+ "version": "14.2.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.2.tgz",
+ "integrity": "sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA==",
+ "requires": {
+ "cliui": "^5.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^15.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "15.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
+ "integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
"signal-exit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
@@ -9920,7 +9966,6 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
"requires": {
"ansi-regex": "^4.1.0"
},
@@ -9928,8 +9973,7 @@
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
- "dev": true
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
}
}
},
@@ -11145,8 +11189,7 @@
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
- "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
- "dev": true
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
},
"which-pm-runs": {
"version": "1.0.0",
@@ -11257,8 +11300,7 @@
"y18n": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
- "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
- "dev": true
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
},
"yallist": {
"version": "3.1.1",
diff --git a/package.json b/package.json
index c7833f1..19e26e4 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"@svgr/webpack": "^5.1.0",
"@types/react": "^16.9.19",
"@types/react-dom": "^16.9.5",
+ "@types/showdown": "^1.9.3",
"@types/styled-components": "^4.4.2",
"@types/twemoji": "^12.1.0",
"@types/uuid": "^3.4.7",
@@ -66,6 +67,7 @@
"react-apollo": "^3.1.3",
"react-dom": "^16.12.0",
"react-feather": "^2.0.3",
+ "showdown": "^1.9.1",
"styled-components": "^5.0.0",
"uuid": "^3.4.0"
},
diff --git a/src/Chat/components/Emojify.tsx b/src/Chat/components/Emojify.tsx
index 04a262f..a1d7726 100644
--- a/src/Chat/components/Emojify.tsx
+++ b/src/Chat/components/Emojify.tsx
@@ -2,7 +2,7 @@ import * as React from 'react'
import { parse } from 'twemoji'
import styled from 'styled-components'
-const Twemoji = styled.span`
+export const WithTwemoji = styled.span`
img.emoji {
height: 1em;
width: 1em;
@@ -11,13 +11,16 @@ const Twemoji = styled.span`
}
`
+export const convert = (text: string) =>
+ parse(text, {
+ folder: 'svg',
+ ext: '.svg',
+ })
+
export const emojify = (text: string) => (
-
)
diff --git a/src/Chat/components/Markdownify.tsx b/src/Chat/components/Markdownify.tsx
new file mode 100644
index 0000000..6967cf4
--- /dev/null
+++ b/src/Chat/components/Markdownify.tsx
@@ -0,0 +1,39 @@
+import * as React from 'react'
+import { Converter } from 'showdown'
+import { convert, WithTwemoji } from './Emojify'
+import styled from 'styled-components'
+
+// See https://github.com/showdownjs/showdown#valid-options
+const converter = new Converter({
+ simplifiedAutoLink: true,
+ excludeTrailingPunctuationFromURLs: true,
+ strikethrough: true,
+ ghCodeBlocks: false,
+ simpleLineBreaks: true,
+ openLinksInNewWindow: true,
+})
+
+const FromMarkdown = styled(WithTwemoji)`
+ p {
+ padding: 0.5rem;
+ margin: 0;
+ }
+ code {
+ color: inherit;
+ padding: 0.15rem;
+ border-radius: 4px;
+ font-weight: bold;
+ text-shadow: 1px 1px 2px #000000dd;
+ }
+ img {
+ max-width: 100%;
+ }
+`
+
+export const markdownify = (text: string) => (
+
+)
diff --git a/src/Chat/components/MessageItem.tsx b/src/Chat/components/MessageItem.tsx
index 9c62fb6..01231a6 100644
--- a/src/Chat/components/MessageItem.tsx
+++ b/src/Chat/components/MessageItem.tsx
@@ -3,45 +3,51 @@ import { useLayoutEffect } from 'react'
import styled from 'styled-components'
import { Timestamp } from './Timestamp'
import { emojify } from './Emojify'
+import { markdownify } from './Markdownify'
import { UIButton } from './ChannelView'
import DeleteIcon from 'feather-icons/dist/icons/trash-2.svg'
const MessageView = styled.div`
- border-radius: 10px;
- background-color: #dbedff;
margin: 0.5rem 0.5rem 0.5rem 4rem;
`
const UserMessageView = styled(MessageView)`
margin: 0.5rem 4rem 0.5rem 0.5rem;
- background-color: #dbfff7;
`
const Text = styled.div`
- font-size: 95%;
- padding: 0.5rem 0.5rem 0 0.5rem;
+ padding: 0;
+ a {
+ color: inherit;
+ }
+ font-weight: 400;
`
const Meta = styled.div`
+ border-bottom-left-radius: 10px;
+ border-bottom-right-radius: 10px;
display: flex;
justify-content: flex-end;
align-items: center;
font-size: 80%;
font-weight: 300;
- margin: 0.5rem;
- padding-bottom: 0.5rem;
- opacity: 0.6;
+ margin: 0;
+ padding: 0.5rem;
+ opacity: 0.7;
time + ${UIButton} {
margin-left: 0.5rem;
+ opacity: inherit;
}
`
const From = styled.div`
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
font-size: 80%;
font-weight: 300;
- padding: 0.5rem 0.5rem 0 0.5rem;
- opacity: 0.85;
+ padding: 0.5rem;
+ opacity: 0.7;
`
const GreenIndicator = styled.span`
@@ -147,11 +153,13 @@ export const MessageItem = ({
onRendered()
})
+ const userColorStyle = stringToColor(from)
+
return (
-
- {emojify(nick || from)}
- {emojify(message)}
-
+
+ {emojify(nick || from)}
+ {markdownify(message)}
+
{fromUser && (