novel
novel copied to clipboard
Not able to set HTML in `defaultValue`
In tiptap, setContent
can be used with HTML.
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
Is there a workaround for this?
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
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
@steven-tey this error isnt solved yet
As a workaround for this I'll add PR so you can configure/remove the Markdown extension
Any update on this one? Does Novel have any other solution for this?
I tried to find a solution as the Tiptap editor allows you to set content with either JSONContent or HTMLContent
Novel does not allow that, or at least not by default
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.
+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
+1 does anyone have a solution for passing html? Thanks
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 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 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.
This is how I solved it. I store both HTML and JSON objects.
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.
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);