diff --git a/package.json b/package.json
index 0b7e1437..b2767e85 100644
--- a/package.json
+++ b/package.json
@@ -63,8 +63,10 @@
"destr": "^2.0.2",
"framer-motion": "^10.16.4",
"html-to-text": "^9.0.5",
+ "immer": "^10.0.3",
"light-bolt11-decoder": "^3.0.0",
"lru-cache": "^10.0.1",
+ "markdown-to-jsx": "^7.3.2",
"media-chrome": "^1.4.5",
"million": "^2.6.4",
"minidenticons": "^4.2.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b3f5fdfd..5a0dd272 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -140,12 +140,18 @@ dependencies:
html-to-text:
specifier: ^9.0.5
version: 9.0.5
+ immer:
+ specifier: ^10.0.3
+ version: 10.0.3
light-bolt11-decoder:
specifier: ^3.0.0
version: 3.0.0
lru-cache:
specifier: ^10.0.1
version: 10.0.1
+ markdown-to-jsx:
+ specifier: ^7.3.2
+ version: 7.3.2(react@18.2.0)
media-chrome:
specifier: ^1.4.5
version: 1.4.5
@@ -193,7 +199,7 @@ dependencies:
version: 1.1.1
reactflow:
specifier: ^11.9.4
- version: 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
+ version: 11.9.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
rehype-external-links:
specifier: ^3.0.0
version: 3.0.0
@@ -220,7 +226,7 @@ dependencies:
version: 0.15.6(react-dom@18.2.0)(react@18.2.0)
zustand:
specifier: ^4.4.4
- version: 4.4.4(@types/react@18.2.33)(react@18.2.0)
+ version: 4.4.4(@types/react@18.2.33)(immer@10.0.3)(react@18.2.0)
devDependencies:
'@tailwindcss/typography':
@@ -1792,39 +1798,39 @@ packages:
'@babel/runtime': 7.23.2
dev: false
- /@reactflow/background@11.3.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
+ /@reactflow/background@11.3.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-bgwvqWxF09chwmdkyClpYEMaewBspdwjgLbbFlLf4SpWPFMYyuvCBQrcISsvy/EDEWO9i3Uj9ktgGAhvtSQsmA==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
- '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/core': 11.9.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- zustand: 4.4.4(@types/react@18.2.33)(react@18.2.0)
+ zustand: 4.4.4(@types/react@18.2.33)(immer@10.0.3)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
- /@reactflow/controls@11.2.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
+ /@reactflow/controls@11.2.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-x6e5p9iHjC6gd+4SoZ3DOOp0F1MefGKQ8hT6yPVdqxfo1+rV2WhrWvrX/MCoEu12Dp7457LdLfa0giy3aho8tQ==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
- '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/core': 11.9.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- zustand: 4.4.4(@types/react@18.2.33)(react@18.2.0)
+ zustand: 4.4.4(@types/react@18.2.33)(immer@10.0.3)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
- /@reactflow/core@11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
+ /@reactflow/core@11.9.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-Ko7nKPOYalwDTTbRHi2+QXDiidSAcpUzGN3G+0B+QysLZkcaPCkpkMjjHiDC4c/Z1BJBzs1FRJg/T6BXaBnYkg==}
peerDependencies:
react: '>=17'
@@ -1840,19 +1846,19 @@ packages:
d3-zoom: 3.0.0
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- zustand: 4.4.4(@types/react@18.2.33)(react@18.2.0)
+ zustand: 4.4.4(@types/react@18.2.33)(immer@10.0.3)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
- /@reactflow/minimap@11.7.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
+ /@reactflow/minimap@11.7.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-Jo1R+uDey9IV7O2s3m0gK2+cZpg9M8hq2EZJb3NGfOSzMAPhj3mby0fNJIgTzycreuht0TpA51c2YfjGI3YIOw==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
- '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/core': 11.9.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
'@types/d3-selection': 3.0.8
'@types/d3-zoom': 3.0.6
classcat: 5.0.4
@@ -1860,41 +1866,41 @@ packages:
d3-zoom: 3.0.0
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- zustand: 4.4.4(@types/react@18.2.33)(react@18.2.0)
+ zustand: 4.4.4(@types/react@18.2.33)(immer@10.0.3)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
- /@reactflow/node-resizer@2.2.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
+ /@reactflow/node-resizer@2.2.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-+p271/hAsM5M1+RQTWW/02pbNkCHeGXwxGimIlL1tMIagyuko0NX2vOz2B8jxJnPKlF09Wj18BcXBNUm3nDcSg==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
- '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/core': 11.9.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4
d3-drag: 3.0.0
d3-selection: 3.0.0
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- zustand: 4.4.4(@types/react@18.2.33)(react@18.2.0)
+ zustand: 4.4.4(@types/react@18.2.33)(immer@10.0.3)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
- /@reactflow/node-toolbar@1.3.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
+ /@reactflow/node-toolbar@1.3.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-TfcmpXHRBb2mUfzKGjburiU6FWqRME9pPFs1OwIC1z5e9BjupQhNDEKEk8XHi7PKL/mAiDfwuGXaM1BVVFuPqw==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
- '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/core': 11.9.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- zustand: 4.4.4(@types/react@18.2.33)(react@18.2.0)
+ zustand: 4.4.4(@types/react@18.2.33)(immer@10.0.3)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
@@ -4445,6 +4451,10 @@ packages:
engines: {node: '>= 4'}
dev: true
+ /immer@10.0.3:
+ resolution: {integrity: sha512-pwupu3eWfouuaowscykeckFmVTpqbzW+rXFCX8rQLkZzM9ftBmU/++Ra+o+L27mz03zJTlyV4UUr+fdKNffo4A==}
+ dev: false
+
/import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
@@ -4922,6 +4932,15 @@ packages:
resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
dev: false
+ /markdown-to-jsx@7.3.2(react@18.2.0):
+ resolution: {integrity: sha512-B+28F5ucp83aQm+OxNrPkS8z0tMKaeHiy0lHJs3LqCyDQFtWuenaIrkaVTgAm1pf1AU85LXltva86hlaT17i8Q==}
+ engines: {node: '>= 10'}
+ peerDependencies:
+ react: '>= 0.14.0'
+ dependencies:
+ react: 18.2.0
+ dev: false
+
/mdast-util-find-and-replace@3.0.1:
resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==}
dependencies:
@@ -6122,18 +6141,18 @@ packages:
loose-envify: 1.4.0
dev: false
- /reactflow@11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
+ /reactflow@11.9.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-IHAKBkJngNvU9y1vZ5Nw9rvA3Z+zc9geTgQQIi9qq9Y9knGLlDDr9KfsjbFMew9AycAAgVg8TvBEakF4IT5lqg==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
- '@reactflow/background': 11.3.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
- '@reactflow/controls': 11.2.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
- '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
- '@reactflow/minimap': 11.7.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
- '@reactflow/node-resizer': 2.2.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
- '@reactflow/node-toolbar': 1.3.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/background': 11.3.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/controls': 11.2.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/core': 11.9.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/minimap': 11.7.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/node-resizer': 2.2.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
+ '@reactflow/node-toolbar': 1.3.4(@types/react@18.2.33)(immer@10.0.3)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
transitivePeerDependencies:
@@ -7117,7 +7136,7 @@ packages:
engines: {node: '>=10'}
dev: true
- /zustand@4.4.4(@types/react@18.2.33)(react@18.2.0):
+ /zustand@4.4.4(@types/react@18.2.33)(immer@10.0.3)(react@18.2.0):
resolution: {integrity: sha512-5UTUIAiHMNf5+mFp7/AnzJXS7+XxktULFN0+D1sCiZWyX7ZG+AQpqs2qpYrynRij4QvoDdCD+U+bmg/cG3Ucxw==}
engines: {node: '>=12.7.0'}
peerDependencies:
@@ -7133,6 +7152,7 @@ packages:
optional: true
dependencies:
'@types/react': 18.2.33
+ immer: 10.0.3
react: 18.2.0
use-sync-external-store: 1.2.0(react@18.2.0)
dev: false
diff --git a/src/shared/notes/kinds/text.tsx b/src/shared/notes/kinds/text.tsx
index 47064ec0..857c5fc0 100644
--- a/src/shared/notes/kinds/text.tsx
+++ b/src/shared/notes/kinds/text.tsx
@@ -1,6 +1,16 @@
+import Markdown from 'markdown-to-jsx';
import { memo } from 'react';
-import { ImagePreview, LinkPreview, MentionNote, VideoPreview } from '@shared/notes';
+import {
+ Boost,
+ Hashtag,
+ ImagePreview,
+ Invoice,
+ LinkPreview,
+ MentionNote,
+ MentionUser,
+ VideoPreview,
+} from '@shared/notes';
import { parser } from '@utils/parser';
@@ -17,9 +27,30 @@ export function TextNote(props: { content?: string; truncate?: boolean }) {
return (
-
+ str,
+ forceBlock: true,
+ enforceAtxHeadings: true,
+ }}
+ className="break-p prose prose-neutral max-w-none select-text whitespace-pre-line leading-normal dark:prose-invert prose-headings:mb-1 prose-headings:mt-3 prose-p:mb-0 prose-p:mt-0 prose-p:last:mb-1 prose-a:font-normal prose-a:text-blue-500 prose-blockquote:mb-1 prose-blockquote:mt-1 prose-blockquote:border-l-[2px] prose-blockquote:border-blue-500 prose-blockquote:pl-2 prose-pre:whitespace-pre-wrap prose-pre:bg-white/10 prose-ol:m-0 prose-ol:mb-1 prose-ul:mb-1 prose-ul:mt-1 prose-img:mb-2 prose-img:mt-3 prose-hr:mx-0 prose-hr:my-2 hover:prose-a:text-blue-600 prose-a:hover:underline"
+ >
{richContent.parsed}
-
+
{richContent.images.length ?
: null}
{richContent.videos.length ?
: null}
{richContent.links.length ?
: null}
diff --git a/src/shared/notes/mentions/note.tsx b/src/shared/notes/mentions/note.tsx
index e5de7205..059d5019 100644
--- a/src/shared/notes/mentions/note.tsx
+++ b/src/shared/notes/mentions/note.tsx
@@ -75,13 +75,14 @@ export const MentionNote = memo(function MentionNote({ id }: { id: string }) {
}
return (
-
+
);
});
diff --git a/src/shared/widgets/newsfeed.tsx b/src/shared/widgets/newsfeed.tsx
index ab080eae..12a9c510 100644
--- a/src/shared/widgets/newsfeed.tsx
+++ b/src/shared/widgets/newsfeed.tsx
@@ -124,7 +124,13 @@ export function NewsfeedWidget() {
sub(
filter,
async (event) => {
- queryClient.setQueryData(['newsfeed'], (old: NDKEvent[]) => [event, ...old]);
+ queryClient.setQueryData(
+ ['newsfeed'],
+ (prev: { pageParams: number; pages: Array }) => ({
+ ...prev,
+ pages: [[event], ...prev.pages],
+ })
+ );
},
false,
'newsfeed'
diff --git a/src/shared/widgets/notification.tsx b/src/shared/widgets/notification.tsx
index 104226d5..2265803f 100644
--- a/src/shared/widgets/notification.tsx
+++ b/src/shared/widgets/notification.tsx
@@ -77,10 +77,13 @@ export function NotificationWidget() {
sub(
filter,
async (event) => {
- queryClient.setQueryData(['notification'], (old: NDKEvent[]) => [
- event,
- ...old,
- ]);
+ queryClient.setQueryData(
+ ['notification'],
+ (prev: { pageParams: number; pages: Array }) => ({
+ ...prev,
+ pages: [[event], ...prev.pages],
+ })
+ );
const user = ndk.getUser({ hexpubkey: event.pubkey });
await user.fetchProfile();
diff --git a/src/utils/parser.ts b/src/utils/parser.ts
new file mode 100644
index 00000000..42d1fac4
--- /dev/null
+++ b/src/utils/parser.ts
@@ -0,0 +1,132 @@
+import { nip19 } from 'nostr-tools';
+import {
+ AddressPointer,
+ EventPointer,
+ ProfilePointer,
+} from 'nostr-tools/lib/types/nip19';
+
+import { RichContent } from '@utils/types';
+
+function isURL(string: string) {
+ try {
+ const url = new URL(string);
+ if (url.protocol.length > 0) {
+ if (url.protocol === 'https:' || url.protocol === 'http:') {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+export function parser(content: string) {
+ const richContent: RichContent = {
+ parsed: null,
+ images: [],
+ videos: [],
+ links: [],
+ notes: [],
+ };
+
+ const parsed = content
+ .trim()
+ .split(/(\s+)/)
+ .map((word) => {
+ // url
+ if (isURL(word)) {
+ const url = new URL(word);
+ url.search = '';
+
+ if (url.pathname.match(/\.(jpg|jpeg|gif|png|webp|avif)$/)) {
+ // image url
+ richContent.images.push(word);
+ // remove url from original content
+ return word.replace(word, '');
+ }
+
+ if (url.pathname.match(/\.(mp4|mov|webm|wmv|flv|mts|avi|ogv|mkv|mp3|m3u8)$/)) {
+ // video url
+ richContent.videos.push(word);
+ // remove url from original content
+ return word.replace(word, '');
+ }
+
+ // normal url
+ if (richContent.links.length < 1) {
+ richContent.links.push(url.toString());
+ }
+ }
+
+ // hashtag
+ if (word.startsWith('#') && word.length > 1) {
+ return word.replace(word, ``);
+ }
+
+ // boost
+ if (word.startsWith('$prism') && word.length > 1) {
+ return word.replace(word, ``);
+ }
+
+ // nostr account references (depreciated)
+ if (word.startsWith('@npub1')) {
+ const npub = word.replace('@', '').replace(/[^a-zA-Z0-9 ]/g, '');
+ return word.replace(
+ word,
+ ``
+ );
+ }
+
+ // nostr account references
+ if (word.startsWith('nostr:npub1') || word.startsWith('npub1')) {
+ const npub = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
+ return word.replace(
+ word,
+ ``
+ );
+ }
+
+ // nostr profile references
+ if (word.startsWith('nostr:nprofile1') || word.startsWith('nprofile1')) {
+ const nprofile = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
+ const decoded = nip19.decode(nprofile).data as ProfilePointer;
+ return word.replace(word, ``);
+ }
+
+ // nostr address references
+ if (word.startsWith('nostr:naddr1') || word.startsWith('naddr1')) {
+ const naddr = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
+ const decoded = nip19.decode(naddr).data as AddressPointer;
+ return word.replace(word, ``);
+ }
+
+ // lightning invoice
+ if (word.startsWith('lnbc') && word.length > 60) {
+ return word.replace(word, ``);
+ }
+
+ // nostr note references
+ if (word.startsWith('nostr:note1') || word.startsWith('note1')) {
+ const note = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
+ richContent.notes.push(nip19.decode(note).data as string);
+ return word.replace(word, '');
+ }
+
+ // nostr event references
+ if (word.startsWith('nostr:nevent1') || word.startsWith('nevent1')) {
+ const nevent = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
+ const decoded = nip19.decode(nevent).data as EventPointer;
+ richContent.notes.push(decoded.id);
+ return word.replace(word, '');
+ }
+
+ return word;
+ });
+
+ // update content with parsed version
+ richContent.parsed = parsed.join(' ').trim();
+ return richContent;
+}
diff --git a/src/utils/parser.tsx b/src/utils/parser.tsx
deleted file mode 100644
index 2441dcf7..00000000
--- a/src/utils/parser.tsx
+++ /dev/null
@@ -1,173 +0,0 @@
-import { nip19 } from 'nostr-tools';
-import {
- AddressPointer,
- EventPointer,
- ProfilePointer,
-} from 'nostr-tools/lib/types/nip19';
-import { Link } from 'react-router-dom';
-import reactStringReplace from 'react-string-replace';
-
-import { Boost, Hashtag, Invoice, MentionUser } from '@shared/notes';
-
-import { RichContent } from '@utils/types';
-
-function isURL(string: string) {
- try {
- const url = new URL(string);
- if (url.protocol.length > 0) {
- if (url.protocol === 'https:' || url.protocol === 'http:') {
- return true;
- } else {
- return false;
- }
- }
- return true;
- } catch (e) {
- return false;
- }
-}
-
-export function parser(eventContent: string) {
- const content: RichContent = {
- parsed: null,
- images: [],
- videos: [],
- links: [],
- notes: [],
- };
-
- const parsed = eventContent.split(/\s/gm).map((word) => {
- // nostr note references
- if (word.startsWith('nostr:note1') || word.startsWith('note1')) {
- const note = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
- content.notes.push(nip19.decode(note).data as string);
- return word.replace(word, ' ');
- }
-
- // nostr event references
- if (word.startsWith('nostr:nevent1') || word.startsWith('nevent1')) {
- const nevent = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
- const decoded = nip19.decode(nevent).data as EventPointer;
- content.notes.push(decoded.id);
- return word.replace(word, ' ');
- }
-
- // url
- if (isURL(word)) {
- const url = new URL(word);
- url.search = '';
-
- if (url.pathname.match(/\.(jpg|jpeg|gif|png|webp|avif)$/)) {
- // image url
- content.images.push(word);
- // remove url from original content
- return word.replace(word, ' ');
- }
-
- if (url.pathname.match(/\.(mp4|mov|webm|wmv|flv|mts|avi|ogv|mkv|mp3|m3u8)$/)) {
- // video url
- content.videos.push(word);
- // remove url from original content
- return word.replace(word, ' ');
- }
-
- // normal url
- if (content.links.length < 1) {
- content.links.push(url.toString());
- return word.replace(word, ' ');
- } else {
- return reactStringReplace(word, word, (match, i) => (
- <>
- {' '}
-
- {word}
- {' '}
- >
- ));
- }
- }
-
- // hashtag
- if (word.startsWith('#') && word.length > 1) {
- return reactStringReplace(word, word, (match, i) => (
- <>
- {' '}
- {' '}
- >
- ));
- }
-
- // boost
- if (word.startsWith('$prism') && word.length > 1) {
- return reactStringReplace(word, word, (match, i) => (
- <>
- {' '}
- {' '}
- >
- ));
- }
-
- // nostr account references (depreciated)
- if (word.startsWith('@npub1')) {
- const npub = word.replace('@', '').replace(/[^a-zA-Z0-9 ]/g, '');
- return reactStringReplace(word, word, (match, i) => (
- <>
- {' '}
- {' '}
- >
- ));
- }
-
- // nostr account references
- if (word.startsWith('nostr:npub1') || word.startsWith('npub1')) {
- const npub = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
- return reactStringReplace(word, word, (match, i) => (
- <>
- {' '}
- {' '}
- >
- ));
- }
-
- // nostr profile references
- if (word.startsWith('nostr:nprofile1') || word.startsWith('nprofile1')) {
- const nprofile = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
- const decoded = nip19.decode(nprofile).data as ProfilePointer;
- return reactStringReplace(word, word, (match, i) => (
- <>
- {' '}
- {' '}
- >
- ));
- }
-
- // nostr address references
- if (word.startsWith('nostr:naddr1') || word.startsWith('naddr1')) {
- const naddr = word.replace('nostr:', '').replace(/[^a-zA-Z0-9 ]/g, '');
- const decoded = nip19.decode(naddr).data as AddressPointer;
- return reactStringReplace(word, word, (match, i) => (
- <>
- {' '}
- {' '}
- >
- ));
- }
-
- // lightning invoice
- if (word.startsWith('lnbc') && word.length > 60) {
- return reactStringReplace(word, word, (match, i) => (
- <>
- {' '}
- {' '}
- >
- ));
- }
-
- // normal word
- return ' ' + word + ' ';
- });
-
- // update content with parsed version
- content.parsed = parsed;
- return content;
-}
diff --git a/src/utils/types.d.ts b/src/utils/types.d.ts
index ba8794ae..0c427925 100644
--- a/src/utils/types.d.ts
+++ b/src/utils/types.d.ts
@@ -1,9 +1,8 @@
import { type NDKEvent, type NDKUserProfile } from '@nostr-dev-kit/ndk';
import { type Response } from '@tauri-apps/plugin-http';
-import { ReactNode } from 'react';
export interface RichContent {
- parsed: string | ReactNode[];
+ parsed: string;
images: string[];
videos: string[];
links: string[];