@platejs/ai 51.1.1 → 51.1.2

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.
@@ -167,11 +167,11 @@ var createPromptFromConfig = (config, params) => {
167
167
  const { isBlockSelecting, isSelecting: isSelecting3 } = params;
168
168
  if (isBlockSelecting && config.blockSelecting) {
169
169
  return config.blockSelecting ?? config.default;
170
- } else if (isSelecting3 && config.selecting) {
170
+ }
171
+ if (isSelecting3 && config.selecting) {
171
172
  return config.selecting ?? config.default;
172
- } else {
173
- return config.default;
174
173
  }
174
+ return config.default;
175
175
  };
176
176
  var getEditorPrompt = (editor, {
177
177
  prompt = ""
@@ -234,7 +234,7 @@ function findTextRangeInBlock({
234
234
  let matchEnd = matchStart >= 0 ? matchStart + findText.length : -1;
235
235
  if (matchStart === -1) {
236
236
  const maxDist = maxAllowedDistance(findText.length);
237
- let bestMatch = { distance: Infinity, end: -1, start: -1 };
237
+ let bestMatch = { distance: Number.POSITIVE_INFINITY, end: -1, start: -1 };
238
238
  for (let i = 0; i <= fullText.length - findText.length; i++) {
239
239
  for (let lenOffset = -maxDist; lenOffset <= maxDist; lenOffset++) {
240
240
  const len = findText.length + lenOffset;
@@ -264,7 +264,6 @@ function findTextRangeInBlock({
264
264
  }
265
265
  if (matchStart === -1) return null;
266
266
  const findPoint = (charOffset, isEnd = false) => {
267
- const accumulated = 0;
268
267
  if (!isEnd) {
269
268
  for (const segment of textSegments) {
270
269
  if (charOffset === segment.offset) {
@@ -444,7 +443,7 @@ var applyAISuggestions = (editor, content) => {
444
443
  at: path
445
444
  });
446
445
  }
447
- if (isSameString && isSameSuggestion && node.id == diffNode.id) {
446
+ if (isSameString && isSameSuggestion && node.id === diffNode.id) {
448
447
  return;
449
448
  }
450
449
  editor.tf.replaceNodes(diffNode, {
@@ -468,64 +467,57 @@ var applyAISuggestions = (editor, content) => {
468
467
  return;
469
468
  }
470
469
  };
471
- var withProps = (diffNodes, chatNodes) => {
472
- return diffNodes.map((node, index) => {
473
- if (!import_platejs8.ElementApi.isElement(node)) return node;
474
- const originalNode = chatNodes?.[index];
470
+ var withProps = (diffNodes, chatNodes) => diffNodes.map((node, index) => {
471
+ if (!import_platejs8.ElementApi.isElement(node)) return node;
472
+ const originalNode = chatNodes?.[index];
473
+ return {
474
+ ...node,
475
+ ...originalNode ?? { id: (0, import_platejs8.nanoid)() },
476
+ children: node.children
477
+ };
478
+ });
479
+ var withTransient = (diffNodes) => diffNodes.map((node) => {
480
+ if (import_platejs8.TextApi.isText(node)) {
475
481
  return {
476
482
  ...node,
477
- ...originalNode ?? { id: (0, import_platejs8.nanoid)() },
478
- children: node.children
483
+ [(0, import_suggestion3.getTransientSuggestionKey)()]: true
479
484
  };
480
- });
481
- };
482
- var withTransient = (diffNodes) => {
483
- return diffNodes.map((node) => {
484
- if (import_platejs8.TextApi.isText(node)) {
485
- return {
486
- ...node,
487
- [(0, import_suggestion3.getTransientSuggestionKey)()]: true
488
- };
489
- } else {
485
+ }
486
+ return {
487
+ ...node,
488
+ children: withTransient(node.children),
489
+ [(0, import_suggestion3.getTransientSuggestionKey)()]: true
490
+ };
491
+ });
492
+ var withoutSuggestionAndComments = (nodes) => nodes.map((node) => {
493
+ if (import_platejs8.TextApi.isText(node)) {
494
+ if (node[import_platejs8.KEYS.suggestion] || node[import_platejs8.KEYS.comment]) {
490
495
  return {
491
- ...node,
492
- children: withTransient(node.children),
493
- [(0, import_suggestion3.getTransientSuggestionKey)()]: true
496
+ text: node.text
494
497
  };
495
498
  }
496
- });
497
- };
498
- var withoutSuggestionAndComments = (nodes) => {
499
- return nodes.map((node) => {
500
- if (import_platejs8.TextApi.isText(node)) {
501
- if (node[import_platejs8.KEYS.suggestion] || node[import_platejs8.KEYS.comment]) {
502
- return {
503
- text: node.text
504
- };
505
- }
506
- return node;
507
- }
508
- if (import_platejs8.ElementApi.isElement(node)) {
509
- if (node[import_platejs8.KEYS.suggestion]) {
510
- const nodeWithoutSuggestion = {};
511
- Object.keys(node).forEach((key) => {
512
- if (key !== import_platejs8.KEYS.suggestion && !key.startsWith(import_platejs8.KEYS.suggestion)) {
513
- nodeWithoutSuggestion[key] = node[key];
514
- }
515
- });
516
- return {
517
- ...nodeWithoutSuggestion,
518
- children: withoutSuggestionAndComments(node.children)
519
- };
520
- }
499
+ return node;
500
+ }
501
+ if (import_platejs8.ElementApi.isElement(node)) {
502
+ if (node[import_platejs8.KEYS.suggestion]) {
503
+ const nodeWithoutSuggestion = {};
504
+ Object.keys(node).forEach((key) => {
505
+ if (key !== import_platejs8.KEYS.suggestion && !key.startsWith(import_platejs8.KEYS.suggestion)) {
506
+ nodeWithoutSuggestion[key] = node[key];
507
+ }
508
+ });
521
509
  return {
522
- ...node,
510
+ ...nodeWithoutSuggestion,
523
511
  children: withoutSuggestionAndComments(node.children)
524
512
  };
525
513
  }
526
- return node;
527
- });
528
- };
514
+ return {
515
+ ...node,
516
+ children: withoutSuggestionAndComments(node.children)
517
+ };
518
+ }
519
+ return node;
520
+ });
529
521
  var getDiffNodes = (editor, aiContent) => {
530
522
  const chatNodes = withoutSuggestionAndComments(
531
523
  editor.getOption(AIChatPlugin, "chatNodes")
@@ -877,7 +869,7 @@ var withAIChat = ({
877
869
  api,
878
870
  editor,
879
871
  getOptions,
880
- tf: { apply, insertText, normalizeNode },
872
+ tf: { insertText, normalizeNode },
881
873
  type
882
874
  }) => {
883
875
  const tf = editor.getTransforms(AIPlugin);
@@ -952,63 +944,61 @@ var AIChatPlugin = (0, import_react13.createTPlatePlugin)({
952
944
  trigger: " ",
953
945
  triggerPreviousCharPattern: /^\s?$/
954
946
  }
955
- }).overrideEditor(withAIChat).extendApi(({ editor, getOption, getOptions, setOption, type }) => {
956
- return {
957
- reset: (0, import_platejs15.bindFirst)(resetAIChat, editor),
958
- submit: (0, import_platejs15.bindFirst)(submitAIChat, editor),
959
- node: (options = {}) => {
960
- const { anchor = false, streaming = false, ...rest } = options;
961
- if (anchor) {
962
- return editor.api.node({
963
- at: [],
964
- match: (n) => import_platejs15.ElementApi.isElement(n) && n.type === type,
965
- ...rest
966
- });
967
- }
968
- if (streaming) {
969
- if (!getOption("streaming")) return;
970
- const path = getOption("_blockPath");
971
- if (!path) return;
972
- return editor.api.node({
973
- at: path,
974
- mode: "lowest",
975
- reverse: true,
976
- match: (t) => !!t[(0, import_platejs15.getPluginType)(editor, import_platejs15.KEYS.ai)],
977
- ...rest
978
- });
979
- }
947
+ }).overrideEditor(withAIChat).extendApi(({ editor, getOption, getOptions, setOption, type }) => ({
948
+ reset: (0, import_platejs15.bindFirst)(resetAIChat, editor),
949
+ submit: (0, import_platejs15.bindFirst)(submitAIChat, editor),
950
+ node: (options = {}) => {
951
+ const { anchor = false, streaming = false, ...rest } = options;
952
+ if (anchor) {
980
953
  return editor.api.node({
981
- match: (n) => n[(0, import_platejs15.getPluginType)(editor, import_platejs15.KEYS.ai)],
954
+ at: [],
955
+ match: (n) => import_platejs15.ElementApi.isElement(n) && n.type === type,
982
956
  ...rest
983
957
  });
984
- },
985
- reload: () => {
986
- const { chat, chatNodes, chatSelection } = getOptions();
987
- editor.getTransforms(AIPlugin).ai.undo();
988
- if (chatSelection) {
989
- editor.tf.setSelection(chatSelection);
990
- } else {
991
- editor.getApi(import_react12.BlockSelectionPlugin).blockSelection.set(chatNodes.map((node) => node.id));
992
- }
993
- const blocks = editor.getApi(import_react12.BlockSelectionPlugin).blockSelection.getNodes();
994
- const selection = blocks.length > 0 ? editor.api.nodesRange(blocks) : editor.selection;
995
- const ctx = {
996
- children: editor.children,
997
- selection: selection ?? null,
998
- toolName: getOption("toolName")
999
- };
1000
- void chat.regenerate?.({
1001
- body: {
1002
- ctx
1003
- }
958
+ }
959
+ if (streaming) {
960
+ if (!getOption("streaming")) return;
961
+ const path = getOption("_blockPath");
962
+ if (!path) return;
963
+ return editor.api.node({
964
+ at: path,
965
+ mode: "lowest",
966
+ reverse: true,
967
+ match: (t) => !!t[(0, import_platejs15.getPluginType)(editor, import_platejs15.KEYS.ai)],
968
+ ...rest
1004
969
  });
1005
- },
1006
- stop: () => {
1007
- setOption("streaming", false);
1008
- getOptions().chat.stop?.();
1009
970
  }
1010
- };
1011
- }).extendApi(({ api, editor, getOptions, setOption, tf, type }) => ({
971
+ return editor.api.node({
972
+ match: (n) => n[(0, import_platejs15.getPluginType)(editor, import_platejs15.KEYS.ai)],
973
+ ...rest
974
+ });
975
+ },
976
+ reload: () => {
977
+ const { chat, chatNodes, chatSelection } = getOptions();
978
+ editor.getTransforms(AIPlugin).ai.undo();
979
+ if (chatSelection) {
980
+ editor.tf.setSelection(chatSelection);
981
+ } else {
982
+ editor.getApi(import_react12.BlockSelectionPlugin).blockSelection.set(chatNodes.map((node) => node.id));
983
+ }
984
+ const blocks = editor.getApi(import_react12.BlockSelectionPlugin).blockSelection.getNodes();
985
+ const selection = blocks.length > 0 ? editor.api.nodesRange(blocks) : editor.selection;
986
+ const ctx = {
987
+ children: editor.children,
988
+ selection: selection ?? null,
989
+ toolName: getOption("toolName")
990
+ };
991
+ void chat.regenerate?.({
992
+ body: {
993
+ ctx
994
+ }
995
+ });
996
+ },
997
+ stop: () => {
998
+ setOption("streaming", false);
999
+ getOptions().chat.stop?.();
1000
+ }
1001
+ })).extendApi(({ api, editor, getOptions, setOption, tf }) => ({
1012
1002
  hide: ({
1013
1003
  focus = true,
1014
1004
  undo = true
@@ -1024,7 +1014,7 @@ var AIChatPlugin = (0, import_react13.createTPlatePlugin)({
1024
1014
  }
1025
1015
  const lastBatch = editor.history.undos.at(-1);
1026
1016
  if (lastBatch?.ai) {
1027
- delete lastBatch.ai;
1017
+ lastBatch.ai = void 0;
1028
1018
  }
1029
1019
  tf.aiChat.removeAnchor();
1030
1020
  },
@@ -1048,12 +1038,10 @@ var import_react15 = require("platejs/react");
1048
1038
  var useAIChatEditor = (editor, content, { parser } = {}) => {
1049
1039
  const { setOption } = (0, import_react15.useEditorPlugin)(AIChatPlugin);
1050
1040
  editor.children = (0, import_react14.useMemo)(
1051
- () => {
1052
- return editor.getApi(import_markdown3.MarkdownPlugin).markdown.deserialize(content, {
1053
- memoize: true,
1054
- parser
1055
- });
1056
- },
1041
+ () => editor.getApi(import_markdown3.MarkdownPlugin).markdown.deserialize(content, {
1042
+ memoize: true,
1043
+ parser
1044
+ }),
1057
1045
  // eslint-disable-next-line react-hooks/exhaustive-deps
1058
1046
  [content]
1059
1047
  );
@@ -1114,7 +1102,6 @@ var import_react18 = require("react");
1114
1102
  var import_react19 = require("@platejs/selection/react");
1115
1103
  var import_react20 = require("platejs/react");
1116
1104
  var useEditorChat = ({
1117
- chat,
1118
1105
  onOpenBlockSelection,
1119
1106
  onOpenChange,
1120
1107
  onOpenCursor,
@@ -1150,9 +1137,7 @@ var useEditorChat = ({
1150
1137
 
1151
1138
  // src/react/ai-chat/streaming/streamDeserializeInlineMd.ts
1152
1139
  var import_markdown4 = require("@platejs/markdown");
1153
- var streamDeserializeInlineMd = (editor, text, options) => {
1154
- return editor.getApi(import_markdown4.MarkdownPlugin).markdown.deserializeInline(text, options);
1155
- };
1140
+ var streamDeserializeInlineMd = (editor, text, options) => editor.getApi(import_markdown4.MarkdownPlugin).markdown.deserializeInline(text, options);
1156
1141
 
1157
1142
  // src/react/ai-chat/streaming/streamDeserializeMd.ts
1158
1143
  var import_markdown5 = require("@platejs/markdown");
@@ -1165,9 +1150,8 @@ var getChunkTrimmed = (chunk, {
1165
1150
  const str = direction === "right" ? chunk.trimEnd() : chunk.trimStart();
1166
1151
  if (direction === "right") {
1167
1152
  return chunk.slice(str.length);
1168
- } else {
1169
- return chunk.slice(0, chunk.length - str.length);
1170
1153
  }
1154
+ return chunk.slice(0, chunk.length - str.length);
1171
1155
  };
1172
1156
  function isCompleteCodeBlock(str) {
1173
1157
  const trimmed = str.trim();
@@ -1199,13 +1183,12 @@ var getListNode = (editor, node) => {
1199
1183
  })?.[0];
1200
1184
  if (previousNode?.listStyleType && previousNode?.listStart) {
1201
1185
  return node;
1202
- } else {
1203
- if (node.listStart === 1) return node;
1204
- return {
1205
- ...node,
1206
- listRestartPolite: node.listStart
1207
- };
1208
1186
  }
1187
+ if (node.listStart === 1) return node;
1188
+ return {
1189
+ ...node,
1190
+ listRestartPolite: node.listStart
1191
+ };
1209
1192
  }
1210
1193
  return node;
1211
1194
  };
@@ -1224,23 +1207,20 @@ var isSameNode = (editor, node1, node2) => {
1224
1207
 
1225
1208
  // src/react/ai-chat/streaming/utils/nodesWithProps.ts
1226
1209
  var import_platejs18 = require("platejs");
1227
- var nodesWithProps = (editor, nodes, options) => {
1228
- return nodes.map((node) => {
1229
- if (import_platejs18.ElementApi.isElement(node)) {
1230
- return {
1231
- ...getListNode(editor, node),
1232
- ...options.elementProps,
1233
- children: nodesWithProps(editor, node.children, options)
1234
- };
1235
- } else {
1236
- return {
1237
- ...options.textProps,
1238
- ...node,
1239
- text: node.text
1240
- };
1241
- }
1242
- });
1243
- };
1210
+ var nodesWithProps = (editor, nodes, options) => nodes.map((node) => {
1211
+ if (import_platejs18.ElementApi.isElement(node)) {
1212
+ return {
1213
+ ...getListNode(editor, node),
1214
+ ...options.elementProps,
1215
+ children: nodesWithProps(editor, node.children, options)
1216
+ };
1217
+ }
1218
+ return {
1219
+ ...options.textProps,
1220
+ ...node,
1221
+ text: node.text
1222
+ };
1223
+ });
1244
1224
 
1245
1225
  // src/react/ai-chat/streaming/streamDeserializeMd.ts
1246
1226
  var statMdxTagRegex = /<([A-Za-z][A-Za-z0-9._:-]*)(?:\s[^>]*?)?(?<!\/)>/;
@@ -1300,23 +1280,21 @@ var withoutDeserializeInMdx = (editor, input) => {
1300
1280
  if (isMdxEnd) {
1301
1281
  editor.setOption(AIChatPlugin, "_mdxName", null);
1302
1282
  return false;
1303
- } else {
1304
- return [
1305
- {
1306
- children: [
1307
- {
1308
- text: input
1309
- }
1310
- ],
1311
- type: (0, import_platejs19.getPluginType)(editor, import_platejs19.KEYS.p)
1312
- }
1313
- ];
1314
- }
1315
- } else {
1316
- const newMdxName = statMdxTagRegex.exec(input)?.[1];
1317
- if (input.startsWith(`<${newMdxName}`)) {
1318
- editor.setOption(AIChatPlugin, "_mdxName", newMdxName ?? null);
1319
1283
  }
1284
+ return [
1285
+ {
1286
+ children: [
1287
+ {
1288
+ text: input
1289
+ }
1290
+ ],
1291
+ type: (0, import_platejs19.getPluginType)(editor, import_platejs19.KEYS.p)
1292
+ }
1293
+ ];
1294
+ }
1295
+ const newMdxName = statMdxTagRegex.exec(input)?.[1];
1296
+ if (input.startsWith(`<${newMdxName}`)) {
1297
+ editor.setOption(AIChatPlugin, "_mdxName", newMdxName ?? null);
1320
1298
  }
1321
1299
  };
1322
1300
 
@@ -1539,9 +1517,7 @@ var getCurrentBlockPath = (editor) => {
1539
1517
  return import_platejs21.PathApi.previous(anchorNode[1]);
1540
1518
  }
1541
1519
  };
1542
- const getFocusPath = (editor2) => {
1543
- return editor2.selection?.focus.path.slice(0, 1);
1544
- };
1520
+ const getFocusPath = (editor2) => editor2.selection?.focus.path.slice(0, 1);
1545
1521
  const path = getAnchorPreviousPath(editor) ?? getFocusPath(editor) ?? [0];
1546
1522
  const entry = editor.api.node(path);
1547
1523
  if (entry && (entry[0].type === (0, import_platejs21.getPluginType)(editor, import_platejs21.KEYS.columnGroup) || entry[0].type === (0, import_platejs21.getPluginType)(editor, import_platejs21.KEYS.table))) {
@@ -1568,9 +1544,7 @@ var renderCopilotBelowNodes = ({
1568
1544
  });
1569
1545
  const { renderGhostText: GhostText } = copilot.getOptions();
1570
1546
  if (!GhostText) return;
1571
- return ({ children }) => {
1572
- return /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, children, /* @__PURE__ */ import_react21.default.createElement(GhostText, null));
1573
- };
1547
+ return ({ children }) => /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, children, /* @__PURE__ */ import_react21.default.createElement(GhostText, null));
1574
1548
  };
1575
1549
 
1576
1550
  // src/react/copilot/transforms/acceptCopilot.ts
@@ -1667,21 +1641,22 @@ async function callCompletionApi({
1667
1641
  }
1668
1642
 
1669
1643
  // src/react/copilot/utils/getNextWord.ts
1644
+ var nonSpaceRegex = /^\s*(\S)/;
1645
+ var cjkCharRegex = /[\u1100-\u11FF\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF]/;
1646
+ var cjkMatchRegex = /^(\s*)([\u1100-\u11FF\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF])([\u3000-\u303F\uFF00-\uFFEF])?/;
1647
+ var nonCjkMatchRegex = /^(\s*\S+?)(?=[\s\u1100-\u11FF\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF]|$)/;
1670
1648
  var getNextWord = ({ text }) => {
1671
1649
  if (!text) return { firstWord: "", remainingText: "" };
1672
- const nonSpaceMatch = /^\s*(\S)/.exec(text);
1650
+ const nonSpaceMatch = nonSpaceRegex.exec(text);
1673
1651
  if (!nonSpaceMatch) return { firstWord: "", remainingText: "" };
1674
1652
  const firstNonSpaceChar = nonSpaceMatch[1];
1675
- const isCJKChar = /[\u1100-\u11FF\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF]/.test(
1676
- firstNonSpaceChar
1677
- );
1678
- let firstWord, remainingText;
1653
+ const isCJKChar = cjkCharRegex.test(firstNonSpaceChar);
1654
+ let firstWord;
1655
+ let remainingText;
1679
1656
  if (isCJKChar) {
1680
- const match = /^(\s*)([\u1100-\u11FF\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF])([\u3000-\u303F\uFF00-\uFFEF])?/.exec(
1681
- text
1682
- );
1657
+ const match = cjkMatchRegex.exec(text);
1683
1658
  if (match) {
1684
- const [fullMatch, spaces = "", char = "", punctuation = ""] = match;
1659
+ const [, spaces = "", char = "", punctuation = ""] = match;
1685
1660
  firstWord = spaces + char + punctuation;
1686
1661
  remainingText = text.slice(firstWord.length);
1687
1662
  } else {
@@ -1689,9 +1664,7 @@ var getNextWord = ({ text }) => {
1689
1664
  remainingText = text;
1690
1665
  }
1691
1666
  } else {
1692
- const match = /^(\s*\S+?)(?=[\s\u1100-\u11FF\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF]|$)/.exec(
1693
- text
1694
- );
1667
+ const match = nonCjkMatchRegex.exec(text);
1695
1668
  if (match) {
1696
1669
  firstWord = match[0];
1697
1670
  remainingText = text.slice(firstWord.length);