steven-tey / novel

Notion-style WYSIWYG editor with AI-powered autocompletion.
https://novel.sh
Apache License 2.0
13.21k stars 1.08k forks source link

feat: Allow Markdown and Html in InitialContent #405

Open fedjabosnic opened 5 months ago

fedjabosnic commented 5 months ago

Describe the feature you'd like to request

I'd like to set initial content to Markdown or Html in string form, received over the wire. At present, the Novel Editor only allows JSONContent to be passed into initialContent and there is no easy facility to convert. This makes it very hard to work with HTML and MD content directly, especially in string form..

Describe the solution you'd like to see

Looking at the types in the core TipTap library, it seems that we can use the union type Content - or even define a union type ourselves. I'm not sure if there are some roadblocks in the codebase but this would allow us to pass any supported type of content to the editor...

CleanShot 2024-05-31 at 16 42 23@2x

Additional information

My use-case is simple, I want to edit content coming from an api call that is either Markdown or Html, and at the moment I can't really get this running. Admittedly I'm not super experienced in Next, React or TipTap so please let me know if there is a decent solution already

MODSetter commented 5 months ago

@fedjabosnic Markdown is not supported by Tiptap. I can look into making editor compatible with html. For your current use case you can see html updates in LocalStorage (key: "html-content").

jacobsamo commented 5 months ago

Would also love this feature as i want to store the content in my db as HTML or text

RealKai42 commented 3 months ago

So is there any way to pass markdown to JSONContent ?

amozoss commented 3 months ago

Would also love this feature as i want to store the content in my db as HTML or text

I used the import { EditorProvider } from "@tiptap/react"; instead of EditorContent (it's just a wrapper anyway).

Then it seems MarkdownExtension was causing html to not work when passed as content, so I removed that extension and I could use html

rossanodr commented 1 month ago

any updates on this issue?

ujasbhuva commented 5 days ago

This worked for me. I added one additional extension markdownExtension in extensions.ts.

import {  MarkdownExtension } from "novel/extensions";

const markdownExtension = MarkdownExtension.configure({
  html: true,
  tightLists: true,
  tightListClass: 'tight',
  bulletListMarker: '-',
  linkify: false,
  breaks: false,
  transformPastedText: false,
  transformCopiedText: false,
})

export const defaultExtensions = [
  markdownExtension
];

This allows initial content as Markdown or Html in string form.

rossanodr commented 4 days ago

html: true, tightLists: true, tightListClass: 'tight', bulletListMarker: '-', linkify: false, breaks: false, transformPastedText: false, transformCopiedText: false,

How did you manage to make TypeScript stop complaining with 'Type 'string' is not assignable to type 'JSONContent'?

<EditorContent
                    initialContent={''}
ujasbhuva commented 4 days ago

html: true, tightLists: true, tightListClass: 'tight', bulletListMarker: '-', linkify: false, breaks: false, transformPastedText: false, transformCopiedText: false,

How did you manage to make TypeScript stop complaining with 'Type 'string' is not assignable to type 'JSONContent'?

<EditorContent
                    initialContent={''}

just modify your variable initialContent and add string as a type

const [initialContent, setInitialContent] = useState<null | string | JSONContent>(null);
<EditorContent
            initialContent={initialContent}
            ...
            ...
rossanodr commented 4 days ago

const [initialContent, setInitialContent] = useState<null | string | JSONContent>(null);

the problem is that my Editor show the error

type '{ children: Element[]; extensions: (Node<any, any> | Extension<any, any> | Mark<SubscriptExtensionOptions, any>)[]; ... 6 more ...; initialContent: string | ... 1 more ... | null; }' is not assignable to type '{ readonly children?: ReactNode; readonly className?: string | undefined; readonly initialContent?: JSONContent | undefined; }'.
  Types of property 'initialContent' are incompatible.
    Type 'string | JSONContent | null' is not assignable to type 'JSONContent | undefined'.
      Type 'null' is not assignable to type 'JSONContent | undefined'.ts(2322)

even after using the MarkdownExtension

ujasbhuva commented 4 days ago

const [initialContent, setInitialContent] = useState<null | string | JSONContent>(null);

the problem is that my Editor show the error

type '{ children: Element[]; extensions: (Node<any, any> | Extension<any, any> | Mark<SubscriptExtensionOptions, any>)[]; ... 6 more ...; initialContent: string | ... 1 more ... | null; }' is not assignable to type '{ readonly children?: ReactNode; readonly className?: string | undefined; readonly initialContent?: JSONContent | undefined; }'.
  Types of property 'initialContent' are incompatible.
    Type 'string | JSONContent | null' is not assignable to type 'JSONContent | undefined'.
      Type 'null' is not assignable to type 'JSONContent | undefined'.ts(2322)

even after using the MarkdownExtension

It is happening because EditorContent component from novel has initialContent?: JSONContent | undefined .

So in this case we can use any type for initialContent. This solution might be helpful for you.

const [initialContent, setInitialContent] = useState<any>(null);