aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag/CoreBundle
diff options
context:
space:
mode:
authorJeremy Benoist <jeremy.benoist@gmail.com>2018-11-25 09:58:18 +0100
committerJeremy Benoist <jeremy.benoist@gmail.com>2018-11-25 09:58:18 +0100
commitb878be4cc99fd4927c70b59386cf7a57b33bb381 (patch)
tree9a5186ead93b9f6114b5341a7713f614eb58f6ec /src/Wallabag/CoreBundle
parente673b54f702f274a087e4feff409663d9636e57b (diff)
parentbffe65478de71113a16f6e7a7ef75845c9d61180 (diff)
downloadwallabag-b878be4cc99fd4927c70b59386cf7a57b33bb381.tar.gz
wallabag-b878be4cc99fd4927c70b59386cf7a57b33bb381.tar.zst
wallabag-b878be4cc99fd4927c70b59386cf7a57b33bb381.zip
Merge remote-tracking branch 'origin/master' into 2.4
# Conflicts: # web/wallassets/baggy.js # web/wallassets/manifest.json # web/wallassets/material.css # web/wallassets/material.js
Diffstat (limited to 'src/Wallabag/CoreBundle')
-rw-r--r--src/Wallabag/CoreBundle/Helper/ContentProxy.php172
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.da.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.en.yml10
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.es.yml2
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml6
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.it.yml2
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml2
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/base.html.twig2
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig2
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entry.html.twig16
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig2
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/common/Static/howto.html.twig10
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_no_preview.html.twig7
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_preview.html.twig3
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig4
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig18
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig2
20 files changed, 220 insertions, 56 deletions
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
index 3fe31c2c..d38811a2 100644
--- a/src/Wallabag/CoreBundle/Helper/ContentProxy.php
+++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
@@ -53,6 +53,7 @@ class ContentProxy
53 53
54 if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) { 54 if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) {
55 $fetchedContent = $this->graby->fetchContent($url); 55 $fetchedContent = $this->graby->fetchContent($url);
56 $fetchedContent['title'] = $this->sanitizeContentTitle($fetchedContent['title'], $fetchedContent['content_type']);
56 57
57 // when content is imported, we have information in $content 58 // when content is imported, we have information in $content
58 // in case fetching content goes bad, we'll keep the imported information instead of overriding them 59 // in case fetching content goes bad, we'll keep the imported information instead of overriding them
@@ -65,6 +66,13 @@ class ContentProxy
65 // so we'll be able to refetch it in the future 66 // so we'll be able to refetch it in the future
66 $content['url'] = !empty($content['url']) ? $content['url'] : $url; 67 $content['url'] = !empty($content['url']) ? $content['url'] : $url;
67 68
69 // In one case (at least in tests), url is empty here
70 // so we set it using $url provided in the updateEntry call.
71 // Not sure what are the other possible cases where this property is empty
72 if (empty($entry->getUrl()) && !empty($url)) {
73 $entry->setUrl($url);
74 }
75
68 $this->stockEntry($entry, $content); 76 $this->stockEntry($entry, $content);
69 } 77 }
70 78
@@ -177,6 +185,59 @@ class ContentProxy
177 } 185 }
178 186
179 /** 187 /**
188 * Try to sanitize the title of the fetched content from wrong character encodings and invalid UTF-8 character.
189 *
190 * @param $title
191 * @param $contentType
192 *
193 * @return string
194 */
195 private function sanitizeContentTitle($title, $contentType)
196 {
197 if ('application/pdf' === $contentType) {
198 $title = $this->convertPdfEncodingToUTF8($title);
199 }
200
201 return $this->sanitizeUTF8Text($title);
202 }
203
204 /**
205 * If the title from the fetched content comes from a PDF, then its very possible that the character encoding is not
206 * UTF-8. This methods tries to identify the character encoding and translate the title to UTF-8.
207 *
208 * @param $title
209 *
210 * @return string (maybe contains invalid UTF-8 character)
211 */
212 private function convertPdfEncodingToUTF8($title)
213 {
214 // first try UTF-8 because its easier to detect its present/absence
215 foreach (['UTF-8', 'UTF-16BE', 'WINDOWS-1252'] as $encoding) {
216 if (mb_check_encoding($title, $encoding)) {
217 return mb_convert_encoding($title, 'UTF-8', $encoding);
218 }
219 }
220
221 return $title;
222 }
223
224 /**
225 * Remove invalid UTF-8 characters from the given string.
226 *
227 * @param string $rawText
228 *
229 * @return string
230 */
231 private function sanitizeUTF8Text($rawText)
232 {
233 if (mb_check_encoding($rawText, 'UTF-8')) {
234 return $rawText;
235 }
236
237 return iconv('UTF-8', 'UTF-8//IGNORE', $rawText);
238 }
239
240 /**
180 * Stock entry with fetched or imported content. 241 * Stock entry with fetched or imported content.
181 * Will fall back to OpenGraph data if available. 242 * Will fall back to OpenGraph data if available.
182 * 243 *
@@ -185,7 +246,7 @@ class ContentProxy
185 */ 246 */
186 private function stockEntry(Entry $entry, array $content) 247 private function stockEntry(Entry $entry, array $content)
187 { 248 {
188 $entry->setUrl($content['url']); 249 $this->updateOriginUrl($entry, $content['url']);
189 250
190 $this->setEntryDomainName($entry); 251 $this->setEntryDomainName($entry);
191 252
@@ -252,6 +313,115 @@ class ContentProxy
252 } 313 }
253 314
254 /** 315 /**
316 * Update the origin_url field when a redirection occurs
317 * This field is set if it is empty and new url does not match ignore list.
318 *
319 * @param Entry $entry
320 * @param string $url
321 */
322 private function updateOriginUrl(Entry $entry, $url)
323 {
324 if (empty($url) || $entry->getUrl() === $url) {
325 return false;
326 }
327
328 $parsed_entry_url = parse_url($entry->getUrl());
329 $parsed_content_url = parse_url($url);
330
331 /**
332 * The following part computes the list of part changes between two
333 * parse_url arrays.
334 *
335 * As array_diff_assoc only computes changes to go from the left array
336 * to the right one, we make two differents arrays to have both
337 * directions. We merge these two arrays and sort keys before passing
338 * the result to the switch.
339 *
340 * The resulting array gives us all changing parts between the two
341 * urls: scheme, host, path, query and/or fragment.
342 */
343 $diff_ec = array_diff_assoc($parsed_entry_url, $parsed_content_url);
344 $diff_ce = array_diff_assoc($parsed_content_url, $parsed_entry_url);
345
346 $diff = array_merge($diff_ec, $diff_ce);
347 $diff_keys = array_keys($diff);
348 sort($diff_keys);
349
350 if ($this->ignoreUrl($entry->getUrl())) {
351 $entry->setUrl($url);
352
353 return false;
354 }
355
356 /**
357 * This switch case lets us apply different behaviors according to
358 * changing parts of urls.
359 *
360 * As $diff_keys is an array, we provide arrays as cases. ['path'] means
361 * 'only the path is different between the two urls' whereas
362 * ['fragment', 'query'] means 'only fragment and query string parts are
363 * different between the two urls'.
364 *
365 * Note that values in $diff_keys are sorted.
366 */
367 switch ($diff_keys) {
368 case ['path']:
369 if (($parsed_entry_url['path'] . '/' === $parsed_content_url['path']) // diff is trailing slash, we only replace the url of the entry
370 || ($url === urldecode($entry->getUrl()))) { // we update entry url if new url is a decoded version of it, see EntryRepository#findByUrlAndUserId
371 $entry->setUrl($url);
372 }
373 break;
374 case ['scheme']:
375 $entry->setUrl($url);
376 break;
377 case ['fragment']:
378 // noop
379 break;
380 default:
381 if (empty($entry->getOriginUrl())) {
382 $entry->setOriginUrl($entry->getUrl());
383 }
384 $entry->setUrl($url);
385 break;
386 }
387 }
388
389 /**
390 * Check entry url against an ignore list to replace with content url.
391 *
392 * XXX: move the ignore list in the database to let users handle it
393 *
394 * @param string $url url to test
395 *
396 * @return bool true if url matches ignore list otherwise false
397 */
398 private function ignoreUrl($url)
399 {
400 $ignored_hosts = ['feedproxy.google.com', 'feeds.reuters.com'];
401 $ignored_patterns = ['https?://www\.lemonde\.fr/tiny.*'];
402
403 $parsed_url = parse_url($url);
404
405 $filtered = array_filter($ignored_hosts, function ($var) use ($parsed_url) {
406 return $var === $parsed_url['host'];
407 });
408
409 if ([] !== $filtered) {
410 return true;
411 }
412
413 $filtered = array_filter($ignored_patterns, function ($var) use ($url) {
414 return preg_match("`$var`i", $url);
415 });
416
417 if ([] !== $filtered) {
418 return true;
419 }
420
421 return false;
422 }
423
424 /**
255 * Validate that the given content has at least a title, an html and a url. 425 * Validate that the given content has at least a title, an html and a url.
256 * 426 *
257 * @param array $content 427 * @param array $content
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
index c8500ad3..c6a1ff05 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
@@ -157,8 +157,8 @@ config:
157 # not_equal_to: 'Not equal to...' 157 # not_equal_to: 'Not equal to...'
158 # or: 'One rule OR another' 158 # or: 'One rule OR another'
159 # and: 'One rule AND another' 159 # and: 'One rule AND another'
160 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 160 # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
161 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' 161 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
162 162
163entry: 163entry:
164 # default_title: 'Title of the entry' 164 # default_title: 'Title of the entry'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
index 827bf770..e13987ae 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
@@ -72,9 +72,9 @@ config:
72 300_word: 'I read ~300 words per minute' 72 300_word: 'I read ~300 words per minute'
73 400_word: 'I read ~400 words per minute' 73 400_word: 'I read ~400 words per minute'
74 action_mark_as_read: 74 action_mark_as_read:
75 label: 'Where do you want to be redirected to after marking an article as read?' 75 label: 'What to do after removing, starring or marking as read an article?'
76 redirect_homepage: 'To the homepage' 76 redirect_homepage: 'Go to the homepage'
77 redirect_current_page: 'To the current page' 77 redirect_current_page: 'Stay on the current page'
78 pocket_consumer_key_label: Consumer key for Pocket to import contents 78 pocket_consumer_key_label: Consumer key for Pocket to import contents
79 android_configuration: Configure your Android application 79 android_configuration: Configure your Android application
80 android_instruction: "Touch here to prefill your Android application" 80 android_instruction: "Touch here to prefill your Android application"
@@ -157,8 +157,8 @@ config:
157 not_equal_to: 'Not equal to...' 157 not_equal_to: 'Not equal to...'
158 or: 'One rule OR another' 158 or: 'One rule OR another'
159 and: 'One rule AND another' 159 and: 'One rule AND another'
160 matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 160 matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
161 notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' 161 notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
162 162
163entry: 163entry:
164 default_title: 'Title of the entry' 164 default_title: 'Title of the entry'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
index e5878f2c..ef4b278a 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
@@ -158,7 +158,7 @@ config:
158 or: 'Una regla U otra' 158 or: 'Una regla U otra'
159 and: 'Una regla Y la otra' 159 and: 'Una regla Y la otra'
160 matches: 'Prueba si un <i>sujeto</i> corresponde a una <i>búsqueda</i> (insensible a mayusculas).<br />Ejemplo : <code>title matches "fútbol"</code>' 160 matches: 'Prueba si un <i>sujeto</i> corresponde a una <i>búsqueda</i> (insensible a mayusculas).<br />Ejemplo : <code>title matches "fútbol"</code>'
161 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' 161 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
162 162
163entry: 163entry:
164 default_title: 'Título del artículo' 164 default_title: 'Título del artículo'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
index 2e922358..a13b6668 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
@@ -157,8 +157,8 @@ config:
157 # not_equal_to: 'Not equal to...' 157 # not_equal_to: 'Not equal to...'
158 # or: 'One rule OR another' 158 # or: 'One rule OR another'
159 # and: 'One rule AND another' 159 # and: 'One rule AND another'
160 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 160 # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
161 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' 161 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
162 162
163entry: 163entry:
164 # default_title: 'Title of the entry' 164 # default_title: 'Title of the entry'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index cf5031d3..2d4d0acd 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -72,9 +72,9 @@ config:
72 300_word: "Je lis environ 300 mots par minute" 72 300_word: "Je lis environ 300 mots par minute"
73 400_word: "Je lis environ 400 mots par minute" 73 400_word: "Je lis environ 400 mots par minute"
74 action_mark_as_read: 74 action_mark_as_read:
75 label: "Où souhaitez-vous être redirigé ap¨s avoir marqué un article comme lu ?" 75 label: "Que faire lorsqu'un article est supprimé, marqué comme lu ou marqué comme favoris ?"
76 redirect_homepage: "à la page d’accueil" 76 redirect_homepage: "Retourner à la page d’accueil"
77 redirect_current_page: "À la page courante" 77 redirect_current_page: "Rester sur la page actuelle"
78 pocket_consumer_key_label: "Clé d’authentification Pocket pour importer les données" 78 pocket_consumer_key_label: "Clé d’authentification Pocket pour importer les données"
79 android_configuration: "Configurez votre application Android" 79 android_configuration: "Configurez votre application Android"
80 android_instruction: "Appuyez ici pour préremplir votre application Android" 80 android_instruction: "Appuyez ici pour préremplir votre application Android"
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
index 1563703a..e854c323 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
@@ -158,7 +158,7 @@ config:
158 or: "Una regola O un'altra" 158 or: "Una regola O un'altra"
159 and: "Una regola E un'altra" 159 and: "Una regola E un'altra"
160 matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>' 160 matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>'
161 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' 161 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
162 162
163entry: 163entry:
164 default_title: "Titolo del contenuto" 164 default_title: "Titolo del contenuto"
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
index 127b425e..db5830d2 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
@@ -158,7 +158,7 @@ config:
158 or: 'Uma regra OU outra' 158 or: 'Uma regra OU outra'
159 and: 'Uma regra E outra' 159 and: 'Uma regra E outra'
160 matches: 'Testa que um <i>assunto</i> corresponde a uma <i>pesquisa</i> (maiúscula ou minúscula).<br />Exemplo: <code>título corresponde a "futebol"</code>' 160 matches: 'Testa que um <i>assunto</i> corresponde a uma <i>pesquisa</i> (maiúscula ou minúscula).<br />Exemplo: <code>título corresponde a "futebol"</code>'
161 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' 161 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
162 162
163entry: 163entry:
164 default_title: 'Título da entrada' 164 default_title: 'Título da entrada'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
index e68a91ec..e7daf880 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
@@ -157,8 +157,8 @@ config:
157 # not_equal_to: 'Not equal to...' 157 # not_equal_to: 'Not equal to...'
158 # or: 'One rule OR another' 158 # or: 'One rule OR another'
159 # and: 'One rule AND another' 159 # and: 'One rule AND another'
160 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 160 # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
161 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' 161 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
162 162
163entry: 163entry:
164 # default_title: 'Title of the entry' 164 # default_title: 'Title of the entry'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
index c48a885f..edb1ce7c 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
@@ -157,8 +157,8 @@ config:
157 not_equal_to: 'Eşit değildir…' 157 not_equal_to: 'Eşit değildir…'
158 or: 'Bir kural veya birbaşkası' 158 or: 'Bir kural veya birbaşkası'
159 and: 'Bir kural ve diÄŸeri' 159 and: 'Bir kural ve diÄŸeri'
160 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 160 # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
161 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' 161 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
162 162
163entry: 163entry:
164 default_title: 'Makalenin başlığı' 164 default_title: 'Makalenin başlığı'
diff --git a/src/Wallabag/CoreBundle/Resources/views/base.html.twig b/src/Wallabag/CoreBundle/Resources/views/base.html.twig
index 2499bb88..aa388bcb 100644
--- a/src/Wallabag/CoreBundle/Resources/views/base.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/base.html.twig
@@ -38,6 +38,8 @@
38 38
39 <link rel="shortcut icon" type="image/x-icon" href="{{ asset('wallassets/themes/_global/img/appicon/favicon.ico') }}"> 39 <link rel="shortcut icon" type="image/x-icon" href="{{ asset('wallassets/themes/_global/img/appicon/favicon.ico') }}">
40 40
41 <link rel="manifest" href="{{ asset('manifest.json') }}">
42
41 {% block css %} 43 {% block css %}
42 {% endblock %} 44 {% endblock %}
43 {% block scripts %} 45 {% block scripts %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
index adc704bb..cfc6644b 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
@@ -57,7 +57,7 @@
57 </div> 57 </div>
58 58
59 <ul class="tools links"> 59 <ul class="tools links">
60 <li><a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.list.original_article'|trans }} : {{ entry.title|e }}"><span>{{ entry.domainName|removeWww }}</span></a></li> 60 <li><a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.list.original_article'|trans }} : {{ entry.title|e }}"><span>{{ entry.domainName|removeWww }}</span></a></li>
61 <li><a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool icon {% if entry.isArchived == 0 %}archive-off{% else %}archive{% endif %}" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">check</i><span>{{ 'entry.list.toogle_as_read'|trans }}</span></a></li> 61 <li><a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool icon {% if entry.isArchived == 0 %}archive-off{% else %}archive{% endif %}" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">check</i><span>{{ 'entry.list.toogle_as_read'|trans }}</span></a></li>
62 <li><a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool icon {% if entry.isStarred == 0 %}fav-off{% else %}fav{% endif %}" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">star_rate</i><span>{{ 'entry.list.toogle_as_star'|trans }}</span></a></li> 62 <li><a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool icon {% if entry.isStarred == 0 %}fav-off{% else %}fav{% endif %}" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">star_rate</i><span>{{ 'entry.list.toogle_as_star'|trans }}</span></a></li>
63 <li><a title="{{ 'entry.list.delete'|trans }}" class="tool icon" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">delete</i><span>{{ 'entry.list.delete'|trans }}</span></a></li> 63 <li><a title="{{ 'entry.list.delete'|trans }}" class="tool icon" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">delete</i><span>{{ 'entry.list.delete'|trans }}</span></a></li>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entry.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entry.html.twig
index d42739ac..48866f6e 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entry.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entry.html.twig
@@ -11,7 +11,7 @@
11 <div id="article_toolbar"> 11 <div id="article_toolbar">
12 <ul class="links"> 12 <ul class="links">
13 <li class="topPosF"><a href="#top" title="{{ 'entry.view.left_menu.back_to_top'|trans }}" class="tool top icon icon-arrow-up-thick"><span>{{ 'entry.view.left_menu.set_as_read'|trans }}</span></a></li> 13 <li class="topPosF"><a href="#top" title="{{ 'entry.view.left_menu.back_to_top'|trans }}" class="tool top icon icon-arrow-up-thick"><span>{{ 'entry.view.left_menu.set_as_read'|trans }}</span></a></li>
14 <li><a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e }}" class="tool link icon icon-link original"><span>{{ entry.domainName|removeWww }}</span></a></li> 14 <li><a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e }}" class="tool link icon icon-link original"><span>{{ entry.domainName|removeWww }}</span></a></li>
15 <li><a title="{{ 'entry.view.left_menu.re_fetch_content'|trans }}" class="tool icon icon-reload" href="{{ path('reload_entry', { 'id': entry.id }) }}"><span>{{ 'entry.view.left_menu.re_fetch_content'|trans }}</span></a></li> 15 <li><a title="{{ 'entry.view.left_menu.re_fetch_content'|trans }}" class="tool icon icon-reload" href="{{ path('reload_entry', { 'id': entry.id }) }}"><span>{{ 'entry.view.left_menu.re_fetch_content'|trans }}</span></a></li>
16 16
17 {% set markAsReadLabel = 'entry.view.left_menu.set_as_unread' %} 17 {% set markAsReadLabel = 'entry.view.left_menu.set_as_unread' %}
@@ -27,13 +27,13 @@
27 <li><a href="{{ path('share', {'id': entry.id }) }}" target="_blank" class="tool icon icon-eye" title="{{ 'entry.view.left_menu.public_link'|trans }}"><span>{{ 'entry.view.left_menu.public_link'|trans }}</span></a></li> 27 <li><a href="{{ path('share', {'id': entry.id }) }}" target="_blank" class="tool icon icon-eye" title="{{ 'entry.view.left_menu.public_link'|trans }}"><span>{{ 'entry.view.left_menu.public_link'|trans }}</span></a></li>
28 <li><a href="{{ path('delete_share', {'id': entry.id }) }}" class="tool icon icon-no-eye" title="{{ 'entry.view.left_menu.delete_public_link'|trans }}"><span>{{ 'entry.view.left_menu.delete_public_link'|trans }}</span></a></li> 28 <li><a href="{{ path('delete_share', {'id': entry.id }) }}" class="tool icon icon-no-eye" title="{{ 'entry.view.left_menu.delete_public_link'|trans }}"><span>{{ 'entry.view.left_menu.delete_public_link'|trans }}</span></a></li>
29 {% endif %} 29 {% endif %}
30 {% if craue_setting('share_twitter') %}<li><a href="https://twitter.com/home?status={{entry.title|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" class="tool twitter icon icon-twitter" title="Tweet"><span>Tweet</span></a></li>{% endif %} 30 {% if craue_setting('share_twitter') %}<li><a href="https://twitter.com/home?status={{entry.title|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" rel="noopener" class="tool twitter icon icon-twitter" title="Tweet"><span>Tweet</span></a></li>{% endif %}
31 {% if craue_setting('share_mail') %}<li><a href="mailto:?subject={{ entry.title|url_encode }}&amp;body={{ entry.url|url_encode }}%20via%20@wallabagapp" class="tool email icon icon-mail" title="Email"><span>Email</span></a></li>{% endif %} 31 {% if craue_setting('share_mail') %}<li><a href="mailto:?subject={{ entry.title|url_encode }}&amp;body={{ entry.url|url_encode }}%20via%20@wallabagapp" class="tool email icon icon-mail" title="Email"><span>Email</span></a></li>{% endif %}
32 {% if craue_setting('share_shaarli') %}<li><a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}&amp;tags={{ entry.tags|join(',')|url_encode }}{% if craue_setting('shaarli_share_origin_url') %}&amp;original_url={{ entry.originUrl|url_encode }}{% endif %}" target="_blank" class="tool icon-image icon-image--shaarli" title="shaarli"><span>shaarli</span></a></li>{% endif %} 32 {% if craue_setting('share_shaarli') %}<li><a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}&amp;tags={{ entry.tags|join(',')|url_encode }}{% if craue_setting('shaarli_share_origin_url') %}&amp;original_url={{ entry.originUrl|url_encode }}{% endif %}" target="_blank" rel="noopener" class="tool icon-image icon-image--shaarli" title="shaarli"><span>shaarli</span></a></li>{% endif %}
33 {% if craue_setting('share_scuttle') %}<li><a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&amp;address={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}&amp;tags={{ entry.tags|join(',')|url_encode }}" target="_blank" class="tool icon-image icon-image--scuttle" title="scuttle"><span>scuttle</span></a></li>{% endif %} 33 {% if craue_setting('share_scuttle') %}<li><a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&amp;address={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}&amp;tags={{ entry.tags|join(',')|url_encode }}" target="_blank" rel="noopener" class="tool icon-image icon-image--scuttle" title="scuttle"><span>scuttle</span></a></li>{% endif %}
34 {% if craue_setting('share_diaspora') %}<li><a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}&notes=&v=1&noui=1&jump=doclose" target="_blank" class="tool diaspora icon-image icon-image--diaspora" title="diaspora"><span>diaspora</span></a></li>{% endif %} 34 {% if craue_setting('share_diaspora') %}<li><a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}&notes=&v=1&noui=1&jump=doclose" target="_blank" rel="noopener" class="tool diaspora icon-image icon-image--diaspora" title="diaspora"><span>diaspora</span></a></li>{% endif %}
35 {% if craue_setting('share_unmark') %}<li><a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&amp;title={{entry.title|url_encode}}&amp;v=6" target="_blank" class="tool unmark icon-image icon-image--unmark" title="unmark"><span>unmark.it</span></a></li>{% endif %} 35 {% if craue_setting('share_unmark') %}<li><a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&amp;title={{entry.title|url_encode}}&amp;v=6" target="_blank" rel="noopener" class="tool unmark icon-image icon-image--unmark" title="unmark"><span>unmark.it</span></a></li>{% endif %}
36 {% if craue_setting('carrot') %}<li><a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}" class="tool carrot icon-image icon-image--carrot" target="_blank" title="carrot"><span>Carrot</span></a></li>{% endif %} 36 {% if craue_setting('carrot') %}<li><a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}" class="tool carrot icon-image icon-image--carrot" target="_blank" rel="noopener" title="carrot"><span>Carrot</span></a></li>{% endif %}
37 {% if craue_setting('show_printlink') %}<li><a title="{{ 'entry.view.left_menu.print'|trans }}" class="tool icon icon-print" href="javascript: window.print();"><span>{{ 'entry.view.left_menu.print'|trans }}</span></a></li>{% endif %} 37 {% if craue_setting('show_printlink') %}<li><a title="{{ 'entry.view.left_menu.print'|trans }}" class="tool icon icon-print" href="javascript: window.print();"><span>{{ 'entry.view.left_menu.print'|trans }}</span></a></li>{% endif %}
38 {% if craue_setting('export_epub') %}<li><a href="{{ path('export_entry', { 'id': entry.id, 'format': 'epub' }) }}" title="Generate ePub file">EPUB</a></li>{% endif %} 38 {% if craue_setting('export_epub') %}<li><a href="{{ path('export_entry', { 'id': entry.id, 'format': 'epub' }) }}" title="Generate ePub file">EPUB</a></li>{% endif %}
39 {% if craue_setting('export_mobi') %}<li><a href="{{ path('export_entry', { 'id': entry.id, 'format': 'mobi' }) }}" title="Generate Mobi file">MOBI</a></li>{% endif %} 39 {% if craue_setting('export_mobi') %}<li><a href="{{ path('export_entry', { 'id': entry.id, 'format': 'mobi' }) }}" title="Generate Mobi file">MOBI</a></li>{% endif %}
@@ -74,7 +74,7 @@
74 74
75 {% if entry.originUrl is not empty %} 75 {% if entry.originUrl is not empty %}
76 <i class="material-icons" title="{{ 'entry.view.provided_by'|trans }}">launch</i> 76 <i class="material-icons" title="{{ 'entry.view.provided_by'|trans }}">launch</i>
77 <a href="{{ entry.originUrl|e }}" target="_blank" class="tool"> 77 <a href="{{ entry.originUrl|e }}" target="_blank" rel="noopener" class="tool">
78 {{ entry.originUrl|striptags|removeSchemeAndWww|truncate(32) }} 78 {{ entry.originUrl|striptags|removeSchemeAndWww|truncate(32) }}
79 </a> 79 </a>
80 {% endif %} 80 {% endif %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig
index b9fcc005..e1c7aad9 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig
@@ -27,7 +27,7 @@
27 <body> 27 <body>
28 <header class="block"> 28 <header class="block">
29 <h1>{{ entry.title|e|raw }}</h1> 29 <h1>{{ entry.title|e|raw }}</h1>
30 <a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e|raw }}" class="tool">{{ entry.domainName|removeWww }}</a> 30 <a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e|raw }}" class="tool">{{ entry.domainName|removeWww }}</a>
31 <p class="shared-by">{{ "entry.public.shared_by_wallabag"|trans({'%wallabag_instance%': url('homepage'), '%username%': entry.user.username})|raw }}.</p> 31 <p class="shared-by">{{ "entry.public.shared_by_wallabag"|trans({'%wallabag_instance%': url('homepage'), '%username%': entry.user.username})|raw }}.</p>
32 {% if entry.previewPicture is not null %} 32 {% if entry.previewPicture is not null %}
33 <img class="preview" src="{{ entry.previewPicture }}" alt="{{ entry.title|striptags|e('html_attr') }}" /> 33 <img class="preview" src="{{ entry.previewPicture }}" alt="{{ entry.title|striptags|e('html_attr') }}" />
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/howto.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/howto.html.twig
index 231f9bdf..fbd2755a 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/howto.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/howto.html.twig
@@ -28,18 +28,18 @@
28 <div class="col s12"> 28 <div class="col s12">
29 <h5>{{ 'howto.top_menu.browser_addons'|trans }}</h5> 29 <h5>{{ 'howto.top_menu.browser_addons'|trans }}</h5>
30 <ul> 30 <ul>
31 <li><a href="{{ addonsUrl.firefox }}" target="_blank">{{ 'howto.browser_addons.firefox'|trans }}</a></li> 31 <li><a href="{{ addonsUrl.firefox }}" target="_blank" rel="noopener">{{ 'howto.browser_addons.firefox'|trans }}</a></li>
32 <li><a href="{{ addonsUrl.chrome }}" target="_blank">{{ 'howto.browser_addons.chrome'|trans }}</a></li> 32 <li><a href="{{ addonsUrl.chrome }}" target="_blank" rel="noopener">{{ 'howto.browser_addons.chrome'|trans }}</a></li>
33 <li><a href="{{ addonsUrl.opera }}" target="_blank">{{ 'howto.browser_addons.opera'|trans }}</a></li> 33 <li><a href="{{ addonsUrl.opera }}" target="_blank" rel="noopener">{{ 'howto.browser_addons.opera'|trans }}</a></li>
34 </ul> 34 </ul>
35 </div> 35 </div>
36 36
37 <div class="col s12"> 37 <div class="col s12">
38 <h5>{{ 'howto.top_menu.mobile_apps'|trans }}</h5> 38 <h5>{{ 'howto.top_menu.mobile_apps'|trans }}</h5>
39 <ul> 39 <ul>
40 <li>Android: <a href="{{ addonsUrl.f_droid }}" target="_blank">{{ 'howto.mobile_apps.android.via_f_droid'|trans }}</a> / <a href="{{ addonsUrl.google_play }}" target="_blank">{{ 'howto.mobile_apps.android.via_google_play'|trans }}</a></li> 40 <li>Android: <a href="{{ addonsUrl.f_droid }}" target="_blank" rel="noopener">{{ 'howto.mobile_apps.android.via_f_droid'|trans }}</a> / <a href="{{ addonsUrl.google_play }}" target="_blank" rel="noopener">{{ 'howto.mobile_apps.android.via_google_play'|trans }}</a></li>
41 <li>iOS: <a href="{{ addonsUrl.ios }}" target="_blank">{{ 'howto.mobile_apps.ios'|trans }}</a></li> 41 <li>iOS: <a href="{{ addonsUrl.ios }}" target="_blank">{{ 'howto.mobile_apps.ios'|trans }}</a></li>
42 <li>Windows Phone: <a href="{{ addonsUrl.windows }}" target="_blank">{{ 'howto.mobile_apps.windows'|trans }}</a></li> 42 <li>Windows Phone: <a href="{{ addonsUrl.windows }}" target="_blank" rel="noopener">{{ 'howto.mobile_apps.windows'|trans }}</a></li>
43 </ul> 43 </ul>
44 </div> 44 </div>
45 45
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_no_preview.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_no_preview.html.twig
deleted file mode 100644
index 8e6bbae0..00000000
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_no_preview.html.twig
+++ /dev/null
@@ -1,7 +0,0 @@
1<div class="card">
2 <div class="card-body">
3 {% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry} only %}
4 </div>
5
6 {% include "@WallabagCore/themes/material/Entry/_card_actions.html.twig" with {'entry': entry} only %}
7</div>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_preview.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_preview.html.twig
index e93646dc..581a1813 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_preview.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_preview.html.twig
@@ -7,7 +7,8 @@
7 {% endfor %} 7 {% endfor %}
8 </ul> 8 </ul>
9 <a href="{{ path('view', { 'id': entry.id }) }}"> 9 <a href="{{ path('view', { 'id': entry.id }) }}">
10 <span class="preview" style="background-image: url({{ entry.previewPicture }})"></span> 10 {% set previewClassModifier = entry.previewPicture ? '' : ' preview--default' %}
11 <span class="preview{{ previewClassModifier }}" style="background-image: url({{ entry.previewPicture | default(asset('wallassets/themes/_global/img/logo-square.svg')) }})"></span>
11 </a> 12 </a>
12 </div> 13 </div>
13 {% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry, 'withPreview': true} only %} 14 {% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry, 'withPreview': true} only %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
index e883503e..a137f3c3 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
@@ -39,11 +39,9 @@
39 <li id="entry-{{ entry.id|e }}" class="col {% if listMode == 0 %}l3 m6{% else %}collection-item{% endif %} s12"> 39 <li id="entry-{{ entry.id|e }}" class="col {% if listMode == 0 %}l3 m6{% else %}collection-item{% endif %} s12">
40 {% if listMode == 1 %} 40 {% if listMode == 1 %}
41 {% include "@WallabagCore/themes/material/Entry/_card_list.html.twig" with {'entry': entry} only %} 41 {% include "@WallabagCore/themes/material/Entry/_card_list.html.twig" with {'entry': entry} only %}
42 {% elseif entry.previewPicture is null %}
43 {% include "@WallabagCore/themes/material/Entry/_card_no_preview.html.twig" with {'entry': entry} only %}
44 {% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %} 42 {% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %}
45 {% include "@WallabagCore/themes/material/Entry/_card_full_image.html.twig" with {'entry': entry} only %} 43 {% include "@WallabagCore/themes/material/Entry/_card_full_image.html.twig" with {'entry': entry} only %}
46 {% elseif not entry.previewPicture is null %} 44 {% else %}
47 {% include "@WallabagCore/themes/material/Entry/_card_preview.html.twig" with {'entry': entry} only %} 45 {% include "@WallabagCore/themes/material/Entry/_card_preview.html.twig" with {'entry': entry} only %}
48 {% endif %} 46 {% endif %}
49 </li> 47 </li>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
index 7484d53b..9ae6e73e 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
@@ -46,7 +46,7 @@
46 </li> 46 </li>
47 47
48 <li class="bold border-bottom hide-on-med-and-down"> 48 <li class="bold border-bottom hide-on-med-and-down">
49 <a class="waves-effect collapsible-header original" href="{{ entry.url|e }}" target="_blank"> 49 <a class="waves-effect collapsible-header original" href="{{ entry.url|e }}" target="_blank" rel="noopener">
50 <i class="material-icons small">link</i> 50 <i class="material-icons small">link</i>
51 <span>{{ 'entry.view.left_menu.view_original_article'|trans }}</span> 51 <span>{{ 'entry.view.left_menu.view_original_article'|trans }}</span>
52 </a> 52 </a>
@@ -127,42 +127,42 @@
127 {% endif %} 127 {% endif %}
128 {% if craue_setting('share_twitter') %} 128 {% if craue_setting('share_twitter') %}
129 <li> 129 <li>
130 <a href="https://twitter.com/home?status={{entry.title|striptags|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" class="tool icon-twitter" title="twitter"> 130 <a href="https://twitter.com/home?status={{entry.title|striptags|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" rel="noopener" class="tool icon-twitter" title="twitter">
131 <span>twitter</span> 131 <span>twitter</span>
132 </a> 132 </a>
133 </li> 133 </li>
134 {% endif %} 134 {% endif %}
135 {% if craue_setting('share_shaarli') %} 135 {% if craue_setting('share_shaarli') %}
136 <li> 136 <li>
137 <a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;tags={{ entry.tags|join(',')|striptags|url_encode }}{% if craue_setting('shaarli_share_origin_url') %}&amp;original_url={{ entry.originUrl|url_encode }}{% endif %}" target="_blank" title="shaarli" class="tool icon-image shaarli"> 137 <a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;tags={{ entry.tags|join(',')|striptags|url_encode }}{% if craue_setting('shaarli_share_origin_url') %}&amp;original_url={{ entry.originUrl|url_encode }}{% endif %}" target="_blank" rel="noopener" title="shaarli" class="tool icon-image shaarli">
138 <span>shaarli</span> 138 <span>shaarli</span>
139 </a> 139 </a>
140 </li> 140 </li>
141 {% endif %} 141 {% endif %}
142 {% if craue_setting('share_scuttle') %} 142 {% if craue_setting('share_scuttle') %}
143 <li> 143 <li>
144 <a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&amp;address={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;tags={{ entry.tags|join(',')|striptags|url_encode }}" target="_blank" title="scuttle" class="tool icon-image scuttle"> 144 <a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&amp;address={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;tags={{ entry.tags|join(',')|striptags|url_encode }}" target="_blank" rel="noopener" title="scuttle" class="tool icon-image scuttle">
145 <span>scuttle</span> 145 <span>scuttle</span>
146 </a> 146 </a>
147 </li> 147 </li>
148 {% endif %} 148 {% endif %}
149 {% if craue_setting('share_diaspora') %} 149 {% if craue_setting('share_diaspora') %}
150 <li> 150 <li>
151 <a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;notes=&amp;v=1&amp;noui=1&amp;jump=doclose" target="_blank" class="tool icon-image diaspora" title="diaspora"> 151 <a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;notes=&amp;v=1&amp;noui=1&amp;jump=doclose" target="_blank" rel="noopener" class="tool icon-image diaspora" title="diaspora">
152 <span>diaspora*</span> 152 <span>diaspora*</span>
153 </a> 153 </a>
154 </li> 154 </li>
155 {% endif %} 155 {% endif %}
156 {% if craue_setting('share_unmark') %} 156 {% if craue_setting('share_unmark') %}
157 <li> 157 <li>
158 <a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&amp;title={{entry.title|striptags|url_encode}}&amp;v=6" target="_blank" class="tool icon-image unmark" title="unmark"> 158 <a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&amp;title={{entry.title|striptags|url_encode}}&amp;v=6" target="_blank" rel="noopener" class="tool icon-image unmark" title="unmark">
159 <span>unmark.it</span> 159 <span>unmark.it</span>
160 </a> 160 </a>
161 </li> 161 </li>
162 {% endif %} 162 {% endif %}
163 {% if craue_setting('carrot') %} 163 {% if craue_setting('carrot') %}
164 <li> 164 <li>
165 <a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}" target="_blank" title="carrot" class="tool icon-image carrot"> 165 <a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}" target="_blank" rel="noopener" title="carrot" class="tool icon-image carrot">
166 <span>Carrot</span> 166 <span>Carrot</span>
167 </a> 167 </a>
168 </li> 168 </li>
@@ -251,7 +251,7 @@
251 {% endif %} 251 {% endif %}
252 <li> 252 <li>
253 <i class="material-icons link">link</i> 253 <i class="material-icons link">link</i>
254 <a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|striptags }}" class="tool"> 254 <a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|striptags }}" class="tool">
255 {{ entry.domainName|removeWww }} 255 {{ entry.domainName|removeWww }}
256 </a> 256 </a>
257 </li> 257 </li>
@@ -262,7 +262,7 @@
262 {% if entry.originUrl is not empty %} 262 {% if entry.originUrl is not empty %}
263 <li> 263 <li>
264 <i class="material-icons" title="{{ 'entry.view.provided_by'|trans }}">launch</i> 264 <i class="material-icons" title="{{ 'entry.view.provided_by'|trans }}">launch</i>
265 <a href="{{ entry.originUrl|e }}" target="_blank" class="tool"> 265 <a href="{{ entry.originUrl|e }}" target="_blank" rel="noopener" class="tool">
266 {{ entry.originUrl|striptags|removeSchemeAndWww|truncate(32) }} 266 {{ entry.originUrl|striptags|removeSchemeAndWww|truncate(32) }}
267 </a> 267 </a>
268 </li> 268 </li>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig
index f0012ad9..052a8c01 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig
@@ -143,7 +143,7 @@
143 </div> 143 </div>
144 <div class="col s12 l4"> 144 <div class="col s12 l4">
145 <p class="footer-text"> 145 <p class="footer-text">
146 {{ 'footer.wallabag.powered_by'|trans }} <a target="_blank" href="https://wallabag.org" class="grey-text text-lighten-4">wallabag</a> – 146 {{ 'footer.wallabag.powered_by'|trans }} <a target="_blank" rel="noopener" href="https://wallabag.org" class="grey-text text-lighten-4">wallabag</a> –
147 <a class="grey-text text-lighten-4" href="{{ path('about') }}">{{ 'footer.wallabag.about'|trans|lower }}</a> 147 <a class="grey-text text-lighten-4" href="{{ path('about') }}">{{ 'footer.wallabag.about'|trans|lower }}</a>
148 </p> 148 </p>
149 </div> 149 </div>