Skip to content

Commit 16277ba

Browse files
committed
Add language selector.
1 parent e34a438 commit 16277ba

2 files changed

Lines changed: 73 additions & 3 deletions

File tree

src/index.css

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@
55
line-height: 1.6em;
66
font-size: 12px;
77
background: #f8f7fa;
8-
border: 1px solid #f1f1f4;
98
box-shadow: none;
109
white-space: pre;
1110
word-wrap: normal;
1211
overflow-x: auto;
1312
resize: vertical;
1413
}
14+
15+
.ce-code select, .ce-code .select {
16+
width: 100%;
17+
}
18+
19+
.ce-code .select {
20+
margin-top: 0.1em;
21+
}

src/index.ts

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)