127 lines
2.7 KiB
PHP
127 lines
2.7 KiB
PHP
<?php
|
|
/**
|
|
* @copyright Copyright 2023 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 figure/figcaption blocks.
|
|
*/
|
|
trait FigureTrait
|
|
{
|
|
/**
|
|
* Identify a line as the beginning of a figure.
|
|
*/
|
|
protected function identifyFigure($line): bool
|
|
{
|
|
if (
|
|
$line[0] === ' '
|
|
&& strspn($line, ' ') < 4
|
|
) {
|
|
// Trim up to three spaces.
|
|
$line = ltrim($line, ' ');
|
|
}
|
|
return $line[0] === ':';
|
|
}
|
|
|
|
/**
|
|
* Consume lines for a figure.
|
|
*/
|
|
protected function consumeFigure($lines, $current): array
|
|
{
|
|
$content = [];
|
|
$caption = [];
|
|
|
|
// Consume until end of markers...
|
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
|
$line = $lines[$i];
|
|
if (
|
|
isset($line[0])
|
|
&& $line[0] === ' '
|
|
&& strspn($line, ' ') < 4
|
|
) {
|
|
// Trim up to three spaces.
|
|
$line = ltrim($line, ' ');
|
|
}
|
|
if (ltrim($line) !== '') {
|
|
if (str_starts_with($line, ':: ')) {
|
|
$caption[$i] = substr($line, 3);
|
|
continue;
|
|
} elseif (str_starts_with($line, '::')) {
|
|
$caption[$i] = substr($line, 2);
|
|
continue;
|
|
} elseif (str_starts_with($line, ': ')) {
|
|
$content[] = substr($line, 2);
|
|
} elseif (str_starts_with($line, ':')) {
|
|
$content[] = substr($line, 1);
|
|
} else {
|
|
--$i;
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Decide caption placement and remove invalid lines.
|
|
if (isset($caption[$current])) {
|
|
$endcap = false;
|
|
for ($x = $current; $x < $i; $x++) {
|
|
if ($x !== $current && !isset($caption[$x - 1])) {
|
|
unset($caption[$x]);
|
|
}
|
|
}
|
|
} elseif (isset($caption[$i - 1])) {
|
|
$endcap = true;
|
|
for ($x = $i - 1; $x >= $current; $x--) {
|
|
if ($x !== $i - 1 && !isset($caption[$x + 1])) {
|
|
unset($caption[$x]);
|
|
}
|
|
}
|
|
} else {
|
|
$endcap = null;
|
|
$caption = [];
|
|
}
|
|
|
|
$block = [
|
|
'figure',
|
|
'endcap' => $endcap,
|
|
'content' => $this->parseBlocks($content),
|
|
'caption' => $this->parseBlocks(array_values($caption)),
|
|
];
|
|
|
|
return [$block, $i];
|
|
}
|
|
|
|
/**
|
|
* Renders a figure.
|
|
*/
|
|
protected function renderFigure($block): string
|
|
{
|
|
$caption = $block['endcap'] === null ?
|
|
'' :
|
|
"<figcaption>\n"
|
|
. $this->renderAbsy($block['caption'])
|
|
. "</figcaption>\n" ;
|
|
|
|
if ($block['endcap'] === false) {
|
|
$figure = "<figure>\n"
|
|
. $caption . $this->renderAbsy($block['content'])
|
|
. "</figure>\n";
|
|
} else {
|
|
$figure = "<figure>\n"
|
|
. $this->renderAbsy($block['content'])
|
|
. $caption
|
|
. "</figure>\n";
|
|
}
|
|
|
|
return $figure;
|
|
}
|
|
|
|
abstract protected function parseBlocks($lines);
|
|
abstract protected function renderAbsy($absy);
|
|
}
|