Rewrite for Kirby

This commit is contained in:
Marcel Kapfer 2024-03-17 22:34:51 +01:00
parent 07201d05de
commit f854d60108
Signed by: mmk2410
GPG key ID: CADE6F0C09F21B09
116 changed files with 4156 additions and 8875 deletions

View file

@ -0,0 +1,23 @@
<?php
if (!function_exists('is_base64_string_s')) {
// https://stackoverflow.com/a/51877882
function is_base64_string_s(string $str, $enc = ['UTF-8', 'ASCII'])
{
return !(($b = base64_decode($str, true)) === false) && in_array(mb_detect_encoding($b), $enc);
}
}
return [
'fromBase64' => function ($field) {
if ($field->isNotEmpty()) {
$value = trim((string)$field->value());
if (is_base64_string_s($value)) {
$field->value = base64_decode($value);
}
}
return $field;
},
];

View file

@ -0,0 +1,86 @@
<?php
use Highlight\Highlighter;
use JohannSchopplich\HTML5DOMDocument;
use Kirby\Cms\App;
return [
'kirbytext:after' => function (string|null $text) {
$kirby = App::instance();
// Parse KirbyText input as HTML document
$dom = new HTML5DOMDocument();
$dom->loadHTML($text);
// Retrieve all `pre` elements inside newly created HTML document
$preNodes = $dom->getElementsByTagName('pre');
// Bail if no `pre` elements have been found
if ($preNodes->length === 0) {
return $text;
}
// Loop through all `pre` elements
foreach ($preNodes as $preNode) {
// Ensure nothing but the `code` element exists
if ($preNode->childNodes->length !== 1) {
continue;
}
// Select direct `code` child element of `pre` block
$codeNode = $preNode->firstChild;
// Get language code if present
$language = $codeNode->getAttribute('class');
if (str_starts_with($language, 'language-')) {
$language = preg_replace('/^language-/', '', $language);
}
// Bail highlighting if language isn't set and auto detection is disabled
if (empty($language) && !$kirby->option('johannschopplich.highlighter.autodetect', false)) {
continue;
}
// Add `hljs` class to `pre` block
$preNode->setAttribute('class', $kirby->option('johannschopplich.highlighter.class', 'hljs'));
// Get raw code data to highlight
$code = $codeNode->nodeValue;
// Remove code element afterwards
$preNode->removeChild($codeNode);
// Initiate `Highlighter` and use pre-defined language code, fall
// back to language auto detection if enabled
$highlighter = new Highlighter();
// Highlight code
if (!empty($language)) {
$highlightedCode = $highlighter->highlight($language, $code);
} elseif ($kirby->option('johannschopplich.highlighter.autodetect', false)) {
$languageSubset = $kirby->option('johannschopplich.highlighter.languages', []);
if (!empty($languageSubset)) {
$highlighter->setAutodetectLanguages($languageSubset);
}
$highlightedCode = $highlighter->highlightAuto($code);
}
// Line numbering
if ($kirby->option('johannschopplich.highlighter.line-numbering', false)) {
$lines = preg_split('/\R/', $highlightedCode->value);
$lineClass = $kirby->option('johannschopplich.highlighter.line-numbering-class', 'hljs-code-line');
$highlightedCode->value = '<span class="' . $lineClass . '">' . implode("</span>\n<span class=\"$lineClass\">", $lines) . '</span>';
}
// Append highlighted wrapped in `code` block to parent `pre`
$codeNode = $dom->createDocumentFragment();
$codeNode->appendXML('<code data-language="' . $language . '">' . $highlightedCode->value . '</code>');
$preNode->appendChild($codeNode);
}
// Save all changes
$text = $dom->saveHTML(null, true);
return $text;
}
];

View file

@ -0,0 +1,27 @@
<?php
use Kirby\Cms\App;
return [
'code' => [
'attr' => [
'lang',
'language',
],
// TODO: Type as `\Kirby\Text\KirbyTag` for Kirby 4
'html' => function ($tag) {
$kirby = App::instance();
$code = $tag->value;
$language = $tag->lang ?? $tag->language;
$block = new \Kirby\Cms\Block([
'type' => 'code',
'content' => [
'language' => $language ?? 'plaintext',
'code' => is_base64_string_s($code) ? base64_decode($code) : $code,
]
]);
return $kirby->snippet('blocks/code', ['block' => $block], true);
}
]
];