]> git.joonet.de Git - adminer.git/commitdiff
New plugin: Use Monaco Editor for syntax highlighting
authorJakub Vrana <jakub@vrana.cz>
Tue, 1 Apr 2025 14:37:12 +0000 (16:37 +0200)
committerJakub Vrana <jakub@vrana.cz>
Tue, 1 Apr 2025 14:37:12 +0000 (16:37 +0200)
CHANGELOG.md
plugins/monaco.php [new file with mode: 0644]
plugins/prism.php

index c4afd3b55c3c0bffee72c593b5f3c6a9df595234..e6789f3e00a57e0e2bc02f3bc1115da2b88b9af0 100644 (file)
@@ -5,6 +5,7 @@
 - CSS: Hide menu on mobile
 - CSS: Invert icons in dark mode
 - Plugins: Allow changing CSP by more plugins
+- New plugin: Use Monaco Editor for syntax highlighting
 - New plugin: Use Prism for syntax highlighting
 
 ## Adminer 5.1.0 (released 2025-03-24)
diff --git a/plugins/monaco.php b/plugins/monaco.php
new file mode 100644 (file)
index 0000000..9a72f74
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+
+/** Use VS Code's Monaco Editor for syntax highlighting and SQL <textarea>
+* @link https://microsoft.github.io/monaco-editor/
+* @link https://www.adminer.org/plugins/#use
+* @author Jakub Vrana, https://www.vrana.cz/
+* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
+* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
+*/
+class AdminerMonaco {
+       private $root;
+
+       function __construct($root = "https://cdn.jsdelivr.net/npm/monaco-editor@0.52/min/vs") {
+               $this->root = $root;
+       }
+
+       function syntaxHighlighting($tableStatuses) {
+               echo Adminer\script_src("$this->root/loader.js");
+               ?>
+<script <?php echo Adminer\nonce(); ?>>
+require.config({ paths: { vs: '<?php echo $this->root; ?>' } });
+require(['vs/editor/editor.main'], function (monaco) {
+       adminerHighlighter = els => els.forEach(el => {
+               const lang = getMonacoLang(el);
+               if (lang) {
+                       monaco.editor.colorize(el.textContent, lang).then(html => el.innerHTML = html);
+               }
+       });
+       adminerHighlighter(qsa('code'));
+
+       for (const el of qsa('textarea')) {
+               const lang = getMonacoLang(el);
+               if (lang) {
+                       const container = document.createElement('div');
+                       container.style.border = '1px inset #ccc';
+                       container.style.width = el.clientWidth + 'px';
+                       container.style.height = el.clientHeight + 'px';
+                       el.before(container);
+                       el.style.display = 'none';
+                       var editor = monaco.editor.create(container, {
+                               value: el.value,
+                               lineNumbers: 'off',
+                               glyphMargin: false,
+                               folding: false,
+                               lineDecorationsWidth: 1,
+                               minimap: {enabled: false},
+                               language: lang
+                       });
+                       editor.onDidChangeModelContent(() => el.value = editor.getValue());
+                       el.onchange = () => editor.setValue(el.value);
+                       monaco.editor.addKeybindingRules([
+                               {keybinding: monaco.KeyCode.Tab, command: null}
+                               //! Ctrl+Enter
+                       ]);
+               }
+       }
+});
+
+function getMonacoLang(el) {
+       return (
+               /jush-js/.test(el.className) ? 'javascript' : (
+               /jush-sql/.test(el.className) ? 'mysql' : (
+               /jush-pgsql/.test(el.className) ? 'pgsql' : (
+               /jush-(sqlite|mssql|oracle|clickhouse|firebird)/.test(el.className) ? 'sql' : (
+               ''
+       )))));
+}
+</script>
+<?php
+               return true;
+       }
+}
index acd3583ca32691daab0db37532ebe23390cf0e90..b98c499134c5db9336bc1db57ba04932eba7b706 100644 (file)
@@ -34,7 +34,7 @@ import '<?php echo $this->editorRoot; ?>/prism/languages/sql.js';
 adminerHighlighter = els => els.forEach(el => {
        const mode = (
                /jush-js/.test(el.className) ? 'json' : (
-               /jush-\w*sql/.test(el.className) ? 'sql' : (
+               /jush-(\w*sql|oracle|clickhouse|firebird)/.test(el.className) ? 'sql' : (
                ''
        )));
        if (mode) {