Skip to content

Commit a34ac70

Browse files
Introduce medium importer (#499)
Merge pull request 499
1 parent 07479df commit a34ac70

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed

docs/_data/importer_dependencies.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ jrnl:
5050
- safe_yaml
5151
marley:
5252
- safe_yaml
53+
medium:
54+
- safe_yaml
5355
mephisto:
5456
- mysql2
5557
- sequel

docs/_importers/medium.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
layout: docs
3+
title: Medium
4+
prev_section: marley
5+
link_source: medium
6+
next_section: mephisto
7+
permalink: /docs/medium/
8+
---
9+
10+
To import your posts from [Medium](https://medium.com/), run:
11+
12+
{% highlight bash %}
13+
$ ruby -r rubygems -e 'require "jekyll-import";
14+
JekyllImport::Importers::Medium.run({
15+
"username" => "name",
16+
"render_audio" => false,
17+
"canonical_link" => false,
18+
})'
19+
{% endhighlight %}
20+
21+
The `username` refers to the medium username, and it's a mandatory field.
22+
23+
Other optional fields are as follows:
24+
* `canonical_link` – copy original link as `canonical_url` to post. (default: `false`)
25+
* `render_audio` – render `<audio>` element in posts for the enclosure URLs. (default: `false`)
26+
27+
_Note:_ This importer will also import the existing tags/labels from Medium post and include the tags to [Front Matter](https://jekyllrb.com/docs/front-matter/).
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
3+
module JekyllImport
4+
module Importers
5+
class Medium < Importer
6+
def self.specify_options(c)
7+
c.option "username", "--username NAME", "Medium username"
8+
c.option "canonical_link", "--canonical_link", "Copy original link as canonical_url to post (default: false)"
9+
c.option "render_audio", "--render_audio", "Render <audio> element in posts for the enclosure URLs (default: false)"
10+
end
11+
12+
def self.validate(options)
13+
abort "Missing mandatory option --username." if options["username"].nil?
14+
end
15+
16+
def self.require_deps
17+
Importers::RSS.require_deps
18+
end
19+
20+
# Medium posts and associated metadata are exported as an RSS Feed. Hence invoke our RSS Importer to create the
21+
# Jekyll source directory.
22+
#
23+
# "Tags" attached to a Medium post are exported under the markup `<item><category>...</category></item>` in the
24+
# export feed. Therefore, configure the RSS Importer to always look for tags in the `<category></category>` field
25+
# of an RSS item.
26+
def self.process(options)
27+
Importers::RSS.process({
28+
"source" => "https://medium.com/feed/@#{options.fetch("username")}",
29+
"render_audio" => options.fetch("render_audio", false),
30+
"canonical_link" => options.fetch("canonical_link", false),
31+
"extract_tags" => "category",
32+
})
33+
end
34+
end
35+
end
36+
end

test/mocks/medium_feed.xml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
3+
xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
4+
xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
5+
<channel>
6+
<title><![CDATA[Stories by John Doe on Medium]]></title>
7+
<description><![CDATA[Stories by John Doe on Medium]]></description>
8+
<link>https://medium.com/@John.Doe?source=rss-621a1d970ada------2</link>
9+
<image>
10+
<url>https://cdn-images-1.medium.com/fit/c/150/150/1*dmbNkD5D-u45r44go_cf0g.png</url>
11+
<title>Stories by John Doe on Medium</title>
12+
<link>https://medium.com/@John.Doe?source=rss-621a1d970ada------2</link>
13+
</image>
14+
<generator>Medium</generator>
15+
<lastBuildDate>Tue, 06 Dec 2022 06:52:04 GMT</lastBuildDate>
16+
<atom:link href="https://medium.com/@John.Doe/feed" rel="self" type="application/rss+xml"/>
17+
<webMaster><![CDATA[[email protected]]]></webMaster>
18+
<atom:link href="http://medium.superfeedr.com" rel="hub"/>
19+
<item>
20+
<title><![CDATA[This is a Dummy Post]]></title>
21+
<link>https://example.com/blog/this-is-a-dummy-post-50703370aea7?source=rss-621a1d970ada------2</link>
22+
<guid isPermaLink="false">https://medium.com/p/50703370aea7</guid>
23+
<category><![CDATA[java]]></category>
24+
<category><![CDATA[custom-jre]]></category>
25+
<category><![CDATA[image-size-reduce]]></category>
26+
<category><![CDATA[jvm]]></category>
27+
<category><![CDATA[docker]]></category>
28+
<dc:creator><![CDATA[John Doe]]></dc:creator>
29+
<pubDate>Tue, 22 Nov 2022 08:01:46 GMT</pubDate>
30+
<atom:updated>2022-11-23T14:51:57.412Z</atom:updated>
31+
<content:encoded><<![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v5nynoXfnHHGCpd0V0p8uw.png"
32+
/></figure><p>The quick brown fox jumps over the lazy dog</p>]]></content:encoded>
33+
</item>
34+
<item>
35+
<title><![CDATA[How I cross post Medium articles to GitHub Pages]]></title>
36+
<link>https://example.com/blog/how-i-cross-post-medium-articles-to-github-pages-1cdf174bc674?source=rss-621a1d970ada------2</link>
37+
<guid isPermaLink="false">https://medium.com/p/1cdf174bc674</guid>
38+
<category><![CDATA[import]]></category>
39+
<category><![CDATA[jekyll]]></category>
40+
<category><![CDATA[github-pages]]></category>
41+
<category><![CDATA[medium]]></category>
42+
<category><![CDATA[personal-website]]></category>
43+
<dc:creator><![CDATA[John Doe]]></dc:creator>
44+
<pubDate>Thu, 10 Nov 2022 21:39:51 GMT</pubDate>
45+
<atom:updated>2022-11-11T09:33:39.955Z</atom:updated>
46+
<content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cR9eGZr50HArf_j9-rnjjQ.png"
47+
/></figure><p>The quick brown fox jumps over the lazy dog</p>]]></content:encoded>
48+
</item>
49+
</channel>
50+
</rss>

0 commit comments

Comments
 (0)