@lexical/clipboard
Version:
This package provides the copy/paste functionality for Lexical.
10 lines (8 loc) • 4.74 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.
*
*/
import{$generateHtmlFromNodes as t,$generateNodesFromDOM as e}from"@lexical/html";import{$addNodeStyle as n,$sliceSelectedTextNodeContent as o}from"@lexical/selection";import{objectKlassEquals as r}from"@lexical/utils";import{$isRangeSelection as i,$getSelection as l,$createTabNode as s,SELECTION_INSERT_CLIPBOARD_NODES_COMMAND as c,$getRoot as a,$parseSerializedNode as u,$isTextNode as d,getDOMSelection as f,COPY_COMMAND as p,COMMAND_PRIORITY_CRITICAL as m,isSelectionWithinEditor as h,$getEditor as g,$isElementNode as x,$cloneWithProperties as w}from"lexical";function y(t,...e){const n=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",t);for(const t of e)o.append("v",t);throw n.search=o.toString(),Error(`Minified Lexical error #${t}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}function T(e,n=l()){return null==n&&y(166),i(n)&&n.isCollapsed()||0===n.getNodes().length?"":t(e,n)}function v(t,e=l()){return null==e&&y(166),i(e)&&e.isCollapsed()||0===e.getNodes().length?null:JSON.stringify(R(t,e))}function C(t,e){const n=t.getData("text/plain")||t.getData("text/uri-list");null!=n&&e.insertRawText(n)}function D(t,n,o){const r=t.getData("application/x-lexical-editor");if(r)try{const t=JSON.parse(r);if(t.namespace===o._config.namespace&&Array.isArray(t.nodes)){return N(o,A(t.nodes),n)}}catch(t){}const c=t.getData("text/html"),a=t.getData("text/plain");if(c&&a!==c)try{const t=(new DOMParser).parseFromString(function(t){if(window.trustedTypes&&window.trustedTypes.createPolicy){return window.trustedTypes.createPolicy("lexical",{createHTML:t=>t}).createHTML(t)}return t}(c),"text/html");return N(o,e(o,t),n)}catch(t){}const u=a||t.getData("text/uri-list");if(null!=u)if(i(n)){const t=u.split(/(\r?\n|\t)/);""===t[t.length-1]&&t.pop();for(let e=0;e<t.length;e++){const n=l();if(i(n)){const o=t[e];"\n"===o||"\r\n"===o?n.insertParagraph():"\t"===o?n.insertNodes([s()]):n.insertText(o)}}}else n.insertRawText(u)}function N(t,e,n){t.dispatchCommand(c,{nodes:e,selection:n})||n.insertNodes(e)}function S(t,e,n,r=[]){let i=null===e||n.isSelected(e);const l=x(n)&&n.excludeFromCopy("html");let s=n;if(null!==e){let t=w(n);t=d(t)&&null!==e?o(e,t):t,s=t}const c=x(s)?s.getChildren():[],a=function(t){const e=t.exportJSON(),n=t.constructor;if(e.type!==n.getType()&&y(58,n.name),x(t)){const t=e.children;Array.isArray(t)||y(59,n.name)}return e}(s);if(d(s)){const t=s.__text;t.length>0?a.text=t:i=!1}for(let o=0;o<c.length;o++){const r=c[o],l=S(t,e,r,a.children);!i&&x(n)&&l&&n.extractWithChild(r,e,"clone")&&(i=!0)}if(i&&!l)r.push(a);else if(Array.isArray(a.children))for(let t=0;t<a.children.length;t++){const e=a.children[t];r.push(e)}return i}function R(t,e){const n=[],o=a().getChildren();for(let r=0;r<o.length;r++){S(t,e,o[r],n)}return{namespace:t._config.namespace,nodes:n}}function A(t){const e=[];for(let o=0;o<t.length;o++){const r=t[o],i=u(r);d(i)&&n(i),e.push(i)}return e}let P=null;async function _(t,e,n){if(null!==P)return!1;if(null!==e)return new Promise(((o,r)=>{t.update((()=>{o(E(t,e,n))}))}));const o=t.getRootElement(),i=t._window||window,l=window.document,s=f(i);if(null===o||null===s)return!1;const c=l.createElement("span");c.style.cssText="position: fixed; top: -1000px;",c.append(l.createTextNode("#")),o.append(c);const a=new Range;return a.setStart(c,0),a.setEnd(c,1),s.removeAllRanges(),s.addRange(a),new Promise(((e,o)=>{const i=t.registerCommand(p,(o=>(r(o,ClipboardEvent)&&(i(),null!==P&&(window.clearTimeout(P),P=null),e(E(t,o,n))),!0)),m);P=window.setTimeout((()=>{i(),P=null,e(!1)}),50),l.execCommand("copy"),c.remove()}))}function E(t,e,n){if(void 0===n){const e=f(t._window);if(!e)return!1;const o=e.anchorNode,r=e.focusNode;if(null!==o&&null!==r&&!h(t,o,r))return!1;const i=l();if(null===i)return!1;n=M(i)}e.preventDefault();const o=e.clipboardData;return null!==o&&(O(o,n),!0)}const L=[["text/html",T],["application/x-lexical-editor",v]];function M(t=l()){const e={"text/plain":t?t.getTextContent():""};if(t){const n=g();for(const[o,r]of L){const i=r(n,t);null!==i&&(e[o]=i)}}return e}function O(t,e){for(const n in e){const o=e[n];void 0!==o&&t.setData(n,o)}}export{R as $generateJSONFromSelectedNodes,A as $generateNodesFromSerializedNodes,M as $getClipboardDataFromSelection,T as $getHtmlContent,v as $getLexicalContent,C as $insertDataTransferForPlainText,D as $insertDataTransferForRichText,N as $insertGeneratedNodes,_ as copyToClipboard,O as setLexicalClipboardDataTransfer};