@platejs/ai 49.1.11 → 49.2.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.
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  bindFirst,
4
4
  createTSlatePlugin,
5
- KEYS
5
+ KEYS as KEYS2
6
6
  } from "platejs";
7
7
 
8
8
  // src/lib/transforms/insertAINodes.ts
@@ -24,10 +24,12 @@ var insertAINodes = (editor, nodes, {
24
24
  };
25
25
 
26
26
  // src/lib/transforms/removeAIMarks.ts
27
+ import { getPluginType, KEYS } from "platejs";
27
28
  var removeAIMarks = (editor, { at = [] } = {}) => {
28
- editor.tf.unsetNodes("ai", {
29
+ const nodeType = getPluginType(editor, KEYS.ai);
30
+ editor.tf.unsetNodes(nodeType, {
29
31
  at,
30
- match: (n) => n.ai
32
+ match: (n) => n[nodeType]
31
33
  });
32
34
  };
33
35
 
@@ -68,7 +70,7 @@ var withAIBatch = (editor, fn, {
68
70
 
69
71
  // src/lib/BaseAIPlugin.ts
70
72
  var BaseAIPlugin = createTSlatePlugin({
71
- key: KEYS.ai,
73
+ key: KEYS2.ai,
72
74
  node: { isDecoration: false, isLeaf: true }
73
75
  }).extendTransforms(({ editor }) => ({
74
76
  insertNodes: bindFirst(insertAINodes, editor),
@@ -85,143 +87,7 @@ var streamDeserializeInlineMd = (editor, text, options) => {
85
87
 
86
88
  // src/lib/streaming/streamDeserializeMd.ts
87
89
  import { MarkdownPlugin as MarkdownPlugin2 } from "@platejs/markdown";
88
- import { KEYS as KEYS3, TextApi as TextApi2 } from "platejs";
89
-
90
- // src/lib/streaming/utils/escapeInput.ts
91
- var escapeInput = (data) => {
92
- let res = data;
93
- if (data.startsWith("$$") && !data.startsWith("$$\n") && !isCompleteMath(data)) {
94
- res = data.replace("$$", String.raw`\$\$`);
95
- }
96
- return res;
97
- };
98
-
99
- // src/lib/streaming/utils/getListNode.ts
100
- var getListNode = (editor, node) => {
101
- if (node.listStyleType && node.listStart) {
102
- const previousNode = editor.api.previous({
103
- at: editor.selection?.focus
104
- })?.[0];
105
- if (previousNode?.listStyleType && previousNode?.listStart) {
106
- return node;
107
- } else {
108
- if (node.listStart === 1) return node;
109
- return {
110
- ...node,
111
- listRestartPolite: node.listStart
112
- };
113
- }
114
- }
115
- return node;
116
- };
117
-
118
- // src/lib/streaming/utils/isSameNode.ts
119
- import { isDefined, KEYS as KEYS2 } from "platejs";
120
- var LIST_STYLE_TYPE = "listStyleType";
121
- var isSameNode = (editor, node1, node2) => {
122
- if (node1.type !== editor.getType(KEYS2.p) || node2.type !== editor.getType(KEYS2.p))
123
- return node1.type === node2.type;
124
- if (isDefined(node1[LIST_STYLE_TYPE]) || isDefined(node2[LIST_STYLE_TYPE])) {
125
- return node1[LIST_STYLE_TYPE] === node2[LIST_STYLE_TYPE];
126
- }
127
- return node1.type === node2.type;
128
- };
129
-
130
- // src/lib/streaming/utils/nodesWithProps.ts
131
- import { ElementApi } from "platejs";
132
- var nodesWithProps = (editor, nodes, options) => {
133
- return nodes.map((node) => {
134
- if (ElementApi.isElement(node)) {
135
- return {
136
- ...getListNode(editor, node),
137
- ...options.elementProps,
138
- children: nodesWithProps(editor, node.children, options)
139
- };
140
- } else {
141
- return {
142
- ...options.textProps,
143
- ...node,
144
- text: node.text
145
- };
146
- }
147
- });
148
- };
149
-
150
- // src/lib/streaming/utils/utils.ts
151
- var getChunkTrimmed = (chunk, {
152
- direction = "right"
153
- } = {}) => {
154
- const str = direction === "right" ? chunk.trimEnd() : chunk.trimStart();
155
- if (direction === "right") {
156
- return chunk.slice(str.length);
157
- } else {
158
- return chunk.slice(0, chunk.length - str.length);
159
- }
160
- };
161
- function isCompleteCodeBlock(str) {
162
- const trimmed = str.trim();
163
- const startsWithCodeBlock = trimmed.startsWith("```");
164
- const endsWithCodeBlock = trimmed.endsWith("```");
165
- return startsWithCodeBlock && endsWithCodeBlock;
166
- }
167
- function isCompleteMath(str) {
168
- const trimmed = str.trim();
169
- const startsWithMath = trimmed.startsWith("$$");
170
- const endsWithMath = trimmed.endsWith("$$");
171
- return startsWithMath && endsWithMath;
172
- }
173
-
174
- // src/lib/streaming/streamDeserializeMd.ts
175
- var streamDeserializeMd = (editor, data, options) => {
176
- const input = escapeInput(data);
177
- let blocks = [];
178
- blocks = editor.getApi(MarkdownPlugin2).markdown.deserialize(input, {
179
- ...options,
180
- preserveEmptyParagraphs: false
181
- });
182
- const trimmedData = getChunkTrimmed(data);
183
- const lastBlock = blocks.at(-1);
184
- const addNewLine = trimmedData === "\n\n";
185
- const unshiftNewLine = getChunkTrimmed(data, { direction: "left" }) === "\n\n";
186
- const isCodeBlockOrTable = lastBlock?.type === "code_block" || lastBlock?.type === "table";
187
- let result = blocks;
188
- if (lastBlock && !isCodeBlockOrTable && trimmedData.length > 0 && !addNewLine) {
189
- const textNode = [
190
- {
191
- text: trimmedData
192
- }
193
- ];
194
- const lastChild = lastBlock.children.at(-1);
195
- if (lastChild && TextApi2.isText(lastChild) && Object.keys(lastChild).length === 1) {
196
- lastBlock.children.pop();
197
- const textNode2 = [
198
- {
199
- text: lastChild.text + trimmedData
200
- }
201
- ];
202
- lastBlock.children.push(...textNode2);
203
- } else {
204
- lastBlock.children.push(...textNode);
205
- }
206
- result = [...blocks.slice(0, -1), lastBlock];
207
- }
208
- if (addNewLine && !isCodeBlockOrTable) {
209
- result.push({
210
- children: [{ text: "" }],
211
- type: KEYS3.p
212
- });
213
- }
214
- if (unshiftNewLine && !isCodeBlockOrTable) {
215
- result.unshift({
216
- children: [{ text: "" }],
217
- type: KEYS3.p
218
- });
219
- }
220
- return result;
221
- };
222
-
223
- // src/lib/streaming/streamInsertChunk.ts
224
- import { NodeApi as NodeApi2, PathApi as PathApi2 } from "platejs";
90
+ import { getPluginType as getPluginType4, KEYS as KEYS13, TextApi as TextApi3 } from "platejs";
225
91
 
226
92
  // src/react/ai/AIPlugin.ts
227
93
  import { toPlatePlugin } from "platejs/react";
@@ -231,17 +97,18 @@ var AIPlugin = toPlatePlugin(BaseAIPlugin);
231
97
  import { BlockSelectionPlugin as BlockSelectionPlugin5 } from "@platejs/selection/react";
232
98
  import {
233
99
  bindFirst as bindFirst2,
234
- ElementApi as ElementApi4,
235
- KEYS as KEYS12
100
+ ElementApi as ElementApi3,
101
+ getPluginType as getPluginType3,
102
+ KEYS as KEYS11
236
103
  } from "platejs";
237
104
  import { createTPlatePlugin } from "platejs/react";
238
105
 
239
106
  // src/react/ai-chat/transforms/acceptAIChat.ts
240
- import { KEYS as KEYS4 } from "platejs";
107
+ import { KEYS as KEYS3 } from "platejs";
241
108
  import { getEditorPlugin } from "platejs/react";
242
109
  var acceptAIChat = (editor) => {
243
110
  const { tf } = getEditorPlugin(editor, AIPlugin);
244
- const api = editor.getApi({ key: KEYS4.ai });
111
+ const api = editor.getApi({ key: KEYS3.ai });
245
112
  const lastAINodePath = api.aiChat.node({ at: [], reverse: true })[1];
246
113
  withAIBatch(editor, () => {
247
114
  tf.ai.removeMarks();
@@ -259,7 +126,7 @@ var acceptAIChat = (editor) => {
259
126
  // src/react/ai-chat/transforms/insertBelowAIChat.ts
260
127
  import { BlockSelectionPlugin as BlockSelectionPlugin2 } from "@platejs/selection/react";
261
128
  import cloneDeep2 from "lodash/cloneDeep.js";
262
- import { KEYS as KEYS6, PathApi, RangeApi } from "platejs";
129
+ import { KEYS as KEYS5, PathApi, RangeApi } from "platejs";
263
130
 
264
131
  // src/react/ai-chat/transforms/replaceSelectionAIChat.ts
265
132
  import {
@@ -268,9 +135,9 @@ import {
268
135
  } from "@platejs/selection/react";
269
136
  import cloneDeep from "lodash/cloneDeep.js";
270
137
  import {
271
- KEYS as KEYS5,
138
+ KEYS as KEYS4,
272
139
  NodeApi,
273
- TextApi as TextApi3
140
+ TextApi as TextApi2
274
141
  } from "platejs";
275
142
  var createFormattedBlocks = ({
276
143
  blocks,
@@ -284,7 +151,7 @@ var createFormattedBlocks = ({
284
151
  const blockProps = NodeApi.extractProps(sourceNode);
285
152
  const textProps = NodeApi.extractProps(firstTextEntry[0]);
286
153
  const applyTextFormatting = (node) => {
287
- if (TextApi3.isText(node)) {
154
+ if (TextApi2.isText(node)) {
288
155
  return { ...textProps, ...node };
289
156
  }
290
157
  if (node.children) {
@@ -311,7 +178,7 @@ var replaceSelectionAIChat = (editor, sourceEditor, { format = "single" } = {})
311
178
  BlockSelectionPlugin,
312
179
  "isSelectingSome"
313
180
  );
314
- editor.getApi({ key: KEYS5.ai }).aiChat.hide();
181
+ editor.getApi({ key: KEYS4.ai }).aiChat.hide();
315
182
  if (!isBlockSelecting) {
316
183
  const firstBlock = editor.api.node({
317
184
  block: true,
@@ -375,7 +242,7 @@ var insertBelowAIChat = (editor, sourceEditor, { format = "single" } = {}) => {
375
242
  BlockSelectionPlugin2,
376
243
  "isSelectingSome"
377
244
  );
378
- editor.getApi({ key: KEYS6.ai }).aiChat.hide();
245
+ editor.getApi({ key: KEYS5.ai }).aiChat.hide();
379
246
  const insertBlocksAndSelect = editor.getTransforms(BlockSelectionPlugin2).blockSelection.insertBlocksAndSelect;
380
247
  if (isBlockSelecting) {
381
248
  const selectedBlocks = editor.getApi(BlockSelectionPlugin2).blockSelection.getNodes();
@@ -427,12 +294,12 @@ var insertBelowAIChat = (editor, sourceEditor, { format = "single" } = {}) => {
427
294
  };
428
295
 
429
296
  // src/react/ai-chat/transforms/removeAnchorAIChat.ts
430
- import { ElementApi as ElementApi2, KEYS as KEYS7 } from "platejs";
297
+ import { ElementApi, getPluginType as getPluginType2, KEYS as KEYS6 } from "platejs";
431
298
  var removeAnchorAIChat = (editor, options) => {
432
299
  editor.tf.withoutSaving(() => {
433
300
  editor.tf.removeNodes({
434
301
  at: [],
435
- match: (n) => ElementApi2.isElement(n) && n.type === KEYS7.aiChat,
302
+ match: (n) => ElementApi.isElement(n) && n.type === getPluginType2(editor, KEYS6.aiChat),
436
303
  ...options
437
304
  });
438
305
  });
@@ -445,7 +312,7 @@ import { BlockSelectionPlugin as BlockSelectionPlugin4 } from "@platejs/selectio
445
312
  // src/react/ai-chat/utils/getMarkdown.ts
446
313
  import { serializeMd } from "@platejs/markdown";
447
314
  import { BlockSelectionPlugin as BlockSelectionPlugin3 } from "@platejs/selection/react";
448
- import { KEYS as KEYS8 } from "platejs";
315
+ import { KEYS as KEYS7 } from "platejs";
449
316
  var getMarkdown = (editor, type) => {
450
317
  if (type === "editor") {
451
318
  return serializeMd(editor);
@@ -464,7 +331,7 @@ var getMarkdown = (editor, type) => {
464
331
  const modifiedFragment = [
465
332
  {
466
333
  children: fragment[0].children,
467
- type: KEYS8.p
334
+ type: KEYS7.p
468
335
  }
469
336
  ];
470
337
  return serializeMd(editor, { value: modifiedFragment });
@@ -526,11 +393,11 @@ var getEditorPrompt = (editor, {
526
393
  };
527
394
 
528
395
  // src/react/ai-chat/utils/resetAIChat.ts
529
- import { KEYS as KEYS9 } from "platejs";
396
+ import { KEYS as KEYS8 } from "platejs";
530
397
  import { getEditorPlugin as getEditorPlugin2 } from "platejs/react";
531
398
  var resetAIChat = (editor) => {
532
399
  const { api, getOptions } = getEditorPlugin2(editor, {
533
- key: KEYS9.aiChat
400
+ key: KEYS8.aiChat
534
401
  });
535
402
  api.aiChat.stop();
536
403
  const chat = getOptions().chat;
@@ -542,7 +409,7 @@ var resetAIChat = (editor) => {
542
409
 
543
410
  // src/react/ai-chat/utils/submitAIChat.ts
544
411
  import { isSelecting as isSelecting2 } from "@platejs/selection";
545
- import { KEYS as KEYS10 } from "platejs";
412
+ import { KEYS as KEYS9 } from "platejs";
546
413
  import { getEditorPlugin as getEditorPlugin3 } from "platejs/react";
547
414
  var submitAIChat = (editor, {
548
415
  mode,
@@ -553,7 +420,7 @@ var submitAIChat = (editor, {
553
420
  const { getOptions, setOption } = getEditorPlugin3(
554
421
  editor,
555
422
  {
556
- key: KEYS10.aiChat
423
+ key: KEYS9.aiChat
557
424
  }
558
425
  );
559
426
  const { chat, promptTemplate, systemTemplate } = getOptions();
@@ -592,7 +459,7 @@ var submitAIChat = (editor, {
592
459
  };
593
460
 
594
461
  // src/react/ai-chat/withAIChat.ts
595
- import { ElementApi as ElementApi3, KEYS as KEYS11 } from "platejs";
462
+ import { ElementApi as ElementApi2, KEYS as KEYS10 } from "platejs";
596
463
  var withAIChat = ({
597
464
  api,
598
465
  editor,
@@ -634,11 +501,11 @@ var withAIChat = ({
634
501
  },
635
502
  normalizeNode(entry) {
636
503
  const [node, path] = entry;
637
- if (node[KEYS11.ai] && !getOptions().open) {
504
+ if (node[KEYS10.ai] && !getOptions().open) {
638
505
  tf.ai.removeMarks({ at: path });
639
506
  return;
640
507
  }
641
- if (ElementApi3.isElement(node) && node.type === type && !getOptions().open) {
508
+ if (ElementApi2.isElement(node) && node.type === type && !getOptions().open) {
642
509
  editor.getTransforms(AIChatPlugin).aiChat.removeAnchor({ at: path });
643
510
  return;
644
511
  }
@@ -650,7 +517,7 @@ var withAIChat = ({
650
517
 
651
518
  // src/react/ai-chat/AIChatPlugin.ts
652
519
  var AIChatPlugin = createTPlatePlugin({
653
- key: KEYS12.aiChat,
520
+ key: KEYS11.aiChat,
654
521
  dependencies: ["ai"],
655
522
  node: {
656
523
  isElement: true
@@ -658,6 +525,7 @@ var AIChatPlugin = createTPlatePlugin({
658
525
  options: {
659
526
  _blockChunks: "",
660
527
  _blockPath: null,
528
+ _mdxName: null,
661
529
  aiEditor: null,
662
530
  chat: { messages: [] },
663
531
  experimental_lastTextId: null,
@@ -679,7 +547,7 @@ var AIChatPlugin = createTPlatePlugin({
679
547
  if (anchor) {
680
548
  return editor.api.node({
681
549
  at: [],
682
- match: (n) => ElementApi4.isElement(n) && n.type === type,
550
+ match: (n) => ElementApi3.isElement(n) && n.type === type,
683
551
  ...rest
684
552
  });
685
553
  }
@@ -691,12 +559,12 @@ var AIChatPlugin = createTPlatePlugin({
691
559
  at: path,
692
560
  mode: "lowest",
693
561
  reverse: true,
694
- match: (t) => !!t.ai,
562
+ match: (t) => !!t[getPluginType3(editor, KEYS11.ai)],
695
563
  ...rest
696
564
  });
697
565
  }
698
566
  return editor.api.node({
699
- match: (n) => n.ai,
567
+ match: (n) => n[getPluginType3(editor, KEYS11.ai)],
700
568
  ...rest
701
569
  });
702
570
  },
@@ -744,13 +612,197 @@ var AIChatPlugin = createTPlatePlugin({
744
612
  replaceSelection: bindFirst2(replaceSelectionAIChat, editor)
745
613
  }));
746
614
 
615
+ // src/lib/streaming/utils/escapeInput.ts
616
+ var escapeInput = (data) => {
617
+ let res = data;
618
+ if (data.startsWith("$$") && !data.startsWith("$$\n") && !isCompleteMath(data)) {
619
+ res = data.replace("$$", String.raw`\$\$`);
620
+ }
621
+ return res;
622
+ };
623
+
624
+ // src/lib/streaming/utils/getListNode.ts
625
+ var getListNode = (editor, node) => {
626
+ if (node.listStyleType && node.listStart) {
627
+ const previousNode = editor.api.previous({
628
+ at: editor.selection?.focus
629
+ })?.[0];
630
+ if (previousNode?.listStyleType && previousNode?.listStart) {
631
+ return node;
632
+ } else {
633
+ if (node.listStart === 1) return node;
634
+ return {
635
+ ...node,
636
+ listRestartPolite: node.listStart
637
+ };
638
+ }
639
+ }
640
+ return node;
641
+ };
642
+
643
+ // src/lib/streaming/utils/isSameNode.ts
644
+ import { isDefined, KEYS as KEYS12 } from "platejs";
645
+ var LIST_STYLE_TYPE = "listStyleType";
646
+ var isSameNode = (editor, node1, node2) => {
647
+ if (node1.type !== editor.getType(KEYS12.p) || node2.type !== editor.getType(KEYS12.p))
648
+ return node1.type === node2.type;
649
+ if (isDefined(node1[LIST_STYLE_TYPE]) || isDefined(node2[LIST_STYLE_TYPE])) {
650
+ return node1[LIST_STYLE_TYPE] === node2[LIST_STYLE_TYPE];
651
+ }
652
+ return node1.type === node2.type;
653
+ };
654
+
655
+ // src/lib/streaming/utils/nodesWithProps.ts
656
+ import { ElementApi as ElementApi4 } from "platejs";
657
+ var nodesWithProps = (editor, nodes, options) => {
658
+ return nodes.map((node) => {
659
+ if (ElementApi4.isElement(node)) {
660
+ return {
661
+ ...getListNode(editor, node),
662
+ ...options.elementProps,
663
+ children: nodesWithProps(editor, node.children, options)
664
+ };
665
+ } else {
666
+ return {
667
+ ...options.textProps,
668
+ ...node,
669
+ text: node.text
670
+ };
671
+ }
672
+ });
673
+ };
674
+
675
+ // src/lib/streaming/utils/utils.ts
676
+ var getChunkTrimmed = (chunk, {
677
+ direction = "right"
678
+ } = {}) => {
679
+ const str = direction === "right" ? chunk.trimEnd() : chunk.trimStart();
680
+ if (direction === "right") {
681
+ return chunk.slice(str.length);
682
+ } else {
683
+ return chunk.slice(0, chunk.length - str.length);
684
+ }
685
+ };
686
+ function isCompleteCodeBlock(str) {
687
+ const trimmed = str.trim();
688
+ const startsWithCodeBlock = trimmed.startsWith("```");
689
+ const endsWithCodeBlock = trimmed.endsWith("```");
690
+ return startsWithCodeBlock && endsWithCodeBlock;
691
+ }
692
+ function isCompleteMath(str) {
693
+ const trimmed = str.trim();
694
+ const startsWithMath = trimmed.startsWith("$$");
695
+ const endsWithMath = trimmed.endsWith("$$");
696
+ return startsWithMath && endsWithMath;
697
+ }
698
+
699
+ // src/lib/streaming/streamDeserializeMd.ts
700
+ var statMdxTagRegex = /<([A-Za-z][A-Za-z0-9\-_]*)>/;
701
+ var streamDeserializeMd = (editor, data, options) => {
702
+ const input = escapeInput(data);
703
+ const value = withoutDeserializeInMdx(editor, input);
704
+ if (Array.isArray(value)) return value;
705
+ let blocks = [];
706
+ blocks = editor.getApi(MarkdownPlugin2).markdown.deserialize(input, {
707
+ ...options,
708
+ preserveEmptyParagraphs: false
709
+ });
710
+ const trimmedData = getChunkTrimmed(data);
711
+ const lastBlock = blocks.at(-1);
712
+ const addNewLine = trimmedData === "\n\n";
713
+ const unshiftNewLine = getChunkTrimmed(data, { direction: "left" }) === "\n\n";
714
+ const isCodeBlockOrTable = lastBlock?.type === "code_block" || lastBlock?.type === "table";
715
+ let result = blocks;
716
+ if (lastBlock && !isCodeBlockOrTable && trimmedData.length > 0 && !addNewLine) {
717
+ const textNode = [
718
+ {
719
+ text: trimmedData
720
+ }
721
+ ];
722
+ const lastChild = lastBlock.children.at(-1);
723
+ if (lastChild && TextApi3.isText(lastChild) && Object.keys(lastChild).length === 1) {
724
+ lastBlock.children.pop();
725
+ const textNode2 = [
726
+ {
727
+ text: lastChild.text + trimmedData
728
+ }
729
+ ];
730
+ lastBlock.children.push(...textNode2);
731
+ } else {
732
+ lastBlock.children.push(...textNode);
733
+ }
734
+ result = [...blocks.slice(0, -1), lastBlock];
735
+ }
736
+ if (addNewLine && !isCodeBlockOrTable) {
737
+ result.push({
738
+ children: [{ text: "" }],
739
+ type: KEYS13.p
740
+ });
741
+ }
742
+ if (unshiftNewLine && !isCodeBlockOrTable) {
743
+ result.unshift({
744
+ children: [{ text: "" }],
745
+ type: KEYS13.p
746
+ });
747
+ }
748
+ return result;
749
+ };
750
+ var withoutDeserializeInMdx = (editor, input) => {
751
+ const mdxName = editor.getOption(AIChatPlugin, "_mdxName");
752
+ if (mdxName) {
753
+ const isMdxEnd = input.includes(`</${mdxName}>`);
754
+ if (isMdxEnd) {
755
+ editor.setOption(AIChatPlugin, "_mdxName", null);
756
+ return false;
757
+ } else {
758
+ return [
759
+ {
760
+ children: [
761
+ {
762
+ text: input
763
+ }
764
+ ],
765
+ type: getPluginType4(editor, KEYS13.p)
766
+ }
767
+ ];
768
+ }
769
+ } else {
770
+ const newMdxName = statMdxTagRegex.exec(input)?.[1];
771
+ if (input.startsWith(`<${newMdxName}`)) {
772
+ editor.setOption(AIChatPlugin, "_mdxName", newMdxName ?? null);
773
+ }
774
+ }
775
+ };
776
+
777
+ // src/lib/streaming/streamInsertChunk.ts
778
+ import {
779
+ getPluginType as getPluginType5,
780
+ KEYS as KEYS15,
781
+ NodeApi as NodeApi2,
782
+ PathApi as PathApi2
783
+ } from "platejs";
784
+
747
785
  // src/lib/streaming/streamSerializeMd.ts
748
786
  import { MarkdownPlugin as MarkdownPlugin3 } from "@platejs/markdown";
749
- import { ElementApi as ElementApi5, TextApi as TextApi4 } from "platejs";
750
- var trimEndHeading = (value) => {
751
- const headingKeys = /* @__PURE__ */ new Set(["h1", "h2", "h3", "h4", "h5", "h6"]);
787
+ import {
788
+ ElementApi as ElementApi5,
789
+ getPluginKey,
790
+ KEYS as KEYS14,
791
+ TextApi as TextApi4
792
+ } from "platejs";
793
+ var trimEndHeading = (editor, value) => {
794
+ const headingKeys = /* @__PURE__ */ new Set([
795
+ KEYS14.h1,
796
+ KEYS14.h2,
797
+ KEYS14.h3,
798
+ KEYS14.h4,
799
+ KEYS14.h5,
800
+ KEYS14.h6
801
+ ]);
752
802
  const lastBlock = value.at(-1);
753
- if (lastBlock && headingKeys.has(lastBlock.type) && ElementApi5.isElement(lastBlock)) {
803
+ if (lastBlock && headingKeys.has(
804
+ getPluginKey(editor, lastBlock.type) ?? lastBlock.type
805
+ ) && ElementApi5.isElement(lastBlock)) {
754
806
  const lastTextNode = lastBlock.children.at(-1);
755
807
  if (TextApi4.isText(lastTextNode)) {
756
808
  const trimmedText = getChunkTrimmed(lastTextNode?.text);
@@ -772,7 +824,7 @@ var trimEndHeading = (value) => {
772
824
  };
773
825
  var streamSerializeMd = (editor, options, chunk) => {
774
826
  const { value: optionsValue, ...restOptions } = options;
775
- const { value } = trimEndHeading(optionsValue ?? editor.children);
827
+ const { value } = trimEndHeading(editor, optionsValue ?? editor.children);
776
828
  let result = "";
777
829
  result = editor.getApi(MarkdownPlugin3).markdown.serialize({
778
830
  preserveEmptyParagraphs: false,
@@ -804,12 +856,20 @@ var streamSerializeMd = (editor, options, chunk) => {
804
856
  };
805
857
 
806
858
  // src/lib/streaming/streamInsertChunk.ts
859
+ var getNextPath = (path, length) => {
860
+ let result = path;
861
+ for (let i = 0; i < length; i++) {
862
+ result = PathApi2.next(result);
863
+ }
864
+ return result;
865
+ };
807
866
  function streamInsertChunk(editor, chunk, options = {}) {
808
867
  const { _blockChunks, _blockPath } = editor.getOptions(AIChatPlugin);
809
868
  if (_blockPath === null) {
810
869
  const blocks = streamDeserializeMd(editor, chunk);
811
870
  const path = getCurrentBlockPath(editor);
812
- const startInEmptyParagraph = NodeApi2.string(editor.api.node(path)[0]).length === 0;
871
+ const startBlock = editor.api.node(path)[0];
872
+ const startInEmptyParagraph = NodeApi2.string(startBlock).length === 0 && startBlock.type === getPluginType5(editor, KEYS15.p);
813
873
  if (startInEmptyParagraph) {
814
874
  editor.tf.removeNodes({ at: path });
815
875
  }
@@ -829,7 +889,7 @@ function streamInsertChunk(editor, chunk, options = {}) {
829
889
  nextBlock: true,
830
890
  select: true
831
891
  });
832
- const lastBlock = editor.api.node(nextBlocks.at(-1)) ?? editor.api.node([nextPath[0] + nextBlocks.length]);
892
+ const lastBlock = editor.api.node(getNextPath(nextPath, nextBlocks.length));
833
893
  editor.setOption(AIChatPlugin, "_blockPath", lastBlock[1]);
834
894
  const lastBlockChunks = streamSerializeMd(
835
895
  editor,
@@ -887,7 +947,7 @@ function streamInsertChunk(editor, chunk, options = {}) {
887
947
  AIChatPlugin,
888
948
  "_blockChunks",
889
949
  // one block includes multiple children
890
- tempBlocks[0].type === "code_block" || tempBlocks[0].type === "table" || tempBlocks[0].type === "equation" ? tempBlockChunks : serializedBlock2
950
+ tempBlocks[0].type === getPluginType5(editor, KEYS15.codeBlock) || tempBlocks[0].type === getPluginType5(editor, KEYS15.table) || tempBlocks[0].type === getPluginType5(editor, KEYS15.equation) ? tempBlockChunks : serializedBlock2
891
951
  );
892
952
  }
893
953
  } else {
@@ -913,7 +973,7 @@ function streamInsertChunk(editor, chunk, options = {}) {
913
973
  select: true
914
974
  });
915
975
  if (tempBlocks.length > 1) {
916
- const newEndBlockPath = [_blockPath[0] + tempBlocks.length - 1];
976
+ const newEndBlockPath = getNextPath(_blockPath, tempBlocks.length - 1);
917
977
  editor.tf.insertNodes(
918
978
  nodesWithProps(editor, tempBlocks.slice(1), options),
919
979
  {
@@ -936,11 +996,21 @@ function streamInsertChunk(editor, chunk, options = {}) {
936
996
  }
937
997
  }
938
998
  var getCurrentBlockPath = (editor) => {
939
- const anchorNode = editor.getApi(AIChatPlugin).aiChat.node({ anchor: true });
940
- if (anchorNode) {
941
- return PathApi2.previous(anchorNode[1]);
999
+ const getAnchorPreviousPath = (editor2) => {
1000
+ const anchorNode = editor2.getApi(AIChatPlugin).aiChat.node({ anchor: true });
1001
+ if (anchorNode) {
1002
+ return PathApi2.previous(anchorNode[1]);
1003
+ }
1004
+ };
1005
+ const getFocusPath = (editor2) => {
1006
+ return editor2.selection?.focus.path.slice(0, 1);
1007
+ };
1008
+ const path = getAnchorPreviousPath(editor) ?? getFocusPath(editor) ?? [0];
1009
+ const entry = editor.api.node(path);
1010
+ if (entry && (entry[0].type === getPluginType5(editor, KEYS15.columnGroup) || entry[0].type === getPluginType5(editor, KEYS15.table))) {
1011
+ return editor.api.above()?.[1] ?? path;
942
1012
  }
943
- return editor.selection?.focus.path.slice(0, 1) ?? [0];
1013
+ return path;
944
1014
  };
945
1015
  export {
946
1016
  BaseAIPlugin,