@getguru/slate-yjs-core 1.0.3

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.
Files changed (126) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +3 -0
  3. package/dist/applyToSlate/index.d.ts +23 -0
  4. package/dist/applyToSlate/textEvent.d.ts +4 -0
  5. package/dist/applyToYjs/index.d.ts +4 -0
  6. package/dist/applyToYjs/node/index.d.ts +4 -0
  7. package/dist/applyToYjs/node/insertNode.d.ts +4 -0
  8. package/dist/applyToYjs/node/mergeNode.d.ts +4 -0
  9. package/dist/applyToYjs/node/moveNode.d.ts +4 -0
  10. package/dist/applyToYjs/node/removeNode.d.ts +4 -0
  11. package/dist/applyToYjs/node/setNode.d.ts +4 -0
  12. package/dist/applyToYjs/node/splitNode.d.ts +4 -0
  13. package/dist/applyToYjs/text/index.d.ts +4 -0
  14. package/dist/applyToYjs/text/insertText.d.ts +4 -0
  15. package/dist/applyToYjs/text/removeText.d.ts +4 -0
  16. package/dist/applyToYjs/types.d.ts +9 -0
  17. package/dist/index.cjs +1360 -0
  18. package/dist/index.cjs.map +1 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.global.js +10365 -0
  21. package/dist/index.global.js.map +1 -0
  22. package/dist/index.js +1338 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/model/types.d.ts +38 -0
  25. package/dist/plugins/index.d.ts +4 -0
  26. package/dist/plugins/withCursors.d.ts +39 -0
  27. package/dist/plugins/withYHistory.d.ts +20 -0
  28. package/dist/plugins/withYjs.d.ts +43 -0
  29. package/dist/utils/clone.d.ts +5 -0
  30. package/dist/utils/convert.d.ts +8 -0
  31. package/dist/utils/delta.d.ts +8 -0
  32. package/dist/utils/errors.d.ts +2 -0
  33. package/dist/utils/location.d.ts +12 -0
  34. package/dist/utils/object.d.ts +10 -0
  35. package/dist/utils/position.d.ts +20 -0
  36. package/dist/utils/slate.d.ts +3 -0
  37. package/dist/utils/yjs.d.ts +5 -0
  38. package/package.json +47 -0
  39. package/src/applyToSlate/index.ts +118 -0
  40. package/src/applyToSlate/textEvent.ts +280 -0
  41. package/src/applyToYjs/index.ts +28 -0
  42. package/src/applyToYjs/node/index.ts +17 -0
  43. package/src/applyToYjs/node/insertNode.ts +23 -0
  44. package/src/applyToYjs/node/mergeNode.ts +82 -0
  45. package/src/applyToYjs/node/moveNode.ts +57 -0
  46. package/src/applyToYjs/node/removeNode.ts +16 -0
  47. package/src/applyToYjs/node/setNode.ts +42 -0
  48. package/src/applyToYjs/node/splitNode.ts +98 -0
  49. package/src/applyToYjs/text/index.ts +9 -0
  50. package/src/applyToYjs/text/insertText.ts +27 -0
  51. package/src/applyToYjs/text/removeText.ts +16 -0
  52. package/src/applyToYjs/types.ts +12 -0
  53. package/src/index.ts +47 -0
  54. package/src/model/types.ts +50 -0
  55. package/src/plugins/index.ts +3 -0
  56. package/src/plugins/withCursors.ts +269 -0
  57. package/src/plugins/withYHistory.ts +183 -0
  58. package/src/plugins/withYjs.ts +284 -0
  59. package/src/utils/clone.ts +29 -0
  60. package/src/utils/convert.ts +48 -0
  61. package/src/utils/delta.ts +97 -0
  62. package/src/utils/errors.ts +20 -0
  63. package/src/utils/location.ts +157 -0
  64. package/src/utils/object.ts +93 -0
  65. package/src/utils/position.ts +300 -0
  66. package/src/utils/slate.ts +11 -0
  67. package/src/utils/yjs.ts +10 -0
  68. package/test/collaboration/addMark/acrossMarks.tsx +40 -0
  69. package/test/collaboration/addMark/acrossMarksSame.tsx +36 -0
  70. package/test/collaboration/addMark/atBeginningOfDocument.tsx +27 -0
  71. package/test/collaboration/addMark/atEndOfDocument.tsx +30 -0
  72. package/test/collaboration/addMark/withOtherMarks.tsx +31 -0
  73. package/test/collaboration/insertNode/atBeginningOfDocument.tsx +28 -0
  74. package/test/collaboration/insertNode/atEndOfDocument.tsx +28 -0
  75. package/test/collaboration/insertNode/inTheMiddle.tsx +30 -0
  76. package/test/collaboration/insertText/atBeginningOfBlock.tsx +26 -0
  77. package/test/collaboration/insertText/atBeginningOfDocument.tsx +26 -0
  78. package/test/collaboration/insertText/atEndOfBlock.tsx +26 -0
  79. package/test/collaboration/insertText/atEndOfDocument.tsx +26 -0
  80. package/test/collaboration/insertText/inTheMiddle.tsx +32 -0
  81. package/test/collaboration/insertText/inTheMiddleOfNestedBlock.tsx +30 -0
  82. package/test/collaboration/insertText/insideMarks.tsx +28 -0
  83. package/test/collaboration/insertText/withEmptyString.tsx +25 -0
  84. package/test/collaboration/insertText/withEntities.tsx +28 -0
  85. package/test/collaboration/insertText/withMarks.tsx +25 -0
  86. package/test/collaboration/insertText/withUnicode.tsx +28 -0
  87. package/test/collaboration/mergeNode/afterADeleteBackward.tsx +27 -0
  88. package/test/collaboration/mergeNode/inSameParent.tsx +34 -0
  89. package/test/collaboration/mergeNode/onMixedNestedNodes.tsx +29 -0
  90. package/test/collaboration/mergeNode/onMixedTypeNodes.tsx +27 -0
  91. package/test/collaboration/mergeNode/withUnicode.tsx +25 -0
  92. package/test/collaboration/moveNode/downward/whenBlockBecomesNested.tsx +43 -0
  93. package/test/collaboration/moveNode/downward/whenBlockBecomesNonNested.tsx +41 -0
  94. package/test/collaboration/moveNode/downward/whenBlockStaysNested.tsx +38 -0
  95. package/test/collaboration/moveNode/downward/whenBlockStaysNonNested.tsx +30 -0
  96. package/test/collaboration/moveNode/upward/whenBlockBecomesNested.tsx +43 -0
  97. package/test/collaboration/moveNode/upward/whenBlockBecomesNonNested.tsx +41 -0
  98. package/test/collaboration/moveNode/upward/whenBlockStaysNested.tsx +38 -0
  99. package/test/collaboration/moveNode/upward/whenBlockStaysNonNested.tsx +30 -0
  100. package/test/collaboration/removeMark/inTheMiddleOfText.tsx +43 -0
  101. package/test/collaboration/removeMark/withAddMark.tsx +31 -0
  102. package/test/collaboration/removeMark/withOtherMarks.tsx +47 -0
  103. package/test/collaboration/removeNode/atBeginningOfDocument.tsx +26 -0
  104. package/test/collaboration/removeNode/atEndOfDocument.tsx +26 -0
  105. package/test/collaboration/removeNode/nestedBlock.tsx +28 -0
  106. package/test/collaboration/removeNode/wrapperBlock.tsx +28 -0
  107. package/test/collaboration/removeText/atBeginningOfDocument.tsx +34 -0
  108. package/test/collaboration/removeText/atEndOfDocument.tsx +37 -0
  109. package/test/collaboration/removeText/withUnicode.tsx +29 -0
  110. package/test/collaboration/setNode/atBeginningOfDocument.tsx +27 -0
  111. package/test/collaboration/setNode/atEndOfDocument.tsx +27 -0
  112. package/test/collaboration/setNode/onDataChange.tsx +35 -0
  113. package/test/collaboration/setNode/onDataChangeOnInline.tsx +35 -0
  114. package/test/collaboration/setNode/onResetBlock.tsx +27 -0
  115. package/test/collaboration/setNode/withAChangeOfType.tsx +26 -0
  116. package/test/collaboration/splitNode/atBeginningOfDocument.tsx +28 -0
  117. package/test/collaboration/splitNode/atEndOfBlock.tsx +27 -0
  118. package/test/collaboration/splitNode/atEndOfDocument.tsx +27 -0
  119. package/test/collaboration/splitNode/onNonDefaultBlock.tsx +27 -0
  120. package/test/collaboration/splitNode/withMultipleSubNodes.tsx +32 -0
  121. package/test/collaboration/splitNode/withUnicode.tsx +29 -0
  122. package/test/index.test.ts +65 -0
  123. package/test/slate.d.ts +8 -0
  124. package/test/withTestingElements.ts +46 -0
  125. package/tsconfig.json +11 -0
  126. package/tsup.config.ts +32 -0
@@ -0,0 +1,93 @@
1
+ type InspectableObject = Record<string | number | symbol, unknown>;
2
+
3
+ function isObject(o: unknown): o is InspectableObject {
4
+ return Object.prototype.toString.call(o) === '[object Object]';
5
+ }
6
+
7
+ export function isPlainObject(o: unknown): o is InspectableObject {
8
+ if (!isObject(o)) {
9
+ return false;
10
+ }
11
+
12
+ // If has modified constructor
13
+ const ctor = o.constructor;
14
+ if (ctor === undefined) {
15
+ return true;
16
+ }
17
+
18
+ // If has modified prototype
19
+ const prot = ctor.prototype;
20
+ if (isObject(prot) === false) {
21
+ return false;
22
+ }
23
+
24
+ // If constructor does not have an Object-specific method
25
+ if (prot.hasOwnProperty('isPrototypeOf') === false) {
26
+ return false;
27
+ }
28
+
29
+ // Most likely a plain Object
30
+ return true;
31
+ }
32
+
33
+ // Slates deep equality function: https://github.com/ianstormtaylor/slate/blob/68aff89e892fe15a16314398ff052ade6068900b/packages/slate/src/utils/deep-equal.ts#L13
34
+ // We have to match slates deepEquals behavior to merge insert deltas in the same way slate does.
35
+ export function deepEquals(
36
+ node: InspectableObject,
37
+ another: InspectableObject
38
+ ): boolean {
39
+ // eslint-disable-next-line guard-for-in
40
+ for (const key in node) {
41
+ const a = node[key];
42
+ const b = another[key];
43
+
44
+ if (isPlainObject(a) && isPlainObject(b)) {
45
+ if (!deepEquals(a, b)) {
46
+ return false;
47
+ }
48
+ } else if (Array.isArray(a) && Array.isArray(b)) {
49
+ if (a.length !== b.length) return false;
50
+ for (let i = 0; i < a.length; i++) {
51
+ if (a[i] !== b[i]) {
52
+ return false;
53
+ }
54
+ }
55
+ } else if (a !== b) {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ for (const key in another) {
61
+ if (node[key] === undefined && another[key] !== undefined) {
62
+ return false;
63
+ }
64
+ }
65
+
66
+ return true;
67
+ }
68
+
69
+ export function pick<TObj, TKeys extends keyof TObj>(
70
+ obj: TObj,
71
+ ...keys: TKeys[]
72
+ ): Pick<TObj, TKeys> {
73
+ return Object.fromEntries(
74
+ Object.entries(obj).filter(([key]) => keys.includes(key as TKeys))
75
+ ) as Pick<TObj, TKeys>;
76
+ }
77
+
78
+ export function omit<TObj, TKeys extends keyof TObj>(
79
+ obj: TObj,
80
+ ...keys: TKeys[]
81
+ ): Omit<TObj, TKeys> {
82
+ return Object.fromEntries(
83
+ Object.entries(obj).filter(([key]) => !keys.includes(key as TKeys))
84
+ ) as Omit<TObj, TKeys>;
85
+ }
86
+
87
+ export function omitNullEntries<TObj>(obj: TObj): {
88
+ [K in keyof TObj]: TObj[K] extends null ? never : K;
89
+ } {
90
+ return Object.fromEntries(
91
+ Object.entries(obj).filter(([, value]) => value !== null)
92
+ ) as { [K in keyof TObj]: TObj[K] extends null ? never : K };
93
+ }
@@ -0,0 +1,300 @@
1
+ import { BasePoint, BaseRange, Node, Text } from 'slate';
2
+ import * as Y from 'yjs';
3
+ import { InsertDelta, RelativeRange, TextRange } from '../model/types';
4
+ import { getInsertDeltaLength, yTextToInsertDelta } from './delta';
5
+ import { isSyncSkewError } from './errors';
6
+ import { getSlatePath, getYTarget, yOffsetToSlateOffsets } from './location';
7
+ import { assertDocumentAttachment } from './yjs';
8
+
9
+ export const STORED_POSITION_PREFIX = '__slateYjsStoredPosition_';
10
+
11
+ export function slatePointToRelativePosition(
12
+ sharedRoot: Y.XmlText,
13
+ slateRoot: Node,
14
+ point: BasePoint
15
+ ): Y.RelativePosition {
16
+ const { yTarget, yParent, textRange } = getYTarget(
17
+ sharedRoot,
18
+ slateRoot,
19
+ point.path
20
+ );
21
+
22
+ if (yTarget) {
23
+ throw new Error(
24
+ 'Slate point points to a non-text element inside sharedRoot'
25
+ );
26
+ }
27
+
28
+ const index = textRange.start + point.offset;
29
+ return Y.createRelativePositionFromTypeIndex(
30
+ yParent,
31
+ index,
32
+ index === textRange.end ? -1 : 0
33
+ );
34
+ }
35
+
36
+ export function absolutePositionToSlatePoint(
37
+ sharedRoot: Y.XmlText,
38
+ slateRoot: Node,
39
+ { type, index, assoc }: Y.AbsolutePosition
40
+ ): BasePoint | null {
41
+ if (!(type instanceof Y.XmlText)) {
42
+ throw new Error('Absolute position points to a non-XMLText');
43
+ }
44
+
45
+ try {
46
+ const parentPath = getSlatePath(sharedRoot, slateRoot, type);
47
+ const parent = Node.get(slateRoot, parentPath);
48
+
49
+ if (Text.isText(parent)) {
50
+ return null;
51
+ }
52
+
53
+ const [pathOffset, textOffset] = yOffsetToSlateOffsets(parent, index, {
54
+ assoc,
55
+ });
56
+
57
+ const target = parent.children[pathOffset];
58
+ if (!Text.isText(target)) {
59
+ return null;
60
+ }
61
+
62
+ return { path: [...parentPath, pathOffset], offset: textOffset };
63
+ } catch (error) {
64
+ if (isSyncSkewError(error)) {
65
+ return null;
66
+ }
67
+ throw error;
68
+ }
69
+ }
70
+
71
+ export function relativePositionToSlatePoint(
72
+ sharedRoot: Y.XmlText,
73
+ slateRoot: Node,
74
+ pos: Y.RelativePosition
75
+ ): BasePoint | null {
76
+ if (!sharedRoot.doc) {
77
+ throw new Error("sharedRoot isn't attach to a yDoc");
78
+ }
79
+
80
+ const absPos = Y.createAbsolutePositionFromRelativePosition(
81
+ pos,
82
+ sharedRoot.doc
83
+ );
84
+
85
+ return absPos && absolutePositionToSlatePoint(sharedRoot, slateRoot, absPos);
86
+ }
87
+
88
+ export function getStoredPosition(
89
+ sharedRoot: Y.XmlText,
90
+ key: string
91
+ ): Y.RelativePosition | null {
92
+ const rawPosition = sharedRoot.getAttribute(STORED_POSITION_PREFIX + key);
93
+ if (!rawPosition) {
94
+ return null;
95
+ }
96
+
97
+ return Y.decodeRelativePosition(rawPosition);
98
+ }
99
+
100
+ export function getStoredPositions(
101
+ sharedRoot: Y.XmlText
102
+ ): Record<string, Y.RelativePosition> {
103
+ return Object.fromEntries(
104
+ Object.entries(sharedRoot.getAttributes())
105
+ .filter(([key]) => key.startsWith(STORED_POSITION_PREFIX))
106
+ .map(([key, position]) => [
107
+ key.slice(STORED_POSITION_PREFIX.length),
108
+ Y.createRelativePositionFromJSON(position),
109
+ ])
110
+ );
111
+ }
112
+
113
+ function getStoredPositionsAbsolute(sharedRoot: Y.XmlText) {
114
+ assertDocumentAttachment(sharedRoot);
115
+
116
+ return Object.fromEntries(
117
+ Object.entries(sharedRoot.getAttributes())
118
+ .filter(([key]) => key.startsWith(STORED_POSITION_PREFIX))
119
+ .map(
120
+ ([key, position]) =>
121
+ [
122
+ key.slice(STORED_POSITION_PREFIX.length),
123
+ Y.createAbsolutePositionFromRelativePosition(
124
+ Y.decodeRelativePosition(position),
125
+ sharedRoot.doc
126
+ ),
127
+ ] as const
128
+ )
129
+ .filter(([, position]) => position)
130
+ ) as Record<string, Y.AbsolutePosition>;
131
+ }
132
+
133
+ export function removeStoredPosition(sharedRoot: Y.XmlText, key: string) {
134
+ sharedRoot.removeAttribute(STORED_POSITION_PREFIX + key);
135
+ }
136
+
137
+ export function setStoredPosition(
138
+ sharedRoot: Y.XmlText,
139
+ key: string,
140
+ position: Y.RelativePosition
141
+ ) {
142
+ sharedRoot.setAttribute(
143
+ STORED_POSITION_PREFIX + key,
144
+ Y.encodeRelativePosition(position)
145
+ );
146
+ }
147
+
148
+ function getAbsolutePositionsInTextRange(
149
+ absolutePositions: Record<string, Y.AbsolutePosition>,
150
+ yTarget: Y.XmlText,
151
+ textRange?: TextRange
152
+ ) {
153
+ return Object.fromEntries(
154
+ Object.entries(absolutePositions).filter(([, position]) => {
155
+ if (position.type !== yTarget) {
156
+ return false;
157
+ }
158
+
159
+ if (!textRange) {
160
+ return true;
161
+ }
162
+
163
+ return position.assoc >= 0
164
+ ? position.index >= textRange.start && position.index < textRange.end
165
+ : position.index > textRange.start && position.index >= textRange.end;
166
+ })
167
+ );
168
+ }
169
+
170
+ function getAbsolutePositionsInYText(
171
+ absolutePositions: Record<string, Y.AbsolutePosition>,
172
+ yText: Y.XmlText,
173
+ parentPath = ''
174
+ ): Record<string, Record<string, Y.AbsolutePosition>> {
175
+ const positions = {
176
+ [parentPath]: getAbsolutePositionsInTextRange(absolutePositions, yText),
177
+ };
178
+
179
+ const insertDelta = yTextToInsertDelta(yText);
180
+ insertDelta.forEach(({ insert }, i) => {
181
+ if (insert instanceof Y.XmlText) {
182
+ Object.assign(
183
+ positions,
184
+ getAbsolutePositionsInYText(
185
+ absolutePositions,
186
+ insert,
187
+ parentPath ? `${parentPath}.${i}` : i.toString()
188
+ )
189
+ );
190
+ }
191
+ });
192
+
193
+ return positions;
194
+ }
195
+
196
+ export function getStoredPositionsInDeltaAbsolute(
197
+ sharedRoot: Y.XmlText,
198
+ yText: Y.XmlText,
199
+ delta: InsertDelta,
200
+ deltaOffset = 0
201
+ ) {
202
+ const absolutePositions = getStoredPositionsAbsolute(sharedRoot);
203
+
204
+ const positions = {
205
+ '': getAbsolutePositionsInTextRange(absolutePositions, yText, {
206
+ start: deltaOffset,
207
+ end: deltaOffset + getInsertDeltaLength(delta),
208
+ }),
209
+ };
210
+
211
+ delta.forEach(({ insert }, i) => {
212
+ if (insert instanceof Y.XmlText) {
213
+ Object.assign(
214
+ positions,
215
+ getAbsolutePositionsInYText(absolutePositions, insert, i.toString())
216
+ );
217
+ }
218
+ });
219
+
220
+ return positions;
221
+ }
222
+
223
+ export function restoreStoredPositionsWithDeltaAbsolute(
224
+ sharedRoot: Y.XmlText,
225
+ yText: Y.XmlText,
226
+ absolutePositions: Record<string, Record<string, Y.AbsolutePosition>>,
227
+ delta: InsertDelta,
228
+ newDeltaOffset = 0,
229
+ previousDeltaOffset = 0,
230
+ path = ''
231
+ ) {
232
+ const toRestore = absolutePositions[path];
233
+
234
+ if (toRestore) {
235
+ Object.entries(toRestore).forEach(([key, position]) => {
236
+ setStoredPosition(
237
+ sharedRoot,
238
+ key,
239
+ Y.createRelativePositionFromTypeIndex(
240
+ yText,
241
+ position.index - previousDeltaOffset + newDeltaOffset,
242
+ position.assoc
243
+ )
244
+ );
245
+ });
246
+ }
247
+
248
+ delta.forEach(({ insert }, i) => {
249
+ if (insert instanceof Y.XmlText) {
250
+ restoreStoredPositionsWithDeltaAbsolute(
251
+ sharedRoot,
252
+ insert,
253
+ absolutePositions,
254
+ yTextToInsertDelta(insert),
255
+ 0,
256
+ 0,
257
+ path ? `${path}.${i}` : i.toString()
258
+ );
259
+ }
260
+ });
261
+ }
262
+
263
+ export function slateRangeToRelativeRange(
264
+ sharedRoot: Y.XmlText,
265
+ slateRoot: Node,
266
+ range: BaseRange
267
+ ): RelativeRange {
268
+ return {
269
+ anchor: slatePointToRelativePosition(sharedRoot, slateRoot, range.anchor),
270
+ focus: slatePointToRelativePosition(sharedRoot, slateRoot, range.focus),
271
+ };
272
+ }
273
+
274
+ export function relativeRangeToSlateRange(
275
+ sharedRoot: Y.XmlText,
276
+ slateRoot: Node,
277
+ range: RelativeRange
278
+ ): BaseRange | null {
279
+ const anchor = relativePositionToSlatePoint(
280
+ sharedRoot,
281
+ slateRoot,
282
+ range.anchor
283
+ );
284
+
285
+ if (!anchor) {
286
+ return null;
287
+ }
288
+
289
+ const focus = relativePositionToSlatePoint(
290
+ sharedRoot,
291
+ slateRoot,
292
+ range.focus
293
+ );
294
+
295
+ if (!focus) {
296
+ return null;
297
+ }
298
+
299
+ return { anchor, focus };
300
+ }
@@ -0,0 +1,11 @@
1
+ import { BaseText, Descendant, Text } from 'slate';
2
+ import { omit } from './object';
3
+
4
+ export function getProperties<TNode extends Descendant>(
5
+ node: TNode
6
+ ): Omit<TNode, TNode extends BaseText ? 'text' : 'children'> {
7
+ return omit(
8
+ node,
9
+ (Text.isText(node) ? 'text' : 'children') as keyof TNode
10
+ ) as Omit<TNode, TNode extends BaseText ? 'text' : 'children'>;
11
+ }
@@ -0,0 +1,10 @@
1
+ import * as Y from 'yjs';
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
+ export function assertDocumentAttachment<T extends Y.AbstractType<any>>(
5
+ sharedType: T
6
+ ): asserts sharedType is T & { doc: NonNullable<T['doc']> } {
7
+ if (!sharedType.doc) {
8
+ throw new Error("shared type isn't attached to a document");
9
+ }
10
+ }
@@ -0,0 +1,40 @@
1
+ /** @jsx jsx */
2
+ import { Editor } from 'slate';
3
+ import { jsx } from '../../../../../support/jsx';
4
+
5
+ export const input = (
6
+ <editor>
7
+ <unstyled>
8
+ <text>
9
+ Hel
10
+ <anchor />l
11
+ </text>
12
+ <text bold>o</text>
13
+ <text>
14
+ {' '}
15
+ w<focus />
16
+ orld!
17
+ </text>
18
+ </unstyled>
19
+ </editor>
20
+ );
21
+
22
+ export const expected = (
23
+ <editor>
24
+ <unstyled>
25
+ <text>Hel</text>
26
+ <anchor />
27
+ <text italic>l</text>
28
+ <text italic bold>
29
+ o
30
+ </text>
31
+ <text italic> w</text>
32
+ <focus />
33
+ <text>orld!</text>
34
+ </unstyled>
35
+ </editor>
36
+ );
37
+
38
+ export function run(editor: Editor) {
39
+ editor.addMark('italic', true);
40
+ }
@@ -0,0 +1,36 @@
1
+ /** @jsx jsx */
2
+ import { Editor } from 'slate';
3
+ import { jsx } from '../../../../../support/jsx';
4
+
5
+ export const input = (
6
+ <editor>
7
+ <unstyled>
8
+ <text>
9
+ Hel
10
+ <anchor />l
11
+ </text>
12
+ <text bold>o</text>
13
+ <text>
14
+ {' '}
15
+ w<focus />
16
+ orld!
17
+ </text>
18
+ </unstyled>
19
+ </editor>
20
+ );
21
+
22
+ export const expected = (
23
+ <editor>
24
+ <unstyled>
25
+ <text>Hel</text>
26
+ <anchor />
27
+ <text bold>lo w</text>
28
+ <focus />
29
+ <text>orld!</text>
30
+ </unstyled>
31
+ </editor>
32
+ );
33
+
34
+ export function run(editor: Editor) {
35
+ editor.addMark('bold', true);
36
+ }
@@ -0,0 +1,27 @@
1
+ /** @jsx jsx */
2
+ import { Editor } from 'slate';
3
+ import { jsx } from '../../../../../support/jsx';
4
+
5
+ export const input = (
6
+ <editor>
7
+ <unstyled>
8
+ <anchor />
9
+ Hello
10
+ <focus /> world!
11
+ </unstyled>
12
+ </editor>
13
+ );
14
+
15
+ export const expected = (
16
+ <editor>
17
+ <unstyled>
18
+ <anchor />
19
+ <text bold>Hello</text>
20
+ <focus /> world!
21
+ </unstyled>
22
+ </editor>
23
+ );
24
+
25
+ export function run(editor: Editor) {
26
+ editor.addMark('bold', true);
27
+ }
@@ -0,0 +1,30 @@
1
+ /** @jsx jsx */
2
+ import { Editor } from 'slate';
3
+ import { jsx } from '../../../../../support/jsx';
4
+
5
+ export const input = (
6
+ <editor>
7
+ <unstyled>
8
+ Hello <anchor />
9
+ world!
10
+ <focus />
11
+ </unstyled>
12
+ </editor>
13
+ );
14
+
15
+ export const expected = (
16
+ <editor>
17
+ <unstyled>
18
+ Hello{' '}
19
+ <text bold>
20
+ <anchor />
21
+ world!
22
+ </text>
23
+ <focus />
24
+ </unstyled>
25
+ </editor>
26
+ );
27
+
28
+ export function run(editor: Editor) {
29
+ editor.addMark('bold', true);
30
+ }
@@ -0,0 +1,31 @@
1
+ /** @jsx jsx */
2
+ import { Editor } from 'slate';
3
+ import { jsx } from '../../../../../support/jsx';
4
+
5
+ export const input = (
6
+ <editor>
7
+ <unstyled>
8
+ <anchor />
9
+ <text italic>Hello world</text>
10
+ <focus />
11
+ <text bold>!</text>
12
+ </unstyled>
13
+ </editor>
14
+ );
15
+
16
+ export const expected = (
17
+ <editor>
18
+ <unstyled>
19
+ <anchor />
20
+ <text italic bold>
21
+ Hello world
22
+ </text>
23
+ <focus />
24
+ <text bold>!</text>
25
+ </unstyled>
26
+ </editor>
27
+ );
28
+
29
+ export function run(editor: Editor) {
30
+ editor.addMark('bold', true);
31
+ }
@@ -0,0 +1,28 @@
1
+ /** @jsx jsx */
2
+ import { Editor } from 'slate';
3
+ import { jsx } from '../../../../../support/jsx';
4
+
5
+ export const input = (
6
+ <editor>
7
+ <unstyled>
8
+ <cursor />
9
+ Hello world!
10
+ </unstyled>
11
+ <unstyled>Welcome to slate-yjs!</unstyled>
12
+ </editor>
13
+ );
14
+
15
+ export const expected = (
16
+ <editor>
17
+ <h1>
18
+ Foo bar!
19
+ <cursor />
20
+ </h1>
21
+ <unstyled>Hello world!</unstyled>
22
+ <unstyled>Welcome to slate-yjs!</unstyled>
23
+ </editor>
24
+ );
25
+
26
+ export function run(editor: Editor) {
27
+ editor.insertNode(<h1>Foo bar!</h1>);
28
+ }
@@ -0,0 +1,28 @@
1
+ /** @jsx jsx */
2
+ import { Editor } from 'slate';
3
+ import { jsx } from '../../../../../support/jsx';
4
+
5
+ export const input = (
6
+ <editor>
7
+ <unstyled>Hello world!</unstyled>
8
+ <unstyled>
9
+ Welcome to slate-yjs!
10
+ <cursor />
11
+ </unstyled>
12
+ </editor>
13
+ );
14
+
15
+ export const expected = (
16
+ <editor>
17
+ <unstyled>Hello world!</unstyled>
18
+ <unstyled>Welcome to slate-yjs!</unstyled>
19
+ <h1>
20
+ Foo bar!
21
+ <cursor />
22
+ </h1>
23
+ </editor>
24
+ );
25
+
26
+ export function run(editor: Editor) {
27
+ editor.insertNode(<h1>Foo bar!</h1>);
28
+ }
@@ -0,0 +1,30 @@
1
+ /** @jsx jsx */
2
+ import { Editor } from 'slate';
3
+ import { jsx } from '../../../../../support/jsx';
4
+
5
+ export const input = (
6
+ <editor>
7
+ <unstyled>Hello world!</unstyled>
8
+ <unstyled>
9
+ Welcome
10
+ <cursor />
11
+ to slate-yjs!
12
+ </unstyled>
13
+ </editor>
14
+ );
15
+
16
+ export const expected = (
17
+ <editor>
18
+ <unstyled>Hello world!</unstyled>
19
+ <unstyled>Welcome</unstyled>
20
+ <h1>
21
+ Foo bar!
22
+ <cursor />
23
+ </h1>
24
+ <unstyled>to slate-yjs!</unstyled>
25
+ </editor>
26
+ );
27
+
28
+ export function run(editor: Editor) {
29
+ editor.insertNode(<h1>Foo bar!</h1>);
30
+ }
@@ -0,0 +1,26 @@
1
+ /** @jsx jsx */
2
+ import { Editor } from 'slate';
3
+ import { jsx } from '../../../../../support/jsx';
4
+
5
+ export const input = (
6
+ <editor>
7
+ <unstyled>Hello world!</unstyled>
8
+ <unstyled>
9
+ <cursor />
10
+ </unstyled>
11
+ </editor>
12
+ );
13
+
14
+ export const expected = (
15
+ <editor>
16
+ <unstyled>Hello world!</unstyled>
17
+ <unstyled>
18
+ Welcome to slate-yjs!
19
+ <cursor />
20
+ </unstyled>
21
+ </editor>
22
+ );
23
+
24
+ export function run(editor: Editor) {
25
+ editor.insertText('Welcome to slate-yjs!');
26
+ }