quoin-editor 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +27 -11
- package/dist/ai-labels-BXX32H9a.d.cts +53 -0
- package/dist/ai-labels-BXX32H9a.d.ts +53 -0
- package/dist/ai.cjs +84 -86
- package/dist/ai.d.cts +4 -53
- package/dist/ai.d.ts +4 -53
- package/dist/ai.js +8 -10
- package/dist/ai.js.map +1 -1
- package/dist/catalogue.cjs +27 -24
- package/dist/catalogue.d.cts +12 -1
- package/dist/catalogue.d.ts +12 -1
- package/dist/catalogue.js +19 -16
- package/dist/catalogue.js.map +1 -1
- package/dist/{chunk-QR2NIDUK.cjs → chunk-4MCYQHFL.cjs} +2 -2
- package/dist/{chunk-XFR7QGSN.cjs → chunk-53CNYRVQ.cjs} +92 -94
- package/dist/{chunk-T7O3BROK.cjs → chunk-53FJFYBR.cjs} +115 -117
- package/dist/{chunk-KFYJW7W5.js → chunk-5OZX2LV4.js} +10 -12
- package/dist/chunk-5OZX2LV4.js.map +1 -0
- package/dist/{chunk-OS2O6IKX.js → chunk-5RBMZGKV.js} +4 -4
- package/dist/{chunk-OS2O6IKX.js.map → chunk-5RBMZGKV.js.map} +1 -1
- package/dist/{chunk-4T4TJ2QS.cjs → chunk-7E43TURF.cjs} +7 -7
- package/dist/{chunk-L6RB43YM.cjs → chunk-7X3T7VXV.cjs} +32 -34
- package/dist/{chunk-BJTOLCRR.js → chunk-7Y4B7NHO.js} +2 -2
- package/dist/chunk-7Y4B7NHO.js.map +1 -0
- package/dist/{chunk-LOP66FVU.cjs → chunk-B3OBM6I4.cjs} +25 -27
- package/dist/{chunk-UUSZGUXJ.cjs → chunk-BA5WXBGE.cjs} +291 -293
- package/dist/{chunk-CSKKSXCE.js → chunk-CSPCDVCT.js} +3 -3
- package/dist/{chunk-CSKKSXCE.js.map → chunk-CSPCDVCT.js.map} +1 -1
- package/dist/{chunk-R7MYG522.js → chunk-D4L5FINK.js} +3 -3
- package/dist/{chunk-R7MYG522.js.map → chunk-D4L5FINK.js.map} +1 -1
- package/dist/{chunk-GHNQKJMD.js → chunk-DBOZFNWU.js} +3 -3
- package/dist/{chunk-GHNQKJMD.js.map → chunk-DBOZFNWU.js.map} +1 -1
- package/dist/{chunk-BM2GRZNM.cjs → chunk-DJU25PFC.cjs} +11 -11
- package/dist/chunk-DLQCTGC3.js +10 -0
- package/dist/chunk-DLQCTGC3.js.map +1 -0
- package/dist/{chunk-B5OMWOVI.js → chunk-DXUDBPG5.js} +9 -11
- package/dist/chunk-DXUDBPG5.js.map +1 -0
- package/dist/{chunk-TKCPXUPP.cjs → chunk-EZWJRBQT.cjs} +51 -53
- package/dist/{chunk-N2SCDXTI.js → chunk-EZX37R5D.js} +8 -10
- package/dist/chunk-EZX37R5D.js.map +1 -0
- package/dist/{chunk-VZZPCYA3.cjs → chunk-FK7EBZPX.cjs} +226 -226
- package/dist/{chunk-BXSWZEA5.js → chunk-GPTJYWGS.js} +3 -3
- package/dist/{chunk-BXSWZEA5.js.map → chunk-GPTJYWGS.js.map} +1 -1
- package/dist/{chunk-H3C3MJW5.cjs → chunk-LM3DHROX.cjs} +2 -2
- package/dist/{chunk-AD3NY7NA.js → chunk-LSI4RMTY.js} +3 -3
- package/dist/{chunk-AD3NY7NA.js.map → chunk-LSI4RMTY.js.map} +1 -1
- package/dist/chunk-MMS4D4MK.cjs +87 -0
- package/dist/{chunk-HT7OF52E.js → chunk-MRHDPXQ7.js} +8 -10
- package/dist/chunk-MRHDPXQ7.js.map +1 -0
- package/dist/{chunk-XFEDJEJF.js → chunk-MSWA5ZZM.js} +4 -4
- package/dist/{chunk-XFEDJEJF.js.map → chunk-MSWA5ZZM.js.map} +1 -1
- package/dist/chunk-NCDMQCZR.js +85 -0
- package/dist/chunk-NCDMQCZR.js.map +1 -0
- package/dist/{chunk-QJ34MOFV.cjs → chunk-P6HC7RUN.cjs} +120 -120
- package/dist/{chunk-O7XZFXPE.js → chunk-PHQMHXNG.js} +9 -11
- package/dist/chunk-PHQMHXNG.js.map +1 -0
- package/dist/{chunk-WN7BZDNH.cjs → chunk-PURYVDC3.cjs} +13 -13
- package/dist/{chunk-46JH34SR.cjs → chunk-PVFSJXYQ.cjs} +28 -30
- package/dist/{chunk-QOIVLYMW.js → chunk-SP4F5F6V.js} +5 -5
- package/dist/{chunk-QOIVLYMW.js.map → chunk-SP4F5F6V.js.map} +1 -1
- package/dist/{chunk-JVSYEENH.cjs → chunk-TQHFGSTT.cjs} +57 -59
- package/dist/{chunk-G25FMFEZ.js → chunk-UDBLZILE.js} +4 -4
- package/dist/{chunk-G25FMFEZ.js.map → chunk-UDBLZILE.js.map} +1 -1
- package/dist/{chunk-2AVGGPLT.js → chunk-VM567D6O.js} +8 -10
- package/dist/chunk-VM567D6O.js.map +1 -0
- package/dist/{chunk-KF3KKN4N.js → chunk-VWYPO6SX.js} +8 -10
- package/dist/chunk-VWYPO6SX.js.map +1 -0
- package/dist/{chunk-IJKGF6SC.js → chunk-WOGCD7JN.js} +8 -10
- package/dist/chunk-WOGCD7JN.js.map +1 -0
- package/dist/{chunk-AZF7B2AE.cjs → chunk-XKYNINUX.cjs} +11 -11
- package/dist/{chunk-32OZ2WM2.js → chunk-Y4EJ6UBV.js} +8 -11
- package/dist/chunk-Y4EJ6UBV.js.map +1 -0
- package/dist/{chunk-XZ4NC3Q7.cjs → chunk-YEDPBYO5.cjs} +4 -4
- package/dist/{chunk-STKGRXSA.cjs → chunk-YVPZDTVZ.cjs} +15 -17
- package/dist/chunk-ZWTIRGY5.cjs +10 -0
- package/dist/comments-labels-DWqsSz8G.d.cts +30 -0
- package/dist/comments-labels-DWqsSz8G.d.ts +30 -0
- package/dist/comments.cjs +63 -65
- package/dist/comments.d.cts +4 -30
- package/dist/comments.d.ts +4 -30
- package/dist/comments.js +9 -11
- package/dist/comments.js.map +1 -1
- package/dist/diagram-extension-22x_njXB.d.ts +30 -0
- package/dist/diagram-extension-C_FSkoj9.d.cts +30 -0
- package/dist/diagram-labels-Bi_jEZ8_.d.cts +11 -0
- package/dist/diagram-labels-Bi_jEZ8_.d.ts +11 -0
- package/dist/diagram.cjs +26 -0
- package/dist/diagram.d.cts +9 -0
- package/dist/diagram.d.ts +9 -0
- package/dist/diagram.js +11 -0
- package/dist/diagram.js.map +1 -0
- package/dist/diff-labels-DWwg7N0n.d.cts +27 -0
- package/dist/diff-labels-DWwg7N0n.d.ts +27 -0
- package/dist/diff.cjs +27 -29
- package/dist/diff.d.cts +4 -27
- package/dist/diff.d.ts +4 -27
- package/dist/diff.js +5 -7
- package/dist/diff.js.map +1 -1
- package/dist/docx.cjs +30 -30
- package/dist/docx.js +3 -3
- package/dist/embed-labels-BiVa9HYl.d.cts +23 -0
- package/dist/embed-labels-BiVa9HYl.d.ts +23 -0
- package/dist/embed.cjs +10 -9
- package/dist/embed.d.cts +4 -23
- package/dist/embed.d.ts +4 -23
- package/dist/embed.js +8 -7
- package/dist/emoji-extension-C832oGeT.d.ts +16 -0
- package/dist/emoji-extension-Dk5IQLZf.d.cts +16 -0
- package/dist/{emoji-extension-gRKnbW8G.d.ts → emoji-labels-YwOms7ZJ.d.cts} +2 -15
- package/dist/{emoji-extension-C3o_Y5uC.d.cts → emoji-labels-YwOms7ZJ.d.ts} +2 -15
- package/dist/emoji.cjs +10 -9
- package/dist/emoji.d.cts +4 -3
- package/dist/emoji.d.ts +4 -3
- package/dist/emoji.js +7 -6
- package/dist/engine.cjs +58 -58
- package/dist/engine.d.cts +8 -7
- package/dist/engine.d.ts +8 -7
- package/dist/engine.js +3 -3
- package/dist/find-extension-BfruAPLi.d.cts +15 -0
- package/dist/find-extension-DmK9_N81.d.ts +15 -0
- package/dist/{find-extension-B_Ctrs6T.d.ts → find-labels-C4vs8Qe9.d.cts} +2 -14
- package/dist/{find-extension-BGGsJMu4.d.cts → find-labels-C4vs8Qe9.d.ts} +2 -14
- package/dist/find.cjs +11 -10
- package/dist/find.d.cts +2 -1
- package/dist/find.d.ts +2 -1
- package/dist/find.js +7 -6
- package/dist/headless.cjs +74 -74
- package/dist/headless.d.cts +38 -8
- package/dist/headless.d.ts +38 -8
- package/dist/headless.js +4 -4
- package/dist/highlight.cjs +7 -6
- package/dist/highlight.js +6 -5
- package/dist/highlight.js.map +1 -1
- package/dist/{index-CsG7OQoq.d.cts → index-3fYvwqUZ.d.cts} +1 -1
- package/dist/{index-h1llgZM-.d.ts → index-CgxnzCO5.d.ts} +1 -1
- package/dist/index.cjs +87 -86
- package/dist/index.d.cts +18 -185
- package/dist/index.d.ts +18 -185
- package/dist/index.js +6 -5
- package/dist/labels-BhRJYo46.d.ts +176 -0
- package/dist/labels-CiCxj2jP.d.cts +176 -0
- package/dist/locale-ar.cjs +565 -0
- package/dist/locale-ar.d.cts +63 -0
- package/dist/locale-ar.d.ts +63 -0
- package/dist/locale-ar.js +551 -0
- package/dist/locale-ar.js.map +1 -0
- package/dist/locale-de.cjs +510 -0
- package/dist/locale-de.d.cts +63 -0
- package/dist/locale-de.d.ts +63 -0
- package/dist/locale-de.js +496 -0
- package/dist/locale-de.js.map +1 -0
- package/dist/locale-es.cjs +510 -0
- package/dist/locale-es.d.cts +63 -0
- package/dist/locale-es.d.ts +63 -0
- package/dist/locale-es.js +496 -0
- package/dist/locale-es.js.map +1 -0
- package/dist/locale-fr.cjs +510 -0
- package/dist/locale-fr.d.cts +63 -0
- package/dist/locale-fr.d.ts +63 -0
- package/dist/locale-fr.js +496 -0
- package/dist/locale-fr.js.map +1 -0
- package/dist/locale-ja.cjs +505 -0
- package/dist/locale-ja.d.cts +63 -0
- package/dist/locale-ja.d.ts +63 -0
- package/dist/locale-ja.js +491 -0
- package/dist/locale-ja.js.map +1 -0
- package/dist/locale-pt.cjs +511 -0
- package/dist/locale-pt.d.cts +63 -0
- package/dist/locale-pt.d.ts +63 -0
- package/dist/locale-pt.js +497 -0
- package/dist/locale-pt.js.map +1 -0
- package/dist/locale-zh.cjs +505 -0
- package/dist/locale-zh.d.cts +63 -0
- package/dist/locale-zh.d.ts +63 -0
- package/dist/locale-zh.js +491 -0
- package/dist/locale-zh.js.map +1 -0
- package/dist/math-labels-DOf5KFxp.d.cts +24 -0
- package/dist/math-labels-DOf5KFxp.d.ts +24 -0
- package/dist/math.cjs +11 -10
- package/dist/math.d.cts +4 -24
- package/dist/math.d.ts +4 -24
- package/dist/math.js +9 -8
- package/dist/mention-labels-DIQy8LRT.d.cts +15 -0
- package/dist/mention-labels-DIQy8LRT.d.ts +15 -0
- package/dist/mention.cjs +11 -10
- package/dist/mention.d.cts +4 -15
- package/dist/mention.d.ts +4 -15
- package/dist/mention.js +9 -8
- package/dist/{view-controller-p-2x3J7Y.d.ts → node-reveal-BnFcnHhz.d.ts} +14 -14
- package/dist/{view-controller-BfVSNZYZ.d.cts → node-reveal-DY6bimv3.d.cts} +14 -14
- package/dist/palette-BrX-hEd-.d.cts +4 -0
- package/dist/palette-BrX-hEd-.d.ts +4 -0
- package/dist/presence-labels-DXVJLifl.d.cts +15 -0
- package/dist/presence-labels-DXVJLifl.d.ts +15 -0
- package/dist/presence.cjs +40 -42
- package/dist/presence.d.cts +4 -15
- package/dist/presence.d.ts +4 -15
- package/dist/presence.js +9 -11
- package/dist/presence.js.map +1 -1
- package/dist/source-labels-CeQDXsYZ.d.cts +9 -0
- package/dist/source-labels-CeQDXsYZ.d.ts +9 -0
- package/dist/source.cjs +11 -14
- package/dist/source.d.cts +5 -10
- package/dist/source.d.ts +5 -10
- package/dist/source.js +7 -10
- package/dist/source.js.map +1 -1
- package/dist/{stats-extension-oD6D1cYy.d.ts → stats-extension-D5HySF0a.d.cts} +4 -16
- package/dist/{stats-extension-XqOTvRaq.d.cts → stats-extension-Dmw0Ujxe.d.ts} +4 -16
- package/dist/stats-labels-W8gep51s.d.cts +15 -0
- package/dist/stats-labels-W8gep51s.d.ts +15 -0
- package/dist/stats.cjs +11 -10
- package/dist/stats.d.cts +3 -2
- package/dist/stats.d.ts +3 -2
- package/dist/stats.js +8 -7
- package/dist/styles.css +1 -1
- package/dist/table-extension-7LkLNK6Q.d.cts +15 -0
- package/dist/table-extension-DEpV0DnP.d.ts +15 -0
- package/dist/{table-extension-v6VB59bF.d.ts → table-labels-Dc-MzU3j.d.cts} +2 -14
- package/dist/{table-extension-BP47hHoz.d.cts → table-labels-Dc-MzU3j.d.ts} +2 -14
- package/dist/table.cjs +26 -25
- package/dist/table.d.cts +2 -1
- package/dist/table.d.ts +2 -1
- package/dist/table.js +7 -6
- package/dist/{to-html-1oD-CDle.d.cts → to-html-C19PbIzh.d.cts} +1 -0
- package/dist/{to-html-CLRBCX0I.d.ts → to-html-CogwrQer.d.ts} +1 -0
- package/dist/{to-markdown-CFPMbbiX.d.cts → to-markdown-C2w7Dzg8.d.cts} +1 -0
- package/dist/{to-markdown-BVOzhgVM.d.ts → to-markdown-DC1EUye5.d.ts} +1 -0
- package/dist/toc-extension-Dvh37bWQ.d.cts +15 -0
- package/dist/toc-extension-SVckrFmb.d.ts +15 -0
- package/dist/toc-labels-B2apPfXG.d.cts +14 -0
- package/dist/toc-labels-B2apPfXG.d.ts +14 -0
- package/dist/toc.cjs +10 -9
- package/dist/toc.d.cts +3 -2
- package/dist/toc.d.ts +3 -2
- package/dist/toc.js +7 -6
- package/dist/{types-DXF9p4qV.d.cts → types-Bzhq5AXj.d.cts} +1 -0
- package/dist/{types-BjLcmV00.d.ts → types-DMuuDBVh.d.ts} +1 -0
- package/dist/view.cjs +4 -4
- package/dist/view.js +2 -2
- package/dist/yjs.cjs +121 -121
- package/dist/yjs.d.cts +2 -2
- package/dist/yjs.d.ts +2 -2
- package/dist/yjs.js +5 -5
- package/package.json +81 -1
- package/dist/chunk-2AVGGPLT.js.map +0 -1
- package/dist/chunk-32OZ2WM2.js.map +0 -1
- package/dist/chunk-B5OMWOVI.js.map +0 -1
- package/dist/chunk-BJTOLCRR.js.map +0 -1
- package/dist/chunk-HT7OF52E.js.map +0 -1
- package/dist/chunk-IJKGF6SC.js.map +0 -1
- package/dist/chunk-KF3KKN4N.js.map +0 -1
- package/dist/chunk-KFYJW7W5.js.map +0 -1
- package/dist/chunk-N2SCDXTI.js.map +0 -1
- package/dist/chunk-O7XZFXPE.js.map +0 -1
- package/dist/toc-extension-CI6jNOYl.d.cts +0 -26
- package/dist/toc-extension-CTHWjNJC.d.ts +0 -26
- /package/dist/{chunk-WZA5S5EJ.cjs → chunk-I7X7B3WD.cjs} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
Every release of `quoin-editor` is listed here, newest first, in the spirit of [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). From 1.0.0 the package follows [semantic versioning](https://semver.org/): a breaking change waits for the next major version. Until then, Quoin was 0.x and a minor version could contain breaking changes; those known at release were marked "Breaking". The 0.x sections are kept as they were released, "Docs" headings included. Moving from 0.4 to 1.0 is covered step by step in [MIGRATION.md](MIGRATION.md). Review finding ids such as F-17 are those of the 0.4.0 review in [#73](https://github.com/AmineSeboui/quoin-editor/issues/73).
|
|
4
4
|
|
|
5
|
+
## 1.8.0 (2026-11-05)
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Seven locale packs, one entry each, carrying every string the editor shows or speaks in that language: `quoin-editor/locale-ar` (Arabic), `quoin-editor/locale-de` (German), `quoin-editor/locale-es` (Spanish), `quoin-editor/locale-fr` (French), `quoin-editor/locale-ja` (Japanese), `quoin-editor/locale-pt` (Portuguese) and `quoin-editor/locale-zh` (Simplified Chinese). A pack covers the canvas and all fourteen feature label sets, so `frLabels` goes to the canvas and `frTableLabels` to the table, and it is data alone: no React, no side effects, about 5.5 KB gzip each, downloaded only by a host that imports one. A label that carries a count, a date, a number or a file size is written as its language writes it, through `Intl`, so Arabic gets its six plural forms and Japanese its one. Nothing is detected: the host picks the language, and a key a pack leaves out still falls back to English.
|
|
9
|
+
- `quoin-editor/headless` exports the types its own signatures already named, so a host can write them down rather than reach them through `Parameters` and `ReturnType`: `Announcer` with `Spoken`, `Engagement`, `FocusTarget`, `HostRegistry` with `HostEntry`, and `NodeReveal`, all reached through `ViewController`; `CaretPoint`, which `caretFromPoint` returns; and `BlockShellProps` and `SelectionSinkProps`, taken by the two components named after them. They reach `quoin-editor` too, which re-exports the headless entry. Nothing new runs and no type changes shape.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- The exports a host meets first carry a documentation comment, so an editor explains them on hover: `BlockCanvas`, `EditorView`, `useQuoinEditor`, `createEditor`, `toMarkdown`, `toHTML`, `toPlainText`, `fromMarkdown`, `PALETTE` and `englishLabels`. Nothing about their behaviour changes.
|
|
13
|
+
- `BlockShell`, `SelectionSink`, `defaultRenderers`, `VoidBlockFallback` and `isCrossSelection` are marked deprecated, in an editor and on the headless reference, and they go in 2.0.0. All five are internal to the view layer and a host has no use for them: `EditorView` draws the first two itself and a second copy of either takes the registration with the controller from the first, a renderer of your own draws a block's text with `EditableRegion` rather than reaching for `defaultRenderers`, a block shell already falls back to `VoidBlockFallback` when no renderer draws a block's type, and a host reads `anchor` and `head` of the public `Selection` to tell a selection that spans blocks or regions from one held inside a single region. `BlockRenderProps` and `BlockRenderer` stay public, so a renderer table still types. Every name is still exported and still does what it did.
|
|
14
|
+
- The comparison table weighs Quoin against Lexical and Plate as well, rechecked against each project's own pages and dated 2026-11-05. Lexical keeps an editor state it writes as JSON, draws no interface of its own, and ships neither comments nor translations: none of its forty packages covers either, and the comment plugin a reader finds is playground code. Plate keeps Slate JSON, converts markdown both ways, collaborates over Yjs and marks comments on text, and is MIT with a paid set of components behind its Notion-like template. A localization row goes in beside them: BlockNote ships 24 locales, Editor.js takes a dictionary the host writes, and Tiptap, Lexical and Plate ship none, since their interface strings live in the code a host copies into its own project. The comparison page reads in a wider column than the guide, because seven columns in a line of prose left each one too narrow to read.
|
|
15
|
+
|
|
16
|
+
## 1.7.0 (2026-11-04)
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- `quoin-editor/diagram` draws a code block whose language names a diagram, such as `mermaid`, through a renderer you pass, which may answer at once or with a promise as the common engines do, with its source below the drawing where a writer already edits it. Quoin draws no diagrams itself and bundles no engine. The document is unchanged: a diagram is a fenced code block, and opens as one anywhere else. A renderer that throws or draws nothing leaves the source alone rather than losing the block.
|
|
20
|
+
|
|
5
21
|
## 1.6.0 (2026-11-04)
|
|
6
22
|
|
|
7
23
|
### Added
|
package/README.md
CHANGED
|
@@ -62,29 +62,32 @@ What `onChange` hands you, and what you store:
|
|
|
62
62
|
| Entry | What it adds |
|
|
63
63
|
| --- | --- |
|
|
64
64
|
| `quoin-editor` | The canvas: text, lists, tasks, quotes, callouts, toggles, dividers, code, images and files, with every menu and toolbar |
|
|
65
|
-
| `quoin-editor/table`, `/embed`, `/math`, `/toc`, `/mention`, `/emoji`, `/find`, `/stats` | Opt-in features, each its own entry; `quoin-editor/catalogue` adds them all |
|
|
65
|
+
| `quoin-editor/table`, `/embed`, `/math`, `/diagram`, `/toc`, `/mention`, `/emoji`, `/find`, `/stats` | Opt-in features, each its own entry; `quoin-editor/catalogue` adds them all |
|
|
66
66
|
| `quoin-editor/highlight` | Syntax colouring for code blocks, in every language the picker offers, fetched on demand |
|
|
67
|
+
| `quoin-editor/source` | The document as the markdown it is stored as, read only, beside or below the canvas |
|
|
67
68
|
| `quoin-editor/yjs`, `/presence` | Real-time co-editing through your own Yjs provider, and collaborators' carets |
|
|
68
69
|
| `quoin-editor/comments` | Comment threads anchored to text, kept in your store |
|
|
69
70
|
| `quoin-editor/ai` | Your model's answers streamed into the document; Quoin never calls a model |
|
|
70
71
|
| `quoin-editor/view`, `/diff`, `/docx` | Server rendering with no hooks, a diff of two versions, a Word export |
|
|
72
|
+
| `quoin-editor/locale-ar`, `/locale-de`, `/locale-es`, `/locale-fr`, `/locale-ja`, `/locale-pt`, `/locale-zh` | Every string the editor shows, in that language |
|
|
71
73
|
| `quoin-editor/headless`, `/engine` | The editor without the canvas UI, and the engine alone with no React |
|
|
72
74
|
|
|
73
75
|
## Why Quoin
|
|
74
76
|
|
|
75
77
|
Each competitor cell links to the page that shows it; the Tiptap UI cell also draws on the review in [#73](https://github.com/AmineSeboui/quoin-editor/issues/73) (2026-10-12).
|
|
76
78
|
|
|
77
|
-
| Feature | Quoin 1.
|
|
78
|
-
| --- | --- | --- | --- | --- |
|
|
79
|
-
| Stored document | Block array, markdown per text block | [JSON, or HTML][tt-store] | [Block JSON][bn-formats] | [JSON][ej-repo] |
|
|
80
|
-
| Markdown | The storage format | [`@tiptap/markdown`, an early release][tt-md] | [Export and import, documented as lossy][bn-formats] | [Community plugin][ej-awesome] |
|
|
81
|
-
| Notion-style UI | Included, MIT | [MIT menus and drag handle][tt-review]; [Notion-like template on a paid plan][tt-notion] | [Included][bn-home] | [Toolbox and inline toolbar][ej-repo] |
|
|
82
|
-
| Licence | MIT | [MIT core, paid Pro extensions][tt-repo] | [MPL-2.0, `xl-*` packages GPL-3.0 or commercial][bn-repo] | [Apache-2.0][ej-repo] |
|
|
83
|
-
| Real-time collaboration | Yjs, opt-in entry | [Yjs][tt-collab] | [Yjs][bn-collab] | [On its roadmap, in progress][ej-repo] |
|
|
84
|
-
| Comments | Opt-in, your store | [Paid plan][tt-comments] | [Built in, on Yjs or a thread store][bn-comments] | [Community plugin][ej-awesome] |
|
|
85
|
-
|
|
|
79
|
+
| Feature | Quoin 1.8 | Tiptap 3 | BlockNote | Editor.js | Lexical | Plate |
|
|
80
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
81
|
+
| Stored document | Block array, markdown per text block | [JSON, or HTML][tt-store] | [Block JSON][bn-formats] | [JSON][ej-repo] | [Editor state, as JSON][lx-intro] | [Slate JSON][pl-docs] |
|
|
82
|
+
| Markdown | The storage format | [`@tiptap/markdown`, an early release][tt-md] | [Export and import, documented as lossy][bn-formats] | [Community plugin][ej-awesome] | [`@lexical/markdown`, in and out][lx-md] | [`@platejs/markdown`, in and out][pl-md] |
|
|
83
|
+
| Notion-style UI | Included, MIT | [MIT menus and drag handle][tt-review]; [Notion-like template on a paid plan][tt-notion] | [Included][bn-home] | [Toolbox and inline toolbar][ej-repo] | [None; you draw it][lx-intro] | [MIT components][pl-repo]; [Notion-like set on a paid licence][pl-pro] |
|
|
84
|
+
| Licence | MIT | [MIT core, paid Pro extensions][tt-repo] | [MPL-2.0, `xl-*` packages GPL-3.0 or commercial][bn-repo] | [Apache-2.0][ej-repo] | [MIT][lx-repo] | [MIT, with paid Plus components][pl-pro] |
|
|
85
|
+
| Real-time collaboration | Yjs, opt-in entry | [Yjs][tt-collab] | [Yjs][bn-collab] | [On its roadmap, in progress][ej-repo] | [Yjs][lx-collab] | [Yjs][pl-yjs] |
|
|
86
|
+
| Comments | Opt-in, your store | [Paid plan][tt-comments] | [Built in, on Yjs or a thread store][bn-comments] | [Community plugin][ej-awesome] | [None shipped; a playground example][lx-repo] | [`@platejs/comment`, as text marks][pl-comment] |
|
|
87
|
+
| Localization | Seven packs, every string | [None shipped; the UI is yours][tt-ui] | [24 locales built in][bn-i18n] | [An i18n API; you bring the words][ej-i18n] | [None shipped; it draws no UI][lx-repo] | [None shipped; the UI is yours][pl-docs] |
|
|
88
|
+
| Framework | React | [React, Vue, Svelte, plain JavaScript and more][tt-install] | [React, or vanilla JS with your own UI][bn-vanilla] | [Plain JavaScript][ej-start] | [Any, with React bindings][lx-repo] | [React][pl-repo] |
|
|
86
89
|
|
|
87
|
-
Sources, checked on 2026-11-
|
|
90
|
+
Sources, checked on 2026-11-05: Tiptap [persistence][tt-store], [markdown][tt-md], [Notion-like template][tt-notion], [repository][tt-repo], [collaboration][tt-collab], [comments][tt-comments], [install][tt-install], [UI components][tt-ui]; BlockNote [home][bn-home], [formats][bn-formats], [repository][bn-repo], [collaboration][bn-collab], [comments][bn-comments], [getting started][bn-start], [vanilla JS][bn-vanilla], [localization][bn-i18n]; Editor.js [home][ej-home], [repository][ej-repo], [getting started][ej-start], [awesome-editorjs][ej-awesome], [i18n][ej-i18n]; Lexical [docs][lx-intro], [repository][lx-repo], [markdown][lx-md], [collaboration][lx-collab]; Plate [docs][pl-docs], [repository][pl-repo], [markdown][pl-md], [collaboration][pl-yjs], [comments][pl-comment], [Plate Plus][pl-pro].
|
|
88
91
|
|
|
89
92
|
[tt-store]: https://tiptap.dev/docs/editor/core-concepts/persistence
|
|
90
93
|
[tt-md]: https://tiptap.dev/docs/editor/markdown
|
|
@@ -105,6 +108,19 @@ Sources, checked on 2026-11-03: Tiptap [persistence][tt-store], [markdown][tt-md
|
|
|
105
108
|
[ej-repo]: https://github.com/codex-team/editor.js
|
|
106
109
|
[ej-start]: https://editorjs.io/getting-started
|
|
107
110
|
[ej-awesome]: https://github.com/editor-js/awesome-editorjs
|
|
111
|
+
[tt-ui]: https://tiptap.dev/docs/ui-components/components/overview
|
|
112
|
+
[bn-i18n]: https://www.blocknotejs.org/docs/features/localization
|
|
113
|
+
[ej-i18n]: https://editorjs.io/i18n/
|
|
114
|
+
[lx-intro]: https://lexical.dev/docs/intro
|
|
115
|
+
[lx-repo]: https://github.com/facebook/lexical
|
|
116
|
+
[lx-md]: https://lexical.dev/docs/packages/lexical-markdown
|
|
117
|
+
[lx-collab]: https://lexical.dev/docs/collaboration/react
|
|
118
|
+
[pl-docs]: https://platejs.org/docs
|
|
119
|
+
[pl-repo]: https://github.com/udecode/plate
|
|
120
|
+
[pl-md]: https://platejs.org/docs/markdown
|
|
121
|
+
[pl-yjs]: https://platejs.org/docs/yjs
|
|
122
|
+
[pl-comment]: https://platejs.org/docs/comment
|
|
123
|
+
[pl-pro]: https://pro.platejs.org
|
|
108
124
|
|
|
109
125
|
## Learn more
|
|
110
126
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
type AiAction = 'continue' | 'improve' | 'fix' | 'shorten' | 'lengthen' | 'simplify' | 'tone' | 'translate' | 'summarize' | 'explain' | 'custom';
|
|
2
|
+
/** What the host is asked: `selection` and `context` are markdown, `language` the canvas's `lang` when it has one. */
|
|
3
|
+
type AiRequest = {
|
|
4
|
+
action: AiAction;
|
|
5
|
+
prompt?: string;
|
|
6
|
+
selection: string;
|
|
7
|
+
context: string;
|
|
8
|
+
language?: string;
|
|
9
|
+
};
|
|
10
|
+
/** The host's model, answering a request as markdown in chunks, and stopping when `signal` aborts. */
|
|
11
|
+
type AiStream = (request: AiRequest, signal: AbortSignal) => AsyncIterable<string>;
|
|
12
|
+
|
|
13
|
+
/** Every string AI actions show or speak. */
|
|
14
|
+
type AiLabels = {
|
|
15
|
+
/** The toolbar button, block menu item and slash command that open the AI menu. */
|
|
16
|
+
askAi: string;
|
|
17
|
+
/** What the slash command for the AI menu does. */
|
|
18
|
+
askAiDescription: string;
|
|
19
|
+
/** The name of each action in the AI menu; `custom` names the slash command group's own entry. */
|
|
20
|
+
actions: Record<AiAction, string>;
|
|
21
|
+
/** The name of the list of actions. */
|
|
22
|
+
menu: string;
|
|
23
|
+
/** The field the writer types a request in. */
|
|
24
|
+
prompt: string;
|
|
25
|
+
/** The field once Change tone is chosen. */
|
|
26
|
+
tonePrompt: string;
|
|
27
|
+
/** The field once Translate is chosen. */
|
|
28
|
+
translatePrompt: string;
|
|
29
|
+
/** The choice that sends what was typed as a request of its own. */
|
|
30
|
+
ask(prompt: string): string;
|
|
31
|
+
/** The name of the bar under the answer. */
|
|
32
|
+
response: string;
|
|
33
|
+
writing: string;
|
|
34
|
+
stopped: string;
|
|
35
|
+
stop: string;
|
|
36
|
+
accept: string;
|
|
37
|
+
discard: string;
|
|
38
|
+
retry: string;
|
|
39
|
+
/** The field for a further request about the answer. */
|
|
40
|
+
followUp: string;
|
|
41
|
+
/** Shown when the host's answer failed. */
|
|
42
|
+
failed: string;
|
|
43
|
+
/** Said once an answer is complete, given its text. */
|
|
44
|
+
written(text: string): string;
|
|
45
|
+
/** Said once an answer is stopped, given what it wrote. */
|
|
46
|
+
halted(text: string): string;
|
|
47
|
+
/** Shown when the text the answer was for was deleted meanwhile. */
|
|
48
|
+
targetGone: string;
|
|
49
|
+
};
|
|
50
|
+
declare const englishAiLabels: AiLabels;
|
|
51
|
+
|
|
52
|
+
export { englishAiLabels as e };
|
|
53
|
+
export type { AiStream as A, AiLabels as a, AiAction as b, AiRequest as c };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
type AiAction = 'continue' | 'improve' | 'fix' | 'shorten' | 'lengthen' | 'simplify' | 'tone' | 'translate' | 'summarize' | 'explain' | 'custom';
|
|
2
|
+
/** What the host is asked: `selection` and `context` are markdown, `language` the canvas's `lang` when it has one. */
|
|
3
|
+
type AiRequest = {
|
|
4
|
+
action: AiAction;
|
|
5
|
+
prompt?: string;
|
|
6
|
+
selection: string;
|
|
7
|
+
context: string;
|
|
8
|
+
language?: string;
|
|
9
|
+
};
|
|
10
|
+
/** The host's model, answering a request as markdown in chunks, and stopping when `signal` aborts. */
|
|
11
|
+
type AiStream = (request: AiRequest, signal: AbortSignal) => AsyncIterable<string>;
|
|
12
|
+
|
|
13
|
+
/** Every string AI actions show or speak. */
|
|
14
|
+
type AiLabels = {
|
|
15
|
+
/** The toolbar button, block menu item and slash command that open the AI menu. */
|
|
16
|
+
askAi: string;
|
|
17
|
+
/** What the slash command for the AI menu does. */
|
|
18
|
+
askAiDescription: string;
|
|
19
|
+
/** The name of each action in the AI menu; `custom` names the slash command group's own entry. */
|
|
20
|
+
actions: Record<AiAction, string>;
|
|
21
|
+
/** The name of the list of actions. */
|
|
22
|
+
menu: string;
|
|
23
|
+
/** The field the writer types a request in. */
|
|
24
|
+
prompt: string;
|
|
25
|
+
/** The field once Change tone is chosen. */
|
|
26
|
+
tonePrompt: string;
|
|
27
|
+
/** The field once Translate is chosen. */
|
|
28
|
+
translatePrompt: string;
|
|
29
|
+
/** The choice that sends what was typed as a request of its own. */
|
|
30
|
+
ask(prompt: string): string;
|
|
31
|
+
/** The name of the bar under the answer. */
|
|
32
|
+
response: string;
|
|
33
|
+
writing: string;
|
|
34
|
+
stopped: string;
|
|
35
|
+
stop: string;
|
|
36
|
+
accept: string;
|
|
37
|
+
discard: string;
|
|
38
|
+
retry: string;
|
|
39
|
+
/** The field for a further request about the answer. */
|
|
40
|
+
followUp: string;
|
|
41
|
+
/** Shown when the host's answer failed. */
|
|
42
|
+
failed: string;
|
|
43
|
+
/** Said once an answer is complete, given its text. */
|
|
44
|
+
written(text: string): string;
|
|
45
|
+
/** Said once an answer is stopped, given what it wrote. */
|
|
46
|
+
halted(text: string): string;
|
|
47
|
+
/** Shown when the text the answer was for was deleted meanwhile. */
|
|
48
|
+
targetGone: string;
|
|
49
|
+
};
|
|
50
|
+
declare const englishAiLabels: AiLabels;
|
|
51
|
+
|
|
52
|
+
export { englishAiLabels as e };
|
|
53
|
+
export type { AiStream as A, AiLabels as a, AiAction as b, AiRequest as c };
|