mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2026-02-06 09:55:47 +00:00
seperate hashtags
This commit is contained in:
parent
46705b2162
commit
28dd16dfeb
40
lib/package-lock.json
generated
40
lib/package-lock.json
generated
@ -57,9 +57,11 @@
|
|||||||
"react-toastify": "^9.1.3",
|
"react-toastify": "^9.1.3",
|
||||||
"rehype-raw": "^7.0.0",
|
"rehype-raw": "^7.0.0",
|
||||||
"rehype-sanitize": "^6.0.0",
|
"rehype-sanitize": "^6.0.0",
|
||||||
|
"rehype-stringify": "^10.0.1",
|
||||||
"remark-breaks": "^4.0.0",
|
"remark-breaks": "^4.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-parse": "^11.0.0",
|
"remark-parse": "^11.0.0",
|
||||||
|
"remark-rehype": "^11.1.2",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"tiptap-markdown": "^0.8.10",
|
"tiptap-markdown": "^0.8.10",
|
||||||
"unified": "^11.0.5",
|
"unified": "^11.0.5",
|
||||||
@ -7244,6 +7246,29 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-to-html": {
|
||||||
|
"version": "9.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz",
|
||||||
|
"integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/unist": "^3.0.0",
|
||||||
|
"ccount": "^2.0.0",
|
||||||
|
"comma-separated-tokens": "^2.0.0",
|
||||||
|
"hast-util-whitespace": "^3.0.0",
|
||||||
|
"html-void-elements": "^3.0.0",
|
||||||
|
"mdast-util-to-hast": "^13.0.0",
|
||||||
|
"property-information": "^7.0.0",
|
||||||
|
"space-separated-tokens": "^2.0.0",
|
||||||
|
"stringify-entities": "^4.0.0",
|
||||||
|
"zwitch": "^2.0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-to-jsx-runtime": {
|
"node_modules/hast-util-to-jsx-runtime": {
|
||||||
"version": "2.3.6",
|
"version": "2.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
|
||||||
@ -12009,6 +12034,21 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-stringify": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hast-util-to-html": "^9.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark-breaks": {
|
"node_modules/remark-breaks": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz",
|
||||||
|
|||||||
@ -145,9 +145,11 @@
|
|||||||
"react-toastify": "^9.1.3",
|
"react-toastify": "^9.1.3",
|
||||||
"rehype-raw": "^7.0.0",
|
"rehype-raw": "^7.0.0",
|
||||||
"rehype-sanitize": "^6.0.0",
|
"rehype-sanitize": "^6.0.0",
|
||||||
|
"rehype-stringify": "^10.0.1",
|
||||||
"remark-breaks": "^4.0.0",
|
"remark-breaks": "^4.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-parse": "^11.0.0",
|
"remark-parse": "^11.0.0",
|
||||||
|
"remark-rehype": "^11.1.2",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"tiptap-markdown": "^0.8.10",
|
"tiptap-markdown": "^0.8.10",
|
||||||
"unified": "^11.0.5",
|
"unified": "^11.0.5",
|
||||||
|
|||||||
@ -6,12 +6,14 @@ import remarkBreaks from 'remark-breaks'
|
|||||||
import remarkGfm from 'remark-gfm'
|
import remarkGfm from 'remark-gfm'
|
||||||
|
|
||||||
import { useAddFilterTag } from '#components/Map/hooks/useFilter'
|
import { useAddFilterTag } from '#components/Map/hooks/useFilter'
|
||||||
import { useTags } from '#components/Map/hooks/useTags'
|
import { useGetItemTags, useTags } from '#components/Map/hooks/useTags'
|
||||||
import { decodeTag } from '#utils/FormatTags'
|
import { decodeTag } from '#utils/FormatTags'
|
||||||
|
|
||||||
import type { Item } from '#types/Item'
|
import type { Item } from '#types/Item'
|
||||||
|
|
||||||
export const TextPreview = ({ item }: { item: Item }) => {
|
export const TextPreview = ({ item }: { item: Item }) => {
|
||||||
|
const getItemTags = useGetItemTags()
|
||||||
|
|
||||||
if (!item.text) return null
|
if (!item.text) return null
|
||||||
// Text auf ~100 Zeichen stutzen (inkl. Ellipse „…“)
|
// Text auf ~100 Zeichen stutzen (inkl. Ellipse „…“)
|
||||||
const previewRaw = truncate(item.text, { limit: 100, ellipsis: true }) as string
|
const previewRaw = truncate(item.text, { limit: 100, ellipsis: true }) as string
|
||||||
@ -23,22 +25,21 @@ export const TextPreview = ({ item }: { item: Item }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='markdown'>
|
<div className='markdown'>
|
||||||
<Markdown
|
<Markdown remarkPlugins={[remarkBreaks, remarkGfm]} rehypePlugins={[rehypeRaw]}>
|
||||||
remarkPlugins={[remarkBreaks, remarkGfm]}
|
{removeMentionSpans(removeHashtags(withExtraHashes))}
|
||||||
rehypePlugins={[rehypeRaw]}
|
|
||||||
components={{ span: Span }}
|
|
||||||
>
|
|
||||||
{withExtraHashes}
|
|
||||||
</Markdown>
|
</Markdown>
|
||||||
|
{getItemTags(item).map((tag) => (
|
||||||
|
<HashTag tag={tag} key={tag} />
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HashTag = ({ tag }: { tag: string }) => {
|
export const HashTag = ({ tag }: { tag: Tag }) => {
|
||||||
const tags = useTags()
|
const tags = useTags()
|
||||||
const t = tags.find((t) => t.name === tag.slice(1))
|
const t = tags.find((t) => t.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())
|
||||||
const addFilterTag = useAddFilterTag()
|
const addFilterTag = useAddFilterTag()
|
||||||
if (!t) return <span>{tag}</span>
|
if (!t) return null
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
className='hashtag'
|
className='hashtag'
|
||||||
@ -49,14 +50,26 @@ export const HashTag = ({ tag }: { tag: string }) => {
|
|||||||
addFilterTag(t)
|
addFilterTag(t)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{decodeTag(tag)}
|
{`#${decodeTag(tag.name)} `}
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Span = (node) => {
|
function removeMentionSpans(html) {
|
||||||
if (node['data-type'] === 'mention') {
|
return html.replace(
|
||||||
return <HashTag tag={node.children} />
|
/<span\b(?=[^>]*\bdata-type="mention")(?=[^>]*\bclass="mention")[^>]*>[\s\S]*?<\/span>/gi,
|
||||||
}
|
'',
|
||||||
return <span {...node}>{node.children}</span>
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeHashtags(str) {
|
||||||
|
return str
|
||||||
|
// 1. Hashtags entfernen, außer sie stehen am Zeilenanfang als Markdown-Heading
|
||||||
|
.replace(
|
||||||
|
/(^|\s)(?!#{1,6}\s)(#[A-Za-z0-9_]+)\b/g,
|
||||||
|
'$1'
|
||||||
|
)
|
||||||
|
|
||||||
|
// 3. Anfangs/Ende trimmen
|
||||||
|
.trim()
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user