@@ -43,6 +43,21 @@ function getSavedTheme() {
4343// Branding: set to false to hide the "Powered by Codebox" message
4444const SHOW_BRANDING = true
4545
46+ // Available languages for syntax highlighting
47+ const LANGUAGES = [
48+ { id : 'markdown' , label : 'Markdown' } ,
49+ { id : 'plaintext' , label : 'Plain Text' } ,
50+ { id : 'javascript' , label : 'JavaScript' } ,
51+ { id : 'typescript' , label : 'TypeScript' } ,
52+ { id : 'python' , label : 'Python' } ,
53+ { id : 'html' , label : 'HTML' } ,
54+ { id : 'css' , label : 'CSS' } ,
55+ { id : 'json' , label : 'JSON' } ,
56+ { id : 'yaml' , label : 'YAML' } ,
57+ { id : 'sql' , label : 'SQL' } ,
58+ { id : 'shell' , label : 'Shell' }
59+ ]
60+
4661function saveTheme ( theme ) {
4762 localStorage . setItem ( 'codebox_theme' , theme )
4863}
@@ -533,6 +548,13 @@ function createBranding() {
533548 `
534549}
535550
551+ function createLanguageSelector ( currentLanguage = 'markdown' ) {
552+ const options = LANGUAGES . map ( lang =>
553+ `<option value="${ lang . id } " ${ currentLanguage === lang . id ? 'selected' : '' } >${ lang . label } </option>`
554+ ) . join ( '' )
555+ return `<select id="language-select" class="language-select">${ options } </select>`
556+ }
557+
536558function startEditor ( slug , token , canEdit , userName ) {
537559 const app = document . getElementById ( 'app' )
538560
@@ -545,6 +567,7 @@ function startEditor(slug, token, canEdit, userName) {
545567 </div>
546568 <div class="controls">
547569 <span class="user-name">${ userName } </span>
570+ ${ createLanguageSelector ( ) }
548571 <span id="status" class="status hidden">connecting</span>
549572 ${ createThemeToggle ( ) }
550573 <button id="connect-btn" class="hidden">Reconnect</button>
@@ -566,12 +589,14 @@ function startEditor(slug, token, canEdit, userName) {
566589 } )
567590
568591 const ytext = ydoc . getText ( 'monaco' )
592+ const ySettings = ydoc . getMap ( 'settings' )
569593
570594 // Create Monaco editor
571595 const editorTheme = getEffectiveTheme ( ) === 'dark' ? 'vs-dark' : 'vs'
596+ const initialLanguage = ySettings . get ( 'language' ) || 'markdown'
572597 const editor = monaco . editor . create ( document . getElementById ( 'editor' ) , {
573598 value : '' ,
574- language : 'markdown' ,
599+ language : initialLanguage ,
575600 theme : editorTheme ,
576601 automaticLayout : true ,
577602 minimap : { enabled : false } ,
@@ -582,6 +607,39 @@ function startEditor(slug, token, canEdit, userName) {
582607 readOnly : ! canEdit
583608 } )
584609
610+ // Update language selector to match synced value
611+ const languageSelect = document . getElementById ( 'language-select' )
612+
613+ function updateLanguageFromYjs ( ) {
614+ const language = ySettings . get ( 'language' ) || 'markdown'
615+ if ( languageSelect . value !== language ) {
616+ languageSelect . value = language
617+ }
618+ const currentModel = editor . getModel ( )
619+ if ( currentModel && monaco . editor . getModel ( currentModel . uri ) ) {
620+ const currentLang = currentModel . getLanguageId ( )
621+ if ( currentLang !== language ) {
622+ monaco . editor . setModelLanguage ( currentModel , language )
623+ }
624+ }
625+ }
626+
627+ // Listen for remote changes to language setting
628+ ySettings . observe ( ( ) => {
629+ updateLanguageFromYjs ( )
630+ } )
631+
632+ // Update once synced
633+ provider . on ( 'sync' , ( ) => {
634+ updateLanguageFromYjs ( )
635+ } )
636+
637+ // Language selector handler - update Yjs when user changes
638+ languageSelect . addEventListener ( 'change' , ( e ) => {
639+ const newLanguage = e . target . value
640+ ySettings . set ( 'language' , newLanguage )
641+ } )
642+
585643 // Bind Yjs to Monaco
586644 const monacoBinding = new MonacoBinding (
587645 ytext ,
0 commit comments