Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: A renderless and extendable rich-text editor for Vue.js (github.com)
278 points by hanspagel 5 months ago | hide | past | web | favorite | 74 comments

I started paying attention to this when i saw the "Suggestions" demo. https://tiptap.scrumpy.io/suggestions

Every rich text editor I've tried so far, it's been a nightmare to add autocomplete for stuff like mentions and hashtags. I haven't integrated tiptap yet so maybe it's the same, but the code for the demo looks very promising.

At a quick glance tiptap looks great and I don't want to derail the thread mentioning another solution, but after admittedly struggling longer than I'd hoped to implement mentions into a Vue-compatible RTE I got it working fine using modules (NPM) `vue-quill-editor` and `quill-mention`.

Since this is the first public thread I've ready of at least one other person struggling with this (I'm sure there are others), I created this gist of my Vue component in case it helps anyone who want to use Quill instead of tiptap: https://gist.github.com/whatl3y/d1a9fb7bab75c2188b226e902c6f...

Looks great, thanks for the recommendation!

That's one reason why I built tiptap!

As a frontend dev, this is really, really nice and I wish more libraries followed the renderless principles. So many manhours are wasted, daily, just because a library is a tad too specific about it's preferences. It would be nice to see it standardized in some shape or form so that it's both easier to write for newcomers as well as test.

For those who were confused about the "renderless" bit:

> What does renderless mean?

> With renderless components you'll have full control over markup and styling. tiptap doesn't tell you what a menu should look like or where it should be rendered in the DOM. That's all up to you.


I like it too - the pitch reminds me of https://github.com/enkidevs/seapig (where I first saw this pattern explained for React)

I read the renderless article linked to in the README (https://adamwathan.me/renderless-components-in-vuejs/) and it seems like an absolute nightmare in Vue. Lots of cognitive overhead for something that's completely natural in React.

I didn't downvote your comment, but it seems you've misunderstood the core concepts under discussion here. Renderless isn't inherent to Vue in any way — the problems it addresses are equally present in React-based libraries. You can easily override render functions and the given bindings in both Vue and React, but given libraries that aren't built to be easily extendible, this can often lead to maintenance nightmares. Renderless seeks to counteract that, giving guidelines to architect libraries in a way that doesn't introduce considerable complexity on the library side but makes it a lot more extensible on the consumer side.

I think you've misunderstood my post. I'm saying renderless components come "for free" in React -- there's no cognitive overhead or new concepts to learn. It's something that comes very naturally as you develop React components to the point where I've been writing renderless components for years without ever really thinking about it. From reading the article linked above it feels very clumsy in Vue based on the fact that there's a whole feature (slots) which not only feels fairly magical but requires a rather meaty article to explain it's usage.

I guess what I'm saying is if you're really interested in renderless components it's probably easier to just use React.

I still don't really see what you mean — the functionalities are practically identical between the two frameworks, Vue uses slots, React uses props children. The only difference is naming and minor semantics differences. The same principles apply for both, and the discussion is just as relevant for both. Personally I prefer the Vue approach over the React one since React components are usually build more black-box style in this architecture, but that is mainly a preference argument. The "cost" of the approach is the same in both libraries.

> The only difference is naming and minor semantics differences

I don't agree at all. There are no naming/semantics for doing renderless in React. React has no analogue for "slots" because it's just naturally part of the framework. It's as simple as doing:

   <LinkList renderLink={(linkProps) => <div>...</div>} />
No extra terminology to learn, no slot keys, extra attributes, or rendering magic, and definitely not something you need a whole article to explain.

That's a basic example which doesn't address the topics discussed in the article at all. The same is just as easy in Vue, even with identical property names if you like.

    <link-list :render-link="(props) => ..." />
The whole idea of renderless is to move beyond this very limited and crude approach for library code where you might need to override only small bits of the logic or all of the logic, depending on your use case. At the moment I can't help but feel you've missed the core ideas of the article and we're discussing completely different points.

Why would you want to use slots, then? It's just extra steps for the same functionality.

> The whole idea of renderless is to move beyond this very limited and crude approach for library code where you might need to override only small bits of the logic or all of the logic, depending on your use case

Not at all. For example, react-select does this super seamlessly: https://react-select.com/components

I guess what I'm trying to say is I don't understand why it seems so complicated in Vue.

This is really cool! and I really want to adopt it. I have a question though, can the data be represented as markdown, instead of html and json?

My current editor is monaco and the format is markdown. Monaco is too heavy, I want something closer to what Medium.com has. This renderless rich-text editor looks perfect. But my backend accepts only markdown ...

And I also need to support math equations ...

There is already a feature request about markdown support. You can follow that issue on github. At the moment I'm not sure if this will land in tiptap.

>can the data be represented as markdown

Sounds like a niche enough requirement that you'd be better off writing some form of transformation logic for your needs that can produce a markdown approximation from the JSON structure that the editor generates.

This is really awesome. I’ve been watching Prosemirror for a long time and have considered building something like this on top of it, but haven’t had the time to try. I’ve been using Quill instead, since it’s a lot simpler and was pretty easy to just drop in place. This looks like a nice upgrade though!

We used Quill before as our rich text editor at scrumpy.io … a few months later I started working on tiptap :)

Nice work here, very smooth and supports a good set of functionality by default.

Added to the list of HTML editor: https://gist.github.com/manigandham/65543a0bc2bf7006a487

Might be nice to do some more input validation, particularly for links - the editor is happy to insert a javascript: link. I don't think this poses a security issue (at most, you'll get what - a self XSS?) because you'd obviously do server-side sanitisation in a real application, but it might be nice to check for non-https protocols and warn the user when they insert them?

Good catch! That should be easily done.

It fascinating that in 2019 we aren't able to get one text editor that would work seamlessly across all frameworks , but instead need to basically re-write huge "bindings" to support the reactivity and the rendering logic in each of them.

Web Components have definitely failed.

While I agree we (as in the internet at large) haven't solved the text editor problem, by saying "web components have failed" you're concluding in bad faith.

If such a "universal rich text edit" web component comes out, have web components then succeeded? Then failure isn't such a permanent state as your comment implies, rather an indication of work yet to be done.

Unless you'd like to clarify more, your comment seems to me like you're flinging mud without being able to back it up. What's the reason for that?

Of note, Trix has been using the `customElements` standard since forever: https://github.com/basecamp/trix/

There's also slate, the (old!) tinymce, umm... I know I've at least experimented with a good couple more I can't recall.

And, on the topic of components I wish existed (anywhere - react, vue, angular, etc - anything), I've been searching for a good rich multiselect for a long time! If you know of any please let me know :)

> And, on the topic of components I wish existed (anywhere - react, vue, angular, etc - anything), I've been searching for a good rich multiselect for a long time! If you know of any please let me know :)

Select2 [1] has been around forever but it's always worked out pretty nicely for me.

It's a jQuery plugin, so it's somewhat out of vogue these days, but it's trivially easy to wrap it in a component to make it play nicely with Vue (in fact, the Vue documentation uses it as the example for writing wrapper components [2]). I imagine something similar can be done with React, Angular, etc., though I'm not too familiar with the process there.

[1] https://select2.org

[2] https://vuejs.org/v2/examples/select2.html

not that there's anything wrong with jquery or select2, both of which i used heavily in the past, but if you're working in vue it's a very nice feeling to just completely drop the jquery dependency. ive been using https://github.com/shentao/vue-multiselect for over a year now in production and despite its quirks i'd recommend it.

ooooh nice. I didn't know this was a thing. Yeah, the jquery bundle size really isn't justified for a single thing (rich multiselect). I recently ported `selectr` for use in an app at work, but I'd love to replace it as there's some wonkiness

> If such a "universal rich text edit" web component comes out, have web components then succeeded?

I think (but this is my interpretation) that GP meant to assert by saying "Web Components failed" that no such component will ever come out, because Web Components cannot properly solve that use case. I haven't delved into it deeply, but my intuition is that, indeed, quite a lot of ceremony would be needed to integrate such a component into a larger web app, regardless of whether you use a framework or which one.

What does this have to do with Web Components? Even if you used Web Components you would still need to write bindings for each framework.

It's built on top of ProseMirror (plain JavaScript).

You only have 5 comments, all from today, and 2 of them were flagged dead. I couldn't see any reason why so I vouched for them. I am a bit confused about the situation though.

Sorry I'm not very active here. Reading most of the time.

Oh no worries at all. I was just curious why your comments were flagged, as they seemed perfectly fine.

it's HN. that's why :)

Shame that HN works like that. Anyway, upvoted your comments too ;) Thanks for creating tiptap, you rock!!!!

Same thing goes about almost all controls and UI elements existing inside web browsers. I'm around web development for years and it's very saddening and heart breaking for me to see all this milling around in one place, round and round and results are not that much different.

Sometimes I really, really dread this whole "frontend" related churn, tooling, javascript and it's quirks. I looked at Flutter recently wondering - maybe this is the answer? But this probably is just another turn of the wheel, it was attempted already in the past with adobe air/flex and many other projects.

Maybe reason for this is that programming and whole IT is very young craft, mere child's play compared to different industries like for example construction which has thousands years of history, trials, successes and errors.

the web is a really poor abstraction for building UIs and it's kinda incredible that we collectively don't internalize that simple lesson. We have hacked to death a platform for linked text documents because it's what everyone has, that's the extent of the merits of the web platform, but it's not a good fit for what we're trying to do in the productivity world. Flex for example was leaps and bounds better in that regard, and any desktop OS is too. Javascript is a poorly designed language that we beat into submission by working around its many, many flaws.

We keep making this mistake of wanting to use what's available instead of coming together to build something better, so we waste MILLIONS of collective hours because we're dumb.

creator of tiptap here. a bit late, unfortunately.

Can you write an editor that moves on from 1990's WYSIWYG to use the HTML5 content sectioning elements, so that different 'sections' and 'asides' can be moved around? In so doing - and nesting them - the headings could be given an automatic h2 - h6 level, with the headings inside sections/articles.

It would also be nice to see details/summary entries and nothing in the toolbar that creates inline CSS things.

Out the box such an editor should create accessible HTML that can be easily styled, with structure to it that would result in a document outline.

I think such an editor could be what a lot of the web needs, to make people wonder why we ever had WYSIWYG backend editors that render nothing like the frontend, e.g. the things you get in Wordpress and other content editors.

WYSIWYG made sense in the 1990's when what you wanted was a printed 'dead tree' page, but we have responsive design now and lots of different screen sizes, so it is getting the structure right that matters more, not just for accessibility but SEO.

This is really slick. I like it.

Would love details on browser support, though.

It's built on top of ProseMirror. They're targeting IE11.

Yaaaay, there is a project that integrates it with vuetify my favourite vue UI kit:


I used this for a demo (that took about 30 minutes to build) and my stakeholders loved it. Thanks!

On the topic of rich text editors (since people mentioned Slate) what's your opinion of react's draft.js?

Not OP, but I was an early contributor to Draft.

Draft JS lacks a few features, notably nested block support (tables) and a schema definition and sanitization. Slate is more focused on providing a nice plugin experience.

On the plus side Draft’s core is battle tested and has just picked up Android support, and has the excellent Draft JS Plugins resource.

While this is really nice, it's a shame that a VueJS developer is unable to re-use a React-based text-editor which already exists and he found it perfect. This is why Web Components start making a lot of sense.

I didn't call it "perfect". Slate.js is great but has some downsides too. But for Vue.js there was like nothing, so I took the first step.

There is also a core package of Slate, so it's up to you to build a wrapper for Vue too. Slate is still in beta. That's why I chose to built on top of ProseMirror.

Will web components let him use a React module with Vue.js without loading both libraries and learning React?

Or is web components a third library that is so much better that you don’t need the other two libraries?

Is this the situation where there are too many standards and you can only solve the problem by creating another standard?

Web Components should replace them both. They aren't standards - just frameworks developed by third parties. The Web Components standard is the official standard and should be the one people reach for

Web components can't make React/Vue/Angular components reusable anywhere else, but web components themselves are reusable in React/Vue/Angular apps.

It is possible to use a react component in a Vue app but of course what it does to your page weight may not be acceptable.


This depends on the app however. For a landing page? No way. For a module within an app I would not mind, as long as lazy imports are used.


So you are getting downvoted because you are shitposting some off-topic stuff. I don't know why we have to talk about React in every thread about Vue. But I'll respond anyway.

I like both React and Vue. I used React first, but I've used Vue for longer now. React introducing a new feature doesn't change anything about what makes Vue.js good. One thing I like about Vue.js is that basic data binding is a job that is done by the framework, instead of the programmer. Another thing that I like is that async methods are supported everywhere that methods are supported. So async mounted works great for data loading. We do not "know that lifecycle is a bad pattern". Its just a pattern, and implementations can be good or bad.

As for react, I don't think hooks are the end of the story:


Ya, I also could not understand why lifecycle is bad, because not only vue has it, other frameworks, like iOS sdk also has this concept.

And I have never had trouble using them.

I googled “lifecycle bad pattern. And found https://hackernoon.com/problematic-react-lifecycle-methods-a...

But I didn’t see it explaining why it is bad.

Lifecycle is not to be reused. Hooks could be reused and used everywhere you want.

In Vue nothing prevents you from reusing a common function in or as a lifecycle method. I’m sure you think mixins are bad too, since Dan does, but you can also just use plain functions and bind this.

You're reusing a function, not a lifecycle.

The react community has decided reacts implementation of lifecycle methods has some downsides. Every pattern has pros and cons, which may play out differently in different implementations.

Hooks of course is not the end of story. It's just an evolution of how we do UI/UX.

My comment is due to the fact that, the OP editor uses a lifecycle, which relates to me, on the fact that i DID NOT choose Vue.

Now i'm happy with ReactJS, Hook, Suspense, and more.

Perhaps you're just most comfortable with react and vue seeming inferior is only a product of that. Both are great at what they do and allow people to be very productive. I personally like both and don't agree that vue only copies react. I definitely prefer how react manages state and redrawing, but both approaches have merits. As always, pick what suits the problem you need to solve.

For a software project, library/framework choice is the most critical thing one must do.

For the VueJS case, i did really want to adopt it for my projects, but there's a fact that i'm not confident. They're not just "function".

And as i said above, in React case, they're moving away from "component lifecycles", so if i chose VueJS, i'll get stuck in that paradigm.

React still has a "component lifecycle" -- it's just with hooks the way you interact with that lifecycle is different [1].

> Hooks are a more direct way to use the React features you already know — such as state, lifecycle, context, and refs. They don’t fundamentally change how React works, and your knowledge of components, props, and top-down data flow is just as relevant.

And if you like functional components, VueJS has them as well [2]

[1]: https://reactjs.org/docs/hooks-faq.html#how-much-of-my-react... [2]: https://vuejs.org/v2/guide/render-function.html#Functional-C...

You should try software engineering instead of chasing fads. You cannot go wrong choosing either framework.

It's about the HOW.

How we think, how we code. Yes, you can't go wrong choosing one or another, but you can't change anything in your mind about software engineering.

Hopefully, your mind can change when presented with new information.

> library/framework choice is the most critical thing one must do

This is officially trolling.

I’m not sure what you mean by “lifecycle”, but just to be clear, hooks are tied to the component lifecycle.

They're "didMount", "didX",...

> as we know that `lifecycle` is a bad pattern.

What ever do you mean by this? Hooks are more ergonomic in some scenarios, react's class methods in others.

You're getting downvoted for a good reason, your comment has no place here, this is not a react vs vue debate.

IMO, the biggest appeal of Vue is the same PHP's had for a long time - the ability to just drop a file on a server and see it working. Embedding Vue via <script> tag works beautifully - no Webpack, no plugins, etc.

Great way to get started and experiment. Sure, once you want to do more, you'll want build tooling etc., but that initial ease is really compelling for someone who's learning.

I mean, I prefer Vue for reasons, but I'm pretty sure you can do that with React too...

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact