From 9ef8555ad298668bcb8537ccdd2ab6560f44177f Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Tue, 19 Jan 2021 17:49:19 +0100 Subject: Support search highlights when matching URL content DefaultFormatter: - format 'a' tag content and not href attribute - format hashtags properly Markdown(Extra)Formatter: - Extend Parsedown to format highlight properly: https://github.com/erusev/parsedown/wiki/Tutorial:-Create-Extensions Fixes #1681 --- application/formatter/BookmarkDefaultFormatter.php | 4 +- .../formatter/BookmarkMarkdownExtraFormatter.php | 4 +- .../formatter/BookmarkMarkdownFormatter.php | 19 ++++++-- .../formatter/Parsedown/ShaarliParsedown.php | 10 +++++ .../formatter/Parsedown/ShaarliParsedownExtra.php | 10 +++++ .../formatter/Parsedown/ShaarliParsedownTrait.php | 50 ++++++++++++++++++++++ 6 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 application/formatter/Parsedown/ShaarliParsedown.php create mode 100644 application/formatter/Parsedown/ShaarliParsedownExtra.php create mode 100644 application/formatter/Parsedown/ShaarliParsedownTrait.php (limited to 'application/formatter') diff --git a/application/formatter/BookmarkDefaultFormatter.php b/application/formatter/BookmarkDefaultFormatter.php index 7e0afafc..7e93bf71 100644 --- a/application/formatter/BookmarkDefaultFormatter.php +++ b/application/formatter/BookmarkDefaultFormatter.php @@ -12,8 +12,8 @@ namespace Shaarli\Formatter; */ class BookmarkDefaultFormatter extends BookmarkFormatter { - protected const SEARCH_HIGHLIGHT_OPEN = '|@@HIGHLIGHT'; - protected const SEARCH_HIGHLIGHT_CLOSE = 'HIGHLIGHT@@|'; + public const SEARCH_HIGHLIGHT_OPEN = '||O_HIGHLIGHT'; + public const SEARCH_HIGHLIGHT_CLOSE = '||C_HIGHLIGHT'; /** * @inheritdoc diff --git a/application/formatter/BookmarkMarkdownExtraFormatter.php b/application/formatter/BookmarkMarkdownExtraFormatter.php index 0694b23f..da539bfd 100644 --- a/application/formatter/BookmarkMarkdownExtraFormatter.php +++ b/application/formatter/BookmarkMarkdownExtraFormatter.php @@ -3,6 +3,7 @@ namespace Shaarli\Formatter; use Shaarli\Config\ConfigManager; +use Shaarli\Formatter\Parsedown\ShaarliParsedownExtra; /** * Class BookmarkMarkdownExtraFormatter @@ -18,7 +19,6 @@ class BookmarkMarkdownExtraFormatter extends BookmarkMarkdownFormatter public function __construct(ConfigManager $conf, bool $isLoggedIn) { parent::__construct($conf, $isLoggedIn); - - $this->parsedown = new \ParsedownExtra(); + $this->parsedown = new ShaarliParsedownExtra(); } } diff --git a/application/formatter/BookmarkMarkdownFormatter.php b/application/formatter/BookmarkMarkdownFormatter.php index ee4e8dca..d4dccee6 100644 --- a/application/formatter/BookmarkMarkdownFormatter.php +++ b/application/formatter/BookmarkMarkdownFormatter.php @@ -3,6 +3,7 @@ namespace Shaarli\Formatter; use Shaarli\Config\ConfigManager; +use Shaarli\Formatter\Parsedown\ShaarliParsedown; /** * Class BookmarkMarkdownFormatter @@ -42,7 +43,7 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter { parent::__construct($conf, $isLoggedIn); - $this->parsedown = new \Parsedown(); + $this->parsedown = new ShaarliParsedown(); $this->escape = $conf->get('security.markdown_escape', true); $this->allowedProtocols = $conf->get('security.allowed_protocols', []); } @@ -128,6 +129,9 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter protected function formatHashTags($description) { $indexUrl = ! empty($this->contextData['index_url']) ? $this->contextData['index_url'] : ''; + $tokens = '(?:' . BookmarkDefaultFormatter::SEARCH_HIGHLIGHT_OPEN . ')' . + '(?:' . BookmarkDefaultFormatter::SEARCH_HIGHLIGHT_CLOSE . ')' + ; /* * To support unicode: http://stackoverflow.com/a/35498078/1484919 @@ -136,8 +140,15 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter * \p{L} - letter from any language * \p{Mn} - any non marking space (accents, umlauts, etc) */ - $regex = '/(^|\s)#([\p{Pc}\p{N}\p{L}\p{Mn}]+)/mui'; - $replacement = '$1[#$2](' . $indexUrl . './add-tag/$2)'; + $regex = '/(^|\s)#([\p{Pc}\p{N}\p{L}\p{Mn}' . $tokens . ']+)/mui'; + $replacement = function (array $match) use ($indexUrl): string { + $cleanMatch = str_replace( + BookmarkDefaultFormatter::SEARCH_HIGHLIGHT_OPEN, + '', + str_replace(BookmarkDefaultFormatter::SEARCH_HIGHLIGHT_CLOSE, '', $match[2]) + ); + return $match[1] . '[#' . $match[2] . '](' . $indexUrl . './add-tag/' . $cleanMatch . ')'; + }; $descriptionLines = explode(PHP_EOL, $description); $descriptionOut = ''; @@ -156,7 +167,7 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter } if (!$codeBlockOn && !$codeLineOn) { - $descriptionLine = preg_replace($regex, $replacement, $descriptionLine); + $descriptionLine = preg_replace_callback($regex, $replacement, $descriptionLine); } $descriptionOut .= $descriptionLine; diff --git a/application/formatter/Parsedown/ShaarliParsedown.php b/application/formatter/Parsedown/ShaarliParsedown.php new file mode 100644 index 00000000..d577bdfa --- /dev/null +++ b/application/formatter/Parsedown/ShaarliParsedown.php @@ -0,0 +1,10 @@ +shaarliFormatLink(parent::inlineLink($excerpt), true); + } + + protected function inlineUrl($excerpt) + { + return $this->shaarliFormatLink(parent::inlineUrl($excerpt), false); + } + + protected function shaarliFormatLink(?array $link, bool $fullWrap): ?array + { + if ( + is_array($link) + && strpos($link['element']['attributes']['href'], Formatter::SEARCH_HIGHLIGHT_OPEN) !== false + && strpos($link['element']['attributes']['href'], Formatter::SEARCH_HIGHLIGHT_CLOSE) !== false + ) { + $link['element']['attributes']['href'] = $this->shaarliRemoveSearchTokens( + $link['element']['attributes']['href'] + ); + + if ($fullWrap) { + $link['element']['text'] = Formatter::SEARCH_HIGHLIGHT_OPEN . + $link['element']['text'] . + Formatter::SEARCH_HIGHLIGHT_CLOSE + ; + } + } + + return $link; + } + + protected function shaarliRemoveSearchTokens(string $entry): string + { + $entry = str_replace(Formatter::SEARCH_HIGHLIGHT_OPEN, '', $entry); + $entry = str_replace(Formatter::SEARCH_HIGHLIGHT_CLOSE, '', $entry); + + return $entry; + } +} -- cgit v1.2.3