leilukin-tumbleblog/includes/lib/xenocrat/markdown/block/CodeTrait.php

104 lines
2.3 KiB
PHP
Raw Normal View History

2024-06-20 14:10:42 +00:00
<?php
/**
* @copyright Copyright 2014 Carsten Brandt, 2024 Daniel Pimley
* @license https://github.com/xenocrat/chyrp-markdown/blob/master/LICENSE
* @link https://github.com/xenocrat/chyrp-markdown#readme
*/
namespace xenocrat\markdown\block;
/**
* Adds indented code blocks.
*/
trait CodeTrait
{
/**
* Identify a line as the beginning of a code block.
*/
protected function identifyCode($line): bool
{
// Indentation >= 4 or one tab is code.
return $line[0] === "\t" || strncmp($line, ' ', 4) === 0;
}
/**
* Consume lines for a code block element.
*/
protected function consumeCode($lines, $current): array
{
$content = [];
// Consume until end of markers...
for ($i = $current, $count = count($lines); $i < $count; $i++) {
$line = $lines[$i];
if (isset($line[0]) && $line[0] === "\t") {
// A line belongs to this code block if indented by a tab.
$line = substr($line, 1);
$content[] = $line;
} elseif (str_starts_with($line, ' ')) {
// A line belongs to this code block if indented by 4 spaces.
$line = substr($line, 4);
$content[] = $line;
} elseif (
($line === '' || ltrim($line) === '')
&& isset($lines[$i + 1])
) {
// ...Or if blank and the next is also blank
// or the next is indented by 4 spaces or a tab.
$next = $lines[$i + 1];
if (
$next === ''
|| ltrim($next) === ''
|| $next[0] === "\t"
|| str_starts_with($next, ' ')
) {
$line = '';
$content[] = $line;
} else {
break;
}
} else {
break;
}
}
// Remove leading blank lines.
while (
count($content) > 1
&& ltrim(reset($content)) === ''
) {
array_shift($content);
}
// Remove trailing blank lines.
while (
count($content) > 1
&& ltrim(end($content)) === ''
) {
array_pop($content);
}
$block = [
'code',
'content' => implode("\n", $content),
];
return [$block, --$i];
}
/**
* Renders a code block.
*/
protected function renderCode($block): string
{
$class = isset($block['language']) ?
' class="language-' . $block['language'] . '"' : '';
return "<pre><code$class>"
. $this->escapeHtmlEntities(
$block['content'],
ENT_COMPAT | ENT_SUBSTITUTE
)
. ($block['content'] === '' ? '' : "\n" )
. "</code></pre>\n";
}
abstract protected function escapeHtmlEntities($text, $flags = 0);
}