10 lines
14 KiB
JavaScript
10 lines
14 KiB
JavaScript
/*!
|
|
* Tiny AI plugin
|
|
*
|
|
* Copyright (c) 2023 Ephox Corporation DBA Tiny Technologies, Inc.
|
|
* Licensed under the Tiny commercial license. See https://www.tiny.cloud/legal/
|
|
*
|
|
* Version: 1.2.0-67
|
|
*/
|
|
|
|
!function(){"use strict";const e=e=>parseInt(e,10),t=(e,t)=>{const n=e-t;return 0===n?0:n>0?1:-1},n=(e,t,n)=>({major:e,minor:t,patch:n}),r=t=>{const r=/([0-9]+)\.([0-9]+)\.([0-9]+)(?:(\-.+)?)/.exec(t);return r?n(e(r[1]),e(r[2]),e(r[3])):n(0,0,0)},o=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=r=e,(o=String).prototype.isPrototypeOf(n)||(null===(s=r.constructor)||void 0===s?void 0:s.name)===o.name)?"string":t;var n,r,o,s})(t)===e,s=e=>t=>typeof t===e,i=o("string"),a=o("object"),l=o("array"),c=s("boolean"),p=e=>!(e=>null==e)(e),u=s("function"),m=()=>{};function d(e,...t){return(...n)=>{const r=t.concat(n);return e.apply(null,r)}}const g=e=>{e()},h=()=>!1;class y{constructor(e,t){this.tag=e,this.value=t}static some(e){return new y(!0,e)}static none(){return y.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?y.some(e(this.value)):y.none()}bind(e){return this.tag?e(this.value):y.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:y.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return p(e)?y.some(e):y.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}y.singletonNone=new y(!1);const f=(e,t)=>{for(let n=0,r=e.length;n<r;n++)t(e[n],n)},b=Object.hasOwnProperty,v=(e,t)=>b.call(e,t),w=(e,t)=>e?y.some(t):y.none(),A="generate",T="insert",I="discard",E="stop",S="regenerate",x="prompt",C="AI shortcuts",R="ai-prompt",k="Integration Error: {0}.",_="Response was not a string",O="respondWith was not used",D="An error occurred.",q=[{title:"Summarize content",prompt:"Provide the key points and concepts in this content in a succinct summary.",selection:!0},{title:"Improve writing",prompt:"Rewrite this content with no spelling mistakes, proper grammar, and with more descriptive language, using best writing practices without losing the original meaning.",selection:!0},{title:"Simplify language",prompt:"Rewrite this content with simplified language and reduce the complexity of the writing, so that the content is easier to understand.",selection:!0},{title:"Expand upon",prompt:"Expand upon this content with descriptive language and more detailed explanations, to make the writing easier to understand and increase the length of the content.",selection:!0},{title:"Trim content",prompt:"Remove any repetitive, redundant, or non-essential writing in this content without changing the meaning or losing any key information.",selection:!0},{title:"Change tone",subprompts:[{title:"Professional",prompt:"Rewrite this content using polished, formal, and respectful language to convey professional expertise and competence.",selection:!0},{title:"Casual",prompt:"Rewrite this content with casual, informal language to convey a casual conversation with a real person.",selection:!0},{title:"Direct",prompt:"Rewrite this content with direct language using only the essential information.",selection:!0},{title:"Confident",prompt:"Rewrite this content using compelling, optimistic language to convey confidence in the writing.",selection:!0},{title:"Friendly",prompt:"Rewrite this content using friendly, comforting language, to convey understanding and empathy.",selection:!0}]},{title:"Change style",subprompts:[{title:"Business",prompt:"Rewrite this content as a business professional with formal language.",selection:!0},{title:"Legal",prompt:"Rewrite this content as a legal professional using valid legal terminology.",selection:!0},{title:"Journalism",prompt:"Rewrite this content as a journalist using engaging language to convey the importance of the information.",selection:!0},{title:"Medical",prompt:"Rewrite this content as a medical professional using valid medical terminology.",selection:!0},{title:"Poetic",prompt:"Rewrite this content as a poem using poetic techniques without losing the original meaning.",selection:!0}]}],N=e=>t=>t.options.get(e),M=("ai_request",e=>(e=>y.from(N("ai_request")(e)).filter(u))(e).getOrDie("ai_request has not been implemented."));const j=e=>y.from(N("ai_shortcuts")(e)).filter((e=>e.length>0)),L=N("body_class"),$=N("content_style"),P=N("content_css_cors"),B=(e,t)=>t.parse(e,{insert:!0}),z=(e,t)=>{e.execCommand("mceAiDialog",!1,t)},U=(e,t)=>n=>{const r=e=>()=>n.setEnabled(e),o=r(!0),s=r(!1);return e.on("AIResponse AIError AIDialogClose",o),e.on("AIRequest",s),t.isInProgress()?s():o(),()=>{e.off("AIResponse AIError AIDialogClose",o),e.off("AIRequest",s)}},H=(e,t)=>n=>(n.setEnabled(y.from(t.selection).forall((t=>e.selection.isCollapsed()!==t))),m),K=(e,t)=>((t,n)=>{const r=t.length,o=new Array(r);for(let n=0;n<r;n++){const r=t[n];o[n]=(e=>{return v(t=e,n="subprompts")&&void 0!==t[n]&&null!==t[n];var t,n})(s=r)?((e,t)=>({type:"nestedmenuitem",text:t.title,getSubmenuItems:()=>K(e,t.subprompts)}))(e,s):((e,t)=>({type:"menuitem",text:t.title,value:t.prompt,onSetup:H(e,t),onAction:()=>z(e,{prompt:t.prompt,generate:!0,display:!1})}))(e,s)}var s;return o})(t),W=e=>(t,n)=>{const r=(o=i(n)?B(n,t.parser):n,s=t.schema,tinymce.html.Serializer({validate:!0},s).serialize(o));var o,s;const a=y.from($(t)).map((e=>`<style type="text/css">${e}</style>`)).getOr(""),l=y.from(P(t)).map((e=>e?' crossorigin="anonymous"':"")).getOr(""),c=(p=t.contentCSS,u=(e,n)=>`${e}<link type="text/css" rel="stylesheet" href="${t.documentBaseURI.toAbsolute(n)}"${l}>`,m="",f(p,((e,t)=>{m=u(m,e)})),m);var p,u,m;const d=t.dom.encode,g=`<body${y.from(L(t)).map((e=>` class="${d(e)}"`)).getOr("")}${y.from(t.getBody()).map((e=>d(e.dir))).bind((e=>w(""!==e,` dir="${e}"`))).getOr("")}>`,h=tinymce.Env.os,b='<script>document.addEventListener && document.addEventListener("click", function(e) {for (var elm = e.target; elm; elm = elm.parentNode) {if (elm.nodeName === "A" && !('+(h.isMacOS()||h.isiOS()?"e.metaKey":"e.ctrlKey && !e.altKey")+")) {e.preventDefault();}}}, false);<\/script> ",v=e?"<style>* { opacity: 80% }</style>":"";return`<!DOCTYPE html><html><head><base href="${d(t.documentBaseURI.getURI())}">`+c+a+"<style>table, table td, table th, table caption { border: 1px dashed #bbb }</style>"+v+b+"</head>"+g+r+"</body></html>"},J=W(!1),F=W(!0),G={prompt:"",generate:!1,display:!0},V=e=>{let t=e;return{get:()=>t,set:e=>{t=e}}},Q=()=>{const e=(e=>{const t=V(y.none()),n=()=>t.get().each(e);return{clear:()=>{n(),t.set(y.none())},isSet:()=>t.get().isSome(),get:()=>t.get(),set:e=>{n(),t.set(y.some(e))}}})(m);return{...e,on:t=>e.get().each(t)}},Y=(e,t)=>e.dispatch("AIResponse",{response:t}),X=(e,t)=>e.dispatch("AIError",{error:t}),Z=(e,t)=>{const n=tinymce.util.I18n,r=M(e),o=Q(),s=o.isSet,a=e=>()=>o.get().exists((t=>t===e)),l=a("stream"),c=a("string"),u=Q();return{isInProgress:s,isStream:l,isString:c,closeStream:()=>u.on(g),submitRequest:(s,a,l,c,m)=>{const d=new window.AbortController,g=d.signal;let h=!1;const y={string:r=>{(async r=>{const p="string";o.set(p),h=!0;try{const l=await r(g);if(!i(l)){const e=n.translate([k,_]);throw console.error(e,l),new TypeError(e)}const u={type:p,data:l};t.addNewThreadEvent(s,a,{response:u}),Y(e,u),c(u.data)}catch(n){const r=n;t.addNewThreadEvent(s,a,{error:{type:p,error:r}}),X(e,r),l(r)}finally{o.clear()}})(r)},stream:r=>{(async r=>{const p="stream";o.set(p),h=!0;let y="";const f=()=>{g.removeEventListener("abort",b),u.clear()},b=()=>{const n={type:p,data:y};t.addNewThreadEvent(s,a,{response:n}),Y(e,n),c(y),f()};g.addEventListener("abort",b),u.set((()=>d.abort()));try{await r(g,(e=>{if(!i(e)){const t=n.translate([k,_]);throw console.error(t,e),new TypeError(t)}y+=e,m(y)})).then(b)}catch(n){u.on((e=>{f(),e()}));const r={type:p,data:y},o=n;t.addNewThreadEvent(s,a,{response:r,error:{type:p,error:o}}),Y(e,r),X(e,o),l(o)}finally{o.clear()}})(r)}},f=r(((n,r)=>{const o=((e,n)=>({thread:t.getThread(n).getOr([]),...e}))(n,r);return((e,t)=>{e.dispatch("AIRequest",{request:t})})(e,o),o})(s,a),y);if(p(f)&&console.warn("Integration Warning: ai_request return type was not void."),!h){const r=n.translate([k,O]);console.error(r),t.addNewThreadEvent(s,a,{error:{type:"invalid",error:r}}),X(e,r),l(r)}}}};let ee=0;const te=e=>{const t=(new Date).getTime(),n=Math.floor(1e9*Math.random());return ee++,e+"_"+n+ee+String(t)},ne=()=>{const e=V({}),t=e.get,n=e.set,r=e=>y.from(t()[e]),o=(e,r)=>{const o=t();return o[e]=r,n(o),r};return{getThreadLog:t,setThreadLog:n,createThread:(e=[])=>{const t=te("mce-aithread");return o(t,e),t},getThread:r,setThread:o,getLatestThreadEvent:e=>r(e).bind((e=>((e,t,n)=>{for(let r=0,o=e.length;r<o;r++){const o=e[r];if(t(o,r))return y.some(o);if(n(o,r))break}return y.none()})(e,(e=>v(e,"response")),h))),addNewThreadEvent:(e,t,n)=>{((e,t)=>{r(e).map((n=>o(e,t.concat(n))))})(t,[{eventUid:te("mce-aithreadevent"),timestamp:(new Date).toISOString(),request:e,...n}])}}},re=["Answer the question based on the context below.","The response should be in HTML format.","The response should preserve any HTML formatting, links, and styles in the context."],oe=(e,t)=>`${re.join("\n")}\n\nContext:${t.map((e=>`"""${e}"""`)).getOr('""')}\n\nQuestion: """${e}"""\n\nAnswer:`,se={type:"input",name:x,placeholder:"Ask AI to edit or generate...",maximized:!0},ie=e=>({type:"button",name:A,text:"Generate",icon:"send",buttonType:e?"primary":"secondary"}),ae={type:"bar",items:[se,ie(!0)]},le=[ae],ce=e=>({type:"iframe",name:"preview",border:!0,sandboxed:!1,streamContent:e,transparent:!0}),pe={type:"button",name:T,text:"Insert",buttonType:"primary"},ue={type:"button",name:I,text:"Discard",buttonType:"secondary"},me={...ue,name:E,text:"Stop"},de={type:"button",name:S,text:"Try again",buttonType:"secondary"},ge=e=>({type:"bar",items:[pe,de,e?me:ue]}),he={type:"label",items:[],label:"AI responses can be inaccurate",align:"end"},ye=e=>({type:"grid",columns:2,items:[ge(e),he]}),fe={type:"htmlpanel",html:""},be={type:"bar",items:[se,ie(!1)]},ve=e=>[ce(e),ye(e),fe,be],we=ve(!0),Ae=ve(!1),Te=(e,t,n)=>{const r=Q(),o=Q(),s=Q(),a=V(""),l=e=>t=>{t.setEnabled(E,!e),f([A,T,x,S],(n=>t.setEnabled(n,e)))},c=l(!1),p=l(!0),u=(e,t)=>{t.setEnabled(A,""!==e)},m=(t,r)=>{const o=V(!1),l=(e,t)=>({...r,prompt:e,preview:t}),m=(e,n)=>{t.unblock(),t.redial(k(e,n))},d=("error",n=>{const o=((e,t)=>({type:"label",label:"",items:[{type:"alertbanner",level:t,text:e,icon:"warning"}]}))(n,"error");s.get().map((t=>J(e,t))).fold((()=>m((e=>[e,fe,ae])(o),l(r.prompt))),(e=>m((e=>[ce(!1),ye(!1),e,fe,be])(o),l(r.prompt,e)))),t.focus(x)});const g=e=>{const t=i(e)?e:e instanceof Error?e.message:D;d(t)},h=r=>{const o=n.isStream();s.set(r);const i=J(e,r);if(o)t.setData({preview:i}),p(t);else{const e=l("",i);m(Ae,e)}u("",t),t.focus(x)},y=n=>{s.set(n),o.get()?t.setData({preview:F(e,n)}):((e,t)=>{const n=((e,t)=>{const n=B(e,t);let r=n;do{8===(null==r?void 0:r.type)&&r.remove()}while(r=null==r?void 0:r.walk());return n})(t,e.parser);return w((r=n,o=e.schema,!r.isEmpty(o.getNonEmptyElements(),o.getWhitespaceElements())),F(e,n));var r,o})(e,n).each((e=>{const n=l("",e);m(we,n),c(t),o.set(!0)}))};if(""!==r.prompt){t.block("Awaiting response");const e=(f=r.prompt,b=r.context,{prompt:oe(f,b),query:f,context:b.getOr(""),system:re});n.submitRequest(e,a.get(),g,h,y)}var f,b},g=(t,n=t.getData())=>{const r={...n,context:s.get().or((e=>w(!e.selection.isCollapsed(),e.selection.getContent()))(e))};o.set(r),m(t,r)},h=e=>{r.set(e),r.on(g)},y=(t,r)=>{switch(t.name){case A:g(r);break;case T:s.on((t=>{r.close(),((e,t)=>{e.insertContent(t)})(e,t)}));break;case E:n.closeStream();break;case I:r.close();break;case S:o.get().each((e=>m(r,e)))}},b=(e,t)=>{r.set(e),r.on(d(y,t))},v=(e,t)=>{const n=t.getData();e.name===x&&u(n.prompt,t)},C=(e,t)=>{r.set(e),r.on(d(v,t))},R=()=>{n.closeStream(),(e=>{e.dispatch("AIDialogClose")})(e),o.clear(),s.clear(),r.clear()},k=(e,t)=>({title:"AI Assistant",body:{type:"panel",items:e},size:"medium",initialData:t,onSubmit:h,onAction:b,onChange:C,onClose:R}),_=t=>{const n=t.display?le:[],o=(e=>({prompt:e.prompt}))(t),s=k(n,o);r.set(e.windowManager.open(s,{inline:"bottom",persistent:!0})),r.on(d(u,t.prompt)),t.generate&&r.on((e=>g(e,o)))},O=()=>r.on((e=>e.close()));return{open:n=>{r.isSet()?(e=>!(e.generate&&e.prompt.length>0))(n)?r.on((e=>{e.focus(x)})):(e=>{r.on(O),_(e)})(n):(n=>{a.set(t.createThread()),(e=>{e.dispatch("AIDialogOpen")})(e),_(n)})(n)},close:O}};tinymce.PluginManager.requireLangPack("ai","ar,bg_BG,ca,cs,da,de,el,es,eu,fa,fi,fr_FR,he_IL,hi,hr,hu_HU,id,it,ja,kk,ko_KR,ms,nb_NO,nl,pl,pt_BR,pt_PT,ro,ru,sk,sl_SI,sv_SE,th_TH,tr,uk,vi,zh_CN,zh_TW"),tinymce.PluginManager.add("ai",(e=>{if(((e,n)=>!!e&&-1===((e,n)=>{const r=t(e.major,n.major);if(0!==r)return r;const o=t(e.minor,n.minor);if(0!==o)return o;const s=t(e.patch,n.patch);return 0!==s?s:0})((e=>r((e=>[e.majorVersion,e.minorVersion].join(".").split(".").slice(0,3).join("."))(e)))(e),r(n)))(tinymce,"6.6.0"))return console.error("The ai plugin requires at least version 6.6.0 of TinyMCE."),{};(e=>{const t=e.options.register;t("ai_request",{processor:"function"}),t("ai_shortcuts",{processor:e=>{if(c(e))return{valid:!0,value:e?q:[]};{const t=((e,t)=>{if(l(e)){for(let n=0,r=e.length;n<r;++n)if(!t(e[n]))return!1;return!0}return!1})(e,a);return t?{value:e,valid:t}:{valid:!1,message:"Must be a boolean, empty array, or an array of objects."}}},default:q})})(e);const n=ne(),o=Z(e,n);return((e,t)=>{e.addCommand("mceAiDialog",((e,n)=>{const r={...G,...n};t.open(r)})),e.addCommand("mceAiDialogClose",t.close)})(e,Te(e,n,o)),((e,t)=>{e.ui.registry.addMenuItem("aidialog",{icon:"ai",text:"Ask AI...",shortcut:"Meta+J",onSetup:U(e,t),onAction:()=>z(e)}),j(e).each((n=>{e.ui.registry.addNestedMenuItem("aishortcuts",{icon:R,text:C,onSetup:U(e,t),getSubmenuItems:()=>K(e,n)})}))})(e,o),((e,t)=>{e.ui.registry.addButton("aidialog",{icon:"ai",tooltip:"Ask AI",onSetup:U(e,t),onAction:()=>z(e)}),j(e).each((n=>{e.ui.registry.addMenuButton("aishortcuts",{icon:R,tooltip:C,onSetup:U(e,t),fetch:t=>t(K(e,n))})}))})(e,o),(e=>{e.ui.registry.addContextToolbar("ai",{predicate:t=>!e.selection.isCollapsed()&&e.dom.isEditable(t),items:"aidialog aishortcuts",position:"selection",scope:"editor"})})(e),(e=>{e.addShortcut("Meta+J","Open Ai Dialog",(()=>{e.execCommand("mceAiDialog")}))})(e),(e=>({getThreadLog:e.getThreadLog}))(n)}))}(); |