From 76431bab8098f43f21385d3dd699ade644ed011e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 17:13:08 +0000 Subject: [PATCH] deploy: 674341f4ba3cb2800b8683f5102b0b4bdbdcf709 --- 404.html | 6 +++--- assets/js/22.1d0593c0.js | 1 + assets/js/23.b1e5ac82.js | 1 + assets/js/app.5410f95b.js | 16 ++++++++++++++++ index.html | 26 +++++++++++++------------- zh/index.html | 26 +++++++++++++------------- 6 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 assets/js/22.1d0593c0.js create mode 100644 assets/js/23.b1e5ac82.js create mode 100644 assets/js/app.5410f95b.js diff --git a/404.html b/404.html index 8697399e..cdab521b 100644 --- a/404.html +++ b/404.html @@ -8,13 +8,13 @@ - + -

404

Looks like we've got some broken links.
+ - + diff --git a/assets/js/22.1d0593c0.js b/assets/js/22.1d0593c0.js new file mode 100644 index 00000000..43e57279 --- /dev/null +++ b/assets/js/22.1d0593c0.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{305:function(e,t,r){"use strict";r.r(t);var a=r(10),s=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"🐋-awesome-ttrss"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#🐋-awesome-ttrss"}},[e._v("#")]),e._v(" 🐋 Awesome TTRSS")]),e._v(" "),t("p",[t("img",{attrs:{src:"https://img.shields.io/docker/pulls/wangqiru/ttrss.svg",alt:"Docker Pulls"}}),e._v(" "),t("img",{attrs:{src:"https://img.shields.io/docker/stars/wangqiru/ttrss.svg",alt:"Docker Stars"}}),e._v(" "),t("img",{attrs:{src:"https://img.shields.io/docker/automated/wangqiru/ttrss.svg",alt:"Docker Automated build"}}),e._v(" "),t("img",{attrs:{src:"https://app.fossa.com/api/projects/git%2Bgithub.com%2FHenryQW%2FAwesome-TTRSS.svg?type=shield",alt:"FOSSA Status"}})]),e._v(" "),t("h2",{attrs:{id:"about"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#about"}},[e._v("#")]),e._v(" About")]),e._v(" "),t("p",[e._v("🐋 Awesome TTRSS aims to provide a powerful "),t("strong",[e._v("Dockerized all-in-one")]),e._v(" solution for "),t("a",{attrs:{href:"https://tt-rss.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Tiny Tiny RSS"),t("OutboundLink")],1),e._v(", an open source RSS feed reader and aggregator written in PHP, with enhanced user experience via simplified deployment and a list of curated plugins.")]),e._v(" "),t("h2",{attrs:{id:"special-thanks"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#special-thanks"}},[e._v("#")]),e._v(" Special Thanks")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://opencollective.com/awesome-ttrss#support",target:"_blank",rel:"noopener noreferrer"}},[t("img",{attrs:{src:"https://opencollective.com/awesome-ttrss/backers.svg",alt:"Backers"}}),t("OutboundLink")],1)]),e._v(" "),t("h2",{attrs:{id:"deployment"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#deployment"}},[e._v("#")]),e._v(" Deployment")]),e._v(" "),t("p",[e._v("A VPS is highly recommended to host your Awesome TTRSS instance, a VPS can be obtained from as little as $5/month at "),t("a",{attrs:{href:"https://m.do.co/c/d6ef3c80105c",target:"_blank",rel:"noopener noreferrer"}},[e._v("DigitalOcean"),t("OutboundLink")],1),e._v(". Alternatively, you may request for personalized support, fully-managed service or fully-managed VPS via sponsoring Awesome TTRSS on its "),t("a",{attrs:{href:"https://opencollective.com/Awesome-TTRSS/",target:"_blank",rel:"noopener noreferrer"}},[e._v("💰OpenCollective page"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("Awesome TTRSS supports multiple architectures "),t("Badge",{attrs:{text:"x86 ✓",vertical:"top",type:"tip"}}),t("Badge",{attrs:{text:"arm32v7 ✓",vertical:"top",type:"tip"}}),t("Badge",{attrs:{text:"arm64v8 ✓",vertical:"top",type:"tip"}}),e._v(", except the OpenCC API.")],1),e._v(" "),t("h3",{attrs:{id:"deployment-via-docker"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#deployment-via-docker"}},[e._v("#")]),e._v(" Deployment via docker")]),e._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[e._v("docker")]),e._v(" run "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-it")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--name")]),e._v(" ttrss "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--restart")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("always "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("\\")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-e")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("SELF_URL_PATH")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v(" your public URL "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("\\")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-e")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("DB_HOST")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v(" your DB address "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("\\")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-e")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("DB_PORT")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v(" your DB port "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("\\")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-e")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("DB_NAME")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v(" your DB name "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("\\")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-e")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("DB_USER")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v(" your DB user "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("\\")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-e")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("DB_PASS")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v(" your DB password "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("\\")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-p")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v(" public port "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(":80 "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("\\")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" wangqiru/ttrss\n")])])]),t("h3",{attrs:{id:"deployment-via-docker-compose"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#deployment-via-docker-compose"}},[e._v("#")]),e._v(" Deployment via Docker Compose")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://github.com/HenryQW/Awesome-TTRSS/blob/main/docker-compose.yml",target:"_blank",rel:"noopener noreferrer"}},[e._v("docker-compose.yml"),t("OutboundLink")],1),e._v(" include 4 docker images:")]),e._v(" "),t("ol",[t("li",[t("a",{attrs:{href:"https://hub.docker.com/r/wangqiru/ttrss",target:"_blank",rel:"noopener noreferrer"}},[e._v("TTRSS"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://hub.docker.com/_/postgres",target:"_blank",rel:"noopener noreferrer"}},[e._v("PostgreSQL"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://hub.docker.com/r/wangqiru/mercury-parser-api",target:"_blank",rel:"noopener noreferrer"}},[e._v("Mercury Parser API"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://hub.docker.com/r/wangqiru/opencc-api-server",target:"_blank",rel:"noopener noreferrer"}},[e._v("OpenCC API"),t("OutboundLink")],1),e._v(" "),t("Badge",{attrs:{text:"arm32v7 ✗",vertical:"top",type:"error"}}),t("Badge",{attrs:{text:"arm64v8 ✗",vertical:"top",type:"error"}})],1)]),e._v(" "),t("h4",{attrs:{id:"steps"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#steps"}},[e._v("#")]),e._v(" Steps")]),e._v(" "),t("ol",[t("li",[e._v("Download "),t("a",{attrs:{href:"https://github.com/HenryQW/Awesome-TTRSS/blob/main/docker-compose.yml",target:"_blank",rel:"noopener noreferrer"}},[e._v("docker-compose.yml"),t("OutboundLink")],1),e._v(" to any directory.")]),e._v(" "),t("li",[e._v("Read "),t("code",[e._v("docker-compose.yml")]),e._v(" and change the settings (please ensure you have changed the password for postgres).")]),e._v(" "),t("li",[e._v("Run "),t("code",[e._v("docker compose up -d")]),e._v(" and wait for the deployment to finish.")]),e._v(" "),t("li",[e._v("Access ttrss via port 181, with default credentials "),t("code",[e._v("admin")]),e._v(" and "),t("code",[e._v("password")]),e._v(", please change them asap.")]),e._v(" "),t("li",[t("code",[e._v("wangqiru/mercury-parser-api")]),e._v(" and "),t("code",[e._v("wangqiru/opencc-api-server")]),e._v(" are optional service containers to support additional features, removing them will not affect TTRSS's basic functionalities.")])]),e._v(" "),t("h3",{attrs:{id:"supported-environment-variables"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#supported-environment-variables"}},[e._v("#")]),e._v(" Supported Environment Variables")]),e._v(" "),t("ul",[t("li",[e._v("SELF_URL_PATH: the url to your TTRSS instance. "),t("strong",[e._v("🔴 Please note that this value should be consistent with the URL you see in your browser address bar, otherwise TTRSS will not start.")])]),e._v(" "),t("li",[e._v("DB_HOST: the address of your database")]),e._v(" "),t("li",[e._v("DB_PORT: the port of your database")]),e._v(" "),t("li",[e._v("DB_NAME: the name of your database")]),e._v(" "),t("li",[e._v("DB_USER: the user of your Database")]),e._v(" "),t("li",[e._v("DB_PASS: the password of your database")]),e._v(" "),t("li",[e._v("DB_USER_FILE: Docker Secrets support(alternative to DB_USER), the file containing the user of your database")]),e._v(" "),t("li",[e._v("DB_PASS_FILE: Docker Secrets support(alternative to DB_PASS), the file containing the password of your database")]),e._v(" "),t("li",[e._v("ENABLE_PLUGINS: the plugins you'd like to enable as global plugins, note that "),t("code",[e._v("auth_internal")]),e._v(" is required")]),e._v(" "),t("li",[e._v("ALLOW_PORTS: comma-separated port numbers, eg:"),t("code",[e._v("1200,3000")]),e._v(". Allow subscription of non-'80,443' port feed. "),t("strong",[e._v("🔴 Use with caution.")])]),e._v(" "),t("li",[e._v("SESSION_COOKIE_LIFETIME: the expiry time in hours for your login session cookie in hours, default to "),t("code",[e._v("24")]),e._v(" hours")]),e._v(" "),t("li",[e._v("HTTP_PROXY: "),t("code",[e._v("ip:port")]),e._v(", the global proxy for your TTRSS instance, to set proxy on a per feed basis, use "),t("a",{attrs:{href:"#options-per-feed"}},[e._v("Options per Feed")])]),e._v(" "),t("li",[e._v("DISABLE_USER_IN_DAYS: disable feed update for inactive users after X days without login, until the user performs a login")]),e._v(" "),t("li",[e._v("FEED_LOG_QUIET: "),t("code",[e._v("true")]),e._v(" will disable the printing of feed updating logs")])]),e._v(" "),t("p",[e._v("For more environment variables, please refer to the "),t("a",{attrs:{href:"https://git.tt-rss.org/fox/tt-rss.git/tree/classes/config.php",target:"_blank",rel:"noopener noreferrer"}},[e._v("official tt-rss repo"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h3",{attrs:{id:"configure-https"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#configure-https"}},[e._v("#")]),e._v(" Configure HTTPS")]),e._v(" "),t("p",[e._v("TTRSS container itself doesn't handle HTTPS traffic. Examples of configuring a Caddy or an Nginx reverse proxy with free SSL certificate from "),t("a",{attrs:{href:"https://letsencrypt.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Let's Encrypt"),t("OutboundLink")],1),e._v(" are shown below:")]),e._v(" "),t("div",{staticClass:"language-nginx extra-class"},[t("pre",{pre:!0,attrs:{class:"language-nginx"}},[t("code",[t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# Caddyfile")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("ttrssdev.henry.wang")])]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n reverse_proxy 127.0.0.1:181\n encode zstd gzip\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n")])])]),t("div",{staticClass:"language-nginx extra-class"},[t("pre",{pre:!0,attrs:{class:"language-nginx"}},[t("code",[t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# nginx.conf")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("upstream")]),e._v(" ttrssdev")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("server")]),e._v(" 127.0.0.1:181")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("server")])]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("listen")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("80")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("server_name")]),e._v(" ttrssdev.henry.wang")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("return")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("301")]),e._v(" https://ttrssdev.henry.wang"),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$request_uri")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("server")])]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("listen")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("443")]),e._v(" ssl")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("gzip")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("on")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("server_name")]),e._v(" ttrssdev.henry.wang")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("ssl_certificate")]),e._v(" /etc/letsencrypt/live/ttrssdev.henry.wang/fullchain.pem")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("ssl_certificate_key")]),e._v(" /etc/letsencrypt/live/ttrssdev.henry.wang/privkey.pem")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("location")]),e._v(" /")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_redirect")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("off")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_pass")]),e._v(" http://ttrssdev")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_set_header")]),e._v(" Host "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$http_host")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_set_header")]),e._v(" X-Real-IP "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$remote_addr")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_set_header")]),e._v(" X-Forwarded-Ssl "),t("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("on")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_set_header")]),e._v(" X-Forwarded-For "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$proxy_add_x_forwarded_for")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_set_header")]),e._v(" X-Forwarded-Proto "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$scheme")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_set_header")]),e._v(" X-Frame-Options SAMEORIGIN")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("client_max_body_size")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("100m")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("client_body_buffer_size")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("128k")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_buffer_size")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("4k")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_buffers")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("4")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("32k")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_busy_buffers_size")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64k")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token directive"}},[t("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("proxy_temp_file_write_size")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64k")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n")])])]),t("p",[t("strong",[e._v("🔴 Please note that "),t("a",{attrs:{href:"#supported-environment-variables"}},[e._v("the value in you "),t("code",[e._v("SELF_URL_PATH")]),e._v(" should be changed as well.")])])]),e._v(" "),t("h2",{attrs:{id:"update"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#update"}},[e._v("#")]),e._v(" Update")]),e._v(" "),t("p",[e._v("Awesome TTRSS automatically keeps up with TTRSS by mirroring the official releases, this means update can be issued frequently.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://community.tt-rss.org/t/versioning-changes-for-trunk/2974",target:"_blank",rel:"noopener noreferrer"}},[e._v("TTRSS stopped releasing tags"),t("OutboundLink")],1),e._v(". "),t("code",[e._v("wangqiru/ttrss:latest")]),e._v(" will sync with "),t("a",{attrs:{href:"https://git.tt-rss.org/fox/tt-rss",target:"_blank",rel:"noopener noreferrer"}},[e._v("TTRSS' main branch"),t("OutboundLink")],1),e._v(" periodically.")]),e._v(" "),t("h3",{attrs:{id:"manual-update"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#manual-update"}},[e._v("#")]),e._v(" Manual Update")]),e._v(" "),t("p",[e._v("You can fetch the latest image manually:")]),e._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[e._v("docker")]),e._v(" pull wangqiru/ttrss:latest\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# docker pull wangqiru/mercury-parser-api:latest")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# docker pull wangqiru/opencc-api-server:latest")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("docker")]),e._v(" compose up "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# If you didn't use docker compose, I'm sure you know what to do.")]),e._v("\n")])])]),t("h3",{attrs:{id:"auto-update"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#auto-update"}},[e._v("#")]),e._v(" Auto Update")]),e._v(" "),t("p",[e._v("The example "),t("a",{attrs:{href:"#deployment-via-docker-compose"}},[e._v("Docker Compose")]),e._v(" includes "),t("a",{attrs:{href:"https://github.com/containrrr/watchtower",target:"_blank",rel:"noopener noreferrer"}},[e._v("Watchtower"),t("OutboundLink")],1),e._v(", which automatically pulls all containers included in Awesome TTRSS (and other containers running on your system) and refreshes your running services. By default, it's disabled, "),t("strong",[e._v("make sure it will not affect your other service containers before enabling this.")])]),e._v(" "),t("p",[e._v("To exclude images, check the following for disabling auto update for containers:")]),e._v(" "),t("div",{staticClass:"language-yml extra-class"},[t("pre",{pre:!0,attrs:{class:"language-yml"}},[t("code",[t("span",{pre:!0,attrs:{class:"token key atrule"}},[e._v("service.mercury")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(":")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[e._v("image")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(":")]),e._v(" wangqiru/mercury"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("-")]),e._v("parser"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("-")]),e._v("api"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(":")]),e._v("latest\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[e._v("container_name")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(":")]),e._v(" mercury\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[e._v("expose")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(":")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("-")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("3000")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[e._v("restart")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(":")]),e._v(" always\n "),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# ⬇️ this prevents Watchtower from auto updating mercury-parser-api")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token key atrule"}},[e._v("labels")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(":")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("-")]),e._v(" com.centurylinklabs.watchtower.enable=false\n")])])]),t("h2",{attrs:{id:"database-upgrade-or-migration"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#database-upgrade-or-migration"}},[e._v("#")]),e._v(" Database Upgrade or Migration")]),e._v(" "),t("p",[e._v("Postgres major version upgrades (15->16) will require some manual operations.\nSometimes breaking changes will be introduced to further optimize Awesome TTRSS.")]),e._v(" "),t("h3",{attrs:{id:"steps-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#steps-2"}},[e._v("#")]),e._v(" Steps")]),e._v(" "),t("div",{staticClass:"custom-block warning"},[t("p",{staticClass:"custom-block-title"},[e._v("WARNING")]),e._v(" "),t("p",[e._v("Do not skip multiple major versions when upgrading Postgres, for example, upgrading from 13.x to 16.x directly is not supported and may cause data loss.")])]),e._v(" "),t("p",[e._v("This section demonstrates the steps to upgrade Postgres major version (from 15.x to 16.x) or migrate from other images to postgres:alpine.")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Stop all the service containers:")]),e._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[e._v("docker")]),e._v(" compose stop\n")])])])]),e._v(" "),t("li",[t("p",[e._v("Copy the Postgres data volume "),t("code",[e._v("~/postgres/data/")]),e._v(" (or the location specified in your Docker Compose file) to somewhere else as a backup, "),t("strong",[e._v("THIS IS IMPORTANT")]),e._v(".")])]),e._v(" "),t("li",[t("p",[e._v("Use the following command to dump all your data:")]),e._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[e._v("docker")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v("exec")]),e._v(" postgres pg_dumpall "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-c")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-U")]),e._v(" YourUsername "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v(">")]),e._v(" export.sql\n")])])])]),e._v(" "),t("li",[t("p",[e._v("Delete the Postgres data volume "),t("code",[e._v("~/postgres/data/")]),e._v(".")])]),e._v(" "),t("li",[t("p",[e._v("Update your Docker Compose file ("),t("strong",[e._v("Note that the "),t("code",[e._v("DB_NAME")]),e._v(" must not be changed")]),e._v(") with "),t("code",[e._v("database.postgres")]),e._v(" section in the the latest "),t("a",{attrs:{href:"https://github.com/HenryQW/Awesome-TTRSS/blob/main/docker-compose.yml",target:"_blank",rel:"noopener noreferrer"}},[e._v("docker-compose.yml"),t("OutboundLink")],1),e._v(", and bring it up:")]),e._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[e._v("docker")]),e._v(" compose up "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v("\n")])])])]),e._v(" "),t("li",[t("p",[e._v("Use the following command to restore all your data:")]),e._v(" "),t("div",{staticClass:"language-bash extra-class"},[t("pre",{pre:!0,attrs:{class:"language-bash"}},[t("code",[t("span",{pre:!0,attrs:{class:"token function"}},[e._v("cat")]),e._v(" export.sql "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("docker")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v("exec")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-i")]),e._v(" postgres psql "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-U")]),e._v(" YourUsername\n")])])])]),e._v(" "),t("li",[t("p",[e._v("Test if everything works fine, and now you may remove the backup in step 2.")])])]),e._v(" "),t("h2",{attrs:{id:"plugins"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#plugins"}},[e._v("#")]),e._v(" Plugins")]),e._v(" "),t("h3",{attrs:{id:"mercury-fulltext-extraction"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#mercury-fulltext-extraction"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/HenryQW/mercury_fulltext",target:"_blank",rel:"noopener noreferrer"}},[e._v("Mercury Fulltext Extraction"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("Fetch fulltext of articles via a self-hosted Mercury Parser API. A separate Mercury Parser API is required, the example "),t("a",{attrs:{href:"#deployment-via-docker-compose"}},[e._v("Docker Compose")]),e._v(" has already included "),t("a",{attrs:{href:"https://github.com/HenryQW/mercury-parser-api",target:"_blank",rel:"noopener noreferrer"}},[e._v("such a server"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h4",{attrs:{id:"steps-3"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#steps-3"}},[e._v("#")]),e._v(" Steps")]),e._v(" "),t("ol",[t("li",[e._v("Enable "),t("code",[e._v("mercury-fulltext")]),e._v(" plugin in preference\n"),t("img",{attrs:{src:"https://share.henry.wang/92AGp5/x9xYB93cnX+",alt:"enable Mercury"}})]),e._v(" "),t("li",[e._v("Enter Mercury Parser API endpoint\n"),t("img",{attrs:{src:"https://share.henry.wang/9HJemY/BlTnDhuUGC+",alt:"enter Mercury Parser API endpoint"}})])]),e._v(" "),t("p",[e._v("Use "),t("code",[e._v("service.mercury:3000")]),e._v(" for Mercury instance deployed via Awesome-TTRSS.")]),e._v(" "),t("h4",{attrs:{id:"extraction-button"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#extraction-button"}},[e._v("#")]),e._v(" Extraction Button")]),e._v(" "),t("img",{attrs:{src:"https://share.henry.wang/ubHtDz/uxyKk68jqY+",width:"400"}}),e._v(" "),t("h3",{attrs:{id:"fever-api"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#fever-api"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/DigitalDJ/tinytinyrss-fever-plugin",target:"_blank",rel:"noopener noreferrer"}},[e._v("Fever API"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("Provide Fever API simulation.")]),e._v(" "),t("h4",{attrs:{id:"steps-4"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#steps-4"}},[e._v("#")]),e._v(" Steps")]),e._v(" "),t("ol",[t("li",[e._v("Enable API in preference\n"),t("img",{attrs:{src:"https://share.henry.wang/X2AnXi/bVVDg9mGDm+",alt:"enable API"}})]),e._v(" "),t("li",[e._v("Enter a password for Fever in preference\n"),t("img",{attrs:{src:"https://share.henry.wang/HspODo/xRSbZQheVN+",alt:"enter a Fever password"}})]),e._v(" "),t("li",[e._v("In supported RSS readers, use "),t("code",[e._v("https://[your url]/plugins/fever")]),e._v(" as the target server address, with your account and the password set in Step 2.")]),e._v(" "),t("li",[e._v("The plugin communicates with TTRSS using an unsalted MD5 hash, "),t("a",{attrs:{href:"#configure-https"}},[e._v("using HTTPS")]),e._v(" is strongly recommended.")])]),e._v(" "),t("h3",{attrs:{id:"opencc-simp-trad-chinese-conversion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#opencc-simp-trad-chinese-conversion"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/HenryQW/ttrss_opencc",target:"_blank",rel:"noopener noreferrer"}},[e._v("OpenCC Simp-Trad Chinese Conversion"),t("OutboundLink")],1),e._v(" "),t("Badge",{attrs:{text:"arm32v7 ✗",vertical:"top",type:"error"}}),t("Badge",{attrs:{text:"arm64v8 ✗",vertical:"top",type:"error"}})],1),e._v(" "),t("p",[e._v("Conversion between Traditional and Simplified Chinese via "),t("a",{attrs:{href:"https://github.com/BYVoid/OpenCC",target:"_blank",rel:"noopener noreferrer"}},[e._v("OpenCC"),t("OutboundLink")],1),e._v(" , a separate "),t("a",{attrs:{href:"https://github.com/HenryQW/OpenCC.henry.wang",target:"_blank",rel:"noopener noreferrer"}},[e._v("OpenCC API Server"),t("OutboundLink")],1),e._v(" is required. the example "),t("a",{attrs:{href:"#deployment-via-docker-compose"}},[e._v("Docker Compose")]),e._v(" has already included "),t("a",{attrs:{href:"https://github.com/HenryQW/OpenCC.henry.wang",target:"_blank",rel:"noopener noreferrer"}},[e._v("such a server"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h4",{attrs:{id:"steps-5"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#steps-5"}},[e._v("#")]),e._v(" Steps")]),e._v(" "),t("ol",[t("li",[e._v("Enable "),t("code",[e._v("opencc")]),e._v(" plugin in preference\n"),t("img",{attrs:{src:"https://share.henry.wang/EvN5Nl/2RHNnMV2iP+",alt:"enable opencc"}})]),e._v(" "),t("li",[e._v("Enter OpenCC API endpoint\n"),t("img",{attrs:{src:"https://share.henry.wang/pePHAz/oWXX3I18hW+",alt:"enter OpenCC API endpoint"}})])]),e._v(" "),t("p",[e._v("Use "),t("code",[e._v("service.opencc:3000")]),e._v(" for OpenCC instance deployed via Awesome-TTRSS.")]),e._v(" "),t("h4",{attrs:{id:"conversion-button"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conversion-button"}},[e._v("#")]),e._v(" Conversion Button")]),e._v(" "),t("img",{attrs:{src:"https://share.henry.wang/30kbTr/lSaHKXk5NT+",width:"400"}}),e._v(" "),t("h3",{attrs:{id:"feedreader-api"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#feedreader-api"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/jangernert/FeedReader/tree/master/data/tt-rss-feedreader-plugin",target:"_blank",rel:"noopener noreferrer"}},[e._v("FeedReader API"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("Provide FeedReader API support.")]),e._v(" "),t("p",[e._v("System plugin, enabled by adding "),t("code",[e._v("api_feedreader")]),e._v(" to the environment variable "),t("strong",[e._v("ENABLE_PLUGINS")]),e._v(".")]),e._v(" "),t("p",[e._v("Refer to "),t("a",{attrs:{href:"https://github.com/jangernert/FeedReader/tree/master/data/tt-rss-feedreader-plugin",target:"_blank",rel:"noopener noreferrer"}},[e._v("FeedReader API"),t("OutboundLink")],1),e._v(" for more details.")]),e._v(" "),t("h3",{attrs:{id:"news-api"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#news-api"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/voidstern/tt-rss-newsplus-plugin/",target:"_blank",rel:"noopener noreferrer"}},[e._v("News+ API"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("Provide a faster two-way synchronization for Android App "),t("a",{attrs:{href:"http://github.com/noinnion/newsplus/",target:"_blank",rel:"noopener noreferrer"}},[e._v("News+"),t("OutboundLink")],1),e._v(" and iOS App "),t("a",{attrs:{href:"http://cocoacake.net/apps/fiery/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Fiery Feeds"),t("OutboundLink")],1),e._v(" with TTRSS.")]),e._v(" "),t("p",[e._v("System plugin, enabled by adding "),t("code",[e._v("api_newsplus")]),e._v(" to the environment variable "),t("strong",[e._v("ENABLE_PLUGINS")]),e._v(".")]),e._v(" "),t("p",[e._v("Refer to "),t("a",{attrs:{href:"https://github.com/voidstern/tt-rss-newsplus-plugin/",target:"_blank",rel:"noopener noreferrer"}},[e._v("News+ API"),t("OutboundLink")],1),e._v(" for more details.")]),e._v(" "),t("h3",{attrs:{id:"feediron"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#feediron"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/feediron/ttrss_plugin-feediron",target:"_blank",rel:"noopener noreferrer"}},[e._v("Feediron"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("Provide the ability to manipulate article DOMs.")]),e._v(" "),t("p",[e._v("Refer to "),t("a",{attrs:{href:"https://github.com/feediron/ttrss_plugin-feediron",target:"_blank",rel:"noopener noreferrer"}},[e._v("Feediron"),t("OutboundLink")],1),e._v(" for more details.")]),e._v(" "),t("h3",{attrs:{id:"options-per-feed"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#options-per-feed"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/sergey-dryabzhinsky/options_per_feed",target:"_blank",rel:"noopener noreferrer"}},[e._v("Options per Feed"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("Provide the ability to configure proxy, user-agent and SSL certificate verification on a per feed basis.")]),e._v(" "),t("p",[e._v("Refer to "),t("a",{attrs:{href:"https://github.com/sergey-dryabzhinsky/options_per_feed",target:"_blank",rel:"noopener noreferrer"}},[e._v("Options per Feed"),t("OutboundLink")],1),e._v(" for more details.")]),e._v(" "),t("h3",{attrs:{id:"remove-iframe-sandbox"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#remove-iframe-sandbox"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/DIYgod/ttrss-plugin-remove-iframe-sandbox",target:"_blank",rel:"noopener noreferrer"}},[e._v("Remove iframe sandbox"),t("OutboundLink")],1)]),e._v(" "),t("div",{staticClass:"custom-block warning"},[t("p",{staticClass:"custom-block-title"},[e._v("WARNING")]),e._v(" "),t("p",[e._v("If you are getting data via fever api, enable it by adding "),t("code",[e._v("remove_iframe_sandbox")]),e._v(" to the environment variable "),t("strong",[e._v("ENABLE_PLUGINS")]),e._v(".")]),e._v(" "),t("p",[e._v("This plugin cannot be enabled in conjunction with "),t("code",[e._v("Fever API")]),e._v(" as global plugins, if you require both plugins:")]),e._v(" "),t("ol",[t("li",[e._v("In "),t("code",[e._v("ENABLE_PLUGINS")]),e._v(" replace "),t("code",[e._v("fever")]),e._v(" with "),t("code",[e._v("remove_iframe_sandbox")]),e._v(" to enable this as a global plugin.")]),e._v(" "),t("li",[e._v("Enable "),t("code",[e._v("Fever API")]),e._v(" in the TTRSS preferences panel after login, as a local plugin.")])])]),e._v(" "),t("p",[e._v("Remove the sandbox attribute on iframes, thus enabling playback of embedded video in feeds.")]),e._v(" "),t("p",[e._v("Refer to "),t("a",{attrs:{href:"https://github.com/DIYgod/ttrss-plugin-remove-iframe-sandbox",target:"_blank",rel:"noopener noreferrer"}},[e._v("Remove iframe sandbox"),t("OutboundLink")],1),e._v("。")]),e._v(" "),t("h3",{attrs:{id:"wallabag-v2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#wallabag-v2"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/joshp23/ttrss-to-wallabag-v2",target:"_blank",rel:"noopener noreferrer"}},[e._v("Wallabag v2"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("Save articles to Wallabag.")]),e._v(" "),t("p",[e._v("Refer to "),t("a",{attrs:{href:"https://github.com/joshp23/ttrss-to-wallabag-v2",target:"_blank",rel:"noopener noreferrer"}},[e._v("Wallabag v2"),t("OutboundLink")],1),e._v("。")]),e._v(" "),t("h3",{attrs:{id:"auth-oidc"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#auth-oidc"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://dev.tt-rss.org/tt-rss/ttrss-auth-oidc",target:"_blank",rel:"noopener noreferrer"}},[e._v("Auth OIDC"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This is a system plugin, that allow users to connect through an oidc provider, like Keycloak, to TTRSS.")]),e._v(" "),t("p",[e._v("System plugin, enabled by adding "),t("code",[e._v("auth_oidc")]),e._v(" to the environment variable "),t("strong",[e._v("ENABLE_PLUGINS")]),e._v(".")]),e._v(" "),t("p",[e._v("Then add the following environments variables with according values :")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",[t("code",[e._v("```yaml\n AUTH_OIDC_NAME: 'IDP provider name displayed'\n AUTH_OIDC_URL: 'https://oidc.hostname.com'\n AUTH_OIDC_CLIENT_ID: 'test-rss'\n AUTH_OIDC_CLIENT_SECRET: 'your-secret-token'\n```\n")])])]),t("p",[e._v("Refer to "),t("a",{attrs:{href:"https://dev.tt-rss.org/tt-rss/ttrss-auth-oidc",target:"_blank",rel:"noopener noreferrer"}},[e._v("Auth OIDC"),t("OutboundLink")],1),e._v(" for more details.")]),e._v(" "),t("h2",{attrs:{id:"themes"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#themes"}},[e._v("#")]),e._v(" Themes")]),e._v(" "),t("h3",{attrs:{id:"feedly"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#feedly"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/levito/tt-rss-feedly-theme",target:"_blank",rel:"noopener noreferrer"}},[e._v("Feedly"),t("OutboundLink")],1)]),e._v(" "),t("p",[t("img",{attrs:{src:"https://share.henry.wang/f3WNje/Q7RoLBSUFp+",alt:"Feedly"}})]),e._v(" "),t("h3",{attrs:{id:"rsshub"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rsshub"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/DIYgod/ttrss-theme-rsshub",target:"_blank",rel:"noopener noreferrer"}},[e._v("RSSHub"),t("OutboundLink")],1)]),e._v(" "),t("p",[t("img",{attrs:{src:"https://share.henry.wang/E5Lifa/1ykvdTWuew+",alt:"RssHub"}})]),e._v(" "),t("h2",{attrs:{id:"recommendation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#recommendation"}},[e._v("#")]),e._v(" Recommendation")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://docs.rsshub.app/en/",target:"_blank",rel:"noopener noreferrer"}},[e._v("RSSHub"),t("OutboundLink")],1),e._v(" is an interesting place for discovering RSS feeds.")]),e._v(" "),t("li",[e._v("For iOS and macOS user, the integrated "),t("a",{attrs:{href:"https://github.com/DigitalDJ/tinytinyrss-fever-plugin",target:"_blank",rel:"noopener noreferrer"}},[e._v("Fever plugin"),t("OutboundLink")],1),e._v(" supplies "),t("a",{attrs:{href:"http://reederapp.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Reeder 5"),t("OutboundLink")],1),e._v(" backend support.")]),e._v(" "),t("li",[e._v("For Android user, the integrated "),t("a",{attrs:{href:"https://github.com/DigitalDJ/tinytinyrss-fever-plugin",target:"_blank",rel:"noopener noreferrer"}},[e._v("Fever plugin"),t("OutboundLink")],1),e._v(" supplies "),t("a",{attrs:{href:"http://github.com/noinnion/newsplus/",target:"_blank",rel:"noopener noreferrer"}},[e._v("News+"),t("OutboundLink")],1),e._v(" backend support.")]),e._v(" "),t("li",[e._v("For Linux user, the integrated "),t("a",{attrs:{href:"https://github.com/jangernert/FeedReader/tree/master/data/tt-rss-feedreader-plugin",target:"_blank",rel:"noopener noreferrer"}},[e._v("FeedReader API"),t("OutboundLink")],1),e._v(" supplies "),t("a",{attrs:{href:"https://jangernert.github.io/FeedReader/",target:"_blank",rel:"noopener noreferrer"}},[e._v("FeedReader"),t("OutboundLink")],1),e._v(" backend support.")])]),e._v(" "),t("h2",{attrs:{id:"support-and-help"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#support-and-help"}},[e._v("#")]),e._v(" Support and Help")]),e._v(" "),t("ul",[t("li",[e._v("You may request for personalized support via sponsoring Awesome TTRSS on its "),t("a",{attrs:{href:"https://opencollective.com/Awesome-TTRSS/",target:"_blank",rel:"noopener noreferrer"}},[e._v("💰OpenCollective page"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("li",[e._v("Read "),t("a",{attrs:{href:"https://henry.wang/2018/04/25/ttrss-docker-plugins-guide.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("this guide"),t("OutboundLink")],1),e._v(" might help.")]),e._v(" "),t("li",[e._v("Open an issue via "),t("a",{attrs:{href:"https://github.com/HenryQW/Awesome-TTRSS/issues",target:"_blank",rel:"noopener noreferrer"}},[e._v("GitHub issue"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("li",[t("a",{attrs:{href:"https://tt-rss.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Direct donation to TTRSS"),t("OutboundLink")],1),e._v(".")])]),e._v(" "),t("h2",{attrs:{id:"donation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#donation"}},[e._v("#")]),e._v(" Donation")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("PayPal")]),e._v(" "),t("th",[e._v("WeChat Pay")]),e._v(" "),t("th",[e._v("OpenCollective")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[t("a",{attrs:{href:"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MTM5L6T4PHRQS&source=url",target:"_blank",rel:"noopener noreferrer"}},[t("img",{attrs:{src:"https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif",alt:"paypal"}}),t("OutboundLink")],1)]),e._v(" "),t("td",[t("img",{attrs:{src:"https://share.henry.wang/IKaxAW/duFgAuOnmk+",width:"200"}})]),e._v(" "),t("td",[t("a",{attrs:{href:"https://opencollective.com/Awesome-TTRSS/",target:"_blank",rel:"noopener noreferrer"}},[e._v("💰OpenCollective page"),t("OutboundLink")],1)])])])]),e._v(" "),t("h2",{attrs:{id:"license"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#license"}},[e._v("#")]),e._v(" License")]),e._v(" "),t("p",[e._v("MIT")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://app.fossa.com/projects/git%2Bgithub.com%2FHenryQW%2FAwesome-TTRSS?ref=badge_large",target:"_blank",rel:"noopener noreferrer"}},[t("img",{attrs:{src:"https://app.fossa.com/api/projects/git%2Bgithub.com%2FHenryQW%2FAwesome-TTRSS.svg?type=large",alt:"FOSSA Status"}}),t("OutboundLink")],1)])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/23.b1e5ac82.js b/assets/js/23.b1e5ac82.js new file mode 100644 index 00000000..d740d48c --- /dev/null +++ b/assets/js/23.b1e5ac82.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{306:function(t,e,r){"use strict";r.r(e);var a=r(10),s=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"🐋-awesome-ttrss"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#🐋-awesome-ttrss"}},[t._v("#")]),t._v(" 🐋 Awesome TTRSS")]),t._v(" "),e("p",[e("img",{attrs:{src:"https://img.shields.io/docker/pulls/wangqiru/ttrss.svg",alt:"Docker Pulls"}}),t._v(" "),e("img",{attrs:{src:"https://img.shields.io/docker/stars/wangqiru/ttrss.svg",alt:"Docker Stars"}}),t._v(" "),e("img",{attrs:{src:"https://img.shields.io/docker/automated/wangqiru/ttrss.svg",alt:"Docker Automated build"}}),t._v(" "),e("img",{attrs:{src:"https://app.fossa.com/api/projects/git%2Bgithub.com%2FHenryQW%2FAwesome-TTRSS.svg?type=shield",alt:"FOSSA Status"}})]),t._v(" "),e("h2",{attrs:{id:"关于"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#关于"}},[t._v("#")]),t._v(" 关于")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://tt-rss.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tiny Tiny RSS"),e("OutboundLink")],1),t._v(" 是一款基于 PHP 的免费开源 RSS 聚合阅读器。🐋 Awesome TTRSS 旨在提供一个 "),e("strong",[t._v("「一站式容器化」")]),t._v(" 的 Tiny Tiny RSS 解决方案,通过提供简易的部署方式以及一些额外插件,以提升用户体验。")]),t._v(" "),e("h2",{attrs:{id:"鸣谢"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#鸣谢"}},[t._v("#")]),t._v(" 鸣谢")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://opencollective.com/awesome-ttrss#support",target:"_blank",rel:"noopener noreferrer"}},[e("img",{attrs:{src:"https://opencollective.com/awesome-ttrss/backers.svg",alt:"赞助者"}}),e("OutboundLink")],1)]),t._v(" "),e("h2",{attrs:{id:"部署"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#部署"}},[t._v("#")]),t._v(" 部署")]),t._v(" "),e("p",[t._v("推荐使用一台 VPS 来部署您的 Awesome TTRSS 实例,"),e("a",{attrs:{href:"https://m.do.co/c/d6ef3c80105c",target:"_blank",rel:"noopener noreferrer"}},[t._v("DigitalOcean"),e("OutboundLink")],1),t._v(" 提供高性价比的 VPS 仅需 $5/月。除此之外,通过 Awesome TTRSS 的 "),e("a",{attrs:{href:"https://opencollective.com/Awesome-TTRSS/",target:"_blank",rel:"noopener noreferrer"}},[t._v("💰OpenCollective 页面"),e("OutboundLink")],1),t._v(" 进行赞助,即可获得定制支持,全托管服务,全托管 VPS 等私人服务。")]),t._v(" "),e("p",[t._v("Awesome TTRSS 支持多架构 "),e("Badge",{attrs:{text:"x86 ✓",vertical:"top",type:"tip"}}),e("Badge",{attrs:{text:"arm32v7 ✓",vertical:"top",type:"tip"}}),e("Badge",{attrs:{text:"arm64v8 ✓",vertical:"top",type:"tip"}}),t._v("(暂不包括 OpenCC API)。")],1),t._v(" "),e("h3",{attrs:{id:"通过-docker-部署"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#通过-docker-部署"}},[t._v("#")]),t._v(" 通过 Docker 部署")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("docker")]),t._v(" run "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-it")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("--name")]),t._v(" ttrss "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("--restart")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("always "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-e")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("SELF_URL_PATH")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" TTRSS 实例地址 "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-e")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("DB_HOST")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" 数据库地址 "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-e")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("DB_PORT")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" 数据库端口 "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-e")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("DB_NAME")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" 数据库名称 "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-e")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("DB_USER")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" 数据库用户名 "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-e")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("DB_PASS")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" 数据库密码 "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-p")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" 容器对外映射端口 "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(":80 "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-d")]),t._v(" wangqiru/ttrss\n")])])]),e("h3",{attrs:{id:"通过-docker-compose-部署"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#通过-docker-compose-部署"}},[t._v("#")]),t._v(" 通过 Docker Compose 部署")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://github.com/HenryQW/Awesome-TTRSS/blob/main/docker-compose.yml",target:"_blank",rel:"noopener noreferrer"}},[t._v("docker-compose.yml"),e("OutboundLink")],1),t._v(" 包含了 4 个镜像:")]),t._v(" "),e("ol",[e("li",[e("a",{attrs:{href:"https://hub.docker.com/r/wangqiru/ttrss",target:"_blank",rel:"noopener noreferrer"}},[t._v("TTRSS"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://hub.docker.com/_/postgres",target:"_blank",rel:"noopener noreferrer"}},[t._v("PostgreSQL"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://hub.docker.com/r/wangqiru/mercury-parser-api",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mercury Parser API"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://hub.docker.com/r/wangqiru/opencc-api-server",target:"_blank",rel:"noopener noreferrer"}},[t._v("OpenCC API"),e("OutboundLink")],1),t._v(" "),e("Badge",{attrs:{text:"arm32v7 ✗",vertical:"top",type:"error"}}),e("Badge",{attrs:{text:"arm64v8 ✗",vertical:"top",type:"error"}})],1)]),t._v(" "),e("h4",{attrs:{id:"步骤"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#步骤"}},[t._v("#")]),t._v(" 步骤")]),t._v(" "),e("ol",[e("li",[t._v("下载 "),e("a",{attrs:{href:"https://github.com/HenryQW/Awesome-TTRSS/blob/main/docker-compose.yml",target:"_blank",rel:"noopener noreferrer"}},[t._v("docker-compose.yml"),e("OutboundLink")],1),t._v(" 至任意目录。")]),t._v(" "),e("li",[t._v("更改 "),e("code",[t._v("docker-compose.yml")]),t._v(" 中的设置,请务必更改 postgres 用户密码。")]),t._v(" "),e("li",[t._v("通过终端在同目录下运行 "),e("code",[t._v("docker compose up -d")]),t._v(" 后等待部署完成。")]),t._v(" "),e("li",[t._v("默认通过 181 端口访问 TTRSS,默认账户:"),e("code",[t._v("admin")]),t._v(" 密码:"),e("code",[t._v("password")]),t._v(",请第一时间更改。")]),t._v(" "),e("li",[e("code",[t._v("wangqiru/mercury-parser-api")]),t._v(" 及 "),e("code",[t._v("wangqiru/opencc-api-server")]),t._v(" 为支持高级功能而加入的可选服务类容器,删除不会影响 TTRSS 基础功能。")])]),t._v(" "),e("h3",{attrs:{id:"支持的环境变量列表"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#支持的环境变量列表"}},[t._v("#")]),t._v(" 支持的环境变量列表")]),t._v(" "),e("ul",[e("li",[t._v("SELF_URL_PATH: TTRSS 实例地址。"),e("strong",[t._v("🔴 请注意,该变量值必须与你在浏览器中用于访问 TTRSS 的 URL 保持完全一致,否则 TTRSS 将无法启动。")])]),t._v(" "),e("li",[t._v("DB_HOST: 数据库地址")]),t._v(" "),e("li",[t._v("DB_PORT: 数据库端口")]),t._v(" "),e("li",[t._v("DB_NAME: 数据库名字")]),t._v(" "),e("li",[t._v("DB_USER: 数据库用户名")]),t._v(" "),e("li",[t._v("DB_PASS: 数据库密码")]),t._v(" "),e("li",[t._v("DB_USER_FILE: Docker Secrets 支持(替代 DB_USE),包含数据库用户名的文件")]),t._v(" "),e("li",[t._v("DB_PASS_FILE: Docker Secrets 支持(替代 DB_PASS),包含数据库密码的文件")]),t._v(" "),e("li",[t._v("ENABLE_PLUGINS: 全局启用的插件名称,其中 "),e("code",[t._v("auth_internal")]),t._v(" 为必须启用的登录插件")]),t._v(" "),e("li",[t._v("ALLOW_PORTS: 逗号分隔端口号,如"),e("code",[t._v("1200,3000")]),t._v("。允许订阅非 80,443 端口的源。"),e("strong",[t._v("🔴 谨慎使用。")])]),t._v(" "),e("li",[t._v("SESSION_COOKIE_LIFETIME: 使用网页版登陆时 cookie 过期时间,单位为小时,默认为 "),e("code",[t._v("24")]),t._v(" 小时")]),t._v(" "),e("li",[t._v("HTTP_PROXY: "),e("code",[t._v("ip:port")]),t._v(", TTRSS 实例的全局代理,为源地址添加单独代理请使用 "),e("a",{attrs:{href:"#options-per-feed"}},[t._v("Options per Feed")])]),t._v(" "),e("li",[t._v("DISABLE_USER_IN_DAYS: 当用户 X 天后没有登录后,停止为其自动更新订阅源,直至用户再次登陆")]),t._v(" "),e("li",[t._v("FEED_LOG_QUIET: true 禁用订阅源更新所产生的日志打印")])]),t._v(" "),e("p",[t._v("更多环境变量,参见 "),e("a",{attrs:{href:"https://git.tt-rss.org/fox/tt-rss.git/tree/classes/config.php",target:"_blank",rel:"noopener noreferrer"}},[t._v("官方 tt-rss"),e("OutboundLink")],1),t._v("。")]),t._v(" "),e("h3",{attrs:{id:"配置-https"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#配置-https"}},[t._v("#")]),t._v(" 配置 HTTPS")]),t._v(" "),e("p",[t._v("TTRSS 容器自身不负责使用 HTTPS 加密通信。参见下方的样例自行配置 Caddy 或 Nginx 反向代理。使用 "),e("a",{attrs:{href:"https://letsencrypt.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Let's Encrypt"),e("OutboundLink")],1),t._v(" 可以获取免费 SSL 证书。")]),t._v(" "),e("div",{staticClass:"language-nginx extra-class"},[e("pre",{pre:!0,attrs:{class:"language-nginx"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Caddyfile")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ttrssdev.henry.wang")])]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n reverse_proxy 127.0.0.1:181\n encode zstd gzip\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("div",{staticClass:"language-nginx extra-class"},[e("pre",{pre:!0,attrs:{class:"language-nginx"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# nginx.conf")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("upstream")]),t._v(" ttrssdev")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("server")]),t._v(" 127.0.0.1:181")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("server")])]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("listen")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("80")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("server_name")]),t._v(" ttrssdev.henry.wang")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("301")]),t._v(" https://ttrssdev.henry.wang"),e("span",{pre:!0,attrs:{class:"token variable"}},[t._v("$request_uri")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("server")])]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("listen")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("443")]),t._v(" ssl")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("gzip")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("on")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("server_name")]),t._v(" ttrssdev.henry.wang")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ssl_certificate")]),t._v(" /etc/letsencrypt/live/ttrssdev.henry.wang/fullchain.pem")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ssl_certificate_key")]),t._v(" /etc/letsencrypt/live/ttrssdev.henry.wang/privkey.pem")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("location")]),t._v(" /")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_redirect")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("off")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_pass")]),t._v(" http://ttrssdev")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_set_header")]),t._v(" Host "),e("span",{pre:!0,attrs:{class:"token variable"}},[t._v("$http_host")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_set_header")]),t._v(" X-Real-IP "),e("span",{pre:!0,attrs:{class:"token variable"}},[t._v("$remote_addr")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_set_header")]),t._v(" X-Forwarded-Ssl "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("on")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_set_header")]),t._v(" X-Forwarded-For "),e("span",{pre:!0,attrs:{class:"token variable"}},[t._v("$proxy_add_x_forwarded_for")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_set_header")]),t._v(" X-Forwarded-Proto "),e("span",{pre:!0,attrs:{class:"token variable"}},[t._v("$scheme")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_set_header")]),t._v(" X-Frame-Options SAMEORIGIN")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("client_max_body_size")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("100m")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("client_body_buffer_size")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("128k")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_buffer_size")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("4k")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_buffers")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("32k")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_busy_buffers_size")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("64k")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token directive"}},[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("proxy_temp_file_write_size")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("64k")])]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[e("strong",[t._v("🔴 请注意, "),e("a",{attrs:{href:"#supported-environment-variables"}},[t._v("你需要更新 "),e("code",[t._v("SELF_URL_PATH")]),t._v(" 环境变量。")])])]),t._v(" "),e("h2",{attrs:{id:"更新"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#更新"}},[t._v("#")]),t._v(" 更新")]),t._v(" "),e("p",[t._v("Awesome TTRSS 会自动监控 TTRSS 官方更新并与之同步,这意味着更新会比较频繁。")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://community.tt-rss.org/t/versioning-changes-for-trunk/2974",target:"_blank",rel:"noopener noreferrer"}},[t._v("TTRSS 官方不再释出 tag"),e("OutboundLink")],1),t._v("。 "),e("code",[t._v("wangqiru/ttrss:latest")]),t._v(" 会与 "),e("a",{attrs:{href:"https://git.tt-rss.org/fox/tt-rss",target:"_blank",rel:"noopener noreferrer"}},[t._v("官方 main branch"),e("OutboundLink")],1),t._v(" 同步。")]),t._v(" "),e("h3",{attrs:{id:"手动更新"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#手动更新"}},[t._v("#")]),t._v(" 手动更新")]),t._v(" "),e("p",[t._v("通过以下命令进行手动更新:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("docker")]),t._v(" pull wangqiru/ttrss:latest\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# docker pull wangqiru/mercury-parser-api:latest")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# docker pull wangqiru/opencc-api-server:latest")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("docker")]),t._v(" compose up "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-d")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 如果您没有使用 docker compose,我确信您知道该怎么做。")]),t._v("\n")])])]),e("h3",{attrs:{id:"自动更新"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#自动更新"}},[t._v("#")]),t._v(" 自动更新")]),t._v(" "),e("p",[e("a",{attrs:{href:"#%E9%80%9A%E8%BF%87-docker-compose-%E9%83%A8%E7%BD%B2"}},[t._v("样例 Docker Compose")]),t._v(" 中包含了 "),e("a",{attrs:{href:"https://github.com/containrrr/watchtower",target:"_blank",rel:"noopener noreferrer"}},[t._v("Watchtower"),e("OutboundLink")],1),t._v(",它会自动拉取并更新您所有的服务容器 (包括当前系统上运行的非 Awesome TTRSS 服务的容器)。该服务默认关闭,"),e("strong",[t._v("启用前请确认它将不会影响您其他的服务容器。")])]),t._v(" "),e("p",[t._v("您也可以设置 watchtower 忽略您的其他容器:")]),t._v(" "),e("div",{staticClass:"language-yml extra-class"},[e("pre",{pre:!0,attrs:{class:"language-yml"}},[e("code",[e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("service.mercury")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("image")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" wangqiru/mercury"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("parser"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v("api"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("latest\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("container_name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" mercury\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("expose")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3000")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("restart")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" always\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# ⬇️ 这将使 Watchtower 跳过对 mercury-parser-api 的更新检测")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token key atrule"}},[t._v("labels")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("-")]),t._v(" com.centurylinklabs.watchtower.enable=false\n")])])]),e("h2",{attrs:{id:"数据库更新或迁移"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#数据库更新或迁移"}},[t._v("#")]),t._v(" 数据库更新或迁移")]),t._v(" "),e("p",[t._v("Postgres 大版本更新 (15->16) 需要额外的步骤来确保服务正常运行。\n为了更好地优化 Awesome TTRSS,有时候可能会推出一些破坏性更新。")]),t._v(" "),e("h3",{attrs:{id:"步骤-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#步骤-2"}},[t._v("#")]),t._v(" 步骤")]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("注意")]),t._v(" "),e("p",[t._v("在升级时,请勿跳过多个大版本,例如直接从 13.x 升级到 16.x 是不支援的,并可能导致数据丢失。")])]),t._v(" "),e("p",[t._v("这些步骤演示了如何进行 Postgres 大版本更新(从 15.x 至 16.x),或者从其他镜像迁移至 postgres:alpine。")]),t._v(" "),e("ol",[e("li",[e("p",[t._v("停止所有服务容器:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("docker")]),t._v(" compose stop\n")])])])]),t._v(" "),e("li",[e("p",[t._v("复制 Postgres 数据卷 "),e("code",[t._v("~/postgres/data/")]),t._v("(或者你在 Docker Compose 中指定的目录)至其他任何地方作为备份,这非常重要!")])]),t._v(" "),e("li",[e("p",[t._v("执行如下命令来导出所有数据:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("docker")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("exec")]),t._v(" postgres pg_dumpall "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-c")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-U")]),t._v(" 数据库用户名 "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" export.sql\n")])])])]),t._v(" "),e("li",[e("p",[t._v("删除 Postgres 数据卷 "),e("code",[t._v("~/postgres/data/")]),t._v("。")])]),t._v(" "),e("li",[e("p",[t._v("根据最新 "),e("a",{attrs:{href:"https://github.com/HenryQW/Awesome-TTRSS/blob/main/docker-compose.yml",target:"_blank",rel:"noopener noreferrer"}},[t._v("docker-compose.yml"),e("OutboundLink")],1),t._v(" 中的"),e("code",[t._v("database.postgres")]),t._v(" 部份来更新你的 Docker Compose 文件("),e("strong",[t._v("注意 "),e("code",[t._v("DB_NAME")]),t._v(" 不可更改")]),t._v("),并启动:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("docker")]),t._v(" compose up "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-d")]),t._v("\n")])])])]),t._v(" "),e("li",[e("p",[t._v("执行如下命令来导入所有数据:")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("cat")]),t._v(" export.sql "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("docker")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("exec")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-i")]),t._v(" postgres psql "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-U")]),t._v(" 数据库用户名\n")])])])]),t._v(" "),e("li",[e("p",[t._v("测试所有服务是否正常工作,现在你可以移除步骤二中的备份了。")])])]),t._v(" "),e("h2",{attrs:{id:"插件"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#插件"}},[t._v("#")]),t._v(" 插件")]),t._v(" "),e("h3",{attrs:{id:"mercury-全文获取"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#mercury-全文获取"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/HenryQW/mercury_fulltext",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mercury 全文获取"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("全文内容提取插件,配合单独的 Mercury Parser API 服务器使用。"),e("a",{attrs:{href:"#%E9%80%9A%E8%BF%87-docker-compose-%E9%83%A8%E7%BD%B2"}},[t._v("样例 Docker Compose")]),t._v(" 中已经包含了 "),e("a",{attrs:{href:"https://github.com/HenryQW/mercury-parser-api",target:"_blank",rel:"noopener noreferrer"}},[t._v("HenryQW/mercury-parser-api"),e("OutboundLink")],1),t._v(" 服务器。")]),t._v(" "),e("h4",{attrs:{id:"设置步骤"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#设置步骤"}},[t._v("#")]),t._v(" 设置步骤")]),t._v(" "),e("ol",[e("li",[t._v("在设置中启用 "),e("code",[t._v("mercury-fulltext")]),t._v(" 插件\n"),e("img",{attrs:{src:"https://share.henry.wang/92AGp5/x9xYB93cnX+",alt:"启用 Mercury"}})]),t._v(" "),e("li",[t._v("在设置中填入 Mercury Parser API 地址\n"),e("img",{attrs:{src:"https://share.henry.wang/9HJemY/BlTnDhuUGC+",alt:"填入 Mercury Parser API 地址"}})])]),t._v(" "),e("p",[t._v("使用 Awesome-TTRSS 部署的 mercury 可填写"),e("code",[t._v("service.mercury:3000")]),t._v("。")]),t._v(" "),e("h4",{attrs:{id:"全文提取按钮"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#全文提取按钮"}},[t._v("#")]),t._v(" 全文提取按钮")]),t._v(" "),e("img",{attrs:{src:"https://share.henry.wang/ubHtDz/uxyKk68jqY+",width:"400"}}),t._v(" "),e("h3",{attrs:{id:"fever-api"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#fever-api"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/DigitalDJ/tinytinyrss-fever-plugin",target:"_blank",rel:"noopener noreferrer"}},[t._v("Fever API"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("提供 Fever API 支持。")]),t._v(" "),e("h4",{attrs:{id:"设置步骤-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#设置步骤-2"}},[t._v("#")]),t._v(" 设置步骤")]),t._v(" "),e("ol",[e("li",[t._v("在设置中启用 API。\n"),e("img",{attrs:{src:"https://share.henry.wang/X2AnXi/bVVDg9mGDm+",alt:"启用 API"}})]),t._v(" "),e("li",[t._v("在插件设置中设置 Fever 密码。\n"),e("img",{attrs:{src:"https://share.henry.wang/HspODo/xRSbZQheVN+",alt:"设置 Fever 密码"}})]),t._v(" "),e("li",[t._v("在支持 Fever 的阅读器用,使用 "),e("code",[t._v("https://[您的地址]/plugins/fever")]),t._v(" 作为服务器地址。使用您的账号和步骤 2 中的密码登录。")]),t._v(" "),e("li",[t._v("由于该插件使用未加盐的 MD5 加密密码进行通信,强烈建议 "),e("a",{attrs:{href:"#%E9%85%8D%E7%BD%AE-https"}},[t._v("开启 HTTPS")]),t._v("。")])]),t._v(" "),e("h3",{attrs:{id:"opencc-繁简转换"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#opencc-繁简转换"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/HenryQW/ttrss_opencc",target:"_blank",rel:"noopener noreferrer"}},[t._v("OpenCC 繁简转换"),e("OutboundLink")],1),t._v(" "),e("Badge",{attrs:{text:"arm32v7 ✗",vertical:"top",type:"error"}}),e("Badge",{attrs:{text:"arm64v8 ✗",vertical:"top",type:"error"}})],1),t._v(" "),e("p",[t._v("使用 "),e("a",{attrs:{href:"https://github.com/BYVoid/OpenCC",target:"_blank",rel:"noopener noreferrer"}},[t._v("OpenCC"),e("OutboundLink")],1),t._v(" 为 TTRSS 提供中文繁转简的插件,需要配合单独的 OpenCC API 服务器使用。"),e("a",{attrs:{href:"#%E9%80%9A%E8%BF%87-docker-compose-%E9%83%A8%E7%BD%B2"}},[t._v("样例 Docker Compose")]),t._v(" 中已经包含了 "),e("a",{attrs:{href:"https://github.com/HenryQW/OpenCC.henry.wang",target:"_blank",rel:"noopener noreferrer"}},[t._v("HenryQW/OpenCC.henry.wang"),e("OutboundLink")],1),t._v(" 服务器。")]),t._v(" "),e("h4",{attrs:{id:"设置步骤-3"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#设置步骤-3"}},[t._v("#")]),t._v(" 设置步骤")]),t._v(" "),e("ol",[e("li",[t._v("在设置中启用 "),e("code",[t._v("opencc")]),t._v(" 插件\n"),e("img",{attrs:{src:"https://share.henry.wang/EvN5Nl/2RHNnMV2iP+",alt:"启用 opencc"}})]),t._v(" "),e("li",[t._v("在设置中填入 OpenCC API 地址\n"),e("img",{attrs:{src:"https://share.henry.wang/pePHAz/oWXX3I18hW+",alt:"填入 OpenCC API 地址"}})])]),t._v(" "),e("p",[t._v("使用 Awesome-TTRSS 部署的 OpenCC 可填写"),e("code",[t._v("service.opencc:3000")]),t._v("。")]),t._v(" "),e("h4",{attrs:{id:"转换按钮"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#转换按钮"}},[t._v("#")]),t._v(" 转换按钮")]),t._v(" "),e("img",{attrs:{src:"https://share.henry.wang/30kbTr/lSaHKXk5NT+",width:"400"}}),t._v(" "),e("h3",{attrs:{id:"feedreader-api"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#feedreader-api"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/jangernert/FeedReader/tree/master/data/tt-rss-feedreader-plugin",target:"_blank",rel:"noopener noreferrer"}},[t._v("FeedReader API"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("提供 FeedReader API 支持。")]),t._v(" "),e("p",[t._v("系统插件,将 "),e("code",[t._v("api_feedreader")]),t._v(" 添加到 "),e("strong",[t._v("ENABLE_PLUGINS")]),t._v(" 环境变量中以启用。")]),t._v(" "),e("p",[t._v("使用指南见 "),e("a",{attrs:{href:"https://github.com/jangernert/FeedReader/tree/master/data/tt-rss-feedreader-plugin",target:"_blank",rel:"noopener noreferrer"}},[t._v("FeedReader API"),e("OutboundLink")],1),t._v("。")]),t._v(" "),e("h3",{attrs:{id:"news-api"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#news-api"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/voidstern/tt-rss-newsplus-plugin/",target:"_blank",rel:"noopener noreferrer"}},[t._v("News+ API"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("为 Android App "),e("a",{attrs:{href:"http://github.com/noinnion/newsplus/",target:"_blank",rel:"noopener noreferrer"}},[t._v("News+"),e("OutboundLink")],1),t._v(" 和 iOS App "),e("a",{attrs:{href:"http://cocoacake.net/apps/fiery/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Fiery Feeds"),e("OutboundLink")],1),t._v(" 提供更快的同步速度。")]),t._v(" "),e("p",[t._v("系统插件,将 "),e("code",[t._v("api_newsplus")]),t._v(" 添加到 "),e("strong",[t._v("ENABLE_PLUGINS")]),t._v(" 环境变量中以启用。")]),t._v(" "),e("p",[t._v("使用指南见 "),e("a",{attrs:{href:"https://github.com/voidstern/tt-rss-newsplus-plugin/",target:"_blank",rel:"noopener noreferrer"}},[t._v("News+ API"),e("OutboundLink")],1),t._v("。")]),t._v(" "),e("h3",{attrs:{id:"feediron"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#feediron"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/feediron/ttrss_plugin-feediron",target:"_blank",rel:"noopener noreferrer"}},[t._v("Feediron"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("提供文章 DOM 操控能力的插件。")]),t._v(" "),e("p",[t._v("使用指南见 "),e("a",{attrs:{href:"https://github.com/feediron/ttrss_plugin-feediron",target:"_blank",rel:"noopener noreferrer"}},[t._v("Feediron"),e("OutboundLink")],1),t._v("。")]),t._v(" "),e("h3",{attrs:{id:"options-per-feed"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#options-per-feed"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/sergey-dryabzhinsky/options_per_feed",target:"_blank",rel:"noopener noreferrer"}},[t._v("Options per Feed"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("提供单独为源地址配置代理、user-agent 以及 SSL 证书验证的能力。")]),t._v(" "),e("p",[t._v("使用指南见 "),e("a",{attrs:{href:"https://github.com/sergey-dryabzhinsky/options_per_feed",target:"_blank",rel:"noopener noreferrer"}},[t._v("Options per Feed"),e("OutboundLink")],1),t._v("。")]),t._v(" "),e("h3",{attrs:{id:"wallabag-v2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#wallabag-v2"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/joshp23/ttrss-to-wallabag-v2",target:"_blank",rel:"noopener noreferrer"}},[t._v("Wallabag v2"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("保存文章至 Wallabag。")]),t._v(" "),e("p",[t._v("使用指南见 "),e("a",{attrs:{href:"https://github.com/joshp23/ttrss-to-wallabag-v2",target:"_blank",rel:"noopener noreferrer"}},[t._v("Wallabag v2"),e("OutboundLink")],1),t._v("。")]),t._v(" "),e("h3",{attrs:{id:"remove-iframe-sandbox"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#remove-iframe-sandbox"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/DIYgod/ttrss-plugin-remove-iframe-sandbox",target:"_blank",rel:"noopener noreferrer"}},[t._v("Remove iframe sandbox"),e("OutboundLink")],1)]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("注意")]),t._v(" "),e("p",[t._v("该插件与 "),e("code",[t._v("Fever API")]),t._v(" 不能同时作为全局插件启用。如果您同时需要两者:")]),t._v(" "),e("ol",[e("li",[t._v("在环境变量 "),e("code",[t._v("ENABLE_PLUGINS")]),t._v(" 中移除 "),e("code",[t._v("fever")]),t._v(" 并添加 "),e("code",[t._v("remove_iframe_sandbox")]),t._v(" 作为全局插件启用。")]),t._v(" "),e("li",[t._v("在登陆 TTRSS 后,通过设置将 "),e("code",[t._v("Fever API")]),t._v(" 作为本地插件启用。")])])]),t._v(" "),e("p",[t._v("移除 iframe 上的 sandbox 属性,以支持 feed 中直接播放嵌入视频。")]),t._v(" "),e("p",[t._v("使用指南见 "),e("a",{attrs:{href:"https://github.com/DIYgod/ttrss-plugin-remove-iframe-sandbox",target:"_blank",rel:"noopener noreferrer"}},[t._v("Remove iframe sandbox"),e("OutboundLink")],1),t._v("。")]),t._v(" "),e("h2",{attrs:{id:"主题"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#主题"}},[t._v("#")]),t._v(" 主题")]),t._v(" "),e("h3",{attrs:{id:"feedly"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#feedly"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/levito/tt-rss-feedly-theme",target:"_blank",rel:"noopener noreferrer"}},[t._v("Feedly"),e("OutboundLink")],1)]),t._v(" "),e("p",[e("img",{attrs:{src:"https://share.henry.wang/f3WNje/Q7RoLBSUFp+",alt:"Feedly"}})]),t._v(" "),e("h3",{attrs:{id:"rsshub"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rsshub"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/DIYgod/ttrss-theme-rsshub",target:"_blank",rel:"noopener noreferrer"}},[t._v("RSSHub"),e("OutboundLink")],1)]),t._v(" "),e("p",[e("img",{attrs:{src:"https://share.henry.wang/E5Lifa/1ykvdTWuew+",alt:"RssHub"}})]),t._v(" "),e("h2",{attrs:{id:"使用建议"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#使用建议"}},[t._v("#")]),t._v(" 使用建议")]),t._v(" "),e("ul",[e("li",[t._v("推荐使用 "),e("a",{attrs:{href:"https://docs.rsshub.app/",target:"_blank",rel:"noopener noreferrer"}},[t._v("RSSHub"),e("OutboundLink")],1),t._v(" 来发现更多有趣的订阅源。")]),t._v(" "),e("li",[t._v("对于 iOS 和 macOS 用户,内置的 "),e("a",{attrs:{href:"#fever-api"}},[t._v("Fever API 模拟插件")]),t._v(" 提供 "),e("a",{attrs:{href:"http://reederapp.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Reeder 5"),e("OutboundLink")],1),t._v(" 后端支持。")]),t._v(" "),e("li",[t._v("对于 Linux 用户,内置的 "),e("a",{attrs:{href:"#feedreader-api"}},[t._v("FeedReader API")]),t._v(" 提供 "),e("a",{attrs:{href:"https://jangernert.github.io/FeedReader/",target:"_blank",rel:"noopener noreferrer"}},[t._v("FeedReader"),e("OutboundLink")],1),t._v(" 后端支持。")])]),t._v(" "),e("h2",{attrs:{id:"支持与帮助"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#支持与帮助"}},[t._v("#")]),t._v(" 支持与帮助")]),t._v(" "),e("ul",[e("li",[t._v("通过 Awesome TTRSS 的 "),e("a",{attrs:{href:"https://opencollective.com/Awesome-TTRSS/",target:"_blank",rel:"noopener noreferrer"}},[t._v("💰OpenCollective 页面"),e("OutboundLink")],1),t._v(" 进行赞助,即可获得私人定制支持。")]),t._v(" "),e("li",[t._v("阅读此 "),e("a",{attrs:{href:"https://henry.wang/2018/04/25/ttrss-docker-plugins-guide.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("指南"),e("OutboundLink")],1),t._v(" 可能会有帮助。")]),t._v(" "),e("li",[t._v("通过 "),e("a",{attrs:{href:"https://github.com/HenryQW/Awesome-TTRSS/issues",target:"_blank",rel:"noopener noreferrer"}},[t._v("GitHub issue"),e("OutboundLink")],1),t._v(" 提交问题。")]),t._v(" "),e("li",[e("a",{attrs:{href:"https://tt-rss.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("直接捐助支持"),e("OutboundLink")],1),t._v("。")])]),t._v(" "),e("h2",{attrs:{id:"捐赠"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#捐赠"}},[t._v("#")]),t._v(" 捐赠")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("PayPal")]),t._v(" "),e("th",[t._v("微信赞赏")]),t._v(" "),e("th",[t._v("OpenCollective")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("a",{attrs:{href:"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MTM5L6T4PHRQS&source=url",target:"_blank",rel:"noopener noreferrer"}},[e("img",{attrs:{src:"https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif",alt:"paypal"}}),e("OutboundLink")],1)]),t._v(" "),e("td",[e("img",{attrs:{src:"https://share.henry.wang/IKaxAW/duFgAuOnmk+",width:"200"}})]),t._v(" "),e("td",[e("a",{attrs:{href:"https://opencollective.com/Awesome-TTRSS/",target:"_blank",rel:"noopener noreferrer"}},[t._v("💰OpenCollective page"),e("OutboundLink")],1)])])])]),t._v(" "),e("h2",{attrs:{id:"许可"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#许可"}},[t._v("#")]),t._v(" 许可")]),t._v(" "),e("p",[t._v("MIT")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://app.fossa.com/projects/git%2Bgithub.com%2FHenryQW%2FAwesome-TTRSS?ref=badge_large",target:"_blank",rel:"noopener noreferrer"}},[e("img",{attrs:{src:"https://app.fossa.com/api/projects/git%2Bgithub.com%2FHenryQW%2FAwesome-TTRSS.svg?type=large",alt:"FOSSA Status"}}),e("OutboundLink")],1)])])}),[],!1,null,null,null);e.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/app.5410f95b.js b/assets/js/app.5410f95b.js new file mode 100644 index 00000000..c394b7f6 --- /dev/null +++ b/assets/js/app.5410f95b.js @@ -0,0 +1,16 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,s=e[0],c=e[1],u=e[2],f=0,p=[];f=e||n<0||m&&t-u>=i}function x(){var t=d();if(_(t))return w(t);s=setTimeout(x,function(t){var n=e-(t-c);return m?p(n,i-(t-u)):n}(t))}function w(t){return s=void 0,y&&r?g(t):(r=o=void 0,a)}function O(){var t=d(),n=_(t);if(r=arguments,o=this,c=t,n){if(void 0===s)return b(c);if(m)return s=setTimeout(x,e),g(c)}return void 0===s&&(s=setTimeout(x,e)),a}return e=v(e)||0,h(n)&&(l=!!n.leading,i=(m="maxWait"in n)?f(v(n.maxWait)||0,e):i,y="trailing"in n?!!n.trailing:y),O.cancel=function(){void 0!==s&&clearTimeout(s),u=0,r=c=o=s=void 0},O.flush=function(){return void 0===s?a:w(d())},O}},function(t,e,n){var r,o; +/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress + * @license MIT */void 0===(o="function"==typeof(r=function(){var t,e,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function o(t,e,n){return tn?n:t}function i(t){return 100*(-1+t)}n.configure=function(t){var e,n;for(e in t)void 0!==(n=t[e])&&t.hasOwnProperty(e)&&(r[e]=n);return this},n.status=null,n.set=function(t){var e=n.isStarted();t=o(t,r.minimum,1),n.status=1===t?null:t;var c=n.render(!e),u=c.querySelector(r.barSelector),l=r.speed,f=r.easing;return c.offsetWidth,a((function(e){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(u,function(t,e,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+i(t)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+i(t)+"%,0)"}:{"margin-left":i(t)+"%"}).transition="all "+e+"ms "+n,o}(t,l,f)),1===t?(s(c,{transition:"none",opacity:1}),c.offsetWidth,setTimeout((function(){s(c,{transition:"all "+l+"ms linear",opacity:0}),setTimeout((function(){n.remove(),e()}),l)}),l)):setTimeout(e,l)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var t=function(){setTimeout((function(){n.status&&(n.trickle(),t())}),r.trickleSpeed)};return r.trickle&&t(),this},n.done=function(t){return t||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(t){var e=n.status;return e?("number"!=typeof t&&(t=(1-e)*o(Math.random()*e,.1,.95)),e=o(e+t,0,.994),n.set(e)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},t=0,e=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===e&&n.start(),t++,e++,r.always((function(){0==--e?(t=0,n.done()):n.set((t-e)/t)})),this):this},n.render=function(t){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var e=document.createElement("div");e.id="nprogress",e.innerHTML=r.template;var o,a=e.querySelector(r.barSelector),c=t?"-100":i(n.status||0),l=document.querySelector(r.parent);return s(a,{transition:"all 0 linear",transform:"translate3d("+c+"%,0,0)"}),r.showSpinner||(o=e.querySelector(r.spinnerSelector))&&p(o),l!=document.body&&u(l,"nprogress-custom-parent"),l.appendChild(e),e},n.remove=function(){l(document.documentElement,"nprogress-busy"),l(document.querySelector(r.parent),"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&p(t)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var t=document.body.style,e="WebkitTransform"in t?"Webkit":"MozTransform"in t?"Moz":"msTransform"in t?"ms":"OTransform"in t?"O":"";return e+"Perspective"in t?"translate3d":e+"Transform"in t?"translate":"margin"};var a=function(){var t=[];function e(){var n=t.shift();n&&n(e)}return function(n){t.push(n),1==t.length&&e()}}(),s=function(){var t=["Webkit","O","Moz","ms"],e={};function n(n){return n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(t,e){return e.toUpperCase()})),e[n]||(e[n]=function(e){var n=document.body.style;if(e in n)return e;for(var r,o=t.length,i=e.charAt(0).toUpperCase()+e.slice(1);o--;)if((r=t[o]+i)in n)return r;return e}(n))}function r(t,e,r){e=n(e),t.style[e]=r}return function(t,e){var n,o,i=arguments;if(2==i.length)for(n in e)void 0!==(o=e[n])&&e.hasOwnProperty(n)&&r(t,n,o);else r(t,i[1],i[2])}}();function c(t,e){return("string"==typeof t?t:f(t)).indexOf(" "+e+" ")>=0}function u(t,e){var n=f(t),r=n+e;c(n,e)||(t.className=r.substring(1))}function l(t,e){var n,r=f(t);c(t,e)&&(n=r.replace(" "+e+" "," "),t.className=n.substring(1,n.length-1))}function f(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}function p(t){t&&t.parentNode&&t.parentNode.removeChild(t)}return n})?r.call(e,n,e,t):r)||(t.exports=o)},function(t,e,n){"use strict";var r=n(0),o=n(47).f,i=n(13),a=n(92),s=n(34),c=n(62),u=n(120);t.exports=function(t,e){var n,l,f,p,d,h=t.target,v=t.global,m=t.stat;if(n=v?r:m?r[h]||s(h,{}):r[h]&&r[h].prototype)for(l in e){if(p=e[l],f=t.dontCallGetSet?(d=o(n,l))&&d.value:n[l],!u(v?l:h+(m?".":"#")+l,t.forced)&&void 0!==f){if(typeof p==typeof f)continue;c(p,f)}(t.sham||f&&f.sham)&&i(p,"sham",!0),a(n,l,p,t)}}},function(t,e,n){"use strict";var r=n(26),o=Function.prototype.call;t.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},function(t,e,n){"use strict";var r=n(3);t.exports=!r((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},function(t,e,n){"use strict";t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){"use strict";var r=n(48),o=n(29);t.exports=function(t){return r(o(t))}},function(t,e,n){"use strict";var r=n(49),o=TypeError;t.exports=function(t){if(r(t))throw new o("Can't call method on "+t);return t}},function(t,e,n){"use strict";var r=n(0),o=n(1),i=function(t){return o(t)?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t]):r[t]&&r[t][e]}},function(t,e,n){"use strict";var r=n(1),o=n(102),i=TypeError;t.exports=function(t){if(r(t))return t;throw new i(o(t)+" is not a function")}},function(t,e,n){"use strict";var r=n(0),o=n(56),i=n(8),a=n(58),s=n(54),c=n(53),u=r.Symbol,l=o("wks"),f=c?u.for||u:u&&u.withoutSetter||a;t.exports=function(t){return i(l,t)||(l[t]=s&&i(u,t)?u[t]:f("Symbol."+t)),l[t]}},function(t,e,n){"use strict";var r=n(57),o=n(0),i=n(34),a=t.exports=o["__core-js_shared__"]||i("__core-js_shared__",{});(a.versions||(a.versions=[])).push({version:"3.37.0",mode:r?"pure":"global",copyright:"© 2014-2024 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.37.0/LICENSE",source:"https://github.com/zloirock/core-js"})},function(t,e,n){"use strict";var r=n(0),o=Object.defineProperty;t.exports=function(t,e){try{o(r,t,{value:e,configurable:!0,writable:!0})}catch(n){r[t]=e}return e}},function(t,e,n){"use strict";var r=n(29),o=Object;t.exports=function(t){return o(r(t))}},function(t,e,n){"use strict";var r=n(117);t.exports=function(t){return r(t.length)}},function(t,e,n){var r=n(144),o=n(11),i=Object.prototype,a=i.hasOwnProperty,s=i.propertyIsEnumerable,c=r(function(){return arguments}())?r:function(t){return o(t)&&a.call(t,"callee")&&!s.call(t,"callee")};t.exports=c},function(t,e,n){var r=n(9)(n(7),"Map");t.exports=r},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){var r=n(164),o=n(171),i=n(173),a=n(174),s=n(175);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}},function(t,e,n){var r=n(4),o=n(44),i=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;t.exports=function(t,e){if(r(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!o(t))||(a.test(t)||!i.test(t)||null!=e&&t in Object(e))}},function(t,e,n){var r=n(12),o=n(11);t.exports=function(t){return"symbol"==typeof t||o(t)&&"[object Symbol]"==r(t)}},function(t,e){t.exports=function(t){return t}},function(t,e,n){"use strict";var r=n(24),o=n(35),i=n(36),a=n(139),s=n(141);r({target:"Array",proto:!0,arity:1,forced:n(3)((function(){return 4294967297!==[].push.call({length:4294967296},1)}))||!function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(t){return t instanceof TypeError}}()},{push:function(t){var e=o(this),n=i(e),r=arguments.length;s(n+r);for(var c=0;c0&&r[0]<4?1:+(r[0]+r[1])),!o&&a&&(!(r=a.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/))&&(o=+r[1]),t.exports=o},function(t,e,n){"use strict";var r=n(33);t.exports=function(t,e){return r[t]||(r[t]=e||{})}},function(t,e,n){"use strict";t.exports=!1},function(t,e,n){"use strict";var r=n(2),o=0,i=Math.random(),a=r(1..toString);t.exports=function(t){return"Symbol("+(void 0===t?"":t)+")_"+a(++o+i,36)}},function(t,e,n){"use strict";var r=n(5),o=n(3),i=n(104);t.exports=!r&&!o((function(){return 7!==Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},function(t,e,n){"use strict";var r=n(6),o=String,i=TypeError;t.exports=function(t){if(r(t))return t;throw new i(o(t)+" is not an object")}},function(t,e,n){"use strict";t.exports={}},function(t,e,n){"use strict";var r=n(8),o=n(111),i=n(47),a=n(15);t.exports=function(t,e,n){for(var s=o(e),c=a.f,u=i.f,l=0;ll))return!1;var p=c.get(t),d=c.get(e);if(p&&d)return p==e&&d==t;var h=-1,v=!0,m=2&n?new r:void 0;for(c.set(t,e),c.set(e,t);++h-1&&t%1==0&&t]/;t.exports=function(t){var e,n=""+t,o=r.exec(n);if(!o)return n;var i="",a=0,s=0;for(a=o.index;a79&&a<83||!i("reduce")},{reduce:function(t){var e=arguments.length;return o(this,t,e,e>1?arguments[1]:void 0)}})},function(t,e,n){"use strict";var r={}.propertyIsEnumerable,o=Object.getOwnPropertyDescriptor,i=o&&!r.call({1:2},1);e.f=i?function(t){var e=o(this,t);return!!e&&e.enumerable}:r},function(t,e,n){"use strict";var r=n(25),o=n(6),i=n(51),a=n(101),s=n(103),c=n(32),u=TypeError,l=c("toPrimitive");t.exports=function(t,e){if(!o(t)||i(t))return t;var n,c=a(t,l);if(c){if(void 0===e&&(e="default"),n=r(c,t,e),!o(n)||i(n))return n;throw new u("Can't convert object to primitive value")}return void 0===e&&(e="number"),s(t,e)}},function(t,e,n){"use strict";t.exports="undefined"!=typeof navigator&&String(navigator.userAgent)||""},function(t,e,n){"use strict";var r=n(31),o=n(49);t.exports=function(t,e){var n=t[e];return o(n)?void 0:r(n)}},function(t,e,n){"use strict";var r=String;t.exports=function(t){try{return r(t)}catch(t){return"Object"}}},function(t,e,n){"use strict";var r=n(25),o=n(1),i=n(6),a=TypeError;t.exports=function(t,e){var n,s;if("string"===e&&o(n=t.toString)&&!i(s=r(n,t)))return s;if(o(n=t.valueOf)&&!i(s=r(n,t)))return s;if("string"!==e&&o(n=t.toString)&&!i(s=r(n,t)))return s;throw new a("Can't convert object to primitive value")}},function(t,e,n){"use strict";var r=n(0),o=n(6),i=r.document,a=o(i)&&o(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},function(t,e,n){"use strict";var r=n(5),o=n(3);t.exports=r&&o((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype}))},function(t,e,n){"use strict";var r=n(5),o=n(8),i=Function.prototype,a=r&&Object.getOwnPropertyDescriptor,s=o(i,"name"),c=s&&"something"===function(){}.name,u=s&&(!r||r&&a(i,"name").configurable);t.exports={EXISTS:s,PROPER:c,CONFIGURABLE:u}},function(t,e,n){"use strict";var r=n(2),o=n(1),i=n(33),a=r(Function.toString);o(i.inspectSource)||(i.inspectSource=function(t){return a(t)}),t.exports=i.inspectSource},function(t,e,n){"use strict";var r,o,i,a=n(109),s=n(0),c=n(6),u=n(13),l=n(8),f=n(33),p=n(110),d=n(61),h=s.TypeError,v=s.WeakMap;if(a||f.state){var m=f.state||(f.state=new v);m.get=m.get,m.has=m.has,m.set=m.set,r=function(t,e){if(m.has(t))throw new h("Object already initialized");return e.facade=t,m.set(t,e),e},o=function(t){return m.get(t)||{}},i=function(t){return m.has(t)}}else{var y=p("state");d[y]=!0,r=function(t,e){if(l(t,y))throw new h("Object already initialized");return e.facade=t,u(t,y,e),e},o=function(t){return l(t,y)?t[y]:{}},i=function(t){return l(t,y)}}t.exports={set:r,get:o,has:i,enforce:function(t){return i(t)?o(t):r(t,{})},getterFor:function(t){return function(e){var n;if(!c(e)||(n=o(e)).type!==t)throw new h("Incompatible receiver, "+t+" required");return n}}}},function(t,e,n){"use strict";var r=n(0),o=n(1),i=r.WeakMap;t.exports=o(i)&&/native code/.test(String(i))},function(t,e,n){"use strict";var r=n(56),o=n(58),i=r("keys");t.exports=function(t){return i[t]||(i[t]=o(t))}},function(t,e,n){"use strict";var r=n(30),o=n(2),i=n(112),a=n(119),s=n(60),c=o([].concat);t.exports=r("Reflect","ownKeys")||function(t){var e=i.f(s(t)),n=a.f;return n?c(e,n(t)):e}},function(t,e,n){"use strict";var r=n(113),o=n(118).concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return r(t,o)}},function(t,e,n){"use strict";var r=n(2),o=n(8),i=n(28),a=n(114).indexOf,s=n(61),c=r([].push);t.exports=function(t,e){var n,r=i(t),u=0,l=[];for(n in r)!o(s,n)&&o(r,n)&&c(l,n);for(;e.length>u;)o(r,n=e[u++])&&(~a(l,n)||c(l,n));return l}},function(t,e,n){"use strict";var r=n(28),o=n(115),i=n(36),a=function(t){return function(e,n,a){var s=r(e),c=i(s);if(0===c)return!t&&-1;var u,l=o(a,c);if(t&&n!=n){for(;c>l;)if((u=s[l++])!=u)return!0}else for(;c>l;l++)if((t||l in s)&&s[l]===n)return t||l||0;return!t&&-1}};t.exports={includes:a(!0),indexOf:a(!1)}},function(t,e,n){"use strict";var r=n(63),o=Math.max,i=Math.min;t.exports=function(t,e){var n=r(t);return n<0?o(n+e,0):i(n,e)}},function(t,e,n){"use strict";var r=Math.ceil,o=Math.floor;t.exports=Math.trunc||function(t){var e=+t;return(e>0?o:r)(e)}},function(t,e,n){"use strict";var r=n(63),o=Math.min;t.exports=function(t){var e=r(t);return e>0?o(e,9007199254740991):0}},function(t,e,n){"use strict";t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(t,e,n){"use strict";e.f=Object.getOwnPropertySymbols},function(t,e,n){"use strict";var r=n(3),o=n(1),i=/#|\.prototype\./,a=function(t,e){var n=c[s(t)];return n===l||n!==u&&(o(e)?r(e):!!e)},s=a.normalize=function(t){return String(t).replace(i,".").toLowerCase()},c=a.data={},u=a.NATIVE="N",l=a.POLYFILL="P";t.exports=a},function(t,e,n){"use strict";var r=n(31),o=n(35),i=n(48),a=n(36),s=TypeError,c="Reduce of empty array with no initial value",u=function(t){return function(e,n,u,l){var f=o(e),p=i(f),d=a(f);if(r(n),0===d&&u<2)throw new s(c);var h=t?d-1:0,v=t?-1:1;if(u<2)for(;;){if(h in p){l=p[h],h+=v;break}if(h+=v,t?h<0:d<=h)throw new s(c)}for(;t?h>=0:d>h;h+=v)h in p&&(l=n(l,p[h],h,f));return l}};t.exports={left:u(!1),right:u(!0)}},function(t,e,n){"use strict";var r=n(3);t.exports=function(t,e){var n=[][t];return!!n&&r((function(){n.call(null,e||function(){return 1},1)}))}},function(t,e,n){"use strict";var r=n(0),o=n(16);t.exports="process"===o(r.process)},function(t,e,n){"use strict";var r=n(24),o=n(0),i=n(125),a=n(126),s=o.WebAssembly,c=7!==new Error("e",{cause:7}).cause,u=function(t,e){var n={};n[t]=a(t,e,c),r({global:!0,constructor:!0,arity:1,forced:c},n)},l=function(t,e){if(s&&s[t]){var n={};n[t]=a("WebAssembly."+t,e,c),r({target:"WebAssembly",stat:!0,constructor:!0,arity:1,forced:c},n)}};u("Error",(function(t){return function(e){return i(t,this,arguments)}})),u("EvalError",(function(t){return function(e){return i(t,this,arguments)}})),u("RangeError",(function(t){return function(e){return i(t,this,arguments)}})),u("ReferenceError",(function(t){return function(e){return i(t,this,arguments)}})),u("SyntaxError",(function(t){return function(e){return i(t,this,arguments)}})),u("TypeError",(function(t){return function(e){return i(t,this,arguments)}})),u("URIError",(function(t){return function(e){return i(t,this,arguments)}})),l("CompileError",(function(t){return function(e){return i(t,this,arguments)}})),l("LinkError",(function(t){return function(e){return i(t,this,arguments)}})),l("RuntimeError",(function(t){return function(e){return i(t,this,arguments)}}))},function(t,e,n){"use strict";var r=n(26),o=Function.prototype,i=o.apply,a=o.call;t.exports="object"==typeof Reflect&&Reflect.apply||(r?a.bind(i):function(){return a.apply(i,arguments)})},function(t,e,n){"use strict";var r=n(30),o=n(8),i=n(13),a=n(52),s=n(64),c=n(62),u=n(130),l=n(131),f=n(132),p=n(135),d=n(136),h=n(5),v=n(57);t.exports=function(t,e,n,m){var y=m?2:1,g=t.split("."),b=g[g.length-1],_=r.apply(null,g);if(_){var x=_.prototype;if(!v&&o(x,"cause")&&delete x.cause,!n)return _;var w=r("Error"),O=e((function(t,e){var n=f(m?e:t,void 0),r=m?new _(t):new _;return void 0!==n&&i(r,"message",n),d(r,O,r.stack,2),this&&a(x,this)&&l(r,this,O),arguments.length>y&&p(r,arguments[y]),r}));if(O.prototype=x,"Error"!==b?s?s(O,w):c(O,w,{name:!0}):h&&"stackTraceLimit"in _&&(u(O,_,"stackTraceLimit"),u(O,_,"prepareStackTrace")),c(O,_),!v)try{x.name!==b&&i(x,"name",b),x.constructor=O}catch(t){}return O}}},function(t,e,n){"use strict";var r=n(2),o=n(31);t.exports=function(t,e,n){try{return r(o(Object.getOwnPropertyDescriptor(t,e)[n]))}catch(t){}}},function(t,e,n){"use strict";var r=n(129),o=String,i=TypeError;t.exports=function(t){if(r(t))return t;throw new i("Can't set "+o(t)+" as a prototype")}},function(t,e,n){"use strict";var r=n(6);t.exports=function(t){return r(t)||null===t}},function(t,e,n){"use strict";var r=n(15).f;t.exports=function(t,e,n){n in t||r(t,n,{configurable:!0,get:function(){return e[n]},set:function(t){e[n]=t}})}},function(t,e,n){"use strict";var r=n(1),o=n(6),i=n(64);t.exports=function(t,e,n){var a,s;return i&&r(a=e.constructor)&&a!==n&&o(s=a.prototype)&&s!==n.prototype&&i(t,s),t}},function(t,e,n){"use strict";var r=n(93);t.exports=function(t,e){return void 0===t?arguments.length<2?"":e:r(t)}},function(t,e,n){"use strict";var r=n(134),o=n(1),i=n(16),a=n(32)("toStringTag"),s=Object,c="Arguments"===i(function(){return arguments}());t.exports=r?i:function(t){var e,n,r;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=function(t,e){try{return t[e]}catch(t){}}(e=s(t),a))?n:c?i(e):"Object"===(r=i(e))&&o(e.callee)?"Arguments":r}},function(t,e,n){"use strict";var r={};r[n(32)("toStringTag")]="z",t.exports="[object z]"===String(r)},function(t,e,n){"use strict";var r=n(6),o=n(13);t.exports=function(t,e){r(e)&&"cause"in e&&o(t,"cause",e.cause)}},function(t,e,n){"use strict";var r=n(13),o=n(137),i=n(138),a=Error.captureStackTrace;t.exports=function(t,e,n,s){i&&(a?a(t,e):r(t,"stack",o(n,s)))}},function(t,e,n){"use strict";var r=n(2),o=Error,i=r("".replace),a=String(new o("zxcasd").stack),s=/\n\s*at [^:]*:[^\n]*/,c=s.test(a);t.exports=function(t,e){if(c&&"string"==typeof t&&!o.prepareStackTrace)for(;e--;)t=i(t,s,"");return t}},function(t,e,n){"use strict";var r=n(3),o=n(27);t.exports=!r((function(){var t=new Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",o(1,7)),7!==t.stack)}))},function(t,e,n){"use strict";var r=n(5),o=n(140),i=TypeError,a=Object.getOwnPropertyDescriptor,s=r&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(t){return t instanceof TypeError}}();t.exports=s?function(t,e){if(o(t)&&!a(t,"length").writable)throw new i("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e}},function(t,e,n){"use strict";var r=n(16);t.exports=Array.isArray||function(t){return"Array"===r(t)}},function(t,e,n){"use strict";var r=TypeError;t.exports=function(t){if(t>9007199254740991)throw r("Maximum allowed index exceeded");return t}},function(t,e,n){var r=n(65),o=n(143);t.exports=function t(e,n,i,a,s){var c=-1,u=e.length;for(i||(i=o),s||(s=[]);++c0&&i(l)?n>1?t(l,n-1,i,a,s):r(s,l):a||(s[s.length]=l)}return s}},function(t,e,n){var r=n(14),o=n(37),i=n(4),a=r?r.isConcatSpreadable:void 0;t.exports=function(t){return i(t)||o(t)||!!(a&&t&&t[a])}},function(t,e,n){var r=n(12),o=n(11);t.exports=function(t){return o(t)&&"[object Arguments]"==r(t)}},function(t,e,n){var r=n(14),o=Object.prototype,i=o.hasOwnProperty,a=o.toString,s=r?r.toStringTag:void 0;t.exports=function(t){var e=i.call(t,s),n=t[s];try{t[s]=void 0;var r=!0}catch(t){}var o=a.call(t);return r&&(e?t[s]=n:delete t[s]),o}},function(t,e){var n=Object.prototype.toString;t.exports=function(t){return n.call(t)}},function(t,e,n){var r=n(148),o=n(204),i=n(45),a=n(4),s=n(214);t.exports=function(t){return"function"==typeof t?t:null==t?i:"object"==typeof t?a(t)?o(t[0],t[1]):r(t):s(t)}},function(t,e,n){var r=n(149),o=n(203),i=n(83);t.exports=function(t){var e=o(t);return 1==e.length&&e[0][2]?i(e[0][0],e[0][1]):function(n){return n===t||r(n,t,e)}}},function(t,e,n){var r=n(67),o=n(71);t.exports=function(t,e,n,i){var a=n.length,s=a,c=!i;if(null==t)return!s;for(t=Object(t);a--;){var u=n[a];if(c&&u[2]?u[1]!==t[u[0]]:!(u[0]in t))return!1}for(;++a-1}},function(t,e,n){var r=n(18);t.exports=function(t,e){var n=this.__data__,o=r(n,t);return o<0?(++this.size,n.push([t,e])):n[o][1]=e,this}},function(t,e,n){var r=n(17);t.exports=function(){this.__data__=new r,this.size=0}},function(t,e){t.exports=function(t){var e=this.__data__,n=e.delete(t);return this.size=e.size,n}},function(t,e){t.exports=function(t){return this.__data__.get(t)}},function(t,e){t.exports=function(t){return this.__data__.has(t)}},function(t,e,n){var r=n(17),o=n(38),i=n(40);t.exports=function(t,e){var n=this.__data__;if(n instanceof r){var a=n.__data__;if(!o||a.length<199)return a.push([t,e]),this.size=++n.size,this;n=this.__data__=new i(a)}return n.set(t,e),this.size=n.size,this}},function(t,e,n){var r=n(69),o=n(161),i=n(39),a=n(70),s=/^\[object .+?Constructor\]$/,c=Function.prototype,u=Object.prototype,l=c.toString,f=u.hasOwnProperty,p=RegExp("^"+l.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=function(t){return!(!i(t)||o(t))&&(r(t)?p:s).test(a(t))}},function(t,e,n){var r,o=n(162),i=(r=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";t.exports=function(t){return!!i&&i in t}},function(t,e,n){var r=n(7)["__core-js_shared__"];t.exports=r},function(t,e){t.exports=function(t,e){return null==t?void 0:t[e]}},function(t,e,n){var r=n(165),o=n(17),i=n(38);t.exports=function(){this.size=0,this.__data__={hash:new r,map:new(i||o),string:new r}}},function(t,e,n){var r=n(166),o=n(167),i=n(168),a=n(169),s=n(170);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}},function(t,e,n){var r=n(73),o=n(226),i=n(231),a=n(74),s=n(232),c=n(41);t.exports=function(t,e,n){var u=-1,l=o,f=t.length,p=!0,d=[],h=d;if(n)p=!1,l=i;else if(f>=200){var v=e?null:s(t);if(v)return c(v);p=!1,l=a,h=new r}else h=e?[]:d;t:for(;++u-1}},function(t,e,n){var r=n(228),o=n(229),i=n(230);t.exports=function(t,e,n){return e==e?i(t,e,n):r(t,o,n)}},function(t,e){t.exports=function(t,e,n,r){for(var o=t.length,i=n+(r?1:-1);r?i--:++i=0&&Math.floor(e)===e&&isFinite(t)}function v(t){return a(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function m(t){return null==t?"":Array.isArray(t)||p(t)&&t.toString===f?JSON.stringify(t,y,2):String(t)}function y(t,e){return e&&e.__v_isRef?e.value:e}function g(t){var e=parseFloat(t);return isNaN(e)?t:e}function b(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(r,1)}}var w=Object.prototype.hasOwnProperty;function O(t,e){return w.call(t,e)}function S(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var $=/-(\w)/g,C=S((function(t){return t.replace($,(function(t,e){return e?e.toUpperCase():""}))})),j=S((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),k=/\B([A-Z])/g,T=S((function(t){return t.replace(k,"-$1").toLowerCase()}));var E=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function P(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function A(t,e){for(var n in e)t[n]=e[n];return t}function R(t){for(var e={},n=0;n0,Q=X&&X.indexOf("edge/")>0;X&&X.indexOf("android");var tt=X&&/iphone|ipad|ipod|ios/.test(X);X&&/chrome\/\d+/.test(X),X&&/phantomjs/.test(X);var et,nt=X&&X.match(/firefox\/(\d+)/),rt={}.watch,ot=!1;if(J)try{var it={};Object.defineProperty(it,"passive",{get:function(){ot=!0}}),window.addEventListener("test-passive",null,it)}catch(t){}var at=function(){return void 0===et&&(et=!J&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),et},st=J&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ct(t){return"function"==typeof t&&/native code/.test(t.toString())}var ut,lt="undefined"!=typeof Symbol&&ct(Symbol)&&"undefined"!=typeof Reflect&&ct(Reflect.ownKeys);ut="undefined"!=typeof Set&&ct(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var ft=null;function pt(t){void 0===t&&(t=null),t||ft&&ft._scope.off(),ft=t,t&&t._scope.on()}var dt=function(){function t(t,e,n,r,o,i,a,s){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}return Object.defineProperty(t.prototype,"child",{get:function(){return this.componentInstance},enumerable:!1,configurable:!0}),t}(),ht=function(t){void 0===t&&(t="");var e=new dt;return e.text=t,e.isComment=!0,e};function vt(t){return new dt(void 0,void 0,void 0,String(t))}function mt(t){var e=new dt(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}"function"==typeof SuppressedError&&SuppressedError;var yt=0,gt=[],bt=function(){function t(){this._pending=!1,this.id=yt++,this.subs=[]}return t.prototype.addSub=function(t){this.subs.push(t)},t.prototype.removeSub=function(t){this.subs[this.subs.indexOf(t)]=null,this._pending||(this._pending=!0,gt.push(this))},t.prototype.depend=function(e){t.target&&t.target.addDep(this)},t.prototype.notify=function(t){var e=this.subs.filter((function(t){return t}));for(var n=0,r=e.length;n0&&(Xt((u=t(u,"".concat(n||"","_").concat(r)))[0])&&Xt(f)&&(p[l]=vt(f.text+u[0].text),u.shift()),p.push.apply(p,u)):c(u)?Xt(f)?p[l]=vt(f.text+u):""!==u&&p.push(vt(u)):Xt(u)&&Xt(f)?p[l]=vt(f.text+u.text):(s(e._isVList)&&a(u.tag)&&i(u.key)&&a(n)&&(u.key="__vlist".concat(n,"_").concat(r,"__")),p.push(u)));return p}(t):void 0}function Xt(t){return a(t)&&a(t.text)&&!1===t.isComment}function Yt(t,e){var n,r,i,s,c=null;if(o(t)||"string"==typeof t)for(c=new Array(t.length),n=0,r=t.length;n0,s=e?!!e.$stable:!a,c=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(s&&o&&o!==r&&c===o.$key&&!a&&!o.$hasNormal)return o;for(var u in i={},e)e[u]&&"$"!==u[0]&&(i[u]=me(t,n,u,e[u]))}else i={};for(var l in n)l in i||(i[l]=ye(n,l));return e&&Object.isExtensible(e)&&(e._normalized=i),W(i,"$stable",s),W(i,"$key",c),W(i,"$hasNormal",a),i}function me(t,e,n,r){var i=function(){var e=ft;pt(t);var n=arguments.length?r.apply(null,arguments):r({}),i=(n=n&&"object"==typeof n&&!o(n)?[n]:Jt(n))&&n[0];return pt(e),n&&(!i||1===n.length&&i.isComment&&!he(i))?void 0:n};return r.proxy&&Object.defineProperty(e,n,{get:i,enumerable:!0,configurable:!0}),i}function ye(t,e){return function(){return t[e]}}function ge(t){return{get attrs(){if(!t._attrsProxy){var e=t._attrsProxy={};W(e,"_v_attr_proxy",!0),be(e,t.$attrs,r,t,"$attrs")}return t._attrsProxy},get listeners(){t._listenersProxy||be(t._listenersProxy={},t.$listeners,r,t,"$listeners");return t._listenersProxy},get slots(){return function(t){t._slotsProxy||xe(t._slotsProxy={},t.$scopedSlots);return t._slotsProxy}(t)},emit:E(t.$emit,t),expose:function(e){e&&Object.keys(e).forEach((function(n){return Ut(t,e,n)}))}}}function be(t,e,n,r,o){var i=!1;for(var a in e)a in t?e[a]!==n[a]&&(i=!0):(i=!0,_e(t,a,r,o));for(var a in t)a in e||(i=!0,delete t[a]);return i}function _e(t,e,n,r){Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){return n[r][e]}})}function xe(t,e){for(var n in e)t[n]=e[n];for(var n in t)n in e||delete t[n]}var we=null;function Oe(t,e){return(t.__esModule||lt&&"Module"===t[Symbol.toStringTag])&&(t=t.default),l(t)?e.extend(t):t}function Se(t){if(o(t))for(var e=0;edocument.createEvent("Event").timeStamp&&(un=function(){return ln.now()})}var fn=function(t,e){if(t.post){if(!e.post)return 1}else if(e.post)return-1;return t.id-e.id};function pn(){var t,e;for(cn=un(),an=!0,en.sort(fn),sn=0;snsn&&en[n].id>t.id;)n--;en.splice(n+1,0,t)}else en.push(t);on||(on=!0,Fe(pn))}}function hn(t,e){if(t){for(var n=Object.create(null),r=lt?Reflect.ownKeys(t):Object.keys(t),o=0;o-1)if(i&&!O(o,"default"))a=!1;else if(""===a||a===T(t)){var c=In(String,o.type);(c<0||s-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!d(t)&&t.test(e)}function Yn(t,e){var n=t.cache,r=t.keys,o=t._vnode,i=t.$vnode;for(var a in n){var s=n[a];if(s){var c=s.name;c&&!e(c)&&Zn(n,a,r,o)}}i.componentOptions.children=void 0}function Zn(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,x(n,e)}Kn.prototype._init=function(t){var e=this;e._uid=Hn++,e._isVue=!0,e.__v_skip=!0,e._scope=new Bt(!0),e._scope.parent=void 0,e._scope._vm=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=En(Wn(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._provided=n?n._provided:Object.create(null),t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Je(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,n=t.$vnode=e._parentVnode,o=n&&n.context;t.$slots=pe(e._renderChildren,o),t.$scopedSlots=n?ve(t.$parent,n.data.scopedSlots,t.$slots):r,t._c=function(e,n,r,o){return $e(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return $e(t,e,n,r,o,!0)};var i=n&&n.data;At(t,"$attrs",i&&i.attrs||r,null,!0),At(t,"$listeners",e._parentListeners||r,null,!0)}(e),tn(e,"beforeCreate",void 0,!1),function(t){var e=hn(t.$options.inject,t);e&&(kt(!1),Object.keys(e).forEach((function(n){At(t,n,e[n])})),kt(!0))}(e),Fn(e),function(t){var e=t.$options.provide;if(e){var n=u(e)?e.call(t):e;if(!l(n))return;for(var r=Vt(t),o=lt?Reflect.ownKeys(n):Object.keys(n),i=0;i1?P(n):n;for(var r=P(arguments,1),o='event handler for "'.concat(t,'"'),i=0,a=n.length;iparseInt(this.max)&&Zn(t,e[0],e,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)Zn(this.cache,t,this.keys)},mounted:function(){var t=this;this.cacheVNode(),this.$watch("include",(function(e){Yn(t,(function(t){return Xn(e,t)}))})),this.$watch("exclude",(function(e){Yn(t,(function(t){return!Xn(e,t)}))}))},updated:function(){this.cacheVNode()},render:function(){var t=this.$slots.default,e=Se(t),n=e&&e.componentOptions;if(n){var r=Jn(n),o=this.include,i=this.exclude;if(o&&(!r||!Xn(o,r))||i&&r&&Xn(i,r))return e;var a=this.cache,s=this.keys,c=null==e.key?n.Ctor.cid+(n.tag?"::".concat(n.tag):""):e.key;a[c]?(e.componentInstance=a[c].componentInstance,x(s,c),s.push(c)):(this.vnodeToCache=e,this.keyToCache=c),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return V}};Object.defineProperty(t,"config",e),t.util={warn:On,extend:A,mergeOptions:En,defineReactive:At},t.set=Rt,t.delete=Lt,t.nextTick=Fe,t.observable=function(t){return Pt(t),t},t.options=Object.create(null),z.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,A(t.options.components,tr),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=P(arguments,1);return n.unshift(this),u(t.install)?t.install.apply(t,n):u(t)&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=En(this.options,t),this}}(t),Gn(t),function(t){z.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&p(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&u(n)&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(Kn),Object.defineProperty(Kn.prototype,"$isServer",{get:at}),Object.defineProperty(Kn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Kn,"FunctionalRenderContext",{value:vn}),Kn.version="2.7.16";var er=b("style,class"),nr=b("input,textarea,option,select,progress"),rr=b("contenteditable,draggable,spellcheck"),or=b("events,caret,typing,plaintext-only"),ir=b("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),ar="http://www.w3.org/1999/xlink",sr=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},cr=function(t){return sr(t)?t.slice(6,t.length):""},ur=function(t){return null==t||!1===t};function lr(t){for(var e=t.data,n=t,r=t;a(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(e=fr(r.data,e));for(;a(n=n.parent);)n&&n.data&&(e=fr(e,n.data));return function(t,e){if(a(t)||a(e))return pr(t,dr(e));return""}(e.staticClass,e.class)}function fr(t,e){return{staticClass:pr(t.staticClass,e.staticClass),class:a(t.class)?[t.class,e.class]:e.class}}function pr(t,e){return t?e?t+" "+e:t:e||""}function dr(t){return Array.isArray(t)?function(t){for(var e,n="",r=0,o=t.length;r-1?Dr(t,e,n):ir(e)?ur(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):rr(e)?t.setAttribute(e,function(t,e){return ur(e)||"false"===e?"false":"contenteditable"===t&&or(e)?e:"true"}(e,n)):sr(e)?ur(n)?t.removeAttributeNS(ar,cr(e)):t.setAttributeNS(ar,e,n):Dr(t,e,n)}function Dr(t,e,n){if(ur(n))t.removeAttribute(e);else{if(Y&&!Z&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var Nr={create:Mr,update:Mr};function Fr(t,e){var n=e.elm,r=e.data,o=t.data;if(!(i(r.staticClass)&&i(r.class)&&(i(o)||i(o.staticClass)&&i(o.class)))){var s=lr(e),c=n._transitionClasses;a(c)&&(s=pr(s,dr(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}var Ur,zr={create:Fr,update:Fr};function Br(t,e,n){var r=Ur;return function o(){var i=e.apply(null,arguments);null!==i&&Hr(t,o,n,r)}}var Vr=Pe&&!(nt&&Number(nt[1])<=53);function qr(t,e,n,r){if(Vr){var o=cn,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}Ur.addEventListener(t,e,ot?{capture:n,passive:r}:n)}function Hr(t,e,n,r){(r||Ur).removeEventListener(t,e._wrapper||e,n)}function Wr(t,e){if(!i(t.data.on)||!i(e.data.on)){var n=e.data.on||{},r=t.data.on||{};Ur=e.elm||t.elm,function(t){if(a(t.__r)){var e=Y?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}a(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(n),Wt(n,r,qr,Hr,Br,e.context),Ur=void 0}}var Kr,Gr={create:Wr,update:Wr,destroy:function(t){return Wr(t,Sr)}};function Jr(t,e){if(!i(t.data.domProps)||!i(e.data.domProps)){var n,r,o=e.elm,c=t.data.domProps||{},u=e.data.domProps||{};for(n in(a(u.__ob__)||s(u._v_attr_proxy))&&(u=e.data.domProps=A({},u)),c)n in u||(o[n]="");for(n in u){if(r=u[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),r===c[n])continue;1===o.childNodes.length&&o.removeChild(o.childNodes[0])}if("value"===n&&"PROGRESS"!==o.tagName){o._value=r;var l=i(r)?"":String(r);Xr(o,l)&&(o.value=l)}else if("innerHTML"===n&&mr(o.tagName)&&i(o.innerHTML)){(Kr=Kr||document.createElement("div")).innerHTML="".concat(r,"");for(var f=Kr.firstChild;o.firstChild;)o.removeChild(o.firstChild);for(;f.firstChild;)o.appendChild(f.firstChild)}else if(r!==c[n])try{o[n]=r}catch(t){}}}}function Xr(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,r=t._vModifiers;if(a(r)){if(r.number)return g(n)!==g(e);if(r.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Yr={create:Jr,update:Jr},Zr=S((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function Qr(t){var e=to(t.style);return t.staticStyle?A(t.staticStyle,e):e}function to(t){return Array.isArray(t)?R(t):"string"==typeof t?Zr(t):t}var eo,no=/^--/,ro=/\s*!important$/,oo=function(t,e,n){if(no.test(e))t.style.setProperty(e,n);else if(ro.test(n))t.style.setProperty(T(e),n.replace(ro,""),"important");else{var r=ao(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(uo).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" ".concat(t.getAttribute("class")||""," ");n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function fo(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(uo).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" ".concat(t.getAttribute("class")||""," "),r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function po(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&A(e,ho(t.name||"v")),A(e,t),e}return"string"==typeof t?ho(t):void 0}}var ho=S((function(t){return{enterClass:"".concat(t,"-enter"),enterToClass:"".concat(t,"-enter-to"),enterActiveClass:"".concat(t,"-enter-active"),leaveClass:"".concat(t,"-leave"),leaveToClass:"".concat(t,"-leave-to"),leaveActiveClass:"".concat(t,"-leave-active")}})),vo=J&&!Z,mo="transition",yo="transitionend",go="animation",bo="animationend";vo&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(mo="WebkitTransition",yo="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(go="WebkitAnimation",bo="webkitAnimationEnd"));var _o=J?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function xo(t){_o((function(){_o(t)}))}function wo(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),lo(t,e))}function Oo(t,e){t._transitionClasses&&x(t._transitionClasses,e),fo(t,e)}function So(t,e,n){var r=Co(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s="transition"===o?yo:bo,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout((function(){c0&&(n="transition",l=a,f=i.length):"animation"===e?u>0&&(n="animation",l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?"transition":"animation":null)?"transition"===n?i.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:"transition"===n&&$o.test(r[mo+"Property"])}}function jo(t,e){for(;t.length1}function Ro(t,e){!0!==e.data.show&&To(e)}var Lo=function(t){var e,n,r={},u=t.modules,l=t.nodeOps;for(e=0;e<$r.length;++e)for(r[$r[e]]=[],n=0;nh?_(t,i(n[y+1])?null:n[y+1].elm,n,d,y,r):d>y&&w(e,f,h)}(f,v,y,n,u):a(y)?(a(t.text)&&l.setTextContent(f,""),_(f,null,y,0,y.length-1,n)):a(v)?w(v,0,v.length-1):a(t.text)&&l.setTextContent(f,""):t.text!==e.text&&l.setTextContent(f,e.text),a(h)&&a(d=h.hook)&&a(d=d.postpatch)&&d(t,e)}}}function C(t,e,n){if(s(n)&&a(t.parent))t.parent.data.pendingInsert=e;else for(var r=0;r-1,a.selected!==i&&(a.selected=i);else if(D(Fo(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function No(t,e){return e.every((function(e){return!D(e,t)}))}function Fo(t){return"_value"in t?t._value:t.value}function Uo(t){t.target.composing=!0}function zo(t){t.target.composing&&(t.target.composing=!1,Bo(t.target,"input"))}function Bo(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function Vo(t){return!t.componentInstance||t.data&&t.data.transition?t:Vo(t.componentInstance._vnode)}var qo={model:Mo,show:{bind:function(t,e,n){var r=e.value,o=(n=Vo(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,To(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=Vo(n)).data&&n.data.transition?(n.data.show=!0,r?To(n,(function(){t.style.display=t.__vOriginalDisplay})):Eo(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},Ho={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Wo(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Wo(Se(e.children)):t}function Ko(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var r in o)e[C(r)]=o[r];return e}function Go(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Jo=function(t){return t.tag||he(t)},Xo=function(t){return"show"===t.name},Yo={name:"transition",props:Ho,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Jo)).length){0;var r=this.mode;0;var o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var i=Wo(o);if(!i)return o;if(this._leaving)return Go(t,o);var a="__transition-".concat(this._uid,"-");i.key=null==i.key?i.isComment?a+"comment":a+i.tag:c(i.key)?0===String(i.key).indexOf(a)?i.key:a+i.key:i.key;var s=(i.data||(i.data={})).transition=Ko(this),u=this._vnode,l=Wo(u);if(i.data.directives&&i.data.directives.some(Xo)&&(i.data.show=!0),l&&l.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(i,l)&&!he(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=A({},s);if("out-in"===r)return this._leaving=!0,Kt(f,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),Go(t,o);if("in-out"===r){if(he(i))return u;var p,d=function(){p()};Kt(s,"afterEnter",d),Kt(s,"enterCancelled",d),Kt(f,"delayLeave",(function(t){p=t}))}}return o}}},Zo=A({tag:String,moveClass:String},Ho);function Qo(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function ti(t){t.data.newPos=t.elm.getBoundingClientRect()}function ei(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate(".concat(r,"px,").concat(o,"px)"),i.transitionDuration="0s"}}delete Zo.mode;var ni={Transition:Yo,TransitionGroup:{props:Zo,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=Ye(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=Ko(this),s=0;s-1?gr[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:gr[t]=/HTMLUnknownElement/.test(e.toString())},A(Kn.options.directives,qo),A(Kn.options.components,ni),Kn.prototype.__patch__=J?Lo:L,Kn.prototype.$mount=function(t,e){return function(t,e,n){var r;t.$el=e,t.$options.render||(t.$options.render=ht),tn(t,"beforeMount"),r=function(){t._update(t._render(),n)},new He(t,r,L,{before:function(){t._isMounted&&!t._isDestroyed&&tn(t,"beforeUpdate")}},!0),n=!1;var o=t._preWatchers;if(o)for(var i=0;i=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}(o.path||""),u=e&&e.path||"/",l=c.path?Oi(c.path,u,n||o.append):u,f=function(t,e,n){void 0===e&&(e={});var r,o=n||li;try{r=o(t||"")}catch(t){r={}}for(var i in e){var a=e[i];r[i]=Array.isArray(a)?a.map(ui):ui(a)}return r}(c.query,o.query,r&&r.options.parseQuery),p=o.hash||c.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:l,query:f,hash:p}}var qi,Hi=function(){},Wi={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),i=o.location,a=o.route,s=o.href,c={},u=n.options.linkActiveClass,l=n.options.linkExactActiveClass,f=null==u?"router-link-active":u,p=null==l?"router-link-exact-active":l,d=null==this.activeClass?f:this.activeClass,h=null==this.exactActiveClass?p:this.exactActiveClass,v=a.redirectedFrom?di(null,Vi(a.redirectedFrom),null,n):a;c[h]=gi(r,v,this.exactPath),c[d]=this.exact||this.exactPath?c[h]:function(t,e){return 0===t.path.replace(pi,"/").indexOf(e.path.replace(pi,"/"))&&(!e.hash||t.hash===e.hash)&&function(t,e){for(var n in e)if(!(n in t))return!1;return!0}(t.query,e.query)}(r,v);var m=c[h]?this.ariaCurrentValue:null,y=function(t){Ki(t)&&(e.replace?n.replace(i,Hi):n.push(i,Hi))},g={click:Ki};Array.isArray(this.event)?this.event.forEach((function(t){g[t]=y})):g[this.event]=y;var b={class:c},_=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:s,route:a,navigate:y,isActive:c[d],isExactActive:c[h]});if(_){if(1===_.length)return _[0];if(_.length>1||!_.length)return 0===_.length?t():t("span",{},_)}if("a"===this.tag)b.on=g,b.attrs={href:s,"aria-current":m};else{var x=function t(e){var n;if(e)for(var r=0;r-1&&(s.params[p]=n.params[p]);return s.path=Bi(l.path,s.params),c(l,s,a)}if(s.path){s.params={};for(var d=0;d-1}function $a(t,e){return Sa(t)&&t._isRouter&&(null==e||t.type===e)}function Ca(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],(function(){r(o+1)})):r(o+1)};r(0)}function ja(t){return function(e,n,r){var o=!1,i=0,a=null;ka(t,(function(t,e,n,s){if("function"==typeof t&&void 0===t.cid){o=!0,i++;var c,u=Pa((function(e){var o;((o=e).__esModule||Ea&&"Module"===o[Symbol.toStringTag])&&(e=e.default),t.resolved="function"==typeof e?e:qi.extend(e),n.components[s]=e,--i<=0&&r()})),l=Pa((function(t){var e="Failed to resolve async component "+s+": "+t;a||(a=Sa(t)?t:new Error(e),r(a))}));try{c=t(u,l)}catch(t){l(t)}if(c)if("function"==typeof c.then)c.then(u,l);else{var f=c.component;f&&"function"==typeof f.then&&f.then(u,l)}}})),o||r()}}function ka(t,e){return Ta(t.map((function(t){return Object.keys(t.components).map((function(n){return e(t.components[n],t.instances[n],t,n)}))})))}function Ta(t){return Array.prototype.concat.apply([],t)}var Ea="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function Pa(t){var e=!1;return function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];if(!e)return e=!0,t.apply(this,n)}}var Aa=function(t,e){this.router=t,this.base=function(t){if(!t)if(Gi){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";"/"!==t.charAt(0)&&(t="/"+t);return t.replace(/\/$/,"")}(e),this.current=vi,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function Ra(t,e,n,r){var o=ka(t,(function(t,r,o,i){var a=function(t,e){"function"!=typeof t&&(t=qi.extend(t));return t.options[e]}(t,e);if(a)return Array.isArray(a)?a.map((function(t){return n(t,r,o,i)})):n(a,r,o,i)}));return Ta(r?o.reverse():o)}function La(t,e){if(e)return function(){return t.apply(e,arguments)}}Aa.prototype.listen=function(t){this.cb=t},Aa.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},Aa.prototype.onError=function(t){this.errorCbs.push(t)},Aa.prototype.transitionTo=function(t,e,n){var r,o=this;try{r=this.router.match(t,this.current)}catch(t){throw this.errorCbs.forEach((function(e){e(t)})),t}var i=this.current;this.confirmTransition(r,(function(){o.updateRoute(r),e&&e(r),o.ensureURL(),o.router.afterHooks.forEach((function(t){t&&t(r,i)})),o.ready||(o.ready=!0,o.readyCbs.forEach((function(t){t(r)})))}),(function(t){n&&n(t),t&&!o.ready&&($a(t,ba.redirected)&&i===vi||(o.ready=!0,o.readyErrorCbs.forEach((function(e){e(t)}))))}))},Aa.prototype.confirmTransition=function(t,e,n){var r=this,o=this.current;this.pending=t;var i,a,s=function(t){!$a(t)&&Sa(t)&&(r.errorCbs.length?r.errorCbs.forEach((function(e){e(t)})):console.error(t)),n&&n(t)},c=t.matched.length-1,u=o.matched.length-1;if(gi(t,o)&&c===u&&t.matched[c]===o.matched[u])return this.ensureURL(),t.hash&&aa(this.router,o,t,!1),s(((a=wa(i=o,t,ba.duplicated,'Avoided redundant navigation to current location: "'+i.fullPath+'".')).name="NavigationDuplicated",a));var l=function(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n0)){var e=this.router,n=e.options.scrollBehavior,r=va&&n;r&&this.listeners.push(ia());var o=function(){var n=t.current,o=Ia(t.base);t.current===vi&&o===t._startLocation||t.transitionTo(o,(function(t){r&&aa(e,t,n,!0)}))};window.addEventListener("popstate",o),this.listeners.push((function(){window.removeEventListener("popstate",o)}))}},e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ma(Si(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ya(Si(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.ensureURL=function(t){if(Ia(this.base)!==this.current.fullPath){var e=Si(this.base+this.current.fullPath);t?ma(e):ya(e)}},e.prototype.getCurrentLocation=function(){return Ia(this.base)},e}(Aa);function Ia(t){var e=window.location.pathname,n=e.toLowerCase(),r=t.toLowerCase();return!t||n!==r&&0!==n.indexOf(Si(r+"/"))||(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}var Da=function(t){function e(e,n,r){t.call(this,e,n),r&&function(t){var e=Ia(t);if(!/^\/#/.test(e))return window.location.replace(Si(t+"/#"+e)),!0}(this.base)||Na()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router.options.scrollBehavior,n=va&&e;n&&this.listeners.push(ia());var r=function(){var e=t.current;Na()&&t.transitionTo(Fa(),(function(r){n&&aa(t.router,r,e,!0),va||Ba(r.fullPath)}))},o=va?"popstate":"hashchange";window.addEventListener(o,r),this.listeners.push((function(){window.removeEventListener(o,r)}))}},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){za(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Ba(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;Fa()!==e&&(t?za(e):Ba(e))},e.prototype.getCurrentLocation=function(){return Fa()},e}(Aa);function Na(){var t=Fa();return"/"===t.charAt(0)||(Ba("/"+t),!1)}function Fa(){var t=window.location.href,e=t.indexOf("#");return e<0?"":t=t.slice(e+1)}function Ua(t){var e=window.location.href,n=e.indexOf("#");return(n>=0?e.slice(0,n):e)+"#"+t}function za(t){va?ma(Ua(t)):window.location.hash=t}function Ba(t){va?ya(Ua(t)):window.location.replace(Ua(t))}var Va=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)}),n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,(function(){var t=e.current;e.index=n,e.updateRoute(r),e.router.afterHooks.forEach((function(e){e&&e(r,t)}))}),(function(t){$a(t,ba.duplicated)&&(e.index=n)}))}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Aa),qa=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=Yi(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!va&&!1!==t.fallback,this.fallback&&(e="hash"),Gi||(e="abstract"),this.mode=e,e){case"history":this.history=new Ma(this,t.base);break;case"hash":this.history=new Da(this,t.base,this.fallback);break;case"abstract":this.history=new Va(this,t.base);break;default:0}},Ha={currentRoute:{configurable:!0}};qa.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},Ha.currentRoute.get=function(){return this.history&&this.history.current},qa.prototype.init=function(t){var e=this;if(this.apps.push(t),t.$once("hook:destroyed",(function(){var n=e.apps.indexOf(t);n>-1&&e.apps.splice(n,1),e.app===t&&(e.app=e.apps[0]||null),e.app||e.history.teardown()})),!this.app){this.app=t;var n=this.history;if(n instanceof Ma||n instanceof Da){var r=function(t){n.setupListeners(),function(t){var r=n.current,o=e.options.scrollBehavior;va&&o&&"fullPath"in t&&aa(e,t,r,!1)}(t)};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen((function(t){e.apps.forEach((function(e){e._route=t}))}))}},qa.prototype.beforeEach=function(t){return Ka(this.beforeHooks,t)},qa.prototype.beforeResolve=function(t){return Ka(this.resolveHooks,t)},qa.prototype.afterEach=function(t){return Ka(this.afterHooks,t)},qa.prototype.onReady=function(t,e){this.history.onReady(t,e)},qa.prototype.onError=function(t){this.history.onError(t)},qa.prototype.push=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.push(t,e,n)}));this.history.push(t,e,n)},qa.prototype.replace=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.replace(t,e,n)}));this.history.replace(t,e,n)},qa.prototype.go=function(t){this.history.go(t)},qa.prototype.back=function(){this.go(-1)},qa.prototype.forward=function(){this.go(1)},qa.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map((function(t){return Object.keys(t.components).map((function(e){return t.components[e]}))}))):[]},qa.prototype.resolve=function(t,e,n){var r=Vi(t,e=e||this.history.current,n,this),o=this.match(r,e),i=o.redirectedFrom||o.fullPath;return{location:r,route:o,href:function(t,e,n){var r="hash"===n?"#"+e:e;return t?Si(t+"/"+r):r}(this.history.base,i,this.mode),normalizedTo:r,resolved:o}},qa.prototype.getRoutes=function(){return this.matcher.getRoutes()},qa.prototype.addRoute=function(t,e){this.matcher.addRoute(t,e),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},qa.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(qa.prototype,Ha);var Wa=qa;function Ka(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}qa.install=function t(e){if(!t.installed||qi!==e){t.installed=!0,qi=e;var n=function(t){return void 0!==t},r=function(t,e){var r=t.$options._parentVnode;n(r)&&n(r=r.data)&&n(r=r.registerRouteInstance)&&r(t,e)};e.mixin({beforeCreate:function(){n(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),e.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,r(this,this)},destroyed:function(){r(this)}}),Object.defineProperty(e.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(e.prototype,"$route",{get:function(){return this._routerRoot._route}}),e.component("RouterView",xi),e.component("RouterLink",Wi);var o=e.config.optionMergeStrategies;o.beforeRouteEnter=o.beforeRouteLeave=o.beforeRouteUpdate=o.created}},qa.version="3.6.5",qa.isNavigationFailure=$a,qa.NavigationFailureType=ba,qa.START_LOCATION=vi,Gi&&window.Vue&&window.Vue.use(qa);n(97);n(124),n(46);var Ga={"components/AlgoliaSearchBox":()=>Promise.all([n.e(0),n.e(13)]).then(n.bind(null,299)),"components/DropdownLink":()=>Promise.all([n.e(0),n.e(14)]).then(n.bind(null,256)),"components/DropdownTransition":()=>Promise.all([n.e(0),n.e(19)]).then(n.bind(null,244)),"components/Home":()=>Promise.all([n.e(0),n.e(16)]).then(n.bind(null,282)),"components/NavLink":()=>n.e(21).then(n.bind(null,243)),"components/NavLinks":()=>Promise.all([n.e(0),n.e(12)]).then(n.bind(null,267)),"components/Navbar":()=>Promise.all([n.e(0),n.e(1)]).then(n.bind(null,296)),"components/Page":()=>Promise.all([n.e(0),n.e(11)]).then(n.bind(null,283)),"components/PageEdit":()=>Promise.all([n.e(0),n.e(17)]).then(n.bind(null,269)),"components/PageNav":()=>Promise.all([n.e(0),n.e(15)]).then(n.bind(null,270)),"components/Sidebar":()=>Promise.all([n.e(0),n.e(10)]).then(n.bind(null,284)),"components/SidebarButton":()=>Promise.all([n.e(0),n.e(20)]).then(n.bind(null,285)),"components/SidebarGroup":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,268)),"components/SidebarLink":()=>Promise.all([n.e(0),n.e(18)]).then(n.bind(null,257)),"components/SidebarLinks":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,255)),"global-components/Badge":()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,304)),"global-components/CodeBlock":()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,300)),"global-components/CodeGroup":()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,301)),"layouts/404":()=>n.e(7).then(n.bind(null,302)),"layouts/Layout":()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,303)),NotFound:()=>n.e(7).then(n.bind(null,302)),Layout:()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,303))},Ja={"v-8d183370":()=>n.e(22).then(n.bind(null,305)),"v-44c77310":()=>n.e(23).then(n.bind(null,306))};function Xa(t){const e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}const Ya=/-(\w)/g,Za=Xa(t=>t.replace(Ya,(t,e)=>e?e.toUpperCase():"")),Qa=/\B([A-Z])/g,ts=Xa(t=>t.replace(Qa,"-$1").toLowerCase()),es=Xa(t=>t.charAt(0).toUpperCase()+t.slice(1));function ns(t,e){if(!e)return;if(t(e))return t(e);return e.includes("-")?t(es(Za(e))):t(es(e))||t(ts(e))}const rs=Object.assign({},Ga,Ja),os=t=>rs[t],is=t=>Ja[t],as=t=>Ga[t],ss=t=>Kn.component(t);function cs(t){return ns(is,t)}function us(t){return ns(as,t)}function ls(t){return ns(os,t)}function fs(t){return ns(ss,t)}function ps(...t){return Promise.all(t.filter(t=>t).map(async t=>{if(!fs(t)&&ls(t)){const e=await ls(t)();Kn.component(t,e.default)}}))}function ds(t,e){"undefined"!=typeof window&&window.__VUEPRESS__&&(window.__VUEPRESS__[t]=e)}var hs=n(89),vs=n.n(hs),ms=n(90),ys=n.n(ms),gs={created(){if(this.siteMeta=this.$site.headTags.filter(([t])=>"meta"===t).map(([t,e])=>e),this.$ssrContext){const e=this.getMergedMetaTags();this.$ssrContext.title=this.$title,this.$ssrContext.lang=this.$lang,this.$ssrContext.pageMeta=(t=e)?t.map(t=>{let e="{e+=` ${n}="${ys()(t[n])}"`}),e+">"}).join("\n "):"",this.$ssrContext.canonicalLink=_s(this.$canonicalUrl)}var t},mounted(){this.currentMetaTags=[...document.querySelectorAll("meta")],this.updateMeta(),this.updateCanonicalLink()},methods:{updateMeta(){document.title=this.$title,document.documentElement.lang=this.$lang;const t=this.getMergedMetaTags();this.currentMetaTags=xs(t,this.currentMetaTags)},getMergedMetaTags(){const t=this.$page.frontmatter.meta||[];return vs()([{name:"description",content:this.$description}],t,this.siteMeta,ws)},updateCanonicalLink(){bs(),this.$canonicalUrl&&document.head.insertAdjacentHTML("beforeend",_s(this.$canonicalUrl))}},watch:{$page(){this.updateMeta(),this.updateCanonicalLink()}},beforeDestroy(){xs(null,this.currentMetaTags),bs()}};function bs(){const t=document.querySelector("link[rel='canonical']");t&&t.remove()}function _s(t=""){return t?``:""}function xs(t,e){if(e&&[...e].filter(t=>t.parentNode===document.head).forEach(t=>document.head.removeChild(t)),t)return t.map(t=>{const e=document.createElement("meta");return Object.keys(t).forEach(n=>{e.setAttribute(n,t[n])}),document.head.appendChild(e),e})}function ws(t){for(const e of["name","property","itemprop"])if(t.hasOwnProperty(e))return t[e]+e;return JSON.stringify(t)}var Os=n(22),Ss=n.n(Os),$s={mounted(){window.addEventListener("scroll",this.onScroll)},methods:{onScroll:Ss()((function(){this.setActiveHash()}),300),setActiveHash(){const t=[].slice.call(document.querySelectorAll(".sidebar-link")),e=[].slice.call(document.querySelectorAll(".header-anchor")).filter(e=>t.some(t=>t.hash===e.hash)),n=Math.max(window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop),r=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),o=window.innerHeight+n;for(let t=0;t=i.parentElement.offsetTop+10&&(!a||n{this.$nextTick(()=>{this.$vuepress.$set("disableScrollBehavior",!1)})})}}}},beforeDestroy(){window.removeEventListener("scroll",this.onScroll)}},Cs=n(23),js=n.n(Cs),ks=[gs,$s,{mounted(){js.a.configure({showSpinner:!1}),this.$router.beforeEach((t,e,n)=>{t.path===e.path||Kn.component(t.name)||js.a.start(),n()}),this.$router.afterEach(()=>{js.a.done(),this.isSidebarOpen=!1})}}],Ts={name:"GlobalLayout",computed:{layout(){const t=this.getLayout();return ds("layout",t),Kn.component(t)}},methods:{getLayout(){if(this.$page.path){const t=this.$page.frontmatter.layout;return t&&(this.$vuepress.getLayoutAsyncComponent(t)||this.$vuepress.getVueComponent(t))?t:"Layout"}return"NotFound"}}},Es=n(10),Ps=Object(Es.a)(Ts,(function(){return(0,this._self._c)(this.layout,{tag:"component"})}),[],!1,null,null,null).exports;!function(t,e,n){switch(e){case"components":t[e]||(t[e]={}),Object.assign(t[e],n);break;case"mixins":t[e]||(t[e]=[]),t[e].push(...n);break;default:throw new Error("Unknown option name.")}}(Ps,"mixins",ks);const As=[{name:"v-8d183370",path:"/",component:Ps,beforeEnter:(t,e,n)=>{ps("Layout","v-8d183370").then(n)}},{path:"/index.html",redirect:"/"},{name:"v-44c77310",path:"/zh/",component:Ps,beforeEnter:(t,e,n)=>{ps("Layout","v-44c77310").then(n)}},{path:"/zh/index.html",redirect:"/zh/"},{path:"*",component:Ps}],Rs={title:"",description:"",base:"/",headTags:[],pages:[{title:"🐋 Awesome TTRSS",frontmatter:{},regularPath:"/",relativePath:"README.md",key:"v-8d183370",path:"/",headers:[{level:2,title:"About",slug:"about"},{level:2,title:"Special Thanks",slug:"special-thanks"},{level:2,title:"Deployment",slug:"deployment"},{level:3,title:"Deployment via docker",slug:"deployment-via-docker"},{level:3,title:"Deployment via Docker Compose",slug:"deployment-via-docker-compose"},{level:3,title:"Supported Environment Variables",slug:"supported-environment-variables"},{level:3,title:"Configure HTTPS",slug:"configure-https"},{level:2,title:"Update",slug:"update"},{level:3,title:"Manual Update",slug:"manual-update"},{level:3,title:"Auto Update",slug:"auto-update"},{level:2,title:"Database Upgrade or Migration",slug:"database-upgrade-or-migration"},{level:3,title:"Steps",slug:"steps-2"},{level:2,title:"Plugins",slug:"plugins"},{level:3,title:"Mercury Fulltext Extraction",slug:"mercury-fulltext-extraction"},{level:3,title:"Fever API",slug:"fever-api"},{level:3,title:"OpenCC Simp-Trad Chinese Conversion",slug:"opencc-simp-trad-chinese-conversion"},{level:3,title:"FeedReader API",slug:"feedreader-api"},{level:3,title:"News+ API",slug:"news-api"},{level:3,title:"Feediron",slug:"feediron"},{level:3,title:"Options per Feed",slug:"options-per-feed"},{level:3,title:"Remove iframe sandbox",slug:"remove-iframe-sandbox"},{level:3,title:"Wallabag v2",slug:"wallabag-v2"},{level:3,title:"Auth OIDC",slug:"auth-oidc"},{level:2,title:"Themes",slug:"themes"},{level:3,title:"Feedly",slug:"feedly"},{level:3,title:"RSSHub",slug:"rsshub"},{level:2,title:"Recommendation",slug:"recommendation"},{level:2,title:"Support and Help",slug:"support-and-help"},{level:2,title:"Donation",slug:"donation"},{level:2,title:"License",slug:"license"}],lastUpdated:"02/05/2024, 17:12:38",lastUpdatedTimestamp:1714669958e3},{title:"🐋 Awesome TTRSS",frontmatter:{},regularPath:"/zh/",relativePath:"zh/README.md",key:"v-44c77310",path:"/zh/",headers:[{level:2,title:"关于",slug:"关于"},{level:2,title:"鸣谢",slug:"鸣谢"},{level:2,title:"部署",slug:"部署"},{level:3,title:"通过 Docker 部署",slug:"通过-docker-部署"},{level:3,title:"通过 Docker Compose 部署",slug:"通过-docker-compose-部署"},{level:3,title:"支持的环境变量列表",slug:"支持的环境变量列表"},{level:3,title:"配置 HTTPS",slug:"配置-https"},{level:2,title:"更新",slug:"更新"},{level:3,title:"手动更新",slug:"手动更新"},{level:3,title:"自动更新",slug:"自动更新"},{level:2,title:"数据库更新或迁移",slug:"数据库更新或迁移"},{level:3,title:"步骤",slug:"步骤-2"},{level:2,title:"插件",slug:"插件"},{level:3,title:"Mercury 全文获取",slug:"mercury-全文获取"},{level:3,title:"Fever API",slug:"fever-api"},{level:3,title:"OpenCC 繁简转换",slug:"opencc-繁简转换"},{level:3,title:"FeedReader API",slug:"feedreader-api"},{level:3,title:"News+ API",slug:"news-api"},{level:3,title:"Feediron",slug:"feediron"},{level:3,title:"Options per Feed",slug:"options-per-feed"},{level:3,title:"Wallabag v2",slug:"wallabag-v2"},{level:3,title:"Remove iframe sandbox",slug:"remove-iframe-sandbox"},{level:2,title:"主题",slug:"主题"},{level:3,title:"Feedly",slug:"feedly"},{level:3,title:"RSSHub",slug:"rsshub"},{level:2,title:"使用建议",slug:"使用建议"},{level:2,title:"支持与帮助",slug:"支持与帮助"},{level:2,title:"捐赠",slug:"捐赠"},{level:2,title:"许可",slug:"许可"}],lastUpdated:"2024/5/2 17:12:38",lastUpdatedTimestamp:1714669958e3}],themeConfig:{sidebar:"auto",sidebarDepth:1,docsDir:"site",repo:"HenryQW/Awesome-TTRSS",locales:{"/zh/":{lang:"zh-CN",selectText:"English",label:"中文",lastUpdated:"上次更新",nav:[{text:"首页",link:"/zh/"},{text:"赞助",link:"https://opencollective.com/Awesome-TTRSS/"}]},"/":{lang:"en-GB",selectText:"中文",label:"English",lastUpdated:"Last Updated",nav:[{text:"Home",link:"/"},{text:"Sponsor",link:"https://opencollective.com/Awesome-TTRSS/"}]}}},locales:{"/zh/":{lang:"zh-CN",title:"🐋 Awesome TTRSS",description:"🐋 A Dockerized powerful all-in-one Tiny Tiny RSS solution.",path:"/zh/"},"/":{lang:"en-GB",title:"🐋 Awesome TTRSS",description:"🐋 一个「容器化」的 Tiny Tiny RSS 一站式解决方案。",path:"/"}}};n(235);Kn.component("Badge",()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,304))),Kn.component("CodeBlock",()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,300))),Kn.component("CodeGroup",()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,301)));n(236);var Ls={name:"BackToTop",props:{threshold:{type:Number,default:300}},data:()=>({scrollTop:null}),computed:{show(){return this.scrollTop>this.threshold}},mounted(){this.scrollTop=this.getScrollTop(),window.addEventListener("scroll",Ss()(()=>{this.scrollTop=this.getScrollTop()},100))},methods:{getScrollTop:()=>window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,scrollToTop(){window.scrollTo({top:0,behavior:"smooth"}),this.scrollTop=0}}},Ms=(n(237),Object(Es.a)(Ls,(function(){var t=this._self._c;return t("transition",{attrs:{name:"fade"}},[this.show?t("svg",{staticClass:"go-to-top",attrs:{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 49.484 28.284"},on:{click:this.scrollToTop}},[t("g",{attrs:{transform:"translate(-229 -126.358)"}},[t("rect",{attrs:{fill:"currentColor",width:"35",height:"5",rx:"2",transform:"translate(229 151.107) rotate(-45)"}}),this._v(" "),t("rect",{attrs:{fill:"currentColor",width:"35",height:"5",rx:"2",transform:"translate(274.949 154.642) rotate(-135)"}})])]):this._e()])}),[],!1,null,"5cf0f4c0",null).exports),Is=[{},({Vue:t})=>{t.mixin({computed:{$dataBlock(){return this.$options.__data__block__}}})},{},{},({router:t})=>{var e,n,r,o,i,a;"undefined"!=typeof window&&(e=window,n=document,r="script",o="ga",e.GoogleAnalyticsObject=o,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,i=n.createElement(r),a=n.getElementsByTagName(r)[0],i.async=1,i.src="https://www.google-analytics.com/analytics.js",a.parentNode.insertBefore(i,a),ga("create","G-S0X56ZZMQB","auto"),ga("set","anonymizeIp",!0),t.afterEach((function(e){ga("set","page",t.app.$withBase(e.fullPath)),ga("send","pageview")})))},({Vue:t})=>{t.component("BackToTop",Ms)}],Ds=["BackToTop"];class Ns extends class{constructor(){this.store=new Kn({data:{state:{}}})}$get(t){return this.store.state[t]}$set(t,e){Kn.set(this.store.state,t,e)}$emit(...t){this.store.$emit(...t)}$on(...t){this.store.$on(...t)}}{}Object.assign(Ns.prototype,{getPageAsyncComponent:cs,getLayoutAsyncComponent:us,getAsyncComponent:ls,getVueComponent:fs});var Fs={install(t){const e=new Ns;t.$vuepress=e,t.prototype.$vuepress=e}};function Us(t,e){const n=e.toLowerCase();return t.options.routes.some(t=>t.path.toLowerCase()===n)}var zs={props:{pageKey:String,slotKey:{type:String,default:"default"}},render(t){const e=this.pageKey||this.$parent.$page.key;return ds("pageKey",e),Kn.component(e)||Kn.component(e,cs(e)),Kn.component(e)?t(e):t("")}},Bs={functional:!0,props:{slotKey:String,required:!0},render:(t,{props:e,slots:n})=>t("div",{class:["content__"+e.slotKey]},n()[e.slotKey])},Vs={computed:{openInNewWindowTitle(){return this.$themeLocaleConfig.openNewWindowText||"(opens new window)"}}},qs=(n(238),n(239),Object(Es.a)(Vs,(function(){var t=this._self._c;return t("span",[t("svg",{staticClass:"icon outbound",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"}},[t("path",{attrs:{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}}),this._v(" "),t("polygon",{attrs:{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"}})]),this._v(" "),t("span",{staticClass:"sr-only"},[this._v(this._s(this.openInNewWindowTitle))])])}),[],!1,null,null,null).exports),Hs={functional:!0,render(t,{parent:e,children:n}){if(e._isMounted)return n;e.$once("hook:mounted",()=>{e.$forceUpdate()})}};Kn.config.productionTip=!1,Kn.use(Wa),Kn.use(Fs),Kn.mixin(function(t,e,n=Kn){!function(t){t.locales&&Object.keys(t.locales).forEach(e=>{t.locales[e].path=e});Object.freeze(t)}(e),n.$vuepress.$set("siteData",e);const r=new(t(n.$vuepress.$get("siteData"))),o=Object.getOwnPropertyDescriptors(Object.getPrototypeOf(r)),i={};return Object.keys(o).reduce((t,e)=>(e.startsWith("$")&&(t[e]=o[e].get),t),i),{computed:i}}(t=>class{setPage(t){this.__page=t}get $site(){return t}get $themeConfig(){return this.$site.themeConfig}get $frontmatter(){return this.$page.frontmatter}get $localeConfig(){const{locales:t={}}=this.$site;let e,n;for(const r in t)"/"===r?n=t[r]:0===this.$page.path.indexOf(r)&&(e=t[r]);return e||n||{}}get $siteTitle(){return this.$localeConfig.title||this.$site.title||""}get $canonicalUrl(){const{canonicalUrl:t}=this.$page.frontmatter;return"string"==typeof t&&t}get $title(){const t=this.$page,{metaTitle:e}=this.$page.frontmatter;if("string"==typeof e)return e;const n=this.$siteTitle,r=t.frontmatter.home?null:t.frontmatter.title||t.title;return n?r?r+" | "+n:n:r||"VuePress"}get $description(){const t=function(t){if(t){const e=t.filter(t=>"description"===t.name)[0];if(e)return e.content}}(this.$page.frontmatter.meta);return t||(this.$page.frontmatter.description||this.$localeConfig.description||this.$site.description||"")}get $lang(){return this.$page.frontmatter.lang||this.$localeConfig.lang||"en-US"}get $localePath(){return this.$localeConfig.path||"/"}get $themeLocaleConfig(){return(this.$site.themeConfig.locales||{})[this.$localePath]||{}}get $page(){return this.__page?this.__page:function(t,e){for(let n=0;nn||(t.hash?!Kn.$vuepress.$get("disableScrollBehavior")&&{selector:decodeURIComponent(t.hash)}:{x:0,y:0})});!function(t){t.beforeEach((e,n,r)=>{if(Us(t,e.path))r();else if(/(\/|\.html)$/.test(e.path))if(/\/$/.test(e.path)){const n=e.path.replace(/\/$/,"")+".html";Us(t,n)?r(n):r()}else r();else{const n=e.path+"/",o=e.path+".html";Us(t,o)?r(o):Us(t,n)?r(n):r()}})}(n);const r={};try{await Promise.all(Is.filter(t=>"function"==typeof t).map(e=>e({Vue:Kn,options:r,router:n,siteData:Rs,isServer:t})))}catch(t){console.error(t)}return{app:new Kn(Object.assign(r,{router:n,render:t=>t("div",{attrs:{id:"app"}},[t("RouterView",{ref:"layout"}),t("div",{class:"global-ui"},Ds.map(e=>t(e)))])})),router:n}}(!1).then(({app:t,router:e})=>{e.onReady(()=>{t.$mount("#app")})})}]); \ No newline at end of file diff --git a/index.html b/index.html index 852cba1c..16b33e89 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@ - + @@ -32,7 +32,7 @@ English
GitHub - (opens new window)

# 🐋 Awesome TTRSS

Docker Pulls Docker Stars Docker Automated build FOSSA Status

# About

🐋 Awesome TTRSS aims to provide a powerful Dockerized all-in-one solution for Tiny Tiny RSS (opens new window), an open source RSS feed reader and aggregator written in PHP, with enhanced user experience via simplified deployment and a list of curated plugins.

# Special Thanks

Backers (opens new window)

# Deployment

A VPS is highly recommended to host your Awesome TTRSS instance, a VPS can be obtained from as little as $5/month at DigitalOcean (opens new window). Alternatively, you may request for personalized support, fully-managed service or fully-managed VPS via sponsoring Awesome TTRSS on its 💰OpenCollective page (opens new window).

Awesome TTRSS supports multiple architectures x86 ✓arm32v7 ✓arm64v8 ✓, except the OpenCC API.

# Deployment via docker

docker run -it --name ttrss --restart=always \
+     (opens new window)    

# 🐋 Awesome TTRSS

Docker Pulls Docker Stars Docker Automated build FOSSA Status

# About

🐋 Awesome TTRSS aims to provide a powerful Dockerized all-in-one solution for Tiny Tiny RSS (opens new window), an open source RSS feed reader and aggregator written in PHP, with enhanced user experience via simplified deployment and a list of curated plugins.

# Special Thanks

Backers (opens new window)

# Deployment

A VPS is highly recommended to host your Awesome TTRSS instance, a VPS can be obtained from as little as $5/month at DigitalOcean (opens new window). Alternatively, you may request for personalized support, fully-managed service or fully-managed VPS via sponsoring Awesome TTRSS on its 💰OpenCollective page (opens new window).

Awesome TTRSS supports multiple architectures x86 ✓arm32v7 ✓arm64v8 ✓, except the OpenCC API.

# Deployment via docker

docker run -it --name ttrss --restart=always \
 -e SELF_URL_PATH=[ your public URL ]  \
 -e DB_HOST=[ your DB address ]  \
 -e DB_PORT=[ your DB port ]  \
@@ -41,7 +41,7 @@
 -e DB_PASS=[ your DB password ]  \
 -p [ public port ]:80  \
 -d wangqiru/ttrss
-

# Deployment via docker-compose

docker-compose.yml (opens new window) include 4 docker images:

  1. TTRSS (opens new window)
  2. PostgreSQL (opens new window)
  3. Mercury Parser API (opens new window)
  4. OpenCC API (opens new window) arm32v7 ✗arm64v8 ✗

# Steps

  1. Download docker-compose.yml (opens new window) to any directory.
  2. Read docker-compose.yml and change the settings (please ensure you have changed the password for postgres).
  3. Run docker-compose up -d and wait for the deployment to finish.
  4. Access ttrss via port 181, with default credentials admin and password, please change them asap.
  5. wangqiru/mercury-parser-api and wangqiru/opencc-api-server are optional service containers to support additional features, removing them will not affect TTRSS's basic functionalities.

# Supported Environment Variables

  • SELF_URL_PATH: the url to your TTRSS instance. 🔴 Please note that this value should be consistent with the URL you see in your browser address bar, otherwise TTRSS will not start.
  • DB_HOST: the address of your database
  • DB_PORT: the port of your database
  • DB_NAME: the name of your database
  • DB_USER: the user of your Database
  • DB_PASS: the password of your database
  • DB_USER_FILE: Docker Secrets support(alternative to DB_USER), the file containing the user of your database
  • DB_PASS_FILE: Docker Secrets support(alternative to DB_PASS), the file containing the password of your database
  • ENABLE_PLUGINS: the plugins you'd like to enable as global plugins, note that auth_internal is required
  • ALLOW_PORTS: comma-separated port numbers, eg:1200,3000. Allow subscription of non-'80,443' port feed. 🔴 Use with caution.
  • SESSION_COOKIE_LIFETIME: the expiry time in hours for your login session cookie in hours, default to 24 hours
  • HTTP_PROXY: ip:port, the global proxy for your TTRSS instance, to set proxy on a per feed basis, use Options per Feed
  • DISABLE_USER_IN_DAYS: disable feed update for inactive users after X days without login, until the user performs a login
  • FEED_LOG_QUIET: true will disable the printing of feed updating logs

For more environment variables, please refer to the official tt-rss repo (opens new window).

# Configure HTTPS

TTRSS container itself doesn't handle HTTPS traffic. Examples of configuring a Caddy or an Nginx reverse proxy with free SSL certificate from Let's Encrypt (opens new window) are shown below:

# Caddyfile
+

# Deployment via Docker Compose

docker-compose.yml (opens new window) include 4 docker images:

  1. TTRSS (opens new window)
  2. PostgreSQL (opens new window)
  3. Mercury Parser API (opens new window)
  4. OpenCC API (opens new window) arm32v7 ✗arm64v8 ✗

# Steps

  1. Download docker-compose.yml (opens new window) to any directory.
  2. Read docker-compose.yml and change the settings (please ensure you have changed the password for postgres).
  3. Run docker compose up -d and wait for the deployment to finish.
  4. Access ttrss via port 181, with default credentials admin and password, please change them asap.
  5. wangqiru/mercury-parser-api and wangqiru/opencc-api-server are optional service containers to support additional features, removing them will not affect TTRSS's basic functionalities.

# Supported Environment Variables

  • SELF_URL_PATH: the url to your TTRSS instance. 🔴 Please note that this value should be consistent with the URL you see in your browser address bar, otherwise TTRSS will not start.
  • DB_HOST: the address of your database
  • DB_PORT: the port of your database
  • DB_NAME: the name of your database
  • DB_USER: the user of your Database
  • DB_PASS: the password of your database
  • DB_USER_FILE: Docker Secrets support(alternative to DB_USER), the file containing the user of your database
  • DB_PASS_FILE: Docker Secrets support(alternative to DB_PASS), the file containing the password of your database
  • ENABLE_PLUGINS: the plugins you'd like to enable as global plugins, note that auth_internal is required
  • ALLOW_PORTS: comma-separated port numbers, eg:1200,3000. Allow subscription of non-'80,443' port feed. 🔴 Use with caution.
  • SESSION_COOKIE_LIFETIME: the expiry time in hours for your login session cookie in hours, default to 24 hours
  • HTTP_PROXY: ip:port, the global proxy for your TTRSS instance, to set proxy on a per feed basis, use Options per Feed
  • DISABLE_USER_IN_DAYS: disable feed update for inactive users after X days without login, until the user performs a login
  • FEED_LOG_QUIET: true will disable the printing of feed updating logs

For more environment variables, please refer to the official tt-rss repo (opens new window).

# Configure HTTPS

TTRSS container itself doesn't handle HTTPS traffic. Examples of configuring a Caddy or an Nginx reverse proxy with free SSL certificate from Let's Encrypt (opens new window) are shown below:

# Caddyfile
 ttrssdev.henry.wang {
     reverse_proxy 127.0.0.1:181
     encode zstd gzip
@@ -88,8 +88,8 @@
 

🔴 Please note that the value in you SELF_URL_PATH should be changed as well.

# Update

Awesome TTRSS automatically keeps up with TTRSS by mirroring the official releases, this means update can be issued frequently.

TTRSS stopped releasing tags (opens new window). wangqiru/ttrss:latest will sync with TTRSS' main branch (opens new window) periodically.

# Manual Update

You can fetch the latest image manually:

docker pull wangqiru/ttrss:latest
 # docker pull wangqiru/mercury-parser-api:latest
 # docker pull wangqiru/opencc-api-server:latest
-docker-compose up -d # If you didn't use docker-compose, I'm sure you know what to do.
-

# Auto Update

The example docker-compose includes Watchtower (opens new window), which automatically pulls all containers included in Awesome TTRSS (and other containers running on your system) and refreshes your running services. By default, it's disabled, make sure it will not affect your other service containers before enabling this.

To exclude images, check the following for disabling auto update for containers:

service.mercury:
+docker compose up -d # If you didn't use docker compose, I'm sure you know what to do.
+

# Auto Update

The example Docker Compose includes Watchtower (opens new window), which automatically pulls all containers included in Awesome TTRSS (and other containers running on your system) and refreshes your running services. By default, it's disabled, make sure it will not affect your other service containers before enabling this.

To exclude images, check the following for disabling auto update for containers:

service.mercury:
   image: wangqiru/mercury-parser-api:latest
   container_name: mercury
   expose:
@@ -98,16 +98,16 @@
   # ⬇️ this prevents Watchtower from auto updating mercury-parser-api
   labels:
     - com.centurylinklabs.watchtower.enable=false
-

# Database Upgrade or Migration

Postgres major version upgrades (13->14) will require some manual operations. -Sometimes breaking changes will be introduced to further optimize Awesome TTRSS.

# Steps

This section demonstrates the steps to upgrade Postgres major version (from 12.x to 13.x) or migrate from other images to postgres:alpine.

  1. Stop all the service containers:

    docker-compose stop
    -
  2. Copy the Postgres data volume ~/postgres/data/ (or the location specified in your docker-compose file) to somewhere else as a backup, THIS IS IMPORTANT.

  3. Use the following command to dump all your data:

    docker exec postgres pg_dumpall -c -U YourUsername > export.sql
    -
  4. Delete the Postgres data volume ~/postgres/data/.

  5. Update your docker-compose file (Note that the DB_NAME must not be changed) with database.postgres section in the the latest docker-compose.yml (opens new window), and bring it up:

    docker-compose up -d
    +

    # Database Upgrade or Migration

    Postgres major version upgrades (15->16) will require some manual operations. +Sometimes breaking changes will be introduced to further optimize Awesome TTRSS.

    # Steps

    WARNING

    Do not skip multiple major versions when upgrading Postgres, for example, upgrading from 13.x to 16.x directly is not supported and may cause data loss.

    This section demonstrates the steps to upgrade Postgres major version (from 15.x to 16.x) or migrate from other images to postgres:alpine.

    1. Stop all the service containers:

      docker compose stop
      +
    2. Copy the Postgres data volume ~/postgres/data/ (or the location specified in your Docker Compose file) to somewhere else as a backup, THIS IS IMPORTANT.

    3. Use the following command to dump all your data:

      docker exec postgres pg_dumpall -c -U YourUsername > export.sql
      +
    4. Delete the Postgres data volume ~/postgres/data/.

    5. Update your Docker Compose file (Note that the DB_NAME must not be changed) with database.postgres section in the the latest docker-compose.yml (opens new window), and bring it up:

      docker compose up -d
       
    6. Use the following command to restore all your data:

      cat export.sql | docker exec -i postgres psql -U YourUsername
      -
    7. Test if everything works fine, and now you may remove the backup in step 2.

    # Plugins

    # Mercury Fulltext Extraction (opens new window)

    Fetch fulltext of articles via a self-hosted Mercury Parser API. A separate Mercury Parser API is required, the example docker-compose has already included such a server (opens new window).

    # Steps

    1. Enable mercury-fulltext plugin in preference +
  • Test if everything works fine, and now you may remove the backup in step 2.

  • # Plugins

    # Mercury Fulltext Extraction (opens new window)

    Fetch fulltext of articles via a self-hosted Mercury Parser API. A separate Mercury Parser API is required, the example Docker Compose has already included such a server (opens new window).

    # Steps

    1. Enable mercury-fulltext plugin in preference enable Mercury
    2. Enter Mercury Parser API endpoint enter Mercury Parser API endpoint

    Use service.mercury:3000 for Mercury instance deployed via Awesome-TTRSS.

    # Extraction Button

    # Fever API (opens new window)

    Provide Fever API simulation.

    # Steps

    1. Enable API in preference enable API
    2. Enter a password for Fever in preference -enter a Fever password
    3. In supported RSS readers, use https://[your url]/plugins/fever as the target server address, with your account and the password set in Step 2.
    4. The plugin communicates with TTRSS using an unsalted MD5 hash, using HTTPS is strongly recommended.

    # OpenCC Simp-Trad Chinese Conversion (opens new window) arm32v7 ✗arm64v8 ✗

    Conversion between Traditional and Simplified Chinese via OpenCC (opens new window) , a separate OpenCC API Server (opens new window) is required. the example docker-compose has already included such a server (opens new window).

    # Steps

    1. Enable opencc plugin in preference +enter a Fever password
    2. In supported RSS readers, use https://[your url]/plugins/fever as the target server address, with your account and the password set in Step 2.
    3. The plugin communicates with TTRSS using an unsalted MD5 hash, using HTTPS is strongly recommended.

    # OpenCC Simp-Trad Chinese Conversion (opens new window) arm32v7 ✗arm64v8 ✗

    Conversion between Traditional and Simplified Chinese via OpenCC (opens new window) , a separate OpenCC API Server (opens new window) is required. the example Docker Compose has already included such a server (opens new window).

    # Steps

    1. Enable opencc plugin in preference enable opencc
    2. Enter OpenCC API endpoint enter OpenCC API endpoint

    Use service.opencc:3000 for OpenCC instance deployed via Awesome-TTRSS.

    # Conversion Button

    # FeedReader API (opens new window)

    Provide FeedReader API support.

    System plugin, enabled by adding api_feedreader to the environment variable ENABLE_PLUGINS.

    Refer to FeedReader API (opens new window) for more details.

    # News+ API (opens new window)

    Provide a faster two-way synchronization for Android App News+ (opens new window) and iOS App Fiery Feeds (opens new window) with TTRSS.

    System plugin, enabled by adding api_newsplus to the environment variable ENABLE_PLUGINS.

    Refer to News+ API (opens new window) for more details.

    # Feediron (opens new window)

    Provide the ability to manipulate article DOMs.

    Refer to Feediron (opens new window) for more details.

    # Options per Feed (opens new window)

    Provide the ability to configure proxy, user-agent and SSL certificate verification on a per feed basis.

    Refer to Options per Feed (opens new window) for more details.

    # Remove iframe sandbox (opens new window)

    WARNING

    If you are getting data via fever api, enable it by adding remove_iframe_sandbox to the environment variable ENABLE_PLUGINS.

    This plugin cannot be enabled in conjunction with Fever API as global plugins, if you require both plugins:

    1. In ENABLE_PLUGINS replace fever with remove_iframe_sandbox to enable this as a global plugin.
    2. Enable Fever API in the TTRSS preferences panel after login, as a local plugin.

    Remove the sandbox attribute on iframes, thus enabling playback of embedded video in feeds.

    Refer to Remove iframe sandbox (opens new window)

    # Wallabag v2 (opens new window)

    Save articles to Wallabag.

    Refer to Wallabag v2 (opens new window)

    # Auth OIDC (opens new window)

    This is a system plugin, that allow users to connect through an oidc provider, like Keycloak, to TTRSS.

    System plugin, enabled by adding auth_oidc to the environment variable ENABLE_PLUGINS.

    Then add the following environments variables with according values :

    ```yaml
         AUTH_OIDC_NAME: 'IDP provider name displayed'
    @@ -115,7 +115,7 @@
         AUTH_OIDC_CLIENT_ID: 'test-rss'
         AUTH_OIDC_CLIENT_SECRET: 'your-secret-token'
     ```
    -

    Refer to Auth OIDC (opens new window) for more details.

    # Themes

    # Feedly (opens new window)

    Feedly

    # RSSHub (opens new window)

    RssHub

    # Recommendation

    # Support and Help

    # Donation

    PayPal WeChat Pay OpenCollective
    paypal (opens new window) 💰OpenCollective page (opens new window)

    # License

    MIT

    FOSSA Status (opens new window)

    Last Updated: 02/05/2024, 14:58:56
    - +

    Refer to Auth OIDC (opens new window) for more details.

    # Themes

    # Feedly (opens new window)

    Feedly

    # RSSHub (opens new window)

    RssHub

    # Recommendation

    # Support and Help

    # Donation

    PayPal WeChat Pay OpenCollective
    paypal (opens new window) 💰OpenCollective page (opens new window)

    # License

    MIT

    FOSSA Status (opens new window)

    + diff --git a/zh/index.html b/zh/index.html index e1b42594..4f788fa9 100644 --- a/zh/index.html +++ b/zh/index.html @@ -8,7 +8,7 @@ - + @@ -32,7 +32,7 @@ English GitHub - (opens new window)

    # 🐋 Awesome TTRSS

    Docker Pulls Docker Stars Docker Automated build FOSSA Status

    # 关于

    Tiny Tiny RSS (opens new window) 是一款基于 PHP 的免费开源 RSS 聚合阅读器。🐋 Awesome TTRSS 旨在提供一个 「一站式容器化」 的 Tiny Tiny RSS 解决方案,通过提供简易的部署方式以及一些额外插件,以提升用户体验。

    # 鸣谢

    赞助者 (opens new window)

    # 部署

    推荐使用一台 VPS 来部署您的 Awesome TTRSS 实例,DigitalOcean (opens new window) 提供高性价比的 VPS 仅需 $5/月。除此之外,通过 Awesome TTRSS 的 💰OpenCollective 页面 (opens new window) 进行赞助,即可获得定制支持,全托管服务,全托管 VPS 等私人服务。

    Awesome TTRSS 支持多架构 x86 ✓arm32v7 ✓arm64v8 ✓(暂不包括 OpenCC API)。

    # 通过 Docker 部署

    docker run -it --name ttrss --restart=always \
    +     (opens new window)    

    # 🐋 Awesome TTRSS

    Docker Pulls Docker Stars Docker Automated build FOSSA Status

    # 关于

    Tiny Tiny RSS (opens new window) 是一款基于 PHP 的免费开源 RSS 聚合阅读器。🐋 Awesome TTRSS 旨在提供一个 「一站式容器化」 的 Tiny Tiny RSS 解决方案,通过提供简易的部署方式以及一些额外插件,以提升用户体验。

    # 鸣谢

    赞助者 (opens new window)

    # 部署

    推荐使用一台 VPS 来部署您的 Awesome TTRSS 实例,DigitalOcean (opens new window) 提供高性价比的 VPS 仅需 $5/月。除此之外,通过 Awesome TTRSS 的 💰OpenCollective 页面 (opens new window) 进行赞助,即可获得定制支持,全托管服务,全托管 VPS 等私人服务。

    Awesome TTRSS 支持多架构 x86 ✓arm32v7 ✓arm64v8 ✓(暂不包括 OpenCC API)。

    # 通过 Docker 部署

    docker run -it --name ttrss --restart=always \
     -e SELF_URL_PATH=[ TTRSS 实例地址 ]  \
     -e DB_HOST=[ 数据库地址 ]  \
     -e DB_PORT=[ 数据库端口 ]  \
    @@ -41,7 +41,7 @@
     -e DB_PASS=[ 数据库密码 ]  \
     -p [ 容器对外映射端口 ]:80  \
     -d wangqiru/ttrss
    -

    # 通过 docker-compose 部署

    docker-compose.yml (opens new window) 包含了 4 个镜像:

    1. TTRSS (opens new window)
    2. PostgreSQL (opens new window)
    3. Mercury Parser API (opens new window)
    4. OpenCC API (opens new window) arm32v7 ✗arm64v8 ✗

    # 步骤

    1. 下载 docker-compose.yml (opens new window) 至任意目录。
    2. 更改 docker-compose.yml 中的设置,请务必更改 postgres 用户密码。
    3. 通过终端在同目录下运行 docker-compose up -d 后等待部署完成。
    4. 默认通过 181 端口访问 TTRSS,默认账户:admin 密码:password,请第一时间更改。
    5. wangqiru/mercury-parser-apiwangqiru/opencc-api-server 为支持高级功能而加入的可选服务类容器,删除不会影响 TTRSS 基础功能。

    # 支持的环境变量列表

    • SELF_URL_PATH: TTRSS 实例地址。🔴 请注意,该变量值必须与你在浏览器中用于访问 TTRSS 的 URL 保持完全一致,否则 TTRSS 将无法启动。
    • DB_HOST: 数据库地址
    • DB_PORT: 数据库端口
    • DB_NAME: 数据库名字
    • DB_USER: 数据库用户名
    • DB_PASS: 数据库密码
    • DB_USER_FILE: Docker Secrets 支持(替代 DB_USE),包含数据库用户名的文件
    • DB_PASS_FILE: Docker Secrets 支持(替代 DB_PASS),包含数据库密码的文件
    • ENABLE_PLUGINS: 全局启用的插件名称,其中 auth_internal 为必须启用的登录插件
    • ALLOW_PORTS: 逗号分隔端口号,如1200,3000。允许订阅非 80,443 端口的源。🔴 谨慎使用。
    • SESSION_COOKIE_LIFETIME: 使用网页版登陆时 cookie 过期时间,单位为小时,默认为 24 小时
    • HTTP_PROXY: ip:port, TTRSS 实例的全局代理,为源地址添加单独代理请使用 Options per Feed
    • DISABLE_USER_IN_DAYS: 当用户 X 天后没有登录后,停止为其自动更新订阅源,直至用户再次登陆
    • FEED_LOG_QUIET: true 禁用订阅源更新所产生的日志打印

    更多环境变量,参见 官方 tt-rss (opens new window)

    # 配置 HTTPS

    TTRSS 容器自身不负责使用 HTTPS 加密通信。参见下方的样例自行配置 Caddy 或 Nginx 反向代理。使用 Let's Encrypt (opens new window) 可以获取免费 SSL 证书。

    # Caddyfile
    +

    # 通过 Docker Compose 部署

    docker-compose.yml (opens new window) 包含了 4 个镜像:

    1. TTRSS (opens new window)
    2. PostgreSQL (opens new window)
    3. Mercury Parser API (opens new window)
    4. OpenCC API (opens new window) arm32v7 ✗arm64v8 ✗

    # 步骤

    1. 下载 docker-compose.yml (opens new window) 至任意目录。
    2. 更改 docker-compose.yml 中的设置,请务必更改 postgres 用户密码。
    3. 通过终端在同目录下运行 docker compose up -d 后等待部署完成。
    4. 默认通过 181 端口访问 TTRSS,默认账户:admin 密码:password,请第一时间更改。
    5. wangqiru/mercury-parser-apiwangqiru/opencc-api-server 为支持高级功能而加入的可选服务类容器,删除不会影响 TTRSS 基础功能。

    # 支持的环境变量列表

    • SELF_URL_PATH: TTRSS 实例地址。🔴 请注意,该变量值必须与你在浏览器中用于访问 TTRSS 的 URL 保持完全一致,否则 TTRSS 将无法启动。
    • DB_HOST: 数据库地址
    • DB_PORT: 数据库端口
    • DB_NAME: 数据库名字
    • DB_USER: 数据库用户名
    • DB_PASS: 数据库密码
    • DB_USER_FILE: Docker Secrets 支持(替代 DB_USE),包含数据库用户名的文件
    • DB_PASS_FILE: Docker Secrets 支持(替代 DB_PASS),包含数据库密码的文件
    • ENABLE_PLUGINS: 全局启用的插件名称,其中 auth_internal 为必须启用的登录插件
    • ALLOW_PORTS: 逗号分隔端口号,如1200,3000。允许订阅非 80,443 端口的源。🔴 谨慎使用。
    • SESSION_COOKIE_LIFETIME: 使用网页版登陆时 cookie 过期时间,单位为小时,默认为 24 小时
    • HTTP_PROXY: ip:port, TTRSS 实例的全局代理,为源地址添加单独代理请使用 Options per Feed
    • DISABLE_USER_IN_DAYS: 当用户 X 天后没有登录后,停止为其自动更新订阅源,直至用户再次登陆
    • FEED_LOG_QUIET: true 禁用订阅源更新所产生的日志打印

    更多环境变量,参见 官方 tt-rss (opens new window)

    # 配置 HTTPS

    TTRSS 容器自身不负责使用 HTTPS 加密通信。参见下方的样例自行配置 Caddy 或 Nginx 反向代理。使用 Let's Encrypt (opens new window) 可以获取免费 SSL 证书。

    # Caddyfile
     ttrssdev.henry.wang {
         reverse_proxy 127.0.0.1:181
         encode zstd gzip
    @@ -88,8 +88,8 @@
     

    🔴 请注意, 你需要更新 SELF_URL_PATH 环境变量。

    # 更新

    Awesome TTRSS 会自动监控 TTRSS 官方更新并与之同步,这意味着更新会比较频繁。

    TTRSS 官方不再释出 tag (opens new window)wangqiru/ttrss:latest 会与 官方 main branch (opens new window) 同步。

    # 手动更新

    通过以下命令进行手动更新:

        docker pull wangqiru/ttrss:latest
         # docker pull wangqiru/mercury-parser-api:latest
         # docker pull wangqiru/opencc-api-server:latest
    -    docker-compose up -d # 如果您没有使用 docker-compose,我确信您知道该怎么做。
    -

    # 自动更新

    [样例 docker-compose](#通过-docker-compose-部署) 中包含了 Watchtower (opens new window),它会自动拉取并更新您所有的服务容器 (包括当前系统上运行的非 Awesome TTRSS 服务的容器)。该服务默认关闭,启用前请确认它将不会影响您其他的服务容器。

    您也可以设置 watchtower 忽略您的其他容器:

    service.mercury:
    +    docker compose up -d # 如果您没有使用 docker compose,我确信您知道该怎么做。
    +

    # 自动更新

    样例 Docker Compose 中包含了 Watchtower (opens new window),它会自动拉取并更新您所有的服务容器 (包括当前系统上运行的非 Awesome TTRSS 服务的容器)。该服务默认关闭,启用前请确认它将不会影响您其他的服务容器。

    您也可以设置 watchtower 忽略您的其他容器:

    service.mercury:
       image: wangqiru/mercury-parser-api:latest
       container_name: mercury
       expose:
    @@ -98,18 +98,18 @@
       # ⬇️ 这将使 Watchtower 跳过对 mercury-parser-api 的更新检测
       labels:
         - com.centurylinklabs.watchtower.enable=false
    -

    # 数据库更新或迁移

    Postgres 大版本更新 (13->14) 需要额外的步骤来确保服务正常运行。 -为了更好地优化 Awesome TTRSS,有时候可能会推出一些破坏性更新。

    # 步骤

    这些步骤演示了如何进行 Postgres 大版本更新(从 12.x 至 13.x),或者从其他镜像迁移至 postgres:alpine。

    1. 停止所有服务容器:

      docker-compose stop
      -
    2. 复制 Postgres 数据卷 ~/postgres/data/(或者你在 docker-compose 中指定的目录)至其他任何地方作为备份,这非常重要!

    3. 执行如下命令来导出所有数据:

      docker exec postgres pg_dumpall -c -U 数据库用户名 > export.sql
      -
    4. 删除 Postgres 数据卷 ~/postgres/data/

    5. 根据最新 docker-compose.yml (opens new window) 中的database.postgres 部份来更新你的 docker-compose 文件(注意 DB_NAME 不可更改),并启动:

      docker-compose up -d
      +

      # 数据库更新或迁移

      Postgres 大版本更新 (15->16) 需要额外的步骤来确保服务正常运行。 +为了更好地优化 Awesome TTRSS,有时候可能会推出一些破坏性更新。

      # 步骤

      注意

      在升级时,请勿跳过多个大版本,例如直接从 13.x 升级到 16.x 是不支援的,并可能导致数据丢失。

      这些步骤演示了如何进行 Postgres 大版本更新(从 15.x 至 16.x),或者从其他镜像迁移至 postgres:alpine。

      1. 停止所有服务容器:

        docker compose stop
        +
      2. 复制 Postgres 数据卷 ~/postgres/data/(或者你在 Docker Compose 中指定的目录)至其他任何地方作为备份,这非常重要!

      3. 执行如下命令来导出所有数据:

        docker exec postgres pg_dumpall -c -U 数据库用户名 > export.sql
        +
      4. 删除 Postgres 数据卷 ~/postgres/data/

      5. 根据最新 docker-compose.yml (opens new window) 中的database.postgres 部份来更新你的 Docker Compose 文件(注意 DB_NAME 不可更改),并启动:

        docker compose up -d
         
      6. 执行如下命令来导入所有数据:

        cat export.sql | docker exec -i postgres psql -U 数据库用户名
        -
      7. 测试所有服务是否正常工作,现在你可以移除步骤二中的备份了。

      # 插件

      # Mercury 全文获取 (opens new window)

      全文内容提取插件,配合单独的 Mercury Parser API 服务器使用。[样例 docker-compose](#通过-docker-compose-部署) 中已经包含了 HenryQW/mercury-parser-api (opens new window) 服务器。

      # 设置步骤

      1. 在设置中启用 mercury-fulltext 插件 +
  • 测试所有服务是否正常工作,现在你可以移除步骤二中的备份了。

  • # 插件

    # Mercury 全文获取 (opens new window)

    全文内容提取插件,配合单独的 Mercury Parser API 服务器使用。样例 Docker Compose 中已经包含了 HenryQW/mercury-parser-api (opens new window) 服务器。

    # 设置步骤

    1. 在设置中启用 mercury-fulltext 插件 启用 Mercury
    2. 在设置中填入 Mercury Parser API 地址 填入 Mercury Parser API 地址

    使用 Awesome-TTRSS 部署的 mercury 可填写service.mercury:3000

    # 全文提取按钮

    # Fever API (opens new window)

    提供 Fever API 支持。

    # 设置步骤

    1. 在设置中启用 API。 启用 API
    2. 在插件设置中设置 Fever 密码。 -设置 Fever 密码
    3. 在支持 Fever 的阅读器用,使用 https://[您的地址]/plugins/fever 作为服务器地址。使用您的账号和步骤 2 中的密码登录。
    4. 由于该插件使用未加盐的 MD5 加密密码进行通信,强烈建议 开启 HTTPS

    # OpenCC 繁简转换 (opens new window) arm32v7 ✗arm64v8 ✗

    使用 OpenCC (opens new window) 为 TTRSS 提供中文繁转简的插件,需要配合单独的 OpenCC API 服务器使用。[样例 docker-compose](#通过-docker-compose-部署) 中已经包含了 HenryQW/OpenCC.henry.wang (opens new window) 服务器。

    # 设置步骤

    1. 在设置中启用 opencc 插件 +设置 Fever 密码
    2. 在支持 Fever 的阅读器用,使用 https://[您的地址]/plugins/fever 作为服务器地址。使用您的账号和步骤 2 中的密码登录。
    3. 由于该插件使用未加盐的 MD5 加密密码进行通信,强烈建议 开启 HTTPS

    # OpenCC 繁简转换 (opens new window) arm32v7 ✗arm64v8 ✗

    使用 OpenCC (opens new window) 为 TTRSS 提供中文繁转简的插件,需要配合单独的 OpenCC API 服务器使用。样例 Docker Compose 中已经包含了 HenryQW/OpenCC.henry.wang (opens new window) 服务器。

    # 设置步骤

    1. 在设置中启用 opencc 插件 启用 opencc
    2. 在设置中填入 OpenCC API 地址 -填入 OpenCC API 地址

    使用 Awesome-TTRSS 部署的 OpenCC 可填写service.opencc:3000

    # 转换按钮

    # FeedReader API (opens new window)

    提供 FeedReader API 支持。

    系统插件,将 api_feedreader 添加到 ENABLE_PLUGINS 环境变量中以启用。

    使用指南见 FeedReader API (opens new window)

    # News+ API (opens new window)

    为 Android App News+ (opens new window) 和 iOS App Fiery Feeds (opens new window) 提供更快的同步速度。

    系统插件,将 api_newsplus 添加到 ENABLE_PLUGINS 环境变量中以启用。

    使用指南见 News+ API (opens new window)

    # Feediron (opens new window)

    提供文章 DOM 操控能力的插件。

    使用指南见 Feediron (opens new window)

    # Options per Feed (opens new window)

    提供单独为源地址配置代理、user-agent 以及 SSL 证书验证的能力。

    使用指南见 Options per Feed (opens new window)

    # Wallabag v2 (opens new window)

    保存文章至 Wallabag。

    使用指南见 Wallabag v2 (opens new window)

    # Remove iframe sandbox (opens new window)

    注意

    该插件与 Fever API 不能同时作为全局插件启用。如果您同时需要两者:

    1. 在环境变量 ENABLE_PLUGINS 中移除 fever 并添加 remove_iframe_sandbox 作为全局插件启用。
    2. 在登陆 TTRSS 后,通过设置将 Fever API 作为本地插件启用。

    移除 iframe 上的 sandbox 属性,以支持 feed 中直接播放嵌入视频。

    使用指南见 Remove iframe sandbox (opens new window)

    # 主题

    # Feedly (opens new window)

    Feedly

    # RSSHub (opens new window)

    RssHub

    # 使用建议

    # 支持与帮助

    # 捐赠

    PayPal 微信赞赏 OpenCollective
    paypal (opens new window) 💰OpenCollective page (opens new window)

    # 许可

    MIT

    FOSSA Status (opens new window)

    - +填入 OpenCC API 地址

    使用 Awesome-TTRSS 部署的 OpenCC 可填写service.opencc:3000

    # 转换按钮

    # FeedReader API (opens new window)

    提供 FeedReader API 支持。

    系统插件,将 api_feedreader 添加到 ENABLE_PLUGINS 环境变量中以启用。

    使用指南见 FeedReader API (opens new window)

    # News+ API (opens new window)

    为 Android App News+ (opens new window) 和 iOS App Fiery Feeds (opens new window) 提供更快的同步速度。

    系统插件,将 api_newsplus 添加到 ENABLE_PLUGINS 环境变量中以启用。

    使用指南见 News+ API (opens new window)

    # Feediron (opens new window)

    提供文章 DOM 操控能力的插件。

    使用指南见 Feediron (opens new window)

    # Options per Feed (opens new window)

    提供单独为源地址配置代理、user-agent 以及 SSL 证书验证的能力。

    使用指南见 Options per Feed (opens new window)

    # Wallabag v2 (opens new window)

    保存文章至 Wallabag。

    使用指南见 Wallabag v2 (opens new window)

    # Remove iframe sandbox (opens new window)

    注意

    该插件与 Fever API 不能同时作为全局插件启用。如果您同时需要两者:

    1. 在环境变量 ENABLE_PLUGINS 中移除 fever 并添加 remove_iframe_sandbox 作为全局插件启用。
    2. 在登陆 TTRSS 后,通过设置将 Fever API 作为本地插件启用。

    移除 iframe 上的 sandbox 属性,以支持 feed 中直接播放嵌入视频。

    使用指南见 Remove iframe sandbox (opens new window)

    # 主题

    # Feedly (opens new window)

    Feedly

    # RSSHub (opens new window)

    RssHub

    # 使用建议

    # 支持与帮助

    # 捐赠

    PayPal 微信赞赏 OpenCollective
    paypal (opens new window) 💰OpenCollective page (opens new window)

    # 许可

    MIT

    FOSSA Status (opens new window)

    +