@@ -34,6 +34,55 @@ export const Editor = ({
3434 const divEl = useRef < HTMLDivElement > ( null ) ;
3535 const editorRef =
3636 useRef < import ( 'monaco-editor' ) . editor . IStandaloneCodeEditor > ( null ) ;
37+ const urlUpdateTimer = useRef < number | null > ( null ) ;
38+
39+ function decodeParam ( value : string | null ) : string | null {
40+ if ( ! value ) return null ;
41+ try {
42+ return decodeURIComponent ( value ) ;
43+ } catch {
44+ return value ;
45+ }
46+ }
47+
48+ function getInitialCode ( ) : string {
49+ if ( typeof window === 'undefined' ) {
50+ return [ 'let a: any;' , 'a.b = 10;' ] . join ( '\n' ) ;
51+ }
52+ const { search, hash } = window . location ;
53+ const searchParams = new URLSearchParams ( search ) ;
54+ // URLSearchParams.get already decodes percent-encoding
55+ const fromSearch = searchParams . get ( 'code' ) ;
56+ if ( fromSearch != null ) return fromSearch ;
57+ // Also support hash like #code=...
58+ if ( hash && hash . startsWith ( '#' ) ) {
59+ const hashParams = new URLSearchParams ( hash . slice ( 1 ) ) ;
60+ const fromHash = hashParams . get ( 'code' ) ;
61+ if ( fromHash != null ) return fromHash ;
62+ }
63+ return [ 'let a: any;' , 'a.b = 10;' ] . join ( '\n' ) ;
64+ }
65+
66+ function scheduleSerializeToUrl ( value : string ) {
67+ if ( typeof window === 'undefined' ) return ;
68+ if ( urlUpdateTimer . current ) {
69+ window . clearTimeout ( urlUpdateTimer . current ) ;
70+ urlUpdateTimer . current = null ;
71+ }
72+ urlUpdateTimer . current = window . setTimeout ( ( ) => {
73+ try {
74+ const url = new URL ( window . location . href ) ;
75+ url . searchParams . set ( 'code' , value ) ;
76+ // Remove any code=... from hash if present to avoid ambiguity
77+ if ( url . hash && url . hash . includes ( 'code=' ) ) {
78+ url . hash = '' ;
79+ }
80+ window . history . replaceState ( null , '' , url . toString ( ) ) ;
81+ } catch {
82+ // ignore URL update errors
83+ }
84+ } , 300 ) ;
85+ }
3786 // get value from editor using forwardRef
3887 React . useImperativeHandle ( ref , ( ) => ( {
3988 getValue : ( ) => editorRef . current ?. getValue ( ) ,
@@ -68,15 +117,24 @@ export const Editor = ({
68117 }
69118
70119 const editor = monaco . editor . create ( divEl . current , {
71- value : [ 'let a: any;' , 'a.b = 10;' ] . join ( '\n' ) ,
120+ value : getInitialCode ( ) ,
72121 language : 'typescript' ,
73122 automaticLayout : true ,
74123 scrollBeyondLastLine : false ,
75124 } ) ;
125+ // Ensure ref is set before first onChange so parent can read value
126+ editorRef . current = editor ;
127+ // Trigger initial onChange + URL sync with initial value
128+ {
129+ const initialVal = editor . getValue ( ) || '' ;
130+ onChange ( initialVal ) ;
131+ scheduleSerializeToUrl ( initialVal ) ;
132+ }
76133 editor . onDidChangeModelContent ( ( ) => {
77- onChange ( editor . getValue ( ) || '' ) ;
134+ const val = editor . getValue ( ) || '' ;
135+ onChange ( val ) ;
136+ scheduleSerializeToUrl ( val ) ;
78137 } ) ;
79- editorRef . current = editor ;
80138
81139 return ( ) => {
82140 editor . dispose ( ) ;
0 commit comments