Read our blogs, tips and tutorials
Try our exercises or test your skills
Watch our tutorial videos or shorts
Take a self-paced course
Read our recent newsletters
License our courseware
Book expert consultancy
Buy our publications
Get help in using our site
547 attributed reviews in the last 3 years
Refreshingly small course sizes
Outstandingly good courseware
Whizzy online classrooms
Wise Owl trainers only (no freelancers)
Almost no cancellations
We have genuine integrity
We invoice after training
Review 30+ years of Wise Owl
View our top 100 clients
Search our website
We also send out useful tips in a monthly email newsletter ...
Introducing (finally!) our new web-based HTML editor using TipTap |
---|
After a few false starts we have finally created our web-based HTML editor using TipTap. It's been one of the hardest IT projects we've embarked upon, so we thought we'd share our learning experiences in the hope that they will save others our pain. |
In this blog
How hard can it be to create an HTML editor?
Our new HTML editor, complete with custom toolbars.
The answer? Surprisingly hard!
Our original intention was to create our own HTML editor, but it turns out that this is unfeasibly difficult to do because of the way HTML is constructed:
There's one small example above - if a user presses Del, what should the results be?
After reviewing hundreds of websites and articles, we eventually plumped for writing a Windows system in Python using PyQt - only to run into a brick wall after a month or more of development.
This metaphor isn't quite right: it was more like running into a bog, with progress getting slower and slower. The problem, as always with Windows systems, was handling events in a grid of data.
Chastened, we went back to the drawing-board. After reviewing many platforms (including Quill, ProseMirror, TinyMCE and CK Editor) we eventually decided to run with TipTap. The rest of this blog explains what TipTip is and how it works, gives some advice which we wish we'd known when we started and finishes with our recommendations for whether you should use it.
Many HTML editors are built on a platform called ProseMirror, You would expect an HTML editor to use HTML to construct blocks of text:
The above paragraph in HTML view.
However, ProseMirror uses a completely different structure to construct passages of text, then translates this into HTML when requested. You can choose which ProseMirror nodes you want your editor to support:
Part of our HTML editor: some of these nodes are just imported as is, but some of them have been extended (ie we've added additional functionality to them).
TipTap is written in TypeScript, but you can use plain JavaScript if you prefer to implement it (in either React, Vue or just a plain environment).
We went with Vue (because we had experience using this) and TypeScript (because we liked the fact that everything is strongly-typed). In retrospect we should perhaps have gone for JavaScript, as there are many more JS than TS examples on the web.
To give an idea of what TipTap involves, here's what our editor looks like in Visual Studio Code, without any embellishment from any surrounding webpage:
The vanilla TipTap editor is an editable text box.
We then add in these extensions from TipTap:
import { Component, Emit, Prop, Vue } from 'vue-facing-decorator'
import { Editor, EditorContent } from '@tiptap/vue-3'
import Document from '@tiptap/extension-document'
import History from '@tiptap/extension-history'
import Heading from '@tiptap/extension-heading'
import Text from '@tiptap/extension-text'
import BlockQuote from '@tiptap/extension-blockquote'
import Code from '@tiptap/extension-code'
import DropCursor from '@tiptap/extension-dropcursor'
import GapCursor from '@tiptap/extension-gapcursor'
import HardBreak from '@tiptap/extension-hard-break'
import HorizontalRule from '@tiptap/extension-horizontal-rule'
import BulletList from '@tiptap/extension-bullet-list'
import OrderedList from '@tiptap/extension-ordered-list'
import ListItem from '@tiptap/extension-list-item'
import { Bold } from '@tiptap/extension-bold'
import { Italic } from '@tiptap/extension-italic'
import { Underline } from '@tiptap/extension-underline'
import { KeyboardShortcutExtension } from '../extensions/KeyboardShortcut'
import { Color } from '@tiptap/extension-color'
import { Extension } from '@tiptap/core'
import { Div } from '@/extensions/div'
// Wise Owl custom extensions
import WhealImage from '@/extensions/image'
import WhealParagraph from '@/extensions/paragraph'
import WhealSpan from '@/extensions/span'
import WhealTable from '@/extensions/table'
import { TableRow } from '@tiptap/extension-table-row'
import WhealTableHeader from '@/extensions/tableHeader'
import WhealTableCell from '@/extensions/tableCell'
import WhealLink from '@/extensions/link'
Roughly speaking, each of these corresponds to an HTML attribute. So for example a user of the editor can add bulleted lists using the ul and li tags in HTML because we've imported the extension, but they can't use the iframe tag - because we haven't.
So we haven't really created an HTML editor at all, but rather an editor which allows you to create ProseMirror documents using supported nodes, which can then be translated into HTML.
Here's the start of the function handling different choices made in our custom toolbar:
// do different things for different toolbar buttons/keys
switch (thing.toLowerCase()) {
// **************
// FONT ACTIONS
// **************
case 'bold':
return this.thisEditor?.chain().toggleBold().run()
case 'italics':
return this.thisEditor?.chain().toggleItalic().run()
case 'underline':
return this.thisEditor?.chain().toggleUnderline().run()
case 'key':
// apply keystroke formatting
return this.thisEditor?.chain().applySpanClassName('bpSpanKey').run()
The methods toggleBold, toggleItalic, toggleUnderline and applySpanClassName are all native to TipTap, but it's possible to add your own custom extensions to built-in nodes.
The hardest thing to implement in any HTML editor is image capture. When someone pastes an image into your editor, what should happen? Here is the key code in our editor capturing the event of someone inserting or pasting an image:
This pretty much sums up TipTap: the above code does exactly what we needed it to do, but getting the syntax right was challenging to say the least (and in this case involved some paid TipTap consultancy).
There's a famous quotation whose source is hard to track down but which was referenced by (who else?) Winston Churchiill:
Similarly TipTap is the worst way to build an HTML editor - apart from all the other alternatives out there. Here's why it was the right tool for our purposes:
Strength | Notes |
---|---|
Simplicity | I like the fact that with TipTap you start with nothing and add in the features that you want your editor to support. This means that you can be confident that people can only generate simple HTML - anything else would just get removed! |
Support | Although the online documentation for TipTap is a bit threadbare (at least if you're using TypeScript), we bought a day's paid consultancy from Uberdosis (the Berlin-based company behind TipTap) which was excellent. |
So we would recommend TipTap as a tool for creating an HTML editor, but only for experienced web developers (if you're fairly new to HTML and client script you run the risk of drowning rather than swimming). And don't be afraid to splash out on a bit of paid support or traning!
Kingsmoor House
Railway Street
GLOSSOP
SK13 2AA
Landmark Offices
99 Bishopsgate
LONDON
EC2M 3XD
Holiday Inn
25 Aytoun Street
MANCHESTER
M1 3AE
© Wise Owl Business Solutions Ltd 2024. All Rights Reserved.