276276 }
277277
278278 # editor {
279- flex : 1 ;
279+ position : absolute;
280+ top : 0 ;
281+ left : 0 ;
282+ right : 0 ;
283+ bottom : 0 ;
280284 padding : 20px ;
281285 font-family : 'Menlo' , 'Monaco' , 'Consolas' , 'Courier New' , monospace;
282286 font-size : 14px ;
283287 line-height : 1.7 ;
284- background : var ( --bg-primary ) ;
285- color : var ( --text-primary ) ;
288+ background : transparent ;
289+ color : transparent ;
286290 border : none;
287291 outline : none;
288292 resize : none;
289293 tab-size : 4 ;
290294 overflow-y : auto;
295+ caret-color : white;
296+ z-index : 2 ;
297+ }
298+
299+ # editor-wrapper {
300+ flex : 1 ;
301+ position : relative;
302+ overflow : hidden;
291303 }
292304
305+ # editor-highlight {
306+ position : absolute;
307+ top : 0 ;
308+ left : 0 ;
309+ right : 0 ;
310+ bottom : 0 ;
311+ padding : 20px ;
312+ font-family : 'Menlo' , 'Monaco' , 'Consolas' , 'Courier New' , monospace;
313+ font-size : 14px ;
314+ line-height : 1.7 ;
315+ white-space : pre-wrap;
316+ word-wrap : break-word;
317+ overflow-y : auto;
318+ pointer-events : none;
319+ z-index : 1 ;
320+ }
321+
322+ /* Syntax highlighting colors - VS Code Dark+ theme */
323+ .hljs-keyword { color : # 569cd6 ; } /* Blue for keywords */
324+ .hljs-type { color : # 4ec9b0 ; } /* Teal for types */
325+ .hljs-string { color : # ce9178 ; } /* Orange for strings */
326+ .hljs-number { color : # b5cea8 ; } /* Light green for numbers */
327+ .hljs-comment { color : # 6a9955 ; font-style : italic; } /* Green for comments */
328+ .hljs-function { color : # dcdcaa ; } /* Yellow for functions */
329+ .hljs-preprocessor { color : # c586c0 ; } /* Purple for preprocessor */
330+ .hljs-operator { color : # d4d4d4 ; }
331+ .hljs-punctuation { color : # d4d4d4 ; }
332+
293333 # output {
294334 flex : 1 ;
295335 padding : 20px ;
@@ -422,7 +462,10 @@ <h1>Null-Safe C Playground</h1>
422462 < button class ="icon-btn " title ="Keyboard shortcut: Cmd/Ctrl+Enter "> ⌨️ Ctrl+Enter to compile</ button >
423463 </ div >
424464 </ div >
425- < textarea id ="editor " spellcheck ="false " placeholder ="Write your C code here... "> </ textarea >
465+ < div id ="editor-wrapper ">
466+ < div id ="editor-highlight "> </ div >
467+ < textarea id ="editor " spellcheck ="false " placeholder ="Write your C code here... "> </ textarea >
468+ </ div >
426469 </ div >
427470
428471 < div class ="divider " id ="divider "> </ div >
@@ -442,6 +485,7 @@ <h1>Null-Safe C Playground</h1>
442485
443486 < script >
444487 const editor = document . getElementById ( 'editor' ) ;
488+ const editorHighlight = document . getElementById ( 'editor-highlight' ) ;
445489 const output = document . getElementById ( 'output' ) ;
446490 const compileBtn = document . getElementById ( 'compileBtn' ) ;
447491 const status = document . getElementById ( 'status' ) ;
@@ -453,6 +497,78 @@ <h1>Null-Safe C Playground</h1>
453497 const outputStats = document . getElementById ( 'outputStats' ) ;
454498 const divider = document . getElementById ( 'divider' ) ;
455499
500+ // Simple C syntax highlighter
501+ function highlightCode ( code ) {
502+ // Escape HTML
503+ code = code . replace ( / & / g, '&' ) . replace ( / < / g, '<' ) . replace ( / > / g, '>' ) ;
504+
505+ // Store strings and comments temporarily to avoid highlighting inside them
506+ const protected = [ ] ;
507+ let index = 0 ;
508+
509+ // Protect multi-line comments
510+ code = code . replace ( / \/ \* [ \s \S ] * ?\* \/ / g, match => {
511+ const placeholder = `___PROTECTED_${ index } ___` ;
512+ protected . push ( `<span class="hljs-comment">${ match } </span>` ) ;
513+ index ++ ;
514+ return placeholder ;
515+ } ) ;
516+
517+ // Protect single-line comments
518+ code = code . replace ( / \/ \/ .* / g, match => {
519+ const placeholder = `___PROTECTED_${ index } ___` ;
520+ protected . push ( `<span class="hljs-comment">${ match } </span>` ) ;
521+ index ++ ;
522+ return placeholder ;
523+ } ) ;
524+
525+ // Protect strings
526+ code = code . replace ( / " ( [ ^ " \\ ] | \\ .) * " / g, match => {
527+ const placeholder = `___PROTECTED_${ index } ___` ;
528+ protected . push ( `<span class="hljs-string">${ match } </span>` ) ;
529+ index ++ ;
530+ return placeholder ;
531+ } ) ;
532+
533+ // Now safely highlight everything else
534+
535+ // Preprocessor directives
536+ code = code . replace ( / ( ^ | \n ) ( # \s * (?: i n c l u d e | d e f i n e | u n d e f | i f d e f | i f n d e f | i f | e l s e | e l i f | e n d i f | p r a g m a | e r r o r | w a r n i n g | l i n e ) \b [ ^ \n ] * ) / g,
537+ ( match , newline , directive ) => `${ newline } <span class="hljs-preprocessor">${ directive } </span>` ) ;
538+
539+ // Numbers
540+ code = code . replace ( / \b ( \d + \. ? \d * | \. \d + ) ( [ e E ] [ + - ] ? \d + ) ? [ f F l L u U ] ? \b / g,
541+ match => `<span class="hljs-number">${ match } </span>` ) ;
542+
543+ // Keywords
544+ code = code . replace ( / \b ( a u t o | b r e a k | c a s e | c h a r | c o n s t | c o n t i n u e | d e f a u l t | d o | d o u b l e | e l s e | e n u m | e x t e r n | f l o a t | f o r | g o t o | i f | i n l i n e | i n t | l o n g | r e g i s t e r | r e s t r i c t | r e t u r n | s h o r t | s i g n e d | s i z e o f | s t a t i c | s t r u c t | s w i t c h | t y p e d e f | u n i o n | u n s i g n e d | v o i d | v o l a t i l e | w h i l e | _ B o o l | _ C o m p l e x | _ I m a g i n a r y | _ N u l l a b l e | _ N o n n u l l ) \b / g,
545+ match => `<span class="hljs-keyword">${ match } </span>` ) ;
546+
547+ // Function names
548+ code = code . replace ( / \b ( [ a - z A - Z _ ] [ a - z A - Z 0 - 9 _ ] * ) \s * (? = \( ) / g,
549+ ( match , name ) => `<span class="hljs-function">${ name } </span> (` ) ;
550+
551+ // Restore protected strings and comments
552+ for ( let i = 0 ; i < protected . length ; i ++ ) {
553+ code = code . replace ( `___PROTECTED_${ i } ___` , protected [ i ] ) ;
554+ }
555+
556+ return code ;
557+ }
558+
559+ function updateHighlight ( ) {
560+ const code = editor . value ;
561+ editorHighlight . innerHTML = highlightCode ( code ) ;
562+ // Sync scroll
563+ editorHighlight . scrollTop = editor . scrollTop ;
564+ }
565+
566+ // Update highlighting on input
567+ editor . addEventListener ( 'input' , updateHighlight ) ;
568+ editor . addEventListener ( 'scroll' , ( ) => {
569+ editorHighlight . scrollTop = editor . scrollTop ;
570+ } ) ;
571+
456572 const examples = {
457573 'null-check' : `#include <stdio.h>
458574#include <stdlib.h>
@@ -515,6 +631,7 @@ <h1>Null-Safe C Playground</h1>
515631
516632 const defaultCode = examples [ 'null-check' ] ;
517633 editor . value = defaultCode ;
634+ updateHighlight ( ) ; // Initial highlight
518635
519636 let ClangModule = null ;
520637 let isCompiling = false ;
@@ -559,6 +676,7 @@ <h1>Null-Safe C Playground</h1>
559676 const example = e . target . value ;
560677 if ( example && examples [ example ] ) {
561678 editor . value = examples [ example ] ;
679+ updateHighlight ( ) ; // Update highlighting
562680 showToast ( 'Example loaded!' ) ;
563681 e . target . value = '' ;
564682 }
0 commit comments