@blocknote/xl-multi-column 0.19.0
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/LICENSE +661 -0
- package/dist/blocknote-xl-multi-column.js +3038 -0
- package/dist/blocknote-xl-multi-column.js.map +1 -0
- package/dist/blocknote-xl-multi-column.umd.cjs +69 -0
- package/dist/blocknote-xl-multi-column.umd.cjs.map +1 -0
- package/dist/webpack-stats.json +1 -0
- package/package.json +80 -0
- package/src/blocks/Columns/index.ts +15 -0
- package/src/blocks/schema.ts +43 -0
- package/src/extensions/ColumnResize/ColumnResizeExtension.ts +357 -0
- package/src/extensions/DropCursor/MultiColumnDropCursorPlugin.ts +480 -0
- package/src/extensions/SuggestionMenu/getMultiColumnSlashMenuItems.tsx +105 -0
- package/src/i18n/dictionary.ts +27 -0
- package/src/i18n/locales/ar.ts +18 -0
- package/src/i18n/locales/de.ts +18 -0
- package/src/i18n/locales/en.ts +16 -0
- package/src/i18n/locales/es.ts +18 -0
- package/src/i18n/locales/fr.ts +18 -0
- package/src/i18n/locales/hr.ts +18 -0
- package/src/i18n/locales/index.ts +15 -0
- package/src/i18n/locales/is.ts +18 -0
- package/src/i18n/locales/ja.ts +18 -0
- package/src/i18n/locales/ko.ts +18 -0
- package/src/i18n/locales/nl.ts +18 -0
- package/src/i18n/locales/pl.ts +18 -0
- package/src/i18n/locales/pt.ts +18 -0
- package/src/i18n/locales/ru.ts +18 -0
- package/src/i18n/locales/vi.ts +18 -0
- package/src/i18n/locales/zh.ts +18 -0
- package/src/index.ts +7 -0
- package/src/pm-nodes/Column.ts +87 -0
- package/src/pm-nodes/ColumnList.ts +44 -0
- package/src/test/commands/__snapshots__/insertBlocks.test.ts.snap +757 -0
- package/src/test/commands/__snapshots__/textCursorPosition.test.ts.snap +169 -0
- package/src/test/commands/__snapshots__/updateBlock.test.ts.snap +964 -0
- package/src/test/commands/insertBlocks.test.ts +206 -0
- package/src/test/commands/textCursorPosition.test.ts +19 -0
- package/src/test/commands/updateBlock.test.ts +212 -0
- package/src/test/conversions/__snapshots__/multi-column/undefined/external.html +1 -0
- package/src/test/conversions/__snapshots__/multi-column/undefined/internal.html +1 -0
- package/src/test/conversions/__snapshots__/nodeConversion.test.ts.snap +118 -0
- package/src/test/conversions/htmlConversion.test.ts +100 -0
- package/src/test/conversions/nodeConversion.test.ts +84 -0
- package/src/test/conversions/testCases.ts +54 -0
- package/src/test/setupTestEnv.ts +99 -0
- package/src/vite-env.d.ts +1 -0
- package/types/src/blocks/Columns/index.d.ts +32 -0
- package/types/src/blocks/schema.d.ts +102 -0
- package/types/src/extensions/ColumnResize/ColumnResizeExtension.d.ts +3 -0
- package/types/src/extensions/DropCursor/MultiColumnDropCursorPlugin.d.ts +11 -0
- package/types/src/extensions/SuggestionMenu/getMultiColumnSlashMenuItems.d.ts +5 -0
- package/types/src/i18n/dictionary.d.ts +19 -0
- package/types/src/i18n/locales/ar.d.ts +2 -0
- package/types/src/i18n/locales/de.d.ts +2 -0
- package/types/src/i18n/locales/en.d.ts +16 -0
- package/types/src/i18n/locales/es.d.ts +2 -0
- package/types/src/i18n/locales/fr.d.ts +2 -0
- package/types/src/i18n/locales/hr.d.ts +2 -0
- package/types/src/i18n/locales/index.d.ts +15 -0
- package/types/src/i18n/locales/is.d.ts +2 -0
- package/types/src/i18n/locales/ja.d.ts +2 -0
- package/types/src/i18n/locales/ko.d.ts +2 -0
- package/types/src/i18n/locales/nl.d.ts +2 -0
- package/types/src/i18n/locales/pl.d.ts +2 -0
- package/types/src/i18n/locales/pt.d.ts +2 -0
- package/types/src/i18n/locales/ru.d.ts +2 -0
- package/types/src/i18n/locales/vi.d.ts +2 -0
- package/types/src/i18n/locales/zh.d.ts +2 -0
- package/types/src/index.d.ts +7 -0
- package/types/src/pm-nodes/Column.d.ts +6 -0
- package/types/src/pm-nodes/ColumnList.d.ts +6 -0
- package/types/src/test/commands/insertBlocks.test.d.ts +1 -0
- package/types/src/test/commands/textCursorPosition.test.d.ts +1 -0
- package/types/src/test/commands/updateBlock.test.d.ts +1 -0
- package/types/src/test/conversions/htmlConversion.test.d.ts +1 -0
- package/types/src/test/conversions/nodeConversion.test.d.ts +1 -0
- package/types/src/test/conversions/testCases.d.ts +3 -0
- package/types/src/test/setupTestEnv.d.ts +1041 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { setupTestEnv } from "../setupTestEnv.js";
|
|
4
|
+
|
|
5
|
+
const getEditor = setupTestEnv();
|
|
6
|
+
|
|
7
|
+
describe("Test insertBlocks", () => {
|
|
8
|
+
it("Insert empty column list", () => {
|
|
9
|
+
// should throw an error as we don't allow empty column lists
|
|
10
|
+
expect(() => {
|
|
11
|
+
getEditor().insertBlocks(
|
|
12
|
+
[{ type: "columnList" }],
|
|
13
|
+
"paragraph-0",
|
|
14
|
+
"after"
|
|
15
|
+
);
|
|
16
|
+
}).toThrow();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("Insert column list with empty column", () => {
|
|
20
|
+
// should throw an error as we don't allow empty columns
|
|
21
|
+
expect(() => {
|
|
22
|
+
getEditor().insertBlocks(
|
|
23
|
+
[
|
|
24
|
+
{
|
|
25
|
+
type: "columnList",
|
|
26
|
+
children: [
|
|
27
|
+
{
|
|
28
|
+
type: "column",
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
"paragraph-0",
|
|
34
|
+
"after"
|
|
35
|
+
);
|
|
36
|
+
}).toThrow();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("Insert column list with single column", () => {
|
|
40
|
+
// should throw an error as we don't allow column list with single column
|
|
41
|
+
expect(() => {
|
|
42
|
+
getEditor().insertBlocks(
|
|
43
|
+
[
|
|
44
|
+
{
|
|
45
|
+
type: "columnList",
|
|
46
|
+
children: [
|
|
47
|
+
{
|
|
48
|
+
type: "column",
|
|
49
|
+
children: [
|
|
50
|
+
{
|
|
51
|
+
type: "paragraph",
|
|
52
|
+
content: "Inserted Column Paragraph",
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
"paragraph-0",
|
|
60
|
+
"after"
|
|
61
|
+
);
|
|
62
|
+
}).toThrow();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("Insert valid column list with two columns", () => {
|
|
66
|
+
getEditor().insertBlocks(
|
|
67
|
+
[
|
|
68
|
+
{
|
|
69
|
+
type: "columnList",
|
|
70
|
+
children: [
|
|
71
|
+
{
|
|
72
|
+
type: "column",
|
|
73
|
+
children: [
|
|
74
|
+
{
|
|
75
|
+
type: "paragraph",
|
|
76
|
+
content: "Inserted Column Paragraph",
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
type: "column",
|
|
82
|
+
children: [
|
|
83
|
+
{
|
|
84
|
+
type: "paragraph",
|
|
85
|
+
content: "Inserted Second Column Paragraph",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
"paragraph-0",
|
|
93
|
+
"after"
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("Insert column with paragraph into column list", () => {
|
|
100
|
+
getEditor().insertBlocks(
|
|
101
|
+
[
|
|
102
|
+
{
|
|
103
|
+
type: "column",
|
|
104
|
+
children: [
|
|
105
|
+
{
|
|
106
|
+
type: "paragraph",
|
|
107
|
+
content: "Inserted Column Paragraph",
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
"column-0",
|
|
113
|
+
"before"
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("Insert column list into paragraph", () => {
|
|
120
|
+
getEditor().insertBlocks(
|
|
121
|
+
[
|
|
122
|
+
{
|
|
123
|
+
type: "columnList",
|
|
124
|
+
children: [
|
|
125
|
+
{
|
|
126
|
+
type: "column",
|
|
127
|
+
children: [
|
|
128
|
+
{
|
|
129
|
+
type: "paragraph",
|
|
130
|
+
content: "Inserted Column Paragraph",
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: "column",
|
|
136
|
+
children: [
|
|
137
|
+
{
|
|
138
|
+
type: "paragraph",
|
|
139
|
+
content: "Inserted Column Paragraph",
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
"nested-paragraph-0",
|
|
147
|
+
"after"
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// TODO: failing because prosemirror "insert" finds a place to insert this using the fitting algorithm
|
|
154
|
+
it.skip("Insert column into paragraph", () => {
|
|
155
|
+
// should throw an error as we don't allow columns to be children of paragraphs
|
|
156
|
+
expect(() => {
|
|
157
|
+
getEditor().insertBlocks(
|
|
158
|
+
[
|
|
159
|
+
{
|
|
160
|
+
type: "column",
|
|
161
|
+
children: [
|
|
162
|
+
{
|
|
163
|
+
type: "paragraph",
|
|
164
|
+
content: "Inserted Column Paragraph",
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
"nested-paragraph-0",
|
|
170
|
+
"after"
|
|
171
|
+
);
|
|
172
|
+
}).toThrow();
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// TODO: failing because prosemirror "insert" finds a place to insert this using the fitting algorithm
|
|
176
|
+
it.skip("Insert paragraph into column list", () => {
|
|
177
|
+
// should throw an error as we don't allow paragraphs to be children of column lists
|
|
178
|
+
expect(() => {
|
|
179
|
+
getEditor().insertBlocks(
|
|
180
|
+
[
|
|
181
|
+
{
|
|
182
|
+
type: "paragraph",
|
|
183
|
+
content: "Inserted Column List Paragraph",
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
"column-0",
|
|
187
|
+
"after"
|
|
188
|
+
);
|
|
189
|
+
}).toThrow();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("Insert paragraph into column", () => {
|
|
193
|
+
getEditor().insertBlocks(
|
|
194
|
+
[
|
|
195
|
+
{
|
|
196
|
+
type: "paragraph",
|
|
197
|
+
content: "Inserted Column List Paragraph",
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
"column-paragraph-0",
|
|
201
|
+
"after"
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { setupTestEnv } from "../setupTestEnv.js";
|
|
4
|
+
|
|
5
|
+
const getEditor = setupTestEnv();
|
|
6
|
+
|
|
7
|
+
describe("Test getTextCursorPosition & setTextCursorPosition", () => {
|
|
8
|
+
it("Column list", () => {
|
|
9
|
+
getEditor().setTextCursorPosition("column-list-0");
|
|
10
|
+
|
|
11
|
+
expect(getEditor().getTextCursorPosition()).toMatchSnapshot();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("Column", () => {
|
|
15
|
+
getEditor().setTextCursorPosition("column-0");
|
|
16
|
+
|
|
17
|
+
expect(getEditor().getTextCursorPosition()).toMatchSnapshot();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { setupTestEnv } from "../setupTestEnv.js";
|
|
4
|
+
|
|
5
|
+
const getEditor = setupTestEnv();
|
|
6
|
+
|
|
7
|
+
describe("Test updateBlock", () => {
|
|
8
|
+
it("Update column list new children", () => {
|
|
9
|
+
getEditor().updateBlock("column-list-0", {
|
|
10
|
+
type: "columnList",
|
|
11
|
+
children: [
|
|
12
|
+
{
|
|
13
|
+
type: "column",
|
|
14
|
+
children: [
|
|
15
|
+
{
|
|
16
|
+
type: "paragraph",
|
|
17
|
+
content: "Inserted Column Paragraph",
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: "column",
|
|
23
|
+
children: [
|
|
24
|
+
{
|
|
25
|
+
type: "paragraph",
|
|
26
|
+
content: "Inserted Column Paragraph",
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("Update column list new empty children", () => {
|
|
37
|
+
// should throw because we don't allow empty columns / single columns
|
|
38
|
+
expect(() => {
|
|
39
|
+
getEditor().updateBlock("column-list-0", {
|
|
40
|
+
type: "columnList",
|
|
41
|
+
children: [
|
|
42
|
+
{
|
|
43
|
+
type: "paragraph",
|
|
44
|
+
content: "Inserted Column Paragraph",
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
}).toThrow();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("Update column new children", () => {
|
|
52
|
+
getEditor().updateBlock("column-0", {
|
|
53
|
+
type: "column",
|
|
54
|
+
children: [
|
|
55
|
+
{
|
|
56
|
+
type: "paragraph",
|
|
57
|
+
content: "Inserted Column Paragraph",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("Update paragraph to column list", () => {
|
|
66
|
+
getEditor().updateBlock("paragraph-0", {
|
|
67
|
+
type: "columnList",
|
|
68
|
+
children: [
|
|
69
|
+
{
|
|
70
|
+
type: "column",
|
|
71
|
+
children: [
|
|
72
|
+
{
|
|
73
|
+
type: "paragraph",
|
|
74
|
+
content: "Inserted Column Paragraph",
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
type: "column",
|
|
80
|
+
children: [
|
|
81
|
+
{
|
|
82
|
+
type: "paragraph",
|
|
83
|
+
content: "Inserted Column Paragraph",
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("Update nested paragraph to column list", () => {
|
|
94
|
+
getEditor().updateBlock("nested-paragraph-0", {
|
|
95
|
+
type: "columnList",
|
|
96
|
+
children: [
|
|
97
|
+
{
|
|
98
|
+
type: "column",
|
|
99
|
+
children: [
|
|
100
|
+
{
|
|
101
|
+
type: "paragraph",
|
|
102
|
+
content: "Inserted Column Paragraph",
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
type: "column",
|
|
108
|
+
children: [
|
|
109
|
+
{
|
|
110
|
+
type: "paragraph",
|
|
111
|
+
content: "Inserted Column Paragraph",
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("Update column to column list", () => {
|
|
122
|
+
// should throw an error as we don't allow a column list inside a columnlist
|
|
123
|
+
expect(() => {
|
|
124
|
+
getEditor().updateBlock("column-0", {
|
|
125
|
+
type: "columnList",
|
|
126
|
+
children: [
|
|
127
|
+
{
|
|
128
|
+
type: "column",
|
|
129
|
+
children: [
|
|
130
|
+
{
|
|
131
|
+
type: "paragraph",
|
|
132
|
+
content: "Inserted Column Paragraph",
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
type: "column",
|
|
138
|
+
children: [
|
|
139
|
+
{
|
|
140
|
+
type: "paragraph",
|
|
141
|
+
content: "Inserted Column Paragraph",
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
}).toThrow();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("Update paragraph to column", () => {
|
|
151
|
+
getEditor().updateBlock("paragraph-0", {
|
|
152
|
+
type: "column",
|
|
153
|
+
children: [
|
|
154
|
+
{
|
|
155
|
+
type: "paragraph",
|
|
156
|
+
content: "Inserted Column Paragraph",
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("Update nested paragraph to column", () => {
|
|
165
|
+
getEditor().updateBlock("nested-paragraph-0", {
|
|
166
|
+
type: "column",
|
|
167
|
+
children: [
|
|
168
|
+
{
|
|
169
|
+
type: "paragraph",
|
|
170
|
+
content: "Inserted Column Paragraph",
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
expect(getEditor().document).toMatchSnapshot();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("Update column list to column", () => {
|
|
179
|
+
// this would cause a column to become a child of a node that's not a column list, and should thus throw an error
|
|
180
|
+
expect(() => {
|
|
181
|
+
getEditor().updateBlock("column-list-0", {
|
|
182
|
+
type: "column",
|
|
183
|
+
children: [
|
|
184
|
+
{
|
|
185
|
+
type: "paragraph",
|
|
186
|
+
content: "Inserted Column Paragraph",
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
});
|
|
190
|
+
}).toThrow();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("Update column list to paragraph", () => {
|
|
194
|
+
// this would cause columns to become children of a paragraph, and should thus throw an error
|
|
195
|
+
expect(() => {
|
|
196
|
+
getEditor().updateBlock("column-list-0", {
|
|
197
|
+
type: "paragraph",
|
|
198
|
+
content: "Inserted Column Paragraph",
|
|
199
|
+
});
|
|
200
|
+
}).toThrow();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// TODO: this should throw, but currently doesn't, probably because of the fitting algorithm
|
|
204
|
+
it.skip("Update column to paragraph", () => {
|
|
205
|
+
expect(() => {
|
|
206
|
+
getEditor().updateBlock("column-0", {
|
|
207
|
+
type: "paragraph",
|
|
208
|
+
content: "Inserted Column Paragraph",
|
|
209
|
+
});
|
|
210
|
+
}).toThrow();
|
|
211
|
+
});
|
|
212
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<div class="bn-block-column-list" data-node-type="columnList" data-id="1" style="display: flex;"><div class="bn-block-column" data-node-type="column" data-id="2" data-width="1" style="flex-grow: 1;"><p>Column Paragraph 0</p><p>Column Paragraph 1</p></div><div class="bn-block-column" data-node-type="column" data-id="5" data-width="1" style="flex-grow: 1;"><p>Column Paragraph 2</p><p>Column Paragraph 3</p></div></div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-column-list" data-node-type="columnList" data-id="1" style="display: flex;"><div class="bn-block-column" data-node-type="column" data-id="2" data-width="1" style="flex-grow: 1;"><div class="bn-block-outer" data-node-type="blockOuter" data-id="3"><div class="bn-block" data-node-type="blockContainer" data-id="3"><div class="bn-block-content" data-content-type="paragraph"><p class="bn-inline-content">Column Paragraph 0</p></div></div></div><div class="bn-block-outer" data-node-type="blockOuter" data-id="4"><div class="bn-block" data-node-type="blockContainer" data-id="4"><div class="bn-block-content" data-content-type="paragraph"><p class="bn-inline-content">Column Paragraph 1</p></div></div></div></div><div class="bn-block-column" data-node-type="column" data-id="5" data-width="1" style="flex-grow: 1;"><div class="bn-block-outer" data-node-type="blockOuter" data-id="6"><div class="bn-block" data-node-type="blockContainer" data-id="6"><div class="bn-block-content" data-content-type="paragraph"><p class="bn-inline-content">Column Paragraph 2</p></div></div></div><div class="bn-block-outer" data-node-type="blockOuter" data-id="7"><div class="bn-block" data-node-type="blockContainer" data-id="7"><div class="bn-block-content" data-content-type="paragraph"><p class="bn-inline-content">Column Paragraph 3</p></div></div></div></div></div></div>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`Test BlockNote-Prosemirror conversion > Case: multi-column-schema > Convert multi-column to/from prosemirror 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"attrs": {
|
|
6
|
+
"id": "1",
|
|
7
|
+
},
|
|
8
|
+
"content": [
|
|
9
|
+
{
|
|
10
|
+
"attrs": {
|
|
11
|
+
"id": "2",
|
|
12
|
+
"width": 1,
|
|
13
|
+
},
|
|
14
|
+
"content": [
|
|
15
|
+
{
|
|
16
|
+
"attrs": {
|
|
17
|
+
"backgroundColor": "default",
|
|
18
|
+
"id": "3",
|
|
19
|
+
"textColor": "default",
|
|
20
|
+
},
|
|
21
|
+
"content": [
|
|
22
|
+
{
|
|
23
|
+
"attrs": {
|
|
24
|
+
"textAlignment": "left",
|
|
25
|
+
},
|
|
26
|
+
"content": [
|
|
27
|
+
{
|
|
28
|
+
"text": "Column Paragraph 0",
|
|
29
|
+
"type": "text",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
"type": "paragraph",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
"type": "blockContainer",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"attrs": {
|
|
39
|
+
"backgroundColor": "default",
|
|
40
|
+
"id": "4",
|
|
41
|
+
"textColor": "default",
|
|
42
|
+
},
|
|
43
|
+
"content": [
|
|
44
|
+
{
|
|
45
|
+
"attrs": {
|
|
46
|
+
"textAlignment": "left",
|
|
47
|
+
},
|
|
48
|
+
"content": [
|
|
49
|
+
{
|
|
50
|
+
"text": "Column Paragraph 1",
|
|
51
|
+
"type": "text",
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
"type": "paragraph",
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
"type": "blockContainer",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
"type": "column",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"attrs": {
|
|
64
|
+
"id": "5",
|
|
65
|
+
"width": 1,
|
|
66
|
+
},
|
|
67
|
+
"content": [
|
|
68
|
+
{
|
|
69
|
+
"attrs": {
|
|
70
|
+
"backgroundColor": "default",
|
|
71
|
+
"id": "6",
|
|
72
|
+
"textColor": "default",
|
|
73
|
+
},
|
|
74
|
+
"content": [
|
|
75
|
+
{
|
|
76
|
+
"attrs": {
|
|
77
|
+
"textAlignment": "left",
|
|
78
|
+
},
|
|
79
|
+
"content": [
|
|
80
|
+
{
|
|
81
|
+
"text": "Column Paragraph 2",
|
|
82
|
+
"type": "text",
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
"type": "paragraph",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
"type": "blockContainer",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"attrs": {
|
|
92
|
+
"backgroundColor": "default",
|
|
93
|
+
"id": "7",
|
|
94
|
+
"textColor": "default",
|
|
95
|
+
},
|
|
96
|
+
"content": [
|
|
97
|
+
{
|
|
98
|
+
"attrs": {
|
|
99
|
+
"textAlignment": "left",
|
|
100
|
+
},
|
|
101
|
+
"content": [
|
|
102
|
+
{
|
|
103
|
+
"text": "Column Paragraph 3",
|
|
104
|
+
"type": "text",
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
"type": "paragraph",
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
"type": "blockContainer",
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
"type": "column",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
"type": "columnList",
|
|
117
|
+
}
|
|
118
|
+
`;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
BlockNoteEditor,
|
|
5
|
+
BlockSchema,
|
|
6
|
+
InlineContentSchema,
|
|
7
|
+
PartialBlock,
|
|
8
|
+
StyleSchema,
|
|
9
|
+
addIdsToBlocks,
|
|
10
|
+
createExternalHTMLExporter,
|
|
11
|
+
createInternalHTMLSerializer,
|
|
12
|
+
partialBlocksToBlocksForTesting,
|
|
13
|
+
} from "@blocknote/core";
|
|
14
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
15
|
+
|
|
16
|
+
import { multiColumnSchemaTestCases } from "./testCases.js";
|
|
17
|
+
|
|
18
|
+
// TODO: code same from @blocknote/core, maybe create separate test util package
|
|
19
|
+
async function convertToHTMLAndCompareSnapshots<
|
|
20
|
+
B extends BlockSchema,
|
|
21
|
+
I extends InlineContentSchema,
|
|
22
|
+
S extends StyleSchema
|
|
23
|
+
>(
|
|
24
|
+
editor: BlockNoteEditor<B, I, S>,
|
|
25
|
+
blocks: PartialBlock<B, I, S>[],
|
|
26
|
+
snapshotDirectory: string,
|
|
27
|
+
snapshotName: string
|
|
28
|
+
) {
|
|
29
|
+
addIdsToBlocks(blocks);
|
|
30
|
+
const serializer = createInternalHTMLSerializer(editor.pmSchema, editor);
|
|
31
|
+
const internalHTML = serializer.serializeBlocks(blocks, {});
|
|
32
|
+
const internalHTMLSnapshotPath =
|
|
33
|
+
"./__snapshots__/" +
|
|
34
|
+
snapshotDirectory +
|
|
35
|
+
"/" +
|
|
36
|
+
snapshotName +
|
|
37
|
+
"/internal.html";
|
|
38
|
+
expect(internalHTML).toMatchFileSnapshot(internalHTMLSnapshotPath);
|
|
39
|
+
|
|
40
|
+
// turn the internalHTML back into blocks, and make sure no data was lost
|
|
41
|
+
const fullBlocks = partialBlocksToBlocksForTesting(editor.schema, blocks);
|
|
42
|
+
const parsed = await editor.tryParseHTMLToBlocks(internalHTML);
|
|
43
|
+
|
|
44
|
+
expect(parsed).toStrictEqual(fullBlocks);
|
|
45
|
+
|
|
46
|
+
// Create the "external" HTML, which is a cleaned up HTML representation, but lossy
|
|
47
|
+
const exporter = createExternalHTMLExporter(editor.pmSchema, editor);
|
|
48
|
+
const externalHTML = exporter.exportBlocks(blocks, {});
|
|
49
|
+
const externalHTMLSnapshotPath =
|
|
50
|
+
"./__snapshots__/" +
|
|
51
|
+
snapshotDirectory +
|
|
52
|
+
"/" +
|
|
53
|
+
snapshotName +
|
|
54
|
+
"/external.html";
|
|
55
|
+
expect(externalHTML).toMatchFileSnapshot(externalHTMLSnapshotPath);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const testCases = [multiColumnSchemaTestCases];
|
|
59
|
+
|
|
60
|
+
describe("Test multi-column HTML conversion", () => {
|
|
61
|
+
for (const testCase of testCases) {
|
|
62
|
+
describe("Case: " + testCase.name, () => {
|
|
63
|
+
let editor: BlockNoteEditor<any, any, any>;
|
|
64
|
+
const div = document.createElement("div");
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
editor = testCase.createEditor();
|
|
67
|
+
|
|
68
|
+
// Note that we don't necessarily need to mount a root
|
|
69
|
+
// Currently, we do mount to a root so that it reflects the "production" use-case more closely.
|
|
70
|
+
|
|
71
|
+
// However, it would be nice to increased converage and share the same set of tests for these cases:
|
|
72
|
+
// - does render to a root
|
|
73
|
+
// - does not render to a root
|
|
74
|
+
// - runs in server (jsdom) environment using server-util
|
|
75
|
+
editor.mount(div);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
afterEach(() => {
|
|
79
|
+
editor.mount(undefined);
|
|
80
|
+
editor._tiptapEditor.destroy();
|
|
81
|
+
editor = undefined as any;
|
|
82
|
+
|
|
83
|
+
delete (window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS;
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
for (const document of testCase.documents) {
|
|
87
|
+
// eslint-disable-next-line no-loop-func
|
|
88
|
+
it("Convert " + document.name + " to HTML", async () => {
|
|
89
|
+
const nameSplit = document.name.split("/");
|
|
90
|
+
await convertToHTMLAndCompareSnapshots(
|
|
91
|
+
editor,
|
|
92
|
+
document.blocks,
|
|
93
|
+
nameSplit[0],
|
|
94
|
+
nameSplit[1]
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|