aboutsummaryrefslogtreecommitdiffhomepage
path: root/application/formatter
diff options
context:
space:
mode:
Diffstat (limited to 'application/formatter')
-rw-r--r--application/formatter/BookmarkDefaultFormatter.php4
-rw-r--r--application/formatter/BookmarkMarkdownExtraFormatter.php4
-rw-r--r--application/formatter/BookmarkMarkdownFormatter.php19
-rw-r--r--application/formatter/Parsedown/ShaarliParsedown.php15
-rw-r--r--application/formatter/Parsedown/ShaarliParsedownExtra.php15
-rw-r--r--application/formatter/Parsedown/ShaarliParsedownTrait.php81
6 files changed, 130 insertions, 8 deletions
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;
12 */ 12 */
13class BookmarkDefaultFormatter extends BookmarkFormatter 13class BookmarkDefaultFormatter extends BookmarkFormatter
14{ 14{
15 protected const SEARCH_HIGHLIGHT_OPEN = '|@@HIGHLIGHT'; 15 public const SEARCH_HIGHLIGHT_OPEN = '||O_HIGHLIGHT';
16 protected const SEARCH_HIGHLIGHT_CLOSE = 'HIGHLIGHT@@|'; 16 public const SEARCH_HIGHLIGHT_CLOSE = '||C_HIGHLIGHT';
17 17
18 /** 18 /**
19 * @inheritdoc 19 * @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 @@
3namespace Shaarli\Formatter; 3namespace Shaarli\Formatter;
4 4
5use Shaarli\Config\ConfigManager; 5use Shaarli\Config\ConfigManager;
6use Shaarli\Formatter\Parsedown\ShaarliParsedownExtra;
6 7
7/** 8/**
8 * Class BookmarkMarkdownExtraFormatter 9 * Class BookmarkMarkdownExtraFormatter
@@ -18,7 +19,6 @@ class BookmarkMarkdownExtraFormatter extends BookmarkMarkdownFormatter
18 public function __construct(ConfigManager $conf, bool $isLoggedIn) 19 public function __construct(ConfigManager $conf, bool $isLoggedIn)
19 { 20 {
20 parent::__construct($conf, $isLoggedIn); 21 parent::__construct($conf, $isLoggedIn);
21 22 $this->parsedown = new ShaarliParsedownExtra();
22 $this->parsedown = new \ParsedownExtra();
23 } 23 }
24} 24}
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 @@
3namespace Shaarli\Formatter; 3namespace Shaarli\Formatter;
4 4
5use Shaarli\Config\ConfigManager; 5use Shaarli\Config\ConfigManager;
6use Shaarli\Formatter\Parsedown\ShaarliParsedown;
6 7
7/** 8/**
8 * Class BookmarkMarkdownFormatter 9 * Class BookmarkMarkdownFormatter
@@ -42,7 +43,7 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter
42 { 43 {
43 parent::__construct($conf, $isLoggedIn); 44 parent::__construct($conf, $isLoggedIn);
44 45
45 $this->parsedown = new \Parsedown(); 46 $this->parsedown = new ShaarliParsedown();
46 $this->escape = $conf->get('security.markdown_escape', true); 47 $this->escape = $conf->get('security.markdown_escape', true);
47 $this->allowedProtocols = $conf->get('security.allowed_protocols', []); 48 $this->allowedProtocols = $conf->get('security.allowed_protocols', []);
48 } 49 }
@@ -128,6 +129,9 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter
128 protected function formatHashTags($description) 129 protected function formatHashTags($description)
129 { 130 {
130 $indexUrl = ! empty($this->contextData['index_url']) ? $this->contextData['index_url'] : ''; 131 $indexUrl = ! empty($this->contextData['index_url']) ? $this->contextData['index_url'] : '';
132 $tokens = '(?:' . BookmarkDefaultFormatter::SEARCH_HIGHLIGHT_OPEN . ')' .
133 '(?:' . BookmarkDefaultFormatter::SEARCH_HIGHLIGHT_CLOSE . ')'
134 ;
131 135
132 /* 136 /*
133 * To support unicode: http://stackoverflow.com/a/35498078/1484919 137 * To support unicode: http://stackoverflow.com/a/35498078/1484919
@@ -136,8 +140,15 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter
136 * \p{L} - letter from any language 140 * \p{L} - letter from any language
137 * \p{Mn} - any non marking space (accents, umlauts, etc) 141 * \p{Mn} - any non marking space (accents, umlauts, etc)
138 */ 142 */
139 $regex = '/(^|\s)#([\p{Pc}\p{N}\p{L}\p{Mn}]+)/mui'; 143 $regex = '/(^|\s)#([\p{Pc}\p{N}\p{L}\p{Mn}' . $tokens . ']+)/mui';
140 $replacement = '$1[#$2](' . $indexUrl . './add-tag/$2)'; 144 $replacement = function (array $match) use ($indexUrl): string {
145 $cleanMatch = str_replace(
146 BookmarkDefaultFormatter::SEARCH_HIGHLIGHT_OPEN,
147 '',
148 str_replace(BookmarkDefaultFormatter::SEARCH_HIGHLIGHT_CLOSE, '', $match[2])
149 );
150 return $match[1] . '[#' . $match[2] . '](' . $indexUrl . './add-tag/' . $cleanMatch . ')';
151 };
141 152
142 $descriptionLines = explode(PHP_EOL, $description); 153 $descriptionLines = explode(PHP_EOL, $description);
143 $descriptionOut = ''; 154 $descriptionOut = '';
@@ -156,7 +167,7 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter
156 } 167 }
157 168
158 if (!$codeBlockOn && !$codeLineOn) { 169 if (!$codeBlockOn && !$codeLineOn) {
159 $descriptionLine = preg_replace($regex, $replacement, $descriptionLine); 170 $descriptionLine = preg_replace_callback($regex, $replacement, $descriptionLine);
160 } 171 }
161 172
162 $descriptionOut .= $descriptionLine; 173 $descriptionOut .= $descriptionLine;
diff --git a/application/formatter/Parsedown/ShaarliParsedown.php b/application/formatter/Parsedown/ShaarliParsedown.php
new file mode 100644
index 00000000..8eb48fda
--- /dev/null
+++ b/application/formatter/Parsedown/ShaarliParsedown.php
@@ -0,0 +1,15 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Formatter\Parsedown;
6
7/**
8 * Parsedown extension for Shaarli.
9 *
10 * Extension for both Parsedown and ParsedownExtra centralized in ShaarliParsedownTrait.
11 */
12class ShaarliParsedown extends \Parsedown
13{
14 use ShaarliParsedownTrait;
15}
diff --git a/application/formatter/Parsedown/ShaarliParsedownExtra.php b/application/formatter/Parsedown/ShaarliParsedownExtra.php
new file mode 100644
index 00000000..15a35da4
--- /dev/null
+++ b/application/formatter/Parsedown/ShaarliParsedownExtra.php
@@ -0,0 +1,15 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Formatter\Parsedown;
6
7/**
8 * ParsedownExtra extension for Shaarli.
9 *
10 * Extension for both Parsedown and ParsedownExtra centralized in ShaarliParsedownTrait.
11 */
12class ShaarliParsedownExtra extends \ParsedownExtra
13{
14 use ShaarliParsedownTrait;
15}
diff --git a/application/formatter/Parsedown/ShaarliParsedownTrait.php b/application/formatter/Parsedown/ShaarliParsedownTrait.php
new file mode 100644
index 00000000..ed7b1747
--- /dev/null
+++ b/application/formatter/Parsedown/ShaarliParsedownTrait.php
@@ -0,0 +1,81 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Formatter\Parsedown;
6
7use Shaarli\Formatter\BookmarkDefaultFormatter as Formatter;
8
9/**
10 * Trait used for Parsedown and ParsedownExtra extension.
11 *
12 * Extended:
13 * - Format links properly in search context
14 */
15trait ShaarliParsedownTrait
16{
17 /**
18 * @inheritDoc
19 */
20 protected function inlineLink($excerpt)
21 {
22 return $this->shaarliFormatLink(parent::inlineLink($excerpt), true);
23 }
24
25 /**
26 * @inheritDoc
27 */
28 protected function inlineUrl($excerpt)
29 {
30 return $this->shaarliFormatLink(parent::inlineUrl($excerpt), false);
31 }
32
33 /**
34 * Properly format markdown link:
35 * - remove highlight tags from HREF attribute
36 * - (optional) add highlight tags to link caption
37 *
38 * @param array|null $link Parsedown formatted link array.
39 * It can be empty.
40 * @param bool $fullWrap Add highlight tags the whole link caption
41 *
42 * @return array|null
43 */
44 protected function shaarliFormatLink(?array $link, bool $fullWrap): ?array
45 {
46 // If open and clean search tokens are found in the link, process.
47 if (
48 is_array($link)
49 && strpos($link['element']['attributes']['href'] ?? '', Formatter::SEARCH_HIGHLIGHT_OPEN) !== false
50 && strpos($link['element']['attributes']['href'] ?? '', Formatter::SEARCH_HIGHLIGHT_CLOSE) !== false
51 ) {
52 $link['element']['attributes']['href'] = $this->shaarliRemoveSearchTokens(
53 $link['element']['attributes']['href']
54 );
55
56 if ($fullWrap) {
57 $link['element']['text'] = Formatter::SEARCH_HIGHLIGHT_OPEN .
58 $link['element']['text'] .
59 Formatter::SEARCH_HIGHLIGHT_CLOSE
60 ;
61 }
62 }
63
64 return $link;
65 }
66
67 /**
68 * Remove open and close tags from provided string.
69 *
70 * @param string $entry input
71 *
72 * @return string Striped input
73 */
74 protected function shaarliRemoveSearchTokens(string $entry): string
75 {
76 $entry = str_replace(Formatter::SEARCH_HIGHLIGHT_OPEN, '', $entry);
77 $entry = str_replace(Formatter::SEARCH_HIGHLIGHT_CLOSE, '', $entry);
78
79 return $entry;
80 }
81}