mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
basic markdown implementation in item text view
This commit is contained in:
parent
444cac6dc2
commit
25fcb4ef9c
1129
package-lock.json
generated
1129
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -52,8 +52,8 @@
|
||||
"react-image-crop": "^10.1.8",
|
||||
"react-leaflet": "^4.2.1",
|
||||
"react-leaflet-cluster": "^2.1.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-router-dom": "^6.16.0",
|
||||
"react-string-replace": "^1.1.1",
|
||||
"react-toastify": "^9.1.3",
|
||||
"tributejs": "^5.1.3",
|
||||
"tw-elements": "^1.0.0"
|
||||
|
||||
@ -11,6 +11,6 @@ export const PopupTextInput = ({ dataField, placeholder, style, item }:
|
||||
}) => {
|
||||
|
||||
return (
|
||||
<TextInput defaultValue={item?.text ? item.text : ""} dataField={dataField} placeholder={placeholder} inputStyle={style} type='text'></TextInput>
|
||||
<TextInput defaultValue={item?.name ? item.name : ""} dataField={dataField} placeholder={placeholder} inputStyle={style} type='text'></TextInput>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,27 +1,22 @@
|
||||
import * as React from 'react'
|
||||
import { Item } from '../../../../types'
|
||||
import { useAddTag, useTags } from '../../hooks/useTags';
|
||||
import reactStringReplace from 'react-string-replace';
|
||||
import { useTags } from '../../hooks/useTags';
|
||||
import { useAddFilterTag } from '../../hooks/useFilter';
|
||||
import { hashTagRegex } from '../../../../Utils/HashTagRegex';
|
||||
import { fixUrls, mailRegex } from '../../../../Utils/ReplaceURLs';
|
||||
import { useMap } from 'react-leaflet';
|
||||
import { randomColor } from '../../../../Utils/RandomColor';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import Markdown from 'react-markdown'
|
||||
|
||||
export const TextView = ({ item }: { item?: Item }) => {
|
||||
const tags = useTags();
|
||||
const addTag = useAddTag();
|
||||
const addFilterTag = useAddFilterTag();
|
||||
|
||||
let replacedText;
|
||||
|
||||
|
||||
|
||||
console.log(item?.text);
|
||||
|
||||
|
||||
if (item && item.text) replacedText = fixUrls(item.text);
|
||||
|
||||
replacedText = reactStringReplace(replacedText, /(https?:\/\/\S+)/g, (url, i) => {
|
||||
replacedText = replacedText.replace(/(?<!\]\()https?:\/\/[^\s\)]+(?!\))/g, (url) => {
|
||||
let shortUrl = url;
|
||||
if (url.match('^https:\/\/')) {
|
||||
shortUrl = url.split('https://')[1];
|
||||
@ -29,35 +24,110 @@ export const TextView = ({ item }: { item?: Item }) => {
|
||||
if (url.match('^http:\/\/')) {
|
||||
shortUrl = url.split('http://')[1];
|
||||
}
|
||||
return (
|
||||
<a key={i.toString+item!.id+url} href={url} target="_blank" rel="noopener noreferrer">{shortUrl}</a>
|
||||
)
|
||||
});
|
||||
|
||||
replacedText = reactStringReplace(replacedText, mailRegex, (url, i) => {
|
||||
return (
|
||||
<a key={i.toString+item!.id+url} href={`mailto:${url}`} target="_blank" rel="noopener noreferrer">{url}</a>
|
||||
)
|
||||
});
|
||||
|
||||
replacedText = reactStringReplace(replacedText, hashTagRegex, (match, i) => {
|
||||
|
||||
const tag = tags.find(t => t.id.toLowerCase() == match.slice(1).toLowerCase())
|
||||
return (
|
||||
<a style={{ color: tag ? tag.color : '#aaa' , fontWeight: 'bold', cursor: 'pointer' }} key={tag ? tag.id+item!.id+i : i} onClick={() => {
|
||||
addFilterTag(tag!);
|
||||
// map.fitBounds(items)
|
||||
// map.closePopup();
|
||||
}}>{match}</a>
|
||||
)
|
||||
return `[${shortUrl}](${url})`
|
||||
})
|
||||
|
||||
console.log(replacedText);
|
||||
|
||||
|
||||
replacedText = replacedText.replace(mailRegex, (url) => {
|
||||
return `[${url}](mailto:${url})`
|
||||
})
|
||||
|
||||
console.log(replacedText);
|
||||
|
||||
|
||||
replacedText = replacedText.replace(hashTagRegex, (match) => {
|
||||
return `[${match}](${match})`
|
||||
})
|
||||
|
||||
console.log(replacedText);
|
||||
|
||||
|
||||
const CustomH1 = ({ children }) => (
|
||||
<h1 className="tw-text-xl tw-font-bold">{children}</h1>
|
||||
);
|
||||
const CustomH2 = ({ children }) => (
|
||||
<h2 className="tw-text-lg tw-font-bold">{children}</h2>
|
||||
);
|
||||
const CustomH3 = ({ children }) => (
|
||||
<h3 className="tw-text-base tw-font-bold">{children}</h3>
|
||||
);
|
||||
const CustomH4 = ({ children }) => (
|
||||
<h4 className="tw-text-base tw-font-bold">{children}</h4>
|
||||
);
|
||||
const CustomH5 = ({ children }) => (
|
||||
<h5 className="tw-text-sm tw-font-bold">{children}</h5>
|
||||
);
|
||||
const CustomH6 = ({ children }) => (
|
||||
<h6 className="tw-text-sm tw-font-bold">{children}</h6>
|
||||
);
|
||||
const CustomParagraph = ({ children }) => (
|
||||
<p className="!tw-my-1">{children}</p>
|
||||
);
|
||||
const CustomUnorderdList = ({ children }) => (
|
||||
<ul className="tw-list-disc tw-list-inside">{children}</ul>
|
||||
);
|
||||
const CustomOrderdList = ({ children }) => (
|
||||
<ol className="tw-list-decimal tw-list-inside">{children}</ol>
|
||||
);
|
||||
const CustomImage = ({ alt, src, title }) => (
|
||||
<img
|
||||
className="max-w-full rounded-lg shadow-md"
|
||||
src={src}
|
||||
alt={alt}
|
||||
title={title}
|
||||
/>
|
||||
);
|
||||
const CustomExternalLink = ({ href, children }) => (
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
const CustomHashTagLink = ({ children, tag, item }) => (
|
||||
<a style={{ color: tag ? tag.color : '#faa' , fontWeight: 'bold', cursor: 'pointer' }} key={tag ? tag.id+item!.id : item.id} onClick={() => {
|
||||
addFilterTag(tag!);
|
||||
// map.fitBounds(items)
|
||||
// map.closePopup();
|
||||
}}>{children}</a>
|
||||
);
|
||||
|
||||
return (
|
||||
<p style={{ whiteSpace: "pre-wrap" }} className="!tw-m-0 !tw-mb-2 !tw-mt-2">
|
||||
<Markdown components={{
|
||||
p: CustomParagraph,
|
||||
a: ({ href, children }) => {
|
||||
if (href?.startsWith("#")) {
|
||||
console.log(href);
|
||||
|
||||
const tag = tags.find(t => t.id.toLowerCase() == href.slice(1).toLowerCase())
|
||||
console.log(tag);
|
||||
|
||||
return <CustomHashTagLink tag={tag} item={item}>{children}</CustomHashTagLink>;
|
||||
} else {
|
||||
return (
|
||||
<CustomExternalLink href={href}>{children}</CustomExternalLink>
|
||||
);
|
||||
}
|
||||
},
|
||||
ul: CustomUnorderdList,
|
||||
ol: CustomOrderdList,
|
||||
img: CustomImage,
|
||||
h1: CustomH1,
|
||||
h2: CustomH2,
|
||||
h3: CustomH3,
|
||||
h4: CustomH4,
|
||||
h5: CustomH5,
|
||||
h6: CustomH6,
|
||||
}}>
|
||||
{replacedText}
|
||||
</p>
|
||||
</Markdown>
|
||||
)
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: a
|
||||
}
|
||||
|
||||
</div>
|
||||
<div className='tw-flex -tw-mb-1 tw-flex-row-reverse tw-mr-2'>
|
||||
<div className='tw-flex -tw-mb-1 tw-flex-row tw-mr-2'>
|
||||
|
||||
|
||||
{
|
||||
|
||||
@ -51,7 +51,6 @@ export function ProfileSettings() {
|
||||
|
||||
function onImageLoad(e: React.SyntheticEvent<HTMLImageElement>) {
|
||||
const { width, height } = e.currentTarget
|
||||
console.log(width);
|
||||
|
||||
setCrop(centerAspectCrop(width, height, 1))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user