diff --git a/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx b/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx
index c5a9352d..afb5fded 100644
--- a/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx
+++ b/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx
@@ -1,24 +1,24 @@
-import * as React from 'react'
-import { Item } from '../../../../types'
+import * as React from 'react';
+import { Item } from '../../../../types';
import { useTags } from '../../hooks/useTags';
import { useAddFilterTag } from '../../hooks/useFilter';
import { hashTagRegex } from '../../../../Utils/HashTagRegex';
import { fixUrls, mailRegex } from '../../../../Utils/ReplaceURLs';
-import Markdown from 'react-markdown'
+import Markdown from 'react-markdown';
import { getValue } from '../../../../Utils/GetValue';
-import remarkBreaks from 'remark-breaks'
+import remarkBreaks from 'remark-breaks';
import { decodeTag } from '../../../../Utils/FormatTags';
-export const TextView = ({ item, truncate = false, itemTextField}: { item?: Item, truncate?: boolean,itemTextField?: string }) => {
+export const TextView = ({ item, truncate = false, itemTextField }: { item?: Item, truncate?: boolean, itemTextField?: string }) => {
const tags = useTags();
- const addFilterTag = useAddFilterTag();
+ const addFilterTag = useAddFilterTag();
let text = "";
- if(itemTextField && item) text = getValue(item, itemTextField);
- else text = item?.layer?.itemTextField && item ? getValue(item, item.layer?.itemTextField) : ""
+ if (itemTextField && item) text = getValue(item, itemTextField);
+ else text = item?.layer?.itemTextField && item ? getValue(item, item.layer?.itemTextField) : "";
- if(item && text && truncate) text = truncateString(text, 100, true);
+ if (item && text && truncate) text = truncateText(removeMarkdownKeepLinksAndParagraphs(text), 100);
let replacedText;
@@ -32,19 +32,17 @@ export const TextView = ({ item, truncate = false, itemTextField}: { item?: Item
if (url.match('^http:\/\/')) {
shortUrl = url.split('http://')[1];
}
- return `[${shortUrl}](${url})`
- }) : "" ;
+ return `[${shortUrl}](${url})`;
+ }) : "";
replacedText ? replacedText = replacedText.replace(mailRegex, (url) => {
- return `[${url}](mailto:${url})`
+ return `[${url}](mailto:${url})`;
}) : "";
replacedText ? replacedText = replacedText.replace(hashTagRegex, (match) => {
- return `[${match}](${match})`
+ return `[${match}](${match})`;
}) : "";
-
-
const CustomH1 = ({ children }) => (
{children}
);
@@ -89,43 +87,37 @@ export const TextView = ({ item, truncate = false, itemTextField}: { item?: Item
target='_blank'
> {children}
);
- const CustomHashTagLink = ({ children, tag, item }) => {
+ const CustomHashTagLink = ({ children, tag, item }) => {
return (
- {
- e.stopPropagation();
- addFilterTag(tag!);
- // map.fitBounds(items)
- // map.closePopup();
- }}>{decodeTag(children)}
- )};
-
+ {
+ e.stopPropagation();
+ addFilterTag(tag!);
+ }}>{decodeTag(children)}
+ )
+ };
return (
- //@ts-ignore
{
- // Prüft, ob der Link ein YouTube-Video ist
const isYouTubeVideo = href?.startsWith('https://www.youtube.com/watch?v=');
if (isYouTubeVideo) {
- const videoId = href?.split('v=')[1].split('&')[0]; // Extrahiert die Video-ID aus der URL
+ const videoId = href?.split('v=')[1].split('&')[0];
const youtubeEmbedUrl = `https://www.youtube-nocookie.com/embed/${videoId}`;
return (
-
-
);
}
- if (href?.startsWith("#")) {
- const tag = tags.find(t => t.name.toLowerCase() == decodeURI(href).slice(1).toLowerCase())
+ if (href?.startsWith("#")) {
+ const tag = tags.find(t => t.name.toLowerCase() === decodeURI(href).slice(1).toLowerCase());
return {children};
} else {
return (
@@ -146,16 +138,41 @@ export const TextView = ({ item, truncate = false, itemTextField}: { item?: Item
}}>
{replacedText}
- )
-
-
+ );
+};
+function removeMarkdownKeepLinksAndParagraphs(text) {
+ // Remove Markdown syntax using regular expressions but keep links and paragraphs
+ return text
+ .replace(/!\[.*?\]\(.*?\)/g, '') // Remove images
+ .replace(/(`{1,3})(.*?)\1/g, '$2') // Remove inline code
+ .replace(/(\*{1,2}|_{1,2})(.*?)\1/g, '$2') // Remove bold and italic
+ .replace(/(#+)\s+(.*)/g, '$2') // Remove headers
+ .replace(/>\s+(.*)/g, '$1') // Remove blockquotes
+ .replace(/^\s*\n/gm, '\n') // Preserve empty lines
+ .replace(/(\r\n|\n|\r)/gm, '\n'); // Preserve line breaks
}
-function truncateString( str, n, useWordBoundary ){
- if (str.length <= n) { return str; }
- const subString = str.slice(0, n-1); // the original check
- return (useWordBoundary
- ? subString.slice(0, subString.lastIndexOf(" "))
- : subString) + "…";
-};
\ No newline at end of file
+function truncateText(text, limit) {
+ if (text.length <= limit) {
+ return text;
+ }
+
+ let truncated = "";
+ let length = 0;
+
+ // Split the text by paragraphs
+ const paragraphs = text.split('\n');
+
+ for (let paragraph of paragraphs) {
+ if (length + paragraph.length > limit) {
+ truncated += paragraph.slice(0, limit - length) + '...';
+ break;
+ } else {
+ truncated += paragraph + '\n';
+ length += paragraph.length;
+ }
+ }
+
+ return truncated.trim();
+}
diff --git a/src/Components/Templates/OverlayItemsIndexPage.tsx b/src/Components/Templates/OverlayItemsIndexPage.tsx
index 78b7b031..b9f46fc5 100644
--- a/src/Components/Templates/OverlayItemsIndexPage.tsx
+++ b/src/Components/Templates/OverlayItemsIndexPage.tsx
@@ -113,28 +113,30 @@ export const OverlayItemsIndexPage = ({ url, layerName, parameterField, plusButt
-
-
-
-
+
+
+
+
-
- {
- items?.filter(i => i.layer?.name === layerName).
- filter(item =>
- filterTags.length == 0 ? item : filterTags.every(tag => getItemTags(item).some(filterTag => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))?.
- sort((a, b) => {
- // Convert date_created to milliseconds, handle undefined by converting to lowest possible date (0 milliseconds)
- const dateA = a.date_updated ? new Date(a.date_updated).getTime() : a.date_created ? new Date(a.date_created).getTime() : 0;
- const dateB = b.date_updated ? new Date(b.date_updated).getTime() : b.date_created ? new Date(b.date_created).getTime() : 0;
- return dateB - dateA; // Subtracts milliseconds which are numbers
- })?.
- map((i, k) => {
- return (
-
deleteItem(i)} >
- )
- })
- }
+
+
+ {
+ items?.filter(i => i.layer?.name === layerName).
+ filter(item =>
+ filterTags.length == 0 ? item : filterTags.every(tag => getItemTags(item).some(filterTag => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))?.
+ sort((a, b) => {
+ // Convert date_created to milliseconds, handle undefined by converting to lowest possible date (0 milliseconds)
+ const dateA = a.date_updated ? new Date(a.date_updated).getTime() : a.date_created ? new Date(a.date_created).getTime() : 0;
+ const dateB = b.date_updated ? new Date(b.date_updated).getTime() : b.date_created ? new Date(b.date_created).getTime() : 0;
+ return dateB - dateA; // Subtracts milliseconds which are numbers
+ })?.
+ map((i, k) => {
+ return (
+ deleteItem(i)} >
+ )
+ })
+ }
+
{addItemPopupType == "place" ?