@@ -67,6 +67,10 @@ interface ActiveNode {
6767 class ?: 'tooltip-top' | 'tooltip-bottom' ;
6868}
6969
70+ type InspectorAction = 'copy' | 'locate' | 'target' | 'all' ;
71+ type TrackAction = InspectorAction | 'default' ;
72+ type ResolvedAction = InspectorAction | 'none' ;
73+
7074const PopperWidth = 300 ;
7175
7276function nextTick ( ) {
@@ -89,7 +93,9 @@ export class CodeInspectorComponent extends LitElement {
8993 @property ( )
9094 locate : boolean = true ;
9195 @property ( )
92- copy : boolean | string = false ;
96+ copy : boolean | string = true ;
97+ @property ( { attribute : 'default-action' } )
98+ defaultAction : InspectorAction = 'copy' ;
9399 @property ( )
94100 target : string = '' ;
95101 @property ( )
@@ -531,16 +537,41 @@ export class CodeInspectorComponent extends LitElement {
531537 } ;
532538
533539 // 触发功能的处理
534- trackCode = ( ) => {
535- if ( this . locate ) {
536- // 请求本地服务端,打开vscode
540+ trackCode = ( action : TrackAction = 'default' ) => {
541+ let resolvedAction : ResolvedAction ;
542+ if ( action === 'default' ) {
543+ resolvedAction = this . getDefaultAction ( ) ;
544+ } else if ( action === 'all' ) {
545+ resolvedAction = this . copy || this . locate || this . target ? 'all' : 'none' ;
546+ } else if ( this . isActionEnabled ( action ) ) {
547+ resolvedAction = action ;
548+ } else {
549+ resolvedAction = 'none' ;
550+ }
551+
552+ if ( resolvedAction === 'none' ) {
553+ return ;
554+ }
555+
556+ const shouldLocate =
557+ ( resolvedAction === 'locate' || resolvedAction === 'all' ) && this . locate ;
558+ const shouldCopy =
559+ ( resolvedAction === 'copy' || resolvedAction === 'all' ) && ! ! this . copy ;
560+ const shouldTarget =
561+ ( resolvedAction === 'target' || resolvedAction === 'all' ) && ! ! this . target ;
562+
563+ if ( ! shouldLocate && ! shouldCopy && ! shouldTarget ) {
564+ return ;
565+ }
566+
567+ if ( shouldLocate ) {
537568 if ( this . sendType === 'xhr' ) {
538569 this . sendXHR ( ) ;
539570 } else {
540571 this . sendImg ( ) ;
541572 }
542573 }
543- if ( this . copy ) {
574+ if ( shouldCopy ) {
544575 const path = formatOpenPath (
545576 this . element . path ,
546577 String ( this . element . line ) ,
@@ -549,14 +580,133 @@ export class CodeInspectorComponent extends LitElement {
549580 ) ;
550581 this . copyToClipboard ( path [ 0 ] ) ;
551582 }
552- if ( this . target ) {
583+ if ( shouldTarget ) {
553584 window . open ( this . buildTargetUrl ( ) , '_blank' ) ;
554585 }
555- window . dispatchEvent ( new CustomEvent ( 'code-inspector:trackCode' , {
556- detail : this . element ,
557- } ) ) ;
586+ window . dispatchEvent (
587+ new CustomEvent ( 'code-inspector:trackCode' , {
588+ detail : this . element ,
589+ } )
590+ ) ;
591+ } ;
592+
593+ private getDefaultAction ( ) : ResolvedAction {
594+ const resolved = this . resolvePreferredAction ( this . defaultAction ) ;
595+ if ( resolved !== 'none' && resolved !== this . defaultAction ) {
596+ this . defaultAction = resolved ;
597+ }
598+ return resolved ;
599+ }
600+
601+ private isActionEnabled ( action : Exclude < InspectorAction , 'all' > ) : boolean {
602+ if ( action === 'copy' ) {
603+ return ! ! this . copy ;
604+ }
605+ if ( action === 'locate' ) {
606+ return ! ! this . locate ;
607+ }
608+ return ! ! this . target ;
609+ }
610+
611+ private resolvePreferredAction (
612+ preferred : InspectorAction
613+ ) : ResolvedAction {
614+ if ( preferred === 'all' ) {
615+ return this . copy || this . locate || this . target ? 'all' : 'none' ;
616+ }
617+ if ( this . isActionEnabled ( preferred ) ) {
618+ return preferred ;
619+ }
620+ const fallbackOrder : Array < Exclude < InspectorAction , 'all' > > = [
621+ 'copy' ,
622+ 'locate' ,
623+ 'target' ,
624+ ] ;
625+ for ( const candidate of fallbackOrder ) {
626+ if ( candidate !== preferred && this . isActionEnabled ( candidate ) ) {
627+ return candidate ;
628+ }
629+ }
630+ return 'none' ;
631+ }
632+
633+ private getAvailableDefaultActions ( ) : InspectorAction [ ] {
634+ const actions : InspectorAction [ ] = [ ] ;
635+ if ( this . copy ) {
636+ actions . push ( 'copy' ) ;
637+ }
638+ if ( this . locate ) {
639+ actions . push ( 'locate' ) ;
640+ }
641+ if ( this . target ) {
642+ actions . push ( 'target' ) ;
643+ }
644+ if ( actions . length > 1 && this . copy && this . locate ) {
645+ actions . push ( 'all' ) ;
646+ }
647+ return actions ;
648+ }
649+
650+ private handleModeShortcut = ( e : KeyboardEvent ) => {
651+ if ( ! e . shiftKey || ! e . altKey ) {
652+ return ;
653+ }
654+ const code = e . code ?. toLowerCase ( ) ;
655+ const key = e . key ?. toLowerCase ( ) ;
656+ const isCKey = code ? code === 'keyc' : key === 'c' ;
657+ if ( ! isCKey ) {
658+ return ;
659+ }
660+ e . preventDefault ( ) ;
661+ e . stopPropagation ( ) ;
662+ const actions = this . getAvailableDefaultActions ( ) ;
663+ if ( actions . length <= 1 ) {
664+ return ;
665+ }
666+ const currentIndex = actions . indexOf ( this . defaultAction ) ;
667+ const nextAction =
668+ currentIndex === - 1
669+ ? actions [ 0 ]
670+ : actions [ ( currentIndex + 1 ) % actions . length ] ;
671+ this . defaultAction = nextAction ;
672+ this . printModeChange ( nextAction ) ;
558673 } ;
559674
675+ private printModeChange ( action : InspectorAction ) {
676+ if ( this . hideConsole ) {
677+ return ;
678+ }
679+ const label = this . getActionLabel ( action ) ;
680+ const agent =
681+ typeof navigator !== 'undefined' ? navigator . userAgent . toLowerCase ( ) : '' ;
682+ const isWindows = [ 'windows' , 'win32' , 'wow32' , 'win64' , 'wow64' ] . some (
683+ ( item ) => agent . toUpperCase ( ) . includes ( item . toUpperCase ( ) )
684+ ) ;
685+ const shortcut = isWindows ? 'Shift+Alt+C' : 'Shift+Opt+C' ;
686+ console . log (
687+ `%c[code-inspector-plugin]%c Mode switched to %c${ label } %c (${ shortcut } )` ,
688+ 'color: #006aff; font-weight: bolder; font-size: 12px;' ,
689+ 'color: #006aff; font-size: 12px;' ,
690+ 'color: #00B42A; font-weight: bold; font-size: 12px;' ,
691+ 'color: #006aff; font-size: 12px;'
692+ ) ;
693+ }
694+
695+ private getActionLabel ( action : ResolvedAction ) : string {
696+ switch ( action ) {
697+ case 'copy' :
698+ return 'Copy Path' ;
699+ case 'locate' :
700+ return 'Open in IDE' ;
701+ case 'target' :
702+ return 'Open Target Link' ;
703+ case 'all' :
704+ return 'Copy + Open' ;
705+ default :
706+ return 'Disabled' ;
707+ }
708+ }
709+
560710 copyToClipboard ( text : string ) {
561711 if ( typeof navigator ?. clipboard ?. writeText === 'function' ) {
562712 navigator . clipboard . writeText ( text ) ;
@@ -657,8 +807,10 @@ export class CodeInspectorComponent extends LitElement {
657807 e . stopPropagation ( ) ;
658808 // 阻止默认事件
659809 e . preventDefault ( ) ;
660- // 唤醒 vscode
661- this . trackCode ( ) ;
810+ const primaryAction = this . getDefaultAction ( ) ;
811+ if ( primaryAction !== 'none' ) {
812+ this . trackCode ( primaryAction as InspectorAction ) ;
813+ }
662814 // 清除遮罩层
663815 this . removeCover ( ) ;
664816 if ( this . autoToggle ) {
@@ -756,6 +908,7 @@ export class CodeInspectorComponent extends LitElement {
756908 const isWindows = [ 'windows' , 'win32' , 'wow32' , 'win64' , 'wow64' ] . some (
757909 ( item ) => agent . toUpperCase ( ) . match ( item . toUpperCase ( ) )
758910 ) ;
911+ const modeShortcut = isWindows ? 'Shift+Alt+C' : 'Shift+Opt+C' ;
759912 const hotKeyMap = isWindows ? WindowsHotKeyMap : MacHotKeyMap ;
760913 const keys = this . hotKeys
761914 . split ( ',' )
@@ -771,10 +924,11 @@ export class CodeInspectorComponent extends LitElement {
771924 }
772925 } ) ;
773926 const replacement = '%c' ;
927+ const currentMode = this . getActionLabel ( this . getDefaultAction ( ) ) ;
774928 console . log (
775929 `${ replacement } [code-inspector-plugin]${ replacement } Press and hold ${ keys . join (
776930 ` ${ replacement } + `
777- ) } ${ replacement } to enable the feature. (click on page elements to locate the source code in the editor )`,
931+ ) } ${ replacement } to enable the feature. (Current mode: ${ currentMode } ; press ${ modeShortcut } to switch )`,
778932 'color: #006aff; font-weight: bolder; font-size: 12px;' ,
779933 ...colors
780934 ) ;
@@ -829,7 +983,7 @@ export class CodeInspectorComponent extends LitElement {
829983
830984 handleClickTreeNode = ( node : TreeNode ) => {
831985 this . element = node ;
832- this . trackCode ( ) ;
986+ this . trackCode ( 'locate' ) ;
833987 this . removeLayerPanel ( ) ;
834988 } ;
835989
@@ -883,6 +1037,7 @@ export class CodeInspectorComponent extends LitElement {
8831037 window . addEventListener ( 'click' , this . handleMouseClick , true ) ;
8841038 window . addEventListener ( 'pointerdown' , this . handlePointerDown , true ) ;
8851039 window . addEventListener ( 'keyup' , this . handleKeyUp , true ) ;
1040+ window . addEventListener ( 'keydown' , this . handleModeShortcut , true ) ;
8861041 window . addEventListener ( 'mouseleave' , this . removeCover , true ) ;
8871042 window . addEventListener ( 'mouseup' , this . handleMouseUp , true ) ;
8881043 window . addEventListener ( 'touchend' , this . handleMouseUp , true ) ;
@@ -897,6 +1052,7 @@ export class CodeInspectorComponent extends LitElement {
8971052 window . removeEventListener ( 'click' , this . handleMouseClick , true ) ;
8981053 window . removeEventListener ( 'pointerdown' , this . handlePointerDown , true ) ;
8991054 window . removeEventListener ( 'keyup' , this . handleKeyUp , true ) ;
1055+ window . removeEventListener ( 'keydown' , this . handleModeShortcut , true ) ;
9001056 window . removeEventListener ( 'mouseleave' , this . removeCover , true ) ;
9011057 window . removeEventListener ( 'mouseup' , this . handleMouseUp , true ) ;
9021058 window . removeEventListener ( 'touchend' , this . handleMouseUp , true ) ;
@@ -967,6 +1123,13 @@ export class CodeInspectorComponent extends LitElement {
9671123 bottom : this . activeNode . bottom ,
9681124 display : this . showNodeTree ? '' : 'none' ,
9691125 } ;
1126+ const resolvedDefaultAction = this . getDefaultAction ( ) ;
1127+ const modeLabel = this . getActionLabel ( resolvedDefaultAction ) ;
1128+ const modeShortcut =
1129+ typeof navigator !== 'undefined' &&
1130+ / m a c | i p h o n e | i p a d | i p o d / i. test ( navigator . userAgent )
1131+ ? 'Shift+Opt+C'
1132+ : 'Shift+Alt+C' ;
9701133
9711134 return html `
9721135 <div
@@ -995,7 +1158,9 @@ export class CodeInspectorComponent extends LitElement {
9951158 <div class= "name-line" >
9961159 <div class= "element-name" >
9971160 <span class= "element-title" > & lt;${ this . element . name } & gt;</ span>
998- <span class= "element-tip" > click to open editor </ span>
1161+ <span class= "element-tip" >
1162+ Mode : ${ modeLabel } · ${ modeShortcut } to switch
1163+ </ span>
9991164 </ div>
10001165 </ div>
10011166 <div class= "path-line" >
0 commit comments