RSS+ : 显示当前网站所有的 RSS

显示当前网站的所有 RSS(如果有的话)

目前为 2022-04-05 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name RSS+ : Show Site All RSS
  3. // @name:zh RSS+ : 显示当前网站所有的 RSS
  4. // @name:zh-CN RSS+ : 显示当前网站所有的 RSS
  5. // @name:zh-TW RSS+ : 顯示當前網站所有的 RSS
  6. // @name:ja RSS+ : 現在のサイトのRSSを表示
  7. // @name:ko RSS+ : 현재 사이트의 RSS 표시
  8. // @description Show All RSS Of The Site (If Any)
  9. // @description:zh 显示当前网站的所有 RSS(如果有的话)
  10. // @description:zh-CN 显示当前网站的所有 RSS(如果有的话)
  11. // @description:zh-TW 顯示當前網站的所有 RSS(如果有的话)
  12. // @description:ja サイトのすべてのRSSを表示します (あれば)
  13. // @description:ko 웹 사이트의 모든 RSS 를 표시합니다 (있는 경우)
  14. // @license GPL3.0
  15. // @version 1.0.2
  16. // @icon https://www.innoreader.com/favicon.ico
  17. // @author Wizos
  18. // @namespace https://blog.wizos.me
  19. // @supportURL wizos@qq.com
  20. // @match http://*/*
  21. // @match https://*/*
  22. // @require https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
  23. // @require https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js
  24. // @require https://cdn.jsdelivr.net/npm/greensock@1.20.2/dist/TweenMax.min.js
  25. // @require https://cdn.jsdelivr.net/npm/qrcode@1.4.4/build/qrcode.js
  26. // @resource RulerJs https://cdn.jsdelivr.net/gh/wizos/rssplus@2.0.0/Ruler.js?_=1624989578204
  27. // @grant GM_xmlhttpRequest
  28. // @grant GM_getResourceText
  29. // @grant GM_setClipboard
  30. // @grant GM_notification
  31. // @grant GM_addStyle
  32. // @grant GM_getValue
  33. // @grant GM_setValue
  34. // @grant GM_registerMenuCommand
  35. // @grant unsafeWindow
  36. // @connect rssfinder.vercel.app
  37. // @connect rssplus.vercel.app
  38. // @noframes
  39. // @run-at document-end
  40. // ==/UserScript==
  41.  
  42. // 2022.04.05_1.0.2 1.受unsafe-eval影响,无法听过本地执行规则时使用远程规则。2.调整 UI,每次获取到新 RSS 都同步到 UI 中。3.精简设置项。4.监听 URL 变化,同步获取新的 RSS。
  43. // 2022.04.02_1.0.0 1.将远程规则放到 GitHub。2.修复订阅 RSS 网址的转义问题。
  44. // 2021.12.17_0.9.2 1.支持设置 FreshRSS 一键订阅。2.支持设置带端口的网址。
  45. // 2021.02.24_0.9.1 1.支持开启/关闭二维码。
  46. // 2021.02.19_0.9.0 1.支持鼠标悬停在订阅链接上时展示其二维码,方便扫码订阅。
  47. // 2021.02.05_0.8.1 1.url参数用base64编码,防止服务端获取url参数时,漏掉query部分的数据。
  48. // 2021.02.03_0.8.0 1.支持小屏幕展示。2.支持设置 TinyTinyRSS 服务的域名。
  49. // 2021.01.05_0.7.3 1.改用 GM_xmlhttpRequest。2.改用 rssfinder.vercel.app 接口。
  50. // 2020.12.16_0.7.2 1.修复 bug。
  51. // 2020.12.06_0.7.1 1.调整搞定。2.优化代码。
  52. // 2020.11.16_0.7.0 1.支持设置 InoReader 服务的域名。2.在打印页面时隐藏。3.修复影响页面样式的问题。
  53. // 2020.09.11_0.6.4 1.支持 RSSHub 服务器为 IP 地址。2.被识别的 RSS 地址不再转换为小写(因为 news.google.com 的小写地址打不开)
  54. // 2020.04.28_0.6.3 修复改了脚本name导致无法更新的bug。
  55. // 2020.04.27_0.6.2 修复rsshub domain默认为undefined的bug。
  56. // 2020.04.26_0.6.1 支持设置 RSSHub 服务的域名。
  57. // 2020.03.01_0.6 1.可设置点击“订阅”时打开的rss服务商(feedly,inoreadly)。2.修复火狐浏览器下无法展示的问题。
  58. // 2019.09.29_0.5 增加hexo站点的rss嗅探规则。
  59. // 2019.04.26_0.4.2 1.修复默认圆圈状态下宽度太宽,导致遮挡下层页面事件触发的问题。2.将icon由字体改为svg形式,修复部分站点无法显示icon的问题。3.优化RSS没有title时的默认名称。
  60. // 2018.11.10_0.4.1 关闭发现RSS后的h5通知
  61. // 2018.10.29_0.4 1.在无法链接服务器时也能展示本地的RSS;2.针对开启 Content-Security-Policy 的网站直接展示本地的RSS;3.发现RSS后,进行h5通知
  62. // 2018.10.23_0.4 1.增加识别为 wordpress 站点时,尝试使用/feed后缀;2.增加多语言支持
  63. // 2018.10.16_0.3 1.改为iframe方式显示,兼容性更好;2.改为post方式传递页面地址;
  64. // 2018.10.14_0.2 第一版 RSS+ 成型;
  65. // 2018.09.16_0.1 在 RSS+Atom Feed Subscribe Button Generator 脚本基础上增加连接后端获取feed的方式;
  66.  
  67.  
  68. // 过滤掉明确不包含 RSS 源的URL
  69. if (location.href.match(/(api\.wizos\.me)|(feedly\.com\/i\/subscription)|(inoreader\.com\/feed\/http)/i)) {
  70. return;
  71. }
  72.  
  73.  
  74. const zhcn = {
  75. "no_title": "无名称",
  76. "copied": "已复制",
  77. "copy": "复制",
  78. "copy_succeeded": "复制成功",
  79. "follow": "订阅",
  80. "found": "发现 ",
  81. "feed": " 个订阅源",
  82. "click_the_number_to_view": "点击右下角的数字查看",
  83. "use_feedly": "使用 Feedly 订阅",
  84. "use_inoreader": "使用 InoReader 订阅",
  85. "use_tinytinyrss": "使用 TinyTinyRSS 订阅",
  86. "use_freshrss": "使用 FreshRSS 订阅",
  87. "setting_rsshub_domain": "设置 RSSHub 服务的域名",
  88. "setting_inoreader_domain": "设置 InoReader 服务的域名",
  89. "setting_tinytinyrss_domain": "设置 TinyTinyRSS 服务的域名",
  90. "setting_freshrss_domain": "设置 FreshRSS 服务的域名",
  91. "domain_is_wrong": "服务器地址格式有问题,请检查",
  92. "enable_qr_code": "启用/禁用二维码",
  93. "enabled": "已启用",
  94. "disabled": "已禁用",
  95. "close": "关闭"
  96. };
  97. const zhtw = {
  98. "no_title": "無名稱",
  99. "copied": "已複製",
  100. "copy": "複製",
  101. "copy_succeeded": "複製成功",
  102. "follow": "訂閱",
  103. "found": "發現 ",
  104. "feed": " 個訂閱源",
  105. "click_the_number_to_view": "點擊右下角的數位查看",
  106. "use_feedly": "使用 Feedly 訂閱",
  107. "use_inoreader": "使用 InoReader 訂閱",
  108. "use_tinytinyrss": "使用 TinyTinyRSS 訂閱",
  109. "use_freshrss": "使用 FreshRSS 訂閱",
  110. "setting_rsshub_domain": "設定 RSSHub 服務的網域名稱",
  111. "setting_inoreader_domain": "設定 InoReader 服務的網域名稱",
  112. "setting_tinytinyrss_domain": "設定 TinyTinyRSS 服務的網域名稱",
  113. "setting_freshrss_domain": "設定 FreshRSS 服務的網域名稱",
  114. "domain_is_wrong": "伺服器位址格式有問題,請檢查",
  115. "enable_qr_code": "啟用/禁用二維碼",
  116. "enabled": "已啟用",
  117. "disabled": "已禁用",
  118. "close": "關閉"
  119. };
  120. const en = {
  121. "no_title": "NO TITILE",
  122. "copied": "copied",
  123. "copy": "copy",
  124. "copy_succeeded": "copy succeeded",
  125. "follow": "follow",
  126. "found": "found ",
  127. "feed": " feed",
  128. "click_the_number_to_view": "click on the number in the lower right corner to view it",
  129. "setting": "setting",
  130. "use_feedly": "Use Feedly Subscription",
  131. "use_inoreader": "Use InoReader Subscription",
  132. "use_tinytinyrss": "Use TinyTinyRSS Subscription",
  133. "use_freshrss": "Use FreshRSS Subscription",
  134. "setting_rsshub_domain": "Setting RSSHub Domain",
  135. "setting_inoreader_domain": "Setting InoReader Domain",
  136. "setting_tinytinyrss_domain": "Setting TinyTinyRSS Domain",
  137. "setting_freshrss_domain": "Setting FreshRSS Domain",
  138. "domain_is_wrong": "Error in domain name format, please check",
  139. "enable_qr_code": "Enable/disable QR code",
  140. "enabled": "Enabled",
  141. "disabled": "Disabled",
  142. "close": "close"
  143. };
  144. const ja = {
  145. "no_title": "名前なし",
  146. "copied": "コピーされました",
  147. "copy": "コピー",
  148. "copy_succeeded": "コピー成功",
  149. "follow": "購読",
  150. "found": "発見 ",
  151. "feed": " フィード",
  152. "click_the_number_to_view": "右下の数字をクリックして表示",
  153. "use_feedly": "Feedly で購読",
  154. "use_inoreader": "InoReader で購読",
  155. "use_tinytinyrss": "TinyTinyRSS で購読",
  156. "use_freshrss": "FreshRSS で購読",
  157. "setting_rsshub_domain": "RSSHub サービスのドメイン名を設定する",
  158. "setting_inoreader_domain": "InoReader サービスのドメイン名を設定する",
  159. "setting_freshrss_domain": "FreshRSS サービスのドメイン名を設定する",
  160. "domain_is_wrong": "サーバーのアドレス形式に問題があります。確認してください",
  161. "enable_qr_code": "QRコードを有効/無効にする",
  162. "enabled": "有効にした",
  163. "disabled": "無効にしました",
  164. "close": "閉じる"
  165. };
  166. const ko = {
  167. "no_title": "이름 없음",
  168. "copied": "복사",
  169. "copy": "복사",
  170. "copy_succeeded": "복사 성공",
  171. "follow": "구독",
  172. "found": "발견 ",
  173. "feed": "피드",
  174. "click_the_number_to_view": "오른쪽 하단에있는 숫자를 클릭하면 볼 수 있습니다",
  175. "use_feedly": "Feedly 로 구독",
  176. "use_inoreader": "InoReader 로 구독",
  177. "use_tinytinyrss": "TinyTinyRSS 로 구독",
  178. "use_freshrss": "FreshRSS 로 구독",
  179. "setting_rsshub_domain": "RSSub 서비스의 도메인 이름 설정",
  180. "setting_inoreader_domain": "InoReader 서비스의 도메인 이름 설정",
  181. "setting_tinytinyrss_domain": "TinyTinyRSS 서비스의 도메인 이름 설정",
  182. "setting_freshrss_domain": "FreshRSS 서비스의 도메인 이름 설정",
  183. "domain_is_wrong": "서버 주소 형식에 문제가 있습니다. 확인하십시오",
  184. "enable_qr_code": "큐알(QR)코드 사용/사용 안 함",
  185. "enabled": "활성화됨",
  186. "disabled": "사용 안 함",
  187. "close": "닫기"
  188. };
  189. var languages = {
  190. "zh": zhcn,
  191. "zhcn": zhcn,
  192. "zhtw": zhtw,
  193. "ja": ja,
  194. "ko": ko,
  195. "en": en
  196. };
  197.  
  198. var lang = navigator.language.replace('-', "").toLowerCase();
  199. lang = languages[lang];
  200. if (!lang) {
  201. lang = languages.en;
  202. }
  203.  
  204.  
  205. var feedsMap = {};
  206. const feed_suffix = ['/feed', '/rss', '/rss.xml', '/atom.xml', '/feed.xml', '/?feed=rss2', '/?feed=rss'];
  207.  
  208.  
  209.  
  210. setTimeout(function() {
  211. GM_registerMenuCommand(lang.use_feedly, function () {
  212. GM_setValue("rss_service", "feedly");
  213. });
  214. GM_registerMenuCommand(lang.use_inoreader, function () {
  215. var domain = GM_getValue("inoreader_domain");
  216. if(!domain){
  217. domain = "https://www.inoreader.com";
  218. }
  219. domain = window.prompt(lang.setting_inoreader_domain, domain);
  220. if(isValidUrl(domain)){
  221. GM_setValue("inoreader_domain", domain);
  222. GM_setValue("rss_service", "inoreader");
  223. /*
  224. GM_notification({
  225. title: "设置成功",
  226. text: lang.click_the_number_to_view,
  227. timeout: 3000
  228. });
  229. */
  230. //alert("设置成功");
  231. }else{
  232. alert(lang.domain_is_wrong);
  233. }
  234. });
  235. GM_registerMenuCommand(lang.use_tinytinyrss, function () {
  236. var domain = GM_getValue("tinytinyrss_domain");
  237. if(!domain){
  238. domain = "https://www.example.com";
  239. }
  240. domain = window.prompt(lang.setting_tinytinyrss_domain, domain);
  241. if(isValidUrl(domain)){
  242. GM_setValue("tinytinyrss_domain", domain);
  243. GM_setValue("rss_service", "tinytinyrss");
  244. }else{
  245. alert(lang.domain_is_wrong);
  246. }
  247. });
  248. GM_registerMenuCommand(lang.use_freshrss, function () {
  249. var domain = GM_getValue("freshrss_domain");
  250. if(!domain){
  251. domain = "https://www.example.com";
  252. }
  253. domain = window.prompt(lang.setting_freshrss_domain, domain);
  254. if(isValidUrl(domain)){
  255. GM_setValue("freshrss_domain", domain);
  256. GM_setValue("rss_service", "freshrss");
  257. }else{
  258. alert(lang.domain_is_wrong);
  259. }
  260. });
  261.  
  262. GM_registerMenuCommand(lang.enable_qr_code, function () {
  263. if(!GM_getValue("enable_qr_code")){
  264. GM_setValue("enable_qr_code", true);
  265. GM_notification({text: lang.enabled, title: lang.enable_qr_code, timeout: 2000 });
  266. }else{
  267. GM_setValue("enable_qr_code", false);
  268. GM_notification({text: lang.disabled, title: lang.enable_qr_code, timeout: 2000 });
  269. }
  270. });
  271.  
  272.  
  273. GM_registerMenuCommand(lang.setting_rsshub_domain, function () {
  274. var domain = GM_getValue("rsshub_domain");
  275. if(!domain){
  276. domain = "https://rsshub.app";
  277. }
  278. domain = window.prompt(lang.setting_rsshub_domain, domain);
  279. if(isValidUrl(domain)){
  280. GM_setValue("rsshub_domain", domain);
  281. }else{
  282. alert(lang.domain_is_wrong);
  283. }
  284. });
  285.  
  286. findRSS();
  287.  
  288. const _historyWrap = function(type) {
  289. const orig = history[type];
  290. const e = new Event(type);
  291. return function() {
  292. const rv = orig.apply(this, arguments);
  293. e.arguments = arguments;
  294. window.dispatchEvent(e);
  295. return rv;
  296. };
  297. };
  298. history.pushState = _historyWrap('pushState');
  299. history.replaceState = _historyWrap('replaceState');
  300. window.addEventListener('pushState', function(e) {
  301. console.log('change pushState');
  302. clearRSS();
  303. findRSS();
  304. });
  305. window.addEventListener('replaceState', function(e) {
  306. console.log('change replaceState');
  307. clearRSS();
  308. findRSS();
  309. });
  310.  
  311. }, 0);
  312.  
  313.  
  314. function clearRSS() {
  315. if(!feedsView){
  316. return;
  317. }
  318. var childs = feedsView.childNodes;
  319. for (var i = childs.length - 1; i > 0; i--) {
  320. console.log(childs[i]);
  321. feedsView.removeChild(childs[i]);
  322. }
  323. }
  324.  
  325.  
  326. function findRSS() {
  327. getKnowFeeds();
  328. getUnknownFeeds();
  329. findCloudFeeds(optimizeLink(location.href), document.documentElement.outerHTML);
  330. }
  331.  
  332. function showWithCloudFeeds(url) {
  333. GM_xmlhttpRequest({
  334. method: "get",
  335. /*
  336. data: "url=" + Base64.encode(url),
  337. headers: {
  338. "Content-Type": "application/x-www-form-urlencoded"
  339. },
  340. */
  341. url: "https://rssplus.vercel.app/api/find.js?url=" + encodeURIComponent(url), // https://rssplus.vercel.app/api/find.js,https://rssfinder.vercel.app/find.php
  342. onload: response => {
  343. if (response.status != 200) {
  344. return;
  345. }
  346.  
  347. var obj = JSON.parse(response.responseText);
  348.  
  349. if (!obj) {
  350. return;
  351. }
  352. obj.forEach(element => {
  353. addRSS(element.title, element.link);
  354. });
  355. }
  356. });
  357. }
  358.  
  359. function looseJsonParse(obj) {
  360. return Function('"use strict";return (' + obj + ')')();
  361. }
  362.  
  363. function findCloudFeeds(url, res) {
  364. return function(jsStr, url, res) {
  365. try{
  366. if (!jsStr) {
  367. return;
  368. }
  369. //eval(jsStr);
  370. const Ruler = looseJsonParse(jsStr);
  371.  
  372. var list = Ruler.find(url, res);
  373. if (!list) {
  374. return;
  375. }
  376. list.forEach(element => {
  377. addRSS(element.title, element.link);
  378. });
  379. }catch(e){
  380. console.log("请求远程:" + url);
  381. //console.log(e);
  382. showWithCloudFeeds(url);
  383. }
  384. }.call(window, GM_getResourceText('RulerJs'), url, res);
  385. }
  386.  
  387. function optimizeLink(link){
  388. if(link.match(/douban\.com\/people/i)){
  389. var src = document.querySelector("#profile > div > div.bd > div.basic-info > div.uhead-wrap > img.userface").src;
  390. var m = src.match(/ul(\d+)-/i);
  391. link = "https://www.douban.com/people/" + m[1];
  392. }
  393. return link;
  394. }
  395.  
  396.  
  397. // 获取在<head>的<link>元素中,已经声明为RSS的链接
  398. function getKnowFeeds() {
  399. var links = document.getElementsByTagName("link");
  400. var link, linkHref, linkType, linkTitle;
  401. for (var i = 0, l = links.length; i < l; i++) {
  402. link = links[i];
  403. if (!link) continue;
  404. linkHref = link.href;
  405. linkType = link.type;
  406. linkTitle = link.title;
  407. if (!linkTitle) {
  408. linkTitle = document.title;
  409. }
  410. if (linkType && linkType.match(/.+\/(rss|rdf|atom)/i)) {
  411. addRSS(linkTitle, linkHref);
  412. } else if (linkType && linkType.match(/^text\/xml$/i)) {
  413. addRSS(linkTitle, linkHref);
  414. }
  415. }
  416. }
  417.  
  418. // 寻找未明确标示的RSS源
  419. function getUnknownFeeds() {
  420. //var link, linkHref, linkType, linkTitle;
  421. var links,link,linkhref,linktitle;
  422. // links 属性返回一个文档中所有具有 href 属性值的 <area> 元素与 <a> 元素的集合
  423. if (!document.links) { //console.log("页面内没有发现具有 href 属性值的 <area> 元素或 <a> 元素");
  424. links = document.getElementsByTagName("a");
  425. }else{
  426. links = document.links;
  427. }
  428. for (var a = 0, len = links.length; a < len; a++) {
  429. link = links[a];
  430. linkhref = link.href;
  431. linktitle = link.title;
  432. if (!linktitle) {
  433. linktitle = document.title;
  434. } else if (link.innerText) {
  435. linktitle = link.innerText;
  436. }
  437. if (linkhref.match(/^(https|http|ftp|feed).*([\.\/]rss([\.\/]xml|\.aspx|\.jsp|\/)?$|\/node\/feed$|\/feed(\.xml|\/$|$)|\/rss\/[a-z0-9]+$|[?&;](rss|xml)=|[?&;]feed=rss[0-9.]*$|[?&;]action=rss_rc$|feeds\.feedburner\.com\/[\w\W]+$)/i)) {
  438. addRSS(linktitle, linkhref);
  439. } else if (linkhref.match(/^(https|http|ftp|feed).*\/atom(\.xml|\.aspx|\.jsp|\/)?$|[?&;]feed=atom[0-9.]*$/i)) {
  440. addRSS(linktitle, linkhref);
  441. } else if (linkhref.match(/^(https|http|ftp|feed).*(\/feeds?\/[^.\/]*\.xml$|.*\/index\.xml$|feed\/msgs\.xml(\?num=\d+)?$)/i)) {
  442. addRSS(linktitle, linkhref);
  443. } else if (linkhref.match(/^(https|http|ftp|feed).*\.rdf$/i)) {
  444. addRSS(linktitle, linkhref);
  445. } else if (linkhref.match(/^(rss|feed):\/\//i)) {
  446. addRSS(linktitle, linkhref);
  447. } else if (linkhref.match(/^(https|http):\/\/feed\./i)) {
  448. addRSS(linktitle, linkhref);
  449. }
  450. }
  451.  
  452. links = document.querySelectorAll("html > head > link");
  453. for (var i = 0, size = links.length; i < size; i++) {
  454. link = links[i];
  455. if (link.href.match(/(wp-content)/i)) {
  456. checkFeed(document.location.protocol + '//' + document.domain);
  457. break;
  458. }
  459. }
  460.  
  461. links = document.querySelectorAll("html > body footer a");
  462. for (i = 0, size = links.length; i < size; i++) {
  463. link = links[i];
  464. if (link.href.match(/(bitcron\.com|typecho\.org|hexo\.io)/i)) {
  465. checkFeed(document.location.protocol + '//' + document.domain);
  466. break;
  467. }
  468. }
  469. }
  470.  
  471. function checkFeed(href) {
  472. ['/feed', '/rss', '/rss.xml', '/atom.xml', '/feed.xml', '/?feed=rss2', '/?feed=rss'].forEach(suffix => {
  473. GM_xmlhttpRequest({
  474. method: "HEAD",
  475. url: href + suffix,
  476. onload: response => {
  477. //console.log("请求api返回状态:" + response.status + " => " + href + flag);
  478. if (response.status == 200) {
  479. addRSS(document.title, href + suffix);
  480. }
  481. }
  482. });
  483. });
  484. }
  485.  
  486.  
  487. var feedsBadge;
  488. var feedsDialog;
  489. var countLabels;
  490. var feedsView;
  491. var rssPlusDocument;
  492.  
  493. function addRSS(title, link){
  494. if (link.match(/(api\.wizos\.me)|(feedly\.com\/i\/subscription)|(inoreader\.com\/feed\/http)/i)) {
  495. return;
  496. }
  497.  
  498. if(Object.keys(feedsMap).length == 0){
  499. // 安装 RSS Plus Box 和 RSS Plus Frame
  500. // console.log("RSSPlus:首次渲染");
  501.  
  502. var body = document.getElementsByTagName("body");
  503. if (body && body[0]) body = body[0];
  504.  
  505. var rssPlusStyle = document.createElement("style");
  506. rssPlusStyle.innerHTML = '@media print {#rss-plus {display: none;}} #rss-plus{position:fixed;bottom:60px;right:5px;z-index:9999;width:auto;height:auto;} #rss-plus > iframe{display: block!important; max-width: 100%!important;border:0px;margin:0px !important; }';
  507. body.appendChild(rssPlusStyle);
  508.  
  509. var rssPlusDiv = document.createElement("div");
  510. rssPlusDiv.setAttribute("id", "rss-plus");
  511. body.appendChild(rssPlusDiv);
  512.  
  513. var rssPlusIFrame = document.createElement("iframe");
  514. rssPlusIFrame.setAttribute("id", "rss-plus-iframe");
  515. rssPlusIFrame.setAttribute("name", "rssPlusEnvironment");
  516. rssPlusIFrame.setAttribute("allowTransparency", "true");
  517.  
  518. if(navigator.userAgent.indexOf("Firefox") !== -1){
  519. rssPlusIFrame.setAttribute("src", "javascript:");
  520. }
  521. rssPlusDiv.appendChild(rssPlusIFrame);
  522.  
  523.  
  524. rssPlusDocument = rssPlusEnvironment.window.document;
  525. var frameBody = rssPlusDocument.getElementsByTagName("body");
  526. if (frameBody && frameBody[0]) frameBody = frameBody[0];
  527.  
  528.  
  529. var styleEl = document.createElement("style");
  530. styleEl.innerHTML = BOX_STYLE;
  531. frameBody.appendChild(styleEl);
  532.  
  533. var rssPlusBoxDiv = document.createElement("div");
  534. rssPlusBoxDiv.setAttribute("id", "rss-plus-box");
  535. rssPlusBoxDiv.innerHTML = '<div id="rp-feeds-badge" class="rp-card rp-card-bordered"><span class="rp-badge-count rp-feed-count" place="count">0</span></div>'
  536. + '<div id="rp-feeds-dialog" class="rp-card rp-card-bordered"><div class="rp-table"><table cellspacing="0" cellpadding="0" border="0"><colgroup><col width="70%"><col width="30%"></colgroup><tbody id="rp-table-tbody">'
  537. + '<tr><th><div id="rp-card-head" class="rp-card-head"><div class="card-title">' + ICON_LOGO + lang.found + '<span class="rp-mark-count rp-feed-count" place="count"></span>' + lang.feed + ' -【RSS+】</div></div></th><th class="rp-table-column-end"><button type="button" id="rp-close-btn" class="rp-btn rp-btn-small endrp-btn-dashed" title="' + lang.close + '"><span>' + ICON_CLOSE + '</span></button></th></tr>'
  538. + "</tbody></table></div></div>";
  539. frameBody.appendChild(rssPlusBoxDiv);
  540.  
  541. feedsBadge = rssPlusDocument.getElementById("rp-feeds-badge");
  542. feedsDialog = rssPlusDocument.getElementById("rp-feeds-dialog");
  543.  
  544. countLabels = rssPlusDocument.getElementsByClassName("rp-feed-count");
  545. feedsView = rssPlusDocument.getElementById("rp-table-tbody");
  546.  
  547. rssPlusIFrame.style.width = feedsBadge.offsetWidth + "px";
  548. rssPlusIFrame.style.height = feedsBadge.offsetHeight + "px";
  549.  
  550. addEventHandler(rssPlusDocument.getElementById("rp-close-btn"), "click", function() {
  551. feedsDialog.style.display = "none";
  552. feedsBadge.style.display = "block";
  553. rssPlusIFrame.style.width = feedsBadge.offsetWidth + "px";
  554. rssPlusIFrame.style.height = feedsBadge.offsetHeight + "px";
  555. });
  556. addEventHandler(rssPlusDocument.getElementById("rp-feeds-badge"), "click", function() {
  557. feedsDialog.style.display = "block";
  558. feedsBadge.style.display = "none";
  559.  
  560. if(document.body.clientWidth < 600){
  561. feedsDialog.style.width = "100%";
  562. rssPlusIFrame.style.width = "100%";
  563. }else{
  564. rssPlusIFrame.style.width = rssPlusDocument.getElementById("rss-plus-box").offsetWidth + "px";
  565. rssPlusIFrame.style.height = rssPlusDocument.getElementById("rss-plus-box").offsetHeight + "px";
  566. }
  567. });
  568.  
  569. }
  570.  
  571. //link = link.replace(/\/$/g, "");
  572.  
  573. // 防止重复,如果能查找到,证明数组元素重复了
  574. if (!feedsMap[link.toLowerCase()]) {
  575. feedsMap[link.toLowerCase()] = 1;
  576. }
  577.  
  578. console.log("发现:" + title + " -> " + link);
  579.  
  580. Array.from(countLabels).forEach(label => label.innerText = Object.keys(feedsMap).length);
  581.  
  582. if(link.match(/^https*:\/\/rsshub.app/)){
  583. var rsshub_domain = GM_getValue("rsshub_domain");
  584. if(rsshub_domain != null && rsshub_domain != ""){
  585. link = link.replace(/^https*:\/\/rsshub.app/,rsshub_domain);
  586. }
  587. }
  588. if (!title) {
  589. title = lang.no_title;
  590. }
  591.  
  592. var item = document.createElement("tr");
  593. feedsView.appendChild(item);
  594.  
  595. item.innerHTML
  596. = '<td><div class="rp-table-cell"><div class="feed-title">' + title + '</div><div class="feed-tips"><a class="feed-link" href="' + link + '" target="_blank">' + link + '</a></div></div></td>'
  597. + '<td class="rp-table-column-end">'
  598. + '<button type="button" class="rp-btn rp-btn-primary rp-btn-small rp-copy-feed-link"><span>' + lang.copy + '</span></button>'
  599. + '<button type="button" class="rp-btn rp-btn-primary rp-btn-small rp-follow-feed-link"><span>' + lang.follow + '</span></button></td>';
  600.  
  601.  
  602. var copyFeedLinkButton = item.getElementsByClassName("rp-copy-feed-link")[0];
  603. //Array.from(copyFeedLinkButton).forEach(function (button) {
  604. //});
  605. addEventHandler(copyFeedLinkButton, "click", function() {
  606. copy(link);
  607. });
  608.  
  609. var followFeedLinkButton = item.getElementsByClassName("rp-follow-feed-link")[0];
  610. addEventHandler(followFeedLinkButton, "click", function() {
  611. follow(link); // .replace(/&/g,"%26") 转义&避免RSS链接识别错误
  612. });
  613.  
  614. var feedLinkButton = item.getElementsByClassName("feed-link")[0];
  615. new HoverImgFx1(feedLinkButton);
  616. }
  617.  
  618.  
  619. function isValidUrl(url) {
  620. if(url && (url.match(/^https*:\/\/.*?\.\w+(:\d+)?(\/|$)/) || url.match(/^https*:\/\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\:\d+)*(:\d+)?(\/|$)/)) ){
  621. return true;
  622. }else{
  623. return false;
  624. }
  625. }
  626.  
  627.  
  628. function addEventHandler(target, eventName, eventHandler, scope) {
  629. var f = scope ? function() {
  630. eventHandler.apply(scope, arguments);
  631. } : eventHandler;
  632. if (target.addEventListener) {
  633. target.addEventListener(eventName, f, true);
  634. } else if (target.attachEvent) {
  635. target.attachEvent("on" + eventName, f);
  636. }
  637. return f;
  638. }
  639.  
  640.  
  641. function notification(size) {
  642. GM_notification({
  643. title: lang.found + " " + size + " " + lang.feed,
  644. text: lang.click_the_number_to_view,
  645. timeout: 3000
  646. });
  647. }
  648.  
  649.  
  650. function copy(str) {
  651. GM_setClipboard(str);
  652. GM_notification({
  653. text: lang.copied + ": " + str,
  654. title: lang.copy_succeeded,
  655. timeout: 2000
  656. });
  657. }
  658.  
  659. function follow(link) {
  660. const rssService = GM_getValue("rss_service", "feedly");
  661. if( rssService === "feedly" ){
  662. window.open("https://feedly.com/i/subscription/feed/" + encodeURIComponent(link), "_blank");
  663. }else if( rssService === "inoreader" ){
  664. window.open(GM_getValue("inoreader_domain", "https://www.inoreader.com") + "/?add_feed=" + encodeURIComponent(link), "_blank");
  665. }else if( rssService === "tinytinyrss" ){
  666. window.open(GM_getValue("tinytinyrss_domain") + "/public.php?op=bookmarklets-subscribe&feed_url=" + link, "_blank");
  667. }else if( rssService === "freshrss" ){
  668. window.open(GM_getValue("freshrss_domain") + "/i/?c=feed&a=add&url_rss=" + encodeURIComponent(link), "_blank");
  669. }else if( rssService === "NewsBlur" ){
  670. window.open("http://www.newsblur.com/?url=" + encodeURIComponent(link), "_blank");
  671. }
  672. // [tinytinyrss]https://example.com/public.php?op=subscribe&feed_url=https://rsshub.wizos.me/weibo/user/5261556444
  673. // bookmarklets-subscribe
  674. // [feedly]https://feedly.com/i/subscription/feed%2Fhttp%3A%2F%2Ffeeds.howtogeek.com%2FHowToGeek
  675. // [inoreader]http://www.inoreader.com/?add_feed=https%3A%2F%2Fwww.howtogeek.com%2Ffeed%2F
  676. // [NewsBlur]http://www.newsblur.com/?url=https%3A%2F%2Ffeeds.howtogeek.com%2FHowToGeek
  677. // [theoldreader]https://theoldreader.com/feeds/subscribe?url=https://api.izgq.net/weibo/rss/1197161814
  678. // [freshrss]https://rss.iridium.cyou/i/?c=feed&a=add&url_rss=https://rsshub.wizos.me/zhihu/question/20180238
  679. }
  680.  
  681.  
  682. // Effect 1
  683. class HoverImgFx1 {
  684. constructor(el) {
  685. this.DOM = {
  686. el: el
  687. };
  688. this.DOM.reveal = document.createElement('div');
  689. this.DOM.reveal.className = 'hover-reveal';
  690.  
  691. let thisDOM = this.DOM;
  692. QRCode.toDataURL(this.DOM.el.href, function(error, url) {
  693. if (error) {
  694. console.log(error);
  695. } else {
  696. thisDOM.reveal.innerHTML = `<div class="hover-reveal__inner"><div class="hover-reveal__img" style="background-image:url(${url})"></div></div>`
  697. thisDOM.revealInner = thisDOM.reveal.querySelector('.hover-reveal__inner');
  698. thisDOM.revealInner.style.overflow = 'hidden';
  699. thisDOM.revealImg = thisDOM.revealInner.querySelector('.hover-reveal__img');
  700. thisDOM.el.appendChild(thisDOM.reveal);
  701. }
  702. });
  703. this.initEvents();
  704. }
  705. getMousePos(e) {
  706. let posx = 0;
  707. let posy = 0;
  708. if (!e) e = window.event;
  709. if (e.pageX || e.pageY) {
  710. posx = e.pageX;
  711. posy = e.pageY;
  712. } else if (e.clientX || e.clientY) {
  713. posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
  714. posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
  715. }
  716. return {
  717. x: posx,
  718. y: posy
  719. }
  720. }
  721. initEvents() {
  722. this.positionElement = (ev) => {
  723. const mousePos = this.getMousePos(ev);
  724. const docScrolls = {
  725. left: rssPlusDocument.body.scrollLeft + rssPlusDocument.documentElement.scrollLeft,
  726. top: rssPlusDocument.body.scrollTop + rssPlusDocument.documentElement.scrollTop
  727. };
  728. this.DOM.reveal.style.top = `${mousePos.y-70-docScrolls.top}px`;
  729. this.DOM.reveal.style.left = `${mousePos.x+10-docScrolls.left}px`;
  730. };
  731. this.mouseenterFn = (ev) => {
  732. if (!GM_getValue("enable_qr_code")) return;
  733. this.positionElement(ev);
  734. this.showImage();
  735. };
  736. this.mousemoveFn = ev => requestAnimationFrame(() => {
  737. if (!GM_getValue("enable_qr_code")) return;
  738. this.positionElement(ev);
  739. });
  740. this.mouseleaveFn = () => {
  741. if (!GM_getValue("enable_qr_code")) return;
  742. this.hideImage();
  743. };
  744. this.DOM.el.addEventListener('mouseenter', this.mouseenterFn);
  745. this.DOM.el.addEventListener('mousemove', this.mousemoveFn);
  746. this.DOM.el.addEventListener('mouseleave', this.mouseleaveFn);
  747. }
  748. showImage() {
  749. TweenMax.killTweensOf(this.DOM.revealInner);
  750. TweenMax.killTweensOf(this.DOM.revealImg);
  751.  
  752. this.tl = new TimelineMax({
  753. onStart: () => {
  754. this.DOM.reveal.style.opacity = 1;
  755. TweenMax.set(this.DOM.el, {
  756. zIndex: 1000
  757. });
  758. }
  759. })
  760. .add('begin')
  761. .add(new TweenMax(this.DOM.revealInner, 0.2, {
  762. ease: Sine.easeOut,
  763. startAt: {
  764. x: '-100%'
  765. },
  766. x: '0%'
  767. }), 'begin')
  768. .add(new TweenMax(this.DOM.revealImg, 0.2, {
  769. ease: Sine.easeOut,
  770. startAt: {
  771. x: '100%'
  772. },
  773. x: '0%'
  774. }), 'begin');
  775. }
  776. hideImage() {
  777. TweenMax.killTweensOf(this.DOM.revealInner);
  778. TweenMax.killTweensOf(this.DOM.revealImg);
  779.  
  780. this.tl = new TimelineMax({
  781. onStart: () => {
  782. TweenMax.set(this.DOM.el, {
  783. zIndex: 999
  784. });
  785. },
  786. onComplete: () => {
  787. TweenMax.set(this.DOM.el, {
  788. zIndex: ''
  789. });
  790. TweenMax.set(this.DOM.reveal, {
  791. opacity: 0
  792. });
  793. }
  794. })
  795. .add('begin')
  796. .add(new TweenMax(this.DOM.revealInner, 0.2, {
  797. ease: Sine.easeOut,
  798. x: '100%'
  799. }), 'begin')
  800. .add(new TweenMax(this.DOM.revealImg, 0.2, {
  801. ease: Sine.easeOut,
  802. x: '-100%'
  803. }), 'begin');
  804. }
  805. }
  806.  
  807. const ICON_LOGO = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 1024 1024"><<defs><style type="text/css"></style></defs><path d="M129.832 884.872a381.336 81.488 0 1 0 762.672 0 381.336 81.488 0 1 0-762.672 0Z" fill="#B8CBCD" p-id="1377"></path><path d="M208.52 243.224c-22.608-66.672 13.44-102.72 80.112-80.112l38.12 12.92L459.2 220.944c6.176 2.096 15.192 0.856 20.024-2.744l111.376-83.112 33.68-25.136c56.424-42.104 101.848-18.96 100.952 51.432l-0.512 40.024-1.784 139.96c-0.088 6.584 2.824 14.072 6.456 16.648 3.64 2.568 52.992 38.84 109.672 80.592l41.896 30.864c56.68 41.76 47.664 91.728-20.032 111.056l-41.832 11.936c-67.696 19.32-127.032 36.36-131.848 37.856-4.832 1.504-10.48 8.2-12.56 14.896-2.08 6.696-20.872 67.176-41.776 134.4l-11.424 36.736c-20.896 67.224-71.248 75.2-111.896 17.72l-28.4-40.144-78.176-110.544c-2.344-3.32-9.384-5.976-15.632-5.896l-139.36 1.784-41.216 0.528c-70.4 0.896-93.536-44.528-51.44-100.944l26.032-34.888L264.064 433.2c3.368-4.504 4.312-13.512 2.112-20.016l-45.12-133.04-12.536-36.92z" fill="#F6E89A" p-id="1378"></path><path d="M566.6 896.488c-27.272 0-54.488-17.24-76.616-48.544l-28.4-40.144-75.072-106.16-181.768 2.176c-57.552 0-79.488-26.6-87.44-42.456-8.024-16.008-16.256-49.872 18.808-96.856l107.224-143.688a1.632 1.632 0 0 0-0.032-0.312l-57.528-169.584c-15.696-46.272-5.656-74.584 5.528-90.184 19.992-27.872 59.288-35.856 105.024-20.36l169.752 57.56 0.168-0.016 143.664-107.2c22.928-17.112 45.304-25.792 66.488-25.792 18.512 0 34.968 6.768 47.608 19.576 16.912 17.128 25.624 43.816 25.2 77.192l-0.832 64.472c-0.752 58.376-1.368 107.024-1.464 114.936 13.904 10.144 62.248 45.696 106.352 78.184l41.896 30.864c47.464 34.968 49.192 69.84 46.008 87.52-3.184 17.68-17 49.752-73.688 65.936l-41.832 11.936a35027.144 35027.144 0 0 0-128.04 36.728 0.856 0.856 0 0 0-0.072 0.152l-53.168 171.064c-14.392 46.384-42.744 72.992-77.768 73zM387.088 653.504c11.472 0 27.16 4.208 35.52 16.056l78.168 110.528 28.4 40.144c12.512 17.696 26.504 28.264 37.432 28.256 12.184 0 24.432-15.04 31.952-39.248l53.2-171.128c3.768-12.08 13.984-26.24 28.368-30.704 5.528-1.72 71.656-20.688 132.384-38.024l41.832-11.936c22.792-6.504 37.6-17.08 39.624-28.296 2.024-11.216-8.168-26.304-27.24-40.352l-41.896-30.864c-61.624-45.4-106.256-78.176-109.28-80.312-11.704-8.296-16.768-24.336-16.608-36.568l1.472-115.496 0.832-64.472c0.248-19.664-3.888-35.288-11.36-42.856-3.56-3.616-7.84-5.296-13.456-5.296-10.312 0-23.736 5.776-37.792 16.264L493.552 237.44c-10.912 8.136-28.664 10.784-42.08 6.232L280.92 185.84c-24.128-8.184-43.456-7.104-50.592 2.864-6.36 8.872-6.016 26.368 0.912 46.808l57.648 169.984c4.744 14 2.432 31.304-5.616 42.08L174.584 593.216c-14.136 18.944-19.504 36.376-14.368 46.632 5.016 10 21.664 15.976 44.528 15.976l42.952-0.536 139.368-1.784h0.024z" fill="#8D4520" p-id="1379"></path><path d="M407.296 713.44a23.976 23.976 0 0 1-19.928-10.592l-20.152-29.944H149.624c-10.704 0-20.208-5.672-24.832-14.8-4.864-9.632-3.544-21.144 3.536-30.776l73.568-100.024c34.4-46.768 65.376-88.84 72.896-99.016a1.816 1.816 0 0 0-0.032-0.328c-1.736-5.064-21.912-58.88-49.016-130.296l-4.776-12.592c-22.096-58.224-4.672-87.296 7.688-99.448 11.44-11.248 38.048-27.168 87.744-7.344 57.136 22.792 103.344 40.96 116.336 45.872 1.712-0.664 4.232-1.984 6.384-3.872l15.472-13.584a24 24 0 1 1 31.656 36.08l-15.456 13.56c-12.872 11.304-33.4 20.168-50.24 14.456-7.664-2.6-68.536-26.64-121.928-47.936-19.36-7.728-32.184-7.072-36.312-3.016-5.168 5.088-6.272 22.336 3.536 48.192l4.776 12.592c22.424 59.08 47.152 124.728 49.72 132.304 4.744 14 2.432 31.312-5.624 42.08-3.328 4.472-36.712 49.8-74.152 100.704l-50.872 69.168h181.808c12.728 0 25.84 6.784 32.632 16.88l23.048 34.24a24 24 0 0 1-6.504 33.32 23.744 23.744 0 0 1-13.384 4.12z" fill="#FFFFFF" p-id="1380"></path><path d="M599.296 895.168l-46.592-11.544 33.2-133.96c15.208-61.36 32.44-129.664 34.952-137.752 3.768-12.08 13.984-26.24 28.368-30.704 7.048-2.192 84.76-20.24 135.272-31.832l29.376-6.744c28.376-6.512 37.296-16.584 38.056-20.992 0.76-4.408-4.312-16.872-28.912-32.448l-23.728-15.032c-41.984-26.584-110.544-70.144-115.776-73.84-11.688-8.272-16.752-24.312-16.592-36.552 0.088-7.08 1.384-73.52 2.616-135.488l2.472-123.352 47.984 0.96-2.472 123.344c-1.384 69.672-2.456 125.056-2.592 134.32 12.888 8.352 56.024 35.848 110.048 70.056l23.728 15.032c50.568 32.024 53.368 64.552 50.536 81.096-2.824 16.544-16.288 46.296-74.632 59.68l-29.376 6.744c-64.416 14.784-114.64 26.584-128.552 30.056l-0.008 0.008c-1.712 5.552-16.184 62.416-34.168 134.984l-33.208 133.96z" fill="#8D4520" p-id="1381"></path><path d="M566.6 896.488c-27.272 0-54.488-17.24-76.616-48.544l-28.4-40.144-75.072-106.16-181.768 2.176c-57.552 0-79.488-26.6-87.44-42.456-8.024-16.008-16.256-49.872 18.808-96.856l107.224-143.688a1.632 1.632 0 0 0-0.032-0.312l-57.528-169.584c-15.696-46.272-5.656-74.584 5.528-90.184 19.992-27.872 59.288-35.856 105.024-20.36l169.752 57.56 0.168-0.016 143.664-107.2c22.928-17.112 45.304-25.792 66.488-25.792 18.512 0 34.968 6.768 47.608 19.576 16.912 17.128 25.624 43.816 25.2 77.192l-0.832 64.472c-0.752 58.376-1.368 107.024-1.464 114.936 13.904 10.144 62.248 45.696 106.352 78.184l41.896 30.864c47.464 34.968 49.192 69.84 46.008 87.52-3.184 17.68-17 49.752-73.688 65.936l-41.832 11.936a35027.144 35027.144 0 0 0-128.04 36.728 0.856 0.856 0 0 0-0.072 0.152l-53.168 171.064c-14.392 46.384-42.744 72.992-77.768 73zM387.088 653.504c11.472 0 27.16 4.208 35.52 16.056l78.168 110.528 28.4 40.144c12.512 17.696 26.504 28.264 37.432 28.256 12.184 0 24.432-15.04 31.952-39.248l53.2-171.128c3.768-12.08 13.984-26.24 28.368-30.704 5.528-1.72 71.656-20.688 132.384-38.024l41.832-11.936c22.792-6.504 37.6-17.08 39.624-28.296 2.024-11.216-8.168-26.304-27.24-40.352l-41.896-30.864c-61.624-45.4-106.256-78.176-109.28-80.312-11.704-8.296-16.768-24.336-16.608-36.568l1.472-115.496 0.832-64.472c0.248-19.664-3.888-35.288-11.36-42.856-3.56-3.616-7.84-5.296-13.456-5.296-10.312 0-23.736 5.776-37.792 16.264L493.552 237.44c-10.912 8.136-28.664 10.784-42.08 6.232L280.92 185.84c-24.128-8.184-43.456-7.104-50.592 2.864-6.36 8.872-6.016 26.368 0.912 46.808l57.648 169.984c4.744 14 2.432 31.304-5.616 42.08L174.584 593.216c-14.136 18.944-19.504 36.376-14.368 46.632 5.016 10 21.664 15.976 44.528 15.976l42.952-0.536 139.368-1.784h0.024z" fill="#8D4520" p-id="1382"></path></svg>';
  808. const ICON_CLOSE = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 1024 1024"><defs><style type="text/css"></style></defs><path d="M583.168 523.776L958.464 148.48c18.944-18.944 18.944-50.176 0-69.12l-2.048-2.048c-18.944-18.944-50.176-18.944-69.12 0L512 453.12 136.704 77.312c-18.944-18.944-50.176-18.944-69.12 0l-2.048 2.048c-19.456 18.944-19.456 50.176 0 69.12l375.296 375.296L65.536 899.072c-18.944 18.944-18.944 50.176 0 69.12l2.048 2.048c18.944 18.944 50.176 18.944 69.12 0L512 594.944 887.296 970.24c18.944 18.944 50.176 18.944 69.12 0l2.048-2.048c18.944-18.944 18.944-50.176 0-69.12L583.168 523.776z" p-id="3440"></path></svg>';
  809. const BOX_STYLE = '.hover-reveal{position:fixed;width:80px;height:80px;top:0;left:0;pointer-events:none;opacity:0}.hover-reveal__inner,.hover-reveal__img{width:100%;height:100%;position:relative}.hover-reveal__deco{width:100%;height:100%;position:absolute;top:0;left:0;background-color:#181314}.hover-reveal__img{background-size:cover;background-position:50% 50%}; body {margin: 0px;}#rss-plus-box { position:fixed;z-index:99999;bottom:0px; right:0px; }div.feed-title { font-weight: bold;font-size:0.8rem; cursor: pointer;}div.feed-tips,div.feed-tips a { font-size: 0.75rem; color: rgb(158, 158, 158);}.card-title {}.rp-table-body { max-height: 400px; height: auto; overflow-x: hidden;}.table-footer { position: fixed; bottom: 0 ; padding-left: 10px; width: 100%; background-color: #fff;}.table-footer a { color: #ed3f14;}.support-box { height: 28px; line-height: 28px;}#rp-feeds-dialog{display:none;z-index:23333;box-shadow: 1px 1px 2px 2px #4242426b; width:600px;} #rp-feeds-badge{width: 28px; height: 28px; line-height: 28px; border-radius: 14px; float: right;cursor: pointer;z-index:23333;}#rp-feeds-badge:hover{border-color:#e9eaec}.badge{ top:-17px; left: -6%; width: 26px; height: 26px; line-height: 26px; border-radius: 13px;}.rp-card:hover{-webkit-box-shadow:0 1px 6px rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.2);border-color:#eee}.rp-card{background:#fff;border-radius:4px;font-size:14px;position:relative;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.rp-card-bordered:hover{border-color:#e9eaec}.rp-card-bordered{border:1px solid #dddee1;border-color:#e9eaec}.rp-mark-count{font-weight:bold;color: #ed3f14;}.rp-badge-count{position:relative;display:inline-block;width: 26px;height: 26px;line-height: 26px;border-radius: 15px;min-width: 20px;background:#4b5979;border: 1px solid transparent;color: #fff;text-align: center;font-size: 12px;white-space: nowrap;-webkit-transform-origin: -10% center;-ms-transform-origin: -10% center;transform-origin: -10% center;z-index: 10;-webkit-box-shadow: 0 0 0 1px #fff;box-shadow: 0 0 0 1px #fff;}.rp-badge-count a,.rp-badge-count a:hover{color:#fff}.rp-card-head{font-size: 14px;padding:10px 16px;line-height:1}.rp-tooltip{display:inline-block}.rp-tooltip-rel{display:inline-block;position:relative}.rp-btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;line-height:1.5;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:6px 15px;font-size:12px;border-radius:4px;-webkit-transition:color .2s linear,background-color .2s linear,border .2s linear,-webkit-box-shadow .2s linear;transition:color .2s linear,background-color .2s linear,border .2s linear,-webkit-box-shadow .2s linear;transition:color .2s linear,background-color .2s linear,border .2s linear,box-shadow .2s linear;transition:color .2s linear,background-color .2s linear,border .2s linear,box-shadow .2s linear,-webkit-box-shadow .2s linear;color:#495060;background-color:#f7f7f7;border-color:#dddee1}.rp-btn>.rp-icon{line-height:1}.rp-btn,.rp-btn:active,.rp-btn:focus{outline:0}.rp-btn:not([disabled]):hover{text-decoration:none}.rp-btn:not([disabled]):active{outline:0}.rp-btn.disabled,.rp-btn[disabled]{cursor:not-allowed}.rp-btn.disabled>*,.rp-btn[disabled]>*{pointer-events:none}.rp-btn>a:only-child{color:currentColor}.rp-btn>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn:hover{color:#6d7380;background-color:#f9f9f9;border-color:#e4e5e7}.rp-btn:hover>a:only-child{color:currentColor}.rp-btn:hover>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn.active,.rp-btn:active{color:#454c5b;background-color:#ebebeb;border-color:#ebebeb}.rp-btn.active>a:only-child,.rp-btn:active>a:only-child{color:currentColor}.rp-btn.active>a:only-child:after,.rp-btn:active>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn.disabled,.rp-btn.disabled.active,.rp-btn.disabled:active,.rp-btn.disabled:focus,.rp-btn.disabled:hover,.rp-btn[disabled],.rp-btn[disabled].active,.rp-btn[disabled]:active,.rp-btn[disabled]:focus,.rp-btn[disabled]:hover,fieldset[disabled] .rp-btn,fieldset[disabled] .rp-btn.active,fieldset[disabled] .rp-btn:active,fieldset[disabled] .rp-btn:focus,fieldset[disabled] .rp-btn:hover{color:#bbbec4;background-color:#f7f7f7;border-color:#dddee1}.rp-btn.disabled.active>a:only-child,.rp-btn.disabled:active>a:only-child,.rp-btn.disabled:focus>a:only-child,.rp-btn.disabled:hover>a:only-child,.rp-btn.disabled>a:only-child,.rp-btn[disabled].active>a:only-child,.rp-btn[disabled]:active>a:only-child,.rp-btn[disabled]:focus>a:only-child,.rp-btn[disabled]:hover>a:only-child,.rp-btn[disabled]>a:only-child,fieldset[disabled] .rp-btn.active>a:only-child,fieldset[disabled] .rp-btn:active>a:only-child,fieldset[disabled] .rp-btn:focus>a:only-child,fieldset[disabled] .rp-btn:hover>a:only-child,fieldset[disabled] .rp-btn>a:only-child{color:currentColor}.rp-btn.disabled.active>a:only-child:after,.rp-btn.disabled:active>a:only-child:after,.rp-btn.disabled:focus>a:only-child:after,.rp-btn.disabled:hover>a:only-child:after,.rp-btn.disabled>a:only-child:after,.rp-btn[disabled].active>a:only-child:after,.rp-btn[disabled]:active>a:only-child:after,.rp-btn[disabled]:focus>a:only-child:after,.rp-btn[disabled]:hover>a:only-child:after,.rp-btn[disabled]>a:only-child:after,fieldset[disabled] .rp-btn.active>a:only-child:after,fieldset[disabled] .rp-btn:active>a:only-child:after,fieldset[disabled] .rp-btn:focus>a:only-child:after,fieldset[disabled] .rp-btn:hover>a:only-child:after,fieldset[disabled] .rp-btn>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn:hover{color:#57a3f3;background-color:#fff;border-color:#57a3f3}.rp-btn:hover>a:only-child{color:currentColor}.rp-btn:hover>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn.active,.rp-btn:active{color:#2b85e4;background-color:#fff;border-color:#2b85e4}.rp-btn.active>a:only-child,.rp-btn:active>a:only-child{color:currentColor}.rp-btn.active>a:only-child:after,.rp-btn:active>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn:focus{-webkit-box-shadow:0 0 0 2px rgba(45,140,240,.2);box-shadow:0 0 0 2px rgba(45,140,240,.2)}.rp-btn-long{width:100%}.rp-btn>.rp-icon+span,.rp-btn>span+.rp-icon{margin-left:4px}.rp-table{width:inherit;max-height:280px;max-width:100%;overflow:auto;color:#495060;font-size:12px;background-color:#fff;-webkit-box-sizing:border-box;box-sizing:border-box}.rp-table:before{content:"";width:100%;height:1px;position:absolute;left:0;bottom:0;background-color:#dddee1;z-index:1}.rp-table:after{content:"";width:1px;height:100%;position:absolute;top:0;right:0;background-color:#dddee1;z-index:3}.rp-table-body{overflow:auto}.rp-table td,.rp-table th{min-width:0;height:48px;-webkit-box-sizing:border-box;box-sizing:border-box;text-align:left;text-overflow:ellipsis;vertical-align:middle;border-bottom:1px solid #e9eaec}.rp-table th{height:40px;white-space:nowrap;overflow:hidden;background-color:#f8f8f9}.rp-table td{background-color:#fff;-webkit-transition:background-color .2s ease-in-out;transition:background-color .2s ease-in-out}//.rp-table-cell span{display:none}.rp-table-cell{display:inline-block;word-wrap:normal;vertical-align:middle}.rp-table-cell{padding-top:5px; padding-bottom:5px; padding-left:18px;padding-right:18px;overflow:hidden;text-overflow:ellipsis;white-space:normal;word-break:break-all;-webkit-box-sizing:border-box;box-sizing:border-box}td.rp-table-column-end,th.rp-table-column-end{text-align: end;padding-right: 10px;}td.rp-table-column-right,th.rp-table-column-right{text-align:right}.rp-table table{table-layout:fixed;width: 100%;}.rp-btn-primary{color:#fff;background-color:#2d8cf0;border-color:#2d8cf0;}.rp-btn-primary>a:only-child{color:currentColor}.rp-btn-primary>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn-primary:hover{color:#fff;background-color:#57a3f3;border-color:#57a3f3}.rp-btn-primary:hover>a:only-child{color:currentColor}.rp-btn-primary:hover>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn-primary.active,.rp-btn-primary:active{color:#f2f2f2;background-color:#2b85e4;border-color:#2b85e4}.rp-btn-primary.active>a:only-child,.rp-btn-primary:active>a:only-child{color:currentColor}.rp-btn-primary.active>a:only-child:after,.rp-btn-primary:active>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn-primary.disabled,.rp-btn-primary.disabled.active,.rp-btn-primary.disabled:active,.rp-btn-primary.disabled:focus,.rp-btn-primary.disabled:hover,.rp-btn-primary[disabled],.rp-btn-primary[disabled].active,.rp-btn-primary[disabled]:active,.rp-btn-primary[disabled]:focus,.rp-btn-primary[disabled]:hover,fieldset[disabled] .rp-btn-primary,fieldset[disabled] .rp-btn-primary.active,fieldset[disabled] .rp-btn-primary:active,fieldset[disabled] .rp-btn-primary:focus,fieldset[disabled] .rp-btn-primary:hover{color:#bbbec4;background-color:#f7f7f7;border-color:#dddee1}.rp-btn-primary.disabled.active>a:only-child,.rp-btn-primary.disabled:active>a:only-child,.rp-btn-primary.disabled:focus>a:only-child,.rp-btn-primary.disabled:hover>a:only-child,.rp-btn-primary.disabled>a:only-child,.rp-btn-primary[disabled].active>a:only-child,.rp-btn-primary[disabled]:active>a:only-child,.rp-btn-primary[disabled]:focus>a:only-child,.rp-btn-primary[disabled]:hover>a:only-child,.rp-btn-primary[disabled]>a:only-child,fieldset[disabled] .rp-btn-primary.active>a:only-child,fieldset[disabled] .rp-btn-primary:active>a:only-child,fieldset[disabled] .rp-btn-primary:focus>a:only-child,fieldset[disabled] .rp-btn-primary:hover>a:only-child,fieldset[disabled] .rp-btn-primary>a:only-child{color:currentColor}.rp-btn-primary.disabled.active>a:only-child:after,.rp-btn-primary.disabled:active>a:only-child:after,.rp-btn-primary.disabled:focus>a:only-child:after,.rp-btn-primary.disabled:hover>a:only-child:after,.rp-btn-primary.disabled>a:only-child:after,.rp-btn-primary[disabled].active>a:only-child:after,.rp-btn-primary[disabled]:active>a:only-child:after,.rp-btn-primary[disabled]:focus>a:only-child:after,.rp-btn-primary[disabled]:hover>a:only-child:after,.rp-btn-primary[disabled]>a:only-child:after,fieldset[disabled] .rp-btn-primary.active>a:only-child:after,fieldset[disabled] .rp-btn-primary:active>a:only-child:after,fieldset[disabled] .rp-btn-primary:focus>a:only-child:after,fieldset[disabled] .rp-btn-primary:hover>a:only-child:after,fieldset[disabled] .rp-btn-primary>a:only-child:after{content:"";position:absolute;top:0;left:0;bottom:0;right:0;background:0 0}.rp-btn-primary.active,.rp-btn-primary:active,.rp-btn-primary:hover{color:#fff}.rp-btn-primary:focus{-webkit-box-shadow:0 0 0 2px rgba(45,140,240,.2);box-shadow:0 0 0 2px rgba(45,140,240,.2)}.rp-btn-group:not(.rp-btn-group-vertical) .rp-btn-primary:not(:first-child):not(:last-child){border-right-color:#2b85e4;border-left-color:#2b85e4}.rp-btn-group:not(.rp-btn-group-vertical) .rp-btn-primary:first-child:not(:last-child){border-right-color:#2b85e4}.rp-btn-group:not(.rp-btn-group-vertical) .rp-btn-primary:first-child:not(:last-child)[disabled]{border-right-color:#dddee1}.rp-btn-group:not(.rp-btn-group-vertical) .rp-btn-primary+.rp-btn,.rp-btn-group:not(.rp-btn-group-vertical) .rp-btn-primary:last-child:not(:first-child){border-left-color:#2b85e4}.rp-btn-group:not(.rp-btn-group-vertical) .rp-btn-primary+.rp-btn[disabled],.rp-btn-group:not(.rp-btn-group-vertical) .rp-btn-primary:last-child:not(:first-child)[disabled]{border-left-color:#dddee1}.rp-btn-group-vertical .rp-btn-primary:not(:first-child):not(:last-child){border-top-color:#2b85e4;border-bottom-color:#2b85e4}.rp-btn-group-vertical .rp-btn-primary:first-child:not(:last-child){border-bottom-color:#2b85e4}.rp-btn-group-vertical .rp-btn-primary:first-child:not(:last-child)[disabled]{border-top-color:#dddee1}.rp-btn-group-vertical .rp-btn-primary+.rp-btn,.rp-btn-group-vertical .rp-btn-primary:last-child:not(:first-child){border-top-color:#2b85e4}.rp-btn-group-vertical .rp-btn-primary+.rp-btn[disabled],.rp-btn-group-vertical .rp-btn-primary:last-child:not(:first-child)[disabled]{border-bottom-color:#dddee1}#card-tips{margin-top: 5px;}.rp-btn-small {padding: 2px 7px;font-size: 12px;border-radius: 3px;margin:5px;}';