ueberdosis / tiptap

The headless rich text editor framework for web artisans.
https://tiptap.dev
MIT License
27.77k stars 2.31k forks source link

Output as Vue components #1221

Closed timhanlon closed 2 years ago

timhanlon commented 3 years ago

The problem I am facing I can create interactive nodes for the tiptap editor but when it comes time to output, generateHTML is the only option.

The solution I would like A way to generate Vue components on the front end from the ProseMirror JSON.

Alternatives I have considered I've previously hacked a solution together on a Wordpress/Nuxt project by using node-html-parser, processing the childNodes, and feeding them into components...but it's not ideal.

sugoidesune commented 3 years ago

nuxt-content can do that. https://content.nuxtjs.org/writing#vue-components Would be very interesting to see.

crnkovic commented 3 years ago

I agree -- if you build a custom extension and implement addNodeView method that renders a Vue component, or any specific tree of DOM elements, your editor "look" would be different to the rendered HTML -- mostly because addNodeView and renderHTML render different structure.

One example. Say you have an Avatar Vue component that renders the user avatar based on initials. When mention is rendered in the editor, it should display the user avatar (by rendering a Vue component) next to the name of the mentionee (basically avatar instead of the @). Implementing addNodeView that returns VueNodeViewRenderer(Mention) component works great. But since renderHTML doesn't really support "complex" DOM elements, such as this one (root element with 2 children), it's very hard to get the same HTML markup to be rendered in e.g. blog post. Or maybe I'm just missing something?

If you also want to render the same mention style (avatar + name) in the HTML in your blog post/whatever, the only way I can think of is regex matching the <some-tag data-mention=""></some-tag> (or whatever renderHTML returns) and replacing with the actual markup.

Utility to generate the same markup that the editor renders (so including addNodeView) would be amazing, or else the way to parse custom Vue components :)

philippkuehn commented 3 years ago

But since renderHTML doesn't really support "complex" DOM elements, such as this one (root element with 2 children)

This is not true. You can do something like this:

renderHTML() {
  return ['p',
    ['span', { contentEditable: 'false' }, 'this is not editable'],
    ['span', 0],
  ]
}
FreekVR commented 3 years ago

Yes, I would love to see this! For example, to process some HTML elements into custom vue component, for example using an optimized nuxt-image in place of a normal HTML img-tag. As far as I've been able to find, there's no library anywhere that lets you easily map prosemirror json structures to vue components, only to normal HTML, which wouldn't be reactive (eg. the same as using v-html). The new HTML utility comes close: https://www.tiptap.dev/api/utilities/html/ but this uses normal DOM structures and not Vue.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Youhan commented 6 months ago

I've seen StoryBlok has implemented their own richtextRenderer that accepts Prosmirror JSONContent and you can add vue components like <NuxtImg to handle rendering of a block. https://github.com/storyblok/storyblok-js-client