diff --git a/web/components/chat/ChatUserMessage/customMatcher.ts b/web/components/chat/ChatUserMessage/customMatcher.ts
new file mode 100644
index 000000000..d6136da1a
--- /dev/null
+++ b/web/components/chat/ChatUserMessage/customMatcher.ts
@@ -0,0 +1,44 @@
+/* eslint-disable class-methods-use-this */
+import { ChildrenNode, Matcher, MatchResponse, Node } from 'interweave';
+import React from 'react';
+
+export interface CustomProps {
+ children: React.ReactNode;
+ key: string;
+}
+
+interface options {
+ highlightString: string;
+}
+
+export class ChatMessageHighlightMatcher extends Matcher {
+ match(str: string): MatchResponse<{}> | null {
+ const { highlightString } = this.options as options;
+
+ if (!highlightString) {
+ return null;
+ }
+
+ const result = str.match(highlightString);
+
+ if (!result) {
+ return null;
+ }
+
+ return {
+ index: result.index!,
+ length: result[0].length,
+ match: result[0],
+ valid: true,
+ };
+ }
+
+ replaceWith(children: ChildrenNode, props: CustomProps): Node {
+ const { key } = props;
+ return React.createElement('mark', { key }, children);
+ }
+
+ asTag(): string {
+ return 'mark';
+ }
+}
diff --git a/web/components/chat/ChatUserMessage/messageFmt.ts b/web/components/chat/ChatUserMessage/messageFmt.ts
index 81fb53184..4624e2747 100644
--- a/web/components/chat/ChatUserMessage/messageFmt.ts
+++ b/web/components/chat/ChatUserMessage/messageFmt.ts
@@ -1,38 +1,8 @@
import { convertToText } from '../chat';
import { getDiffInDaysFromNow } from '../../../utils/helpers';
-const stripTags = (str: string) => str && str.replace(/<\/?[^>]+(>|$)/g, '');
const convertToMarkup = (str = '') => convertToText(str).replace(/\n/g, '
');
-function getInstagramEmbedFromURL(url: string) {
- const urlObject = new URL(url.replace(/\/$/, ''));
- urlObject.pathname += '/embed';
- return `
`;
-}
-
-function isMessageJustAnchor(embedText: string, message: string, anchors: HTMLAnchorElement[]) {
- if (embedText !== '' && anchors.length === 1) return false;
- return stripTags(message) === stripTags(anchors[0]?.innerHTML);
-}
-
-function getMessageWithEmbeds(message: string) {
- let embedText = '';
- // Make a temporary element so we can actually parse the html and pull anchor tags from it.
- // This is a better approach than regex.
- const container = document.createElement('p');
- container.innerHTML = message;
-
- const anchors = Array.from(container.querySelectorAll('a'));
- anchors.forEach(({ href }) => {
- if (href.includes('instagram.com/p/')) embedText += getInstagramEmbedFromURL(href);
- });
-
- // If this message only consists of a single embeddable link
- // then only return the embed and strip the link url from the text.
- if (isMessageJustAnchor(embedText, message, anchors)) return embedText;
- return message + embedText;
-}
-
export function formatTimestamp(sentAt: Date) {
const now = new Date(sentAt);
if (Number.isNaN(now)) return '';
@@ -56,8 +26,6 @@ export function formatTimestamp(sentAt: Date) {
*/
export function formatMessageText(message: string) {
- let formattedText = getMessageWithEmbeds(message);
- formattedText = convertToMarkup(formattedText);
+ const formattedText = convertToMarkup(message);
return formattedText;
- // return await highlightUsername(formattedText, username);
}
diff --git a/web/package-lock.json b/web/package-lock.json
index e5b32383c..52be0c4fe 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -24,8 +24,8 @@
"chart.js": "^4.2.0",
"classnames": "2.3.2",
"date-fns": "^2.29.3",
- "entities": "^4.4.0",
- "linkify-html": "^4.1.0",
+ "interweave": "^13.0.0",
+ "interweave-autolink": "^5.1.0",
"linkifyjs": "^4.1.0",
"lodash": "4.17.21",
"next": "13.1.6",
@@ -38,6 +38,7 @@
"react-chartkick": "^0.5.3",
"react-crossfade-img": "1.0.0",
"react-dom": "18.2.0",
+ "react-highlight-words": "^0.20.0",
"react-highlighter-ts": "18.0.1",
"react-hotkeys-hook": "4.3.4",
"react-linkify": "1.0.0-alpha",
@@ -18064,6 +18065,7 @@
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
"integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+ "dev": true,
"engines": {
"node": ">=0.12"
},
@@ -18265,8 +18267,7 @@
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "dev": true
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
@@ -21328,6 +21329,11 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/highlight-words-core": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz",
+ "integrity": "sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg=="
+ },
"node_modules/hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -21769,6 +21775,34 @@
"node": ">= 0.10"
}
},
+ "node_modules/interweave": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/interweave/-/interweave-13.0.0.tgz",
+ "integrity": "sha512-Mckwj+ix/VtrZu1bRBIIohwrsXj12ZTvJCoYUMZlJmgtvIaQCj0i77eSZ63ckbA1TsPrz2VOvLW9/kTgm5d+mw==",
+ "dependencies": {
+ "escape-html": "^1.0.3"
+ },
+ "funding": {
+ "type": "ko-fi",
+ "url": "https://ko-fi.com/milesjohnson"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/interweave-autolink": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/interweave-autolink/-/interweave-autolink-5.1.0.tgz",
+ "integrity": "sha512-WOEakAdwqv/W2H85cLdigkpMM7o6qVg4CWM6iO5cHrFCywwUh+ILVmZgX1tHphEpa55sFdzpKNO2EHhAjbR4GA==",
+ "funding": {
+ "type": "ko-fi",
+ "url": "https://ko-fi.com/milesjohnson"
+ },
+ "peerDependencies": {
+ "interweave": "^13.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -23444,14 +23478,6 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
- "node_modules/linkify-html": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/linkify-html/-/linkify-html-4.1.0.tgz",
- "integrity": "sha512-cQSNN4i5V1xRjdSUEnXgn855xsl+usD7zBSsNyMSFBf4NlaZFocn7cExJA217azxODeqea79b6fDPXLa7jdkcA==",
- "peerDependencies": {
- "linkifyjs": "^4.0.0"
- }
- },
"node_modules/linkify-it": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
@@ -24614,6 +24640,11 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/memoize-one": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-4.0.3.tgz",
+ "integrity": "sha512-QmpUu4KqDmX0plH4u+tf0riMc1KHE1+lw95cMrLlXQAFOx/xnBtwhZ52XJxd9X2O6kwKBqX32kmhbhlobD0cuw=="
+ },
"node_modules/memoizerific": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz",
@@ -31907,6 +31938,19 @@
"react": "^18.2.0"
}
},
+ "node_modules/react-highlight-words": {
+ "version": "0.20.0",
+ "resolved": "https://registry.npmjs.org/react-highlight-words/-/react-highlight-words-0.20.0.tgz",
+ "integrity": "sha512-asCxy+jCehDVhusNmCBoxDf2mm1AJ//D+EzDx1m5K7EqsMBIHdZ5G4LdwbSEXqZq1Ros0G0UySWmAtntSph7XA==",
+ "dependencies": {
+ "highlight-words-core": "^1.2.0",
+ "memoize-one": "^4.0.0",
+ "prop-types": "^15.5.8"
+ },
+ "peerDependencies": {
+ "react": "^0.14.0 || ^15.0.0 || ^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0"
+ }
+ },
"node_modules/react-highlighter-ts": {
"version": "18.0.1",
"resolved": "https://registry.npmjs.org/react-highlighter-ts/-/react-highlighter-ts-18.0.1.tgz",
diff --git a/web/package.json b/web/package.json
index 861441b99..f4eb0a847 100644
--- a/web/package.json
+++ b/web/package.json
@@ -28,8 +28,8 @@
"chart.js": "^4.2.0",
"classnames": "2.3.2",
"date-fns": "^2.29.3",
- "entities": "^4.4.0",
- "linkify-html": "^4.1.0",
+ "interweave": "^13.0.0",
+ "interweave-autolink": "^5.1.0",
"linkifyjs": "^4.1.0",
"lodash": "4.17.21",
"next": "13.1.6",
@@ -42,6 +42,7 @@
"react-chartkick": "^0.5.3",
"react-crossfade-img": "1.0.0",
"react-dom": "18.2.0",
+ "react-highlight-words": "^0.20.0",
"react-highlighter-ts": "18.0.1",
"react-hotkeys-hook": "4.3.4",
"react-linkify": "1.0.0-alpha",