Skip to content

Commit

Permalink
CodeMirror um optionale eigene Optionen erweitert, Anpassung für den …
Browse files Browse the repository at this point in the history
…Darkmode (#5164)

- zusätzliche globale Optionen über die Addon-Einstellungen möglich
- zusätzliche/eigene Optionen können einer Textarea im JSON-Format übergeben werden z.B. data-codemirror-options='{"indentWithTabs": true, "lineNumbers": false}'
- Addon-Einstellungen erweitert und überarbeitet
- Unterstützung für den Darkmode, `dracula` als Standard
  • Loading branch information
aeberhard committed Jul 16, 2022
1 parent f4d1a37 commit ea96378
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 35 deletions.
Binary file modified .github/tests-visual/system_customizer--dark.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .github/tests-visual/system_customizer.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 1 addition & 16 deletions .tools/psalm/baseline.xml
Expand Up @@ -108,30 +108,15 @@
</MixedOperand>
</file>
<file src="redaxo/src/addons/be_style/plugins/customizer/boot.php">
<MixedOperand occurrences="4">
<MixedOperand occurrences="2">
<code>$_SESSION['codemirror_reload']</code>
<code>$_SESSION['codemirror_reload']</code>
<code>$config['codemirror-selectors']</code>
<code>$config['codemirror_theme']</code>
</MixedOperand>
<PossiblyNullOperand occurrences="2">
<code>rex_file::get($filename)</code>
<code>rex_file::get($filename)</code>
</PossiblyNullOperand>
</file>
<file src="redaxo/src/addons/be_style/plugins/customizer/pages/system.customizer.php">
<MixedArgument occurrences="5">
<code>$config['codemirror-selectors']</code>
<code>$config['labelcolor']</code>
<code>$config['labelcolor']</code>
<code>$labelcolor</code>
<code>$newConfig['codemirror_theme']</code>
</MixedArgument>
<MixedAssignment occurrences="2">
<code>$labelcolor</code>
<code>$tempConfig['codemirror-selectors']</code>
</MixedAssignment>
</file>
<file src="redaxo/src/addons/be_style/plugins/redaxo/boot.php">
<MixedArgument occurrences="1">
<code>$subject</code>
Expand Down
71 changes: 62 additions & 9 deletions redaxo/src/addons/be_style/plugins/customizer/assets/js/main.js
@@ -1,7 +1,7 @@
$(document).on('rex:ready', function (event, container) {
if (container.find(rex.customizer_codemirror_selectors).length > 0) {
// Zusätzliche Themes?
themes = '';
themes = rex.customizer_codemirror_defaulttheme + ',' + rex.customizer_codemirror_defaultdarktheme + ',';
container.find(rex.customizer_codemirror_selectors).each(function () {
$.each(this.attributes, function () {
if (this.specified) {
Expand Down Expand Up @@ -48,7 +48,7 @@ $(document).on('rex:ready', function (event, container) {
}
});

var Customizer = function () {};
var Customizer = function () { };

Customizer.init = function (container) {
var cm_editor = {};
Expand All @@ -67,8 +67,38 @@ Customizer.init = function (container) {
var mode = "application/x-httpd-php";
var theme = rex.customizer_codemirror_defaulttheme;

let systemDarkModeDetector = null;
if (window.matchMedia) {
systemDarkModeDetector = window.matchMedia('(prefers-color-scheme: dark)');
// Systemseitige Einstellung abfragen
if (systemDarkModeDetector.matches) {
theme = rex.customizer_codemirror_defaultdarktheme;
}
// Einstellung aus Profil
if (document.body.classList.contains('rex-theme-light')) {
theme = rex.customizer_codemirror_defaulttheme;
} else if (document.body.classList.contains('rex-theme-dark')) {
theme = rex.customizer_codemirror_defaultdarktheme;
}
// Systemseitiges Umschalten Dark/Light erkennen
systemDarkModeDetector.addEventListener('change', function (e) {
if (systemDarkModeDetector.matches) {
theme = rex.customizer_codemirror_defaultdarktheme;
} else {
theme = rex.customizer_codemirror_defaulttheme;
}
if (document.body.classList.contains('rex-theme-light')) {
theme = rex.customizer_codemirror_defaulttheme;
} else if (document.body.classList.contains('rex-theme-dark')) {
theme = rex.customizer_codemirror_defaultdarktheme;
}
cm_editor[cm].setOption('theme', theme);
});
}

var new_mode = t.attr("data-codemirror-mode");
var new_theme = t.attr("data-codemirror-theme");
var new_options = t.attr("data-codemirror-options");

if (typeof new_mode !== "undefined") {
mode = new_mode;
Expand All @@ -77,9 +107,8 @@ Customizer.init = function (container) {
if (typeof new_theme !== "undefined") {
theme = new_theme;
}

if (typeof CodeMirror === "function") {
cm_editor[cm] = CodeMirror.fromTextArea(document.getElementById(id), {
cm_options = {
mode: mode,
theme: theme,
autoRefresh: true,
Expand All @@ -94,6 +123,7 @@ Customizer.init = function (container) {
tabSize: 4,
indentUnit: 4,
indentWithTabs: false,
smartIndent: true,
enterMode: "keep",
tabMode: "shift",
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
Expand All @@ -109,13 +139,36 @@ Customizer.init = function (container) {
if (cm.doc.somethingSelected()) {
return CodeMirror.Pass;
}
var spacesPerTab = cm.getOption("indentUnit");
var spacesToInsert = spacesPerTab - (cm.doc.getCursor("start").ch % spacesPerTab);
var spaces = Array(spacesToInsert + 1).join(" ");
cm.replaceSelection(spaces, "end", "+input");
if (!cm.getOption("indentWithTabs")) {
var spacesPerTab = cm.getOption("indentUnit");
var spacesToInsert = spacesPerTab - (cm.doc.getCursor("start").ch % spacesPerTab);
var spaces = Array(spacesToInsert + 1).join(" ");
cm.replaceSelection(spaces, "end", "+input");
} else {
cm.replaceSelection('\t', "end", "+input");
}
}
}
});
}
try {
if (rex.customizer_codemirror_options) {
additional_options = jQuery.parseJSON(rex.customizer_codemirror_options);
$.extend(cm_options, additional_options);
}
} catch (e) {
console.log('Error in global Codemirror-Options! \nOptions: ' + rex.customizer_codemirror_options);
console.log(e);
}
try {
if (new_options) {
additional_options = jQuery.parseJSON(new_options);
$.extend(cm_options, additional_options);
}
} catch (e) {
console.log('Error in Textarea-Codemirror-Options! \nOptions: ' + new_options);
console.log(e);
}
cm_editor[cm] = CodeMirror.fromTextArea(document.getElementById(id), cm_options);
}
});

Expand Down
Binary file not shown.
7 changes: 6 additions & 1 deletion redaxo/src/addons/be_style/plugins/customizer/boot.php
Expand Up @@ -9,6 +9,7 @@

// Plugin-Config
$plugin = rex_plugin::get('be_style', 'customizer');
/** @var array{codemirror_theme: string, codemirror_darktheme: string, codemirror-selectors: string, codemirror-options: string, codemirror: int, codemirror-langs: int, codemirror-tools: int, labelcolor: string, showlink: int, codemirror-autoresize?: bool} $config */
$config = $plugin->getConfig();

/* Output CodeMirror-CSS */
Expand Down Expand Up @@ -119,16 +120,20 @@
if ($config['codemirror']) {
// JsProperty CodeMirror-Theme
rex_view::setJsProperty('customizer_codemirror_defaulttheme', $config['codemirror_theme']);
rex_view::setJsProperty('customizer_codemirror_defaultdarktheme', $config['codemirror_darktheme']);
// JsProperty CodeMirror-Selectors
$selectors = 'textarea.rex-code, textarea.rex-js-code, textarea.codemirror';
if (isset($config['codemirror-selectors']) && '' != $config['codemirror-selectors']) {
$selectors = $selectors . ', ' . $config['codemirror-selectors'];
}
rex_view::setJsProperty('customizer_codemirror_selectors', $selectors);
// JsProperty CodeMirror-Autoresize
if (isset($config['codemirror-autoresize'])) {
rex_view::setJsProperty('customizer_codemirror_autoresize', $config['codemirror-autoresize']);
}

// JsProperty Codemirror-Options
rex_view::setJsProperty('customizer_codemirror_options', str_replace(["\n", "\r"], '', trim($config['codemirror-options'])));
// JsProperty JS/CSS-Buster
$mtimejs = filemtime($plugin->getAssetsUrl('vendor/codemirror/codemirror.min.js'));
$mtimecss = filemtime($plugin->getAssetsUrl('vendor/codemirror/codemirror.min.css'));
if (isset($_SESSION['codemirror_reload'])) {
Expand Down
7 changes: 5 additions & 2 deletions redaxo/src/addons/be_style/plugins/customizer/lang/de_de.lang
Expand Up @@ -4,16 +4,19 @@ customizer_features = CodeMirror
customizer_codemirror = CodeMirror
customizer_codemirror_check = CodeMirror aktivieren
customizer_codemirror_selectors = Zusätzliche jQuery-Selektoren für CodeMirror
customizer_codemirror_selectors_info = Kommaseparierte Liste von jQuery-Selektoren für die der CodeMirror angewendet wird.<br>Default sind <code>textarea.rex-js-code</code> und <code>textarea.codemirror</code>.
customizer_codemirror_selectors_info = Kommaseparierte Liste von jQuery-Selektoren für die der CodeMirror angewendet wird.<br>Default sind <code>textarea.rex-code</code>, <code>textarea.rex-js-code</code> und <code>textarea.codemirror</code>.
customizer_codemirror_theme = CodeMirror Theme
customizer_codemirror_darktheme = CodeMirror Theme Darkmode
customizer_codemirror_langs = Zusätzliche Highlighter
customizer_codemirror_langs_text = (markdown, textile, gfm, yaml, sql ...)
customizer_codemirror_tools = Zusätzliche Features
customizer_codemirror_tools_text = (Code-Folding, Bracket-Matching, Tag-Matching, Close-Brackets, Search)
customizer_codemirror_autoresize = AutoResize
customizer_codemirror_autoresize_text = (CodeMirror passt sich in der Höhe an den Inhalt an)
customizer_codemirror_options = Zusätzliche Optionen für CodeMirror
customizer_codemirror_options_info = Achtung! Die Optionen müssen im korrekten JSON-Format angegeben werden! Fehler werden in der JavaScript-Console ausgegeben.<br>Beispiel: <code>{"indentWithTabs": true, "lineNumbers": true}</code>

customizer_codemirror_info = Sobald CodeMirror aktiviert ist, wird dieser bei Templates, Modulen, Aktionen und bei Cronjobs automatisch verwendet. Sofern man selbst den CodeMirror verwenden möchte, bitte folgende Form verwenden:<br><br><code><textarea class="codemirror" data-codemirror-theme="themename" data-codemirror-mode="php/htmlmixed"></textarea></code><br><br>Die Parameter <i>data-codemirror-theme</i> und <i>data-codemirror-mode</i> sind optional.<br><br>Mit den Tasten F11 und ESC kann der Fullscreen-Modus aufgerufen werden.
customizer_codemirror_info = Sobald CodeMirror aktiviert ist, wird dieser bei Templates, Modulen, Aktionen und bei Cronjobs automatisch verwendet.<br><br>Sofern man selbst den CodeMirror verwenden möchte, bitte folgende Form verwenden:<br><br><code><textarea class="codemirror" data-codemirror-theme="themename" data-codemirror-mode="php" data-codemirror-options='{"indentWithTabs": true, "lineNumbers": false}'></textarea></code><br><br>Die Parameter <code>data-codemirror-theme</code>, <code>data-codemirror-mode</code> und <code>data-codemirror-options</code> sind optional.<br><br>Mit den Tasten F11 und ESC kann der Fullscreen-Modus aufgerufen werden.

customizer_labeling = Ergänzungen
customizer_labelcolor = Erkennungsfarbe
Expand Down
3 changes: 2 additions & 1 deletion redaxo/src/addons/be_style/plugins/customizer/package.yml
Expand Up @@ -20,9 +20,10 @@ requires:
default_config:
labelcolor: '#3bb594'
codemirror_theme: 'eclipse'
codemirror_darktheme: 'dracula'
codemirror-selectors: ''
codemirror-options: ''
codemirror: 1
codemirror-langs: 0
codemirror-tools: 0
showlink: 1

Expand Up @@ -16,7 +16,7 @@

$tempConfig['codemirror-selectors'] = '';
if (isset($newConfig['codemirror-selectors'])) {
$tempConfig['codemirror-selectors'] = $newConfig['codemirror-selectors'];
$tempConfig['codemirror-selectors'] = (string) $newConfig['codemirror-selectors'];
}

$tempConfig['codemirror-langs'] = 0;
Expand All @@ -34,9 +34,16 @@
$tempConfig['codemirror-autoresize'] = 1;
}

$tempConfig['codemirror_theme'] = htmlspecialchars($newConfig['codemirror_theme']);
$tempConfig['codemirror-options'] = '';
if (isset($newConfig['codemirror-options'])) {
$tempConfig['codemirror-options'] = (string) $newConfig['codemirror-options'];
}

$tempConfig['codemirror_theme'] = htmlspecialchars((string) $newConfig['codemirror_theme']);

$tempConfig['codemirror_darktheme'] = htmlspecialchars((string) $newConfig['codemirror_darktheme']);

$labelcolor = $newConfig['labelcolor'];
$labelcolor = (string) $newConfig['labelcolor'];
if ('' == $labelcolor) {
$tempConfig['labelcolor'] = '';
} else {
Expand All @@ -49,7 +56,6 @@
}

// save config

if (rex_plugin::get('be_style', 'customizer')->setConfig($tempConfig)) {
$success = rex_i18n::msg('customizer_config_updated');
} else {
Expand All @@ -61,7 +67,12 @@

// load config

/** @var array{codemirror_theme: string, codemirror_darktheme: string, codemirror-selectors: string, codemirror-options: string, codemirror: int, codemirror-langs: int, codemirror-tools: int, labelcolor: string, showlink: int, codemirror-autoresize?: bool} $config */
$config = rex_plugin::get('be_style', 'customizer')->getConfig();

if (!isset($config['codemirror_darktheme'])) {
$config['codemirror_darktheme'] = $config['codemirror_theme'];
}
if (!isset($config['codemirror-langs'])) {
$config['codemirror-langs'] = 0;
}
Expand All @@ -74,6 +85,9 @@
if (!isset($config['codemirror-selectors'])) {
$config['codemirror-selectors'] = '';
}
if (!isset($config['codemirror-options'])) {
$config['codemirror-options'] = '';
}

// build elements

Expand All @@ -92,8 +106,18 @@
$tselect->setAttribute('class', 'form-control selectpicker');
$tselect->setAttribute('data-live-search', 'true');
$tselect->setSelected($config['codemirror_theme']);

$tselectdark = new rex_select();
$tselectdark->setId('customizer-codemirror_darktheme');
$tselectdark->setName('settings[codemirror_darktheme]');
$tselectdark->setSize(1);
$tselectdark->setAttribute('class', 'form-control selectpicker');
$tselectdark->setAttribute('data-live-search', 'true');
$tselectdark->setSelected($config['codemirror_darktheme']);

foreach ($themes as $theme) {
$tselect->addOption($theme, $theme);
$tselectdark->addOption($theme, $theme);
}

// messages
Expand Down Expand Up @@ -136,8 +160,8 @@
$formElements[] = $n;

$n = [];
$n['label'] = '';
$n['field'] = '<p>' . rex_i18n::msg('customizer_codemirror_info') . '</p>';
$n['label'] = '<label for="customizer-codemirror_darktheme">' . rex_i18n::msg('customizer_codemirror_darktheme') . '</label>';
$n['field'] = $tselectdark->get();
$formElements[] = $n;

$n = [];
Expand All @@ -158,6 +182,17 @@
$n['field'] .= ' '.rex_i18n::msg('customizer_codemirror_autoresize_text');
$formElements[] = $n;

$n = [];
$n['label'] = '<label for="customizer-codemirror-options">' . rex_i18n::msg('customizer_codemirror_options') . '</label>';
$n['field'] = '<textarea rows="4" class="form-control" id="customizer-codemirror-options" name="settings[codemirror-options]">' . htmlspecialchars($config['codemirror-options']) . '</textarea>';
$n['note'] = rex_i18n::msg('customizer_codemirror_options_info');
$formElements[] = $n;

$n = [];
$n['label'] = '';
$n['field'] = '<p>' . rex_i18n::msg('customizer_codemirror_info') . '</p>';
$formElements[] = $n;

$fragment = new rex_fragment();
$fragment->setVar('elements', $formElements, false);
$content .= $fragment->parse('core/form/form.php');
Expand Down

0 comments on commit ea96378

Please sign in to comment.