@blocknote/xl-ai 0.51.4 → 0.52.1

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 (77) hide show
  1. package/dist/blocknote-xl-ai.cjs +1 -1
  2. package/dist/blocknote-xl-ai.cjs.map +1 -1
  3. package/dist/blocknote-xl-ai.js +503 -107
  4. package/dist/blocknote-xl-ai.js.map +1 -1
  5. package/dist/locales.cjs.map +1 -1
  6. package/dist/locales.js.map +1 -1
  7. package/dist/{server-JIYg7ELG.js → server-CafGbRLa.js} +35 -31
  8. package/dist/server-CafGbRLa.js.map +1 -0
  9. package/dist/server-CxZHspeS.cjs +36 -0
  10. package/dist/server-CxZHspeS.cjs.map +1 -0
  11. package/dist/server.cjs +1 -1
  12. package/dist/server.js +1 -2
  13. package/dist/style.css +1 -1
  14. package/dist/webpack-stats.json +1 -1
  15. package/package.json +12 -25
  16. package/src/AIExtension.ts +12 -7
  17. package/src/api/formats/base-tools/createAddBlocksTool.ts +4 -4
  18. package/src/api/formats/base-tools/createUpdateBlockTool.ts +4 -4
  19. package/src/api/formats/html-blocks/columnContainerDocumentState.test.ts +1 -1
  20. package/src/api/formats/html-blocks/htmlBlocks.test.ts +6 -8
  21. package/src/api/formats/html-blocks/tools/getPartialHTML.test.ts +1 -1
  22. package/src/api/formats/html-blocks/tools/index.ts +15 -21
  23. package/src/api/formats/html-blocks/tools/rebaseTool.ts +3 -3
  24. package/src/api/formats/json/errorHandling.test.ts +8 -1
  25. package/src/api/formats/json/json.test.ts +1 -1
  26. package/src/api/formats/json/tools/index.ts +4 -4
  27. package/src/api/formats/json/tools/jsontools.test.ts +1 -1
  28. package/src/api/formats/markdown-blocks/markdownBlocks.test.ts +1 -1
  29. package/src/api/formats/markdown-blocks/tools/index.ts +9 -11
  30. package/src/api/formats/markdown-blocks/tools/rebaseTool.ts +3 -3
  31. package/src/api/formats/tests/sharedTestCases.ts +2 -3
  32. package/src/api/formats/tests/snapshotPath.ts +2 -2
  33. package/src/api/formats/tests/validateTestEnvironment.test.ts +1 -1
  34. package/src/api/promptHelpers/suffixIds.ts +1 -1
  35. package/src/api/schema/__snapshots__/schemaToJSONSchema.test.ts.snap +1 -1
  36. package/src/api/schema/schemaToJSONSchema.test.ts +3 -3
  37. package/src/api/schema/schemaToJSONSchema.ts +5 -3
  38. package/src/components/AIMenu/PromptSuggestionMenu.tsx +1 -1
  39. package/src/plugins/AgentCursorPlugin.ts +8 -1
  40. package/src/prosemirror/AttributionMarks.ts +204 -0
  41. package/src/prosemirror/__snapshots__/agent.test.ts.snap +16 -265
  42. package/src/prosemirror/__snapshots__/rebaseTool.test.ts.snap +4 -4
  43. package/src/prosemirror/agent.test.ts +8 -10
  44. package/src/prosemirror/agent.ts +1 -1
  45. package/src/prosemirror/changeset.test.ts +1 -1
  46. package/src/prosemirror/fragmentUtil.test.ts +1 -1
  47. package/src/prosemirror/rebaseTool.test.ts +8 -3
  48. package/src/server.ts +0 -1
  49. package/src/streamTool/filterNewOrUpdatedOperations.test.ts +1 -1
  50. package/src/streamTool/filterValidOperations.test.ts +1 -1
  51. package/src/streamTool/preprocess.test.ts +1 -1
  52. package/src/streamTool/toValidatedOperations.test.ts +1 -1
  53. package/src/streamTool/vercelAiSdk/clientside/ClientSideTransport.ts +8 -5
  54. package/src/streamTool/vercelAiSdk/util/appendableStream.test.ts +15 -15
  55. package/src/streamTool/vercelAiSdk/util/chatHandlers.test.ts +10 -1
  56. package/src/streamTool/vercelAiSdk/util/chatHandlers.ts +7 -7
  57. package/src/style.css +0 -19
  58. package/src/testUtil/suggestChangesTestUtil.ts +1 -1
  59. package/src/util/stream.ts +1 -1
  60. package/src/vite-env.d.ts +1 -0
  61. package/types/src/AIExtension.d.ts +4 -0
  62. package/types/src/api/formats/base-tools/createAddBlocksTool.d.ts +2 -2
  63. package/types/src/api/formats/base-tools/createUpdateBlockTool.d.ts +2 -2
  64. package/types/src/api/formats/formats.d.ts +3 -3
  65. package/types/src/api/formats/html-blocks/tools/rebaseTool.d.ts +2 -2
  66. package/types/src/api/formats/json/json.d.ts +3 -3
  67. package/types/src/api/formats/markdown-blocks/tools/rebaseTool.d.ts +2 -2
  68. package/types/src/api/schema/schemaToJSONSchema.d.ts +3 -3
  69. package/types/src/prosemirror/AttributionMarks.d.ts +15 -0
  70. package/types/src/testUtil/cases/editors/blockFormatting.d.ts +17 -17
  71. package/types/src/testUtil/cases/editors/formattingAndMentions.d.ts +17 -17
  72. package/types/src/testUtil/cases/editors/simpleEditor.d.ts +51 -51
  73. package/types/src/testUtil/cases/editors/tables.d.ts +17 -17
  74. package/types/src/testUtil/cases/schemas/mention.d.ts +17 -17
  75. package/dist/server-D-Xyj9BS.cjs +0 -36
  76. package/dist/server-D-Xyj9BS.cjs.map +0 -1
  77. package/dist/server-JIYg7ELG.js.map +0 -1
@@ -0,0 +1,204 @@
1
+ import {
2
+ BLOCK_LEVEL_SUGGESTION_GROUP,
3
+ NON_FORMATTING_MARK_GROUP,
4
+ createExtension,
5
+ } from "@blocknote/core";
6
+ import { Mark } from "@tiptap/core";
7
+ import { MarkSpec } from "prosemirror-model";
8
+
9
+ // This copies the marks from @handlewithcare/prosemirror-suggest-changes,
10
+ // but uses the Tiptap Mark API instead so we can use them in BlockNote
11
+
12
+ // The ideal solution would be to not depend on tiptap nodes / marks, but be able to use prosemirror nodes / marks directly
13
+ // this way we could directly use the exported marks from @handlewithcare/prosemirror-suggest-changes
14
+ export const SuggestionAddMark = Mark.create({
15
+ name: "insertion",
16
+ inclusive: false,
17
+ excludes: "deletion modification insertion",
18
+ // Two groups: `BLOCK_LEVEL_SUGGESTION_GROUP` lets the mark sit on block nodes
19
+ // (see core's `suggestionMarks`), so a whole block (e.g. a table row) can be
20
+ // marked as inserted in suggestion mode; `NON_FORMATTING_MARK_GROUP` lets it
21
+ // annotate text inside `"plain"` blocks (e.g. code blocks) — see core's
22
+ // `nonFormattingMarks`.
23
+ group: `${BLOCK_LEVEL_SUGGESTION_GROUP} ${NON_FORMATTING_MARK_GROUP}`,
24
+ addAttributes() {
25
+ return {
26
+ id: { default: null, validate: "number" }, // note: validate is supported in prosemirror but not in tiptap, so this doesn't actually work (considered not critical)
27
+ };
28
+ },
29
+ extendMarkSchema(extension) {
30
+ if (extension.name !== "insertion") {
31
+ return {};
32
+ }
33
+ return {
34
+ blocknoteIgnore: true,
35
+ inclusive: false,
36
+
37
+ toDOM(mark, inline) {
38
+ return [
39
+ "ins",
40
+ {
41
+ "data-id": String(mark.attrs["id"]),
42
+ "data-inline": String(inline),
43
+ ...(!inline && { style: "display: contents" }), // changed to "contents" to make this work for table rows
44
+ },
45
+ 0,
46
+ ];
47
+ },
48
+ parseDOM: [
49
+ {
50
+ tag: "ins",
51
+ getAttrs(node) {
52
+ if (!node.dataset["id"]) {
53
+ return false;
54
+ }
55
+ return {
56
+ id: parseInt(node.dataset["id"], 10),
57
+ };
58
+ },
59
+ },
60
+ ],
61
+ } satisfies MarkSpec;
62
+ },
63
+ });
64
+
65
+ export const SuggestionDeleteMark = Mark.create({
66
+ name: "deletion",
67
+ inclusive: false,
68
+ excludes: "insertion modification deletion",
69
+ group: `${BLOCK_LEVEL_SUGGESTION_GROUP} ${NON_FORMATTING_MARK_GROUP}`,
70
+ addAttributes() {
71
+ return {
72
+ id: { default: null, validate: "number" }, // note: validate is supported in prosemirror but not in tiptap
73
+ };
74
+ },
75
+ extendMarkSchema(extension) {
76
+ if (extension.name !== "deletion") {
77
+ return {};
78
+ }
79
+ return {
80
+ blocknoteIgnore: true,
81
+ inclusive: false,
82
+
83
+ // attrs: {
84
+ // id: { validate: "number" },
85
+ // },
86
+ toDOM(mark, inline) {
87
+ return [
88
+ "del",
89
+ {
90
+ "data-id": String(mark.attrs["id"]),
91
+ "data-inline": String(inline),
92
+ ...(!inline && { style: "display: contents" }), // changed to "contents" to make this work for table rows
93
+ },
94
+ 0,
95
+ ];
96
+ },
97
+ parseDOM: [
98
+ {
99
+ tag: "del",
100
+ getAttrs(node) {
101
+ if (!node.dataset["id"]) {
102
+ return false;
103
+ }
104
+ return {
105
+ id: parseInt(node.dataset["id"], 10),
106
+ };
107
+ },
108
+ },
109
+ ],
110
+ } satisfies MarkSpec;
111
+ },
112
+ });
113
+
114
+ export const SuggestionModificationMark = Mark.create({
115
+ name: "modification",
116
+ inclusive: false,
117
+ excludes: "deletion insertion",
118
+ group: `${BLOCK_LEVEL_SUGGESTION_GROUP} ${NON_FORMATTING_MARK_GROUP}`,
119
+ addAttributes() {
120
+ // note: validate is supported in prosemirror but not in tiptap
121
+ return {
122
+ id: { default: null, validate: "number" },
123
+ type: { validate: "string" },
124
+ attrName: { default: null, validate: "string|null" },
125
+ previousValue: { default: null },
126
+ newValue: { default: null },
127
+ };
128
+ },
129
+ extendMarkSchema(extension) {
130
+ if (extension.name !== "modification") {
131
+ return {};
132
+ }
133
+ return {
134
+ blocknoteIgnore: true,
135
+ inclusive: false,
136
+ // attrs: {
137
+ // id: { validate: "number" },
138
+ // type: { validate: "string" },
139
+ // attrName: { default: null, validate: "string|null" },
140
+ // previousValue: { default: null },
141
+ // newValue: { default: null },
142
+ // },
143
+ toDOM(mark, inline) {
144
+ return [
145
+ inline ? "span" : "div",
146
+ {
147
+ "data-type": "modification",
148
+ "data-id": String(mark.attrs["id"]),
149
+ "data-mod-type": mark.attrs["type"] as string,
150
+ "data-mod-prev-val": JSON.stringify(mark.attrs["previousValue"]),
151
+ // TODO: Try to serialize marks with toJSON?
152
+ "data-mod-new-val": JSON.stringify(mark.attrs["newValue"]),
153
+ },
154
+ 0,
155
+ ];
156
+ },
157
+ parseDOM: [
158
+ {
159
+ tag: "span[data-type='modification']",
160
+ getAttrs(node) {
161
+ if (!node.dataset["id"]) {
162
+ return false;
163
+ }
164
+ return {
165
+ id: parseInt(node.dataset["id"], 10),
166
+ type: node.dataset["modType"],
167
+ previousValue: node.dataset["modPrevVal"],
168
+ newValue: node.dataset["modNewVal"],
169
+ };
170
+ },
171
+ },
172
+ {
173
+ tag: "div[data-type='modification']",
174
+ getAttrs(node) {
175
+ if (!node.dataset["id"]) {
176
+ return false;
177
+ }
178
+ return {
179
+ id: parseInt(node.dataset["id"], 10),
180
+ type: node.dataset["modType"],
181
+ previousValue: node.dataset["modPrevVal"],
182
+ };
183
+ },
184
+ },
185
+ ],
186
+ } satisfies MarkSpec;
187
+ },
188
+ });
189
+
190
+ /**
191
+ * Bundles the three AI suggestion marks (`insertion` / `deletion` /
192
+ * `modification`) into a single BlockNote extension, so they can be registered
193
+ * in one line wherever they're needed (the AI extension, or a test that
194
+ * exercises suggestions). The marks opt into being allowed on block nodes via
195
+ * their `blockLevelSuggestion` option — see core's `suggestionMarks`.
196
+ */
197
+ export const AttributionMarksExtension = createExtension(() => ({
198
+ key: "aiAttributionMarks",
199
+ tiptapExtensions: [
200
+ SuggestionAddMark,
201
+ SuggestionDeleteMark,
202
+ SuggestionModificationMark,
203
+ ],
204
+ }));