sjdemartini / mui-tiptap

A Material UI (MUI) styled WYSIWYG rich text editor, using Tiptap
MIT License
289 stars 38 forks source link

Rendering Content without `RichTextReadOnly` #245

Closed Jasermon closed 2 months ago

Jasermon commented 2 months ago

Describe the bug

I created my editor using CodeSandbox Repo as a reference. Everything works very well. My problem occurs when rendering the HTML code I receive with getHTML().

If I had to give an example, here is the post in editor;

image

When I render it with the following code it looks like this:

<Box dangerouslySetInnerHTML={{ __html: details.items.content }}

image

When I render it with RichTextReadOnly it looks like this:

image

But I don't want to use RichTextReadOnly. I have several reasons for this:

Expected behavior

A component that allows the content received with getHTML() or getJSON() to be rendered as in the editor can solve this problem.

System (please complete the following information)

export default function useExtensions({ placeholder } = {}) {
    return useMemo(() => {
        return [
            TableImproved.configure({
                resizable: true,
            }),
            TableRow,
            TableHeader,
            TableCell,
            BulletList,
            CodeBlock,
            Document,
            HardBreak,
            ListItem,
            OrderedList,
            Paragraph,
            CustomSubscript,
            CustomSuperscript,
            Text,
            Bold,
            Blockquote,
            Code,
            Italic,
            Underline,
            Strike,
            CustomLinkExtension.configure({
                autolink: true,
                linkOnPaste: true,
                openOnClick: false,
            }),
            LinkBubbleMenuHandler,
            Gapcursor,
            // HeadingWithAnchor,
            Heading,
            TextAlign.configure({
                types: ["heading", "paragraph", "image"],
            }),
            TextStyle,
            Color,
            FontFamily,
            FontSize,
            Highlight.configure({ multicolor: true }),
            HorizontalRule,
            ResizableImage,
            Dropcursor,
            TaskList,
            TaskItem.configure({
                nested: true,
            }),
            Placeholder.configure({
                placeholder,
            }),
            History,
        ];
    }, [placeholder]);
}
sjdemartini commented 2 months ago

Hi @Jasermon, as mentioned in https://github.com/sjdemartini/mui-tiptap/issues/136#issuecomment-2049890241, getHTML is a serialized representation of your content. While it can be used for display, there are Tiptap extensions where the Tiptap-based rendering of that content will visually differ from the serialized data due to JS-based logic used in rendering (where the serialized content is parsed but the visual representation is more involved).

For your particular extensions, which in general perhaps don't need any additional JS-based logic, you may be able to apply the mui-tiptap styles to your dangerouslySetInnerHTML element via using the getEditorStyles utility from mui-tiptap (e.g. similar to what the mui-tipap RichTextContent component does here).

In general though, if you want your editor and your serialized content to render/look the same, you should let Tiptap do the rendering, which is what RichTextReadOnly is for.

Jasermon commented 2 months ago

Hi @Jasermon, as mentioned in #136 (comment), getHTML is a serialized representation of your content. While it can be used for display, there are Tiptap extensions where the Tiptap-based rendering of that content will visually differ from the serialized data due to JS-based logic used in rendering (where the serialized content is parsed but the visual representation is more involved).

For your particular extensions, which in general perhaps don't need any additional JS-based logic, you may be able to apply the mui-tiptap styles to your dangerouslySetInnerHTML element via using the getEditorStyles utility from mui-tiptap (e.g. similar to what the mui-tipap RichTextContent component does here).

In general though, if you want your editor and your serialized content to render/look the same, you should let Tiptap do the rendering, which is what RichTextReadOnly is for.

Thanks for your answer. I have no problem using RichTextReadOnly, but I am bothered by the issue of setting the contenteditable prop to true with DevTools. Isn't there any way to prevent this?

sjdemartini commented 2 months ago

@Jasermon Your concern is a user changing contenteditable to true via dev tools, and thereby being able to edit stuff they otherwise shouldn't be able to edit? I don't believe there's a way to prevent someone from manipulating the DOM manually/externally to the application. Even if this were preventable via JS, couldn't they also then manipulate the JS? I don't know that there will be reasonable ways to prevent it, but you could try looking through Tiptap's issues and discussions (https://github.com/ueberdosis/tiptap) and/or Prosemirror's to see if anyone else discussed something similar. This sort of thing is outside of mui-tiptap in particular. Good luck!