diff --git a/docs/en/traditional-media.md b/docs/en/traditional-media.md
index 56b661f121..240be960c1 100644
--- a/docs/en/traditional-media.md
+++ b/docs/en/traditional-media.md
@@ -108,6 +108,20 @@ Refer to [Chicago Tribune's feed page](https://www.chicagotribune.com/about/ct-c
+## ChinaFile
+
+### Reporting & Opinion
+
+
+
+Generates full-text feeds that the official feed doesn't provide.
+
+| All | The China NGO Project |
+| --- | --------------------- |
+| all | ngo |
+
+
+
## NHK
### News Web Easy
diff --git a/docs/traditional-media.md b/docs/traditional-media.md
index 2f3128a729..f0a4613745 100644
--- a/docs/traditional-media.md
+++ b/docs/traditional-media.md
@@ -91,6 +91,18 @@ pageClass: routes
+## ChinaFile
+
+
+
+通过提取文章全文,以提供比官方源更佳的阅读体验。
+
+| 全部 | The China NGO Project |
+| ---- | --------------------- |
+| all | ngo |
+
+
+
## e 公司
### 快讯
diff --git a/lib/router.js b/lib/router.js
index d51efac170..b5a7edba52 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -3444,4 +3444,7 @@ router.get('/gov/harbin/kjj', require('./routes/gov/harbin/kjj'));
// WSJ
router.get('/wsj/:lang/:category', require('./routes/wsj/index'));
+// China File
+router.get('/chinafile/:category?', require('./routes/chinafile/index'));
+
module.exports = router;
diff --git a/lib/routes/chinafile/index.js b/lib/routes/chinafile/index.js
new file mode 100644
index 0000000000..0c5fd4cdf8
--- /dev/null
+++ b/lib/routes/chinafile/index.js
@@ -0,0 +1,69 @@
+const Parser = require('rss-parser');
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+
+module.exports = async (ctx) => {
+ const category = ctx.params.category || 'all';
+ const rssUrl = `https://feeds.feedburner.com/chinafile/${category}`;
+
+ // The custom UA in @/utils/parser (mimic browser) results in a HTML page
+ // which cannot be parsed
+ const parser = new Parser();
+ const feed = await parser.parseURL(rssUrl);
+
+ const items = await Promise.all(
+ feed.items.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ let url = item.link;
+ const response = await got({ url });
+ const html = response.body;
+ const $ = cheerio.load(html);
+ const content = $('article');
+
+ // Cover
+ const cover = $('.view-featured-photo');
+
+ if (cover.length > 0) {
+ cover.insertBefore(content[0].childNodes[0]);
+ $(cover).remove();
+ }
+
+ // Summary
+ const summary = $('meta[name="description"]').attr('content');
+ const updatedAt = $('meta[name="og:updated_time"]').attr('content');
+
+ const categories = $('meta[name="news_keywords"]')
+ .attr('content')
+ .split(',')
+ .map((c) => c.trim());
+
+ url = $('link[rel="canonical"]').attr('href');
+
+ return {
+ title: item.title,
+ id: item.guid,
+ pubDate: item.pubDate,
+ updated: updatedAt,
+ author: item.creator,
+ link: url,
+ summary: summary,
+ description: content.html(),
+ category: categories,
+ icon: 'https://www.chinafile.com/sites/default/files/chinafile_favicon.png',
+ logo: 'https://www.chinafile.com/sites/all/themes/cftwo/assets/images/logos/logo-large.png',
+ };
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: feed.title,
+ link: feed.link,
+ description: feed.description,
+ item: items,
+ language: 'en-us',
+ icon: 'https://www.chinafile.com/sites/default/files/chinafile_favicon.png',
+ logo: 'https://www.chinafile.com/sites/all/themes/cftwo/assets/images/logos/logo-large.png',
+ };
+};