343 lines
11 KiB
PHP
343 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
use App\Models\User;
|
|
|
|
class Markdown extends \Parsedown {
|
|
|
|
|
|
function __construct() {
|
|
$this->setMarkupEscaped(true);
|
|
$this->setBreaksEnabled(true);
|
|
$this->setUrlsLinked(true);
|
|
$this->InlineTypes['@'][] = 'UserMention';
|
|
#$this->InlineTypes['%'][] = 'ColoredText';
|
|
$this->InlineTypes['['][] = 'KrebsText';
|
|
$this->InlineTypes['['][] = 'ReichText';
|
|
$this->InlineTypes['['][] = 'RainbowText';
|
|
$this->InlineTypes['['][] = 'SpoilerText';
|
|
$this->InlineTypes[':'][] = 'emojimatcherpng';
|
|
//$this->InlineTypes[':'][] = 'emojimatchermp4';
|
|
$this->InlineTypes[':'][] = 'ClickableTimestamp';
|
|
$this->inlineMarkerList .= '@';
|
|
}
|
|
|
|
protected function paragraph($Line) {
|
|
$Block = array(
|
|
'element' => array(
|
|
'name' => 'p',
|
|
'text' => $Line['text'],
|
|
'handler' => 'line',
|
|
'attributes' => [
|
|
'class' => 'comment'
|
|
]
|
|
),
|
|
);
|
|
|
|
return $Block;
|
|
}
|
|
|
|
// Matches the emojis in png format
|
|
protected function inlineemojimatcherpng($Excerpt) {
|
|
if (preg_match('/\:(\w+)\:/mUs', $Excerpt['text'], $matches)) {
|
|
$path = "images/comments/" . $matches[1];
|
|
$file_ext = "";
|
|
if(file_exists($path . ".webp"))
|
|
$file_ext = ".webp";
|
|
else if(file_exists($path . ".webp"))
|
|
$file_ext = ".webp";
|
|
if($file_ext === "")
|
|
return;
|
|
return [
|
|
'extent' => strlen($matches[0]),
|
|
'element' => [
|
|
'name' => 'img',
|
|
'handler' => 'line',
|
|
'attributes' => [
|
|
'class' => 'comment_emoji',
|
|
'src' => '/images/comments/' . $matches[1] . $file_ext,
|
|
'alt' => ':' . $matches[1] . ':',
|
|
'title' => ':' . $matches[1] . ':'
|
|
],
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
// Matches MP4 Emojis (Currently not possible due to Chromes shitty and malfunctioning autplay policy. Thanks idiots :*)
|
|
//protected function inlineemojimatchermp4($Excerpt) {
|
|
// if (preg_match('/\:(uwe)\:/mUs', $Excerpt['text'], $matches)) {
|
|
// return [
|
|
// 'extent' => strlen($matches[0]),
|
|
// 'element' => [
|
|
// 'name' => 'video',
|
|
// 'handler' => 'line',
|
|
// 'attributes' => [
|
|
// 'loop' => 'true',
|
|
// 'autoplay' => 'true',
|
|
// 'muted' => '',
|
|
// 'class' => 'comment_video',
|
|
// 'src' => '/images/comments/' . $matches[1] . '.mp4'
|
|
// ],
|
|
// ]
|
|
// ];
|
|
// }
|
|
//}
|
|
|
|
protected function inlineUserMention($Excerpt) {
|
|
if (preg_match('/\B@([\wÄÖÜäöü]+)/i', $Excerpt['context'], $matches)) {
|
|
if(User::whereUsername($matches[1])->count() > 0) {
|
|
return [
|
|
'extent' => strlen($matches[0]),
|
|
'element' => [
|
|
'name' => 'a',
|
|
'text' => $matches[0],
|
|
'attributes' => [
|
|
'href' => '/user/' . $matches[1], //link to username profile
|
|
'class' => 'user-mention', //style class of url
|
|
],
|
|
],
|
|
];
|
|
} else {
|
|
return [
|
|
'markup' => $matches[0],
|
|
'extent' => strlen($matches[0]),
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Matches [rb][/rb]
|
|
protected function inlineRainbowText($Excerpt) {
|
|
if (preg_match('/\[rb\](.+)\[\/rb]/mUs', $Excerpt['text'], $matches)) {
|
|
return [
|
|
'extent' => strlen($matches[0]),
|
|
'element' => [
|
|
'name' => 'span',
|
|
'handler' => 'line',
|
|
'text' => $matches[1],
|
|
'attributes' => [
|
|
'class' => 'rainbow'
|
|
],
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
// Matches [spoiler][/spoiler]
|
|
protected function inlineSpoilerText($Excerpt) {
|
|
if (preg_match('/\[spoiler\](.+)\[\/spoiler]/mUs', $Excerpt['text'], $matches)) {
|
|
return [
|
|
'extent' => strlen($matches[0]),
|
|
'element' => [
|
|
'name' => 'span',
|
|
'handler' => 'line',
|
|
'text' => $matches[1],
|
|
'attributes' => [
|
|
'class' => 'spoiler'
|
|
],
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
|
|
// Matches [krebs][/krebs]
|
|
protected function inlineKrebsText($Excerpt) {
|
|
if (preg_match('/\[krebs\](.+)\[\/krebs]/mUs', $Excerpt['text'], $matches)) {
|
|
return [
|
|
'extent' => strlen($matches[0]),
|
|
'element' => [
|
|
'name' => 'span',
|
|
'handler' => 'line',
|
|
'text' => $matches[1],
|
|
'attributes' => [
|
|
'class' => 'anim'
|
|
],
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
// Matches Reichtext
|
|
protected function inlineReichText($Excerpt) {
|
|
if (preg_match('/\[reich\](.+)\[\/reich]/mUs', $Excerpt['text'], $matches)) {
|
|
return [
|
|
'extent' => strlen($matches[0]),
|
|
'element' => [
|
|
'name' => 'span',
|
|
'handler' => 'line',
|
|
'text' => $matches[1],
|
|
'attributes' => [
|
|
'class' => 'reich'
|
|
],
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
// Matches %text% <- literally wtf error
|
|
/*protected function inlineColoredText($Excerpt) {
|
|
if (preg_match('/%(.+)%/', $Excerpt['text'], $matches)) {
|
|
return [
|
|
'extent' => strlen($matches[0]),
|
|
'element' => [
|
|
'name' => 'span',
|
|
'text' => $matches[1],
|
|
'attributes' => [
|
|
'class' => ''
|
|
],
|
|
]
|
|
];
|
|
}
|
|
}*/
|
|
|
|
//Greentext
|
|
protected function blockQuote($Excerpt) {
|
|
if (preg_match('/^>[ ]?(.*)/', $Excerpt['text'], $matches)) {
|
|
$Block = [
|
|
'element' => [
|
|
'name' => 'blockquote',
|
|
'handler' => 'lines',
|
|
'text' => (array) ('>' . $matches[1]),
|
|
],
|
|
];
|
|
return $Block;
|
|
}
|
|
|
|
}
|
|
|
|
protected function blockQuoteContinue($Excerpt, array $Block) {
|
|
if ($Excerpt['text'][0] === '>' && preg_match('/^>[ ]?(.*)/', $Excerpt['text'], $matches)) {
|
|
if (isset($Block['interrupted'])) {
|
|
$Block['element']['text'][] = '';
|
|
unset($Block['interrupted']);
|
|
}
|
|
$Block['element']['text'][] = '>' . $matches[1];
|
|
return $Block;
|
|
}
|
|
if (!isset($Block['interrupted'])) {
|
|
$Block['element']['text'][] = '>' . $Excerpt['text'];
|
|
return $Block;
|
|
}
|
|
}
|
|
|
|
// Disable Lists
|
|
protected function blockList($Excerpt) {
|
|
return;
|
|
}
|
|
|
|
protected function blockListContinue($Excerpt, array $block) {
|
|
return;
|
|
}
|
|
|
|
// Disable headers
|
|
protected function blockHeader($Excerpt) {
|
|
return;
|
|
}
|
|
|
|
protected function blockSetextHeader($Excerpt, array $block = null) {
|
|
return;
|
|
}
|
|
|
|
protected function blockTable($Excerpt, array $block = null) {
|
|
return;
|
|
}
|
|
|
|
// Disable markdown links
|
|
protected function inlineLink($Excerpt) {
|
|
return;
|
|
}
|
|
|
|
// Disable markdown images
|
|
protected function inlineImage($Excerpt) {
|
|
return;
|
|
}
|
|
|
|
// Differentiate between internal and external urls and images
|
|
protected function inlineUrl($Excerpt) {
|
|
$e = parent::inlineUrl($Excerpt);
|
|
if (is_null($e)) return;
|
|
$e['element']['attributes']['href'] = htmlspecialchars($e['element']['attributes']['href']);
|
|
if (static::isImage($e['element']['attributes']['href'])) {
|
|
$e['element']['name'] = 'img';
|
|
$e['element']['attributes']['src'] = $e['element']['attributes']['href'];
|
|
$e['element']['attributes']['alt'] = 'Image';
|
|
$e['element']['attributes']['class'] = 'comment_image';
|
|
$e['element']['attributes']['loading'] = 'lazy';
|
|
unset($e['element']['attributes']['href']);
|
|
unset($e['element']['text']);
|
|
return $e;
|
|
}
|
|
if (!static::isInternal($e['element']['attributes']['href'])) {
|
|
$e['element']['attributes']['target'] = '_blank';
|
|
$e['element']['attributes']['rel'] = 'extern';
|
|
} else {
|
|
$url = parse_url($e['element']['text']);
|
|
$text = $url['path'];
|
|
if (isset($url['query'])) {
|
|
$text .= '?' . $url['query'];
|
|
}
|
|
if (isset($url['fragment'])) {
|
|
$text .= '#' . $url['fragment'];
|
|
}
|
|
$e['element']['text'] = $text;
|
|
}
|
|
return $e;
|
|
}
|
|
|
|
protected function inlineClickableTimestamp($Excerpt) {
|
|
if (preg_match('/(?<=\s|^)([0-5]?\d:[0-5]\d)(?=\s|$)/', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) {
|
|
return [
|
|
'extent' => strlen($matches[0][0]),
|
|
'position' => $matches[0][1],
|
|
'element' => [
|
|
'name' => 'a',
|
|
'text' => $matches[0][0],
|
|
'attributes' => [
|
|
'href' => '#',
|
|
'class' => 'comment_clickable_timestamp'
|
|
]
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
private static function isInternal($url) {
|
|
$host = parse_url($url, PHP_URL_HOST);
|
|
$currhost = $_SERVER['SERVER_NAME'];
|
|
if (0 === strpos($host, 'www')) {
|
|
$host = substr($host, 4);
|
|
}
|
|
if (0 === strpos($currhost, 'www')) {
|
|
$currhost = substr($currhost, 4);
|
|
}
|
|
return $host === $currhost;
|
|
}
|
|
|
|
private static function isImage($url) {
|
|
$cfg = config('comments');
|
|
$allowedHosters = $cfg['allowedHosters'];
|
|
$allowedExtensions = $cfg['allowedImageFileExtensions'];
|
|
$url = parse_url($url);
|
|
if (isset($url['path'])) {
|
|
$ext = pathinfo($url['path'], PATHINFO_EXTENSION);
|
|
if (in_array($ext, $allowedExtensions)) {
|
|
if (isset($url['scheme']) && $url['scheme'] === 'https') {
|
|
foreach($allowedHosters as $hoster) {
|
|
foreach($hoster as $regex) {
|
|
if(preg_match($regex, $url['host'])) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
}
|