Als erste Funktionalität, die über das absolute Mindestmass hinausgeht, erhält diese Plattform ein code highlighting-Feature. In zwei Punkten zusammengefasst war dazu notwendig:
Der neue Codeblock kommt selbstverständlich schon in dieser Dokumentation zum Zug.
Hinzufügen und Einbinden von Drittpackages via Webpack
Für das highlighting auf dieser Webseite wird das package highlight.js verwendet. Es besticht durch seine geringe Grösse und die Tatsache, dass es keine weiteren dependencies hat. Ausserdem unterstützt es eine grosse Anzahl an Sprachen und wir mit einer Anzahl themes geliefert.
Der erste Schritt ist es, das package zu installieren - dies geschieht ganz einfach über den Befehl npm install highlight.js im Projektordner.
webpack erlaubt es, packages zu bündeln - also ihre zahlreichen Inhalte, dependencies und Ressourcen in einzelne, einfach zu verwendende und verwaltende statische assets zu verwandeln. webpack wird in einer besonderen .js-Datei im project root konfiguriert (webpack.config.js), deren config array um einen Eintrag für highlight.js ergänzt werden musste:
const config = [{
[...]
}, {
name: 'highlight.js',
entry: {
main: Path.resolve(__dirname, 'app/client/src/highlight.js/bundle.js')
},
output: {
path: Path.resolve(__dirname, 'app/client/dist/highlight.js'),
filename: 'bundle.js',
},
devtool: (ENV !== 'production') ? 'source-map' : '',
resolve: resolves(ENV, PATHS),
module: modules(ENV, PATHS),
plugins: plugins(ENV, PATHS),
}
];
Hier wird definiert, dass es in /app/client/src einen weiteren Ordner namens highlight.js gibt, in dem weitere Konfigurationen stattfinden. Diesen lege ich an. webpack erwartet darin weitere Dateien:
bundle.js sieht so aus:
import hljs from 'highlight.js';
import './style.scss';
hljs.highlightAll();
style.scss enthält nur diese eine Zeile. Sie verweist auf eine .scss-Datei, die sich im Installordner des Moduls befindet:
@import '~highlight.js/scss/atom-one-light';
Mit npm run watch wird webpack dann angewiesen, die entsprechenden Dateien in /app/client/dist zu generieren. Wichtig: Bearbeitet wird stets nur /app/client/src, /app/client/dist enthält nur die automatisch Dateien.
highlight.js ist nun konfiguriert und eingebunden. Es kann jetzt in einem Elemental-Block aufgerufen und verwendet werden.
Coden eines custom Elemental-Blocks in Silverstripe
Die grundlegenden Schritte für die Erstellung eines eigenen Elemental-Blocks sind die folgenden:
Die neue Klasse namens CodeElement ist ziemlich einfach strukturiert. Sie ergänzt BaseElement nur um folgende Punkte:
/app/src/Elements/CodeElement.php sieht dann so aus:
<?php
namespace Lerndok\Elements;
class CodeElement extends BaseElement
{
[...]
private static $db = [
'Content' => 'Text',
'Language' => 'Varchar(255)'
];
public function getCMSFields()
{
$fields = parent::getCMSFields();
$fields->push(new DropdownField('Language', 'Language', array(
'language-auto' => 'Auto',
'language-plaintext' => 'plain text',
'language-html' => 'HTML',
'language-bash' => 'bash',
'language-css' => 'CSS',
'language-php' => 'PHP',
'language-javascript' => 'JS',
'language-c' => 'C',
)));
$fields->push(new TextareaField('Content'));
return $fields;
}
[...]
}
Nun fehlt nur noch das entsprechende template. Hier muss folgendes geschehen:
Das Endergebnis in /app/templates/Lerndok/Elements/CodeElement.ss:
<% require themedJavascript('client/dist/highlight.js/bundle.js') %>
<% require themedCSS('client/dist/highlight.js/bundle.css') %>
<div class="content-element__content<% if $Style %> $StyleVariant<% end_if %>">
<% if $ShowTitle %>
<h2 class="content-element__title">$Title</h2>
<% end_if %>
<div class="rounded-3 p-2">
<% if $Language != "language-auto" %>
<pre>
<code class=$Language>
$Content
</code>
</pre>
<% else %>
<pre>
<code>
$Content
</code>
</pre>
<% end_if %>
</div>
</div>