Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"require": {
"php": "^8.2",
"ext-dom": "*",
"contao-community-alliance/dc-general": "^2.4.2",
"contao-community-alliance/dc-general": "^2.4.12",
"contao-community-alliance/events-contao-bindings": "^5.0",
"contao-community-alliance/meta-palettes": "^2.0.10",
"contao-community-alliance/translator": "^2.5",
Expand Down
5 changes: 3 additions & 2 deletions src/Attribute/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* This file is part of MetaModels/core.
*
* (c) 2012-2025 The MetaModels team.
* (c) 2012-2026 The MetaModels team.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
Expand All @@ -19,7 +19,7 @@
* @author David Molineus <david.molineus@netzmacht.de>
* @author Sven Baumann <baumann.sv@gmail.com>
* @author Ingolf Steinhardt <info@e-spin.de>
* @copyright 2012-2025 The MetaModels team.
* @copyright 2012-2026 The MetaModels team.
* @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later
* @filesource
*/
Expand Down Expand Up @@ -526,6 +526,7 @@ private function setBaseEval($fieldDefinition, $overrides)
'preserveTags',
'decodeEntities',
'rte',
'highlight',
'rows',
'cols',
'spaceToUnderscore',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

/**
* This file is part of MetaModels/core.
*
* (c) 2012-2026 The MetaModels team.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* This project is provided in good faith and hope to be usable by anyone.
*
* @package MetaModels/core
* @author Ingolf Steinhardt <info@e-spin.de>
* @copyright 2012-2026 The MetaModels team.
* @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later
* @filesource
*/

namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting;

use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface;
use ContaoCommunityAlliance\DcGeneral\Data\PropertyValueBag;
use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyCallbackCondition;
use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyConditionChain;
use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyValueCondition;
use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\PropertyInterface;
use ContaoCommunityAlliance\DcGeneral\Factory\Event\BuildDataDefinitionEvent;

/**
* Replaces the exact-match condition for the "highlight" property's "rte" selector with a prefix match,
* so that "highlight" is visible for all ACE editor template variants (e.g. "ace", "ace_mm").
*/
final class AceHighlightVisibilityListener
{
/**
* Replace the PropertyValueCondition('rte', 'ace') on the "highlight" property with a callback
* condition that matches any rte value starting with 'ace'.
*
* @param BuildDataDefinitionEvent $event The event.
*
* @return void
*/
public function handle(BuildDataDefinitionEvent $event): void
{
if ($event->getContainer()->getName() !== 'tl_metamodel_dcasetting') {
return;
}

if (!$event->getContainer()->hasPalettesDefinition()) {
return;
}

$palettesDefinition = $event->getContainer()->getPalettesDefinition();

foreach ($palettesDefinition->getPalettes() as $palette) {
foreach ($palette->getLegends() as $legend) {
foreach ($legend->getProperties() as $property) {
if ($property->getName() !== 'highlight') {
continue;
}

$this->replaceRteValueCondition($property);
}
}
}
}

/**
* Replace PropertyValueCondition('rte', *) in the property's AND chain with a prefix callback.
*
* @param PropertyInterface $property The palette property.
*
* @return void
*/
private function replaceRteValueCondition(PropertyInterface $property): void
{
$condition = $property->getVisibleCondition();
if (!($condition instanceof PropertyConditionChain)) {
return;
}

foreach ($condition->getConditions() as $subCondition) {
if (
($subCondition instanceof PropertyValueCondition)
&& ($subCondition->getPropertyName() === 'rte')
) {
$condition->removeCondition($subCondition);
$condition->addCondition(
new PropertyCallbackCondition(
static function (?ModelInterface $model, ?PropertyValueBag $input): bool {
if (null !== $input && $input->hasPropertyValue('rte')) {
$value = $input->getPropertyValue('rte');
} elseif (null !== $model) {
$value = $model->getProperty('rte');
} else {
return false;
}

return \is_string($value) && \str_starts_with($value, 'ace');
}
)
);

return;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* This file is part of MetaModels/core.
*
* (c) 2012-2019 The MetaModels team.
* (c) 2012-2026 The MetaModels team.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
Expand All @@ -14,7 +14,7 @@
* @author Christian Schiffler <c.schiffler@cyberspectrum.de>
* @author Ingolf Steinhardt <info@e-spin.de>
* @author Sven Baumann <baumann.sv@gmail.com>
* @copyright 2012-2019 The MetaModels team.
* @copyright 2012-2026 The MetaModels team.
* @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later
* @filesource
*/
Expand Down Expand Up @@ -64,9 +64,14 @@ public function handle(GetPropertyOptionsEvent $event)

$configs = [];
// Delete 'be_' prefix from keys.
// Add tiny templates.
foreach ($this->templateList->getTemplatesForBase('be_tiny') as $key => $value) {
$configs[substr($key, 3)] = $value;
}
// Add ace templates.
foreach ($this->templateList->getTemplatesForBase('be_ace') as $key => $value) {
$configs[substr($key, 3)] = $value;
}

$event->setOptions($configs);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ services:
event: dc-general.factory.build-data-definition
method: handle

metamodels.listener.table.tl_metamodel_dcasetting.ace_highlight_visibility:
class: MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\AceHighlightVisibilityListener
tags:
- name: kernel.event_listener
event: dc-general.factory.build-data-definition
method: handle
priority: -100

metamodels.listener.table.tl_metamodel_dcasetting.rich_text_options:
class: MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\RichTextOptionListener
arguments:
Expand Down Expand Up @@ -154,3 +162,4 @@ services:
- name: kernel.event_listener
event: dc-general.view.contao2backend.manipulate-widget
method: handle

46 changes: 44 additions & 2 deletions src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
// * preserveTags do not encode html tags.
// * decodeEntities do decode HTML entities.
// * rte enable richtext editor on this
// * highlight set type of highlighting for ACE editor
// * rows amount of rows in longtext and tables.
// * cols amount of columns in longtext and tables.
// * trailingSlash allow trailing slash, 2 => do nothing, 1 => add one on save, 0 => strip it on save.
Expand All @@ -253,7 +254,14 @@
// * readonly readonly.
// * be_template widget template for backend.
// * fe_template form template for frontend.
]
],
'rte' => [
'ace' => [
'presentation after rte' => [
'highlight',
]
]
],
],
'fields' => [
'id' => [
Expand Down Expand Up @@ -442,17 +450,51 @@
'eval' => [
'tl_class' => 'w50',
'includeBlankOption' => true,
'submitOnChange' => true,
],
'sql' => "varchar(64) NOT NULL default 'tinyMCE'"
],
'highlight' => [
'label' => 'highlight.label',
'description' => 'highlight.description',
'inputType' => 'select',
'options' => [
'Apache',
'Bash',
'C#',
'C++',
'CSS',
'Diff',
'HTML',
'HTTP',
'Ini',
'JSON',
'Java',
'JavaScript',
'Markdown',
'Nginx',
'Perl',
'PHP',
'PowerShell',
'Python',
'Ruby',
'SCSS',
'SQL',
'Twig',
'YAML',
'XML'
],
'eval' => ['includeBlankOption' => true, 'decodeEntities' => true, 'tl_class' => 'w50'],
'sql' => "varchar(32) COLLATE ascii_bin NOT NULL default ''"
],
'rows' => [
'label' => 'rows.label',
'description' => 'rows.description',
'exclude' => true,
'inputType' => 'text',
'eval' =>
[
'tl_class' => 'w50',
'tl_class' => 'clr w50',
'rgxp' => 'digit'
],
'sql' => "int(10) NOT NULL default '0'"
Expand Down
79 changes: 79 additions & 0 deletions src/CoreBundle/Resources/contao/templates/be_ace_mm.html5
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

namespace Contao;

if ($GLOBALS['TL_CONFIG']['useCE']):

// Use document.write() here in case ACE is loaded in a subpalette (see #1424)
?>
<script>window.ace || document.write('<script src="<?= $this->asset('js/ace.js', 'contao-components/ace') ?>" charset="utf-8">\x3C/script><script src="<?= $this->asset('js/ext-language_tools.js', 'contao-components/ace') ?>" charset="utf-8">\x3C/script><script src="<?= $this->asset('js/ext-whitespace.js', 'contao-components/ace') ?>" charset="utf-8">\x3C/script>')</script>
<script>
window.ace && window.addEvent('domready', function() {
let ta = document.getElementById('<?= $this->selector ?>');
if (!ta) return;

// Create a div to apply the editor to
let div = document.createElement('div');
div.id = '<?= $this->selector ?>_div';
div.className = ta.className;
ta.parentNode.insertBefore(div, ta.nextSibling);

// Hide the textarea
ta.style['display'] = 'none';

// Instantiate the editor
let editor = ace.edit('<?= $this->selector ?>_div', {maxLines: Infinity});
editor.$blockScrolling = Infinity;
editor.setTheme((document.documentElement.dataset.colorScheme === 'dark' ? 'ace/theme/twilight' : 'ace/theme/clouds'));
editor.renderer.setScrollMargin(3, 3, 0, 0);
editor.renderer.scrollBy(0, -6);
editor.container.style.lineHeight = 1.45;
editor.getSession().setValue(ta.value);
editor.getSession().setMode("ace/mode/<?= Backend::getAceType($this->type) ?>");
editor.getSession().setUseSoftTabs(false);
editor.getSession().setUseWrapMode(true);
editor.setAutoScrollEditorIntoView(true);

<?php if ($this->readonly): ?>
editor.setReadOnly(true);
<?php endif; ?>

// Auto-detect the indentation
let ws = ace.require('ace/ext/whitespace');
ws.detectIndentation(editor.getSession());

// Add the fullscreen command
editor.commands.addCommand({
name: 'Fullscreen',
bindKey: 'F11',
exec: function(editor) {
let dom = ace.require('ace/lib/dom');
dom.toggleCssClass(document.body, 'ace-fullsize');
editor.resize();
}
});

editor.setOptions({
enableSnippets: true,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableKeyboardAccessibility: true,
<?php if (!empty($this->rows)): ?>
maxLines: <?= $this->rows ?>,
minLines: 2,
<?php endif; ?>
});

editor.on('focus', function() {
window.dispatchEvent(new Event('store-scroll-offset'));
});

editor.getSession().on('change', function() {
ta.value = editor.getValue();
});

// Disable command conflicts with AltGr (see #5792)
editor.commands.bindKey('Ctrl-alt-a|Ctrl-alt-e|Ctrl-alt-h|Ctrl-alt-l|Ctrl-alt-s', null);
});
</script>
<?php endif; ?>
7 changes: 7 additions & 0 deletions src/CoreBundle/Resources/contao/templates/be_tinyMCE_mm.html5
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php $this->extend('be_tinyMCE'); ?>

<?php $this->block('custom'); ?>
<?php if (!empty($this->rows)): ?>
max_height: <?= $this->rows ?>,
<?php endif; ?>
<?php $this->endblock(); ?>
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,14 @@
<source>Select the rich text configuration that shall be used on this field (if any).</source>
<target>Wählen Sie eine Voreinstellung für den Richtext-Editor aus, die für dieses Feld benutzt werden soll (falls vorhanden).</target>
</trans-unit>
<trans-unit id="highlight.label" resname="highlight.label">
<source>Syntax highlighting mode</source>
<target>Syntax-Hervorhebungsmodus</target>
</trans-unit>
<trans-unit id="highlight.description" resname="highlight.description">
<source>Select the syntax highlighting mode for the ACE editor (e.g. "html", "css", "javascript"). Only relevant when an ACE editor configuration is selected.</source>
<target>Wählen Sie den Syntax-Hervorhebungsmodus für den ACE-Editor (z.B. "html", "css", "javascript"). Nur relevant, wenn eine ACE-Editor-Konfiguration ausgewählt ist.</target>
</trans-unit>
<trans-unit id="rows.label" resname="rows.label">
<source>Rows</source>
<target>Zeilen</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@
<trans-unit id="rte.description" resname="rte.description">
<source>Select the rich text configuration that shall be used on this field (if any).</source>
</trans-unit>
<trans-unit id="highlight.label" resname="highlight.label">
<source>Syntax highlighting mode</source>
</trans-unit>
<trans-unit id="highlight.description" resname="highlight.description">
<source>Select the syntax highlighting mode for the ACE editor (e.g. "html", "css", "javascript"). Only relevant when an ACE editor configuration is selected.</source>
</trans-unit>
<trans-unit id="rows.label" resname="rows.label">
<source>Rows</source>
</trans-unit>
Expand Down