novel icon indicating copy to clipboard operation
novel copied to clipboard

Not able to set HTML in `defaultValue`

Open tksumanth1994 opened this issue 1 year ago • 14 comments

In tiptap, setContent can be used with HTML.

image

But, in Novel, it renders as a string when I set defaultValue as HTML - <p>Hello</p>.

This code

<Editor
    disableLocalStorage={true}
    defaultValue="<p>Hello</p>"
/>

renders this

image

Is there a workaround for this?

tksumanth1994 avatar Oct 19 '23 08:10 tksumanth1994

I'm also hitting this - if you look at where the code sets the content, it's just calling setContent directly in tiptap. Looking upstream I don't see anyone reporting it, but I'm wondering if this is a regression there

tiniscule avatar Oct 25 '23 13:10 tiniscule

Actually - found it. Novel uses the tiptap-markdown extension, which overrides the setContent function with its own. This line here sets HTML support to false, but I'm not sure why. Swapping this to true enables support for markdown. I don't want to submit a PR for this as I'm not sure why it's disabled in the first place. I've enabled it in my local copy.

https://github.com/steven-tey/novel/blob/b4526fc63175caed02bdbfbee490e87b3466dd1c/packages/core/src/ui/editor/extensions/index.tsx#L137-L140

tiniscule avatar Oct 25 '23 14:10 tiniscule

@steven-tey this error isnt solved yet

swarajbachu avatar Jan 13 '24 15:01 swarajbachu

As a workaround for this I'll add PR so you can configure/remove the Markdown extension

andrewdoro avatar Feb 13 '24 09:02 andrewdoro

Any update on this one? Does Novel have any other solution for this?

bouceka avatar Feb 22 '24 06:02 bouceka

I tried to find a solution as the Tiptap editor allows you to set content with either JSONContent or HTMLContent Screenshot 2024-02-24 at 11 05 13 AM Novel does not allow that, or at least not by default Screenshot 2024-02-24 at 11 05 36 AM Unfortunately, even though I changed the markdown and configured the HTML to true, it still does not work for me. If anyone has a neat solution, please let me know.

bouceka avatar Feb 24 '24 19:02 bouceka

+1 on this issue. This seems to be a very important feature missing which is supposed to be supported out of the box. I would suggest exposing lower level APIs from TipTap so we can hook into this directly. @andrewdoro

JasonDevTech avatar Feb 29 '24 06:02 JasonDevTech

+1 does anyone have a solution for passing html? Thanks

lh15 avatar Mar 10 '24 04:03 lh15

this worked for me, I am able to set html by converting it to json. However, the style won't apply automatically

import { generateJSON } from "@tiptap/html";

	useEffect(() => {
		const htmlString: string = `<h1><strong>This is strong</strong></h1>
		<h2><b>And this</b></h2>
		<h3 style="font-weight: bold">This as well</h3>
		<p>Oh! and this</p>
		<p style="color: #E00000">Cool!</p>`;
		console.log(generateJSON(htmlString, extensions));
		setInitialContent(generateJSON(htmlString, extensions));
	}, []);

We need to handle these style using global attributes and create a custom extension as mentioned here

below is an example i used to apply colors and passed it as an extension

import { Extension } from "@tiptap/core";

const style = Extension.create({
	addGlobalAttributes() {
		return [
			{
				// Extend the following extensions
				types: ["heading", "paragraph"],
				// … with those attributes
				attributes: {
					textAlign: {
						default: "left",
						renderHTML: (attributes) => ({
							style: `text-align: ${attributes.textAlign}`,
						}),
						parseHTML: (element) => element.style.textAlign || "left",
					},
					color: {
						default: "#000000",
						renderHTML: (attributes) => ({
							style: `color: ${attributes.color}`,
						}),
						parseHTML: (element) => element.style.color || "#000000",
					},
				},
			},
		];
	},
}); 

amang06 avatar Mar 10 '24 05:03 amang06

@amang06 Did you have to add every possible HTML element to extensions?

My concern is that if I miss something, it'll break the original html.

I am using this as a wordpress post editor

lh15 avatar Mar 10 '24 06:03 lh15

@lh15 I am afraid yes. Refer this I also share your concern, I guess we are better off storing both json and html at this point.

amang06 avatar Mar 10 '24 06:03 amang06

This is how I solved it. I store both HTML and JSON objects.

bouceka avatar Mar 10 '24 06:03 bouceka

Can you explain how it helps to store both the html and json?

Say I load in html from a wordpress post, once I parse it into tiptap, I lose data.

I can't really "recover" the missing data.

lh15 avatar Mar 10 '24 06:03 lh15

Tiptap provided the api to convert html into tip-tap json. See here

Uses

import { generateJSON } from "@tiptap/html";

import Document from "@tiptap/extension-document";
import Paragraph from "@tiptap/extension-paragraph";
import Text from "@tiptap/extension-text";
import CodeBlock from "@tiptap/extension-code-block"; 


const html = `<h2>Introducing salman</h2>`
const json = generateJSON(html, [Document, Paragraph, Text, CodeBlock]); // import and add more extensions as needed
console.log(json);

prathamesh-dukare avatar Mar 31 '24 06:03 prathamesh-dukare