@@ -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 ,
@@ -43,7 +44,6 @@ import {
4344 JupyterInputNode ,
4445 $isJupyterInputNode ,
4546} from '../nodes/JupyterInputNode' ;
46- import { $isJupyterInputHighlightNode } from '../nodes/JupyterInputHighlightNode' ;
4747import { registerCodeHighlighting } from '../nodes/JupyterInputHighlighter' ;
4848import {
4949 JupyterOutputNode ,
@@ -451,101 +451,36 @@ export const JupyterInputOutputPlugin = (
451451 } , [ editor , kernel ] ) ;
452452
453453 // Handle Ctrl+A to select all content within a Jupyter input cell
454- // Use Lexical command system with HIGH priority to intercept before default behavior
454+ // Use CRITICAL priority to run before Lexical's internal select-all handler
455455 useEffect ( ( ) => {
456456 return editor . registerCommand < KeyboardEvent > (
457457 SELECT_ALL_COMMAND ,
458458 ( event : KeyboardEvent ) => {
459- console . log (
460- '🎯 SELECT_ALL_COMMAND intercepted before default behavior' ,
461- ) ;
462-
463459 const selection = $getSelection ( ) ;
464460 if ( ! $isRangeSelection ( selection ) ) {
465- console . log ( '❌ No range selection available' ) ;
466- return false ; // Let default behavior handle it
467- }
468-
469- // Debug: Log current selection details BEFORE default Ctrl+A
470- console . log ( '📍 Current selection details (BEFORE default Ctrl+A):' , {
471- anchorKey : selection . anchor . key ,
472- anchorOffset : selection . anchor . offset ,
473- anchorType : selection . anchor . type ,
474- focusKey : selection . focus . key ,
475- focusOffset : selection . focus . offset ,
476- focusType : selection . focus . type ,
477- } ) ;
478-
479- // Start from the anchor node and traverse up the hierarchy
480- const anchorNode = selection . anchor . getNode ( ) ;
481- console . log ( '🔍 Anchor node details (BEFORE default Ctrl+A):' , {
482- type : anchorNode . getType ( ) ,
483- key : anchorNode . getKey ( ) ,
484- textContent : anchorNode . getTextContent ?.( ) ?. slice ( 0 , 50 ) || 'N/A' ,
485- parent : anchorNode . getParent ( ) ?. getType ( ) || 'No parent' ,
486- } ) ;
487-
488- // Also check the focus node in case it's different
489- const focusNode = selection . focus . getNode ( ) ;
490- if ( focusNode !== anchorNode ) {
491- console . log ( '🔍 Focus node (different from anchor):' , {
492- type : focusNode . getType ( ) ,
493- key : focusNode . getKey ( ) ,
494- textContent : focusNode . getTextContent ?.( ) ?. slice ( 0 , 50 ) || 'N/A' ,
495- parent : focusNode . getParent ( ) ?. getType ( ) || 'No parent' ,
496- } ) ;
461+ return false ;
497462 }
498463
499- let currentNode : LexicalNode | null = anchorNode ;
464+ // Traverse up from current node to find parent JupyterInputNode
465+ let currentNode : LexicalNode | null = selection . anchor . getNode ( ) ;
500466 let jupyterInputNode : JupyterInputNode | null = null ;
501467 let depth = 0 ;
502- const maxDepth = 20 ; // Prevent infinite loops
468+ const maxDepth = 20 ;
503469
504- // Traverse up the tree hierarchy
505470 while ( currentNode && depth < maxDepth ) {
506- const nodeType = currentNode . getType ( ) ;
507- const nodeKey = currentNode . getKey ( ) ;
508- const isJupyterInput = $isJupyterInputNode ( currentNode ) ;
509- const isJupyterHighlight = $isJupyterInputHighlightNode ( currentNode ) ;
510-
511- console . log (
512- `🔍 Depth ${ depth } : ${ nodeType } (${ nodeKey } ) - isJupyterInput: ${ isJupyterInput } , isJupyterHighlight: ${ isJupyterHighlight } ` ,
513- ) ;
514-
515- // Direct check: Is this node a JupyterInputNode?
516- if ( isJupyterInput ) {
471+ if ( $isJupyterInputNode ( currentNode ) ) {
517472 jupyterInputNode = currentNode as JupyterInputNode ;
518- console . log ( `🎯 SUCCESS: Found JupyterInputNode at depth ${ depth } ` ) ;
519- break ;
520- }
521-
522- // If this is a JupyterInputHighlightNode, continue traversing up
523- // (the parent should be a JupyterInputNode)
524- if ( isJupyterHighlight ) {
525- console . log (
526- `🔍 Found JupyterInputHighlightNode at depth ${ depth } , continuing traversal...` ,
527- ) ;
528- }
529-
530- // Move to parent
531- const parentNode : LexicalNode | null = currentNode . getParent ( ) ;
532- if ( parentNode ) {
533- currentNode = parentNode ;
534- depth ++ ;
535- } else {
536- console . log ( `🔍 No parent at depth ${ depth } , reached root` ) ;
537473 break ;
538474 }
539- }
540475
541- if ( depth >= maxDepth ) {
542- console . warn ( `🔍 Max depth ${ maxDepth } reached, stopping traversal` ) ;
476+ currentNode = currentNode . getParent ( ) ;
477+ depth ++ ;
543478 }
544479
545480 if ( jupyterInputNode ) {
546- console . log (
547- '🎯 SUCCESS: Found JupyterInputNode, selecting all content within cell' ,
548- ) ;
481+ // Prevent default browser behavior only when we're handling the event
482+ event . preventDefault ( ) ;
483+ event . stopPropagation ( ) ;
549484
550485 // Select all content within the Jupyter input node
551486 const rangeSelection = $createRangeSelection ( ) ;
@@ -556,16 +491,12 @@ export const JupyterInputOutputPlugin = (
556491 'element' ,
557492 ) ;
558493 $setSelection ( rangeSelection ) ;
559-
560- return true ; // Prevent default Ctrl+A behavior
494+ return true ; // Prevent default select-all behavior
561495 }
562496
563- console . log (
564- '❌ No JupyterInputNode found in hierarchy - allowing default Ctrl+A' ,
565- ) ;
566- return false ; // Let default behavior handle it
497+ return false ; // Allow default select-all if not in Jupyter cell
567498 } ,
568- COMMAND_PRIORITY_HIGH , // HIGH priority to intercept before default behavior
499+ COMMAND_PRIORITY_CRITICAL ,
569500 ) ;
570501 } , [ editor ] ) ;
571502
0 commit comments