@blocknote/core 0.2.2 → 0.2.4-alpha.7
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/dist/blocknote.js +1061 -936
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +1 -1
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +22 -29
- package/src/BlockNoteExtensions.ts +11 -10
- package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +61 -0
- package/src/extensions/BackgroundColor/BackgroundColorMark.ts +62 -0
- package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +112 -106
- package/src/extensions/Blocks/apiTypes.ts +48 -0
- package/src/extensions/Blocks/helpers/findBlock.ts +3 -1
- package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +1 -1
- package/src/extensions/Blocks/index.ts +10 -8
- package/src/extensions/Blocks/nodes/Block.module.css +122 -35
- package/src/extensions/Blocks/{BlockAttributes.ts → nodes/BlockAttributes.ts} +0 -0
- package/src/extensions/Blocks/nodes/{Block.ts → BlockContainer.ts} +113 -119
- package/src/extensions/Blocks/nodes/{BlockTypes/HeadingBlock/HeadingContent.ts → BlockContent/HeadingBlockContent/HeadingBlockContent.ts} +16 -24
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +76 -0
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/ListItemKeyboardShortcuts.ts +47 -0
- package/src/extensions/Blocks/nodes/{BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.ts → BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts} +10 -14
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +95 -0
- package/src/extensions/Blocks/nodes/{BlockTypes/TextBlock/TextContent.ts → BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts} +7 -12
- package/src/extensions/Blocks/nodes/BlockGroup.ts +4 -4
- package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +9 -1
- package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts +87 -42
- package/src/extensions/{Blocks → DraggableBlocks}/MultipleNodeSelection.ts +0 -0
- package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +20 -7
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +51 -12
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.ts +1 -1
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +3 -1
- package/src/extensions/Placeholder/PlaceholderExtension.ts +1 -1
- package/src/extensions/SlashMenu/SlashMenuExtension.ts +1 -1
- package/src/extensions/SlashMenu/SlashMenuItem.ts +3 -28
- package/src/extensions/SlashMenu/defaultCommands.tsx +36 -55
- package/src/extensions/SlashMenu/index.ts +1 -6
- package/src/extensions/TextAlignment/TextAlignmentExtension.ts +75 -0
- package/src/extensions/TextColor/TextColorExtension.ts +54 -0
- package/src/extensions/TextColor/TextColorMark.ts +62 -0
- package/src/extensions/TrailingNode/TrailingNodeExtension.ts +4 -4
- package/src/extensions/UniqueID/UniqueID.ts +6 -0
- package/src/index.ts +2 -1
- package/src/shared/EditorElement.ts +12 -6
- package/src/shared/plugins/suggestion/SuggestionItem.ts +0 -9
- package/src/shared/plugins/suggestion/SuggestionPlugin.ts +191 -228
- package/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.ts +2 -2
- package/types/src/BlockNoteEditor.d.ts +1 -1
- package/types/src/BlockNoteExtensions.d.ts +1 -3
- package/types/src/api/Document.d.ts +5 -0
- package/types/src/extensions/BackgroundColor/BackgroundColorExtension.d.ts +9 -0
- package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +9 -0
- package/types/src/extensions/Blocks/PreviousBlockTypePlugin.d.ts +3 -2
- package/types/src/extensions/Blocks/apiTypes.d.ts +16 -0
- package/types/src/extensions/Blocks/helpers/getBlockInfoFromPos.d.ts +1 -1
- package/types/src/extensions/Blocks/nodes/BlockAttributes.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContainer.d.ts +21 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/BlockContentTypes.d.ts +4 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContentTypes.d.ts +4 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContentTypes.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/ListItemKeyboardShortcuts.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContentTypes.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContentTypes.d.ts +2 -0
- package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +9 -5
- package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +1 -1
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +6 -11
- package/types/src/extensions/DraggableBlocks/MultipleNodeSelection.d.ts +24 -0
- package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +18 -8
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +1 -1
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +5 -5
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +2 -2
- package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +1 -1
- package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +2 -19
- package/types/src/extensions/SlashMenu/defaultSlashCommands.d.ts +5 -0
- package/types/src/extensions/SlashMenu/index.d.ts +1 -2
- package/types/src/extensions/TextAlignment/TextAlignmentExtension.d.ts +9 -0
- package/types/src/extensions/TextColor/TextColorExtension.d.ts +9 -0
- package/types/src/extensions/TextColor/TextColorMark.d.ts +9 -0
- package/types/src/index.d.ts +2 -1
- package/types/src/shared/EditorElement.d.ts +6 -2
- package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +0 -6
- package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +11 -25
- package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +6 -6
- package/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.ts +0 -177
- package/src/extensions/Paragraph/FixedParagraph.ts +0 -12
|
@@ -10,12 +10,6 @@ BASIC STYLES
|
|
|
10
10
|
font-weight: normal;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
.block {
|
|
14
|
-
border-left: 2px solid white;
|
|
15
|
-
border-color: white;
|
|
16
|
-
transition: all 0.2s;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
13
|
.block {
|
|
20
14
|
/* content: ""; */
|
|
21
15
|
transition: all 0.2s;
|
|
@@ -115,34 +109,34 @@ NESTED BLOCKS
|
|
|
115
109
|
}
|
|
116
110
|
|
|
117
111
|
/* HEADINGS*/
|
|
118
|
-
[data-
|
|
112
|
+
[data-level="1"] {
|
|
119
113
|
--level: 3em;
|
|
120
114
|
}
|
|
121
|
-
[data-
|
|
115
|
+
[data-level="2"] {
|
|
122
116
|
--level: 2em;
|
|
123
117
|
}
|
|
124
|
-
[data-
|
|
118
|
+
[data-level="3"] {
|
|
125
119
|
--level: 1.3em;
|
|
126
120
|
}
|
|
127
121
|
|
|
128
|
-
[data-prev-
|
|
122
|
+
[data-prev-level="1"] {
|
|
129
123
|
--prev-level: 3em;
|
|
130
124
|
}
|
|
131
|
-
[data-prev-
|
|
125
|
+
[data-prev-level="2"] {
|
|
132
126
|
--prev-level: 2em;
|
|
133
127
|
}
|
|
134
|
-
[data-prev-
|
|
128
|
+
[data-prev-level="3"] {
|
|
135
129
|
--prev-level: 1.3em;
|
|
136
130
|
}
|
|
137
131
|
|
|
138
|
-
.blockOuter[data-prev-type="
|
|
132
|
+
.blockOuter[data-prev-type="heading"] > .block > .blockContent {
|
|
139
133
|
font-size: var(--prev-level);
|
|
140
134
|
font-weight: bold;
|
|
141
135
|
}
|
|
142
136
|
|
|
143
137
|
.blockOuter:not([data-prev-type])
|
|
144
138
|
> .block
|
|
145
|
-
> .blockContent[data-content-type="
|
|
139
|
+
> .blockContent[data-content-type="heading"] {
|
|
146
140
|
font-size: var(--level);
|
|
147
141
|
font-weight: bold;
|
|
148
142
|
}
|
|
@@ -155,15 +149,15 @@ NESTED BLOCKS
|
|
|
155
149
|
}
|
|
156
150
|
|
|
157
151
|
/* Ordered */
|
|
158
|
-
[data-
|
|
159
|
-
--index: attr(data-
|
|
152
|
+
[data-content-type="numberedListItem"] {
|
|
153
|
+
--index: attr(data-index)
|
|
160
154
|
}
|
|
161
155
|
|
|
162
|
-
[data-prev-
|
|
163
|
-
--prev-index: attr(data-prev-
|
|
156
|
+
[data-prev-type="numberedListItem"] {
|
|
157
|
+
--prev-index: attr(data-prev-index)
|
|
164
158
|
}
|
|
165
159
|
|
|
166
|
-
.blockOuter[data-prev-
|
|
160
|
+
.blockOuter[data-prev-type="numberedListItem"]:not([data-prev-index="none"])
|
|
167
161
|
> .block
|
|
168
162
|
> .blockContent::before {
|
|
169
163
|
margin-right: 1.2em;
|
|
@@ -172,14 +166,14 @@ NESTED BLOCKS
|
|
|
172
166
|
|
|
173
167
|
.blockOuter:not([data-prev-type])
|
|
174
168
|
> .block
|
|
175
|
-
> .blockContent[data-
|
|
169
|
+
> .blockContent[data-content-type="numberedListItem"]::before {
|
|
176
170
|
margin-right: 1.2em;
|
|
177
171
|
content: var(--index)".";
|
|
178
172
|
}
|
|
179
173
|
|
|
180
174
|
/* Unordered */
|
|
181
175
|
/* No list nesting */
|
|
182
|
-
.blockOuter[data-prev-
|
|
176
|
+
.blockOuter[data-prev-type="bulletListItem"]
|
|
183
177
|
> .block
|
|
184
178
|
> .blockContent::before {
|
|
185
179
|
margin-right: 1.2em;
|
|
@@ -188,43 +182,43 @@ NESTED BLOCKS
|
|
|
188
182
|
|
|
189
183
|
.blockOuter:not([data-prev-type])
|
|
190
184
|
> .block
|
|
191
|
-
> .blockContent[data-
|
|
185
|
+
> .blockContent[data-content-type="bulletListItem"]::before {
|
|
192
186
|
margin-right: 1.2em;
|
|
193
187
|
content: "•";
|
|
194
188
|
}
|
|
195
189
|
|
|
196
190
|
/* 1 level of list nesting */
|
|
197
|
-
[data-
|
|
198
|
-
> .blockOuter[data-prev-
|
|
191
|
+
[data-content-type="bulletListItem"]~.blockGroup
|
|
192
|
+
> .blockOuter[data-prev-type="bulletListItem"]
|
|
199
193
|
> .block
|
|
200
194
|
> .blockContent::before {
|
|
201
195
|
margin-right: 1.2em;
|
|
202
196
|
content: "◦";
|
|
203
197
|
}
|
|
204
198
|
|
|
205
|
-
[data-
|
|
199
|
+
[data-content-type="bulletListItem"]~.blockGroup
|
|
206
200
|
> .blockOuter:not([data-prev-type])
|
|
207
201
|
> .block
|
|
208
|
-
> .blockContent[data-
|
|
202
|
+
> .blockContent[data-content-type="bulletListItem"]::before {
|
|
209
203
|
margin-right: 1.2em;
|
|
210
204
|
content: "◦";
|
|
211
205
|
}
|
|
212
206
|
|
|
213
207
|
/* 2 levels of list nesting */
|
|
214
|
-
[data-
|
|
215
|
-
[data-
|
|
216
|
-
> .blockOuter[data-prev-
|
|
208
|
+
[data-content-type="bulletListItem"]~.blockGroup
|
|
209
|
+
[data-content-type="bulletListItem"]~.blockGroup
|
|
210
|
+
> .blockOuter[data-prev-type="bulletListItem"]
|
|
217
211
|
> .block
|
|
218
212
|
> .blockContent::before {
|
|
219
213
|
margin-right: 1.2em;
|
|
220
214
|
content: "▪";
|
|
221
215
|
}
|
|
222
216
|
|
|
223
|
-
[data-
|
|
224
|
-
[data-
|
|
217
|
+
[data-content-type="bulletListItem"]~.blockGroup
|
|
218
|
+
[data-content-type="bulletListItem"]~.blockGroup
|
|
225
219
|
> .blockOuter:not([data-prev-type])
|
|
226
220
|
> .block
|
|
227
|
-
> .blockContent[data-
|
|
221
|
+
> .blockContent[data-content-type="bulletListItem"]::before {
|
|
228
222
|
margin-right: 1.2em;
|
|
229
223
|
content: "▪";
|
|
230
224
|
}
|
|
@@ -257,12 +251,105 @@ NESTED BLOCKS
|
|
|
257
251
|
content: "Type to filter";
|
|
258
252
|
}
|
|
259
253
|
|
|
260
|
-
.blockContent[data-content-type="
|
|
254
|
+
.blockContent[data-content-type="heading"].isEmpty
|
|
261
255
|
> :first-child::before {
|
|
262
256
|
content: "Heading";
|
|
263
257
|
}
|
|
264
258
|
|
|
265
|
-
.blockContent[data-content-type="
|
|
266
|
-
|
|
259
|
+
.blockContent[data-content-type="bulletListItem"].isEmpty
|
|
260
|
+
> :first-child:before,
|
|
261
|
+
.blockContent[data-content-type="numberedListItem"].isEmpty
|
|
262
|
+
> :first-child:before {
|
|
267
263
|
content: "List";
|
|
268
264
|
}
|
|
265
|
+
|
|
266
|
+
/* TEXT COLORS */
|
|
267
|
+
[data-text-color="gray"] {
|
|
268
|
+
color: #9b9a97;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
[data-text-color="brown"] {
|
|
272
|
+
color: #64473a;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
[data-text-color="red"] {
|
|
276
|
+
color: #e03e3e;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
[data-text-color="orange"] {
|
|
280
|
+
color: #d9730d;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
[data-text-color="yellow"] {
|
|
284
|
+
color: #dfab01;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
[data-text-color="green"] {
|
|
288
|
+
color: #4d6461;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
[data-text-color="blue"] {
|
|
292
|
+
color: #0b6e99;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
[data-text-color="purple"] {
|
|
296
|
+
color: #6940a5;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
[data-text-color="pink"] {
|
|
300
|
+
color: #ad1a72;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/* BACKGROUND COLORS */
|
|
304
|
+
[data-background-color="gray"] {
|
|
305
|
+
background-color: #ebeced;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
[data-background-color="brown"] {
|
|
309
|
+
background-color: #e9e5e3;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
[data-background-color="red"] {
|
|
313
|
+
background-color: #fbe4e4;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
[data-background-color="orange"] {
|
|
317
|
+
background-color: #faebdd;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
[data-background-color="yellow"] {
|
|
321
|
+
background-color: #fbf3db;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
[data-background-color="green"] {
|
|
325
|
+
background-color: #ddedea;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
[data-background-color="blue"] {
|
|
329
|
+
background-color: #ddebf1;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
[data-background-color="purple"] {
|
|
333
|
+
background-color: #eae4f2;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
[data-background-color="pink"] {
|
|
337
|
+
background-color: #f4dfeb;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* TEXT ALIGNMENT */
|
|
341
|
+
[data-text-alignment="left"] {
|
|
342
|
+
text-align: left;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
[data-text-alignment="center"] {
|
|
346
|
+
text-align: center;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
[data-text-alignment="right"] {
|
|
350
|
+
text-align: right;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
[data-text-alignment="justify"] {
|
|
354
|
+
text-align: justify;
|
|
355
|
+
}
|
|
File without changes
|
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
import { mergeAttributes, Node } from "@tiptap/core";
|
|
2
|
-
import { Slice } from "prosemirror-model";
|
|
2
|
+
import { Fragment, Slice } from "prosemirror-model";
|
|
3
3
|
import { TextSelection } from "prosemirror-state";
|
|
4
|
-
import
|
|
4
|
+
import { BlockUpdate } from "../apiTypes";
|
|
5
5
|
import { getBlockInfoFromPos } from "../helpers/getBlockInfoFromPos";
|
|
6
6
|
import { PreviousBlockTypePlugin } from "../PreviousBlockTypePlugin";
|
|
7
7
|
import styles from "./Block.module.css";
|
|
8
|
-
import
|
|
9
|
-
import { HeadingContentType } from "./BlockTypes/HeadingBlock/HeadingContent";
|
|
10
|
-
import { ListItemContentType } from "./BlockTypes/ListItemBlock/ListItemContent";
|
|
8
|
+
import BlockAttributes from "./BlockAttributes";
|
|
11
9
|
|
|
10
|
+
// TODO
|
|
12
11
|
export interface IBlock {
|
|
13
12
|
HTMLAttributes: Record<string, any>;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
export type BlockContentType =
|
|
17
|
-
| TextContentType
|
|
18
|
-
| HeadingContentType
|
|
19
|
-
| ListItemContentType;
|
|
20
|
-
|
|
21
15
|
declare module "@tiptap/core" {
|
|
22
16
|
interface Commands<ReturnType> {
|
|
23
17
|
block: {
|
|
@@ -25,13 +19,13 @@ declare module "@tiptap/core" {
|
|
|
25
19
|
BNDeleteBlock: (posInBlock: number) => ReturnType;
|
|
26
20
|
BNMergeBlocks: (posBetweenBlocks: number) => ReturnType;
|
|
27
21
|
BNSplitBlock: (posInBlock: number, keepType: boolean) => ReturnType;
|
|
28
|
-
|
|
22
|
+
BNUpdateBlock: (
|
|
29
23
|
posInBlock: number,
|
|
30
|
-
|
|
24
|
+
blockUpdate: BlockUpdate
|
|
31
25
|
) => ReturnType;
|
|
32
|
-
|
|
26
|
+
BNCreateOrUpdateBlock: (
|
|
33
27
|
posInBlock: number,
|
|
34
|
-
|
|
28
|
+
blockUpdate: BlockUpdate
|
|
35
29
|
) => ReturnType;
|
|
36
30
|
};
|
|
37
31
|
}
|
|
@@ -40,9 +34,9 @@ declare module "@tiptap/core" {
|
|
|
40
34
|
/**
|
|
41
35
|
* The main "Block node" documents consist of
|
|
42
36
|
*/
|
|
43
|
-
export const
|
|
44
|
-
name: "
|
|
45
|
-
group: "
|
|
37
|
+
export const BlockContainer = Node.create<IBlock>({
|
|
38
|
+
name: "blockContainer",
|
|
39
|
+
group: "blockContainer",
|
|
46
40
|
// A block always contains content, and optionally a blockGroup which contains nested blocks
|
|
47
41
|
content: "blockContent blockGroup?",
|
|
48
42
|
// Ensures content-specific keyboard handlers trigger first.
|
|
@@ -55,17 +49,6 @@ export const Block = Node.create<IBlock>({
|
|
|
55
49
|
};
|
|
56
50
|
},
|
|
57
51
|
|
|
58
|
-
addAttributes() {
|
|
59
|
-
return {
|
|
60
|
-
blockColor: {
|
|
61
|
-
default: undefined,
|
|
62
|
-
},
|
|
63
|
-
blockStyle: {
|
|
64
|
-
default: undefined,
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
},
|
|
68
|
-
|
|
69
52
|
parseHTML() {
|
|
70
53
|
return [
|
|
71
54
|
{
|
|
@@ -82,7 +65,7 @@ export const Block = Node.create<IBlock>({
|
|
|
82
65
|
}
|
|
83
66
|
}
|
|
84
67
|
|
|
85
|
-
if (element.getAttribute("data-node-type") === "
|
|
68
|
+
if (element.getAttribute("data-node-type") === "blockContainer") {
|
|
86
69
|
return attrs;
|
|
87
70
|
}
|
|
88
71
|
|
|
@@ -93,23 +76,15 @@ export const Block = Node.create<IBlock>({
|
|
|
93
76
|
},
|
|
94
77
|
|
|
95
78
|
renderHTML({ HTMLAttributes }) {
|
|
96
|
-
const attrs: Record<string, string> = {};
|
|
97
|
-
for (let [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {
|
|
98
|
-
// Ensure falsy values are not misinterpreted.
|
|
99
|
-
if (HTMLAttributes[nodeAttr] !== undefined) {
|
|
100
|
-
attrs[HTMLAttr] = HTMLAttributes[nodeAttr];
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
79
|
return [
|
|
105
80
|
"div",
|
|
106
|
-
mergeAttributes(
|
|
81
|
+
mergeAttributes(HTMLAttributes, {
|
|
107
82
|
class: styles.blockOuter,
|
|
108
83
|
"data-node-type": "block-outer",
|
|
109
84
|
}),
|
|
110
85
|
[
|
|
111
86
|
"div",
|
|
112
|
-
mergeAttributes(
|
|
87
|
+
mergeAttributes(HTMLAttributes, {
|
|
113
88
|
// TODO: maybe remove html attributes from inner block
|
|
114
89
|
class: styles.block,
|
|
115
90
|
"data-node-type": this.name,
|
|
@@ -125,7 +100,8 @@ export const Block = Node.create<IBlock>({
|
|
|
125
100
|
BNCreateBlock:
|
|
126
101
|
(pos) =>
|
|
127
102
|
({ state, dispatch }) => {
|
|
128
|
-
const newBlock =
|
|
103
|
+
const newBlock =
|
|
104
|
+
state.schema.nodes["blockContainer"].createAndFill()!;
|
|
129
105
|
|
|
130
106
|
if (dispatch) {
|
|
131
107
|
state.tr.insert(pos, newBlock);
|
|
@@ -176,10 +152,10 @@ export const Block = Node.create<IBlock>({
|
|
|
176
152
|
({ state, dispatch }) => {
|
|
177
153
|
const nextNodeIsBlock =
|
|
178
154
|
state.doc.resolve(posBetweenBlocks + 1).node().type.name ===
|
|
179
|
-
"
|
|
155
|
+
"blockContainer";
|
|
180
156
|
const prevNodeIsBlock =
|
|
181
157
|
state.doc.resolve(posBetweenBlocks - 1).node().type.name ===
|
|
182
|
-
"
|
|
158
|
+
"blockContainer";
|
|
183
159
|
|
|
184
160
|
if (!nextNodeIsBlock || !prevNodeIsBlock) {
|
|
185
161
|
return false;
|
|
@@ -246,19 +222,36 @@ export const Block = Node.create<IBlock>({
|
|
|
246
222
|
const { contentNode, contentType, startPos, endPos, depth } =
|
|
247
223
|
blockInfo;
|
|
248
224
|
|
|
249
|
-
const
|
|
225
|
+
const originalBlockContent = state.doc.cut(startPos + 1, posInBlock);
|
|
226
|
+
const newBlockContent = state.doc.cut(posInBlock, endPos - 1);
|
|
250
227
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const secondBlockContent = state.doc.textBetween(posInBlock, endPos);
|
|
228
|
+
const newBlock =
|
|
229
|
+
state.schema.nodes["blockContainer"].createAndFill()!;
|
|
254
230
|
|
|
255
|
-
const
|
|
231
|
+
const newBlockInsertionPos = endPos + 1;
|
|
256
232
|
const newBlockContentPos = newBlockInsertionPos + 2;
|
|
257
233
|
|
|
258
234
|
if (dispatch) {
|
|
235
|
+
// Creates a new block. Since the schema requires it to have a content node, a paragraph node is created
|
|
236
|
+
// automatically, spanning newBlockContentPos to newBlockContentPos + 1.
|
|
259
237
|
state.tr.insert(newBlockInsertionPos, newBlock);
|
|
260
|
-
state.tr.insertText(secondBlockContent, newBlockContentPos);
|
|
261
238
|
|
|
239
|
+
// Replaces the content of the newly created block's content node. Doesn't replace the whole content node so
|
|
240
|
+
// its type doesn't change.
|
|
241
|
+
state.tr.replace(
|
|
242
|
+
newBlockContentPos,
|
|
243
|
+
newBlockContentPos + 1,
|
|
244
|
+
newBlockContent.content.size > 0
|
|
245
|
+
? new Slice(
|
|
246
|
+
Fragment.from(newBlockContent),
|
|
247
|
+
depth + 2,
|
|
248
|
+
depth + 2
|
|
249
|
+
)
|
|
250
|
+
: undefined
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
// Changes the type of the content node. The range doesn't matter as long as both from and to positions are
|
|
254
|
+
// within the content node.
|
|
262
255
|
if (keepType) {
|
|
263
256
|
state.tr.setBlockType(
|
|
264
257
|
newBlockContentPos,
|
|
@@ -267,38 +260,49 @@ export const Block = Node.create<IBlock>({
|
|
|
267
260
|
contentNode.attrs
|
|
268
261
|
);
|
|
269
262
|
}
|
|
270
|
-
}
|
|
271
263
|
|
|
272
|
-
|
|
273
|
-
|
|
264
|
+
// Sets the selection to the start of the new block's content node.
|
|
265
|
+
state.tr.setSelection(
|
|
266
|
+
new TextSelection(state.doc.resolve(newBlockContentPos))
|
|
267
|
+
);
|
|
274
268
|
|
|
275
|
-
|
|
269
|
+
// Replaces the content of the original block's content node. Doesn't replace the whole content node so its
|
|
270
|
+
// type doesn't change.
|
|
276
271
|
state.tr.replace(
|
|
277
|
-
startPos,
|
|
278
|
-
endPos,
|
|
279
|
-
|
|
272
|
+
startPos + 1,
|
|
273
|
+
endPos - 1,
|
|
274
|
+
originalBlockContent.content.size > 0
|
|
275
|
+
? new Slice(
|
|
276
|
+
Fragment.from(originalBlockContent),
|
|
277
|
+
depth + 2,
|
|
278
|
+
depth + 2
|
|
279
|
+
)
|
|
280
|
+
: undefined
|
|
280
281
|
);
|
|
281
282
|
}
|
|
282
283
|
|
|
283
284
|
return true;
|
|
284
285
|
},
|
|
285
|
-
//
|
|
286
|
-
|
|
287
|
-
(posInBlock,
|
|
286
|
+
// Updates the type and attributes of a block at a given position.
|
|
287
|
+
BNUpdateBlock:
|
|
288
|
+
(posInBlock, blockUpdate) =>
|
|
288
289
|
({ state, dispatch }) => {
|
|
289
290
|
const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);
|
|
290
291
|
if (blockInfo === undefined) {
|
|
291
292
|
return false;
|
|
292
293
|
}
|
|
293
294
|
|
|
294
|
-
const { startPos, contentNode } = blockInfo;
|
|
295
|
+
const { node, startPos, contentNode } = blockInfo;
|
|
295
296
|
|
|
296
297
|
if (dispatch) {
|
|
297
298
|
state.tr.setBlockType(
|
|
298
299
|
startPos + 1,
|
|
299
300
|
startPos + contentNode.nodeSize + 1,
|
|
300
|
-
state.schema.node(type
|
|
301
|
-
|
|
301
|
+
state.schema.node(blockUpdate.type).type,
|
|
302
|
+
{
|
|
303
|
+
...node.attrs,
|
|
304
|
+
...blockUpdate.props,
|
|
305
|
+
}
|
|
302
306
|
);
|
|
303
307
|
}
|
|
304
308
|
|
|
@@ -306,8 +310,8 @@ export const Block = Node.create<IBlock>({
|
|
|
306
310
|
},
|
|
307
311
|
// Changes the block at a given position to a given content type if it's empty, otherwise creates a new block of
|
|
308
312
|
// that type below it.
|
|
309
|
-
|
|
310
|
-
(posInBlock,
|
|
313
|
+
BNCreateOrUpdateBlock:
|
|
314
|
+
(posInBlock, blockUpdate) =>
|
|
311
315
|
({ state, chain }) => {
|
|
312
316
|
const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);
|
|
313
317
|
if (blockInfo === undefined) {
|
|
@@ -320,7 +324,7 @@ export const Block = Node.create<IBlock>({
|
|
|
320
324
|
const oldBlockContentPos = startPos + 1;
|
|
321
325
|
|
|
322
326
|
return chain()
|
|
323
|
-
.
|
|
327
|
+
.BNUpdateBlock(posInBlock, blockUpdate)
|
|
324
328
|
.setTextSelection(oldBlockContentPos)
|
|
325
329
|
.run();
|
|
326
330
|
} else {
|
|
@@ -329,7 +333,7 @@ export const Block = Node.create<IBlock>({
|
|
|
329
333
|
|
|
330
334
|
return chain()
|
|
331
335
|
.BNCreateBlock(newBlockInsertionPos)
|
|
332
|
-
.
|
|
336
|
+
.BNUpdateBlock(newBlockContentPos, blockUpdate)
|
|
333
337
|
.setTextSelection(newBlockContentPos)
|
|
334
338
|
.run();
|
|
335
339
|
}
|
|
@@ -349,7 +353,7 @@ export const Block = Node.create<IBlock>({
|
|
|
349
353
|
() => commands.deleteSelection(),
|
|
350
354
|
// Undoes an input rule if one was triggered in the last editor state change.
|
|
351
355
|
() => commands.undoInputRule(),
|
|
352
|
-
//
|
|
356
|
+
// Reverts block content type to a paragraph if the selection is at the start of the block.
|
|
353
357
|
() =>
|
|
354
358
|
commands.command(({ state }) => {
|
|
355
359
|
const { contentType } = getBlockInfoFromPos(
|
|
@@ -359,11 +363,12 @@ export const Block = Node.create<IBlock>({
|
|
|
359
363
|
|
|
360
364
|
const selectionAtBlockStart =
|
|
361
365
|
state.selection.$anchor.parentOffset === 0;
|
|
362
|
-
const
|
|
366
|
+
const isParagraph = contentType.name === "paragraph";
|
|
363
367
|
|
|
364
|
-
if (selectionAtBlockStart && !
|
|
365
|
-
return commands.
|
|
366
|
-
|
|
368
|
+
if (selectionAtBlockStart && !isParagraph) {
|
|
369
|
+
return commands.BNUpdateBlock(state.selection.from, {
|
|
370
|
+
type: "paragraph",
|
|
371
|
+
props: {},
|
|
367
372
|
});
|
|
368
373
|
}
|
|
369
374
|
|
|
@@ -376,7 +381,7 @@ export const Block = Node.create<IBlock>({
|
|
|
376
381
|
state.selection.$anchor.parentOffset === 0;
|
|
377
382
|
|
|
378
383
|
if (selectionAtBlockStart) {
|
|
379
|
-
return commands.liftListItem("
|
|
384
|
+
return commands.liftListItem("blockContainer");
|
|
380
385
|
}
|
|
381
386
|
|
|
382
387
|
return false;
|
|
@@ -435,7 +440,7 @@ export const Block = Node.create<IBlock>({
|
|
|
435
440
|
blockEmpty &&
|
|
436
441
|
blockIndented
|
|
437
442
|
) {
|
|
438
|
-
return commands.liftListItem("
|
|
443
|
+
return commands.liftListItem("blockContainer");
|
|
439
444
|
}
|
|
440
445
|
|
|
441
446
|
return false;
|
|
@@ -496,62 +501,51 @@ export const Block = Node.create<IBlock>({
|
|
|
496
501
|
return {
|
|
497
502
|
Backspace: handleBackspace,
|
|
498
503
|
Enter: handleEnter,
|
|
499
|
-
|
|
500
|
-
|
|
504
|
+
// Always returning true for tab key presses ensures they're not captured by the browser. Otherwise, they blur the
|
|
505
|
+
// editor since the browser will try to use tab for keyboard navigation.
|
|
506
|
+
Tab: () => {
|
|
507
|
+
this.editor.commands.sinkListItem("blockContainer");
|
|
508
|
+
return true;
|
|
509
|
+
},
|
|
510
|
+
"Shift-Tab": () => {
|
|
511
|
+
this.editor.commands.liftListItem("blockContainer");
|
|
512
|
+
return true;
|
|
513
|
+
},
|
|
501
514
|
"Mod-Alt-0": () =>
|
|
502
515
|
this.editor.commands.BNCreateBlock(
|
|
503
516
|
this.editor.state.selection.anchor + 2
|
|
504
517
|
),
|
|
505
518
|
"Mod-Alt-1": () =>
|
|
506
|
-
this.editor.commands.
|
|
507
|
-
|
|
508
|
-
{
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
},
|
|
513
|
-
}
|
|
514
|
-
),
|
|
519
|
+
this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
|
|
520
|
+
type: "heading",
|
|
521
|
+
props: {
|
|
522
|
+
level: "1",
|
|
523
|
+
},
|
|
524
|
+
}),
|
|
515
525
|
"Mod-Alt-2": () =>
|
|
516
|
-
this.editor.commands.
|
|
517
|
-
|
|
518
|
-
{
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
},
|
|
523
|
-
}
|
|
524
|
-
),
|
|
526
|
+
this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
|
|
527
|
+
type: "heading",
|
|
528
|
+
props: {
|
|
529
|
+
level: "2",
|
|
530
|
+
},
|
|
531
|
+
}),
|
|
525
532
|
"Mod-Alt-3": () =>
|
|
526
|
-
this.editor.commands.
|
|
527
|
-
|
|
528
|
-
{
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
},
|
|
533
|
-
}
|
|
534
|
-
),
|
|
533
|
+
this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
|
|
534
|
+
type: "heading",
|
|
535
|
+
props: {
|
|
536
|
+
level: "3",
|
|
537
|
+
},
|
|
538
|
+
}),
|
|
535
539
|
"Mod-Shift-7": () =>
|
|
536
|
-
this.editor.commands.
|
|
537
|
-
|
|
538
|
-
{
|
|
539
|
-
|
|
540
|
-
attrs: {
|
|
541
|
-
listItemType: "unordered",
|
|
542
|
-
},
|
|
543
|
-
}
|
|
544
|
-
),
|
|
540
|
+
this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
|
|
541
|
+
type: "bulletListItem",
|
|
542
|
+
props: {},
|
|
543
|
+
}),
|
|
545
544
|
"Mod-Shift-8": () =>
|
|
546
|
-
this.editor.commands.
|
|
547
|
-
|
|
548
|
-
{
|
|
549
|
-
|
|
550
|
-
attrs: {
|
|
551
|
-
listItemType: "ordered",
|
|
552
|
-
},
|
|
553
|
-
}
|
|
554
|
-
),
|
|
545
|
+
this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
|
|
546
|
+
type: "numberedListItem",
|
|
547
|
+
props: {},
|
|
548
|
+
}),
|
|
555
549
|
};
|
|
556
550
|
},
|
|
557
551
|
});
|