diff options
| -rwxr-xr-x | app/Controllers/feedController.php | 1 | ||||
| -rw-r--r-- | app/Controllers/subscriptionController.php | 1 | ||||
| -rw-r--r-- | app/Models/Feed.php | 9 | ||||
| -rw-r--r-- | app/Services/ImportService.php | 1 | ||||
| -rw-r--r-- | app/i18n/cz/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/de/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/en-us/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/en/sub.php | 6 | ||||
| -rwxr-xr-x | app/i18n/es/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/fr/sub.php | 4 | ||||
| -rw-r--r-- | app/i18n/he/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/it/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/ja/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/ko/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/nl/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/oc/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/pl/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/pt-br/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/ru/sub.php | 4 | ||||
| -rw-r--r-- | app/i18n/sk/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/tr/sub.php | 6 | ||||
| -rw-r--r-- | app/i18n/zh-cn/sub.php | 4 | ||||
| -rw-r--r-- | app/views/helpers/export/opml.phtml | 1 | ||||
| -rw-r--r-- | app/views/helpers/feed/update.phtml | 8 | ||||
| -rw-r--r-- | app/views/subscription/add.phtml | 7 | ||||
| -rw-r--r-- | docs/en/developers/OPML.md | 1 |
26 files changed, 115 insertions, 16 deletions
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index c016d3584..95bca33eb 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -198,6 +198,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController { if (Minz_Request::param('xPathItemTimestamp', '') != '') $xPathSettings['itemTimestamp'] = Minz_Request::param('xPathItemTimestamp', '', true); if (Minz_Request::param('xPathItemThumbnail', '') != '') $xPathSettings['itemThumbnail'] = Minz_Request::param('xPathItemThumbnail', '', true); if (Minz_Request::param('xPathItemCategories', '') != '') $xPathSettings['itemCategories'] = Minz_Request::param('xPathItemCategories', '', true); + if (Minz_Request::param('xPathItemUid', '') != '') $xPathSettings['itemUid'] = Minz_Request::param('xPathItemUid', '', true); if (!empty($xPathSettings)) { $attributes['xpath'] = $xPathSettings; } diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index 9e4eab8e2..bbefc2d68 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -204,6 +204,7 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController { if (Minz_Request::param('xPathItemTimestamp', '') != '') $xPathSettings['itemTimestamp'] = Minz_Request::param('xPathItemTimestamp', '', true); if (Minz_Request::param('xPathItemThumbnail', '') != '') $xPathSettings['itemThumbnail'] = Minz_Request::param('xPathItemThumbnail', '', true); if (Minz_Request::param('xPathItemCategories', '') != '') $xPathSettings['itemCategories'] = Minz_Request::param('xPathItemCategories', '', true); + if (Minz_Request::param('xPathItemUid', '') != '') $xPathSettings['itemUid'] = Minz_Request::param('xPathItemUid', '', true); if (!empty($xPathSettings)) { $feed->_attributes('xpath', $xPathSettings); } diff --git a/app/Models/Feed.php b/app/Models/Feed.php index 4de61167b..710f8b557 100644 --- a/app/Models/Feed.php +++ b/app/Models/Feed.php @@ -611,6 +611,7 @@ class FreshRSS_Feed extends Minz_Model { $xPathItemTimestamp = $xPathSettings['itemTimestamp'] ?? ''; $xPathItemThumbnail = $xPathSettings['itemThumbnail'] ?? ''; $xPathItemCategories = $xPathSettings['itemCategories'] ?? ''; + $xPathItemUid = $xPathSettings['itemUid'] ?? ''; if ($xPathItem == '') { return null; } @@ -657,8 +658,14 @@ class FreshRSS_Feed extends Minz_Model { } } } - if ($item['title'] . $item['content'] . $item['link'] != '') { + if ($xPathItemUid != '') { + $item['guid'] = @$xpath->evaluate('normalize-space(' . $xPathItemUid . ')', $node); + } + if (empty($item['guid'])) { $item['guid'] = 'urn:sha1:' . sha1($item['title'] . $item['content'] . $item['link']); + } + + if ($item['title'] . $item['content'] . $item['link'] != '') { $item = Minz_Helper::htmlspecialchars_utf8($item); $view->entries[] = FreshRSS_Entry::fromArray($item); } diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php index e09da1f15..780dcbd07 100644 --- a/app/Services/ImportService.php +++ b/app/Services/ImportService.php @@ -179,6 +179,7 @@ class FreshRSS_Import_Service { case 'xPathItemTimestamp': $xPathSettings['itemTimestamp'] = $value['value']; break; case 'xPathItemThumbnail': $xPathSettings['itemThumbnail'] = $value['value']; break; case 'xPathItemCategories': $xPathSettings['itemCategories'] = $value['value']; break; + case 'xPathItemUid': $xPathSettings['itemUid'] = $value['value']; break; } } } diff --git a/app/i18n/cz/sub.php b/app/i18n/cz/sub.php index 7867055c7..6cacf3e8b 100644 --- a/app/i18n/cz/sub.php +++ b/app/i18n/cz/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/de/sub.php b/app/i18n/de/sub.php index ff4f11ca3..c8a0c7961 100644 --- a/app/i18n/de/sub.php +++ b/app/i18n/de/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/en-us/sub.php b/app/i18n/en-us/sub.php index de5fd9340..648fdec9a 100644 --- a/app/i18n/en-us/sub.php +++ b/app/i18n/en-us/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // IGNORE 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // IGNORE ), - 'item_categories' => 'items tags', // IGNORE + 'item_categories' => 'item tags', // IGNORE 'item_content' => array( '_' => 'item content', // IGNORE 'help' => 'Example to take the full item: <code>.</code>', // IGNORE @@ -104,6 +104,10 @@ return array( '_' => 'item title', // IGNORE 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // IGNORE ), + 'item_uid' => array( + '_' => 'item unique ID', // IGNORE + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // IGNORE 'help' => 'Example: <code>descendant::a/@href</code>', // IGNORE diff --git a/app/i18n/en/sub.php b/app/i18n/en/sub.php index 9cc9c61bf..202d89b3c 100644 --- a/app/i18n/en/sub.php +++ b/app/i18n/en/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', ), - 'item_categories' => 'items tags', + 'item_categories' => 'item tags', 'item_content' => array( '_' => 'item content', 'help' => 'Example to take the full item: <code>.</code>', @@ -104,6 +104,10 @@ return array( '_' => 'item title', 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', 'help' => 'Example: <code>descendant::a/@href</code>', diff --git a/app/i18n/es/sub.php b/app/i18n/es/sub.php index 90e853f9a..dcf72697f 100755 --- a/app/i18n/es/sub.php +++ b/app/i18n/es/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/fr/sub.php b/app/i18n/fr/sub.php index 379bd6296..3faf379c2 100644 --- a/app/i18n/fr/sub.php +++ b/app/i18n/fr/sub.php @@ -104,6 +104,10 @@ return array( '_' => 'titre de l’article', 'help' => 'Utiliser en particulier l’<a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">axe XPath</a> <code>descendant::</code> comme <code>descendant::h2</code>', ), + 'item_uid' => array( + '_' => 'identifiant unique de l’article', + 'help' => 'Optionnel. Exemple : <code>descendant::div/@data-uri</code>', + ), 'item_uri' => array( '_' => 'lien (URL) de l’article', 'help' => 'Exemple : <code>descendant::a/@href</code>', diff --git a/app/i18n/he/sub.php b/app/i18n/he/sub.php index bcb540e6b..0d9f2ea96 100644 --- a/app/i18n/he/sub.php +++ b/app/i18n/he/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/it/sub.php b/app/i18n/it/sub.php index 1a3875892..c9f4823f0 100644 --- a/app/i18n/it/sub.php +++ b/app/i18n/it/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/ja/sub.php b/app/i18n/ja/sub.php index 6ea8fc375..9973e5bec 100644 --- a/app/i18n/ja/sub.php +++ b/app/i18n/ja/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/ko/sub.php b/app/i18n/ko/sub.php index 77e72aa0f..edb97842b 100644 --- a/app/i18n/ko/sub.php +++ b/app/i18n/ko/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/nl/sub.php b/app/i18n/nl/sub.php index b5442ea0e..b8585bcbb 100644 --- a/app/i18n/nl/sub.php +++ b/app/i18n/nl/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/oc/sub.php b/app/i18n/oc/sub.php index 68f9e1f88..28b0de33b 100644 --- a/app/i18n/oc/sub.php +++ b/app/i18n/oc/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/pl/sub.php b/app/i18n/pl/sub.php index 07cc07286..603fe8f4a 100644 --- a/app/i18n/pl/sub.php +++ b/app/i18n/pl/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/pt-br/sub.php b/app/i18n/pt-br/sub.php index 87b9b635b..82ae085ef 100644 --- a/app/i18n/pt-br/sub.php +++ b/app/i18n/pt-br/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/ru/sub.php b/app/i18n/ru/sub.php index dc0cf8eda..9bc64f05d 100644 --- a/app/i18n/ru/sub.php +++ b/app/i18n/ru/sub.php @@ -104,6 +104,10 @@ return array( '_' => 'заголовка элемента', 'help' => 'Используйте, в частности, <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">ось XPath</a> <code>descendant::</code>, наподобие <code>descendant::h2</code>', ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'ссылки элемента (URL)', 'help' => 'Пример: <code>descendant::a/@href</code>', diff --git a/app/i18n/sk/sub.php b/app/i18n/sk/sub.php index 6660ff573..58999e5f3 100644 --- a/app/i18n/sk/sub.php +++ b/app/i18n/sk/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/tr/sub.php b/app/i18n/tr/sub.php index 34169aac3..e0af10d12 100644 --- a/app/i18n/tr/sub.php +++ b/app/i18n/tr/sub.php @@ -87,7 +87,7 @@ return array( '_' => 'item author', // TODO 'help' => 'Can also be a static string. Example: <code>"Anonymous"</code>', // TODO ), - 'item_categories' => 'items tags', // TODO + 'item_categories' => 'item tags', // TODO 'item_content' => array( '_' => 'item content', // TODO 'help' => 'Example to take the full item: <code>.</code>', // TODO @@ -104,6 +104,10 @@ return array( '_' => 'item title', // TODO 'help' => 'Use in particular the <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath axis</a> <code>descendant::</code> like <code>descendant::h2</code>', // TODO ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => 'item link (URL)', // TODO 'help' => 'Example: <code>descendant::a/@href</code>', // TODO diff --git a/app/i18n/zh-cn/sub.php b/app/i18n/zh-cn/sub.php index 7ede19a3d..10211b99e 100644 --- a/app/i18n/zh-cn/sub.php +++ b/app/i18n/zh-cn/sub.php @@ -104,6 +104,10 @@ return array( '_' => '文章标题', 'help' => '特别是用 <a href="https://developer.mozilla.org/docs/Web/XPath/Axes" target="_blank">XPath 轴</a> <code>descendant::</code> 像 <code>descendant::h2</code>', ), + 'item_uid' => array( + '_' => 'item unique ID', // TODO + 'help' => 'Optional. Example: <code>descendant::div/@data-uri</code>', // TODO + ), 'item_uri' => array( '_' => '文章链接 (URL)', 'help' => '例: <code>descendant::a/@href</code>', diff --git a/app/views/helpers/export/opml.phtml b/app/views/helpers/export/opml.phtml index c401b05bd..677bb03b5 100644 --- a/app/views/helpers/export/opml.phtml +++ b/app/views/helpers/export/opml.phtml @@ -28,6 +28,7 @@ function feedsToOutlines($feeds, $excludeMutedFeeds = false): array { $outline['frss:xPathItemTimestamp'] = ['namespace' => FreshRSS_Export_Service::FRSS_NAMESPACE, 'value' => $xPathSettings['itemTimestamp'] ?? null]; $outline['frss:xPathItemThumbnail'] = ['namespace' => FreshRSS_Export_Service::FRSS_NAMESPACE, 'value' => $xPathSettings['itemThumbnail'] ?? null]; $outline['frss:xPathItemCategories'] = ['namespace' => FreshRSS_Export_Service::FRSS_NAMESPACE, 'value' => $xPathSettings['itemCategories'] ?? null]; + $outline['frss:xPathItemUid'] = ['namespace' => FreshRSS_Export_Service::FRSS_NAMESPACE, 'value' => $xPathSettings['itemUid'] ?? null]; } if (!empty($feed->filtersAction('read'))) { $filters = ''; diff --git a/app/views/helpers/feed/update.phtml b/app/views/helpers/feed/update.phtml index 0e4a34a76..02dcb29e6 100644 --- a/app/views/helpers/feed/update.phtml +++ b/app/views/helpers/feed/update.phtml @@ -475,6 +475,14 @@ data-leave-validation="<?= $xpath['itemCategories'] ?? '' ?>"><?= $xpath['itemCategories'] ?? '' ?></textarea> </div> </div> + <div class="form-group"> + <label class="group-name" for="xPathItemUid"><small><?= _t('sub.feed.kind.html_xpath.relative') ?></small><br /> + <?= _t('sub.feed.kind.html_xpath.item_uid') ?></label> + <div class="group-controls"> + <textarea class="valid-xpath w100" name="xPathItemUid" id="xPathItemUid" rows="2" cols="64" spellcheck="false" + data-leave-validation="<?= $xpath['itemUid'] ?? '' ?>"><?= $xpath['itemUid'] ?? '' ?></textarea> + </div> + </div> </fieldset> <div class="form-group form-actions"> <div class="group-controls"> diff --git a/app/views/subscription/add.phtml b/app/views/subscription/add.phtml index 5aadc350b..41ee04fb7 100644 --- a/app/views/subscription/add.phtml +++ b/app/views/subscription/add.phtml @@ -147,6 +147,13 @@ <textarea class="valid-xpath" name="xPathItemCategories" id="xPathItemCategories" rows="2" cols="64" spellcheck="false"></textarea> </div> </div> + <div class="form-group"> + <label class="group-name" for="xPathItemUid"><small><?= _t('sub.feed.kind.html_xpath.relative') ?></small><br /> + <?= _t('sub.feed.kind.html_xpath.item_uid') ?></label> + <div class="group-controls"> + <textarea class="valid-xpath" name="xPathItemUid" id="xPathItemUid" rows="2" cols="64" spellcheck="false"></textarea> + </div> + </div> </fieldset> </details> diff --git a/docs/en/developers/OPML.md b/docs/en/developers/OPML.md index 9daa94b20..859d99c72 100644 --- a/docs/en/developers/OPML.md +++ b/docs/en/developers/OPML.md @@ -39,6 +39,7 @@ The following attributes are using similar naming conventions than [RSS-Bridge]( * `frss:xPathItemThumbnail`: XPath expression for extracting an item’s thumbnail (image) URL from the item context. * Example: `descendant::img/@src` * `frss:xPathItemCategories`: XPath expression for extracting a list of categories (tags) from the item context. +* `frss:xPathItemUid`: XPath expression for extracting an item’s unique ID from the item context. If left empty, a hash is computed automatically. ### Miscellaneous |
