@lexical/clipboard
Version:
This package provides the copy/paste functionality for Lexical.
10 lines (8 loc) • 10.3 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
;var e=require("@lexical/extension"),t=require("@lexical/html"),n=require("@lexical/selection"),r=require("@lexical/utils"),o=require("lexical");function i(e,t){if(void 0!==document.caretRangeFromPoint){const n=document.caretRangeFromPoint(e,t);return null===n?null:{node:n.startContainer,offset:n.startOffset}}if("undefined"!==document.caretPositionFromPoint){const n=document.caretPositionFromPoint(e,t);return null===n?null:{node:n.offsetNode,offset:n.offset}}return null}function l(e,...t){const n=new URL("https://lexical.dev/docs/error"),r=new URLSearchParams;r.append("code",e);for(const e of t)r.append("v",e);throw n.search=r.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}const s={"application/x-lexical-editor":0,"text/html":10,"text/plain":20,"text/uri-list":30};function a(e){if(window.trustedTypes&&window.trustedTypes.createPolicy){return window.trustedTypes.createPolicy("lexical",{createHTML:e=>e}).createHTML(e)}return e}const c=(e,t)=>{if(!o.$isRangeSelection(t))return t.insertRawText(e),!0;const n=e=>{const t=o.$getSelection();o.$isRangeSelection(t)&&e(t)};return o.tokenizeRawText(e,{linebreak:()=>n(e=>e.insertParagraph()),tab:()=>n(e=>e.insertNodes([o.$createTabNode()])),text:e=>n(t=>t.insertText(e))}),!0},u={"application/x-lexical-editor":[(e,t,n)=>{try{const n=o.$getEditor(),r=JSON.parse(e);if(r&&r.namespace===n._config.namespace&&Array.isArray(r.nodes)){return D(n,S(r.nodes),t),!0}}catch(e){console.error(e)}return n()}],"text/html":[(e,n,r)=>{try{const r=o.$getEditor(),i=(new DOMParser).parseFromString(a(e),"text/html");return D(r,t.$generateNodesFromDOM(r,i),n),!0}catch(e){return console.error(e),r()}}],"text/plain":[c],"text/uri-list":[c]};function p(e,t,n,r){if(!e)return!1;const o=i=>!!e[i]&&e[i](t,n,o.bind(null,i-1),r);return o(e.length-1)}function d(e,t,n){const r=t.getData("text/plain");for(const o of function(e){return Object.keys(e.$importMimeType).filter(t=>void 0!==e.$importMimeType[t]).sort((t,n)=>{const r=e.priority[t],o=e.priority[n];return void 0===r&&void 0===o?t<n?-1:t>n?1:0:void 0===r?1:void 0===o?-1:r-o})}(e)){const i=t.getData(o);if(i&&(("text/html"!==o||i!==r)&&p(e.$importMimeType[o],i,n,t)))return!0}return!1}const f={$importMimeType:u,$insertDataTransfer:(e,t)=>d({$importMimeType:u,priority:s},e,t),priority:s};const m=o.defineExtension({build:(e,t)=>({$importMimeType:t.$importMimeType,$insertDataTransfer:(e,n)=>d(t,e,n),priority:t.priority}),config:o.safeCast({$importMimeType:u,priority:s}),mergeConfig(e,t){const n=o.shallowMergeConfig(e,t);if(t.$importMimeType){const r={...e.$importMimeType};for(const[e,n]of Object.entries(t.$importMimeType))if(n){const t=r[e];r[e]=t?[...t,...n]:n}n.$importMimeType=r}return t.priority&&(n.priority={...e.priority,...t.priority}),n},name:"@lexical/clipboard/Import"}),x=o.defineExtension({dependencies:[e.configExtension(m,{$importMimeType:{"text/html":[(e,n,r,i)=>{const l=(new DOMParser).parseFromString(a(e),"text/html"),s=t.$generateNodesFromDOMViaExtension(l,{context:[t.contextValue(t.ImportSource,"paste"),t.contextValue(t.ImportSourceDataTransfer,i)]});return D(o.$getEditor(),s,n),!0}]}})],name:"@lexical/clipboard/DOMImport"});function g(e,n=o.$getSelection()){return null==n&&l(166),o.$isRangeSelection(n)&&n.isCollapsed()||0===n.getNodes().length?"":t.$generateHtmlFromNodes(e,n)}function $(e,t=o.$getSelection()){return null==t&&l(166),o.$isRangeSelection(t)&&t.isCollapsed()||0===t.getNodes().length?null:JSON.stringify(M(e,t))}function y(e,t){const n=e.getData("text/plain")||e.getData("text/uri-list");null!=n&&t.insertRawText(n)}function T(t,n,r){(function(){const t=e.$getPeerDependency(m.name);return t?t.output:f})().$insertDataTransfer(t,n)}const h="application/x-lexical-drag";function C(e,t,n){const r=e.dataTransfer;if(null===r)return!1;const l=function(e){const t=e.getData(h);if(!t)return null;let n;try{n=JSON.parse(t)}catch(e){return null}return null!==(r=n)&&"object"==typeof r&&"editorKey"in r&&"string"==typeof r.editorKey?n:null;var r}(r);if(null===l)return!1;const s=function(e){const t=i(e.clientX,e.clientY);if(null===t)return null;const n=o.$getNearestNodeFromDOMNode(t.node);if(null===n)return null;if(o.$isTextNode(n))return o.$getTextPointCaret(n,"next",t.offset);if(o.$isElementNode(n))return o.$getChildCaretAtIndex(n,t.offset,"next");const r=n.getParent();return null===r?null:o.$getChildCaretAtIndex(r,n.getIndexWithinParent()+1,"next")}(e);if(null===s)return!1;const a=o.$splitAtPointCaretNext(s);if(null===a)return!1;const c=l.editorKey===t.getKey(),u=o.$getSelection();if(c){if(!o.$isRangeSelection(u)||u.isCollapsed())return!1;if(function(e,t){const{anchor:n,focus:r}=o.$getCaretRangeInDirection(o.$caretRangeFromSelection(t),"next");return o.$comparePointCaretNext(n,e)<0&&o.$comparePointCaretNext(e,r)<0}(s,u))return e.preventDefault(),!0;u.removeText()}if(!a.origin.isAttached())return e.preventDefault(),!0;if(n(r,o.$setSelectionFromCaretRange(o.$getCollapsedCaretRange(a)),t),!c){const e=t.getRootElement(),n=e?e.ownerDocument:null,r=n?function(e,t){const n=t.querySelectorAll('[data-lexical-editor="true"]');for(const t of Array.from(n)){const n=t.__lexicalEditor;if(n&&n.getKey()===e)return t}return null}(l.editorKey,n):null;null!==r&&r.dispatchEvent(new InputEvent("beforeinput",{bubbles:!0,cancelable:!0,inputType:"deleteByDrag"}))}return e.preventDefault(),!0}function D(e,t,n){e.dispatchCommand(o.SELECTION_INSERT_CLIPBOARD_NODES_COMMAND,{nodes:t,selection:n})||(n.insertNodes(t),function(e){if(o.$isRangeSelection(e)&&e.isCollapsed()){const t=e.anchor;let n=null;const r=o.$caretFromPoint(t,"previous");if(r)if(o.$isTextPointCaret(r))n=r.origin;else{const e=o.$getCaretRange(r,o.$getChildCaret(o.$getRoot(),"next").getFlipped());for(const t of e){if(o.$isTextNode(t.origin)){n=t.origin;break}if(o.$isElementNode(t.origin)&&!t.origin.isInline())break}}if(n&&o.$isTextNode(n)){const t=n.getFormat(),r=n.getStyle();e.format===t&&e.style===r||(e.format=t,e.style=r,e.dirty=!0)}}}(n))}function N(e,t,r,i=[]){let s=null===t||r.isSelected(t);const a=o.$isElementNode(r)&&r.excludeFromCopy("html");let c=r;null!==t&&o.$isTextNode(c)&&(c=n.$sliceSelectedTextNodeContent(t,c,"clone"));const u=o.$isElementNode(c)?c.getChildren():[],p=function(e){const t=e.exportJSON(),n=e.constructor;if(t.type!==n.getType()&&l(58,n.name),o.$isElementNode(e)){const e=t.children;Array.isArray(e)||l(59,n.name)}return t}(c);o.$isTextNode(c)&&0===c.getTextContentSize()&&(s=!1);for(let n=0;n<u.length;n++){const i=u[n],l=N(e,t,i,p.children);!s&&o.$isElementNode(r)&&l&&r.extractWithChild(i,t,"clone")&&(s=!0)}if(s&&!a)i.push(p);else if(Array.isArray(p.children))for(let e=0;e<p.children.length;e++){const t=p.children[e];i.push(t)}return s}function M(e,t){const n=[],r=o.$getRoot().getChildren();for(let o=0;o<r.length;o++){N(e,t,r[o],n)}return{namespace:e._config.namespace,nodes:n}}function S(e){const t=[];for(const n of e)t.push(o.$parseSerializedNode(n));return t}let E=null;function R(e,t,n){if(void 0===n){const t=o.getDOMSelection(e._window),r=o.$getSelection();if(!r||r.isCollapsed())return!1;if(!t)return!1;const i=t.anchorNode,l=t.focusNode;if(null!==i&&null!==l&&!o.isSelectionWithinEditor(e,i,l))return!1;n=b(r)}t.preventDefault();const r=t.clipboardData;return null!==r&&(O(r,n),!0)}const P=[["text/html",g],["application/x-lexical-editor",$]];function b(e=o.$getSelection()){return function(e,t){const n={"text/plain":""};for(const[r,o]of Object.entries(e))if(o){const e=F(o,t);null!==e&&(n[r]=e)}return n}(w(),e)}function O(e,t){for(const[n]of P)void 0===t[n]&&e.setData(n,"");for(const n in t){const r=t[n];void 0!==r&&e.setData(n,r)}}function w(t=o.$getEditor()){const n=e.getPeerDependencyFromEditor(t,I.name);return n?n.output:v}const v={"application/x-lexical-editor":[(e,t)=>e?$(o.$getEditor(),e):t()],"text/html":[(e,t)=>e?g(o.$getEditor(),e):t()],"text/plain":[(e,t)=>e?e.getTextContent():t()]};function F(e,t){const n=r=>e[r]?e[r](t,n.bind(null,r-1)):null;return n(e.length-1)}const I=o.defineExtension({build:(e,t,n)=>t.$exportMimeType,config:o.safeCast({$exportMimeType:v}),mergeConfig(e,t){const n=o.shallowMergeConfig(e,t);if(t.$exportMimeType){const r={...e.$exportMimeType};for(const[e,n]of Object.entries(t.$exportMimeType))if(n){const t=r[e];r[e]=t?[...t,...n]:n}n.$exportMimeType=r}return n},name:"@lexical/clipboard/GetClipboardData"});exports.$exportMimeTypeFromSelection=function(e,t=o.$getSelection()){return F(w()[e]||[],t)},exports.$generateJSONFromSelectedNodes=M,exports.$generateNodesFromSerializedNodes=S,exports.$getClipboardDataFromSelection=b,exports.$getHtmlContent=g,exports.$getLexicalContent=$,exports.$handlePlainTextDrop=function(e,t){return C(e,t,(e,t)=>y(e,t))},exports.$handleRichTextDrop=function(e,t){return C(e,t,T)},exports.$insertDataTransferForPlainText=y,exports.$insertDataTransferForRichText=T,exports.$insertGeneratedNodes=D,exports.$writeDragSourceToDataTransfer=function(e,t){const n={editorKey:t.getKey()};e.setData(h,JSON.stringify(n))},exports.ClipboardDOMImportExtension=x,exports.ClipboardImportExtension=m,exports.DEFAULT_IMPORT_MIME_TYPE=u,exports.DEFAULT_IMPORT_MIME_TYPE_PRIORITY=s,exports.GetClipboardDataExtension=I,exports.caretFromPoint=i,exports.copyToClipboard=async function(e,t,n){if(null!==E)return!1;if(null!==t)return new Promise((r,o)=>{e.update(()=>{r(R(e,t,n))})});const i=e.getRootElement(),l=e._window||window,s=l.document,a=o.getDOMSelection(l);if(null===i||null===a)return!1;const c=s.createElement("span");c.style.position="fixed",c.style.top="-1000px",c.append(s.createTextNode("#")),i.append(c);const u=new Range;return u.setStart(c,0),u.setEnd(c,1),a.removeAllRanges(),a.addRange(u),new Promise((t,i)=>{const a=e.registerCommand(o.COPY_COMMAND,o=>(r.objectKlassEquals(o,ClipboardEvent)&&(a(),null!==E&&(l.clearTimeout(E),E=null),t(R(e,o,n))),!0),o.COMMAND_PRIORITY_CRITICAL);E=l.setTimeout(()=>{a(),E=null,t(!1)},50),s.execCommand("copy"),c.remove()})},exports.setLexicalClipboardDataTransfer=O;