edytor 0.0.7 → 0.0.9

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 (109) hide show
  1. package/README.md +225 -5
  2. package/dist/block/block.svelte.d.ts +123 -0
  3. package/dist/block/block.svelte.js +430 -0
  4. package/dist/block/block.utils.d.ts +82 -0
  5. package/dist/block/block.utils.js +499 -0
  6. package/dist/block/content.svelte.d.ts +14 -0
  7. package/dist/block/content.svelte.js +40 -0
  8. package/dist/block/inlineBlock.svelte.d.ts +30 -0
  9. package/dist/block/inlineBlock.svelte.js +53 -0
  10. package/dist/components/Block.svelte +27 -0
  11. package/dist/components/Block.svelte.d.ts +7 -0
  12. package/dist/components/Content.svelte +44 -0
  13. package/dist/components/Content.svelte.d.ts +7 -0
  14. package/dist/components/Edytor.svelte +165 -0
  15. package/dist/components/Edytor.svelte.d.ts +33 -0
  16. package/dist/components/InlineBlock.svelte +17 -0
  17. package/dist/components/InlineBlock.svelte.d.ts +7 -0
  18. package/dist/components/Mark.svelte +38 -0
  19. package/dist/components/Mark.svelte.d.ts +11 -0
  20. package/dist/components/ReadonlyEditor.svelte +46 -0
  21. package/dist/components/ReadonlyEditor.svelte.d.ts +4 -0
  22. package/dist/components/Text.svelte +37 -0
  23. package/dist/components/Text.svelte.d.ts +7 -0
  24. package/dist/components/readonlyElements.svelte.d.ts +82 -0
  25. package/dist/components/readonlyElements.svelte.js +144 -0
  26. package/dist/constants.d.ts +4 -0
  27. package/dist/constants.js +4 -0
  28. package/dist/dnd.svelte.d.ts +17 -0
  29. package/dist/dnd.svelte.js +125 -0
  30. package/dist/edytor.svelte.d.ts +94 -0
  31. package/dist/edytor.svelte.js +262 -0
  32. package/dist/edytor.utils.d.ts +3 -0
  33. package/dist/edytor.utils.js +78 -0
  34. package/dist/events/onBeforeInput.d.ts +2 -2
  35. package/dist/events/onBeforeInput.js +338 -0
  36. package/dist/events/onKeyDown.d.ts +2 -69
  37. package/dist/events/onKeyDown.js +18 -0
  38. package/dist/hotkeys.d.ts +27 -0
  39. package/dist/hotkeys.js +282 -0
  40. package/dist/index.d.ts +7 -5
  41. package/dist/index.js +7 -8
  42. package/dist/localProvider.d.ts +82 -0
  43. package/dist/localProvider.js +267 -0
  44. package/dist/plugins/arrowMove/arrowMove.d.ts +2 -0
  45. package/dist/plugins/arrowMove/arrowMove.js +66 -0
  46. package/dist/plugins/code/CodePlugin.svelte +218 -0
  47. package/dist/plugins/code/CodePlugin.svelte.d.ts +23 -0
  48. package/dist/plugins/code/prism.css +141 -0
  49. package/dist/plugins/image/ImagePlugin.svelte +22 -0
  50. package/dist/plugins/image/ImagePlugin.svelte.d.ts +20 -0
  51. package/dist/plugins/index.d.ts +3 -0
  52. package/dist/plugins/index.js +3 -0
  53. package/dist/plugins/mention/MentionPlugin.svelte +40 -0
  54. package/dist/plugins/mention/MentionPlugin.svelte.d.ts +20 -0
  55. package/dist/plugins/richtext/RichTextPlugin.svelte +241 -0
  56. package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +26 -0
  57. package/dist/plugins.d.ts +202 -0
  58. package/dist/plugins.js +19 -0
  59. package/dist/selection/selection.svelte.d.ts +68 -0
  60. package/dist/selection/selection.svelte.js +391 -0
  61. package/dist/selection/selection.utils.d.ts +14 -0
  62. package/dist/selection/selection.utils.js +153 -0
  63. package/dist/text/deltas.d.ts +11 -0
  64. package/dist/text/deltas.js +109 -0
  65. package/dist/text/text.svelte.d.ts +70 -0
  66. package/dist/text/text.svelte.js +119 -0
  67. package/dist/text/text.utils.d.ts +40 -0
  68. package/dist/text/text.utils.js +174 -0
  69. package/dist/utils/json.d.ts +32 -0
  70. package/dist/utils/json.js +2 -0
  71. package/dist/utils/jsx.d.ts +25 -0
  72. package/dist/utils/jsx.js +66 -0
  73. package/dist/utils/serialize.d.ts +1 -0
  74. package/dist/utils/serialize.js +1 -0
  75. package/dist/utils.d.ts +6 -0
  76. package/dist/utils.js +19 -0
  77. package/package.json +81 -33
  78. package/dist/edytor.cjs.development.js +0 -1762
  79. package/dist/edytor.cjs.development.js.map +0 -1
  80. package/dist/edytor.cjs.production.min.js +0 -2
  81. package/dist/edytor.cjs.production.min.js.map +0 -1
  82. package/dist/edytor.esm.js +0 -1691
  83. package/dist/edytor.esm.js.map +0 -1
  84. package/dist/events/index.d.ts +0 -3
  85. package/dist/events/onDrop.d.ts +0 -3
  86. package/dist/operations/deleteText.d.ts +0 -7
  87. package/dist/operations/formatText.d.ts +0 -20
  88. package/dist/operations/index.d.ts +0 -9
  89. package/dist/operations/insertText.d.ts +0 -5
  90. package/dist/operations/merge.d.ts +0 -3
  91. package/dist/operations/moveNode.d.ts +0 -12
  92. package/dist/operations/nestNode.d.ts +0 -2
  93. package/dist/operations/removeEmptyText.d.ts +0 -2
  94. package/dist/operations/splitLeaf.d.ts +0 -2
  95. package/dist/operations/splitNode.d.ts +0 -9
  96. package/dist/types.d.ts +0 -140
  97. package/dist/utils/common.d.ts +0 -17
  98. package/dist/utils/dropper.d.ts +0 -26
  99. package/dist/utils/index.d.ts +0 -6
  100. package/dist/utils/leaves.d.ts +0 -34
  101. package/dist/utils/nodes.d.ts +0 -14
  102. package/dist/utils/selection.d.ts +0 -51
  103. package/dist/utils/yClasses/EdytorDoc.d.ts +0 -16
  104. package/dist/utils/yClasses/index.d.ts +0 -3
  105. package/dist/utils/yClasses/yLeaf.d.ts +0 -7
  106. package/dist/utils/yClasses/yNode.d.ts +0 -12
  107. package/dist/yjs/index.d.ts +0 -1
  108. package/dist/yjs/wsProvider.d.ts +0 -1
  109. package/index.ts +0 -1
@@ -0,0 +1,338 @@
1
+ import { prevent, PreventionError } from '../utils.js';
2
+ import { Text } from '../text/text.svelte.js';
3
+ export async function onBeforeInput(e) {
4
+ const { start, yStart, isCollapsed, isTextSpanning, isAtStartOfBlock, isAtStartOfText, isVoid, endText, isAtEndOfText, length, isBlockSpanning, startText, isAtEndOfBlock, yEnd, islandRoot, texts } = this.selection.state;
5
+ if (this.readonly)
6
+ return;
7
+ const { inputType, dataTransfer, data } = e;
8
+ try {
9
+ // Build virtual keyboard events for plugins hotkeys to listen to before handling the input event
10
+ if (e.inputType === 'insertLineBreak' || e.inputType === 'insertParagraph') {
11
+ const customKeyDownEvent = new KeyboardEvent('keydown', {
12
+ key: 'Enter',
13
+ code: 'Enter',
14
+ shiftKey: e.inputType === 'insertLineBreak'
15
+ });
16
+ this.hotKeys.isHotkey(customKeyDownEvent);
17
+ }
18
+ if (e.inputType === 'deleteContentForward' || e.inputType === 'deleteContentBackward') {
19
+ const customKeyDownEvent = new KeyboardEvent('keydown', {
20
+ key: 'Backspace',
21
+ code: 'Backspace',
22
+ shiftKey: e.inputType === 'deleteContentBackward'
23
+ });
24
+ this.hotKeys.isHotkey(customKeyDownEvent);
25
+ }
26
+ e.preventDefault();
27
+ this.plugins.forEach((plugin) => {
28
+ plugin.onBeforeInput?.({ prevent, e });
29
+ });
30
+ const isFirstChildOfDocument = startText?.parent === this.root?.children.at(0);
31
+ const isNested = startText?.parent.parent !== this.root;
32
+ const isLastChild = startText?.parent.parent?.children.at(-1) === startText?.parent;
33
+ switch (inputType) {
34
+ case 'insertText': {
35
+ if (data === '. ') {
36
+ startText?.insertText({ value: data, isAutoDot: true });
37
+ }
38
+ else {
39
+ if (isBlockSpanning) {
40
+ const [startText, offset] = this.deleteContentWithinSelection({});
41
+ startText && (await this.selection.setAtTextOffset(startText, offset));
42
+ }
43
+ else if (isTextSpanning) {
44
+ startText?.parent.deleteContentAtRange({
45
+ start: [startText.index, yStart],
46
+ end: [endText.index, yEnd]
47
+ });
48
+ await this.selection.setAtTextOffset(startText, yStart);
49
+ }
50
+ startText?.insertText({ value: data });
51
+ // We need to immediately shift the selection to the right by the length of the inserted text
52
+ // This is to prevent selection divergence when the text is rapidly inserted
53
+ this.edytor.selection.shift(data.length);
54
+ // Then we set the caret to the right position of the inserted text
55
+ this.selection.setAtTextOffset(startText, yStart + data.length);
56
+ }
57
+ break;
58
+ }
59
+ case 'deleteContentForward': {
60
+ if (!startText) {
61
+ return;
62
+ }
63
+ if (isBlockSpanning) {
64
+ const startText = texts[0];
65
+ const offset = yStart;
66
+ this.deleteContentWithinSelection({});
67
+ this.selection.setAtTextOffset(startText, offset);
68
+ }
69
+ else {
70
+ if (isCollapsed && isAtEndOfBlock) {
71
+ // Before:
72
+ // [Block]
73
+ // [Text] "Hello|"
74
+ // [NextBlock]
75
+ // [Text] "World"
76
+ //
77
+ // After:
78
+ // [Block]
79
+ // [Text] "Hello|World"
80
+ startText.parent.mergeBlockForward();
81
+ this.edytor.selection.setAtTextOffset(startText, yStart);
82
+ }
83
+ else if (isCollapsed && isAtEndOfText) {
84
+ // Before:
85
+ // [Text] [InlineBlock] [Text]
86
+ //
87
+ // After:
88
+ // [Text]
89
+ const index = startText.parent.content.indexOf(startText) + 1;
90
+ startText.parent.removeInlineBlock({ index });
91
+ this.selection.setAtTextOffset(startText, yStart);
92
+ }
93
+ else if (isTextSpanning) {
94
+ const startText = texts[0];
95
+ const endText = texts[texts.length - 1];
96
+ if (!startText || !endText) {
97
+ return;
98
+ }
99
+ startText.parent.deleteContentAtRange({
100
+ start: [startText.index, yStart],
101
+ end: [endText.index, yEnd]
102
+ });
103
+ this.selection.setAtTextOffset(startText, yStart);
104
+ }
105
+ else {
106
+ // Before:
107
+ // [Text] "Hello| World"
108
+ //
109
+ // After:
110
+ // [Text] "Hello|World"
111
+ startText.deleteText({ direction: 'FORWARD', length: length || 1 });
112
+ this.selection.setAtTextOffset(startText, yStart);
113
+ }
114
+ }
115
+ break;
116
+ }
117
+ case 'deleteContentBackward': {
118
+ if (isCollapsed &&
119
+ isAtStartOfBlock &&
120
+ isFirstChildOfDocument &&
121
+ !startText?.parent.isEmpty) {
122
+ return;
123
+ }
124
+ if (isBlockSpanning) {
125
+ const startText = texts[0];
126
+ const offset = yStart;
127
+ this.deleteContentWithinSelection({});
128
+ this.selection.setAtTextOffset(startText, offset);
129
+ // TODO: implement this later, it's complicated i think.
130
+ }
131
+ else {
132
+ if (!startText) {
133
+ return;
134
+ }
135
+ if (isCollapsed && isAtStartOfBlock) {
136
+ // Last nested block need to be unNest
137
+ // Otherwise we just merge the block backward and eventually remove the block or unnest the children
138
+ if (isNested && isLastChild && !islandRoot) {
139
+ console.log('unNest');
140
+ // Before:
141
+ // [Block]
142
+ // [Block]
143
+ // [Text] "|Hello"
144
+ //
145
+ // After:
146
+ // [Block]
147
+ // [Block]
148
+ // [Text] "|Hello"
149
+ const newBlock = startText?.parent.unNestBlock();
150
+ newBlock && this.edytor.selection.setAtTextOffset(newBlock.firstText, 0);
151
+ }
152
+ else {
153
+ // Before:
154
+ // [Block]
155
+ // [Text] "Hello |World"
156
+ //
157
+ // After:
158
+ // [Block]
159
+ // [Text] "Hello|World"
160
+ //
161
+ // OR
162
+ //
163
+ // Before:
164
+ // [Block]
165
+ // [Text] "Hello"
166
+ // [Block]
167
+ // [Text] "|World"
168
+ //
169
+ // After:
170
+ // [Block]
171
+ // [Text] "Hello|World"
172
+ //
173
+ // OR
174
+ //
175
+ // Before:
176
+ // [Block]
177
+ // [Text] "Hello"
178
+ // [Block]
179
+ // [Text] "|World"
180
+ // [Block]
181
+ // [Text] "!"
182
+ //
183
+ // After:
184
+ // [Block]
185
+ // [Text] "Hello|World"
186
+ // [Block]
187
+ // [Text] "|!"
188
+ if (islandRoot && islandRoot.children.length === 1) {
189
+ this.edytor.selection.selectBlocks(islandRoot);
190
+ }
191
+ else {
192
+ if (islandRoot && islandRoot.children.length > 1 && startText?.parent.index === 0) {
193
+ return;
194
+ }
195
+ else {
196
+ const previousBlock = startText?.parent.closestPreviousBlock;
197
+ const previousText = previousBlock?.lastText;
198
+ const offset = previousText?.length;
199
+ startText?.parent.mergeBlockBackward();
200
+ previousText &&
201
+ this.edytor.selection.setAtTextOffset(previousBlock.lastText, offset);
202
+ }
203
+ }
204
+ }
205
+ }
206
+ else {
207
+ if (isCollapsed && isAtStartOfText) {
208
+ // Before:
209
+ // [Text] [InlineBlock] [Text]
210
+ //
211
+ // After:
212
+ // [Text]
213
+ const index = startText.parent.content.indexOf(startText) - 1;
214
+ const previousText = startText.parent.content.at(index - 1);
215
+ const hasPreviousText = previousText && previousText instanceof Text;
216
+ const offset = hasPreviousText ? previousText.yText.length : 0;
217
+ console.log({ hasPreviousText, offset, previousText });
218
+ startText.parent.removeInlineBlock({ index });
219
+ if (hasPreviousText) {
220
+ this.selection.setAtTextOffset(previousText, offset);
221
+ }
222
+ }
223
+ else if (isTextSpanning) {
224
+ const startText = texts[0];
225
+ const endText = texts[texts.length - 1];
226
+ if (!startText || !endText) {
227
+ return;
228
+ }
229
+ startText.parent.deleteContentAtRange({
230
+ start: [startText.index, yStart],
231
+ end: [endText.index, yEnd]
232
+ });
233
+ this.selection.setAtTextOffset(startText, yStart);
234
+ }
235
+ else {
236
+ startText?.deleteText({ direction: 'BACKWARD', length: length || 1 });
237
+ this.selection.setAtTextOffset(startText, isCollapsed ? yStart - 1 : yStart);
238
+ }
239
+ }
240
+ }
241
+ break;
242
+ }
243
+ case 'insertLineBreak': {
244
+ if (!startText) {
245
+ return;
246
+ }
247
+ if (isBlockSpanning) {
248
+ const [startText, offset] = this.deleteContentWithinSelection({});
249
+ startText && (await this.selection.setAtTextOffset(startText, offset));
250
+ }
251
+ else if (isTextSpanning) {
252
+ startText?.parent.deleteContentAtRange({
253
+ start: [startText.index, yStart],
254
+ end: [endText.index, yEnd]
255
+ });
256
+ await this.selection.setAtTextOffset(startText, yStart);
257
+ }
258
+ this.selection.state.startText?.insertText({ value: '\n' });
259
+ this.selection.setAtTextOffset(this.selection.state.startText, this.selection.state.yStart + 1);
260
+ break;
261
+ }
262
+ case 'insertFromPaste': {
263
+ if (!startText) {
264
+ return;
265
+ }
266
+ if (isBlockSpanning) {
267
+ const [startText, offset] = this.deleteContentWithinSelection({});
268
+ startText && (await this.selection.setAtTextOffset(startText, offset));
269
+ }
270
+ else if (isTextSpanning) {
271
+ startText?.parent.deleteContentAtRange({
272
+ start: [startText.index, yStart],
273
+ end: [endText.index, yEnd]
274
+ });
275
+ await this.selection.setAtTextOffset(startText, yStart);
276
+ }
277
+ const value = dataTransfer.getData('text/plain');
278
+ this.selection.state.startText?.insertText({ value });
279
+ this.selection.setAtTextOffset(this.selection.state.startText, this.selection.state.yStart + value.length);
280
+ break;
281
+ }
282
+ case 'insertParagraph': {
283
+ if (!startText) {
284
+ return;
285
+ }
286
+ if (isBlockSpanning) {
287
+ const [startText, offset] = this.deleteContentWithinSelection({});
288
+ startText && (await this.selection.setAtTextOffset(startText, offset));
289
+ }
290
+ else if (isTextSpanning) {
291
+ startText?.parent.deleteContentAtRange({
292
+ start: [startText.index, yStart],
293
+ end: [endText.index, yEnd]
294
+ });
295
+ await this.selection.setAtTextOffset(startText, yStart);
296
+ }
297
+ else if (!isCollapsed) {
298
+ startText.deleteText({ direction: 'FORWARD', length: yEnd - yStart });
299
+ await this.selection.setAtTextOffset(startText, yStart);
300
+ }
301
+ const defaultBlock = this.getDefaultBlock();
302
+ if (this.selection.state.isCollapsed) {
303
+ if (this.selection.state.isAtEndOfBlock) {
304
+ const newBlock = startText.parent.insertBlockAfter({
305
+ block: {
306
+ type: defaultBlock
307
+ }
308
+ });
309
+ newBlock &&
310
+ this.selection.setAtTextOffset(newBlock.firstText, newBlock?.firstText?.length);
311
+ }
312
+ else if (this.selection.state.isAtStartOfBlock) {
313
+ startText.parent?.insertBlockBefore({
314
+ block: {
315
+ type: defaultBlock
316
+ }
317
+ });
318
+ this.selection.setAtTextOffset(startText, 0);
319
+ }
320
+ else {
321
+ const newBlock = this.selection.state.startText?.parent?.splitBlock({
322
+ index: this.selection.state.yStart,
323
+ text: this.selection.state.startText
324
+ });
325
+ newBlock && this.selection.setAtTextOffset(newBlock.firstText, 0);
326
+ }
327
+ }
328
+ break;
329
+ }
330
+ }
331
+ }
332
+ catch (error) {
333
+ if (error instanceof PreventionError) {
334
+ return error.cb?.();
335
+ }
336
+ throw error;
337
+ }
338
+ }
@@ -1,69 +1,2 @@
1
- import { Editor } from "../types";
2
- export declare const onKeyDown: (editor: Editor, e: KeyboardEvent) => any;
3
- export declare const defaultHotkeys: ({
4
- operation: string;
5
- keys: string;
6
- mark: {
7
- bold: boolean;
8
- italic?: undefined;
9
- underline?: undefined;
10
- code?: undefined;
11
- strikethrough?: undefined;
12
- highlight?: undefined;
13
- };
14
- } | {
15
- operation: string;
16
- keys: string;
17
- mark: {
18
- italic: boolean;
19
- bold?: undefined;
20
- underline?: undefined;
21
- code?: undefined;
22
- strikethrough?: undefined;
23
- highlight?: undefined;
24
- };
25
- } | {
26
- operation: string;
27
- keys: string;
28
- mark: {
29
- underline: boolean;
30
- bold?: undefined;
31
- italic?: undefined;
32
- code?: undefined;
33
- strikethrough?: undefined;
34
- highlight?: undefined;
35
- };
36
- } | {
37
- operation: string;
38
- keys: string;
39
- mark: {
40
- code: boolean;
41
- bold?: undefined;
42
- italic?: undefined;
43
- underline?: undefined;
44
- strikethrough?: undefined;
45
- highlight?: undefined;
46
- };
47
- } | {
48
- operation: string;
49
- keys: string;
50
- mark: {
51
- strikethrough: boolean;
52
- bold?: undefined;
53
- italic?: undefined;
54
- underline?: undefined;
55
- code?: undefined;
56
- highlight?: undefined;
57
- };
58
- } | {
59
- operation: string;
60
- keys: string;
61
- mark: {
62
- highlight: boolean;
63
- bold?: undefined;
64
- italic?: undefined;
65
- underline?: undefined;
66
- code?: undefined;
67
- strikethrough?: undefined;
68
- };
69
- })[];
1
+ import type { Edytor } from '../edytor.svelte.js';
2
+ export declare function onKeyDown(this: Edytor, e: KeyboardEvent): void;
@@ -0,0 +1,18 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { Block } from '../block/block.svelte.js';
3
+ import { prevent, PreventionError } from '../utils.js';
4
+ export function onKeyDown(e) {
5
+ if (this.readonly)
6
+ return;
7
+ try {
8
+ this.hotKeys.isHotkey(e);
9
+ }
10
+ catch (error) {
11
+ if (error instanceof PreventionError) {
12
+ error.cb?.();
13
+ }
14
+ else {
15
+ throw error;
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,27 @@
1
+ import type { Edytor, EdytorOptions } from './edytor.svelte.js';
2
+ import type { InitializedPlugin } from './plugins.js';
3
+ export type HotKey = (payload: {
4
+ event: KeyboardEvent;
5
+ edytor: Edytor;
6
+ prevent: (cb?: () => void) => void;
7
+ }) => void;
8
+ export type HotKeyModifier = 'mod' | 'alt' | 'ctrl' | 'shift';
9
+ declare const letter: Set<"t" | "b" | "i" | "a" | "c" | "d" | "e" | "f" | "g" | "h" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "u" | "v" | "w" | "x" | "y" | "z">;
10
+ type Letter = typeof letter extends Set<infer T> ? T : never;
11
+ type Key = Letter | 'tab' | 'enter' | 'backspace' | 'space' | 'escape' | 'arrowup' | 'arrowdown' | 'arrowleft' | 'arrowright';
12
+ export type SingleModifierCombination = `${HotKeyModifier}+${Key}`;
13
+ export type DoubleModifierCombination = `mod+alt+${Key}` | `mod+ctrl+${Key}` | `mod+shift+${Key}` | `alt+ctrl+${Key}` | `alt+shift+${Key}` | `ctrl+shift+${Key}`;
14
+ export type HotKeyCombination = Key | SingleModifierCombination | DoubleModifierCombination;
15
+ export declare class HotKeys {
16
+ private edytor;
17
+ private userHotKeys;
18
+ private plugins;
19
+ private hotkeys;
20
+ get isMac(): boolean;
21
+ constructor(edytor: Edytor, userHotKeys?: EdytorOptions['hotKeys'], plugins?: InitializedPlugin[]);
22
+ init: () => void;
23
+ private normalizeKey;
24
+ private combination;
25
+ isHotkey: (e: KeyboardEvent) => boolean;
26
+ }
27
+ export {};