@@ -17,6 +17,10 @@ export type CodeData = BlockToolData<{
1717 * The code content input by the user
1818 */
1919 code : string ;
20+ /**
21+ * The language of the code block
22+ */
23+ language : string ;
2024} > ;
2125
2226/**
@@ -27,6 +31,10 @@ export interface CodeConfig {
2731 * Placeholder text to display in the input field when it's empty
2832 */
2933 placeholder : string ;
34+ /**
35+ * a list of languges
36+ */
37+ languages : Record < string , string > ;
3038}
3139
3240/**
@@ -51,6 +59,8 @@ interface CodeToolNodes {
5159 holder : HTMLDivElement | null ;
5260 /** Textarea where user inputs their code */
5361 textarea : HTMLTextAreaElement | null ;
62+ /** Language selector */
63+ languageSelector : HTMLDivElement | null ;
5464}
5565
5666/**
@@ -75,7 +85,12 @@ export default class CodeTool implements BlockTool {
7585 */
7686 private placeholder : string ;
7787 /**
78- * Collection of CSS class names used by CodeTool for styling its elements
88+ * Language options in the dropdown
89+ *
90+ */
91+ private languages : Record < string , string > ;
92+
93+ /* Collection of CSS class names used by CodeTool for styling its elements
7994 */
8095 private CSS : CodeToolCSS ;
8196 /**
@@ -118,6 +133,8 @@ export default class CodeTool implements BlockTool {
118133
119134 this . placeholder = this . api . i18n . t ( config . placeholder as string || CodeTool . DEFAULT_PLACEHOLDER ) ;
120135
136+ this . languages = ( config . languages as Record < string , string > ) ;
137+
121138 this . CSS = {
122139 baseClass : this . api . styles . block ,
123140 input : this . api . styles . input ,
@@ -128,10 +145,12 @@ export default class CodeTool implements BlockTool {
128145 this . nodes = {
129146 holder : null ,
130147 textarea : null ,
148+ languageSelector : null ,
131149 } ;
132150
133151 this . data = {
134152 code : data . code ?? '' ,
153+ language : data . language ?? '' ,
135154 } ;
136155
137156 this . nodes . holder = this . drawView ( ) ;
@@ -153,6 +172,7 @@ export default class CodeTool implements BlockTool {
153172 public save ( codeWrapper : HTMLDivElement ) : CodeData {
154173 return {
155174 code : codeWrapper . querySelector ( 'textarea' ) ! . value ,
175+ language : codeWrapper . querySelector ( 'select' ) ! . value ,
156176 } ;
157177 }
158178
@@ -168,6 +188,7 @@ export default class CodeTool implements BlockTool {
168188
169189 this . data = {
170190 code : content || '' ,
191+ language : '' ,
171192 } ;
172193 }
173194 }
@@ -190,6 +211,10 @@ export default class CodeTool implements BlockTool {
190211 if ( this . nodes . textarea ) {
191212 this . nodes . textarea . textContent = data . code ;
192213 }
214+
215+ if ( this . nodes . languageSelector ) {
216+ this . nodes . languageSelector . value = data . language ;
217+ }
193218 }
194219
195220 /**
@@ -231,7 +256,9 @@ export default class CodeTool implements BlockTool {
231256 */
232257 public static get sanitize ( ) : SanitizerConfig {
233258 return {
234- code : true , // Allow HTML tags
259+ // Allow HTML tags
260+ code : true ,
261+ language : true
235262 } ;
236263 }
237264
@@ -296,6 +323,7 @@ export default class CodeTool implements BlockTool {
296323 private drawView ( ) : HTMLDivElement {
297324 const wrapper = document . createElement ( 'div' ) ;
298325 const textarea = document . createElement ( 'textarea' ) ;
326+ const languageSelector = this . languageSelector ( ) ;
299327
300328 wrapper . classList . add ( this . CSS . baseClass , this . CSS . wrapper ) ;
301329 textarea . classList . add ( this . CSS . textarea , this . CSS . input ) ;
@@ -308,6 +336,7 @@ export default class CodeTool implements BlockTool {
308336 }
309337
310338 wrapper . appendChild ( textarea ) ;
339+ wrapper . appendChild ( languageSelector ) ;
311340
312341 /**
313342 * Enable keydown handlers
@@ -321,7 +350,41 @@ export default class CodeTool implements BlockTool {
321350 } ) ;
322351
323352 this . nodes . textarea = textarea ;
353+ this . nodes . languageSelector = languageSelector ;
324354
325355 return wrapper ;
326356 }
357+
358+ /**
359+ * Create the programming language selector dropdown
360+ */
361+ private languageSelector ( ) : HTMLDivElement {
362+ const languageSelector = document . createElement ( 'select' ) ;
363+
364+ languageSelector . addEventListener ( 'change' , this . dispatchChangeEvent . bind ( this ) ) ;
365+
366+ languageSelector . classList . add ( 'ce-code__language-selector' ) ;
367+
368+ for ( const key in this . languages ) {
369+ const option = document . createElement ( 'option' ) ;
370+
371+ option . value = key ;
372+ option . text = this . languages [ key ] ;
373+ option . selected = key === this . data . language ;
374+
375+ languageSelector . appendChild ( option ) ;
376+ }
377+
378+ const selectWrapper = document . createElement ( 'div' ) ;
379+ selectWrapper . classList . add ( 'select' ) ;
380+ selectWrapper . classList . add ( 'is-small' ) ;
381+
382+ selectWrapper . appendChild ( languageSelector ) ;
383+
384+ return selectWrapper ;
385+ }
386+
387+ private dispatchChangeEvent ( ) : void {
388+ this . api . blocks . getBlockByIndex ( this . api . blocks . getCurrentBlockIndex ( ) ) ?. dispatchChange ( ) ;
389+ }
327390}
0 commit comments