You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
4 years ago | |
---|---|---|
nix | 4 years ago | |
src | 4 years ago | |
.gitignore | 4 years ago | |
.projections.json | 4 years ago | |
README.md | 4 years ago | |
elm.json | 4 years ago | |
shell.nix | 4 years ago |
README.md
elm-edit
This is an experimental rich text editor in Elm (minimal magic, but does require a custom element.)
This is all very aspirational yet, though!
Approach
The Big Deal(tm) here is that we render content in Elm but store the document state in a separate pure-functional data structure. This means that all our edits have semantic meaning instead of having to rely on re-reading the DOM.
The Document Format
We use a similar format to Quill.
See Edit.Document
for the format, and Edit.Delta
for how to make edits.
For example:
type Attr = Bold | Italic
doc : Document Attr
doc =
Document [ Text "Hello, World!" [] ]
edited : Document Attr
edited =
Delta.apply
(Delta
[ Retain 5 { add = [ Bold ], remove = [] }
, Retain 2 { add = [], remove = [] }
, Delete 5
, Insert (Text "Humans" [])
]
)
doc
this produces:
Document
[ Text "Hello" [ Bold ]
, Text ", " []
, Text "Humans!" []
]
The Custom Element
in Elm, create a DOM structure that looks like this:
<elm-edit>
<template>
<!-- rendered content from Elm -->
</template>
<div contenteditable></div>
</elm-edit>
the custom element does these things:
- Manage selection inside the contenteditable node. We can provide cursor/range offset so that we can edit the data structure above. This is similar to the approach taken by Quill, Trix, etc.
- Sync content from the template to the contenteditable node. This lets us get around virtualdom crashing when nodes get removed by the user.
- Observe mutation in the contenteditable node.
Pass these events back to Elm using custom events.
This lets us rely on browser input wherever possible (so pressing
alt-n n
on a Mac will type ñ, speech-to-text will work, etc)- Undo/redo stack
Hopefully we can rely on
MutationObserver
doing the right thing and letting us see when text gets added/removed with ctrl/cmd-z
- Undo/redo stack
Hopefully we can rely on
- Handle paste events. We can get XML representation of pasted rich text from other programs, which we can handle robustly in an Elm parser.