prosemirror-suggestcat-plugin 0.1.8 → 0.1.11

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # prosemirror-suggestcat-plugin
2
2
 
3
- ![made by Emergence Engineering](https://emergence-engineering.com/ee-logo.svg)
3
+ [![made by Emergence Engineering](https://emergence-engineering.com/ee-logo.svg)](https://emergence-engineering.com)
4
4
 
5
5
  [**Made by Emergence-Engineering**](https://emergence-engineering.com/)
6
6
 
@@ -172,17 +172,17 @@ view.dispatch(
172
172
 
173
173
  ```ts
174
174
  export enum TaskType {
175
- Complete = "Complete",
176
- Improve = "Improve",
177
- MakeLonger = "MakeLonger",
178
- MakeShorter = "MakeShorter",
179
- Simplify = "Simplify",
180
- Explain = "Explain",
181
- ActionItems = "ActionItems",
175
+ Complete = "Complete",
176
+ Improve = "Improve",
177
+ MakeLonger = "MakeLonger",
178
+ MakeShorter = "MakeShorter",
179
+ Simplify = "Simplify",
180
+ Explain = "Explain",
181
+ ActionItems = "ActionItems",
182
182
  }
183
183
  export enum OpenAiPromptsWithParam {
184
- ChangeTone = "ChangeTone",
185
- Translate = "Translate",
184
+ ChangeTone = "ChangeTone",
185
+ Translate = "Translate",
186
186
  }
187
187
 
188
188
  export enum Status {
@@ -0,0 +1,125 @@
1
+ /* eslint-disable no-console */
2
+ import { Fragment, Slice } from "prosemirror-model";
3
+ import { Plugin } from "prosemirror-state";
4
+ import { defaultCompleteOptions } from "./defaults";
5
+ import { completeRequest, makeShorterLonger } from "./makeTaksRequest";
6
+ import { OpenAiPromptsWithoutParam, OpenAiPromptsWithParam, Status, } from "./types";
7
+ import { completePluginKey, isCompleteMeta } from "./utils";
8
+ /*
9
+ * idle - initial state, waiting for task
10
+ * new - make request in view
11
+ * streaming - update state in apply method and wait for finished
12
+ * finished - update state in apply method and wait for accepted or rejected
13
+ * accepted - insert/replace text in view and set status to done, also used for clearing an error
14
+ * rejected - set status to done
15
+ * done - used for clearing pluginState, do not use, it is just for internal state management
16
+ * error - whenever an error occurs, this field gets populated so you can display it for the user, use `accepted`* meta to clear it
17
+ */
18
+ export const completePlugin = (apiKey, options = defaultCompleteOptions) => {
19
+ let streaming = false;
20
+ return new Plugin({
21
+ key: completePluginKey,
22
+ state: {
23
+ init() {
24
+ return { status: Status.idle };
25
+ },
26
+ apply(tr, pluginState, prevState, state) {
27
+ const meta = tr.getMeta(completePluginKey);
28
+ if (pluginState.status === Status.done ||
29
+ pluginState.status === Status.rejected) {
30
+ streaming = false;
31
+ return { status: Status.idle };
32
+ }
33
+ if ((meta === null || meta === void 0 ? void 0 : meta.status) === Status.cancelled) {
34
+ return Object.assign(Object.assign(Object.assign({}, pluginState), meta), { isCancelled: true });
35
+ }
36
+ if (meta && isCompleteMeta(meta)) {
37
+ if (pluginState.type && meta.type !== pluginState.type) {
38
+ return pluginState;
39
+ }
40
+ return Object.assign(Object.assign({}, pluginState), meta);
41
+ }
42
+ return pluginState;
43
+ },
44
+ },
45
+ view() {
46
+ return {
47
+ update(view, prevState) {
48
+ const pluginState = completePluginKey.getState(view.state);
49
+ /* eslint-disable prefer-destructuring */
50
+ let tr = view.state.tr;
51
+ if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.status) === Status.new && !streaming) {
52
+ switch (pluginState.type) {
53
+ case OpenAiPromptsWithoutParam.Complete:
54
+ streaming = true;
55
+ completeRequest(pluginState, view, apiKey);
56
+ console.log("complete");
57
+ break;
58
+ case OpenAiPromptsWithoutParam.MakeLonger:
59
+ case OpenAiPromptsWithoutParam.MakeShorter:
60
+ case OpenAiPromptsWithoutParam.Improve:
61
+ case OpenAiPromptsWithoutParam.Simplify:
62
+ case OpenAiPromptsWithoutParam.Explain:
63
+ case OpenAiPromptsWithoutParam.ActionItems:
64
+ case OpenAiPromptsWithParam.Translate:
65
+ case OpenAiPromptsWithParam.ChangeTone:
66
+ streaming = true;
67
+ makeShorterLonger(pluginState.type, pluginState, view, apiKey, options.maxSelection, pluginState.params);
68
+ console.log("improve selected text");
69
+ break;
70
+ default:
71
+ break;
72
+ }
73
+ }
74
+ if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.status) === Status.accepted) {
75
+ if (pluginState.error) {
76
+ tr.setMeta(completePluginKey, {
77
+ type: pluginState.type,
78
+ status: Status.done,
79
+ });
80
+ view.dispatch(tr);
81
+ return;
82
+ }
83
+ switch (pluginState.type) {
84
+ case OpenAiPromptsWithoutParam.Complete:
85
+ tr = tr.insertText(pluginState.result || "", view.state.doc.nodeSize - 2);
86
+ tr.setMeta(completePluginKey, {
87
+ type: OpenAiPromptsWithoutParam.Complete,
88
+ status: Status.done,
89
+ });
90
+ view.dispatch(tr);
91
+ view.focus();
92
+ console.log("complete accepted V1");
93
+ break;
94
+ case OpenAiPromptsWithoutParam.MakeLonger:
95
+ case OpenAiPromptsWithoutParam.MakeShorter:
96
+ case OpenAiPromptsWithoutParam.Improve:
97
+ case OpenAiPromptsWithoutParam.Simplify:
98
+ case OpenAiPromptsWithoutParam.Explain:
99
+ case OpenAiPromptsWithoutParam.ActionItems:
100
+ case OpenAiPromptsWithParam.Translate:
101
+ case OpenAiPromptsWithParam.ChangeTone:
102
+ if (pluginState.selection && pluginState.result) {
103
+ const content = pluginState.result;
104
+ const paragraphs = content.split("\n\n");
105
+ const paragraphNodes = paragraphs.map((paragraph) => view.state.schema.node("paragraph", null, view.state.schema.text(paragraph)));
106
+ const fragment = Fragment.fromArray(paragraphNodes);
107
+ tr.selection.replace(tr, new Slice(fragment, 0, 0));
108
+ }
109
+ tr.setMeta(completePluginKey, {
110
+ type: pluginState.type,
111
+ status: Status.done,
112
+ });
113
+ view.dispatch(tr);
114
+ view.focus();
115
+ console.log("makeShorterLonger acceptedV1");
116
+ break;
117
+ default:
118
+ break;
119
+ }
120
+ }
121
+ },
122
+ };
123
+ },
124
+ });
125
+ };
@@ -0,0 +1,34 @@
1
+ import { GrammarSuggestElementClass } from "./types";
2
+ export const createUpdatePopup = (view, decoration, pos, applySuggestion, discardSuggestion) => {
3
+ const root = document.createElement("div");
4
+ root.className = "grammar-suggest-tooltip";
5
+ const { spec } = decoration;
6
+ const boundingRect = view.dom.getBoundingClientRect();
7
+ root.id = GrammarSuggestElementClass.grammarSuggestPopup;
8
+ const coords = view.coordsAtPos(pos);
9
+ const editorTopScroll = view.dom.scrollTop || 0;
10
+ const editorLeftScroll = view.dom.scrollLeft || 0;
11
+ root.style.left = `${coords.left - boundingRect.left + editorLeftScroll}px`;
12
+ root.style.top = `${coords.bottom - boundingRect.top + editorTopScroll + 5}px`;
13
+ const applyButton = document.createElement("div");
14
+ applyButton.className = "grammar-suggest-tooltip-apply";
15
+ applyButton.innerText = spec.text || spec.originalText;
16
+ console.log({ spec });
17
+ if (!spec.text) {
18
+ applyButton.style.textDecoration = "line-through";
19
+ applyButton.style.color = "red";
20
+ }
21
+ applyButton.onclick = () => {
22
+ applySuggestion(view, decoration);
23
+ };
24
+ root.appendChild(applyButton);
25
+ const discardButton = document.createElement("div");
26
+ discardButton.innerHTML =
27
+ "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'><path d='M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 10.5858L14.8284 7.75736L16.2426 9.17157L13.4142 12L16.2426 14.8284L14.8284 16.2426L12 13.4142L9.17157 16.2426L7.75736 14.8284L10.5858 12L7.75736 9.17157L9.17157 7.75736L12 10.5858Z'></path></svg>";
28
+ discardButton.className = "grammar-suggest-tooltip-discard";
29
+ discardButton.onclick = () => {
30
+ discardSuggestion(view, decoration);
31
+ };
32
+ root.appendChild(discardButton);
33
+ return root;
34
+ };
@@ -0,0 +1,125 @@
1
+ import { Decoration, DecorationSet } from "prosemirror-view";
2
+ import { TextSelection } from "prosemirror-state";
3
+ import { Mapping, StepMap } from "prosemirror-transform";
4
+ import { Fragment, Slice } from "prosemirror-model";
5
+ import { GrammarSuggestMetaType, } from "./types";
6
+ import { getChangedRegions, getTextWithNewlines, grammarSuggestPluginKey, } from "./utils";
7
+ import { getDiff, isIdentity } from "./mergeDiffs";
8
+ import { docToTextWithMapping, textPosToDocPos } from "./mapping";
9
+ export const handleUpdate = (pluginState, meta, tr) => {
10
+ // Add decorations
11
+ const { changedRegion, fix, mapping, text } = meta;
12
+ const newDecorations = getDiff(changedRegion.newText, fix.result)
13
+ .filter((i) => !isIdentity(i))
14
+ .filter((i) => i.original !== `${i.replacement}\n`)
15
+ .map(({ from, to, original, replacement }) => {
16
+ const decorationFrom = textPosToDocPos(changedRegion.start + from, mapping);
17
+ const decorationTo = textPosToDocPos(changedRegion.start + (replacement.endsWith("\n") ? to - 1 : to), mapping);
18
+ const decorationText = replacement.endsWith("\n")
19
+ ? replacement.slice(0, -1)
20
+ : replacement;
21
+ const spec = {
22
+ text: decorationText,
23
+ originalText: original,
24
+ id: {},
25
+ };
26
+ return Decoration.inline(decorationFrom, decorationTo, {
27
+ class: `grammarSuggestion ${replacement === "" ? "removalSuggestion" : ""}`,
28
+ }, spec);
29
+ });
30
+ return Object.assign(Object.assign({}, pluginState), { decorations: pluginState.decorations.add(tr.doc, newDecorations), lastText: text });
31
+ };
32
+ export const handleAccept = (pluginState, meta, tr) => {
33
+ const newDecorations = pluginState.decorations.remove(pluginState.decorations.find(0, tr.doc.nodeSize, (spec) => spec.id === meta.id));
34
+ return Object.assign(Object.assign({}, pluginState), { lastText: getTextWithNewlines(tr.doc), decorations: newDecorations.map(tr.mapping, tr.doc), popupDecoration: DecorationSet.empty });
35
+ };
36
+ export const handleDocChange = (pluginState, tr, oldState, withYjs) => {
37
+ // Do it more efficiently. There's no need to calculate the whole mapping etc.
38
+ const oldText = docToTextWithMapping(oldState.doc).text;
39
+ const { text, mapping } = docToTextWithMapping(tr.doc);
40
+ if (text === oldText)
41
+ return pluginState;
42
+ let pmMapping = tr.mapping;
43
+ if (withYjs) {
44
+ const diffStart = tr.doc.content.findDiffStart(oldState.doc.content);
45
+ const diffEnd = oldState.doc.content.findDiffEnd(tr.doc.content);
46
+ const map = diffEnd && diffStart
47
+ ? new StepMap([diffStart, diffEnd.a - diffStart, diffEnd.b - diffStart])
48
+ : new StepMap([0, 0, 0]);
49
+ pmMapping = new Mapping([map]);
50
+ }
51
+ const changedRegion = getChangedRegions(oldText, text);
52
+ const mappedDecorations = pluginState.decorations.map(pmMapping, tr.doc);
53
+ const decorationsStart = textPosToDocPos(changedRegion.start, mapping);
54
+ const decorationsEnd = textPosToDocPos(changedRegion.end, mapping);
55
+ const mappedPopupDecoration = pluginState.popupDecoration.map(pmMapping, tr.doc);
56
+ return Object.assign(Object.assign({}, pluginState), { decorations: mappedDecorations.remove(mappedDecorations.find(decorationsStart, decorationsEnd)), popupDecoration: mappedPopupDecoration.remove(mappedPopupDecoration.find(decorationsStart, decorationsEnd)) });
57
+ };
58
+ const applySuggestion = (view, decoration) => {
59
+ var _a;
60
+ const currentDecoration = (_a = grammarSuggestPluginKey
61
+ .getState(view.state)) === null || _a === void 0 ? void 0 : _a.decorations.find(0, view.state.doc.nodeSize, (spec) => spec.id === decoration.spec.id)[0];
62
+ if (!currentDecoration)
63
+ return;
64
+ const { text } = currentDecoration.spec;
65
+ const { from, to } = currentDecoration;
66
+ const meta = {
67
+ type: GrammarSuggestMetaType.acceptSuggestion,
68
+ id: decoration.spec.id,
69
+ };
70
+ const paragraphs = text.split("\n");
71
+ const paragraphNodes = paragraphs.map((paragraph) => view.state.schema.node("paragraph", null, view.state.schema.text(paragraph)));
72
+ const fragment = Fragment.fromArray(paragraphNodes);
73
+ let { tr } = view.state;
74
+ tr = tr.setSelection(TextSelection.create(view.state.doc, from, to));
75
+ tr.selection.replace(tr, new Slice(fragment, 1, 1));
76
+ tr.setMeta(grammarSuggestPluginKey, meta);
77
+ view.dispatch(tr);
78
+ };
79
+ const discardSuggestion = (view, decoration) => {
80
+ const { spec } = decoration;
81
+ const meta = {
82
+ type: GrammarSuggestMetaType.discardSuggestion,
83
+ id: spec.id,
84
+ };
85
+ const tr = view.state.tr.setMeta(grammarSuggestPluginKey, meta);
86
+ view.dispatch(tr);
87
+ };
88
+ export const handleOpenSuggestion = (pluginState, meta, tr, options) => {
89
+ const { decoration } = meta;
90
+ const spec = { id: decoration.spec.id };
91
+ return Object.assign(Object.assign({}, pluginState), { popupDecoration: DecorationSet.create(tr.doc, [
92
+ Decoration.widget(decoration.from, (view, getPos) => {
93
+ const pos = getPos();
94
+ if (!pos)
95
+ return document.createElement("div");
96
+ return options.createUpdatePopup(view, decoration, pos, applySuggestion, discardSuggestion);
97
+ }, Object.assign(Object.assign({}, spec), { stopEvent: () => true })),
98
+ ]) });
99
+ };
100
+ export const handleClick = (view, pos) => {
101
+ const pluginState = grammarSuggestPluginKey.getState(view.state);
102
+ if (!pluginState)
103
+ return false;
104
+ const { decorations } = pluginState;
105
+ const decoration = decorations.find(pos, pos)[0];
106
+ if (!decoration) {
107
+ const meta = {
108
+ type: GrammarSuggestMetaType.closeSuggestion,
109
+ };
110
+ view.dispatch(view.state.tr.setMeta(grammarSuggestPluginKey, meta));
111
+ return false;
112
+ }
113
+ const popupDecoration = pluginState.popupDecoration.find()[0];
114
+ if ((popupDecoration === null || popupDecoration === void 0 ? void 0 : popupDecoration.spec.id) === decoration.spec.id)
115
+ return false;
116
+ const meta = {
117
+ type: GrammarSuggestMetaType.openSuggestion,
118
+ decoration,
119
+ };
120
+ view.dispatch(view.state.tr.setMeta(grammarSuggestPluginKey, meta));
121
+ return false;
122
+ };
123
+ export const handleDiscardSuggestion = (pluginState, meta, tr) => {
124
+ return Object.assign(Object.assign({}, pluginState), { decorations: pluginState.decorations.remove(pluginState.decorations.find(0, tr.doc.nodeSize, (spec) => spec.id === meta.id)), popupDecoration: DecorationSet.empty });
125
+ };
package/dist/index.es.js CHANGED
@@ -1 +1 @@
1
- import{PluginKey as e,Plugin as t}from"prosemirror-state";import{Decoration as n,DecorationSet as o}from"prosemirror-view";import r from"fast-diff";import{__awaiter as s}from"tslib";import i from"lodash.debounce";import{StepMap as a,Mapping as c}from"prosemirror-transform";import{Fragment as l,Slice as d}from"prosemirror-model";var p,g,u,m,h,f,x;!function(e){e.suggestionUpdate="suggestionUpdate",e.acceptSuggestion="acceptSuggestion",e.openSuggestion="openSuggestion",e.closeSuggestion="closeSuggestion",e.discardSuggestion="discardSuggestion"}(p||(p={})),function(e){e.grammarSuggestPopup="grammar-suggest-popup"}(g||(g={})),function(e){e.Casual="Casual",e.Confident="Confident",e.Straightforward="Straightforward",e.Friendly="Friendly"}(u||(u={})),function(e){e.English="English",e.Spanish="Spanish",e.French="French",e.German="German",e.Italian="Italian",e.Portuguese="Portuguese",e.Dutch="Dutch",e.Russian="Russian",e.Chinese="Chinese",e.Korean="Korean",e.Japanese="Japanese"}(m||(m={})),function(e){e.Complete="Complete",e.Improve="Improve",e.MakeLonger="MakeLonger",e.MakeShorter="MakeShorter",e.Simplify="Simplify",e.Explain="Explain",e.ActionItems="ActionItems"}(h||(h={})),function(e){e.ChangeTone="ChangeTone",e.Translate="Translate"}(f||(f={})),function(e){e.idle="idle",e.new="new",e.streaming="streaming",e.finished="finished",e.accepted="accepted",e.cancelled="cancelled",e.rejected="rejected",e.done="done",e.error="error"}(x||(x={}));const v=new e("completePlugin"),y=new e("grammarSuggestPlugin"),S=e=>{let t="";return e.descendants(((e,n)=>{e.isText&&(t+=`${e.text}\n`)})),t},w=(e,t)=>{if(e===t)return{start:e.length,end:e.length,oldStart:e.length,oldEnd:e.length,oldText:"",newText:""};const n=r(e,t),o=n[0],s=o[0]===r.EQUAL?o[1].length-1:0,i=((e,t)=>{if(t[t.length-1][0]!==r.EQUAL)return e.length;const n=t.slice(0,t.length-1);let o=0;for(const e of n){const[t,n]=e;t===r.EQUAL&&(o+=n.length),t===r.DELETE&&(o+=n.length)}return o})(e,n),a=e.lastIndexOf("\n",s),c=e.indexOf("\n",i),l=-1===a?0:a+1,d=-1===c?e.length:c,p=e.slice(l,d),g=t.slice(l,t.length-(e.length-d));return{start:l,end:l+g.length,oldStart:l,oldEnd:d,oldText:p,newText:g}},b=[{docPos:1,textPos:0}],j=e=>{let t="";const n=[];return e.descendants(((e,o)=>{e.isText&&(n.push({docPos:o,textPos:t.length}),t+=`${e.text}\n`)})),{text:t,mapping:n.length?n:b}},C=(e,t)=>{for(let n=0;n<t.length;n++)if(e>=t[n].textPos&&(void 0===t[n+1]||e<t[n+1].textPos))return t[n].docPos+(e-t[n].textPos);throw new Error("textPositionToDocumentPosition: textPos not found in mapping")},T=(e,t)=>s(void 0,void 0,void 0,(function*(){const n=[...t.split("\n")];return fetch("https://prosemirror-ai-plugin.web.app/api/suggestion",{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({model:"gpt-3.5-turbo",modelParams:{input:n}})}).then((e=>e.ok?e.json():Promise.reject(e))).then((e=>!e||e.some((e=>(e=>{try{JSON.parse(e)}catch(e){return!0}return!1})(e)))?{fixed:!1,result:t}:{result:e.map((e=>JSON.parse(e).result)).join("\n"),fixed:!0})).catch((e=>(e.text().then((t=>{console.error({status:e.status,text:t})})),{fixed:!1,result:t})))})),O=e=>e.replacement===e.original,E=e=>e.reduce(((e,t)=>{const n=e[e.length-1],o=e.slice(0,e.length-1);if(!n)return[t];return[...o,...((e,t)=>{if(e.to!==t.from)throw new Error(`Replace pairs must be adjacent\n\n, ${JSON.stringify({leftReplace:e,rightReplace:t})}`);if(e.replacement.endsWith("\n"))return[e,t];if(O(e)&&O(t))return[{from:e.from,to:t.to,original:e.original+t.original,replacement:e.replacement+t.replacement}];if(O(e)){if(t.replacement.startsWith(" ")&&""===t.original||t.original.startsWith(" ")&&""===t.replacement)return[e,t];const n=e.original.split(" "),o=n.pop()||"",r=n.join(" ")+(n.length?" ":"");return[...r.length?[{from:e.from,to:e.from+r.length,original:r,replacement:r}]:[],{from:e.from+r.length,to:t.to,original:o+t.original,replacement:o+t.replacement}]}if(O(t)){if(e.replacement.endsWith(" ")&&""===e.original||e.original.endsWith(" ")&&""===e.replacement)return[e,t];const n=t.original.split(" "),o=n.shift()||"",r=(n.length?" ":"")+n.join(" ");return" "===r?[{from:e.from,to:t.to,original:e.original+t.original,replacement:e.replacement+t.replacement}]:[{from:e.from,to:e.to+o.length,original:e.original+o,replacement:e.replacement+o},...r.length?[{from:e.to+o.length,to:t.to,original:r,replacement:r}]:[]]}return[{from:e.from,to:t.to,original:e.original+t.original,replacement:e.replacement+t.replacement}]})(n,t)]}),[]),M=(e,t)=>{const n=(e=>{let t=0;return e.map((([e,n])=>{switch(e){case r.EQUAL:const e=n.lastIndexOf("\n"),o={from:t,to:t+n.length,original:n,replacement:n};if(-1!==e&&"\n"!==n){const o=[{from:t,to:t+e+1,original:n.slice(0,e+1),replacement:n.slice(0,e+1)},{from:t+e+1,to:t+n.length,original:n.slice(e+1),replacement:n.slice(e+1)}];return t+=n.length,o}return t+=n.length,[o];case r.DELETE:const s={from:t,to:t+n.length,original:n,replacement:""};return t+=n.length,[s];case r.INSERT:return[{from:t,to:t,original:"",replacement:n}]}})).flat()})(r(e,t));return E(E(n))},P=(e,t)=>{var n;const o=null===(n=y.getState(e.state))||void 0===n?void 0:n.decorations.find(0,e.state.doc.nodeSize,(e=>e.id===t.spec.id))[0];if(!o)return;const{text:r}=o.spec,{from:s,to:i}=o,a={type:p.acceptSuggestion,id:t.spec.id},c=e.state.tr.insertText(r,s,i).setMeta(y,a);e.dispatch(c)},L=(e,t)=>{const{spec:n}=t,o={type:p.discardSuggestion,id:n.id},r=e.state.tr.setMeta(y,o);e.dispatch(r)},k=(e,t)=>{const n=y.getState(e.state);if(!n)return!1;const{decorations:o}=n,r=o.find(t,t)[0];if(!r){const t={type:p.closeSuggestion};return e.dispatch(e.state.tr.setMeta(y,t)),!1}const s=n.popupDecoration.find()[0];if((null==s?void 0:s.spec.id)===r.spec.id)return!1;const i={type:p.openSuggestion,decoration:r};return e.dispatch(e.state.tr.setMeta(y,i)),!1},D={debounceMs:2e3,createUpdatePopup:(e,t,n,o,r)=>{const s=document.createElement("div");s.className="grammar-suggest-tooltip";const{spec:i}=t,a=e.dom.getBoundingClientRect();s.id=g.grammarSuggestPopup;const c=e.coordsAtPos(n),l=e.dom.scrollTop||0,d=e.dom.scrollLeft||0;s.style.left=`${c.left-a.left+d}px`,s.style.top=`${c.bottom-a.top+l+5}px`;const p=document.createElement("div");p.className="grammar-suggest-tooltip-apply",p.innerText=i.text||i.originalText,i.text||(p.style.textDecoration="line-through",p.style.color="red"),p.onclick=()=>{o(e,t)},s.appendChild(p);const u=document.createElement("div");return u.innerHTML="<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'><path d='M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 10.5858L14.8284 7.75736L16.2426 9.17157L13.4142 12L16.2426 14.8284L14.8284 16.2426L12 13.4142L9.17157 16.2426L7.75736 14.8284L10.5858 12L7.75736 9.17157L9.17157 7.75736L12 10.5858Z'></path></svg>",u.className="grammar-suggest-tooltip-discard",u.onclick=()=>{r(e,t)},s.appendChild(u),s},withYjs:!1},A={maxSelection:1e3},I=(e,r=D)=>{let s=!1;return new t({key:y,state:{init:()=>({lastText:"",decorations:o.empty,popupDecoration:o.empty}),apply(e,t,s,i){const l=e.getMeta(y);return(null==l?void 0:l.type)===p.suggestionUpdate?((e,t,o)=>{const{changedRegion:r,fix:s,mapping:i,text:a}=t,c=M(r.newText,s.result).filter((e=>!O(e))).filter((e=>e.original!==`${e.replacement}\n`)).map((({from:e,to:t,original:o,replacement:s})=>{const a=C(r.start+e,i),c=C(r.start+(s.endsWith("\n")?t-1:t),i),l={text:s.endsWith("\n")?s.slice(0,-1):s,originalText:o,id:{}};return n.inline(a,c,{class:"grammarSuggestion "+(""===s?"removalSuggestion":"")},l)}));return Object.assign(Object.assign({},e),{decorations:e.decorations.add(o.doc,c),lastText:a})})(t,l,e):(null==l?void 0:l.type)===p.acceptSuggestion?((e,t,n)=>{const r=e.decorations.remove(e.decorations.find(0,n.doc.nodeSize,(e=>e.id===t.id)));return Object.assign(Object.assign({},e),{lastText:S(n.doc),decorations:r.map(n.mapping,n.doc),popupDecoration:o.empty})})(t,l,e):(null==l?void 0:l.type)===p.openSuggestion?((e,t,r,s)=>{const{decoration:i}=t,a={id:i.spec.id};return Object.assign(Object.assign({},e),{popupDecoration:o.create(r.doc,[n.widget(i.from,((e,t)=>{const n=t();return n?s.createUpdatePopup(e,i,n,P,L):document.createElement("div")}),Object.assign(Object.assign({},a),{stopEvent:()=>!0}))])})})(t,l,e,r):(null==l?void 0:l.type)===p.closeSuggestion?Object.assign(Object.assign({},t),{popupDecoration:o.empty}):(null==l?void 0:l.type)===p.discardSuggestion?((e,t,n)=>Object.assign(Object.assign({},e),{decorations:e.decorations.remove(e.decorations.find(0,n.doc.nodeSize,(e=>e.id===t.id))),popupDecoration:o.empty}))(t,l,e):e.docChanged?((e,t,n,o)=>{const r=j(n.doc).text,{text:s,mapping:i}=j(t.doc);if(s===r)return e;let l=t.mapping;if(o){const e=t.doc.content.findDiffStart(n.doc.content),o=n.doc.content.findDiffEnd(t.doc.content),r=new a(o&&e?[e,o.a-e,o.b-e]:[0,0,0]);l=new c([r])}const d=w(r,s),p=e.decorations.map(l,t.doc),g=C(d.start,i),u=C(d.end,i),m=e.popupDecoration.map(l,t.doc);return Object.assign(Object.assign({},e),{decorations:p.remove(p.find(g,u)),popupDecoration:m.remove(m.find(g,u))})})(t,e,s,r.withYjs):t}},props:{handleClick:k,decorations:e=>{const t=y.getState(e);if(!t)return null;const n=v.getState(e);return(null==n?void 0:n.status)!==x.idle?t.decorations:t.decorations.add(e.doc,t.popupDecoration.find())}},view(){const t=((e,t)=>i((e=>{var n;const o=j(e.state.doc),r=(null===(n=y.getState(e.state))||void 0===n?void 0:n.lastText)||"",s=w(r,o.text);T(t,s.newText).then((t=>{if(S(e.state.doc)!==o.text)return;const n={type:p.suggestionUpdate,fix:t,changedRegion:s,mapping:o.mapping,text:o.text};e.dispatch(e.state.tr.setMeta(y,n))})).catch((e=>{console.error("Grammar suggest API error",e)}))}),e.debounceMs))(r,e);return{update(e,n){const o=y.getState(e.state);e.state.doc.textBetween(0,e.state.doc.nodeSize-2,"/n")===n.doc.textBetween(0,n.doc.nodeSize-2,"/n")&&s||!o||o.lastText===S(e.state.doc)||(s=!0,t(e))}}}})},R=(e,t,n,o,r,i,a)=>s(void 0,void 0,void 0,(function*(){var e;let n="";const c=new AbortController;try{const l=null===(e=(yield fetch("https://suggestion-gw5lxik4dq-uc.a.run.app",{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json",Authorization:"Bearer -qKivjCv6MfQSmgF438PjEY7RnLfqoVe"},signal:c.signal,body:JSON.stringify({model:"gpt-3.5-turbo",modelParams:{input:[t],task:r,params:a}})})).body)||void 0===e?void 0:e.getReader(),d=({done:e,value:t})=>s(void 0,void 0,void 0,(function*(){var s;if(e)return;if(null===(s=v.getState(o.state))||void 0===s?void 0:s.isCancelled)return void(yield c.abort());const a=(new TextDecoder).decode(t);try{n+=a,o.dispatch(o.state.tr.setMeta(v,Object.assign({type:r,status:x.streaming,result:n},i&&{selection:i})))}catch(e){console.error("Could not parse stream message",a,e)}return null==l?void 0:l.read().then(d)}));yield null==l?void 0:l.read().then(d),o.dispatch(o.state.tr.setMeta(v,Object.assign({type:r,status:x.finished,result:n},i&&{selection:i})))}catch(e){console.error("Error:",e)}})),U=(e,n=A)=>{let o=!1;return new t({key:v,state:{init:()=>({status:x.idle}),apply(e,t,n,r){const s=e.getMeta(v);return t.status===x.done||t.status===x.rejected?(o=!1,{status:x.idle}):(null==s?void 0:s.status)===x.cancelled?Object.assign(Object.assign(Object.assign({},t),s),{isCancelled:!0}):s&&(e=>Object.values(f).includes(e.type)||Object.values(h).includes(e.type))(s)?t.type&&s.type!==t.type?t:Object.assign(Object.assign({},t),s):t}},view:()=>({update(e,t){const r=v.getState(e.state);let i=e.state.tr;if((null==r?void 0:r.status)===x.new&&!o)switch(r.type){case h.Complete:o=!0,((e,t,n)=>{s(void 0,void 0,void 0,(function*(){const{doc:e}=t.state,n=[];e.descendants((e=>{"paragraph"===e.type.name&&n.push(e.textContent)}));let o="";o=n.length>=2?n.slice(-2).join(" "):n.join(" "),R(0,o,0,t,h.Complete)}))})(0,e);break;case h.MakeLonger:case h.MakeShorter:case h.Improve:case h.Simplify:case h.Explain:case h.ActionItems:case f.Translate:case f.ChangeTone:o=!0,((e,t,n,o,r,s)=>{const i=n.state.selection;if(!i)return void n.dispatch(n.state.tr.setMeta(v,{task:e,status:x.done}));if(n.state.doc.textBetween(i.from,i.to).length>r)return void n.dispatch(n.state.tr.setMeta(v,{type:e,status:x.error,error:"Selection is too big"}));const a=n.state.doc.textBetween(i.from,i.to,"\n");R(0,a,0,n,e,i,s)})(r.type,0,e,0,n.maxSelection,r.params)}if((null==r?void 0:r.status)===x.accepted){if(r.error)return i.setMeta(v,{type:r.type,status:x.done}),void e.dispatch(i);switch(r.type){case h.Complete:i=i.insertText(r.result||"",e.state.doc.nodeSize-2),i.setMeta(v,{type:h.Complete,status:x.done}),e.dispatch(i),e.focus();break;case h.MakeLonger:case h.MakeShorter:case h.Improve:case h.Simplify:case h.Explain:case h.ActionItems:case f.Translate:case f.ChangeTone:if(r.selection&&r.result){const t=r.result.split("\n\n").map((t=>e.state.schema.node("paragraph",null,e.state.schema.text(t)))),n=l.fromArray(t);i.selection.replace(i,new d(n,0,0))}i.setMeta(v,{type:r.type,status:x.done}),e.dispatch(i),e.focus()}}}})})};export{u as MoodParamType,f as OpenAiPromptsWithParam,h as OpenAiPromptsWithoutParam,x as Status,m as TranslationTargetLanguage,U as completePlugin,v as completePluginKey,A as defaultCompleteOptions,D as defaultOptions,I as grammarSuggestPlugin};
1
+ import{PluginKey as e,TextSelection as t,Plugin as n}from"prosemirror-state";import{Decoration as o,DecorationSet as r}from"prosemirror-view";import s from"fast-diff";import{__awaiter as a}from"tslib";import i from"lodash.debounce";import{StepMap as c,Mapping as l}from"prosemirror-transform";import{Fragment as d,Slice as p}from"prosemirror-model";var g,u,m,h,f,x,v;!function(e){e.suggestionUpdate="suggestionUpdate",e.acceptSuggestion="acceptSuggestion",e.openSuggestion="openSuggestion",e.closeSuggestion="closeSuggestion",e.discardSuggestion="discardSuggestion"}(g||(g={})),function(e){e.grammarSuggestPopup="grammar-suggest-popup"}(u||(u={})),function(e){e.Casual="Casual",e.Confident="Confident",e.Straightforward="Straightforward",e.Friendly="Friendly"}(m||(m={})),function(e){e.English="English",e.Spanish="Spanish",e.French="French",e.German="German",e.Italian="Italian",e.Portuguese="Portuguese",e.Dutch="Dutch",e.Russian="Russian",e.Chinese="Chinese",e.Korean="Korean",e.Japanese="Japanese"}(h||(h={})),function(e){e.Complete="Complete",e.Improve="Improve",e.MakeLonger="MakeLonger",e.MakeShorter="MakeShorter",e.Simplify="Simplify",e.Explain="Explain",e.ActionItems="ActionItems"}(f||(f={})),function(e){e.ChangeTone="ChangeTone",e.Translate="Translate"}(x||(x={})),function(e){e.idle="idle",e.new="new",e.streaming="streaming",e.finished="finished",e.accepted="accepted",e.cancelled="cancelled",e.rejected="rejected",e.done="done",e.error="error"}(v||(v={}));const y=new e("completePlugin"),S=new e("grammarSuggestPlugin"),w=e=>{let t="";return e.descendants(((e,n)=>{e.isText&&(t+=`${e.text}\n`)})),t},b=(e,t)=>{if(e===t)return{start:e.length,end:e.length,oldStart:e.length,oldEnd:e.length,oldText:"",newText:""};const n=s(e,t),o=n[0],r=o[0]===s.EQUAL?o[1].length-1:0,a=((e,t)=>{if(t[t.length-1][0]!==s.EQUAL)return e.length;const n=t.slice(0,t.length-1);let o=0;for(const e of n){const[t,n]=e;t===s.EQUAL&&(o+=n.length),t===s.DELETE&&(o+=n.length)}return o})(e,n),i=e.lastIndexOf("\n",r),c=e.indexOf("\n",a),l=-1===i?0:i+1,d=-1===c?e.length:c,p=e.slice(l,d),g=t.slice(l,t.length-(e.length-d));return{start:l,end:l+g.length,oldStart:l,oldEnd:d,oldText:p,newText:g}},j=[{docPos:1,textPos:0}],C=e=>{let t="";const n=[];return e.descendants(((e,o)=>{e.isText&&(n.push({docPos:o,textPos:t.length}),t+=`${e.text}\n`)})),{text:t,mapping:n.length?n:j}},T=(e,t)=>{for(let n=0;n<t.length;n++)if(e>=t[n].textPos&&(void 0===t[n+1]||e<t[n+1].textPos))return t[n].docPos+(e-t[n].textPos);throw new Error("textPositionToDocumentPosition: textPos not found in mapping")},O=(e,t)=>a(void 0,void 0,void 0,(function*(){const n=[...t.split("\n")];return fetch("https://prosemirror-ai-plugin.web.app/api/suggestion",{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({model:"gpt-3.5-turbo",modelParams:{input:n}})}).then((e=>e.ok?e.json():Promise.reject(e))).then((e=>!e||e.some((e=>(e=>{try{JSON.parse(e)}catch(e){return!0}return!1})(e)))?{fixed:!1,result:t}:{result:e.map((e=>JSON.parse(e).result)).join("\n"),fixed:!0})).catch((e=>(e.text().then((t=>{console.error({status:e.status,text:t})})),{fixed:!1,result:t})))})),E=e=>e.replacement===e.original,M=e=>e.reduce(((e,t)=>{const n=e[e.length-1],o=e.slice(0,e.length-1);if(!n)return[t];return[...o,...((e,t)=>{if(e.to!==t.from)throw new Error(`Replace pairs must be adjacent\n\n, ${JSON.stringify({leftReplace:e,rightReplace:t})}`);if(e.replacement.endsWith("\n"))return[e,t];if(E(e)&&E(t))return[{from:e.from,to:t.to,original:e.original+t.original,replacement:e.replacement+t.replacement}];if(E(e)){if(t.replacement.startsWith(" ")&&""===t.original||t.original.startsWith(" ")&&""===t.replacement)return[e,t];const n=e.original.split(" "),o=n.pop()||"",r=n.join(" ")+(n.length?" ":"");return[...r.length?[{from:e.from,to:e.from+r.length,original:r,replacement:r}]:[],{from:e.from+r.length,to:t.to,original:o+t.original,replacement:o+t.replacement}]}if(E(t)){if(e.replacement.endsWith(" ")&&""===e.original||e.original.endsWith(" ")&&""===e.replacement)return[e,t];const n=t.original.split(" "),o=n.shift()||"",r=(n.length?" ":"")+n.join(" ");return" "===r?[{from:e.from,to:t.to,original:e.original+t.original,replacement:e.replacement+t.replacement}]:[{from:e.from,to:e.to+o.length,original:e.original+o,replacement:e.replacement+o},...r.length?[{from:e.to+o.length,to:t.to,original:r,replacement:r}]:[]]}return[{from:e.from,to:t.to,original:e.original+t.original,replacement:e.replacement+t.replacement}]})(n,t)]}),[]),P=(e,t)=>{const n=(e=>{let t=0;return e.map((([e,n])=>{switch(e){case s.EQUAL:const e=n.lastIndexOf("\n"),o={from:t,to:t+n.length,original:n,replacement:n};if(-1!==e&&"\n"!==n){const o=[{from:t,to:t+e+1,original:n.slice(0,e+1),replacement:n.slice(0,e+1)},{from:t+e+1,to:t+n.length,original:n.slice(e+1),replacement:n.slice(e+1)}];return t+=n.length,o}return t+=n.length,[o];case s.DELETE:const r={from:t,to:t+n.length,original:n,replacement:""};return t+=n.length,[r];case s.INSERT:return[{from:t,to:t,original:"",replacement:n}]}})).flat()})(s(e,t));return M(M(n))},L=(e,n)=>{var o;const r=null===(o=S.getState(e.state))||void 0===o?void 0:o.decorations.find(0,e.state.doc.nodeSize,(e=>e.id===n.spec.id))[0];if(!r)return;const{text:s}=r.spec,{from:a,to:i}=r,c={type:g.acceptSuggestion,id:n.spec.id},l=s.split("\n").map((t=>e.state.schema.node("paragraph",null,e.state.schema.text(t)))),u=d.fromArray(l);let{tr:m}=e.state;m=m.setSelection(t.create(e.state.doc,a,i)),m.selection.replace(m,new p(u,1,1)),m.setMeta(S,c),e.dispatch(m)},k=(e,t)=>{const{spec:n}=t,o={type:g.discardSuggestion,id:n.id},r=e.state.tr.setMeta(S,o);e.dispatch(r)},D=(e,t)=>{const n=S.getState(e.state);if(!n)return!1;const{decorations:o}=n,r=o.find(t,t)[0];if(!r){const t={type:g.closeSuggestion};return e.dispatch(e.state.tr.setMeta(S,t)),!1}const s=n.popupDecoration.find()[0];if((null==s?void 0:s.spec.id)===r.spec.id)return!1;const a={type:g.openSuggestion,decoration:r};return e.dispatch(e.state.tr.setMeta(S,a)),!1},A={debounceMs:2e3,createUpdatePopup:(e,t,n,o,r)=>{const s=document.createElement("div");s.className="grammar-suggest-tooltip";const{spec:a}=t,i=e.dom.getBoundingClientRect();s.id=u.grammarSuggestPopup;const c=e.coordsAtPos(n),l=e.dom.scrollTop||0,d=e.dom.scrollLeft||0;s.style.left=`${c.left-i.left+d}px`,s.style.top=`${c.bottom-i.top+l+5}px`;const p=document.createElement("div");p.className="grammar-suggest-tooltip-apply",p.innerText=a.text||a.originalText,a.text||(p.style.textDecoration="line-through",p.style.color="red"),p.onclick=()=>{o(e,t)},s.appendChild(p);const g=document.createElement("div");return g.innerHTML="<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'><path d='M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 10.5858L14.8284 7.75736L16.2426 9.17157L13.4142 12L16.2426 14.8284L14.8284 16.2426L12 13.4142L9.17157 16.2426L7.75736 14.8284L10.5858 12L7.75736 9.17157L9.17157 7.75736L12 10.5858Z'></path></svg>",g.className="grammar-suggest-tooltip-discard",g.onclick=()=>{r(e,t)},s.appendChild(g),s},withYjs:!1},I={maxSelection:1e3},R=(e,t=A)=>{let s=!1;return new n({key:S,state:{init:()=>({lastText:"",decorations:r.empty,popupDecoration:r.empty}),apply(e,n,s,a){const i=e.getMeta(S);return(null==i?void 0:i.type)===g.suggestionUpdate?((e,t,n)=>{const{changedRegion:r,fix:s,mapping:a,text:i}=t,c=P(r.newText,s.result).filter((e=>!E(e))).filter((e=>e.original!==`${e.replacement}\n`)).map((({from:e,to:t,original:n,replacement:s})=>{const i=T(r.start+e,a),c=T(r.start+(s.endsWith("\n")?t-1:t),a),l={text:s.endsWith("\n")?s.slice(0,-1):s,originalText:n,id:{}};return o.inline(i,c,{class:"grammarSuggestion "+(""===s?"removalSuggestion":"")},l)}));return Object.assign(Object.assign({},e),{decorations:e.decorations.add(n.doc,c),lastText:i})})(n,i,e):(null==i?void 0:i.type)===g.acceptSuggestion?((e,t,n)=>{const o=e.decorations.remove(e.decorations.find(0,n.doc.nodeSize,(e=>e.id===t.id)));return Object.assign(Object.assign({},e),{lastText:w(n.doc),decorations:o.map(n.mapping,n.doc),popupDecoration:r.empty})})(n,i,e):(null==i?void 0:i.type)===g.openSuggestion?((e,t,n,s)=>{const{decoration:a}=t,i={id:a.spec.id};return Object.assign(Object.assign({},e),{popupDecoration:r.create(n.doc,[o.widget(a.from,((e,t)=>{const n=t();return n?s.createUpdatePopup(e,a,n,L,k):document.createElement("div")}),Object.assign(Object.assign({},i),{stopEvent:()=>!0}))])})})(n,i,e,t):(null==i?void 0:i.type)===g.closeSuggestion?Object.assign(Object.assign({},n),{popupDecoration:r.empty}):(null==i?void 0:i.type)===g.discardSuggestion?((e,t,n)=>Object.assign(Object.assign({},e),{decorations:e.decorations.remove(e.decorations.find(0,n.doc.nodeSize,(e=>e.id===t.id))),popupDecoration:r.empty}))(n,i,e):e.docChanged?((e,t,n,o)=>{const r=C(n.doc).text,{text:s,mapping:a}=C(t.doc);if(s===r)return e;let i=t.mapping;if(o){const e=t.doc.content.findDiffStart(n.doc.content),o=n.doc.content.findDiffEnd(t.doc.content),r=new c(o&&e?[e,o.a-e,o.b-e]:[0,0,0]);i=new l([r])}const d=b(r,s),p=e.decorations.map(i,t.doc),g=T(d.start,a),u=T(d.end,a),m=e.popupDecoration.map(i,t.doc);return Object.assign(Object.assign({},e),{decorations:p.remove(p.find(g,u)),popupDecoration:m.remove(m.find(g,u))})})(n,e,s,t.withYjs):n}},props:{handleClick:D,decorations:e=>{const t=S.getState(e);if(!t)return null;const n=y.getState(e);return(null==n?void 0:n.status)!==v.idle?t.decorations:t.decorations.add(e.doc,t.popupDecoration.find())}},view(){const n=((e,t)=>i((e=>{var n;const o=C(e.state.doc),r=(null===(n=S.getState(e.state))||void 0===n?void 0:n.lastText)||"",s=b(r,o.text);O(t,s.newText).then((t=>{if(w(e.state.doc)!==o.text)return;const n={type:g.suggestionUpdate,fix:t,changedRegion:s,mapping:o.mapping,text:o.text};e.dispatch(e.state.tr.setMeta(S,n))})).catch((e=>{console.error("Grammar suggest API error",e)}))}),e.debounceMs))(t,e);return{update(e,t){const o=S.getState(e.state);e.state.doc.textBetween(0,e.state.doc.nodeSize-2,"/n")===t.doc.textBetween(0,t.doc.nodeSize-2,"/n")&&s||!o||o.lastText===w(e.state.doc)||(s=!0,n(e))}}}})},U=(e,t,n,o,r,s,i)=>a(void 0,void 0,void 0,(function*(){var e;let n="";const c=new AbortController;try{const l=null===(e=(yield fetch("https://suggestion-gw5lxik4dq-uc.a.run.app",{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json",Authorization:"Bearer -qKivjCv6MfQSmgF438PjEY7RnLfqoVe"},signal:c.signal,body:JSON.stringify({model:"gpt-3.5-turbo",modelParams:{input:[t],task:r,params:i}})})).body)||void 0===e?void 0:e.getReader(),d=({done:e,value:t})=>a(void 0,void 0,void 0,(function*(){var a;if(e)return;if(null===(a=y.getState(o.state))||void 0===a?void 0:a.isCancelled)return void(yield c.abort());const i=(new TextDecoder).decode(t);try{n+=i,o.dispatch(o.state.tr.setMeta(y,Object.assign({type:r,status:v.streaming,result:n},s&&{selection:s})))}catch(e){console.error("Could not parse stream message",i,e)}return null==l?void 0:l.read().then(d)}));yield null==l?void 0:l.read().then(d),o.dispatch(o.state.tr.setMeta(y,Object.assign({type:r,status:v.finished,result:n},s&&{selection:s})))}catch(e){console.error("Error:",e)}})),N=(e,t=I)=>{let o=!1;return new n({key:y,state:{init:()=>({status:v.idle}),apply(e,t,n,r){const s=e.getMeta(y);return t.status===v.done||t.status===v.rejected?(o=!1,{status:v.idle}):(null==s?void 0:s.status)===v.cancelled?Object.assign(Object.assign(Object.assign({},t),s),{isCancelled:!0}):s&&(e=>Object.values(x).includes(e.type)||Object.values(f).includes(e.type))(s)?t.type&&s.type!==t.type?t:Object.assign(Object.assign({},t),s):t}},view:()=>({update(e,n){const r=y.getState(e.state);let s=e.state.tr;if((null==r?void 0:r.status)===v.new&&!o)switch(r.type){case f.Complete:o=!0,((e,t,n)=>{a(void 0,void 0,void 0,(function*(){const{doc:e}=t.state,n=[];e.descendants((e=>{"paragraph"===e.type.name&&n.push(e.textContent)}));let o="";o=n.length>=2?n.slice(-2).join(" "):n.join(" "),U(0,o,0,t,f.Complete)}))})(0,e);break;case f.MakeLonger:case f.MakeShorter:case f.Improve:case f.Simplify:case f.Explain:case f.ActionItems:case x.Translate:case x.ChangeTone:o=!0,((e,t,n,o,r,s)=>{const a=n.state.selection;if(!a)return void n.dispatch(n.state.tr.setMeta(y,{task:e,status:v.done}));if(n.state.doc.textBetween(a.from,a.to).length>r)return void n.dispatch(n.state.tr.setMeta(y,{type:e,status:v.error,error:"Selection is too big"}));const i=n.state.doc.textBetween(a.from,a.to,"\n");U(0,i,0,n,e,a,s)})(r.type,0,e,0,t.maxSelection,r.params)}if((null==r?void 0:r.status)===v.accepted){if(r.error)return s.setMeta(y,{type:r.type,status:v.done}),void e.dispatch(s);switch(r.type){case f.Complete:s=s.insertText(r.result||"",e.state.doc.nodeSize-2),s.setMeta(y,{type:f.Complete,status:v.done}),e.dispatch(s),e.focus();break;case f.MakeLonger:case f.MakeShorter:case f.Improve:case f.Simplify:case f.Explain:case f.ActionItems:case x.Translate:case x.ChangeTone:if(r.selection&&r.result){const t=r.result.split("\n\n").map((t=>e.state.schema.node("paragraph",null,e.state.schema.text(t)))),n=d.fromArray(t);s.selection.replace(s,new p(n,0,0))}s.setMeta(y,{type:r.type,status:v.done}),e.dispatch(s),e.focus()}}}})})};export{m as MoodParamType,x as OpenAiPromptsWithParam,f as OpenAiPromptsWithoutParam,v as Status,h as TranslationTargetLanguage,N as completePlugin,y as completePluginKey,I as defaultCompleteOptions,A as defaultOptions,R as grammarSuggestPlugin};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var t,e,o,n,r,s,a,i=require("prosemirror-state"),p=require("prosemirror-view"),c=require("fast-diff"),l=require("tslib"),d=require("lodash.debounce"),u=require("prosemirror-transform"),g=require("prosemirror-model");!function(t){t.suggestionUpdate="suggestionUpdate",t.acceptSuggestion="acceptSuggestion",t.openSuggestion="openSuggestion",t.closeSuggestion="closeSuggestion",t.discardSuggestion="discardSuggestion"}(t||(t={})),function(t){t.grammarSuggestPopup="grammar-suggest-popup"}(e||(e={})),exports.MoodParamType=void 0,(o=exports.MoodParamType||(exports.MoodParamType={})).Casual="Casual",o.Confident="Confident",o.Straightforward="Straightforward",o.Friendly="Friendly",exports.TranslationTargetLanguage=void 0,(n=exports.TranslationTargetLanguage||(exports.TranslationTargetLanguage={})).English="English",n.Spanish="Spanish",n.French="French",n.German="German",n.Italian="Italian",n.Portuguese="Portuguese",n.Dutch="Dutch",n.Russian="Russian",n.Chinese="Chinese",n.Korean="Korean",n.Japanese="Japanese",exports.OpenAiPromptsWithoutParam=void 0,(r=exports.OpenAiPromptsWithoutParam||(exports.OpenAiPromptsWithoutParam={})).Complete="Complete",r.Improve="Improve",r.MakeLonger="MakeLonger",r.MakeShorter="MakeShorter",r.Simplify="Simplify",r.Explain="Explain",r.ActionItems="ActionItems",exports.OpenAiPromptsWithParam=void 0,(s=exports.OpenAiPromptsWithParam||(exports.OpenAiPromptsWithParam={})).ChangeTone="ChangeTone",s.Translate="Translate",exports.Status=void 0,(a=exports.Status||(exports.Status={})).idle="idle",a.new="new",a.streaming="streaming",a.finished="finished",a.accepted="accepted",a.cancelled="cancelled",a.rejected="rejected",a.done="done",a.error="error";const m=new i.PluginKey("completePlugin"),h=new i.PluginKey("grammarSuggestPlugin"),x=t=>{let e="";return t.descendants(((t,o)=>{t.isText&&(e+=`${t.text}\n`)})),e},f=(t,e)=>{if(t===e)return{start:t.length,end:t.length,oldStart:t.length,oldEnd:t.length,oldText:"",newText:""};const o=c(t,e),n=o[0],r=n[0]===c.EQUAL?n[1].length-1:0,s=((t,e)=>{if(e[e.length-1][0]!==c.EQUAL)return t.length;const o=e.slice(0,e.length-1);let n=0;for(const t of o){const[e,o]=t;e===c.EQUAL&&(n+=o.length),e===c.DELETE&&(n+=o.length)}return n})(t,o),a=t.lastIndexOf("\n",r),i=t.indexOf("\n",s),p=-1===a?0:a+1,l=-1===i?t.length:i,d=t.slice(p,l),u=e.slice(p,e.length-(t.length-l));return{start:p,end:p+u.length,oldStart:p,oldEnd:l,oldText:d,newText:u}},P=[{docPos:1,textPos:0}],S=t=>{let e="";const o=[];return t.descendants(((t,n)=>{t.isText&&(o.push({docPos:n,textPos:e.length}),e+=`${t.text}\n`)})),{text:e,mapping:o.length?o:P}},v=(t,e)=>{for(let o=0;o<e.length;o++)if(t>=e[o].textPos&&(void 0===e[o+1]||t<e[o+1].textPos))return e[o].docPos+(t-e[o].textPos);throw new Error("textPositionToDocumentPosition: textPos not found in mapping")},y=(t,e)=>l.__awaiter(void 0,void 0,void 0,(function*(){const o=[...e.split("\n")];return fetch("https://prosemirror-ai-plugin.web.app/api/suggestion",{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({model:"gpt-3.5-turbo",modelParams:{input:o}})}).then((t=>t.ok?t.json():Promise.reject(t))).then((t=>!t||t.some((t=>(t=>{try{JSON.parse(t)}catch(t){return!0}return!1})(t)))?{fixed:!1,result:e}:{result:t.map((t=>JSON.parse(t).result)).join("\n"),fixed:!0})).catch((t=>(t.text().then((e=>{console.error({status:t.status,text:e})})),{fixed:!1,result:e})))})),O=t=>t.replacement===t.original,w=t=>t.reduce(((t,e)=>{const o=t[t.length-1],n=t.slice(0,t.length-1);if(!o)return[e];return[...n,...((t,e)=>{if(t.to!==e.from)throw new Error(`Replace pairs must be adjacent\n\n, ${JSON.stringify({leftReplace:t,rightReplace:e})}`);if(t.replacement.endsWith("\n"))return[t,e];if(O(t)&&O(e))return[{from:t.from,to:e.to,original:t.original+e.original,replacement:t.replacement+e.replacement}];if(O(t)){if(e.replacement.startsWith(" ")&&""===e.original||e.original.startsWith(" ")&&""===e.replacement)return[t,e];const o=t.original.split(" "),n=o.pop()||"",r=o.join(" ")+(o.length?" ":"");return[...r.length?[{from:t.from,to:t.from+r.length,original:r,replacement:r}]:[],{from:t.from+r.length,to:e.to,original:n+e.original,replacement:n+e.replacement}]}if(O(e)){if(t.replacement.endsWith(" ")&&""===t.original||t.original.endsWith(" ")&&""===t.replacement)return[t,e];const o=e.original.split(" "),n=o.shift()||"",r=(o.length?" ":"")+o.join(" ");return" "===r?[{from:t.from,to:e.to,original:t.original+e.original,replacement:t.replacement+e.replacement}]:[{from:t.from,to:t.to+n.length,original:t.original+n,replacement:t.replacement+n},...r.length?[{from:t.to+n.length,to:e.to,original:r,replacement:r}]:[]]}return[{from:t.from,to:e.to,original:t.original+e.original,replacement:t.replacement+e.replacement}]})(o,e)]}),[]),T=(t,e)=>{const o=(t=>{let e=0;return t.map((([t,o])=>{switch(t){case c.EQUAL:const t=o.lastIndexOf("\n"),n={from:e,to:e+o.length,original:o,replacement:o};if(-1!==t&&"\n"!==o){const n=[{from:e,to:e+t+1,original:o.slice(0,t+1),replacement:o.slice(0,t+1)},{from:e+t+1,to:e+o.length,original:o.slice(t+1),replacement:o.slice(t+1)}];return e+=o.length,n}return e+=o.length,[n];case c.DELETE:const r={from:e,to:e+o.length,original:o,replacement:""};return e+=o.length,[r];case c.INSERT:return[{from:e,to:e,original:"",replacement:o}]}})).flat()})(c(t,e));return w(w(o))},A=(e,o)=>{var n;const r=null===(n=h.getState(e.state))||void 0===n?void 0:n.decorations.find(0,e.state.doc.nodeSize,(t=>t.id===o.spec.id))[0];if(!r)return;const{text:s}=r.spec,{from:a,to:i}=r,p={type:t.acceptSuggestion,id:o.spec.id},c=e.state.tr.insertText(s,a,i).setMeta(h,p);e.dispatch(c)},b=(e,o)=>{const{spec:n}=o,r={type:t.discardSuggestion,id:n.id},s=e.state.tr.setMeta(h,r);e.dispatch(s)},j=(e,o)=>{const n=h.getState(e.state);if(!n)return!1;const{decorations:r}=n,s=r.find(o,o)[0];if(!s){const o={type:t.closeSuggestion};return e.dispatch(e.state.tr.setMeta(h,o)),!1}const a=n.popupDecoration.find()[0];if((null==a?void 0:a.spec.id)===s.spec.id)return!1;const i={type:t.openSuggestion,decoration:s};return e.dispatch(e.state.tr.setMeta(h,i)),!1},C={debounceMs:2e3,createUpdatePopup:(t,o,n,r,s)=>{const a=document.createElement("div");a.className="grammar-suggest-tooltip";const{spec:i}=o,p=t.dom.getBoundingClientRect();a.id=e.grammarSuggestPopup;const c=t.coordsAtPos(n),l=t.dom.scrollTop||0,d=t.dom.scrollLeft||0;a.style.left=`${c.left-p.left+d}px`,a.style.top=`${c.bottom-p.top+l+5}px`;const u=document.createElement("div");u.className="grammar-suggest-tooltip-apply",u.innerText=i.text||i.originalText,i.text||(u.style.textDecoration="line-through",u.style.color="red"),u.onclick=()=>{r(t,o)},a.appendChild(u);const g=document.createElement("div");return g.innerHTML="<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'><path d='M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 10.5858L14.8284 7.75736L16.2426 9.17157L13.4142 12L16.2426 14.8284L14.8284 16.2426L12 13.4142L9.17157 16.2426L7.75736 14.8284L10.5858 12L7.75736 9.17157L9.17157 7.75736L12 10.5858Z'></path></svg>",g.className="grammar-suggest-tooltip-discard",g.onclick=()=>{s(t,o)},a.appendChild(g),a},withYjs:!1},M={maxSelection:1e3},W=(t,e,o,n,r,s,a)=>l.__awaiter(void 0,void 0,void 0,(function*(){var t;let o="";const i=new AbortController;try{const p=null===(t=(yield fetch("https://suggestion-gw5lxik4dq-uc.a.run.app",{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json",Authorization:"Bearer -qKivjCv6MfQSmgF438PjEY7RnLfqoVe"},signal:i.signal,body:JSON.stringify({model:"gpt-3.5-turbo",modelParams:{input:[e],task:r,params:a}})})).body)||void 0===t?void 0:t.getReader(),c=({done:t,value:e})=>l.__awaiter(void 0,void 0,void 0,(function*(){var a;if(t)return;if(null===(a=m.getState(n.state))||void 0===a?void 0:a.isCancelled)return void(yield i.abort());const l=(new TextDecoder).decode(e);try{o+=l,n.dispatch(n.state.tr.setMeta(m,Object.assign({type:r,status:exports.Status.streaming,result:o},s&&{selection:s})))}catch(t){console.error("Could not parse stream message",l,t)}return null==p?void 0:p.read().then(c)}));yield null==p?void 0:p.read().then(c),n.dispatch(n.state.tr.setMeta(m,Object.assign({type:r,status:exports.Status.finished,result:o},s&&{selection:s})))}catch(t){console.error("Error:",t)}}));exports.completePlugin=(t,e=M)=>{let o=!1;return new i.Plugin({key:m,state:{init:()=>({status:exports.Status.idle}),apply(t,e,n,r){const s=t.getMeta(m);return e.status===exports.Status.done||e.status===exports.Status.rejected?(o=!1,{status:exports.Status.idle}):(null==s?void 0:s.status)===exports.Status.cancelled?Object.assign(Object.assign(Object.assign({},e),s),{isCancelled:!0}):s&&(t=>Object.values(exports.OpenAiPromptsWithParam).includes(t.type)||Object.values(exports.OpenAiPromptsWithoutParam).includes(t.type))(s)?e.type&&s.type!==e.type?e:Object.assign(Object.assign({},e),s):e}},view:()=>({update(t,n){const r=m.getState(t.state);let s=t.state.tr;if((null==r?void 0:r.status)===exports.Status.new&&!o)switch(r.type){case exports.OpenAiPromptsWithoutParam.Complete:o=!0,((t,e,o)=>{l.__awaiter(void 0,void 0,void 0,(function*(){const{doc:t}=e.state,o=[];t.descendants((t=>{"paragraph"===t.type.name&&o.push(t.textContent)}));let n="";n=o.length>=2?o.slice(-2).join(" "):o.join(" "),W(0,n,0,e,exports.OpenAiPromptsWithoutParam.Complete)}))})(0,t);break;case exports.OpenAiPromptsWithoutParam.MakeLonger:case exports.OpenAiPromptsWithoutParam.MakeShorter:case exports.OpenAiPromptsWithoutParam.Improve:case exports.OpenAiPromptsWithoutParam.Simplify:case exports.OpenAiPromptsWithoutParam.Explain:case exports.OpenAiPromptsWithoutParam.ActionItems:case exports.OpenAiPromptsWithParam.Translate:case exports.OpenAiPromptsWithParam.ChangeTone:o=!0,((t,e,o,n,r,s)=>{const a=o.state.selection;if(!a)return void o.dispatch(o.state.tr.setMeta(m,{task:t,status:exports.Status.done}));if(o.state.doc.textBetween(a.from,a.to).length>r)return void o.dispatch(o.state.tr.setMeta(m,{type:t,status:exports.Status.error,error:"Selection is too big"}));const i=o.state.doc.textBetween(a.from,a.to,"\n");W(0,i,0,o,t,a,s)})(r.type,0,t,0,e.maxSelection,r.params)}if((null==r?void 0:r.status)===exports.Status.accepted){if(r.error)return s.setMeta(m,{type:r.type,status:exports.Status.done}),void t.dispatch(s);switch(r.type){case exports.OpenAiPromptsWithoutParam.Complete:s=s.insertText(r.result||"",t.state.doc.nodeSize-2),s.setMeta(m,{type:exports.OpenAiPromptsWithoutParam.Complete,status:exports.Status.done}),t.dispatch(s),t.focus();break;case exports.OpenAiPromptsWithoutParam.MakeLonger:case exports.OpenAiPromptsWithoutParam.MakeShorter:case exports.OpenAiPromptsWithoutParam.Improve:case exports.OpenAiPromptsWithoutParam.Simplify:case exports.OpenAiPromptsWithoutParam.Explain:case exports.OpenAiPromptsWithoutParam.ActionItems:case exports.OpenAiPromptsWithParam.Translate:case exports.OpenAiPromptsWithParam.ChangeTone:if(r.selection&&r.result){const e=r.result.split("\n\n").map((e=>t.state.schema.node("paragraph",null,t.state.schema.text(e)))),o=g.Fragment.fromArray(e);s.selection.replace(s,new g.Slice(o,0,0))}s.setMeta(m,{type:r.type,status:exports.Status.done}),t.dispatch(s),t.focus()}}}})})},exports.completePluginKey=m,exports.defaultCompleteOptions=M,exports.defaultOptions=C,exports.grammarSuggestPlugin=(e,o=C)=>{let n=!1;return new i.Plugin({key:h,state:{init:()=>({lastText:"",decorations:p.DecorationSet.empty,popupDecoration:p.DecorationSet.empty}),apply(e,n,r,s){const a=e.getMeta(h);return(null==a?void 0:a.type)===t.suggestionUpdate?((t,e,o)=>{const{changedRegion:n,fix:r,mapping:s,text:a}=e,i=T(n.newText,r.result).filter((t=>!O(t))).filter((t=>t.original!==`${t.replacement}\n`)).map((({from:t,to:e,original:o,replacement:r})=>{const a=v(n.start+t,s),i=v(n.start+(r.endsWith("\n")?e-1:e),s),c={text:r.endsWith("\n")?r.slice(0,-1):r,originalText:o,id:{}};return p.Decoration.inline(a,i,{class:"grammarSuggestion "+(""===r?"removalSuggestion":"")},c)}));return Object.assign(Object.assign({},t),{decorations:t.decorations.add(o.doc,i),lastText:a})})(n,a,e):(null==a?void 0:a.type)===t.acceptSuggestion?((t,e,o)=>{const n=t.decorations.remove(t.decorations.find(0,o.doc.nodeSize,(t=>t.id===e.id)));return Object.assign(Object.assign({},t),{lastText:x(o.doc),decorations:n.map(o.mapping,o.doc),popupDecoration:p.DecorationSet.empty})})(n,a,e):(null==a?void 0:a.type)===t.openSuggestion?((t,e,o,n)=>{const{decoration:r}=e,s={id:r.spec.id};return Object.assign(Object.assign({},t),{popupDecoration:p.DecorationSet.create(o.doc,[p.Decoration.widget(r.from,((t,e)=>{const o=e();return o?n.createUpdatePopup(t,r,o,A,b):document.createElement("div")}),Object.assign(Object.assign({},s),{stopEvent:()=>!0}))])})})(n,a,e,o):(null==a?void 0:a.type)===t.closeSuggestion?Object.assign(Object.assign({},n),{popupDecoration:p.DecorationSet.empty}):(null==a?void 0:a.type)===t.discardSuggestion?((t,e,o)=>Object.assign(Object.assign({},t),{decorations:t.decorations.remove(t.decorations.find(0,o.doc.nodeSize,(t=>t.id===e.id))),popupDecoration:p.DecorationSet.empty}))(n,a,e):e.docChanged?((t,e,o,n)=>{const r=S(o.doc).text,{text:s,mapping:a}=S(e.doc);if(s===r)return t;let i=e.mapping;if(n){const t=e.doc.content.findDiffStart(o.doc.content),n=o.doc.content.findDiffEnd(e.doc.content),r=n&&t?new u.StepMap([t,n.a-t,n.b-t]):new u.StepMap([0,0,0]);i=new u.Mapping([r])}const p=f(r,s),c=t.decorations.map(i,e.doc),l=v(p.start,a),d=v(p.end,a),g=t.popupDecoration.map(i,e.doc);return Object.assign(Object.assign({},t),{decorations:c.remove(c.find(l,d)),popupDecoration:g.remove(g.find(l,d))})})(n,e,r,o.withYjs):n}},props:{handleClick:j,decorations:t=>{const e=h.getState(t);if(!e)return null;const o=m.getState(t);return(null==o?void 0:o.status)!==exports.Status.idle?e.decorations:e.decorations.add(t.doc,e.popupDecoration.find())}},view(){const r=((e,o)=>d((e=>{var n;const r=S(e.state.doc),s=(null===(n=h.getState(e.state))||void 0===n?void 0:n.lastText)||"",a=f(s,r.text);y(o,a.newText).then((o=>{if(x(e.state.doc)!==r.text)return;const n={type:t.suggestionUpdate,fix:o,changedRegion:a,mapping:r.mapping,text:r.text};e.dispatch(e.state.tr.setMeta(h,n))})).catch((t=>{console.error("Grammar suggest API error",t)}))}),e.debounceMs))(o,e);return{update(t,e){const o=h.getState(t.state);t.state.doc.textBetween(0,t.state.doc.nodeSize-2,"/n")===e.doc.textBetween(0,e.doc.nodeSize-2,"/n")&&n||!o||o.lastText===x(t.state.doc)||(n=!0,r(t))}}}})};
1
+ "use strict";var t,e,o,n,r,s,a,i=require("prosemirror-state"),p=require("prosemirror-view"),c=require("fast-diff"),l=require("tslib"),d=require("lodash.debounce"),u=require("prosemirror-transform"),g=require("prosemirror-model");!function(t){t.suggestionUpdate="suggestionUpdate",t.acceptSuggestion="acceptSuggestion",t.openSuggestion="openSuggestion",t.closeSuggestion="closeSuggestion",t.discardSuggestion="discardSuggestion"}(t||(t={})),function(t){t.grammarSuggestPopup="grammar-suggest-popup"}(e||(e={})),exports.MoodParamType=void 0,(o=exports.MoodParamType||(exports.MoodParamType={})).Casual="Casual",o.Confident="Confident",o.Straightforward="Straightforward",o.Friendly="Friendly",exports.TranslationTargetLanguage=void 0,(n=exports.TranslationTargetLanguage||(exports.TranslationTargetLanguage={})).English="English",n.Spanish="Spanish",n.French="French",n.German="German",n.Italian="Italian",n.Portuguese="Portuguese",n.Dutch="Dutch",n.Russian="Russian",n.Chinese="Chinese",n.Korean="Korean",n.Japanese="Japanese",exports.OpenAiPromptsWithoutParam=void 0,(r=exports.OpenAiPromptsWithoutParam||(exports.OpenAiPromptsWithoutParam={})).Complete="Complete",r.Improve="Improve",r.MakeLonger="MakeLonger",r.MakeShorter="MakeShorter",r.Simplify="Simplify",r.Explain="Explain",r.ActionItems="ActionItems",exports.OpenAiPromptsWithParam=void 0,(s=exports.OpenAiPromptsWithParam||(exports.OpenAiPromptsWithParam={})).ChangeTone="ChangeTone",s.Translate="Translate",exports.Status=void 0,(a=exports.Status||(exports.Status={})).idle="idle",a.new="new",a.streaming="streaming",a.finished="finished",a.accepted="accepted",a.cancelled="cancelled",a.rejected="rejected",a.done="done",a.error="error";const m=new i.PluginKey("completePlugin"),h=new i.PluginKey("grammarSuggestPlugin"),x=t=>{let e="";return t.descendants(((t,o)=>{t.isText&&(e+=`${t.text}\n`)})),e},f=(t,e)=>{if(t===e)return{start:t.length,end:t.length,oldStart:t.length,oldEnd:t.length,oldText:"",newText:""};const o=c(t,e),n=o[0],r=n[0]===c.EQUAL?n[1].length-1:0,s=((t,e)=>{if(e[e.length-1][0]!==c.EQUAL)return t.length;const o=e.slice(0,e.length-1);let n=0;for(const t of o){const[e,o]=t;e===c.EQUAL&&(n+=o.length),e===c.DELETE&&(n+=o.length)}return n})(t,o),a=t.lastIndexOf("\n",r),i=t.indexOf("\n",s),p=-1===a?0:a+1,l=-1===i?t.length:i,d=t.slice(p,l),u=e.slice(p,e.length-(t.length-l));return{start:p,end:p+u.length,oldStart:p,oldEnd:l,oldText:d,newText:u}},P=[{docPos:1,textPos:0}],S=t=>{let e="";const o=[];return t.descendants(((t,n)=>{t.isText&&(o.push({docPos:n,textPos:e.length}),e+=`${t.text}\n`)})),{text:e,mapping:o.length?o:P}},v=(t,e)=>{for(let o=0;o<e.length;o++)if(t>=e[o].textPos&&(void 0===e[o+1]||t<e[o+1].textPos))return e[o].docPos+(t-e[o].textPos);throw new Error("textPositionToDocumentPosition: textPos not found in mapping")},y=(t,e)=>l.__awaiter(void 0,void 0,void 0,(function*(){const o=[...e.split("\n")];return fetch("https://prosemirror-ai-plugin.web.app/api/suggestion",{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({model:"gpt-3.5-turbo",modelParams:{input:o}})}).then((t=>t.ok?t.json():Promise.reject(t))).then((t=>!t||t.some((t=>(t=>{try{JSON.parse(t)}catch(t){return!0}return!1})(t)))?{fixed:!1,result:e}:{result:t.map((t=>JSON.parse(t).result)).join("\n"),fixed:!0})).catch((t=>(t.text().then((e=>{console.error({status:t.status,text:e})})),{fixed:!1,result:e})))})),O=t=>t.replacement===t.original,w=t=>t.reduce(((t,e)=>{const o=t[t.length-1],n=t.slice(0,t.length-1);if(!o)return[e];return[...n,...((t,e)=>{if(t.to!==e.from)throw new Error(`Replace pairs must be adjacent\n\n, ${JSON.stringify({leftReplace:t,rightReplace:e})}`);if(t.replacement.endsWith("\n"))return[t,e];if(O(t)&&O(e))return[{from:t.from,to:e.to,original:t.original+e.original,replacement:t.replacement+e.replacement}];if(O(t)){if(e.replacement.startsWith(" ")&&""===e.original||e.original.startsWith(" ")&&""===e.replacement)return[t,e];const o=t.original.split(" "),n=o.pop()||"",r=o.join(" ")+(o.length?" ":"");return[...r.length?[{from:t.from,to:t.from+r.length,original:r,replacement:r}]:[],{from:t.from+r.length,to:e.to,original:n+e.original,replacement:n+e.replacement}]}if(O(e)){if(t.replacement.endsWith(" ")&&""===t.original||t.original.endsWith(" ")&&""===t.replacement)return[t,e];const o=e.original.split(" "),n=o.shift()||"",r=(o.length?" ":"")+o.join(" ");return" "===r?[{from:t.from,to:e.to,original:t.original+e.original,replacement:t.replacement+e.replacement}]:[{from:t.from,to:t.to+n.length,original:t.original+n,replacement:t.replacement+n},...r.length?[{from:t.to+n.length,to:e.to,original:r,replacement:r}]:[]]}return[{from:t.from,to:e.to,original:t.original+e.original,replacement:t.replacement+e.replacement}]})(o,e)]}),[]),T=(t,e)=>{const o=(t=>{let e=0;return t.map((([t,o])=>{switch(t){case c.EQUAL:const t=o.lastIndexOf("\n"),n={from:e,to:e+o.length,original:o,replacement:o};if(-1!==t&&"\n"!==o){const n=[{from:e,to:e+t+1,original:o.slice(0,t+1),replacement:o.slice(0,t+1)},{from:e+t+1,to:e+o.length,original:o.slice(t+1),replacement:o.slice(t+1)}];return e+=o.length,n}return e+=o.length,[n];case c.DELETE:const r={from:e,to:e+o.length,original:o,replacement:""};return e+=o.length,[r];case c.INSERT:return[{from:e,to:e,original:"",replacement:o}]}})).flat()})(c(t,e));return w(w(o))},A=(e,o)=>{var n;const r=null===(n=h.getState(e.state))||void 0===n?void 0:n.decorations.find(0,e.state.doc.nodeSize,(t=>t.id===o.spec.id))[0];if(!r)return;const{text:s}=r.spec,{from:a,to:p}=r,c={type:t.acceptSuggestion,id:o.spec.id},l=s.split("\n").map((t=>e.state.schema.node("paragraph",null,e.state.schema.text(t)))),d=g.Fragment.fromArray(l);let{tr:u}=e.state;u=u.setSelection(i.TextSelection.create(e.state.doc,a,p)),u.selection.replace(u,new g.Slice(d,1,1)),u.setMeta(h,c),e.dispatch(u)},b=(e,o)=>{const{spec:n}=o,r={type:t.discardSuggestion,id:n.id},s=e.state.tr.setMeta(h,r);e.dispatch(s)},j=(e,o)=>{const n=h.getState(e.state);if(!n)return!1;const{decorations:r}=n,s=r.find(o,o)[0];if(!s){const o={type:t.closeSuggestion};return e.dispatch(e.state.tr.setMeta(h,o)),!1}const a=n.popupDecoration.find()[0];if((null==a?void 0:a.spec.id)===s.spec.id)return!1;const i={type:t.openSuggestion,decoration:s};return e.dispatch(e.state.tr.setMeta(h,i)),!1},C={debounceMs:2e3,createUpdatePopup:(t,o,n,r,s)=>{const a=document.createElement("div");a.className="grammar-suggest-tooltip";const{spec:i}=o,p=t.dom.getBoundingClientRect();a.id=e.grammarSuggestPopup;const c=t.coordsAtPos(n),l=t.dom.scrollTop||0,d=t.dom.scrollLeft||0;a.style.left=`${c.left-p.left+d}px`,a.style.top=`${c.bottom-p.top+l+5}px`;const u=document.createElement("div");u.className="grammar-suggest-tooltip-apply",u.innerText=i.text||i.originalText,i.text||(u.style.textDecoration="line-through",u.style.color="red"),u.onclick=()=>{r(t,o)},a.appendChild(u);const g=document.createElement("div");return g.innerHTML="<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'><path d='M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 10.5858L14.8284 7.75736L16.2426 9.17157L13.4142 12L16.2426 14.8284L14.8284 16.2426L12 13.4142L9.17157 16.2426L7.75736 14.8284L10.5858 12L7.75736 9.17157L9.17157 7.75736L12 10.5858Z'></path></svg>",g.className="grammar-suggest-tooltip-discard",g.onclick=()=>{s(t,o)},a.appendChild(g),a},withYjs:!1},M={maxSelection:1e3},W=(t,e,o,n,r,s,a)=>l.__awaiter(void 0,void 0,void 0,(function*(){var t;let o="";const i=new AbortController;try{const p=null===(t=(yield fetch("https://suggestion-gw5lxik4dq-uc.a.run.app",{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json",Authorization:"Bearer -qKivjCv6MfQSmgF438PjEY7RnLfqoVe"},signal:i.signal,body:JSON.stringify({model:"gpt-3.5-turbo",modelParams:{input:[e],task:r,params:a}})})).body)||void 0===t?void 0:t.getReader(),c=({done:t,value:e})=>l.__awaiter(void 0,void 0,void 0,(function*(){var a;if(t)return;if(null===(a=m.getState(n.state))||void 0===a?void 0:a.isCancelled)return void(yield i.abort());const l=(new TextDecoder).decode(e);try{o+=l,n.dispatch(n.state.tr.setMeta(m,Object.assign({type:r,status:exports.Status.streaming,result:o},s&&{selection:s})))}catch(t){console.error("Could not parse stream message",l,t)}return null==p?void 0:p.read().then(c)}));yield null==p?void 0:p.read().then(c),n.dispatch(n.state.tr.setMeta(m,Object.assign({type:r,status:exports.Status.finished,result:o},s&&{selection:s})))}catch(t){console.error("Error:",t)}}));exports.completePlugin=(t,e=M)=>{let o=!1;return new i.Plugin({key:m,state:{init:()=>({status:exports.Status.idle}),apply(t,e,n,r){const s=t.getMeta(m);return e.status===exports.Status.done||e.status===exports.Status.rejected?(o=!1,{status:exports.Status.idle}):(null==s?void 0:s.status)===exports.Status.cancelled?Object.assign(Object.assign(Object.assign({},e),s),{isCancelled:!0}):s&&(t=>Object.values(exports.OpenAiPromptsWithParam).includes(t.type)||Object.values(exports.OpenAiPromptsWithoutParam).includes(t.type))(s)?e.type&&s.type!==e.type?e:Object.assign(Object.assign({},e),s):e}},view:()=>({update(t,n){const r=m.getState(t.state);let s=t.state.tr;if((null==r?void 0:r.status)===exports.Status.new&&!o)switch(r.type){case exports.OpenAiPromptsWithoutParam.Complete:o=!0,((t,e,o)=>{l.__awaiter(void 0,void 0,void 0,(function*(){const{doc:t}=e.state,o=[];t.descendants((t=>{"paragraph"===t.type.name&&o.push(t.textContent)}));let n="";n=o.length>=2?o.slice(-2).join(" "):o.join(" "),W(0,n,0,e,exports.OpenAiPromptsWithoutParam.Complete)}))})(0,t);break;case exports.OpenAiPromptsWithoutParam.MakeLonger:case exports.OpenAiPromptsWithoutParam.MakeShorter:case exports.OpenAiPromptsWithoutParam.Improve:case exports.OpenAiPromptsWithoutParam.Simplify:case exports.OpenAiPromptsWithoutParam.Explain:case exports.OpenAiPromptsWithoutParam.ActionItems:case exports.OpenAiPromptsWithParam.Translate:case exports.OpenAiPromptsWithParam.ChangeTone:o=!0,((t,e,o,n,r,s)=>{const a=o.state.selection;if(!a)return void o.dispatch(o.state.tr.setMeta(m,{task:t,status:exports.Status.done}));if(o.state.doc.textBetween(a.from,a.to).length>r)return void o.dispatch(o.state.tr.setMeta(m,{type:t,status:exports.Status.error,error:"Selection is too big"}));const i=o.state.doc.textBetween(a.from,a.to,"\n");W(0,i,0,o,t,a,s)})(r.type,0,t,0,e.maxSelection,r.params)}if((null==r?void 0:r.status)===exports.Status.accepted){if(r.error)return s.setMeta(m,{type:r.type,status:exports.Status.done}),void t.dispatch(s);switch(r.type){case exports.OpenAiPromptsWithoutParam.Complete:s=s.insertText(r.result||"",t.state.doc.nodeSize-2),s.setMeta(m,{type:exports.OpenAiPromptsWithoutParam.Complete,status:exports.Status.done}),t.dispatch(s),t.focus();break;case exports.OpenAiPromptsWithoutParam.MakeLonger:case exports.OpenAiPromptsWithoutParam.MakeShorter:case exports.OpenAiPromptsWithoutParam.Improve:case exports.OpenAiPromptsWithoutParam.Simplify:case exports.OpenAiPromptsWithoutParam.Explain:case exports.OpenAiPromptsWithoutParam.ActionItems:case exports.OpenAiPromptsWithParam.Translate:case exports.OpenAiPromptsWithParam.ChangeTone:if(r.selection&&r.result){const e=r.result.split("\n\n").map((e=>t.state.schema.node("paragraph",null,t.state.schema.text(e)))),o=g.Fragment.fromArray(e);s.selection.replace(s,new g.Slice(o,0,0))}s.setMeta(m,{type:r.type,status:exports.Status.done}),t.dispatch(s),t.focus()}}}})})},exports.completePluginKey=m,exports.defaultCompleteOptions=M,exports.defaultOptions=C,exports.grammarSuggestPlugin=(e,o=C)=>{let n=!1;return new i.Plugin({key:h,state:{init:()=>({lastText:"",decorations:p.DecorationSet.empty,popupDecoration:p.DecorationSet.empty}),apply(e,n,r,s){const a=e.getMeta(h);return(null==a?void 0:a.type)===t.suggestionUpdate?((t,e,o)=>{const{changedRegion:n,fix:r,mapping:s,text:a}=e,i=T(n.newText,r.result).filter((t=>!O(t))).filter((t=>t.original!==`${t.replacement}\n`)).map((({from:t,to:e,original:o,replacement:r})=>{const a=v(n.start+t,s),i=v(n.start+(r.endsWith("\n")?e-1:e),s),c={text:r.endsWith("\n")?r.slice(0,-1):r,originalText:o,id:{}};return p.Decoration.inline(a,i,{class:"grammarSuggestion "+(""===r?"removalSuggestion":"")},c)}));return Object.assign(Object.assign({},t),{decorations:t.decorations.add(o.doc,i),lastText:a})})(n,a,e):(null==a?void 0:a.type)===t.acceptSuggestion?((t,e,o)=>{const n=t.decorations.remove(t.decorations.find(0,o.doc.nodeSize,(t=>t.id===e.id)));return Object.assign(Object.assign({},t),{lastText:x(o.doc),decorations:n.map(o.mapping,o.doc),popupDecoration:p.DecorationSet.empty})})(n,a,e):(null==a?void 0:a.type)===t.openSuggestion?((t,e,o,n)=>{const{decoration:r}=e,s={id:r.spec.id};return Object.assign(Object.assign({},t),{popupDecoration:p.DecorationSet.create(o.doc,[p.Decoration.widget(r.from,((t,e)=>{const o=e();return o?n.createUpdatePopup(t,r,o,A,b):document.createElement("div")}),Object.assign(Object.assign({},s),{stopEvent:()=>!0}))])})})(n,a,e,o):(null==a?void 0:a.type)===t.closeSuggestion?Object.assign(Object.assign({},n),{popupDecoration:p.DecorationSet.empty}):(null==a?void 0:a.type)===t.discardSuggestion?((t,e,o)=>Object.assign(Object.assign({},t),{decorations:t.decorations.remove(t.decorations.find(0,o.doc.nodeSize,(t=>t.id===e.id))),popupDecoration:p.DecorationSet.empty}))(n,a,e):e.docChanged?((t,e,o,n)=>{const r=S(o.doc).text,{text:s,mapping:a}=S(e.doc);if(s===r)return t;let i=e.mapping;if(n){const t=e.doc.content.findDiffStart(o.doc.content),n=o.doc.content.findDiffEnd(e.doc.content),r=n&&t?new u.StepMap([t,n.a-t,n.b-t]):new u.StepMap([0,0,0]);i=new u.Mapping([r])}const p=f(r,s),c=t.decorations.map(i,e.doc),l=v(p.start,a),d=v(p.end,a),g=t.popupDecoration.map(i,e.doc);return Object.assign(Object.assign({},t),{decorations:c.remove(c.find(l,d)),popupDecoration:g.remove(g.find(l,d))})})(n,e,r,o.withYjs):n}},props:{handleClick:j,decorations:t=>{const e=h.getState(t);if(!e)return null;const o=m.getState(t);return(null==o?void 0:o.status)!==exports.Status.idle?e.decorations:e.decorations.add(t.doc,e.popupDecoration.find())}},view(){const r=((e,o)=>d((e=>{var n;const r=S(e.state.doc),s=(null===(n=h.getState(e.state))||void 0===n?void 0:n.lastText)||"",a=f(s,r.text);y(o,a.newText).then((o=>{if(x(e.state.doc)!==r.text)return;const n={type:t.suggestionUpdate,fix:o,changedRegion:a,mapping:r.mapping,text:r.text};e.dispatch(e.state.tr.setMeta(h,n))})).catch((t=>{console.error("Grammar suggest API error",t)}))}),e.debounceMs))(o,e);return{update(t,e){const o=h.getState(t.state);t.state.doc.textBetween(0,t.state.doc.nodeSize-2,"/n")===e.doc.textBetween(0,e.doc.nodeSize-2,"/n")&&n||!o||o.lastText===x(t.state.doc)||(n=!0,r(t))}}}})};
@@ -0,0 +1,96 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import debounce from "lodash.debounce";
11
+ import { getChangedRegions, getTextWithNewlines, grammarSuggestPluginKey, } from "./utils";
12
+ import { GrammarSuggestMetaType, } from "./types";
13
+ import { docToTextWithMapping } from "./mapping";
14
+ const isJsonString = (str) => {
15
+ try {
16
+ JSON.parse(str);
17
+ }
18
+ catch (e) {
19
+ return true;
20
+ }
21
+ return false;
22
+ };
23
+ const myApiRequest = (apiKey, text) => __awaiter(void 0, void 0, void 0, function* () {
24
+ const input = [...text.split("\n")];
25
+ // return fetch("https://prosemirror-ai-plugin.web.app/api/suggestion", {
26
+ return fetch("http://127.0.0.1:5001/prosemirror-ai-plugin/us-central1/suggestion", {
27
+ method: "POST",
28
+ cache: "no-cache",
29
+ headers: {
30
+ "Content-Type": "application/json",
31
+ Authorization: `Bearer ${apiKey}`,
32
+ },
33
+ body: JSON.stringify({
34
+ model: "gpt-3.5-turbo",
35
+ modelParams: {
36
+ input,
37
+ },
38
+ }),
39
+ })
40
+ .then((response) => {
41
+ if (response.ok) {
42
+ return response.json();
43
+ }
44
+ return Promise.reject(response);
45
+ })
46
+ .then((jsonData) => {
47
+ if (!jsonData || jsonData.some((i) => isJsonString(i))) {
48
+ return {
49
+ fixed: false,
50
+ result: text,
51
+ };
52
+ }
53
+ return {
54
+ result: jsonData
55
+ .map((data) => JSON.parse(data).result)
56
+ .join("\n"),
57
+ fixed: true,
58
+ };
59
+ })
60
+ .catch((e) => {
61
+ e.text().then((text) => {
62
+ console.error({ status: e.status, text });
63
+ });
64
+ return {
65
+ fixed: false,
66
+ result: text,
67
+ };
68
+ });
69
+ });
70
+ export const createMakeRequest = (options, apiKey) => debounce((view) => {
71
+ var _a;
72
+ // The document changed, start API request
73
+ const versionAtRequestStart = docToTextWithMapping(view.state.doc);
74
+ const oldText = ((_a = grammarSuggestPluginKey.getState(view.state)) === null || _a === void 0 ? void 0 : _a.lastText) || "";
75
+ const changedRegion = getChangedRegions(oldText, versionAtRequestStart.text);
76
+ myApiRequest(apiKey, changedRegion.newText)
77
+ .then((fix) => {
78
+ // Check if the document version has changed while we were waiting
79
+ if (getTextWithNewlines(view.state.doc) !== versionAtRequestStart.text) {
80
+ // The state changed, abort
81
+ return;
82
+ }
83
+ // State did not change, update the plugin state
84
+ const meta = {
85
+ type: GrammarSuggestMetaType.suggestionUpdate,
86
+ fix,
87
+ changedRegion,
88
+ mapping: versionAtRequestStart.mapping,
89
+ text: versionAtRequestStart.text,
90
+ };
91
+ view.dispatch(view.state.tr.setMeta(grammarSuggestPluginKey, meta));
92
+ })
93
+ .catch((error) => {
94
+ console.error("Grammar suggest API error", error);
95
+ });
96
+ }, options.debounceMs);
package/dist/utils.js ADDED
@@ -0,0 +1,82 @@
1
+ import { PluginKey } from "prosemirror-state";
2
+ import diff from "fast-diff";
3
+ import { OpenAiPromptsWithoutParam, OpenAiPromptsWithParam, } from "./types";
4
+ export const completePluginKey = new PluginKey("completePlugin");
5
+ export const isCompleteMeta = (meta) => {
6
+ return (Object.values(OpenAiPromptsWithParam).includes(meta.type) ||
7
+ Object.values(OpenAiPromptsWithoutParam).includes(meta.type));
8
+ };
9
+ export const grammarSuggestPluginKey = new PluginKey("grammarSuggestPlugin");
10
+ export const getTextWithNewlines = (node) => {
11
+ let text = "";
12
+ node.descendants((n, pos) => {
13
+ if (n.isText) {
14
+ text += `${n.text}\n`;
15
+ }
16
+ });
17
+ console.log({ text });
18
+ return text;
19
+ };
20
+ const getLastChangePos = (oldText, changes) => {
21
+ const lastChange = changes[changes.length - 1];
22
+ if (lastChange[0] !== diff.EQUAL)
23
+ return oldText.length;
24
+ const changesWithoutLast = changes.slice(0, changes.length - 1);
25
+ let lastChangePos = 0;
26
+ for (const change of changesWithoutLast) {
27
+ const [type, text] = change;
28
+ if (type === diff.EQUAL) {
29
+ lastChangePos += text.length;
30
+ }
31
+ if (type === diff.DELETE) {
32
+ lastChangePos += text.length;
33
+ }
34
+ }
35
+ return lastChangePos;
36
+ };
37
+ // TODO: when enters are pressed the new paragraphs are not part of the region
38
+ // - Make a diff between the last stored text and the current one.
39
+ // - We get the end of the beginning identity and the start of the end identity.
40
+ // - Get the first & last newlines before the start and after the end.
41
+ export const getChangedRegions = (oldText, newText) => {
42
+ if (oldText === newText)
43
+ return {
44
+ start: oldText.length,
45
+ end: oldText.length,
46
+ oldStart: oldText.length,
47
+ oldEnd: oldText.length,
48
+ oldText: "",
49
+ newText: "",
50
+ };
51
+ const changes = diff(oldText, newText);
52
+ const fistChange = changes[0];
53
+ const firstChangePos = fistChange[0] === diff.EQUAL ? fistChange[1].length - 1 : 0;
54
+ const lastChangePos = getLastChangePos(oldText, changes);
55
+ const firstNewlinePosFromFirstChange = oldText.lastIndexOf("\n", firstChangePos);
56
+ const lastNewlinePosFromLastChange = oldText.indexOf("\n", lastChangePos);
57
+ const oldStart = firstNewlinePosFromFirstChange === -1
58
+ ? 0
59
+ : firstNewlinePosFromFirstChange + 1;
60
+ const oldEnd = lastNewlinePosFromLastChange === -1
61
+ ? oldText.length
62
+ : lastNewlinePosFromLastChange;
63
+ // console.log({
64
+ // oldText,
65
+ // lastChangePos,
66
+ // lastNewlinePosFromLastChange,
67
+ // oldEnd,
68
+ // firstChangePos,
69
+ // firstNewlinePosFromFirstChange,
70
+ // oldStart,
71
+ // });
72
+ const oldChange = oldText.slice(oldStart, oldEnd);
73
+ const newChange = newText.slice(oldStart, newText.length - (oldText.length - oldEnd));
74
+ return {
75
+ start: oldStart,
76
+ end: oldStart + newChange.length,
77
+ oldStart,
78
+ oldEnd,
79
+ oldText: oldChange,
80
+ newText: newChange,
81
+ };
82
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-suggestcat-plugin",
3
- "version": "0.1.8",
3
+ "version": "0.1.11",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",