leilukin-tumbleblog/includes/lib/xenocrat/markdown/inline/EmphStrongTrait.php

138 lines
2.9 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\inline;
/**
* Adds inline emphasizes and strong elements.
*/
trait EmphStrongTrait
{
protected function parseEmphStrongMarkers(): array
{
return array('_', '*');
}
/**
* Parses emphasized and strong elements.
*
* @marker _
* @marker *
*/
2024-09-05 17:51:48 +00:00
protected function parseEmphStrong($markdown): array
2024-06-20 14:10:42 +00:00
{
2024-09-05 17:51:48 +00:00
$marker = $markdown[0];
2024-06-20 14:10:42 +00:00
2024-09-05 17:51:48 +00:00
if (!isset($markdown[1])) {
return [['text', $markdown[0]], 1];
2024-06-20 14:10:42 +00:00
}
2024-09-05 17:51:48 +00:00
if ($marker == $markdown[1]) {
2024-06-20 14:10:42 +00:00
// Strong.
// Avoid excessive regex backtracking if there is no closing marker.
2024-09-05 17:51:48 +00:00
if (strpos($markdown, $marker . $marker, 2) === false) {
return [['text', $markdown[0]], 1];
2024-06-20 14:10:42 +00:00
}
if (
$marker === '*'
&& preg_match(
'/^[*]{2}((?>\\\\[*]|[^*]|[*][^*]*[*])+?)[*]{2}/s',
2024-09-05 17:51:48 +00:00
$markdown,
2024-06-20 14:10:42 +00:00
$matches
)
|| $marker === '_'
&& preg_match(
'/^__((?>\\\\_|[^_]|_[^_]*_)+?)__\b/us',
2024-09-05 17:51:48 +00:00
$markdown,
2024-06-20 14:10:42 +00:00
$matches
)
) {
$content = $matches[1];
// If nothing is contained in a strong,
// do not consider it valid.
if ($content === '') {
2024-09-05 17:51:48 +00:00
return [['text', $markdown[0]], 2];
2024-06-20 14:10:42 +00:00
}
// First and last chars of the strong text
// cannot be whitespace.
if (
strspn($content, " \t\n", 0, 1) === 0
&& strspn($content, " \t\n", -1) === 0
) {
return [
[
'strong',
$this->parseInline($content),
],
strlen($matches[0])
];
}
}
} else {
// Emphasis
// Avoid excessive regex backtracking if there is no closing marker.
2024-09-05 17:51:48 +00:00
if (strpos($markdown, $marker, 1) === false) {
return [['text', $markdown[0]], 1];
2024-06-20 14:10:42 +00:00
}
if (
$marker === '*'
&& preg_match(
'/^[*]((?>\\\\[*]|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*][^*])/s',
2024-09-05 17:51:48 +00:00
$markdown,
2024-06-20 14:10:42 +00:00
$matches
)
|| $marker === '_'
&& preg_match(
'/^_((?>\\\\_|[^_]|__[^_]*__)+?)_(?!_[^_])\b/us',
2024-09-05 17:51:48 +00:00
$markdown,
2024-06-20 14:10:42 +00:00
$matches
)
) {
$content = $matches[1];
// If nothing is contained in an emphasis,
// do not consider it valid.
if ($content === '') {
2024-09-05 17:51:48 +00:00
return [['text', $markdown[0]], 2];
2024-06-20 14:10:42 +00:00
}
// First and last chars of the emphasised text
// cannot be whitespace.
if (
strspn($content, " \t\n", 0, 1) === 0
&& strspn($content, " \t\n", -1) === 0
) {
return [
[
'emph',
$this->parseInline($content),
],
strlen($matches[0])
];
}
}
}
2024-09-05 17:51:48 +00:00
return [['text', $markdown[0]], 1];
2024-06-20 14:10:42 +00:00
}
protected function renderStrong($block): string
{
return '<strong>'
. $this->renderAbsy($block[1])
. '</strong>';
}
protected function renderEmph($block): string
{
return '<em>'
. $this->renderAbsy($block[1])
. '</em>';
}
abstract protected function parseInline($text);
abstract protected function renderAbsy($blocks);
}