Skip to content

Commit 9951326

Browse files
authored
Add debug view to Playground (#53)
Add debug view to Playground
1 parent 4d73a82 commit 9951326

2 files changed

Lines changed: 98 additions & 8 deletions

File tree

playground/src/Editor.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export type EditorProps = {
5858
handle: DocHandle<unknown>
5959
path: Prop[]
6060
schemaAdapter: SchemaAdapter
61+
onStateChange?: (state: EditorState) => void
6162
}
6263

6364
const toggleBold = (schema: Schema) => toggleMarkCommand(schema.marks.strong)
@@ -97,8 +98,14 @@ function turnSelectionIntoBlockquote(
9798
return true
9899
}
99100

100-
export function Editor({ handle, path, schemaAdapter }: EditorProps) {
101+
export function Editor({
102+
handle,
103+
path,
104+
schemaAdapter,
105+
onStateChange,
106+
}: EditorProps) {
101107
const editorRoot = useRef<HTMLDivElement>(null)
108+
const onChange = useRef(onStateChange)
102109
const [view, setView] = useState<EditorView | null>(null)
103110
const [imageModalOpen, setImageModalOpen] = useState(false)
104111
const [linkModalOpen, setLinkModalOpen] = useState(false)
@@ -140,6 +147,7 @@ export function Editor({ handle, path, schemaAdapter }: EditorProps) {
140147
dispatchTransaction(this: EditorView, tr: Transaction) {
141148
const newState = this.state.apply(tr)
142149
this.updateState(newState)
150+
onChange.current?.(newState)
143151
setMarkState(activeMarks(newState, schema))
144152
},
145153
})

playground/src/Playground.tsx

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import React, { useEffect, useState } from "react"
22
import { Editor } from "./Editor"
3-
import { Repo, DocHandle } from "@automerge/automerge-repo"
3+
import {
4+
Repo,
5+
DocHandle,
6+
DocHandleChangePayload,
7+
} from "@automerge/automerge-repo"
48
//import { MessageChannelNetworkAdapter } from "@automerge/automerge-repo-network-messagechannel"
59
import { PausableNetworkAdapter } from "./PausableNetworkAdapter"
610
import TabContainer from "./Tabs"
@@ -13,6 +17,7 @@ import {
1317
import { Mark, Node } from "prosemirror-model"
1418
import { BlockMarker } from "../../src/types"
1519
import * as Automerge from "@automerge/automerge"
20+
import { EditorState } from "prosemirror-state"
1621

1722
// @ts-expect-error this is for debug
1823
window.A = Automerge
@@ -66,6 +71,7 @@ function Playground({ demoMode }: Props) {
6671
leftHandle={leftHandle}
6772
rightHandle={rightHandle}
6873
showTitle={!demoMode}
74+
showDebug={!demoMode}
6975
/>
7076
)
7177

@@ -85,6 +91,7 @@ function Playground({ demoMode }: Props) {
8591
leftHandle={leftHandle}
8692
rightHandle={rightHandle}
8793
showTitle={true}
94+
showDebug={true}
8895
/>
8996
),
9097
},
@@ -112,60 +119,135 @@ type TabProps = {
112119
leftHandle: DocHandle<{ text: string }>
113120
rightHandle: DocHandle<{ text: string }>
114121
showTitle: boolean
122+
showDebug: boolean
115123
}
116124

117-
function SameSchema({ leftHandle, rightHandle, showTitle }: TabProps) {
125+
function SameSchema({
126+
leftHandle,
127+
rightHandle,
128+
showTitle,
129+
showDebug,
130+
}: TabProps) {
118131
return (
119132
<div>
120133
{showTitle && <h2>Same Schema</h2>}
121134
<div id="editors">
122135
<div className="editor">
123-
<Editor
136+
<DebugEditor
124137
name="left"
125138
handle={leftHandle}
126139
path={["text"]}
127140
schemaAdapter={basicSchemaAdapter}
141+
debug={showDebug}
128142
/>
129143
</div>
130144
<div className="editor">
131-
<Editor
145+
<DebugEditor
132146
name="right"
133147
handle={rightHandle}
134148
path={["text"]}
135149
schemaAdapter={basicSchemaAdapter}
150+
debug={showDebug}
136151
/>
137152
</div>
138153
</div>
139154
</div>
140155
)
141156
}
142157

143-
function DifferentSchema({ leftHandle, rightHandle, showTitle }: TabProps) {
158+
function DifferentSchema({
159+
leftHandle,
160+
rightHandle,
161+
showTitle,
162+
showDebug,
163+
}: TabProps) {
144164
return (
145165
<div>
146166
{showTitle && <h2>Different Schema</h2>}
147167
<div id="editors">
148168
<div className="editor">
149-
<Editor
169+
<DebugEditor
150170
name="left"
151171
handle={leftHandle}
152172
path={["text"]}
153173
schemaAdapter={paragraphAndHeadingSchemaAdapter}
174+
debug={showDebug}
154175
/>
155176
</div>
156177
<div className="editor">
157-
<Editor
178+
<DebugEditor
158179
name="right"
159180
handle={rightHandle}
160181
path={["text"]}
161182
schemaAdapter={paragraphAndListItemsSchemaAdapter}
183+
debug={showDebug}
162184
/>
163185
</div>
164186
</div>
165187
</div>
166188
)
167189
}
168190

191+
function DebugEditor({
192+
name,
193+
handle,
194+
path,
195+
schemaAdapter,
196+
debug,
197+
}: {
198+
name?: string
199+
handle: DocHandle<unknown>
200+
path: Automerge.Prop[]
201+
schemaAdapter: SchemaAdapter
202+
debug?: boolean
203+
}) {
204+
const [spans, setSpans] = useState(Automerge.spans(handle.doc(), path))
205+
useEffect(() => {
206+
if (!debug) {
207+
return
208+
}
209+
function listener(payload: DocHandleChangePayload<unknown>) {
210+
setSpans(Automerge.spans(payload.doc, ["text"]))
211+
}
212+
handle.on("change", listener)
213+
214+
return () => {
215+
handle.off("change", listener)
216+
}
217+
}, [debug, handle])
218+
219+
const [editorState, setEditorState] = useState<EditorState | undefined>(
220+
undefined,
221+
)
222+
function handleEditorStateChange(state: EditorState) {
223+
setEditorState(state)
224+
}
225+
226+
return (
227+
<div>
228+
<Editor
229+
name={name}
230+
handle={handle}
231+
path={path}
232+
schemaAdapter={schemaAdapter}
233+
onStateChange={handleEditorStateChange}
234+
/>
235+
{debug && (
236+
<div style={{ display: "flex" }}>
237+
<div>
238+
<span>ProseMirror state</span>
239+
<pre>{JSON.stringify(editorState?.toJSON(), null, 2)}</pre>
240+
</div>
241+
<div>
242+
<span>Automerge state</span>
243+
<pre>{JSON.stringify(spans, null, 2)}</pre>
244+
</div>
245+
</div>
246+
)}
247+
</div>
248+
)
249+
}
250+
169251
const paragraphAndHeadingSchemaAdapter = new SchemaAdapter({
170252
nodes: {
171253
doc: {

0 commit comments

Comments
 (0)