@lexical/react 0.9.2 → 0.10.0
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/LexicalClickableLinkPlugin.d.ts +10 -0
- package/LexicalClickableLinkPlugin.dev.js +112 -0
- package/LexicalClickableLinkPlugin.js +9 -0
- package/LexicalClickableLinkPlugin.js.flow +12 -0
- package/LexicalClickableLinkPlugin.prod.js +10 -0
- package/LexicalTablePlugin.d.ts +4 -1
- package/LexicalTablePlugin.dev.js +88 -2
- package/LexicalTablePlugin.js.flow +5 -1
- package/LexicalTablePlugin.prod.js +6 -4
- package/LexicalTreeView.d.ts +2 -1
- package/LexicalTreeView.dev.js +54 -9
- package/LexicalTreeView.prod.js +18 -17
- package/package.json +19 -19
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
export default function LexicalClickableLinkPlugin({ newTab, }: {
|
|
9
|
+
newTab?: boolean;
|
|
10
|
+
}): null;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
var link = require('@lexical/link');
|
|
10
|
+
var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
11
|
+
var utils = require('@lexical/utils');
|
|
12
|
+
var lexical = require('lexical');
|
|
13
|
+
var react = require('react');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
17
|
+
*
|
|
18
|
+
* This source code is licensed under the MIT license found in the
|
|
19
|
+
* LICENSE file in the root directory of this source tree.
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
function domGetParent(node, predicate) {
|
|
24
|
+
let parent = node.parentNode;
|
|
25
|
+
|
|
26
|
+
while (parent != null) {
|
|
27
|
+
if (predicate(parent)) {
|
|
28
|
+
return parent;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
parent = parent.parentNode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function LexicalClickableLinkPlugin({
|
|
38
|
+
newTab = true
|
|
39
|
+
}) {
|
|
40
|
+
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
41
|
+
react.useEffect(() => {
|
|
42
|
+
const onClick = event => {
|
|
43
|
+
const target = event.target;
|
|
44
|
+
|
|
45
|
+
if (!(target instanceof Node)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const nearestEditor = lexical.getNearestEditorFromDOMNode(target);
|
|
50
|
+
|
|
51
|
+
if (nearestEditor === null) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let url = null;
|
|
56
|
+
let urlTarget = null;
|
|
57
|
+
nearestEditor.update(() => {
|
|
58
|
+
const clickedNode = lexical.$getNearestNodeFromDOMNode(target);
|
|
59
|
+
|
|
60
|
+
if (clickedNode !== null) {
|
|
61
|
+
const maybeLinkNode = utils.$findMatchingParent(clickedNode, lexical.$isElementNode);
|
|
62
|
+
|
|
63
|
+
if (link.$isLinkNode(maybeLinkNode)) {
|
|
64
|
+
url = maybeLinkNode.getURL();
|
|
65
|
+
urlTarget = maybeLinkNode.getTarget();
|
|
66
|
+
} else {
|
|
67
|
+
const a = utils.isHTMLAnchorElement(target) ? target : domGetParent(target, utils.isHTMLAnchorElement);
|
|
68
|
+
url = a.href;
|
|
69
|
+
urlTarget = a.target;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (url === null || url === '') {
|
|
75
|
+
return;
|
|
76
|
+
} // Allow user to select link text without follwing url
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
const selection = editor.getEditorState().read(lexical.$getSelection);
|
|
80
|
+
|
|
81
|
+
if (lexical.$isRangeSelection(selection) && !selection.isCollapsed()) {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const isMiddle = event.type === 'auxclick' && event.button === 1;
|
|
87
|
+
window.open(url, newTab || isMiddle || event.metaKey || event.ctrlKey || urlTarget === '_blank' ? '_blank' : '_self');
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const onMouseUp = event => {
|
|
92
|
+
if (event.button === 1 && editor.isEditable()) {
|
|
93
|
+
onClick(event);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return editor.registerRootListener((rootElement, prevRootElement) => {
|
|
98
|
+
if (prevRootElement !== null) {
|
|
99
|
+
prevRootElement.removeEventListener('click', onClick);
|
|
100
|
+
prevRootElement.removeEventListener('mouseup', onMouseUp);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (rootElement !== null) {
|
|
104
|
+
rootElement.addEventListener('click', onClick);
|
|
105
|
+
rootElement.addEventListener('mouseup', onMouseUp);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}, [editor, newTab]);
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = LexicalClickableLinkPlugin;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict'
|
|
8
|
+
const LexicalClickableLinkPlugin = process.env.NODE_ENV === 'development' ? require('./LexicalClickableLinkPlugin.dev.js') : require('./LexicalClickableLinkPlugin.prod.js')
|
|
9
|
+
module.exports = LexicalClickableLinkPlugin;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
declare export function MLCClickableLinkPlugin({
|
|
11
|
+
newTab?: boolean,
|
|
12
|
+
}): null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
'use strict';var e=require("@lexical/link"),k=require("@lexical/react/LexicalComposerContext"),q=require("@lexical/utils"),r=require("lexical"),t=require("react");
|
|
8
|
+
module.exports=function({newTab:n=!0}){let [h]=k.useLexicalComposerContext();t.useEffect(()=>{let m=a=>{const c=a.target;if(c instanceof Node){var d=r.getNearestEditorFromDOMNode(c);if(null!==d){var f=null,l=null;d.update(()=>{var b=r.$getNearestNodeFromDOMNode(c);if(null!==b)if(b=q.$findMatchingParent(b,r.$isElementNode),e.$isLinkNode(b))f=b.getURL(),l=b.getTarget();else{if(q.isHTMLAnchorElement(c))b=c;else a:{b=q.isHTMLAnchorElement;let g=c.parentNode;for(;null!=g;){if(b(g)){b=g;break a}g=g.parentNode}b=
|
|
9
|
+
null}f=b.href;l=b.target}});if(null!==f&&""!==f){d=h.getEditorState().read(r.$getSelection);if(!r.$isRangeSelection(d)||d.isCollapsed())d="auxclick"===a.type&&1===a.button,window.open(f,n||d||a.metaKey||a.ctrlKey||"_blank"===l?"_blank":"_self");a.preventDefault()}}}},p=a=>{1===a.button&&h.isEditable()&&m(a)};return h.registerRootListener((a,c)=>{null!==c&&(c.removeEventListener("click",m),c.removeEventListener("mouseup",p));null!==a&&(a.addEventListener("click",m),a.addEventListener("mouseup",p))})},
|
|
10
|
+
[h,n]);return null}
|
package/LexicalTablePlugin.d.ts
CHANGED
|
@@ -6,4 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
/// <reference types="react" />
|
|
9
|
-
export declare function TablePlugin(
|
|
9
|
+
export declare function TablePlugin({ hasCellMerge, hasCellBackgroundColor, }: {
|
|
10
|
+
hasCellMerge?: boolean;
|
|
11
|
+
hasCellBackgroundColor?: boolean;
|
|
12
|
+
}): JSX.Element | null;
|
|
@@ -19,7 +19,21 @@ var react = require('react');
|
|
|
19
19
|
* LICENSE file in the root directory of this source tree.
|
|
20
20
|
*
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
function $insertFirst(parent, node) {
|
|
24
|
+
const firstChild = parent.getFirstChild();
|
|
25
|
+
|
|
26
|
+
if (firstChild !== null) {
|
|
27
|
+
firstChild.insertBefore(node);
|
|
28
|
+
} else {
|
|
29
|
+
parent.append(node);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function TablePlugin({
|
|
34
|
+
hasCellMerge = true,
|
|
35
|
+
hasCellBackgroundColor = true
|
|
36
|
+
}) {
|
|
23
37
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
24
38
|
react.useEffect(() => {
|
|
25
39
|
if (!editor.hasNodes([table.TableNode, table.TableCellNode, table.TableRowNode])) {
|
|
@@ -96,7 +110,79 @@ function TablePlugin() {
|
|
|
96
110
|
tableSelection.removeListeners();
|
|
97
111
|
}
|
|
98
112
|
};
|
|
99
|
-
}, [editor]);
|
|
113
|
+
}, [editor]); // Unmerge cells when the feature isn't enabled
|
|
114
|
+
|
|
115
|
+
react.useEffect(() => {
|
|
116
|
+
if (hasCellMerge) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return editor.registerNodeTransform(table.TableCellNode, node => {
|
|
121
|
+
if (node.getColSpan() > 1 || node.getRowSpan() > 1) {
|
|
122
|
+
// When we have rowSpan we have to map the entire Table to understand where the new Cells
|
|
123
|
+
// fit best; let's analyze all Cells at once to save us from further transform iterations
|
|
124
|
+
const [,, gridNode] = lexical.DEPRECATED_$getNodeTriplet(node);
|
|
125
|
+
const [gridMap] = lexical.DEPRECATED_$computeGridMap(gridNode, node, node); // TODO this function expects Tables to be normalized. Look into this once it exists
|
|
126
|
+
|
|
127
|
+
const rowsCount = gridMap.length;
|
|
128
|
+
const columnsCount = gridMap[0].length;
|
|
129
|
+
let row = gridNode.getFirstChild();
|
|
130
|
+
|
|
131
|
+
if (!lexical.DEPRECATED_$isGridRowNode(row)) {
|
|
132
|
+
throw Error(`Expected TableNode first child to be a RowNode`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const unmerged = [];
|
|
136
|
+
|
|
137
|
+
for (let i = 0; i < rowsCount; i++) {
|
|
138
|
+
if (i !== 0) {
|
|
139
|
+
row = row.getNextSibling();
|
|
140
|
+
|
|
141
|
+
if (!lexical.DEPRECATED_$isGridRowNode(row)) {
|
|
142
|
+
throw Error(`Expected TableNode first child to be a RowNode`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let lastRowCell = null;
|
|
147
|
+
|
|
148
|
+
for (let j = 0; j < columnsCount; j++) {
|
|
149
|
+
const cellMap = gridMap[i][j];
|
|
150
|
+
const cell = cellMap.cell;
|
|
151
|
+
|
|
152
|
+
if (cellMap.startRow === i && cellMap.startColumn === j) {
|
|
153
|
+
lastRowCell = cell;
|
|
154
|
+
unmerged.push(cell);
|
|
155
|
+
} else if (cell.getColSpan() > 1 || cell.getRowSpan() > 1) {
|
|
156
|
+
const newCell = table.$createTableCellNode(cell.__headerState);
|
|
157
|
+
|
|
158
|
+
if (lastRowCell !== null) {
|
|
159
|
+
lastRowCell.insertAfter(newCell);
|
|
160
|
+
} else {
|
|
161
|
+
$insertFirst(row, newCell);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (const cell of unmerged) {
|
|
168
|
+
cell.setColSpan(1);
|
|
169
|
+
cell.setRowSpan(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}, [editor, hasCellMerge]); // Remove cell background color when feature is disabled
|
|
174
|
+
|
|
175
|
+
react.useEffect(() => {
|
|
176
|
+
if (hasCellBackgroundColor) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return editor.registerNodeTransform(table.TableCellNode, node => {
|
|
181
|
+
if (node.getBackgroundColor() !== null) {
|
|
182
|
+
node.setBackgroundColor(null);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}, [editor, hasCellBackgroundColor, hasCellMerge]);
|
|
100
186
|
return null;
|
|
101
187
|
}
|
|
102
188
|
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
'use strict';var c=require("@lexical/react/LexicalComposerContext"),
|
|
8
|
-
exports.TablePlugin=function(){let [
|
|
9
|
-
a=a.getFirstDescendant();
|
|
10
|
-
"destroyed"===
|
|
7
|
+
'use strict';var c=require("@lexical/react/LexicalComposerContext"),h=require("@lexical/table"),n=require("@lexical/utils"),v=require("lexical"),w=require("react");
|
|
8
|
+
exports.TablePlugin=function({hasCellMerge:q=!0,hasCellBackgroundColor:t=!0}){let [d]=c.useLexicalComposerContext();w.useEffect(()=>{if(!d.hasNodes([h.TableNode,h.TableCellNode,h.TableRowNode]))throw Error("Minified Lexical error #10; visit https://lexical.dev/docs/error?code=10 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.");return d.registerCommand(h.INSERT_TABLE_COMMAND,({columns:a,rows:e,includeHeaders:g})=>{a=h.$createTableNodeWithDimensions(Number(e),
|
|
9
|
+
Number(a),g);n.$insertNodeToNearestRoot(a);a=a.getFirstDescendant();v.$isTextNode(a)&&a.select();return!0},v.COMMAND_PRIORITY_EDITOR)},[d]);w.useEffect(()=>{let a=new Map,e=b=>{const f=b.getKey(),l=d.getElementByKey(f);l&&!a.has(f)&&(b=h.applyTableHandlers(b,l,d),a.set(f,b))};d.getEditorState().read(()=>{let b=v.$nodesOfType(h.TableNode);for(let f of b)h.$isTableNode(f)&&e(f)});let g=d.registerMutationListener(h.TableNode,b=>{for(const [f,l]of b)"created"===l?d.getEditorState().read(()=>{const m=
|
|
10
|
+
v.$getNodeByKey(f);h.$isTableNode(m)&&e(m)}):"destroyed"===l&&(b=a.get(f),void 0!==b&&(b.removeListeners(),a.delete(f)))});return()=>{g();for(let [,b]of a)b.removeListeners()}},[d]);w.useEffect(()=>{if(!q)return d.registerNodeTransform(h.TableCellNode,a=>{if(1<a.getColSpan()||1<a.getRowSpan()){var [,,e]=v.DEPRECATED_$getNodeTriplet(a);[a]=v.DEPRECATED_$computeGridMap(e,a,a);let f=a.length,l=a[0].length;e=e.getFirstChild();if(!v.DEPRECATED_$isGridRowNode(e))throw Error("Expected TableNode first child to be a RowNode");
|
|
11
|
+
let m=[];for(let k=0;k<f;k++){if(0!==k&&(e=e.getNextSibling(),!v.DEPRECATED_$isGridRowNode(e)))throw Error("Expected TableNode first child to be a RowNode");let r=null;for(let p=0;p<l;p++){var g=a[k][p],b=g.cell;if(g.startRow===k&&g.startColumn===p)r=b,m.push(b);else if(1<b.getColSpan()||1<b.getRowSpan())if(b=h.$createTableCellNode(b.__headerState),null!==r)r.insertAfter(b);else{g=e;let u=g.getFirstChild();null!==u?u.insertBefore(b):g.append(b)}}}for(let k of m)k.setColSpan(1),k.setRowSpan(1)}})},
|
|
12
|
+
[d,q]);w.useEffect(()=>{if(!t)return d.registerNodeTransform(h.TableCellNode,a=>{null!==a.getBackgroundColor()&&a.setBackgroundColor(null)})},[d,t,q]);return null}
|
package/LexicalTreeView.d.ts
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/// <reference types="react" />
|
|
9
9
|
import type { LexicalEditor } from 'lexical';
|
|
10
|
-
export declare function TreeView({ timeTravelButtonClassName, timeTravelPanelSliderClassName, timeTravelPanelButtonClassName, viewClassName, timeTravelPanelClassName, editor, }: {
|
|
10
|
+
export declare function TreeView({ treeTypeButtonClassName, timeTravelButtonClassName, timeTravelPanelSliderClassName, timeTravelPanelButtonClassName, viewClassName, timeTravelPanelClassName, editor, }: {
|
|
11
11
|
editor: LexicalEditor;
|
|
12
|
+
treeTypeButtonClassName: string;
|
|
12
13
|
timeTravelButtonClassName: string;
|
|
13
14
|
timeTravelPanelButtonClassName: string;
|
|
14
15
|
timeTravelPanelClassName: string;
|
package/LexicalTreeView.dev.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
+
var html = require('@lexical/html');
|
|
9
10
|
var link = require('@lexical/link');
|
|
10
11
|
var mark = require('@lexical/mark');
|
|
11
12
|
var utils = require('@lexical/utils');
|
|
@@ -33,6 +34,7 @@ const SYMBOLS = Object.freeze({
|
|
|
33
34
|
selectedLine: '>'
|
|
34
35
|
});
|
|
35
36
|
function TreeView({
|
|
37
|
+
treeTypeButtonClassName,
|
|
36
38
|
timeTravelButtonClassName,
|
|
37
39
|
timeTravelPanelSliderClassName,
|
|
38
40
|
timeTravelPanelButtonClassName,
|
|
@@ -43,6 +45,7 @@ function TreeView({
|
|
|
43
45
|
const [timeStampedEditorStates, setTimeStampedEditorStates] = React.useState([]);
|
|
44
46
|
const [content, setContent] = React.useState('');
|
|
45
47
|
const [timeTravelEnabled, setTimeTravelEnabled] = React.useState(false);
|
|
48
|
+
const [showExportDOM, setShowExportDOM] = React.useState(false);
|
|
46
49
|
const playingIndexRef = React.useRef(0);
|
|
47
50
|
const treeElementRef = React.useRef(null);
|
|
48
51
|
const inputRef = React.useRef(null);
|
|
@@ -52,20 +55,20 @@ function TreeView({
|
|
|
52
55
|
const lastEditorStateRef = React.useRef(null);
|
|
53
56
|
const commandsLog = useLexicalCommandsLog(editor);
|
|
54
57
|
const generateTree = React.useCallback(editorState => {
|
|
55
|
-
const treeText = generateContent(editor
|
|
58
|
+
const treeText = generateContent(editor, commandsLog, showExportDOM);
|
|
56
59
|
setContent(treeText);
|
|
57
60
|
|
|
58
61
|
if (!timeTravelEnabled) {
|
|
59
62
|
setTimeStampedEditorStates(currentEditorStates => [...currentEditorStates, [Date.now(), editorState]]);
|
|
60
63
|
}
|
|
61
|
-
}, [commandsLog, editor, timeTravelEnabled]);
|
|
64
|
+
}, [commandsLog, editor, timeTravelEnabled, showExportDOM]);
|
|
62
65
|
React.useEffect(() => {
|
|
63
66
|
const editorState = editor.getEditorState();
|
|
64
67
|
|
|
65
|
-
if (!showLimited && editorState._nodeMap.size
|
|
66
|
-
setContent(generateContent(
|
|
68
|
+
if (!showLimited && editorState._nodeMap.size < 1000) {
|
|
69
|
+
setContent(generateContent(editor, commandsLog, showExportDOM));
|
|
67
70
|
}
|
|
68
|
-
}, [commandsLog, editor, showLimited]);
|
|
71
|
+
}, [commandsLog, editor, showLimited, showExportDOM]);
|
|
69
72
|
React.useEffect(() => {
|
|
70
73
|
return utils.mergeRegister(editor.registerUpdateListener(({
|
|
71
74
|
editorState
|
|
@@ -81,10 +84,10 @@ function TreeView({
|
|
|
81
84
|
|
|
82
85
|
generateTree(editorState);
|
|
83
86
|
}), editor.registerEditableListener(() => {
|
|
84
|
-
const treeText = generateContent(editor
|
|
87
|
+
const treeText = generateContent(editor, commandsLog, showExportDOM);
|
|
85
88
|
setContent(treeText);
|
|
86
89
|
}));
|
|
87
|
-
}, [commandsLog, editor, isLimited, generateTree, showLimited]);
|
|
90
|
+
}, [commandsLog, editor, showExportDOM, isLimited, generateTree, showLimited]);
|
|
88
91
|
const totalEditorStates = timeStampedEditorStates.length;
|
|
89
92
|
React.useEffect(() => {
|
|
90
93
|
if (isPlaying) {
|
|
@@ -160,7 +163,11 @@ function TreeView({
|
|
|
160
163
|
cursor: 'pointer',
|
|
161
164
|
padding: 5
|
|
162
165
|
}
|
|
163
|
-
}, "Show full tree")) : null, !
|
|
166
|
+
}, "Show full tree")) : null, !showLimited ? /*#__PURE__*/React.createElement("button", {
|
|
167
|
+
onClick: () => setShowExportDOM(!showExportDOM),
|
|
168
|
+
className: treeTypeButtonClassName,
|
|
169
|
+
type: "button"
|
|
170
|
+
}, showExportDOM ? 'Tree' : 'Export DOM') : null, !timeTravelEnabled && (showLimited || !isLimited) && totalEditorStates > 2 && /*#__PURE__*/React.createElement("button", {
|
|
164
171
|
onClick: () => {
|
|
165
172
|
const rootElement = editor.getRootElement();
|
|
166
173
|
|
|
@@ -275,7 +282,20 @@ function printGridSelection(selection) {
|
|
|
275
282
|
return `: grid\n └ { grid: ${selection.gridKey}, anchorCell: ${selection.anchor.key}, focusCell: ${selection.focus.key} }`;
|
|
276
283
|
}
|
|
277
284
|
|
|
278
|
-
function generateContent(
|
|
285
|
+
function generateContent(editor, commandsLog, exportDOM) {
|
|
286
|
+
const editorState = editor.getEditorState();
|
|
287
|
+
const editorConfig = editor._config;
|
|
288
|
+
const compositionKey = editor._compositionKey;
|
|
289
|
+
const editable = editor._editable;
|
|
290
|
+
|
|
291
|
+
if (exportDOM) {
|
|
292
|
+
let htmlString = '';
|
|
293
|
+
editorState.read(() => {
|
|
294
|
+
htmlString = printPrettyHTML(html.$generateHtmlFromNodes(editor));
|
|
295
|
+
});
|
|
296
|
+
return htmlString;
|
|
297
|
+
}
|
|
298
|
+
|
|
279
299
|
let res = ' root\n';
|
|
280
300
|
const selectionString = editorState.read(() => {
|
|
281
301
|
const selection = lexical.$getSelection();
|
|
@@ -464,6 +484,31 @@ function printSelectedCharsLine({
|
|
|
464
484
|
return [SYMBOLS.selectedLine, indentionChars.join(' '), [...nodePrintSpaces, ...unselectedChars, ...selectedChars].join('')].join(' ') + '\n';
|
|
465
485
|
}
|
|
466
486
|
|
|
487
|
+
function printPrettyHTML(str) {
|
|
488
|
+
const div = document.createElement('div');
|
|
489
|
+
div.innerHTML = str.trim();
|
|
490
|
+
return prettifyHTML(div, 0).innerHTML;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function prettifyHTML(node, level) {
|
|
494
|
+
const indentBefore = new Array(level++ + 1).join(' ');
|
|
495
|
+
const indentAfter = new Array(level - 1).join(' ');
|
|
496
|
+
let textNode;
|
|
497
|
+
|
|
498
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
499
|
+
textNode = document.createTextNode('\n' + indentBefore);
|
|
500
|
+
node.insertBefore(textNode, node.children[i]);
|
|
501
|
+
prettifyHTML(node.children[i], level);
|
|
502
|
+
|
|
503
|
+
if (node.lastElementChild === node.children[i]) {
|
|
504
|
+
textNode = document.createTextNode('\n' + indentAfter);
|
|
505
|
+
node.appendChild(textNode);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return node;
|
|
510
|
+
}
|
|
511
|
+
|
|
467
512
|
function $getSelectionStartEnd(node, selection) {
|
|
468
513
|
const anchor = selection.anchor;
|
|
469
514
|
const focus = selection.focus;
|
package/LexicalTreeView.prod.js
CHANGED
|
@@ -4,20 +4,21 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
'use strict';var
|
|
8
|
-
function
|
|
9
|
-
function
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
{
|
|
22
|
-
|
|
23
|
-
|
|
7
|
+
'use strict';var g=require("@lexical/html"),w=require("@lexical/link"),x=require("@lexical/mark"),I=require("@lexical/utils"),M=require("lexical"),N=require("react");let O=Object.freeze({"\t":"\\t","\n":"\\n"}),P=new RegExp(Object.keys(O).join("|"),"g"),Q=Object.freeze({ancestorHasNextSibling:"|",ancestorIsLastChild:" ",hasNextSibling:"\u251c",isLastChild:"\u2514",selectedChar:"^",selectedLine:">"});
|
|
8
|
+
function R(a){let [b,c]=N.useState([]);N.useEffect(()=>{let l=new Set;for(let [e]of a._commands)l.add(a.registerCommand(e,p=>{c(d=>{d=[...d];d.push({payload:p,type:e.type?e.type:"UNKNOWN"});10<d.length&&d.shift();return d});return!1},M.COMMAND_PRIORITY_HIGH));return()=>l.forEach(e=>e())},[a]);return N.useMemo(()=>b,[b])}
|
|
9
|
+
function U(a){let b="";var c=V(a);b+=`: range ${""!==c?`{ ${c} }`:""} ${""!==a.style?`{ style: ${a.style} } `:""}`;c=a.anchor;a=a.focus;let l=c.offset,e=a.offset;b+=`\n \u251c anchor { key: ${c.key}, offset: ${null===l?"null":l}, type: ${c.type} }`;return b+=`\n \u2514 focus { key: ${a.key}, offset: ${null===e?"null":e}, type: ${a.type} }`}
|
|
10
|
+
function W(a,b,c){let l=a.getEditorState(),e=a._config,p=a._compositionKey,d=a._editable;if(c){let m="";l.read(()=>{var k=g.$generateHtmlFromNodes(a);let t=document.createElement("div");t.innerHTML=k.trim();m=X(t,0).innerHTML});return m}let h=" root\n";c=l.read(()=>{const m=M.$getSelection();Y(M.$getRoot(),(k,t)=>{const y=`(${k.getKey()})`,v=k.getType()||"",q=k.isSelected(),J=x.$isMarkNode(k)?` id: [ ${k.getIDs().join(", ")} ] `:"";var A=h,H=q?Q.selectedLine:" ",F=t.join(" ");if(M.$isTextNode(k)){var n=
|
|
11
|
+
k.getTextContent();var u=0===n.length?"(empty)":`"${Z(n)}"`;n=[V(k),aa(k),ba(k)].filter(Boolean).join(", ");n=[u,0!==n.length?`{ ${n} }`:null].filter(Boolean).join(" ").trim()}else if(w.$isLinkNode(k)){n=k.getURL();n=0===n.length?"(empty)":`"${Z(n)}"`;u=k.getTarget();null!=u&&(u="target: "+u);var B=Boolean;var C=k.getRel();null!=C&&(C="rel: "+C);let r=k.getTitle();null!=r&&(r="title: "+r);u=[u,C,r].filter(B).join(", ");n=[n,0!==u.length?`{ ${u} }`:null].filter(Boolean).join(" ").trim()}else n="";
|
|
12
|
+
h=A+`${H} ${F} ${y} ${v} ${J} ${n}\n`;h+=ca({indent:t,isSelected:q,node:k,nodeKeyDisplay:y,selection:m,typeDisplay:v})});return null===m?": null":M.$isRangeSelection(m)?U(m):M.DEPRECATED_$isGridSelection(m)?`: grid\n \u2514 { grid: ${m.gridKey}, anchorCell: ${m.anchor.key}, focusCell: ${m.focus.key} }`:`: node\n \u2514 [${Array.from(m._nodes).join(", ")}]`});h+="\n selection"+c;h+="\n\n commands:";if(b.length)for(let {type:m,payload:k}of b)h+=`\n \u2514 { type: ${m}, payload: ${k instanceof Event?
|
|
13
|
+
k.constructor.name:k} }`;else h+="\n \u2514 None dispatched.";h+="\n\n editor:";h+=`\n \u2514 namespace ${e.namespace}`;null!==p&&(h+=`\n \u2514 compositionKey ${p}`);return h+=`\n \u2514 editable ${String(d)}`}function Y(a,b,c=[]){a=a.getChildren();let l=a.length;a.forEach((e,p)=>{b(e,c.concat(p===l-1?Q.isLastChild:Q.hasNextSibling));M.$isElementNode(e)&&Y(e,b,c.concat(p===l-1?Q.ancestorIsLastChild:Q.ancestorHasNextSibling))})}
|
|
14
|
+
function Z(a){return Object.entries(O).reduce((b,[c,l])=>b.replace(new RegExp(c,"g"),String(l)),a)}
|
|
15
|
+
let da=[a=>a.hasFormat("bold")&&"Bold",a=>a.hasFormat("code")&&"Code",a=>a.hasFormat("italic")&&"Italic",a=>a.hasFormat("strikethrough")&&"Strikethrough",a=>a.hasFormat("subscript")&&"Subscript",a=>a.hasFormat("superscript")&&"Superscript",a=>a.hasFormat("underline")&&"Underline"],ea=[a=>a.isDirectionless()&&"Directionless",a=>a.isUnmergeable()&&"Unmergeable"],fa=[a=>a.isToken()&&"Token",a=>a.isSegmented()&&"Segmented"];
|
|
16
|
+
function aa(a){let b=ea.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="detail: "+b);return b}function ba(a){let b=fa.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="mode: "+b);return b}function V(a){let b=da.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="format: "+b);return b}
|
|
17
|
+
function ca({indent:a,isSelected:b,node:c,nodeKeyDisplay:l,selection:e,typeDisplay:p}){if(!M.$isTextNode(c)||!M.$isRangeSelection(e)||!b||M.$isElementNode(c))return"";b=e.anchor;var d=e.focus;if(""===c.getTextContent()||b.getNode()===e.focus.getNode()&&b.offset===d.offset)return"";d=e.anchor;let h=e.focus,m=c.getTextContent(),k=m.length;b=e=-1;if("text"===d.type&&"text"===h.type){let v=d.getNode(),q=h.getNode();v===q&&c===v&&d.offset!==h.offset?[e,b]=d.offset<h.offset?[d.offset,h.offset]:[h.offset,
|
|
18
|
+
d.offset]:c===v?[e,b]=v.isBefore(q)?[d.offset,k]:[0,d.offset]:c===q?[e,b]=q.isBefore(v)?[h.offset,k]:[0,h.offset]:[e,b]=[0,k]}c=(m.slice(0,e).match(P)||[]).length;d=(m.slice(e,b).match(P)||[]).length;let [t,y]=[e+c,b+c+d];if(t===y)return"";c=a[a.length-1]===Q.hasNextSibling?Q.ancestorHasNextSibling:Q.ancestorIsLastChild;a=[...a.slice(0,a.length-1),c];c=Array(t+1).fill(" ");e=Array(y-t).fill(Q.selectedChar);l=Array(l.length+(p.length+3)).fill(" ");return[Q.selectedLine,a.join(" "),[...l,...c,...e].join("")].join(" ")+
|
|
19
|
+
"\n"}function X(a,b){let c=Array(b++ +1).join(" "),l=Array(b-1).join(" "),e;for(let p=0;p<a.children.length;p++)e=document.createTextNode("\n"+c),a.insertBefore(e,a.children[p]),X(a.children[p],b),a.lastElementChild===a.children[p]&&(e=document.createTextNode("\n"+l),a.appendChild(e));return a}
|
|
20
|
+
exports.TreeView=function({treeTypeButtonClassName:a,timeTravelButtonClassName:b,timeTravelPanelSliderClassName:c,timeTravelPanelButtonClassName:l,viewClassName:e,timeTravelPanelClassName:p,editor:d}){let [h,m]=N.useState([]),[k,t]=N.useState(""),[y,v]=N.useState(!1),[q,J]=N.useState(!1),A=N.useRef(0),H=N.useRef(null),F=N.useRef(null),[n,u]=N.useState(!1),[B,C]=N.useState(!1),[r,ha]=N.useState(!1),K=N.useRef(null),D=R(d),L=N.useCallback(f=>{const z=W(d,D,q);t(z);y||m(G=>[...G,[Date.now(),f]])},[D,
|
|
21
|
+
d,y,q]);N.useEffect(()=>{let f=d.getEditorState();!r&&1E3>f._nodeMap.size&&t(W(d,D,q))},[D,d,r,q]);N.useEffect(()=>I.mergeRegister(d.registerUpdateListener(({editorState:f})=>{if(!r&&1E3<f._nodeMap.size&&(K.current=f,C(!0),!r))return;L(f)}),d.registerEditableListener(()=>{let f=W(d,D,q);t(f)})),[D,d,q,B,L,r]);let E=h.length;N.useEffect(()=>{if(n){let f,z=()=>{const G=A.current;G===E-1?u(!1):f=setTimeout(()=>{A.current++;const S=A.current,T=F.current;null!==T&&(T.value=String(S));d.setEditorState(h[S][1]);
|
|
22
|
+
z()},h[G+1][0]-h[G][0])};z();return()=>{clearTimeout(f)}}},[h,n,d,E]);N.useEffect(()=>{let f=H.current;if(null!==f)return f.__lexicalEditor=d,()=>{f.__lexicalEditor=null}},[d]);return N.createElement("div",{className:e},!r&&B?N.createElement("div",{style:{padding:20}},N.createElement("span",{style:{marginRight:20}},"Detected large EditorState, this can impact debugging performance."),N.createElement("button",{onClick:()=>{ha(!0);let f=K.current;null!==f&&(K.current=null,L(f))},style:{background:"transparent",
|
|
23
|
+
border:"1px solid white",color:"white",cursor:"pointer",padding:5}},"Show full tree")):null,r?null:N.createElement("button",{onClick:()=>J(!q),className:a,type:"button"},q?"Tree":"Export DOM"),!y&&(r||!B)&&2<E&&N.createElement("button",{onClick:()=>{let f=d.getRootElement();null!==f&&(f.contentEditable="false",A.current=E-1,v(!0))},className:b,type:"button"},"Time Travel"),(r||!B)&&N.createElement("pre",{ref:H},k),y&&(r||!B)&&N.createElement("div",{className:p},N.createElement("button",{className:l,
|
|
24
|
+
onClick:()=>{A.current===E-1&&(A.current=1);u(!n)},type:"button"},n?"Pause":"Play"),N.createElement("input",{className:c,ref:F,onChange:f=>{f=Number(f.target.value);let z=h[f];z&&(A.current=f,d.setEditorState(z[1]))},type:"range",min:"1",max:E-1}),N.createElement("button",{className:l,onClick:()=>{var f=d.getRootElement();if(null!==f){f.contentEditable="true";f=h.length-1;d.setEditorState(h[f][1]);let z=F.current;null!==z&&(z.value=String(f));v(!1);u(!1)}},type:"button"},"Exit")))}
|
package/package.json
CHANGED
|
@@ -8,29 +8,29 @@
|
|
|
8
8
|
"rich-text"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.10.0",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@lexical/clipboard": "0.
|
|
14
|
-
"@lexical/code": "0.
|
|
15
|
-
"@lexical/dragon": "0.
|
|
16
|
-
"@lexical/hashtag": "0.
|
|
17
|
-
"@lexical/history": "0.
|
|
18
|
-
"@lexical/link": "0.
|
|
19
|
-
"@lexical/list": "0.
|
|
20
|
-
"@lexical/mark": "0.
|
|
21
|
-
"@lexical/markdown": "0.
|
|
22
|
-
"@lexical/overflow": "0.
|
|
23
|
-
"@lexical/plain-text": "0.
|
|
24
|
-
"@lexical/rich-text": "0.
|
|
25
|
-
"@lexical/selection": "0.
|
|
26
|
-
"@lexical/table": "0.
|
|
27
|
-
"@lexical/text": "0.
|
|
28
|
-
"@lexical/utils": "0.
|
|
29
|
-
"@lexical/yjs": "0.
|
|
13
|
+
"@lexical/clipboard": "0.10.0",
|
|
14
|
+
"@lexical/code": "0.10.0",
|
|
15
|
+
"@lexical/dragon": "0.10.0",
|
|
16
|
+
"@lexical/hashtag": "0.10.0",
|
|
17
|
+
"@lexical/history": "0.10.0",
|
|
18
|
+
"@lexical/link": "0.10.0",
|
|
19
|
+
"@lexical/list": "0.10.0",
|
|
20
|
+
"@lexical/mark": "0.10.0",
|
|
21
|
+
"@lexical/markdown": "0.10.0",
|
|
22
|
+
"@lexical/overflow": "0.10.0",
|
|
23
|
+
"@lexical/plain-text": "0.10.0",
|
|
24
|
+
"@lexical/rich-text": "0.10.0",
|
|
25
|
+
"@lexical/selection": "0.10.0",
|
|
26
|
+
"@lexical/table": "0.10.0",
|
|
27
|
+
"@lexical/text": "0.10.0",
|
|
28
|
+
"@lexical/utils": "0.10.0",
|
|
29
|
+
"@lexical/yjs": "0.10.0",
|
|
30
30
|
"react-error-boundary": "^3.1.4"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"lexical": "0.
|
|
33
|
+
"lexical": "0.10.0",
|
|
34
34
|
"react": ">=17.x",
|
|
35
35
|
"react-dom": ">=17.x"
|
|
36
36
|
},
|