edytor 0.0.7 → 0.0.8
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 +225 -5
- package/dist/block/block.svelte.d.ts +123 -0
- package/dist/block/block.svelte.js +430 -0
- package/dist/block/block.utils.d.ts +82 -0
- package/dist/block/block.utils.js +499 -0
- package/dist/block/content.svelte.d.ts +14 -0
- package/dist/block/content.svelte.js +40 -0
- package/dist/block/inlineBlock.svelte.d.ts +30 -0
- package/dist/block/inlineBlock.svelte.js +53 -0
- package/dist/components/Block.svelte +27 -0
- package/dist/components/Block.svelte.d.ts +7 -0
- package/dist/components/Content.svelte +44 -0
- package/dist/components/Content.svelte.d.ts +7 -0
- package/dist/components/Edytor.svelte +165 -0
- package/dist/components/Edytor.svelte.d.ts +33 -0
- package/dist/components/InlineBlock.svelte +17 -0
- package/dist/components/InlineBlock.svelte.d.ts +7 -0
- package/dist/components/Mark.svelte +38 -0
- package/dist/components/Mark.svelte.d.ts +11 -0
- package/dist/components/ReadonlyEditor.svelte +46 -0
- package/dist/components/ReadonlyEditor.svelte.d.ts +4 -0
- package/dist/components/Text.svelte +37 -0
- package/dist/components/Text.svelte.d.ts +7 -0
- package/dist/components/readonlyElements.svelte.d.ts +82 -0
- package/dist/components/readonlyElements.svelte.js +144 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +4 -0
- package/dist/dnd.svelte.d.ts +17 -0
- package/dist/dnd.svelte.js +125 -0
- package/dist/edytor.svelte.d.ts +94 -0
- package/dist/edytor.svelte.js +262 -0
- package/dist/edytor.utils.d.ts +3 -0
- package/dist/edytor.utils.js +78 -0
- package/dist/events/onBeforeInput.d.ts +2 -2
- package/dist/events/onBeforeInput.js +338 -0
- package/dist/events/onKeyDown.d.ts +2 -69
- package/dist/events/onKeyDown.js +18 -0
- package/dist/hotkeys.d.ts +27 -0
- package/dist/hotkeys.js +282 -0
- package/dist/index.d.ts +1 -5
- package/dist/index.js +2 -8
- package/dist/localProvider.d.ts +82 -0
- package/dist/localProvider.js +267 -0
- package/dist/plugins/arrowMove/arrowMove.d.ts +2 -0
- package/dist/plugins/arrowMove/arrowMove.js +66 -0
- package/dist/plugins/code/CodePlugin.svelte +218 -0
- package/dist/plugins/code/CodePlugin.svelte.d.ts +23 -0
- package/dist/plugins/code/prism.css +141 -0
- package/dist/plugins/image/ImagePlugin.svelte +22 -0
- package/dist/plugins/image/ImagePlugin.svelte.d.ts +20 -0
- package/dist/plugins/mention/MentionPlugin.svelte +40 -0
- package/dist/plugins/mention/MentionPlugin.svelte.d.ts +20 -0
- package/dist/plugins/richtext/RichTextPlugin.svelte +241 -0
- package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +26 -0
- package/dist/plugins.d.ts +202 -0
- package/dist/plugins.js +19 -0
- package/dist/selection/selection.svelte.d.ts +68 -0
- package/dist/selection/selection.svelte.js +391 -0
- package/dist/selection/selection.utils.d.ts +14 -0
- package/dist/selection/selection.utils.js +153 -0
- package/dist/text/deltas.d.ts +11 -0
- package/dist/text/deltas.js +109 -0
- package/dist/text/text.svelte.d.ts +70 -0
- package/dist/text/text.svelte.js +119 -0
- package/dist/text/text.utils.d.ts +40 -0
- package/dist/text/text.utils.js +174 -0
- package/dist/utils/json.d.ts +32 -0
- package/dist/utils/json.js +2 -0
- package/dist/utils/jsx.d.ts +25 -0
- package/dist/utils/jsx.js +66 -0
- package/dist/utils/serialize.d.ts +1 -0
- package/dist/utils/serialize.js +1 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +19 -0
- package/package.json +81 -33
- package/dist/edytor.cjs.development.js +0 -1762
- package/dist/edytor.cjs.development.js.map +0 -1
- package/dist/edytor.cjs.production.min.js +0 -2
- package/dist/edytor.cjs.production.min.js.map +0 -1
- package/dist/edytor.esm.js +0 -1691
- package/dist/edytor.esm.js.map +0 -1
- package/dist/events/index.d.ts +0 -3
- package/dist/events/onDrop.d.ts +0 -3
- package/dist/operations/deleteText.d.ts +0 -7
- package/dist/operations/formatText.d.ts +0 -20
- package/dist/operations/index.d.ts +0 -9
- package/dist/operations/insertText.d.ts +0 -5
- package/dist/operations/merge.d.ts +0 -3
- package/dist/operations/moveNode.d.ts +0 -12
- package/dist/operations/nestNode.d.ts +0 -2
- package/dist/operations/removeEmptyText.d.ts +0 -2
- package/dist/operations/splitLeaf.d.ts +0 -2
- package/dist/operations/splitNode.d.ts +0 -9
- package/dist/types.d.ts +0 -140
- package/dist/utils/common.d.ts +0 -17
- package/dist/utils/dropper.d.ts +0 -26
- package/dist/utils/index.d.ts +0 -6
- package/dist/utils/leaves.d.ts +0 -34
- package/dist/utils/nodes.d.ts +0 -14
- package/dist/utils/selection.d.ts +0 -51
- package/dist/utils/yClasses/EdytorDoc.d.ts +0 -16
- package/dist/utils/yClasses/index.d.ts +0 -3
- package/dist/utils/yClasses/yLeaf.d.ts +0 -7
- package/dist/utils/yClasses/yNode.d.ts +0 -12
- package/dist/yjs/index.d.ts +0 -1
- package/dist/yjs/wsProvider.d.ts +0 -1
- package/index.ts +0 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { Plugin, MarkSnippetPayload, BlockSnippetPayload } from '../../plugins.js';
|
|
3
|
+
import type { SerializableContent } from '../../utils/json.js';
|
|
4
|
+
import type { HotKey } from '../../hotkeys.js';
|
|
5
|
+
import type { Edytor } from '../../edytor.svelte.js';
|
|
6
|
+
|
|
7
|
+
export const richTextOperations = (edytor: Edytor) => ({
|
|
8
|
+
removeAllMarksAtRange: () => {
|
|
9
|
+
const { yStart, yEnd, startText, texts } = edytor.selection.state;
|
|
10
|
+
texts.forEach((text) => {
|
|
11
|
+
const marks = text.yText.getAttributes();
|
|
12
|
+
Object.entries(marks).forEach(([key]) => {
|
|
13
|
+
text.yText.removeAttribute(key);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
edytor.selection.setAtTextRange(startText, yStart, yEnd);
|
|
17
|
+
},
|
|
18
|
+
setMarkAtRange: (
|
|
19
|
+
mark:
|
|
20
|
+
| 'bold'
|
|
21
|
+
| 'italic'
|
|
22
|
+
| 'underline'
|
|
23
|
+
| 'code'
|
|
24
|
+
| 'link'
|
|
25
|
+
| 'strike'
|
|
26
|
+
| 'superscript'
|
|
27
|
+
| 'subscript'
|
|
28
|
+
| 'color'
|
|
29
|
+
| 'highlight',
|
|
30
|
+
value?: SerializableContent
|
|
31
|
+
) => {
|
|
32
|
+
const { yStart, yEnd, startText, texts } = edytor.selection.state;
|
|
33
|
+
console.table(texts.map((text) => ({ text: text.yText.toJSON() })));
|
|
34
|
+
texts.forEach((text, index) => {
|
|
35
|
+
const isFirst = index === 0;
|
|
36
|
+
const isLast = index === texts.length - 1;
|
|
37
|
+
text.markText({
|
|
38
|
+
mark,
|
|
39
|
+
value,
|
|
40
|
+
toggle: true,
|
|
41
|
+
start: isFirst ? yStart : 0,
|
|
42
|
+
end: isLast ? yEnd : text.yText.length
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
edytor.selection.setAtTextRange(startText, yStart, yEnd);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export const richTextPlugin: Plugin = (edytor) => {
|
|
50
|
+
const setMarkAndSelect =
|
|
51
|
+
(
|
|
52
|
+
mark:
|
|
53
|
+
| 'bold'
|
|
54
|
+
| 'italic'
|
|
55
|
+
| 'underline'
|
|
56
|
+
| 'code'
|
|
57
|
+
| 'link'
|
|
58
|
+
| 'strike'
|
|
59
|
+
| 'superscript'
|
|
60
|
+
| 'subscript'
|
|
61
|
+
| 'color'
|
|
62
|
+
| 'highlight',
|
|
63
|
+
value?: SerializableContent
|
|
64
|
+
): HotKey =>
|
|
65
|
+
({ prevent }) => {
|
|
66
|
+
prevent(() => {
|
|
67
|
+
richTextOperations(edytor).setMarkAtRange(mark, value);
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
defaultBlock: (parent) => {
|
|
72
|
+
if (parent.type === 'ordered-list') {
|
|
73
|
+
return 'list-item';
|
|
74
|
+
}
|
|
75
|
+
if (parent.type === 'unordered-list') {
|
|
76
|
+
return 'list-item';
|
|
77
|
+
}
|
|
78
|
+
return 'paragraph';
|
|
79
|
+
},
|
|
80
|
+
hotkeys: {
|
|
81
|
+
'mod+b': setMarkAndSelect('bold'),
|
|
82
|
+
'mod+i': setMarkAndSelect('italic'),
|
|
83
|
+
'mod+u': setMarkAndSelect('underline'),
|
|
84
|
+
'mod+e': setMarkAndSelect('code'),
|
|
85
|
+
'mod+shift+x': setMarkAndSelect('strike'),
|
|
86
|
+
'mod+shift+h': setMarkAndSelect('color', 'red')
|
|
87
|
+
},
|
|
88
|
+
marks: {
|
|
89
|
+
bold,
|
|
90
|
+
italic,
|
|
91
|
+
underline,
|
|
92
|
+
code,
|
|
93
|
+
link,
|
|
94
|
+
strike,
|
|
95
|
+
superscript,
|
|
96
|
+
subscript,
|
|
97
|
+
color,
|
|
98
|
+
highlight
|
|
99
|
+
},
|
|
100
|
+
blocks: {
|
|
101
|
+
paragraph,
|
|
102
|
+
details,
|
|
103
|
+
heading,
|
|
104
|
+
'ordered-list': orderedList,
|
|
105
|
+
'unordered-list': unorderedList,
|
|
106
|
+
'list-item': listItem,
|
|
107
|
+
horizontalRule
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
{#snippet bold({ content }: MarkSnippetPayload)}
|
|
114
|
+
<b>
|
|
115
|
+
{@render content()}
|
|
116
|
+
</b>
|
|
117
|
+
{/snippet}
|
|
118
|
+
|
|
119
|
+
{#snippet italic({ content }: MarkSnippetPayload)}
|
|
120
|
+
<i>
|
|
121
|
+
{@render content()}
|
|
122
|
+
</i>
|
|
123
|
+
{/snippet}
|
|
124
|
+
|
|
125
|
+
{#snippet underline({ content }: MarkSnippetPayload)}
|
|
126
|
+
<u>
|
|
127
|
+
{@render content()}
|
|
128
|
+
</u>
|
|
129
|
+
{/snippet}
|
|
130
|
+
|
|
131
|
+
{#snippet code({ content }: MarkSnippetPayload)}
|
|
132
|
+
<code>
|
|
133
|
+
{@render content()}
|
|
134
|
+
</code>
|
|
135
|
+
{/snippet}
|
|
136
|
+
|
|
137
|
+
{#snippet link({ mark, content }: MarkSnippetPayload<{ href: string; target?: string }>)}
|
|
138
|
+
<a href={mark.href} target={mark.target}>
|
|
139
|
+
{@render content()}
|
|
140
|
+
</a>
|
|
141
|
+
{/snippet}
|
|
142
|
+
|
|
143
|
+
{#snippet strike({ content }: MarkSnippetPayload)}
|
|
144
|
+
<s>
|
|
145
|
+
{@render content()}
|
|
146
|
+
</s>
|
|
147
|
+
{/snippet}
|
|
148
|
+
|
|
149
|
+
{#snippet superscript({ content }: MarkSnippetPayload)}
|
|
150
|
+
<sup>
|
|
151
|
+
{@render content()}
|
|
152
|
+
</sup>
|
|
153
|
+
{/snippet}
|
|
154
|
+
|
|
155
|
+
{#snippet subscript({ content }: MarkSnippetPayload)}
|
|
156
|
+
<sub>
|
|
157
|
+
{@render content()}
|
|
158
|
+
</sub>
|
|
159
|
+
{/snippet}
|
|
160
|
+
|
|
161
|
+
{#snippet color({ mark, content }: MarkSnippetPayload<{ color: string }>)}
|
|
162
|
+
<span style="color: {mark}">
|
|
163
|
+
{@render content()}
|
|
164
|
+
</span>
|
|
165
|
+
{/snippet}
|
|
166
|
+
|
|
167
|
+
{#snippet highlight({ mark, content }: MarkSnippetPayload<string>)}
|
|
168
|
+
<span style="background-color: {mark}">
|
|
169
|
+
{@render content()}
|
|
170
|
+
</span>
|
|
171
|
+
{/snippet}
|
|
172
|
+
|
|
173
|
+
{#snippet paragraph({ block, content, children }: BlockSnippetPayload)}
|
|
174
|
+
<div class="rounded bg-opacity-25 p-1 my-1" use:block.attach>
|
|
175
|
+
<p>
|
|
176
|
+
{@render content()}
|
|
177
|
+
</p>
|
|
178
|
+
{#if children}
|
|
179
|
+
<div style:padding-left="10px">
|
|
180
|
+
{@render children()}
|
|
181
|
+
</div>
|
|
182
|
+
{/if}
|
|
183
|
+
</div>
|
|
184
|
+
{/snippet}
|
|
185
|
+
{#snippet details({ block, content, children }: BlockSnippetPayload)}
|
|
186
|
+
<details use:block.attach>
|
|
187
|
+
<summary>
|
|
188
|
+
{@render content()}
|
|
189
|
+
</summary>
|
|
190
|
+
{#if children}
|
|
191
|
+
<div>
|
|
192
|
+
{@render children()}
|
|
193
|
+
</div>
|
|
194
|
+
{/if}
|
|
195
|
+
</details>
|
|
196
|
+
{/snippet}
|
|
197
|
+
{#snippet heading({ block, content, children }: BlockSnippetPayload<{ level: number }>)}
|
|
198
|
+
<svelte:element this={block.level || 'h1'} use:block.attach>
|
|
199
|
+
{@render content()}
|
|
200
|
+
{#if children}
|
|
201
|
+
<div>
|
|
202
|
+
{@render children()}
|
|
203
|
+
</div>
|
|
204
|
+
{/if}
|
|
205
|
+
</svelte:element>
|
|
206
|
+
{/snippet}
|
|
207
|
+
|
|
208
|
+
{#snippet orderedList({ block, content, children }: BlockSnippetPayload)}
|
|
209
|
+
<ol use:block.attach>
|
|
210
|
+
{#if children}
|
|
211
|
+
<div>
|
|
212
|
+
{@render children()}
|
|
213
|
+
</div>
|
|
214
|
+
{/if}
|
|
215
|
+
</ol>
|
|
216
|
+
{/snippet}
|
|
217
|
+
|
|
218
|
+
{#snippet unorderedList({ block, content, children }: BlockSnippetPayload)}
|
|
219
|
+
<ul use:block.attach>
|
|
220
|
+
{#if children}
|
|
221
|
+
<div>
|
|
222
|
+
{@render children()}
|
|
223
|
+
</div>
|
|
224
|
+
{/if}
|
|
225
|
+
</ul>
|
|
226
|
+
{/snippet}
|
|
227
|
+
|
|
228
|
+
{#snippet listItem({ block, content, children }: BlockSnippetPayload)}
|
|
229
|
+
<li use:block.attach>
|
|
230
|
+
<div>{@render content()}</div>
|
|
231
|
+
{#if children}
|
|
232
|
+
<div>
|
|
233
|
+
{@render children()}
|
|
234
|
+
</div>
|
|
235
|
+
{/if}
|
|
236
|
+
</li>
|
|
237
|
+
{/snippet}
|
|
238
|
+
|
|
239
|
+
{#snippet horizontalRule({ block }: BlockSnippetPayload)}
|
|
240
|
+
<hr use:block.attach use:block.void />
|
|
241
|
+
{/snippet}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Plugin } from '../../plugins.js';
|
|
2
|
+
import type { SerializableContent } from '../../utils/json.js';
|
|
3
|
+
import type { Edytor } from '../../edytor.svelte.js';
|
|
4
|
+
export declare const richTextOperations: (edytor: Edytor) => {
|
|
5
|
+
removeAllMarksAtRange: () => void;
|
|
6
|
+
setMarkAtRange: (mark: "bold" | "italic" | "underline" | "code" | "link" | "strike" | "superscript" | "subscript" | "color" | "highlight", value?: SerializableContent) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare const richTextPlugin: Plugin;
|
|
9
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
10
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
11
|
+
$$bindings?: Bindings;
|
|
12
|
+
} & Exports;
|
|
13
|
+
(internal: unknown, props: {
|
|
14
|
+
$$events?: Events;
|
|
15
|
+
$$slots?: Slots;
|
|
16
|
+
}): Exports & {
|
|
17
|
+
$set?: any;
|
|
18
|
+
$on?: any;
|
|
19
|
+
};
|
|
20
|
+
z_$$bindings?: Bindings;
|
|
21
|
+
}
|
|
22
|
+
declare const RichTextPlugin: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
23
|
+
[evt: string]: CustomEvent<any>;
|
|
24
|
+
}, {}, {}, string>;
|
|
25
|
+
type RichTextPlugin = InstanceType<typeof RichTextPlugin>;
|
|
26
|
+
export default RichTextPlugin;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { Edytor } from './edytor.svelte.js';
|
|
3
|
+
import type { Block } from './block/block.svelte.js';
|
|
4
|
+
import type { JSONBlock, JSONText } from './utils/json.js';
|
|
5
|
+
import type { Text } from './text/text.svelte.js';
|
|
6
|
+
import type { SerializableContent } from './utils/json.js';
|
|
7
|
+
import type { HotKey, HotKeyCombination } from './hotkeys.js';
|
|
8
|
+
import type { TextOperations } from './text/text.utils.js';
|
|
9
|
+
import type { BlockOperations } from './block/block.utils.js';
|
|
10
|
+
import type { EdytorSelection } from './selection/selection.svelte.js';
|
|
11
|
+
import type { InlineBlock } from './block/inlineBlock.svelte.js';
|
|
12
|
+
/**
|
|
13
|
+
* Represents the payload for mark snippets with generic serializable content.
|
|
14
|
+
* @template D - The type of serializable content
|
|
15
|
+
*/
|
|
16
|
+
export type MarkSnippetPayload<D extends SerializableContent = SerializableContent> = {
|
|
17
|
+
content: Snippet;
|
|
18
|
+
mark: D;
|
|
19
|
+
text: Text;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Function type for preventing default behavior with an optional callback.
|
|
23
|
+
*/
|
|
24
|
+
type Prevent = (cb?: () => void) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Represents the payload for block snippets with generic serializable content.
|
|
27
|
+
* @template D - The type of serializable content
|
|
28
|
+
*/
|
|
29
|
+
export type BlockSnippetPayload<D extends SerializableContent = SerializableContent> = {
|
|
30
|
+
block: Block;
|
|
31
|
+
content: Snippet;
|
|
32
|
+
children: Snippet | null;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Represents the payload for change operations on blocks and text.
|
|
36
|
+
* Combines both text operations and block operations with prevention capability.
|
|
37
|
+
*/
|
|
38
|
+
type ChangePayload = {
|
|
39
|
+
block: Block;
|
|
40
|
+
prevent: Prevent;
|
|
41
|
+
} & ({
|
|
42
|
+
[K in keyof TextOperations]: {
|
|
43
|
+
operation: K;
|
|
44
|
+
text: Text;
|
|
45
|
+
payload: TextOperations[K];
|
|
46
|
+
};
|
|
47
|
+
}[keyof TextOperations] | {
|
|
48
|
+
[K in keyof BlockOperations]: {
|
|
49
|
+
operation: K;
|
|
50
|
+
payload: BlockOperations[K];
|
|
51
|
+
};
|
|
52
|
+
}[keyof BlockOperations]);
|
|
53
|
+
/**
|
|
54
|
+
* Function type for transforming content within a text block.
|
|
55
|
+
*/
|
|
56
|
+
export type ContentTransformer = (payload: {
|
|
57
|
+
text: Text;
|
|
58
|
+
block: Block;
|
|
59
|
+
content: JSONText[];
|
|
60
|
+
}) => JSONText[];
|
|
61
|
+
/**
|
|
62
|
+
* Defines the structure of plugin definitions including marks, blocks, inline blocks, and hotkeys.
|
|
63
|
+
*/
|
|
64
|
+
export type PluginDefinitions = {
|
|
65
|
+
marks?: Record<string, MarkDefinition | Snippet<[MarkSnippetPayload<any>]>>;
|
|
66
|
+
blocks?: Record<string, BlockDefinition | Snippet<[BlockSnippetPayload<any>]>>;
|
|
67
|
+
inlineBlocks?: Record<string, InlineBlockDefinition | Snippet<[InlineBlockSnippetPayload<any>]>>;
|
|
68
|
+
hotkeys?: Partial<Record<HotKeyCombination, HotKey>>;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Plugin factory function type that creates plugin definitions and operations.
|
|
72
|
+
*/
|
|
73
|
+
export type Plugin = (editor: Edytor) => PluginDefinitions & PluginOperations;
|
|
74
|
+
/**
|
|
75
|
+
* Defines the available operations and hooks for plugins.
|
|
76
|
+
*/
|
|
77
|
+
export type PluginOperations = {
|
|
78
|
+
/** Called before an operation is executed */
|
|
79
|
+
onBeforeOperation?: <C extends ChangePayload>(payload: C) => C['payload'] | void;
|
|
80
|
+
/** Called after an operation is executed */
|
|
81
|
+
onAfterOperation?: <C extends Omit<ChangePayload, 'prevent'>>(payload: C) => void;
|
|
82
|
+
/** Called when the editor value changes */
|
|
83
|
+
onChange?: (value: JSONBlock) => void;
|
|
84
|
+
/** Called when the selection changes */
|
|
85
|
+
onSelectionChange?: (selection: EdytorSelection) => void;
|
|
86
|
+
/** Placeholder content for empty blocks */
|
|
87
|
+
placeholder?: string | Snippet<[{
|
|
88
|
+
block: Block;
|
|
89
|
+
}]>;
|
|
90
|
+
/** Called when the editor is attached to the DOM */
|
|
91
|
+
onEdytorAttached?: (payload: {
|
|
92
|
+
node: HTMLElement;
|
|
93
|
+
}) => () => void;
|
|
94
|
+
/** Called when a block is attached to the DOM */
|
|
95
|
+
onBlockAttached?: (payload: {
|
|
96
|
+
node: HTMLElement;
|
|
97
|
+
block: Block;
|
|
98
|
+
}) => () => void;
|
|
99
|
+
/** Called when text is attached to the DOM */
|
|
100
|
+
onTextAttached?: (payload: {
|
|
101
|
+
node: HTMLElement;
|
|
102
|
+
text: Text;
|
|
103
|
+
}) => () => void;
|
|
104
|
+
/** Defines the default block type */
|
|
105
|
+
defaultBlock?: string | ((parent: Block) => string | void);
|
|
106
|
+
/** Called when selected blocks are deleted */
|
|
107
|
+
onDeleteSelectedBlocks?: (payload: {
|
|
108
|
+
prevent: Prevent;
|
|
109
|
+
selectedBlocks: Block[];
|
|
110
|
+
}) => void;
|
|
111
|
+
/** Called before input is processed */
|
|
112
|
+
onBeforeInput?: (payload: {
|
|
113
|
+
prevent: Prevent;
|
|
114
|
+
e: InputEvent;
|
|
115
|
+
}) => void;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Defines the structure and behavior of a block type.
|
|
119
|
+
*/
|
|
120
|
+
export type BlockDefinition = {
|
|
121
|
+
/** The block's rendering snippet */
|
|
122
|
+
snippet: Snippet<[BlockSnippetPayload<any>]>;
|
|
123
|
+
/** Whether the block is void (not editable)
|
|
124
|
+
*
|
|
125
|
+
* Void blocks are blocks that are not editable by the edytor.
|
|
126
|
+
* They can be nested inside other blocks
|
|
127
|
+
* They can not be merged with other blocks
|
|
128
|
+
* If the content of the void block is rendered, it will still be editable. This to allow for rendering caption of the void block. I
|
|
129
|
+
* In void blocks the content is treated as an island
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
132
|
+
void?: boolean;
|
|
133
|
+
/** Whether the block is an island.
|
|
134
|
+
*
|
|
135
|
+
* Island blocks are blocks that are independent of the document.
|
|
136
|
+
*
|
|
137
|
+
* They are editable
|
|
138
|
+
*
|
|
139
|
+
* They can be nested inside other blocks
|
|
140
|
+
*
|
|
141
|
+
* But their children can not be nested or merged with other blocks
|
|
142
|
+
*
|
|
143
|
+
* Their structure will remain as if.
|
|
144
|
+
*
|
|
145
|
+
* In case of a merge operation, the island block will be merged with the parent block and all its children will ne unnest and set to the default block type without being added as children of the merge destination block. The same wil happen to the island's content.
|
|
146
|
+
*/
|
|
147
|
+
island?: boolean;
|
|
148
|
+
/** Transform text content within the block
|
|
149
|
+
*
|
|
150
|
+
* This transformation is applied after the text is synced in to the state.
|
|
151
|
+
*
|
|
152
|
+
* You can use it to render custom marks decorations on the text like code tokens that are not stored in the document.
|
|
153
|
+
*/
|
|
154
|
+
transformText?: (payload: {
|
|
155
|
+
text: Text;
|
|
156
|
+
block: Block;
|
|
157
|
+
content: JSONText[];
|
|
158
|
+
}) => JSONText[];
|
|
159
|
+
/** Called when the block receives focus */
|
|
160
|
+
onFocus?: (payload: {
|
|
161
|
+
block: Block;
|
|
162
|
+
}) => void;
|
|
163
|
+
/** Called when the block loses focus */
|
|
164
|
+
onBlur?: (payload: {
|
|
165
|
+
block: Block;
|
|
166
|
+
}) => void;
|
|
167
|
+
/** Called when the block is selected */
|
|
168
|
+
onSelect?: (payload: {
|
|
169
|
+
block: Block;
|
|
170
|
+
}) => void;
|
|
171
|
+
/** Called when the block is deselected */
|
|
172
|
+
onDeselect?: (payload: {
|
|
173
|
+
block: Block;
|
|
174
|
+
}) => void;
|
|
175
|
+
/** Normalize block content
|
|
176
|
+
* This is called after each operation on the block.
|
|
177
|
+
* You may want to work with the yjs types directly because the operation has not been synced in to the state yet.
|
|
178
|
+
* If you return a function, it will be executed otherwise it will be ignored.
|
|
179
|
+
*/
|
|
180
|
+
normalizeContent?: (payload: {
|
|
181
|
+
block: Block;
|
|
182
|
+
}) => (() => void) | void;
|
|
183
|
+
/** Schema for synchronization state data. It uses syncroState
|
|
184
|
+
*
|
|
185
|
+
* See https://github.com/beynar/syncrostate
|
|
186
|
+
*
|
|
187
|
+
*/
|
|
188
|
+
schema?: any;
|
|
189
|
+
};
|
|
190
|
+
export type InlineBlockSnippetPayload<D extends SerializableContent = SerializableContent> = {
|
|
191
|
+
block: InlineBlock;
|
|
192
|
+
};
|
|
193
|
+
export type InlineBlockDefinition = {
|
|
194
|
+
snippet: Snippet<[InlineBlockSnippetPayload<any>]>;
|
|
195
|
+
};
|
|
196
|
+
export type MarkDefinition = {
|
|
197
|
+
snippet: Snippet<[MarkSnippetPayload<any>]>;
|
|
198
|
+
void?: boolean;
|
|
199
|
+
schema?: any;
|
|
200
|
+
};
|
|
201
|
+
export type InitializedPlugin = ReturnType<Plugin>;
|
|
202
|
+
export {};
|
package/dist/plugins.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
// TODO: add arrow events
|
|
3
|
+
// TODO: add onBeforeInput event
|
|
4
|
+
// TODO: add block focus and selection events
|
|
5
|
+
// TODO: add a cmd+a selection all event
|
|
6
|
+
//
|
|
7
|
+
// ISLAND BLOCKS
|
|
8
|
+
// Island blocks are blocks that are independent of the document.
|
|
9
|
+
// They are editable
|
|
10
|
+
// They can be nested inside other blocks
|
|
11
|
+
// But their children can not be nested or merged with other blocks
|
|
12
|
+
// Their structure will remain as if or will not.
|
|
13
|
+
// In case of a merge operation, the island block will be merged with the parent block and all its children will ne unnest and set to the default block type without being added as children of the merge destination block. The same wil happen to the island's content.
|
|
14
|
+
// VOID BLOCKS
|
|
15
|
+
// Void blocks are blocks that are not editable
|
|
16
|
+
// They can be nested inside other blocks
|
|
17
|
+
// They can not accept children nor be merged with other blocks
|
|
18
|
+
// If the content of the void block is rendered, it will still be editable. This to allow for rendering caption of the void block. I
|
|
19
|
+
// In void blocks the content is treated as an island
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { type RelativePosition } from 'yjs';
|
|
2
|
+
import type { Edytor } from '../edytor.svelte.js';
|
|
3
|
+
import { Text } from '../text/text.svelte.js';
|
|
4
|
+
import { Block } from '../block/block.svelte.js';
|
|
5
|
+
import { SvelteSet } from 'svelte/reactivity';
|
|
6
|
+
import { InlineBlock } from '../block/inlineBlock.svelte.js';
|
|
7
|
+
type SelectionState = {
|
|
8
|
+
selection: Selection | null;
|
|
9
|
+
yStart: number;
|
|
10
|
+
yEnd: number;
|
|
11
|
+
start: number;
|
|
12
|
+
end: number;
|
|
13
|
+
length: number;
|
|
14
|
+
content: string;
|
|
15
|
+
isCollapsed: boolean;
|
|
16
|
+
ranges: Range[];
|
|
17
|
+
isAtStartOfBlock?: boolean;
|
|
18
|
+
isAtEndOfBlock?: boolean;
|
|
19
|
+
isAtStartOfText?: boolean;
|
|
20
|
+
isAtEndOfText?: boolean;
|
|
21
|
+
startText: Text | null;
|
|
22
|
+
endText: Text | null;
|
|
23
|
+
startBlock: Block | null;
|
|
24
|
+
endBlock: Block | null;
|
|
25
|
+
texts: Text[];
|
|
26
|
+
contentParts: (Text | InlineBlock)[];
|
|
27
|
+
blocks: Block[];
|
|
28
|
+
startNode: Node | null;
|
|
29
|
+
endNode: Node | null;
|
|
30
|
+
isTextSpanning: boolean;
|
|
31
|
+
isBlockSpanning: boolean;
|
|
32
|
+
isVoid: boolean;
|
|
33
|
+
voidRoot: Block | null;
|
|
34
|
+
isIsland: boolean;
|
|
35
|
+
islandRoot: Block | null;
|
|
36
|
+
relativePosition: RelativePosition | null;
|
|
37
|
+
yTextContent: string;
|
|
38
|
+
};
|
|
39
|
+
export declare class EdytorSelection {
|
|
40
|
+
private edytorOnSelectionChange?;
|
|
41
|
+
edytor: Edytor;
|
|
42
|
+
focusedBlocks: SvelteSet<Block>;
|
|
43
|
+
selectedBlocks: SvelteSet<Block>;
|
|
44
|
+
hasSelectedAll: boolean;
|
|
45
|
+
state: SelectionState;
|
|
46
|
+
constructor(edytor: Edytor, edytorOnSelectionChange?: ((selection: EdytorSelection) => void) | undefined);
|
|
47
|
+
destroy: () => void;
|
|
48
|
+
getTextOfNode: (node: Node | null) => Text | null;
|
|
49
|
+
getTextsInSelection: (startNode: Node | null, endNode: Node | null, ranges: Range[]) => {
|
|
50
|
+
startText: Text | null;
|
|
51
|
+
endText: Text | null;
|
|
52
|
+
texts: Text[];
|
|
53
|
+
};
|
|
54
|
+
init: () => void;
|
|
55
|
+
handleTripleClick: (e: MouseEvent) => Promise<void>;
|
|
56
|
+
shift: (length: number) => Promise<void>;
|
|
57
|
+
onSelectionChange: () => Promise<void> | undefined;
|
|
58
|
+
restoreRelativePosition: (text: Text) => void;
|
|
59
|
+
selectBlocks: (...blocks: Block[]) => void;
|
|
60
|
+
focusBlocks: (...blocks: Block[]) => void;
|
|
61
|
+
private findTextNode;
|
|
62
|
+
setAtTextOffset: (textOrId: Text | string | undefined | null, textOffset?: number | null | undefined) => Promise<void>;
|
|
63
|
+
setAtTextsRange: (startText: Text, endText: Text) => Promise<void>;
|
|
64
|
+
setAtBlockRange: (block?: Block | null, startOffset?: number, endOffset?: number) => Promise<void>;
|
|
65
|
+
setAtTextRange: (text: Text | undefined | null, start: number | undefined | null, end: number | undefined | null) => Promise<void>;
|
|
66
|
+
setAtNodeOffset: (node: Node, offset: number) => void;
|
|
67
|
+
}
|
|
68
|
+
export {};
|