diff --git a/lib/package-lock.json b/lib/package-lock.json index 573e9970..8a24bbca 100644 --- a/lib/package-lock.json +++ b/lib/package-lock.json @@ -35,6 +35,7 @@ "date-fns": "^3.3.1", "leaflet": "^1.9.4", "leaflet.locatecontrol": "^0.79.0", + "mdast-util-to-string": "^4.0.0", "prosemirror-markdown": "^1.13.2", "radash": "^12.1.0", "react-colorful": "^5.6.1", @@ -52,7 +53,10 @@ "rehype-sanitize": "^6.0.0", "remark-breaks": "^4.0.0", "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remove-markdown": "^0.6.2", "tiptap-markdown": "^0.8.10", + "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "yet-another-react-lightbox": "^3.21.7" }, @@ -12047,6 +12051,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remove-markdown": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.6.2.tgz", + "integrity": "sha512-EijDXJZbzpGbQBd852ViUzcqgpMujthM+SAEHiWCMcZonRbZ+xViWKLJA/vrwbDwYdxrs1aFDjpBhcGrZoJRGA==", + "license": "MIT" + }, "node_modules/request-progress": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", diff --git a/lib/package.json b/lib/package.json index b660a2a5..ea9e7fbf 100644 --- a/lib/package.json +++ b/lib/package.json @@ -123,6 +123,7 @@ "date-fns": "^3.3.1", "leaflet": "^1.9.4", "leaflet.locatecontrol": "^0.79.0", + "mdast-util-to-string": "^4.0.0", "prosemirror-markdown": "^1.13.2", "radash": "^12.1.0", "react-colorful": "^5.6.1", @@ -140,7 +141,10 @@ "rehype-sanitize": "^6.0.0", "remark-breaks": "^4.0.0", "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remove-markdown": "^0.6.2", "tiptap-markdown": "^0.8.10", + "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "yet-another-react-lightbox": "^3.21.7" }, diff --git a/lib/src/Components/Input/RichTextEditor.tsx b/lib/src/Components/Input/RichTextEditor.tsx index 78548003..4016a823 100644 --- a/lib/src/Components/Input/RichTextEditor.tsx +++ b/lib/src/Components/Input/RichTextEditor.tsx @@ -252,29 +252,43 @@ const CustomYoutube = Youtube.extend({ }), ] }, + parseHTML() { + return [ + { + tag: 'iframe[src*="/embed/"]', + priority: 1000, + getAttrs: (dom) => { + const src = (dom as HTMLIFrameElement).getAttribute('src') || '' + console.log(src) + const match = src.match(/\/embed\/([A-Za-z0-9_-]{11})/) + console.log(match) + if (!match) { + return false + } + const videoId = match[1] + console.log(videoId) + // immer auf nocookie normieren + return { + src: `https://www.youtube-nocookie.com/embed/${videoId}`, + } + }, + }, + ] + }, renderHTML({ HTMLAttributes }) { - const otherAttrs = { ...HTMLAttributes } as Record - const originalSrc = otherAttrs.src as string - const match = originalSrc.match( - /(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/, - ) - const videoId = match?.[1] - const nocookieUrl = `https://www.youtube-nocookie.com/embed/${videoId}` - - delete otherAttrs.width - delete otherAttrs.height - - const iframeAttrs = { - ...otherAttrs, - src: nocookieUrl, + // feste Breiten/Höhen raus + const { ...attrs } = HTMLAttributes + delete attrs.width + delete attrs.height + const iframeAttrs = mergeAttributes(attrs, { allowfullscreen: '', - class: 'tw-w-full tw-h-full', loading: 'lazy', - } + class: 'tw-w-full tw-h-full', + }) return [ 'div', - { class: 'tw:w-full tw:aspect-video tw:overflow-hidden' }, + { class: 'tw:w-full tw-aspect-video tw-overflow-hidden' }, ['iframe', iframeAttrs], ] }, diff --git a/lib/src/Components/Map/Subcomponents/Controls/SearchControl.tsx b/lib/src/Components/Map/Subcomponents/Controls/SearchControl.tsx index f82a3693..0083d879 100644 --- a/lib/src/Components/Map/Subcomponents/Controls/SearchControl.tsx +++ b/lib/src/Components/Map/Subcomponents/Controls/SearchControl.tsx @@ -27,6 +27,7 @@ import { useLeafletRefs } from '#components/Map/hooks/useLeafletRefs' import { useTags } from '#components/Map/hooks/useTags' import useWindowDimensions from '#components/Map/hooks/useWindowDimension' import { decodeTag } from '#utils/FormatTags' +import { markdownToPlainText } from '#utils/getTextFromMarkdown' import MarkerIconFactory from '#utils/MarkerIconFactory' import { LocateControl } from './LocateControl' @@ -195,7 +196,7 @@ export const SearchControl = () => { {item.name}
- {item.text} + {markdownToPlainText(item.text ?? '')}
diff --git a/lib/src/Utils/getTextFromMarkdown.ts b/lib/src/Utils/getTextFromMarkdown.ts new file mode 100644 index 00000000..ee4b81b2 --- /dev/null +++ b/lib/src/Utils/getTextFromMarkdown.ts @@ -0,0 +1,15 @@ +import { toString } from 'mdast-util-to-string' +import remarkParse from 'remark-parse' +import { unified } from 'unified' + +export function markdownToPlainText(markdown: string): string { + const tree = unified().use(remarkParse).parse(markdown) + + let text = toString(tree) + + const container = document.createElement('div') + container.innerHTML = text + text = container.textContent ?? '' + + return text.replace(/\n{2,}/g, '\n\n').trim() +}