diff --git a/docs/README.md b/docs/README.md
index 879882d92a..bcec671ccd 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1089,6 +1089,10 @@ GitHub 官方也提供了一些 RSS:
+### Typora
+
+
+
## 大学通知
### 上海海事大学
diff --git a/router.js b/router.js
index 4c3d2eccf9..e4a083775d 100644
--- a/router.js
+++ b/router.js
@@ -790,6 +790,9 @@ router.get('/eeo/:category?', require('./routes/eeo/index'));
// 腾讯视频
router.get('/tencentvideo/playlist/:id', require('./routes/tencent/video/playlist'));
+// typora
+router.get('/typora/changelog', require('./routes/typora/changelog'));
+
// TSSstatus
router.get('/tssstatus/:board/:build', require('./routes/tssstatus'));
diff --git a/routes/typora/changelog.js b/routes/typora/changelog.js
new file mode 100644
index 0000000000..b848f6b1fd
--- /dev/null
+++ b/routes/typora/changelog.js
@@ -0,0 +1,70 @@
+const axios = require('../../utils/axios');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const host = 'https://support.typora.io/';
+
+ const response = await axios({
+ method: 'get',
+ url: host,
+ headers: {
+ Referer: host,
+ },
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const parseContent = async (link) => {
+ // Check cache
+ const cache = await ctx.cache.get(link);
+ if (cache) {
+ return Promise.resolve(JSON.parse(cache));
+ }
+
+ const response = await axios({
+ method: 'get',
+ url: link,
+ headers: {
+ Referer: host,
+ },
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const title = $('h1').text();
+ const pubDate = new Date($('.post-meta time').text());
+ // const author = $('.post-meta span').text();
+ const html = $('#pagecontainer').html();
+
+ const result = {
+ title: title,
+ link: link,
+ guid: link,
+ pubDate: pubDate,
+ description: html,
+ };
+
+ ctx.cache.set(link, JSON.stringify(result), 3 * 60 * 60);
+
+ return result;
+ };
+
+ const items = await Promise.all(
+ $('#content > ul:nth-child(2) > li')
+ .get()
+ .map(async (item) => {
+ const node = $('a', item);
+ const link = node.attr('href');
+ const result = await parseContent(link);
+
+ return Promise.resolve(result);
+ })
+ );
+
+ ctx.state.data = {
+ title: 'Typora Changelog',
+ link: host,
+ description: 'Typora Changelog',
+ item: items,
+ };
+};