@@ -757,6 +757,42 @@ <h2 id="privacyDialogTitle">Privacy</h2>
757757 secretInput . addEventListener ( 'input' , updateEncoded ) ;
758758 encodedOutput . addEventListener ( 'input' , updateDecodedFromToken ) ;
759759
760+ // The encoded pane is a contenteditable div, so the browser's default
761+ // paste/drop inserts the source's rich HTML (with its own inline styles
762+ // like `white-space: nowrap` or `<pre>` wrappers) which overrides the
763+ // pane's `white-space: pre-wrap; word-break: break-all` and produces a
764+ // single overflowing line. Force plain text on every insertion path so
765+ // the layout stays wrapped regardless of where the token came from.
766+ const insertPlainText = ( text ) => {
767+ const selection = window . getSelection ( ) ;
768+ if ( ! selection || selection . rangeCount === 0 ) {
769+ encodedOutput . textContent = text ;
770+ } else {
771+ const range = selection . getRangeAt ( 0 ) ;
772+ if ( ! encodedOutput . contains ( range . commonAncestorContainer ) ) {
773+ encodedOutput . textContent = text ;
774+ } else {
775+ range . deleteContents ( ) ;
776+ range . insertNode ( document . createTextNode ( text ) ) ;
777+ range . collapse ( false ) ;
778+ selection . removeAllRanges ( ) ;
779+ selection . addRange ( range ) ;
780+ }
781+ }
782+ encodedOutput . dispatchEvent ( new Event ( 'input' , { bubbles : true } ) ) ;
783+ } ;
784+ encodedOutput . addEventListener ( 'paste' , ( e ) => {
785+ e . preventDefault ( ) ;
786+ const text = ( e . clipboardData ?? window . clipboardData ) ?. getData ( 'text/plain' ) ?? '' ;
787+ insertPlainText ( text ) ;
788+ } ) ;
789+ encodedOutput . addEventListener ( 'drop' , ( e ) => {
790+ e . preventDefault ( ) ;
791+ const text = e . dataTransfer ?. getData ( 'text/plain' ) ?? '' ;
792+ encodedOutput . focus ( ) ;
793+ insertPlainText ( text ) ;
794+ } ) ;
795+
760796 copyButton . addEventListener ( 'click' , async ( ) => {
761797 try {
762798 await navigator . clipboard . writeText ( encodedOutput . innerText ) ;
0 commit comments