@@ -5,14 +5,22 @@ export const AuthCodeBlock = ({
55 highlight,
66 children,
77} ) => {
8- const [ processedChildren , setProcessedChildren ] = useState ( children ) ;
8+ const [ displayText , setDisplayText ] = useState ( children ) ;
9+ const [ copyText , setCopyText ] = useState ( children ) ;
10+ const wrapperRef = React . useRef ( null ) ;
911
1012 useEffect ( ( ) => {
1113 let unsubscribe = null ;
1214
1315 function init ( ) {
16+ if ( ! window . autorun || ! window . rootStore ) {
17+ return ;
18+ }
19+
1420 unsubscribe = window . autorun ( ( ) => {
15- let processedChildren = children ;
21+ let processedChildrenForDisplay = children ;
22+ let processedChildrenForCopy = children ;
23+
1624 for ( const [
1725 key ,
1826 value ,
@@ -21,12 +29,27 @@ export const AuthCodeBlock = ({
2129 / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g,
2230 String . raw `\$&`
2331 ) ;
24- processedChildren = processedChildren . replaceAll (
32+
33+ // For display: mask client secret if it's not the placeholder
34+ let displayValue = value ;
35+ if ( key === "{yourClientSecret}" && value !== "{yourClientSecret}" ) {
36+ displayValue = value . substring ( 0 , 3 ) + "*****MASKED*****" ;
37+ }
38+
39+ processedChildrenForDisplay = processedChildrenForDisplay . replaceAll (
40+ new RegExp ( escapedKey , "g" ) ,
41+ displayValue
42+ ) ;
43+
44+ // For copy: use the actual value (unmasked)
45+ processedChildrenForCopy = processedChildrenForCopy . replaceAll (
2546 new RegExp ( escapedKey , "g" ) ,
2647 value
2748 ) ;
2849 }
29- setProcessedChildren ( processedChildren ) ;
50+
51+ setDisplayText ( processedChildrenForDisplay ) ;
52+ setCopyText ( processedChildrenForCopy ) ;
3053 } ) ;
3154 }
3255
@@ -42,15 +65,65 @@ export const AuthCodeBlock = ({
4265 } ;
4366 } , [ children ] ) ;
4467
68+ // Override clipboard write to copy unmasked text
69+ useEffect ( ( ) => {
70+ if ( ! wrapperRef . current ) return ;
71+
72+ const originalWriteText = navigator . clipboard . writeText . bind ( navigator . clipboard ) ;
73+ let isOverriding = false ;
74+
75+ const handleClick = ( e ) => {
76+ const button = e . target . closest ( '[data-testid="copy-code-button"]' ) ;
77+ if ( ! button || ! wrapperRef . current . contains ( button ) ) return ;
78+
79+ // Set flag to override next clipboard write
80+ isOverriding = true ;
81+
82+ // Override writeText temporarily
83+ navigator . clipboard . writeText = ( text ) => {
84+
85+ if ( isOverriding ) {
86+ isOverriding = false ;
87+ // Restore original immediately
88+ navigator . clipboard . writeText = originalWriteText ;
89+ // Write our copyText instead
90+ return originalWriteText ( copyText ) ;
91+ }
92+ return originalWriteText ( text ) ;
93+ } ;
94+
95+ // Reset after a short delay in case the write doesn't happen
96+ setTimeout ( ( ) => {
97+ if ( isOverriding ) {
98+ isOverriding = false ;
99+ navigator . clipboard . writeText = originalWriteText ;
100+ }
101+ } , 100 ) ;
102+ } ;
103+
104+ const wrapper = wrapperRef . current ;
105+ wrapper . addEventListener ( 'click' , handleClick , true ) ;
106+
107+ return ( ) => {
108+ wrapper . removeEventListener ( 'click' , handleClick , true ) ;
109+ // Restore original if still overridden
110+ if ( navigator . clipboard . writeText !== originalWriteText ) {
111+ navigator . clipboard . writeText = originalWriteText ;
112+ }
113+ } ;
114+ } , [ copyText ] ) ;
115+
45116 return (
46- < CodeBlock
47- filename = { filename }
48- icon = { icon }
49- language = { language }
50- lines
51- highlight = { highlight }
52- >
53- { processedChildren }
54- </ CodeBlock >
117+ < div ref = { wrapperRef } >
118+ < CodeBlock
119+ filename = { filename }
120+ icon = { icon }
121+ language = { language }
122+ lines
123+ highlight = { highlight }
124+ >
125+ { displayText }
126+ </ CodeBlock >
127+ </ div >
55128 ) ;
56129} ;
0 commit comments