From 1270716d804b819fdf06a50df7dfc107a244853d Mon Sep 17 00:00:00 2001 From: Ivaylo Pavlov Date: Mon, 17 Apr 2023 14:07:52 +0100 Subject: [PATCH] ExportDOM in Debug Tree View (#4307) --- packages/lexical-playground/src/index.css | 15 +++ .../src/plugins/TreeViewPlugin/index.tsx | 1 + .../lexical-react/src/LexicalTreeView.tsx | 97 +++++++++++++------ 3 files changed, 81 insertions(+), 32 deletions(-) diff --git a/packages/lexical-playground/src/index.css b/packages/lexical-playground/src/index.css index 2f6ee54cb73..c51984149c2 100644 --- a/packages/lexical-playground/src/index.css +++ b/packages/lexical-playground/src/index.css @@ -1368,6 +1368,21 @@ button.action-button:disabled { text-decoration: underline; } +.debug-treetype-button { + border: 0; + padding: 0; + font-size: 12px; + top: 10px; + right: 85px; + position: absolute; + background: none; + color: #fff; +} + +.debug-treetype-button:hover { + text-decoration: underline; +} + .connecting { font-size: 15px; color: #999; diff --git a/packages/lexical-playground/src/plugins/TreeViewPlugin/index.tsx b/packages/lexical-playground/src/plugins/TreeViewPlugin/index.tsx index 6daeb39462d..68eae89a00b 100644 --- a/packages/lexical-playground/src/plugins/TreeViewPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/TreeViewPlugin/index.tsx @@ -15,6 +15,7 @@ export default function TreeViewPlugin(): JSX.Element { return ( = Object.freeze({ }); export function TreeView({ + treeTypeButtonClassName, timeTravelButtonClassName, timeTravelPanelSliderClassName, timeTravelPanelButtonClassName, @@ -60,6 +61,7 @@ export function TreeView({ editor, }: { editor: LexicalEditor; + treeTypeButtonClassName: string; timeTravelButtonClassName: string; timeTravelPanelButtonClassName: string; timeTravelPanelClassName: string; @@ -71,6 +73,7 @@ export function TreeView({ >([]); const [content, setContent] = useState(''); const [timeTravelEnabled, setTimeTravelEnabled] = useState(false); + const [showExportDOM, setShowExportDOM] = useState(false); const playingIndexRef = useRef(0); const treeElementRef = useRef(null); const inputRef = useRef(null); @@ -83,13 +86,7 @@ export function TreeView({ const generateTree = useCallback( (editorState: EditorState) => { - const treeText = generateContent( - editor.getEditorState(), - editor._config, - commandsLog, - editor._compositionKey, - editor._editable, - ); + const treeText = generateContent(editor, commandsLog, showExportDOM); setContent(treeText); @@ -100,24 +97,16 @@ export function TreeView({ ]); } }, - [commandsLog, editor, timeTravelEnabled], + [commandsLog, editor, timeTravelEnabled, showExportDOM], ); useEffect(() => { const editorState = editor.getEditorState(); - if (!showLimited && editorState._nodeMap.size > 1000) { - setContent( - generateContent( - editorState, - editor._config, - commandsLog, - editor._compositionKey, - editor._editable, - ), - ); + if (!showLimited && editorState._nodeMap.size < 1000) { + setContent(generateContent(editor, commandsLog, showExportDOM)); } - }, [commandsLog, editor, showLimited]); + }, [commandsLog, editor, showLimited, showExportDOM]); useEffect(() => { return mergeRegister( @@ -132,17 +121,18 @@ export function TreeView({ generateTree(editorState); }), editor.registerEditableListener(() => { - const treeText = generateContent( - editor.getEditorState(), - editor._config, - commandsLog, - editor._compositionKey, - editor._editable, - ); + const treeText = generateContent(editor, commandsLog, showExportDOM); setContent(treeText); }), ); - }, [commandsLog, editor, isLimited, generateTree, showLimited]); + }, [ + commandsLog, + editor, + showExportDOM, + isLimited, + generateTree, + showLimited, + ]); const totalEditorStates = timeStampedEditorStates.length; @@ -224,6 +214,14 @@ export function TreeView({ ) : null} + {!showLimited ? ( + + ) : null} {!timeTravelEnabled && (showLimited || !isLimited) && totalEditorStates > 2 && ( @@ -378,12 +376,23 @@ function printGridSelection(selection: GridSelection): string { } function generateContent( - editorState: EditorState, - editorConfig: EditorConfig, + editor: LexicalEditor, commandsLog: ReadonlyArray & {payload: unknown}>, - compositionKey: null | string, - editable: boolean, + exportDOM: boolean, ): string { + const editorState = editor.getEditorState(); + const editorConfig = editor._config; + const compositionKey = editor._compositionKey; + const editable = editor._editable; + + if (exportDOM) { + let htmlString = ''; + editorState.read(() => { + htmlString = printPrettyHTML($generateHtmlFromNodes(editor)); + }); + return htmlString; + } + let res = ' root\n'; const selectionString = editorState.read(() => { @@ -686,6 +695,30 @@ function printSelectedCharsLine({ ); } +function printPrettyHTML(str: string) { + const div = document.createElement('div'); + div.innerHTML = str.trim(); + return prettifyHTML(div, 0).innerHTML; +} + +function prettifyHTML(node: Element, level: number) { + const indentBefore = new Array(level++ + 1).join(' '); + const indentAfter = new Array(level - 1).join(' '); + let textNode; + + for (let i = 0; i < node.children.length; i++) { + textNode = document.createTextNode('\n' + indentBefore); + node.insertBefore(textNode, node.children[i]); + prettifyHTML(node.children[i], level); + if (node.lastElementChild === node.children[i]) { + textNode = document.createTextNode('\n' + indentAfter); + node.appendChild(textNode); + } + } + + return node; +} + function $getSelectionStartEnd( node: LexicalNode, selection: RangeSelection | GridSelection,