@octane-xplat/tiptap 0.9.0 → 0.11.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/README.md +112 -3
- package/dist/macos/browser.d.ts +1 -0
- package/dist/macos/browser.js +2 -0
- package/dist/native/index3.js +46 -25
- package/dist/native/octane-client-build.json +1 -1
- package/dist/web/index2.js +43 -32
- package/dist/web/octane-client-build.json +1 -1
- package/package.json +9 -6
- package/src/Editor.macos.tsx +9 -0
- package/src/TiptapEditor.mobile.test.ts +229 -0
- package/src/TiptapEditor.tsrx +59 -25
- package/src/TiptapEditor.web.test.tsrx +129 -0
- package/src/TiptapEditor.web.tsrx +43 -25
- package/src/browser-entry.web.tsx +5 -0
- package/src/index.macos.ts +7 -13
- package/src/types.ts +34 -2
- package/types/index.macos.d.ts +7 -0
- package/types/types.d.ts +32 -2
package/README.md
CHANGED
|
@@ -2,14 +2,81 @@
|
|
|
2
2
|
|
|
3
3
|
The unified rich-text facade: one `TiptapEditor` component across web and
|
|
4
4
|
native. Web renders a real tiptap `Editor` through `@octanejs/tiptap`'s
|
|
5
|
-
`EditorContent`;
|
|
5
|
+
`EditorContent`; Android renders the `@octane-xplat/richtext` leaf (WordPress
|
|
6
6
|
Aztec on Android, iOS stub) and layers tiptap document JSON on top through
|
|
7
7
|
the DOM-free ProseMirror slices (`@tiptap/pm`, `@tiptap/static-renderer`)
|
|
8
8
|
with a `zeed-dom` parse shim. No DOM-bound tiptap code (`EditorView`) ever
|
|
9
9
|
enters a native bundle — divergence lives at the file-suffix boundary.
|
|
10
10
|
|
|
11
|
-
```
|
|
11
|
+
```tsx
|
|
12
|
+
import { useState } from 'octane'
|
|
12
13
|
import { TiptapEditor, supported } from '@octane-xplat/tiptap'
|
|
14
|
+
import { Text } from '@octane-xplat/ui'
|
|
15
|
+
|
|
16
|
+
export function Notes() {
|
|
17
|
+
const [html, setHtml] = useState('<p>Trip notes</p>')
|
|
18
|
+
return supported ? (
|
|
19
|
+
<TiptapEditor value={html} onChange={setHtml} />
|
|
20
|
+
) : (
|
|
21
|
+
<Text>Editing is unavailable on this target</Text>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
On web the `web` prop configures the underlying tiptap `Editor`: `extensions`
|
|
27
|
+
appends caller `Extension`/`Node`/`Mark` entries after the built-in
|
|
28
|
+
StarterKit, and `starterKit` takes `StarterKit.configure()` options or
|
|
29
|
+
`false` to hand the schema to `extensions` entirely. A caller `starterKit`
|
|
30
|
+
entry replaces the built-in instead of registering it twice. The options are
|
|
31
|
+
web-only. Android and AppKit do not run caller ProseMirror extensions,
|
|
32
|
+
plugins, node views, or browser menus. A passed `web` option has no effect on
|
|
33
|
+
those targets.
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { TiptapEditor } from '@octane-xplat/tiptap'
|
|
37
|
+
import { Mark } from '@tiptap/core'
|
|
38
|
+
|
|
39
|
+
const Spoiler = Mark.create({
|
|
40
|
+
name: 'spoiler',
|
|
41
|
+
parseHTML: () => [{ tag: 'span[data-spoiler]' }],
|
|
42
|
+
renderHTML: () => ['span', { 'data-spoiler': '' }, 0],
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
export function Notes() {
|
|
46
|
+
return <TiptapEditor web={{ extensions: [Spoiler] }} />
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Engine and feature boundary
|
|
51
|
+
|
|
52
|
+
| Target | Editing engine | `web` options | Caller extensions, plugins, and browser views |
|
|
53
|
+
| --- | --- | --- | --- |
|
|
54
|
+
| Web | Tiptap `Editor` + `EditorContent` | `extensions` and `starterKit` apply | Supported by the web Tiptap engine |
|
|
55
|
+
| Android | WordPress Aztec `AztecText`; a DOM-free Tiptap bridge converts JSON to and from HTML | Ignored | Unsupported; no live ProseMirror view, plugin, node view, or browser menu runs |
|
|
56
|
+
| iOS | Unsupported placeholder from `@octane-xplat/richtext` | Ignored | Unsupported; `supported` is `false` |
|
|
57
|
+
| macOS AppKit | Bundled Tiptap editor in WKWebView | Ignored by the AppKit host | Unsupported through this facade |
|
|
58
|
+
|
|
59
|
+
On Android, keep HTML as the facade's canonical interchange. Tiptap JSON is a
|
|
60
|
+
best-effort conversion over Aztec HTML, not a live ProseMirror document. The
|
|
61
|
+
2026-10-06 [Aztec nested-tree run](../../docs/verify/nested-tree-editor.md)
|
|
62
|
+
preserved nested wrappers, attributes, and child order through synthetic text
|
|
63
|
+
edits and save/reopen. It also flattened paragraphs and accumulated `<br>`
|
|
64
|
+
elements on reopen; it did not qualify Tiptap JSON, OS input, or structural
|
|
65
|
+
tree commands. See the [per-row capability record](../../docs/notes/editor-capabilities.md).
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { useState } from 'octane'
|
|
69
|
+
import { TiptapEditor, supported } from '@octane-xplat/tiptap'
|
|
70
|
+
import { Text } from '@octane-xplat/ui'
|
|
71
|
+
|
|
72
|
+
export function Notes() {
|
|
73
|
+
const [html, setHTML] = useState('<p>Travel notes</p>')
|
|
74
|
+
return supported ? (
|
|
75
|
+
<TiptapEditor value={html} editable onChange={setHTML} />
|
|
76
|
+
) : (
|
|
77
|
+
<Text>Editing is unavailable on this target</Text>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
13
80
|
```
|
|
14
81
|
|
|
15
82
|
`value`/`onChange` exchange document HTML. `getJSON`/`setJSON` exchange
|
|
@@ -19,8 +86,50 @@ returns `null`) on runtimes that cannot host the schema modules. On native,
|
|
|
19
86
|
HTML is the canonical interchange format; JSON output is a best-effort
|
|
20
87
|
mapping of Aztec's flat span list onto ProseMirror's tree.
|
|
21
88
|
|
|
89
|
+
```tsx
|
|
90
|
+
import { useRef, useState } from 'octane'
|
|
91
|
+
import { TiptapEditor, type TiptapEditorHandle } from '@octane-xplat/tiptap'
|
|
92
|
+
import { Button } from '@octane-xplat/ui'
|
|
93
|
+
|
|
94
|
+
export function DocumentCopy() {
|
|
95
|
+
const editor = useRef<TiptapEditorHandle | null>(null)
|
|
96
|
+
const [html, setHtml] = useState('<p>Trip notes</p>')
|
|
97
|
+
const [jsonReady, setJsonReady] = useState(false)
|
|
98
|
+
return (
|
|
99
|
+
<>
|
|
100
|
+
<TiptapEditor
|
|
101
|
+
value={html}
|
|
102
|
+
onChange={setHtml}
|
|
103
|
+
ref={(handle) => {
|
|
104
|
+
editor.current = handle
|
|
105
|
+
}}
|
|
106
|
+
onReady={() => setJsonReady(editor.current?.getJSON() != null)}
|
|
107
|
+
onJSONReady={setJsonReady}
|
|
108
|
+
/>
|
|
109
|
+
<Button
|
|
110
|
+
isDisabled={!jsonReady}
|
|
111
|
+
onPress={() => {
|
|
112
|
+
const document = editor.current?.getJSON()
|
|
113
|
+
if (document) editor.current?.setJSON(document)
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
Round-trip document
|
|
117
|
+
</Button>
|
|
118
|
+
</>
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
22
123
|
The tiptap family pins to `3.28.0` to match `@octanejs/tiptap@0.0.51` —
|
|
23
124
|
extension `^` ranges float ahead of core and break (`getPreviousBlockSibling`),
|
|
24
125
|
so consumers should keep the workspace override. See
|
|
25
|
-
[`docs/rich-text.md`](../../docs/rich-text.md) for the shared contract,
|
|
126
|
+
[`docs/app/rich-text.md`](../../docs/app/rich-text.md) for the shared contract,
|
|
26
127
|
format vocabulary, and known limits.
|
|
128
|
+
|
|
129
|
+
## macOS AppKit
|
|
130
|
+
|
|
131
|
+
The macOS export mounts a bundled local editor document in WKWebView.
|
|
132
|
+
RichText uses StarterKit; Tiptap and Lexical use their existing web facades.
|
|
133
|
+
Wait for `onReady`; synchronous getters return the latest received snapshot
|
|
134
|
+
and commands cross WebKit asynchronously. The `native` handle is the Swift
|
|
135
|
+
host transport. See [AppKit setup and engine limits](../../docs/app/rich-text.md#macos-appkit-editing).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare const html: string; export default html
|