@@ -13,6 +13,7 @@ import {
1313 COMMAND_PRIORITY_EDITOR ,
1414 INSERT_LINE_BREAK_COMMAND ,
1515 COMMAND_PRIORITY_HIGH ,
16+ COMMAND_PRIORITY_CRITICAL ,
1617 KEY_ENTER_COMMAND ,
1718 COMMAND_PRIORITY_LOW ,
1819 $createLineBreakNode ,
@@ -41,7 +42,6 @@ import {
4142 JupyterInputNode ,
4243 $isJupyterInputNode ,
4344} from '../nodes/JupyterInputNode' ;
44- import { $isJupyterInputHighlightNode } from '../nodes/JupyterInputHighlightNode' ;
4545import { registerCodeHighlighting } from '../nodes/JupyterInputHighlighter' ;
4646import {
4747 JupyterOutputNode ,
@@ -425,101 +425,36 @@ export const JupyterInputOutputPlugin = (
425425 } , [ editor , kernel ] ) ;
426426
427427 // Handle Ctrl+A to select all content within a Jupyter input cell
428- // Use Lexical command system with HIGH priority to intercept before default behavior
428+ // Use CRITICAL priority to run before Lexical's internal select-all handler
429429 useEffect ( ( ) => {
430430 return editor . registerCommand < KeyboardEvent > (
431431 SELECT_ALL_COMMAND ,
432432 ( event : KeyboardEvent ) => {
433- console . log (
434- '🎯 SELECT_ALL_COMMAND intercepted before default behavior' ,
435- ) ;
436-
437433 const selection = $getSelection ( ) ;
438434 if ( ! $isRangeSelection ( selection ) ) {
439- console . log ( '❌ No range selection available' ) ;
440- return false ; // Let default behavior handle it
435+ return false ;
441436 }
442437
443- // Debug: Log current selection details BEFORE default Ctrl+A
444- console . log ( '📍 Current selection details (BEFORE default Ctrl+A):' , {
445- anchorKey : selection . anchor . key ,
446- anchorOffset : selection . anchor . offset ,
447- anchorType : selection . anchor . type ,
448- focusKey : selection . focus . key ,
449- focusOffset : selection . focus . offset ,
450- focusType : selection . focus . type ,
451- } ) ;
452-
453- // Start from the anchor node and traverse up the hierarchy
454- const anchorNode = selection . anchor . getNode ( ) ;
455- console . log ( '🔍 Anchor node details (BEFORE default Ctrl+A):' , {
456- type : anchorNode . getType ( ) ,
457- key : anchorNode . getKey ( ) ,
458- textContent : anchorNode . getTextContent ?.( ) ?. slice ( 0 , 50 ) || 'N/A' ,
459- parent : anchorNode . getParent ( ) ?. getType ( ) || 'No parent' ,
460- } ) ;
461-
462- // Also check the focus node in case it's different
463- const focusNode = selection . focus . getNode ( ) ;
464- if ( focusNode !== anchorNode ) {
465- console . log ( '🔍 Focus node (different from anchor):' , {
466- type : focusNode . getType ( ) ,
467- key : focusNode . getKey ( ) ,
468- textContent : focusNode . getTextContent ?.( ) ?. slice ( 0 , 50 ) || 'N/A' ,
469- parent : focusNode . getParent ( ) ?. getType ( ) || 'No parent' ,
470- } ) ;
471- }
472-
473- let currentNode : LexicalNode | null = anchorNode ;
438+ // Traverse up from current node to find parent JupyterInputNode
439+ let currentNode : LexicalNode | null = selection . anchor . getNode ( ) ;
474440 let jupyterInputNode : JupyterInputNode | null = null ;
475441 let depth = 0 ;
476- const maxDepth = 20 ; // Prevent infinite loops
442+ const maxDepth = 20 ;
477443
478- // Traverse up the tree hierarchy
479444 while ( currentNode && depth < maxDepth ) {
480- const nodeType = currentNode . getType ( ) ;
481- const nodeKey = currentNode . getKey ( ) ;
482- const isJupyterInput = $isJupyterInputNode ( currentNode ) ;
483- const isJupyterHighlight = $isJupyterInputHighlightNode ( currentNode ) ;
484-
485- console . log (
486- `🔍 Depth ${ depth } : ${ nodeType } (${ nodeKey } ) - isJupyterInput: ${ isJupyterInput } , isJupyterHighlight: ${ isJupyterHighlight } ` ,
487- ) ;
488-
489- // Direct check: Is this node a JupyterInputNode?
490- if ( isJupyterInput ) {
445+ if ( $isJupyterInputNode ( currentNode ) ) {
491446 jupyterInputNode = currentNode as JupyterInputNode ;
492- console . log ( `🎯 SUCCESS: Found JupyterInputNode at depth ${ depth } ` ) ;
493447 break ;
494448 }
495449
496- // If this is a JupyterInputHighlightNode, continue traversing up
497- // (the parent should be a JupyterInputNode)
498- if ( isJupyterHighlight ) {
499- console . log (
500- `🔍 Found JupyterInputHighlightNode at depth ${ depth } , continuing traversal...` ,
501- ) ;
502- }
503-
504- // Move to parent
505- const parentNode : LexicalNode | null = currentNode . getParent ( ) ;
506- if ( parentNode ) {
507- currentNode = parentNode ;
508- depth ++ ;
509- } else {
510- console . log ( `🔍 No parent at depth ${ depth } , reached root` ) ;
511- break ;
512- }
513- }
514-
515- if ( depth >= maxDepth ) {
516- console . warn ( `🔍 Max depth ${ maxDepth } reached, stopping traversal` ) ;
450+ currentNode = currentNode . getParent ( ) ;
451+ depth ++ ;
517452 }
518453
519454 if ( jupyterInputNode ) {
520- console . log (
521- '🎯 SUCCESS: Found JupyterInputNode, selecting all content within cell' ,
522- ) ;
455+ // Prevent default browser behavior only when we're handling the event
456+ event . preventDefault ( ) ;
457+ event . stopPropagation ( ) ;
523458
524459 // Select all content within the Jupyter input node
525460 const rangeSelection = $createRangeSelection ( ) ;
@@ -530,16 +465,12 @@ export const JupyterInputOutputPlugin = (
530465 'element' ,
531466 ) ;
532467 $setSelection ( rangeSelection ) ;
533-
534- return true ; // Prevent default Ctrl+A behavior
468+ return true ; // Prevent default select-all behavior
535469 }
536470
537- console . log (
538- '❌ No JupyterInputNode found in hierarchy - allowing default Ctrl+A' ,
539- ) ;
540- return false ; // Let default behavior handle it
471+ return false ; // Allow default select-all if not in Jupyter cell
541472 } ,
542- COMMAND_PRIORITY_HIGH , // HIGH priority to intercept before default behavior
473+ COMMAND_PRIORITY_CRITICAL ,
543474 ) ;
544475 } , [ editor ] ) ;
545476
0 commit comments