feat: replace rich text editor with custom Tiptap implementation and add HTML formatting utilities
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import React from "react";
|
||||
|
||||
export function FormattedText({ text }: { text: string }) {
|
||||
const lines = text.split('\n');
|
||||
const urlRegex = /(https?:\/\/[^\s]+)/g;
|
||||
|
||||
return (
|
||||
<>
|
||||
{lines.map((line, i) => {
|
||||
const parts = line.split(urlRegex);
|
||||
return (
|
||||
<React.Fragment key={i}>
|
||||
{i > 0 && <br />}
|
||||
{parts.map((part, j) => {
|
||||
if (part.match(urlRegex)) {
|
||||
return (
|
||||
<a
|
||||
key={j}
|
||||
href={part}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline underline-offset-4"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{part}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
return part;
|
||||
})}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import * as React from "react"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
export interface HtmlDisplayProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
html?: string | null;
|
||||
}
|
||||
|
||||
export function HtmlDisplay({ html, className, ...props }: HtmlDisplayProps) {
|
||||
if (!html) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn("prose prose-sm dark:prose-invert max-w-none [&>p]:m-0", className)}
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user