summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar papaschloss <11808509+papaschloss@users.noreply.github.com> 2022-08-15 12:01:18 -0700
committerGravatar GitHub <noreply@github.com> 2022-08-15 21:01:18 +0200
commit8587efa62189a30e3e47075739382d52ecc34cb6 (patch)
tree66414eb134f8b07a367122e5b6286aa5c9b59edd
parent839fddaba9bc72e542eff2ab8e4a9618c86804e1 (diff)
Article css filtering (#4501)
* Update feedController.php * Update subscriptionController.php * Update DatabaseDAO.php * Update Entry.php * Update Feed.php * Update FeedDAO.php * Update install.sql.mysql.php * Update install.sql.pgsql.php * Update install.sql.sqlite.php * Update sub.php * Update opml.phtml * Update ImportService.php * Update update.phtml * Update feed.js * Update install.sql.mysql.php * Update install.sql.pgsql.php * Update install.sql.sqlite.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update sub.php * Update FeedDAO.php * Update feedController.php * Update subscriptionController.php * Update Entry.php * Update Feed.php * Update feedController.php * Update subscriptionController.php * Update ImportService.php * Update opml.phtml * Update update.phtml * Update update.phtml * Update update.phtml * Update DatabaseDAO.php * Update app/Models/Entry.php Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr> * Update app/i18n/fr/sub.php Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr> * Update p/scripts/feed.js Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr> * Update app/Controllers/feedController.php * make fix-all * Update documentation * css_path_filter help message * i18n en-us ignore Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
-rwxr-xr-xapp/Controllers/feedController.php5
-rw-r--r--app/Controllers/subscriptionController.php2
-rw-r--r--app/Models/Entry.php6
-rw-r--r--app/Services/ImportService.php1
-rw-r--r--app/i18n/cz/sub.php4
-rw-r--r--app/i18n/de/sub.php4
-rw-r--r--app/i18n/en-us/sub.php4
-rw-r--r--app/i18n/en/sub.php4
-rwxr-xr-xapp/i18n/es/sub.php4
-rw-r--r--app/i18n/fr/sub.php4
-rw-r--r--app/i18n/he/sub.php4
-rw-r--r--app/i18n/it/sub.php4
-rw-r--r--app/i18n/ja/sub.php4
-rw-r--r--app/i18n/ko/sub.php4
-rw-r--r--app/i18n/nl/sub.php4
-rw-r--r--app/i18n/oc/sub.php4
-rw-r--r--app/i18n/pl/sub.php4
-rw-r--r--app/i18n/pt-br/sub.php4
-rw-r--r--app/i18n/ru/sub.php4
-rw-r--r--app/i18n/sk/sub.php4
-rw-r--r--app/i18n/tr/sub.php4
-rw-r--r--app/i18n/zh-cn/sub.php4
-rw-r--r--app/views/helpers/export/opml.phtml3
-rw-r--r--app/views/helpers/feed/update.phtml16
-rw-r--r--docs/en/developers/OPML.md4
-rw-r--r--p/scripts/feed.js4
26 files changed, 109 insertions, 4 deletions
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php
index 31875fa56..c016d3584 100755
--- a/app/Controllers/feedController.php
+++ b/app/Controllers/feedController.php
@@ -916,12 +916,15 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
return;
}
+ $attributes = $feed->attributes();
+ $attributes['path_entries_filter'] = trim(Minz_Request::param('selector_filter', ''));
+
//Fetch & select content.
try {
$fullContent = FreshRSS_Entry::getContentByParsing(
htmlspecialchars_decode($entry->link(), ENT_QUOTES),
$content_selector,
- $feed->attributes()
+ $attributes
);
if ($fullContent != '') {
diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php
index b699e9213..9e4eab8e2 100644
--- a/app/Controllers/subscriptionController.php
+++ b/app/Controllers/subscriptionController.php
@@ -209,6 +209,8 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController {
}
}
+ $feed->_attributes('path_entries_filter', Minz_Request::param('path_entries_filter', ''));
+
$values = array(
'name' => Minz_Request::param('name', ''),
'kind' => $feed->kind(),
diff --git a/app/Models/Entry.php b/app/Models/Entry.php
index 0be353c28..d20f5f2a7 100644
--- a/app/Models/Entry.php
+++ b/app/Models/Entry.php
@@ -558,6 +558,12 @@ class FreshRSS_Entry extends Minz_Model {
$nodes = $xpath->query(new Gt\CssXPath\Translator($path));
if ($nodes != false) {
foreach ($nodes as $node) {
+ if (!empty($attributes['path_entries_filter'])) {
+ $filterednodes = $xpath->query(new Gt\CssXPath\Translator($attributes['path_entries_filter']), $node);
+ foreach ($filterednodes as $filterednode) {
+ $filterednode->parentNode->removeChild($filterednode);
+ }
+ }
$content .= $doc->saveHtml($node) . "\n";
}
}
diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php
index 3fde32bb0..e09da1f15 100644
--- a/app/Services/ImportService.php
+++ b/app/Services/ImportService.php
@@ -169,6 +169,7 @@ class FreshRSS_Import_Service {
if (is_array($value) && !empty($value['value']) && ($value['namespace'] ?? '') === FreshRSS_Export_Service::FRSS_NAMESPACE) {
switch ($key) {
case 'cssFullContent': $feed->_pathEntries($value['value']); break;
+ case 'cssFullContentFilter': $feed->_attributes('path_entries_filter', $value['value']); break;
case 'filtersActionRead': $feed->_filtersAction('read', preg_split('/[\n\r]+/', $value['value'])); break;
case 'xPathItem': $xPathSettings['item'] = $value['value']; break;
case 'xPathItemTitle': $xPathSettings['itemTitle'] = $value['value']; break;
diff --git a/app/i18n/cz/sub.php b/app/i18n/cz/sub.php
index 045479d8d..7867055c7 100644
--- a/app/i18n/cz/sub.php
+++ b/app/i18n/cz/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Příklad: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Načte oříznuté kanály RSS (pozor, náročnější na čas!)',
'css_path' => 'Přepínač CSS článku na původních webových stránkách',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Popis',
'empty' => 'Tento kanál je prázdný. Ověřte prosím, zda je stále udržován.',
'error' => 'Vyskytl se problém s kanálem. Ověřte prosím, že je vždy dostupný, pak ho aktualizujte.',
diff --git a/app/i18n/de/sub.php b/app/i18n/de/sub.php
index c0d1e3d04..ff4f11ca3 100644
--- a/app/i18n/de/sub.php
+++ b/app/i18n/de/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Beispiel: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Ruft bei gekürzten RSS-Feeds den vollständigen Artikelinhalt ab (Achtung, benötigt mehr Zeit!)',
'css_path' => 'CSS-Selektor des Artikelinhaltes auf der Original-Webseite',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Beschreibung',
'empty' => 'Dieser Feed ist leer. Bitte stellen Sie sicher, dass er noch gepflegt wird.',
'error' => 'Dieser Feed ist auf ein Problem gestoßen. Bitte stellen Sie sicher, dass er immer lesbar ist und aktualisieren Sie ihn dann.',
diff --git a/app/i18n/en-us/sub.php b/app/i18n/en-us/sub.php
index 7006ff659..de5fd9340 100644
--- a/app/i18n/en-us/sub.php
+++ b/app/i18n/en-us/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>', // IGNORE
'css_help' => 'Retrieves truncated RSS feeds (caution, requires more time!)', // IGNORE
'css_path' => 'Article CSS selector on original website', // IGNORE
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // IGNORE
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // IGNORE
+ ),
'description' => 'Description', // IGNORE
'empty' => 'This feed is empty. Please verify that it is still maintained.', // IGNORE
'error' => 'This feed has encountered a problem. Please verify that it is always reachable then update it.', // IGNORE
diff --git a/app/i18n/en/sub.php b/app/i18n/en/sub.php
index a8bb995a2..9cc9c61bf 100644
--- a/app/i18n/en/sub.php
+++ b/app/i18n/en/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Retrieves truncated RSS feeds (caution, requires more time!)',
'css_path' => 'Article CSS selector on original website',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove',
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Description',
'empty' => 'This feed is empty. Please verify that it is still maintained.',
'error' => 'This feed has encountered a problem. Please verify that it is always reachable then update it.',
diff --git a/app/i18n/es/sub.php b/app/i18n/es/sub.php
index 2302914cc..90e853f9a 100755
--- a/app/i18n/es/sub.php
+++ b/app/i18n/es/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Ejemplo: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Recibir fuentes RSS truncadas (aviso, ¡necesita más tiempo!)',
'css_path' => 'Ruta a la CSS de los artículos en la web original',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Descripción',
'empty' => 'La fuente está vacía. Por favor, verifica que siga activa.',
'error' => 'Hay un problema con esta fuente. Por favor, veritica que esté disponible y prueba de nuevo.',
diff --git a/app/i18n/fr/sub.php b/app/i18n/fr/sub.php
index 90ece987b..379bd6296 100644
--- a/app/i18n/fr/sub.php
+++ b/app/i18n/fr/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Exemple : <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Permet de récupérer les flux tronqués (attention, demande plus de temps !)',
'css_path' => 'Sélecteur CSS des articles sur le site d’origine',
+ 'css_path_filter' => array(
+ '_' => 'Sélecteur CSS des éléments à supprimer',
+ 'help' => 'Un sélecteur CSS peut être une liste comme : <kbd>.footer, .aside</kbd>',
+ ),
'description' => 'Description', // IGNORE
'empty' => 'Ce flux est vide. Veuillez vérifier qu’il est toujours maintenu.',
'error' => 'Ce flux a rencontré un problème. Veuillez vérifier qu’il est toujours accessible puis actualisez-le.',
diff --git a/app/i18n/he/sub.php b/app/i18n/he/sub.php
index c024bb6f4..bcb540e6b 100644
--- a/app/i18n/he/sub.php
+++ b/app/i18n/he/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>', // TODO
'css_help' => 'קבלת הזנות RSS קטומות (זהירות, לוקח זמן רב יותר!)',
'css_path' => 'נתיב הCSS של המאמר באתר המקורי',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'תיאור',
'empty' => 'הזנה זו ריקה. אנא ודאו שהיא עדיין מתוחזקת.',
'error' => 'הזנה זו נתקלה בשגיאה, אנא ודאו שהיא תקינה ואז נסו שנית.',
diff --git a/app/i18n/it/sub.php b/app/i18n/it/sub.php
index e76037f98..1a3875892 100644
--- a/app/i18n/it/sub.php
+++ b/app/i18n/it/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>', // TODO
'css_help' => 'In caso di RSS feeds troncati (attenzione, richiede molto tempo!)',
'css_path' => 'Percorso del foglio di stile CSS del sito di origine',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Descrizione',
'empty' => 'Questo feed non contiene articoli. Per favore verifica il sito direttamente.',
'error' => 'Questo feed ha generato un errore. Per favore verifica se ancora disponibile.',
diff --git a/app/i18n/ja/sub.php b/app/i18n/ja/sub.php
index 46c5e6a30..6ea8fc375 100644
--- a/app/i18n/ja/sub.php
+++ b/app/i18n/ja/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => '例: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'あきらめられたRSSフィードを取得します (注意してください、より多くの時間が必要になるでしょう!)',
'css_path' => '元のwebサイトの記事のCSS',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => '説明',
'empty' => 'このフィードは空です。運営されているかどうかを確認してみてください。',
'error' => 'このフィードに問題が発生しました。ここにいつでもアクセスできるかどうかを確認して更新してみてください。',
diff --git a/app/i18n/ko/sub.php b/app/i18n/ko/sub.php
index b865fe4db..77e72aa0f 100644
--- a/app/i18n/ko/sub.php
+++ b/app/i18n/ko/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => '예시: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => '글의 일부가 포함된 RSS 피드를 가져옵니다 (주의, 시간이 좀 더 걸립니다!)',
'css_path' => '웹사이트 상의 글 본문에 해당하는 CSS 경로',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => '설명',
'empty' => '이 피드는 비어있습니다. 피드가 계속 운영되고 있는지 확인하세요.',
'error' => '이 피드에 문제가 발생했습니다. 이 피드에 접근 권한이 있는지 확인하세요.',
diff --git a/app/i18n/nl/sub.php b/app/i18n/nl/sub.php
index 031f671a2..b5442ea0e 100644
--- a/app/i18n/nl/sub.php
+++ b/app/i18n/nl/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Voorbeeld: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Haalt onvolledige RSS-feeds op (attentie, heeft meer tijd nodig!)',
'css_path' => 'CSS-pad van artikelen op originele website',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Omschrijving',
'empty' => 'Deze feed is leeg. Controleer of deze nog actueel is.',
'error' => 'Deze feed heeft problemen. Verifieer a.u.b het doeladres en actualiseer het.',
diff --git a/app/i18n/oc/sub.php b/app/i18n/oc/sub.php
index d3f341269..68f9e1f88 100644
--- a/app/i18n/oc/sub.php
+++ b/app/i18n/oc/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Exemple : <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Permet de recuperar los fluxes troncats (atencion, demanda mai de temps !)',
'css_path' => 'Selector CSS dels articles sul site d’origina',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Descripcion', // IGNORE
'empty' => 'Aqueste flux es void. Assegurats-vos qu’es totjorn mantengut.',
'error' => 'Aqueste flux a rescontrat un problèma. Volgatz verificar que siá totjorn accessible puèi actualizatz-lo.',
diff --git a/app/i18n/pl/sub.php b/app/i18n/pl/sub.php
index 22cdcd170..07cc07286 100644
--- a/app/i18n/pl/sub.php
+++ b/app/i18n/pl/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Przykład: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Pozwala na ograniczenie zawartości kanałów (uwaga, wymaga więcej czasu!)',
'css_path' => 'Selektor CSS dla wiadomości na pierwotnej stronie',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Opis',
'empty' => 'Ten kanał jest pusty. Należy sprawdzić czy kanał w dalszym ciągu działa.',
'error' => 'Napotkano problem podczas dostępu do tego kanału. Należy sprawdzić czy kanał jest zawsze dostępny, a następnie go odświeżyć.',
diff --git a/app/i18n/pt-br/sub.php b/app/i18n/pt-br/sub.php
index 451ae5445..87b9b635b 100644
--- a/app/i18n/pt-br/sub.php
+++ b/app/i18n/pt-br/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Exemplo: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Retorna RSS feeds truncados (atenção, requer mais tempo!)',
'css_path' => 'Caminho do CSS do artigo no site original',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Descrição',
'empty' => 'Este feed está vazio. Por favor verifique ele ainda é mantido.',
'error' => 'Este feed encontra-se com problema. Por favor verifique se ele ainda está disponível e atualize-o.',
diff --git a/app/i18n/ru/sub.php b/app/i18n/ru/sub.php
index f5cdf7445..dc0cf8eda 100644
--- a/app/i18n/ru/sub.php
+++ b/app/i18n/ru/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Пример: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Получает усечённые RSS-ленты (осторожно, требует больше времени!)',
'css_path' => 'CSS селектор статьи на сайте',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Описание',
'empty' => 'Лента пустая. Пожалуйста, убедитесь, что её до сих пор обслуживают.',
'error' => 'С этой лентой возникла проблема. Пожалуйста, убедитесь, что она всегда досягаема. Затем снова обновите её.',
diff --git a/app/i18n/sk/sub.php b/app/i18n/sk/sub.php
index e4aed5516..6660ff573 100644
--- a/app/i18n/sk/sub.php
+++ b/app/i18n/sk/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Príklad: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Stiahnuť skrátenú verziu RSS kanála (pozor, vyžaduje viac času!)',
'css_path' => 'Pôvodný CSS súbor článku z webovej stránky',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Popis',
'empty' => 'Tento kanál je prázdny. Overte, prosím, či je ešte spravovaný autorom.',
'error' => 'Vyskytol sa problém s týmto kanálom. Overte, prosím, či kanál stále existuje, potom ho obnovte.',
diff --git a/app/i18n/tr/sub.php b/app/i18n/tr/sub.php
index 40a233ecb..34169aac3 100644
--- a/app/i18n/tr/sub.php
+++ b/app/i18n/tr/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => 'Örnek: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => 'Dikkat, daha çok zaman gerekir!',
'css_path' => 'Makaleleri kendi CSS görünümü ile göster',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => 'Tanım',
'empty' => 'Bu akış boş. Lütfen akışın aktif olduğuna emin olun.',
'error' => 'Bu akışda bir hatayla karşılaşıldı. Lütfen akışın sürekli ulaşılabilir olduğuna emin olun.',
diff --git a/app/i18n/zh-cn/sub.php b/app/i18n/zh-cn/sub.php
index aa88636fd..7ede19a3d 100644
--- a/app/i18n/zh-cn/sub.php
+++ b/app/i18n/zh-cn/sub.php
@@ -57,6 +57,10 @@ return array(
'css_cookie_help' => '例:<kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
'css_help' => '用于获取全文(注意,这将耗费更多时间!)',
'css_path' => '原文的 CSS 选择器',
+ 'css_path_filter' => array(
+ '_' => 'CSS selector of the elements to remove', // TODO
+ 'help' => 'A CSS selector may be a list such as: <kbd>.footer, .aside</kbd>', // TODO
+ ),
'description' => '描述',
'empty' => '此源为空。请确认它是否正常更新。',
'error' => '此源遇到一些问题。请在确认是否能正常访问后重试。',
diff --git a/app/views/helpers/export/opml.phtml b/app/views/helpers/export/opml.phtml
index f99754138..c401b05bd 100644
--- a/app/views/helpers/export/opml.phtml
+++ b/app/views/helpers/export/opml.phtml
@@ -40,6 +40,9 @@ function feedsToOutlines($feeds, $excludeMutedFeeds = false): array {
if ($feed->pathEntries() != '') {
$outline['frss:cssFullContent'] = ['namespace' => FreshRSS_Export_Service::FRSS_NAMESPACE, 'value' => $feed->pathEntries()];
}
+ if ($feed->attributes('path_entries_filter') != '') {
+ $outline['frss:cssFullContentFilter'] = ['namespace' => FreshRSS_Export_Service::FRSS_NAMESPACE, 'value' => $feed->attributes('path_entries_filter')];
+ }
$outlines[] = $outline;
}
return $outlines;
diff --git a/app/views/helpers/feed/update.phtml b/app/views/helpers/feed/update.phtml
index 1e9e9afd2..0e4a34a76 100644
--- a/app/views/helpers/feed/update.phtml
+++ b/app/views/helpers/feed/update.phtml
@@ -491,13 +491,27 @@
<input type="text" name="path_entries" id="path_entries" class="w100" value="<?= $this->feed->pathEntries() ?>"
data-leave-validation="<?= $this->feed->pathEntries() ?>" placeholder="<?= _t('gen.short.blank_to_disable') ?>" />
<a id="popup-preview-selector" class="btn" href="<?=
- _url('feed', 'contentSelectorPreview', 'id', $this->feed->id(), 'selector', 'selector-token', '#', 'slider') ?>"><?= _i('look') ?></a>
+ _url('feed', 'contentSelectorPreview', 'id', $this->feed->id(), 'selector', 'selector-token', 'selector_filter', 'selector-filter-token', '#', 'slider') ?>"><?= _i('look') ?></a>
</div>
<p class="help"><?= _i('help') ?> <?= _t('sub.feed.css_help') ?></p>
</div>
</div>
<div class="form-group">
+ <?php
+ $path_entries_filter = Minz_Helper::htmlspecialchars_utf8($this->feed->attributes('path_entries_filter'));
+ ?>
+ <label class="group-name" for="path_entries_filter"><?= _t('sub.feed.css_path_filter') ?></label>
+ <div class="group-controls">
+ <div class="stick w100">
+ <input type="text" name="path_entries_filter" id="path_entries_filter" class="w100" value="<?= $path_entries_filter ?>"
+ data-leave-validation="<?= $path_entries_filter ?>" placeholder="<?= _t('gen.short.blank_to_disable') ?>" />
+ </div>
+ <p class="help"><?= _i('help') ?> <?= _t('sub.feed.css_path_filter.help') ?></p>
+ </div>
+ </div>
+
+ <div class="form-group">
<label class="group-name" for="curl_params_cookie"><?= _t('sub.feed.css_cookie') ?></label>
<div class="group-controls">
<input type="text" name="curl_params_cookie" id="curl_params_cookie" class="w100" value="<?=
diff --git a/docs/en/developers/OPML.md b/docs/en/developers/OPML.md
index 3014dc457..9daa94b20 100644
--- a/docs/en/developers/OPML.md
+++ b/docs/en/developers/OPML.md
@@ -43,7 +43,9 @@ The following attributes are using similar naming conventions than [RSS-Bridge](
### Miscellaneous
* `frss:cssFullContent`: [CSS Selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) to enable the download and extraction of the matching HTML section of each articles’ Web address.
- * Example: `div.main`
+ * Example: `div.main, .summary`
+* `frss:cssFullContentFilter`: [CSS Selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) to remove the matching HTML elements from the full content retrieved by `frss:cssFullContent`.
+ * Example: `.footer, .aside`
* `frss:filtersActionRead`: List (separated by a new line) of search queries to automatically mark a new article as read.
### Dynamic OPML (reading lists)
diff --git a/p/scripts/feed.js b/p/scripts/feed.js
index a5e43c614..1a6833db6 100644
--- a/p/scripts/feed.js
+++ b/p/scripts/feed.js
@@ -56,7 +56,9 @@ function init_popup_preview_selector() {
link.addEventListener('click', function (ev) {
const selector_entries = document.getElementById('path_entries').value;
- const href = link.href.replace('selector-token', encodeURIComponent(selector_entries));
+ const selector_entries_filter = document.getElementById('path_entries_filter').value;
+ const href = link.href.replace('selector-token', encodeURIComponent(selector_entries))
+ .replace('selector-filter-token', encodeURIComponent(selector_entries_filter));
openPopupWithSource(href);