X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FContent%2FText%2FMarkdown.php;h=33e023bc03662b9f55bbec4913a12b6506d6463a;hb=2f7e22c4f754cd43a9de1ec2799544da0d7c9411;hp=a715de7e97e1debba48f30ebe558864bd42962b9;hpb=61fe82ad20fa61e441df5a4bf4e9bb2b7f23411a;p=friendica.git diff --git a/src/Content/Text/Markdown.php b/src/Content/Text/Markdown.php index a715de7e97..33e023bc03 100644 --- a/src/Content/Text/Markdown.php +++ b/src/Content/Text/Markdown.php @@ -1,83 +1,105 @@ . + * */ namespace Friendica\Content\Text; -use Friendica\BaseObject; +use Friendica\Core\Logger; use Friendica\Core\System; +use Friendica\DI; use Friendica\Model\Contact; /** * Friendica-specific usage of Markdown - * - * @author Hypolite Petovan */ -class Markdown extends BaseObject +class Markdown { /** * Converts a Markdown string into HTML. The hardwrap parameter maximizes * compatibility with Diaspora in spite of the Markdown standard. * - * @brief Converts a Markdown string into HTML * @param string $text - * @param bool $hardwrap + * @param bool $hardwrap Enables line breaks on \n without two trailing spaces + * @param string $baseuri Optional. Prepend anchor links with this URL * @return string - * @throws \Exception */ - public static function convert($text, $hardwrap = true) { - $stamp1 = microtime(true); + public static function convert($text, $hardwrap = true, $baseuri = null) { + DI::profiler()->startRecording('rendering'); $MarkdownParser = new MarkdownParser(); $MarkdownParser->code_class_prefix = 'language-'; $MarkdownParser->hard_wrap = $hardwrap; $MarkdownParser->hashtag_protection = true; - $MarkdownParser->url_filter_func = function ($url) { - if (strpos($url, '#') === 0) { - $url = ltrim($_SERVER['REQUEST_URI'], '/') . $url; + $MarkdownParser->url_filter_func = function ($url) use ($baseuri) { + if (!empty($baseuri) && strpos($url, '#') === 0) { + $url = ltrim($baseuri, '/') . $url; } return $url; }; + $text = self::convertDiasporaMentionsToHtml($text); + $html = $MarkdownParser->transform($text); - self::getApp()->getProfiler()->saveTimestamp($stamp1, "parser", System::callstack()); + DI::profiler()->stopRecording(); return $html; } /** - * @brief Callback function to replace a Diaspora style mention in a mention for Friendica + * Replace Diaspora-style mentions in a text since they trip the Markdown parser autolinker. * - * @param array $match Matching values for the callback - * [1] = mention type (@ or !) - * [2] = name (optional) - * [3] = address - * @return string Replaced mention - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - * @throws \ImagickException + * @param string $text + * @return string */ - private static function diasporaMention2BBCodeCallback($match) + private static function convertDiasporaMentionsToHtml(string $text) { - if ($match[3] == '') { - return; - } - - $data = Contact::getDetailsByAddr($match[3]); - - if (empty($data)) { - return; - } - - $name = $match[2]; - - if ($name == '') { - $name = $data['name']; - } - - return $match[1] . '[url=' . $data['url'] . ']' . $name . '[/url]'; + return preg_replace_callback( + '/([@!]){(?:([^}]+?); ?)?([^} ]+)}/', + /* + * Matching values for the callback + * [1] = mention type (@ or !) + * [2] = name (optional) + * [3] = profile URL + */ + function ($matches) { + if ($matches[3] == '') { + return ''; + } + + $data = Contact::getByURL($matches[3]); + + if (empty($data)) { + return ''; + } + + $name = $matches[2]; + + if ($name == '') { + $name = $data['name']; + } + + return $matches[1] . '' . $name . ''; + }, + $text + ); } /* @@ -86,9 +108,19 @@ class Markdown extends BaseObject * So we'll use that to convert to HTML, then convert the HTML back to bbcode, * and then clean up a few Diaspora specific constructs. */ - public static function toBBCode($s) + public static function toBBCode($s): string { - $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8'); + // @TODO Temporary until we find the source of the null value to finally set the correct type-hint + if (is_null($s)) { + Logger::warning('Received null value', ['callstack' => System::callstack()]); + return ''; + } + + if (!$s) { + return $s; + } + + DI::profiler()->startRecording('rendering'); // The parser cannot handle paragraphs correctly $s = str_replace(['

', '

', '

'], ['
', '
', '
'], $s); @@ -98,29 +130,22 @@ class Markdown extends BaseObject $s = self::convert($s); - $regexp = "/([@!])\{(?:([^\}]+?); ?)?([^\} ]+)\}/"; - $s = preg_replace_callback($regexp, ['self', 'diasporaMention2BBCodeCallback'], $s); - $s = HTML::toBBCode($s); // protect the recycle symbol from turning into a tag, but without unescaping angles and naked ampersands $s = str_replace('♲', html_entity_decode('♲', ENT_QUOTES, 'UTF-8'), $s); - // Convert everything that looks like a link to a link - $s = preg_replace('/([^\]=]|^)(https?\:\/\/)([a-zA-Z0-9:\/\-?&;.=_~#%$!+,@]+(?stopRecording(); return $s; } }