refactor: return bbcode parser array from function

Allows calling functions inside of it. Part of #4860.
This commit is contained in:
Roardom
2025-10-23 19:12:58 +00:00
parent 8f49779758
commit 9396c96052
+247 -244
View File
@@ -21,7 +21,7 @@ use App\Models\WhitelistedImageUrl;
class Bbcode
{
/**
* @var array<
* @return array<
* string,
* array{
* openBbcode: string,
@@ -32,246 +32,249 @@ class Bbcode
* }
* > $parsers.
*/
private array $parsers = [
'h1' => [
'openBbcode' => '/^\[h1\]/i',
'closeBbcode' => '[/h1]',
'openHtml' => '<h1>',
'closeHtml' => '</h1>',
'block' => true,
],
'h2' => [
'openBbcode' => '/^\[h2\]/i',
'closeBbcode' => '[/h2]',
'openHtml' => '<h2>',
'closeHtml' => '</h2>',
'block' => true,
],
'h3' => [
'openBbcode' => '/^\[h3\]/i',
'closeBbcode' => '[/h3]',
'openHtml' => '<h3>',
'closeHtml' => '</h3>',
'block' => true,
],
'h4' => [
'openBbcode' => '/^\[h4\]/i',
'closeBbcode' => '[/h4]',
'openHtml' => '<h4>',
'closeHtml' => '</h4>',
'block' => true,
],
'h5' => [
'openBbcode' => '/^\[h5\]/i',
'closeBbcode' => '[/h5]',
'openHtml' => '<h5>',
'closeHtml' => '</h5>',
'block' => true,
],
'h6' => [
'openBbcode' => '/^\[h6\]/i',
'closeBbcode' => '[/h6]',
'openHtml' => '<h6>',
'closeHtml' => '</h6>',
'block' => true,
],
'bold' => [
'openBbcode' => '/^\[b\]/i',
'closeBbcode' => '[/b]',
'openHtml' => '<b>',
'closeHtml' => '</b>',
'block' => false,
],
'italic' => [
'openBbcode' => '/^\[i\]/i',
'closeBbcode' => '[/i]',
'openHtml' => '<i>',
'closeHtml' => '</i>',
'block' => false,
],
'underline' => [
'openBbcode' => '/^\[u\]/i',
'closeBbcode' => '[/u]',
'openHtml' => '<u>',
'closeHtml' => '</u>',
'block' => false,
],
'linethrough' => [
'openBbcode' => '/^\[s\]/i',
'closeBbcode' => '[/s]',
'openHtml' => '<s>',
'closeHtml' => '</s>',
'block' => false,
],
'size' => [
'openBbcode' => '/^\[size=(\d+)\]/i',
'closeBbcode' => '[/size]',
'openHtml' => '<span style="font-size: clamp(10px, $1px, 100px);">',
'closeHtml' => '</span>',
'block' => false,
],
'font' => [
'openBbcode' => '/^\[font=([a-z0-9 ]+)\]/i',
'closeBbcode' => '[/font]',
'openHtml' => '<span style="font-family: $1;">',
'closeHtml' => '</span>',
'block' => false,
],
'color' => [
'openBbcode' => '/^\[color=(\#[a-f0-9]{3,4}|\#[a-f0-9]{6}|\#[a-f0-9]{8}|[a-z]+)\]/i',
'closeBbcode' => '[/color]',
'openHtml' => '<span style="color: $1;">',
'closeHtml' => '</span>',
'block' => false,
],
'center' => [
'openBbcode' => '/^\[center\]/i',
'closeBbcode' => '[/center]',
'openHtml' => '<div class="bbcode-rendered__center" style="text-align: center;">',
'closeHtml' => '</div>',
'block' => true,
],
'left' => [
'openBbcode' => '/^\[left\]/i',
'closeBbcode' => '[/left]',
'openHtml' => '<div class="bbcode-rendered__left" style="text-align: left;">',
'closeHtml' => '</div>',
'block' => true,
],
'right' => [
'openBbcode' => '/^\[right\]/i',
'closeBbcode' => '[/right]',
'openHtml' => '<div class="bbcode-rendered__right" style="text-align: right;">',
'closeHtml' => '</div>',
'block' => true,
],
'quote' => [
'openBbcode' => '/^\[quote\]/i',
'closeBbcode' => '[/quote]',
'openHtml' => '<blockquote>',
'closeHtml' => '</blockquote>',
'block' => true,
],
'namedquote' => [
'openBbcode' => '/^\[quote=(.*?)\]/i',
'closeBbcode' => '[/quote]',
'openHtml' => '<blockquote><i class="fas fa-quote-left"></i> <cite>Quoting $1:</cite><p>',
'closeHtml' => '</p></blockquote>',
'block' => true,
],
'orderedlistnumerical' => [
'openBbcode' => '/^\[list=1\]/i',
'closeBbcode' => '[/list]',
'openHtml' => '<ol>',
'closeHtml' => '</ol>',
'block' => true,
],
'orderedlistalpha' => [
'openBbcode' => '/^\[list=a\]/i',
'closeBbcode' => '[/list]',
'openHtml' => '<ol type="a">',
'closeHtml' => '</ol>',
'block' => true,
],
'unorderedlist' => [
'openBbcode' => '/^\[list\]/i',
'closeBbcode' => '[/list]',
'openHtml' => '<ul>',
'closeHtml' => '</ul>',
'block' => true,
],
'code' => [
'openBbcode' => '/^\[code\]/i',
'closeBbcode' => '[/code]',
'openHtml' => '<div class="bbcode-rendered__clipboard" x-data="clipboardButton"><pre><code>',
'closeHtml' => '</code></pre><div class="bbcode-rendered__clipboard-container"><button class="bbcode-rendered__clipboard-button" x-bind="button"><i class="fa fa-clone"></i></button></div></div>',
'block' => true,
],
'pre' => [
'openBbcode' => '/^\[pre\]/i',
'closeBbcode' => '[/pre]',
'openHtml' => '<code>',
'closeHtml' => '</code>',
'block' => false,
],
'alert' => [
'openBbcode' => '/^\[alert\]/i',
'closeBbcode' => '[/alert]',
'openHtml' => '<div class="bbcode-rendered__alert">',
'closeHtml' => '</div>',
'block' => true,
],
'note' => [
'openBbcode' => '/^\[note\]/i',
'closeBbcode' => '[/note]',
'openHtml' => '<div class="bbcode-rendered__note">',
'closeHtml' => '</div>',
'block' => true,
],
'sub' => [
'openBbcode' => '/^\[sub\]/i',
'closeBbcode' => '[/sub]',
'openHtml' => '<sub>',
'closeHtml' => '</sub>',
'block' => false,
],
'sup' => [
'openBbcode' => '/^\[sup\]/i',
'closeBbcode' => '[/sup]',
'openHtml' => '<sup>',
'closeHtml' => '</sup>',
'block' => false,
],
'small' => [
'openBbcode' => '/^\[small\]/i',
'closeBbcode' => '[/small]',
'openHtml' => '<small>',
'closeHtml' => '</small>',
'block' => false,
],
'table' => [
'openBbcode' => '/^\[table\]/i',
'closeBbcode' => '[/table]',
'openHtml' => '<table>',
'closeHtml' => '</table>',
'block' => true,
],
'table-row' => [
'openBbcode' => '/^\[tr\]/i',
'closeBbcode' => '[/tr]',
'openHtml' => '<tr>',
'closeHtml' => '</tr>',
'block' => true,
],
'table-header' => [
'openBbcode' => '/^\[th\]/i',
'closeBbcode' => '[/th]',
'openHtml' => '<th>',
'closeHtml' => '</th>',
'block' => true,
],
'table-data' => [
'openBbcode' => '/^\[td\]/i',
'closeBbcode' => '[/td]',
'openHtml' => '<td>',
'closeHtml' => '</td>',
'block' => true,
],
'spoiler' => [
'openBbcode' => '/^\[spoiler\]/i',
'closeBbcode' => '[/spoiler]',
'openHtml' => '<details><summary>Spoiler</summary><div style="text-align:left;">',
'closeHtml' => '</div></details>',
'block' => false,
],
'named-spoiler' => [
'openBbcode' => '/^\[spoiler=(.*?)\]/i',
'closeBbcode' => '[/spoiler]',
'openHtml' => '<details><summary>$1</summary><div style="text-align:left;">',
'closeHtml' => '</div></details>',
'block' => false,
],
];
private static function parsers(): array
{
return [
'h1' => [
'openBbcode' => '/^\[h1\]/i',
'closeBbcode' => '[/h1]',
'openHtml' => '<h1>',
'closeHtml' => '</h1>',
'block' => true,
],
'h2' => [
'openBbcode' => '/^\[h2\]/i',
'closeBbcode' => '[/h2]',
'openHtml' => '<h2>',
'closeHtml' => '</h2>',
'block' => true,
],
'h3' => [
'openBbcode' => '/^\[h3\]/i',
'closeBbcode' => '[/h3]',
'openHtml' => '<h3>',
'closeHtml' => '</h3>',
'block' => true,
],
'h4' => [
'openBbcode' => '/^\[h4\]/i',
'closeBbcode' => '[/h4]',
'openHtml' => '<h4>',
'closeHtml' => '</h4>',
'block' => true,
],
'h5' => [
'openBbcode' => '/^\[h5\]/i',
'closeBbcode' => '[/h5]',
'openHtml' => '<h5>',
'closeHtml' => '</h5>',
'block' => true,
],
'h6' => [
'openBbcode' => '/^\[h6\]/i',
'closeBbcode' => '[/h6]',
'openHtml' => '<h6>',
'closeHtml' => '</h6>',
'block' => true,
],
'bold' => [
'openBbcode' => '/^\[b\]/i',
'closeBbcode' => '[/b]',
'openHtml' => '<b>',
'closeHtml' => '</b>',
'block' => false,
],
'italic' => [
'openBbcode' => '/^\[i\]/i',
'closeBbcode' => '[/i]',
'openHtml' => '<i>',
'closeHtml' => '</i>',
'block' => false,
],
'underline' => [
'openBbcode' => '/^\[u\]/i',
'closeBbcode' => '[/u]',
'openHtml' => '<u>',
'closeHtml' => '</u>',
'block' => false,
],
'linethrough' => [
'openBbcode' => '/^\[s\]/i',
'closeBbcode' => '[/s]',
'openHtml' => '<s>',
'closeHtml' => '</s>',
'block' => false,
],
'size' => [
'openBbcode' => '/^\[size=(\d+)\]/i',
'closeBbcode' => '[/size]',
'openHtml' => '<span style="font-size: clamp(10px, $1px, 100px);">',
'closeHtml' => '</span>',
'block' => false,
],
'font' => [
'openBbcode' => '/^\[font=([a-z0-9 ]+)\]/i',
'closeBbcode' => '[/font]',
'openHtml' => '<span style="font-family: $1;">',
'closeHtml' => '</span>',
'block' => false,
],
'color' => [
'openBbcode' => '/^\[color=(\#[a-f0-9]{3,4}|\#[a-f0-9]{6}|\#[a-f0-9]{8}|[a-z]+)\]/i',
'closeBbcode' => '[/color]',
'openHtml' => '<span style="color: $1;">',
'closeHtml' => '</span>',
'block' => false,
],
'center' => [
'openBbcode' => '/^\[center\]/i',
'closeBbcode' => '[/center]',
'openHtml' => '<div class="bbcode-rendered__center" style="text-align: center;">',
'closeHtml' => '</div>',
'block' => true,
],
'left' => [
'openBbcode' => '/^\[left\]/i',
'closeBbcode' => '[/left]',
'openHtml' => '<div class="bbcode-rendered__left" style="text-align: left;">',
'closeHtml' => '</div>',
'block' => true,
],
'right' => [
'openBbcode' => '/^\[right\]/i',
'closeBbcode' => '[/right]',
'openHtml' => '<div class="bbcode-rendered__right" style="text-align: right;">',
'closeHtml' => '</div>',
'block' => true,
],
'quote' => [
'openBbcode' => '/^\[quote\]/i',
'closeBbcode' => '[/quote]',
'openHtml' => '<blockquote>',
'closeHtml' => '</blockquote>',
'block' => true,
],
'namedquote' => [
'openBbcode' => '/^\[quote=(.*?)\]/i',
'closeBbcode' => '[/quote]',
'openHtml' => '<blockquote><i class="fas fa-quote-left"></i> <cite>Quoting $1:</cite><p>',
'closeHtml' => '</p></blockquote>',
'block' => true,
],
'orderedlistnumerical' => [
'openBbcode' => '/^\[list=1\]/i',
'closeBbcode' => '[/list]',
'openHtml' => '<ol>',
'closeHtml' => '</ol>',
'block' => true,
],
'orderedlistalpha' => [
'openBbcode' => '/^\[list=a\]/i',
'closeBbcode' => '[/list]',
'openHtml' => '<ol type="a">',
'closeHtml' => '</ol>',
'block' => true,
],
'unorderedlist' => [
'openBbcode' => '/^\[list\]/i',
'closeBbcode' => '[/list]',
'openHtml' => '<ul>',
'closeHtml' => '</ul>',
'block' => true,
],
'code' => [
'openBbcode' => '/^\[code\]/i',
'closeBbcode' => '[/code]',
'openHtml' => '<div class="bbcode-rendered__clipboard" x-data="clipboardButton"><pre><code>',
'closeHtml' => '</code></pre><div class="bbcode-rendered__clipboard-container"><button class="bbcode-rendered__clipboard-button" x-bind="button"><i class="fa fa-clone"></i></button></div></div>',
'block' => true,
],
'pre' => [
'openBbcode' => '/^\[pre\]/i',
'closeBbcode' => '[/pre]',
'openHtml' => '<code>',
'closeHtml' => '</code>',
'block' => false,
],
'alert' => [
'openBbcode' => '/^\[alert\]/i',
'closeBbcode' => '[/alert]',
'openHtml' => '<div class="bbcode-rendered__alert">',
'closeHtml' => '</div>',
'block' => true,
],
'note' => [
'openBbcode' => '/^\[note\]/i',
'closeBbcode' => '[/note]',
'openHtml' => '<div class="bbcode-rendered__note">',
'closeHtml' => '</div>',
'block' => true,
],
'sub' => [
'openBbcode' => '/^\[sub\]/i',
'closeBbcode' => '[/sub]',
'openHtml' => '<sub>',
'closeHtml' => '</sub>',
'block' => false,
],
'sup' => [
'openBbcode' => '/^\[sup\]/i',
'closeBbcode' => '[/sup]',
'openHtml' => '<sup>',
'closeHtml' => '</sup>',
'block' => false,
],
'small' => [
'openBbcode' => '/^\[small\]/i',
'closeBbcode' => '[/small]',
'openHtml' => '<small>',
'closeHtml' => '</small>',
'block' => false,
],
'table' => [
'openBbcode' => '/^\[table\]/i',
'closeBbcode' => '[/table]',
'openHtml' => '<table>',
'closeHtml' => '</table>',
'block' => true,
],
'table-row' => [
'openBbcode' => '/^\[tr\]/i',
'closeBbcode' => '[/tr]',
'openHtml' => '<tr>',
'closeHtml' => '</tr>',
'block' => true,
],
'table-header' => [
'openBbcode' => '/^\[th\]/i',
'closeBbcode' => '[/th]',
'openHtml' => '<th>',
'closeHtml' => '</th>',
'block' => true,
],
'table-data' => [
'openBbcode' => '/^\[td\]/i',
'closeBbcode' => '[/td]',
'openHtml' => '<td>',
'closeHtml' => '</td>',
'block' => true,
],
'spoiler' => [
'openBbcode' => '/^\[spoiler\]/i',
'closeBbcode' => '[/spoiler]',
'openHtml' => '<details><summary>Spoiler</summary><div style="text-align:left;">',
'closeHtml' => '</div></details>',
'block' => false,
],
'named-spoiler' => [
'openBbcode' => '/^\[spoiler=(.*?)\]/i',
'closeBbcode' => '[/spoiler]',
'openHtml' => '<details><summary>$1</summary><div style="text-align:left;">',
'closeHtml' => '</div></details>',
'block' => false,
],
];
}
/**
* Parses the BBCode string.
@@ -378,7 +381,7 @@ class Bbcode
// Is the potential tag opening or closing?
if ($source[$index + 1] === '/' && !empty($openedElements)) {
$name = array_pop($openedElements);
$el = $this->parsers[$name];
$el = self::parsers()[$name];
$tag = substr((string) $source, $index, \strlen((string) $el['closeBbcode']));
// Replace bbcode tag with html tag if found tag matches expected tag,
@@ -396,7 +399,7 @@ class Bbcode
$remainingText = substr((string) $source, $index);
// Find match between found bbcode tag and valid elements
foreach ($this->parsers as $name => $el) {
foreach (self::parsers() as $name => $el) {
// The opening bbcode tag uses the regex `^` character to make
// sure only the beginning of $remainingText is matched
if (preg_match($el['openBbcode'], $remainingText, $matches) === 1) {
@@ -418,7 +421,7 @@ class Bbcode
}
while (!empty($openedElements)) {
$source .= $this->parsers[array_pop($openedElements)]['closeHtml'];
$source .= self::parsers()[array_pop($openedElements)]['closeHtml'];
}
if ($replaceLineBreaks) {