-
Notifications
You must be signed in to change notification settings - Fork 334
Expand file tree
/
Copy pathrss.rb
More file actions
115 lines (93 loc) · 3.62 KB
/
rss.rb
File metadata and controls
115 lines (93 loc) · 3.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# frozen_string_literal: true
module JekyllImport
module Importers
class RSS < Importer
def self.specify_options(c)
c.option "source", "--source NAME", "The RSS file or URL to import."
c.option "tag", "--tag NAME", "Add a specific tag to all posts."
c.option "extract_tags", "--extract_tags KEY", "Copies tags from the given subfield on the RSS `<item>` to front matter. (default: null)"
c.option "render_audio", "--render_audio", "Render `<audio>` element in posts for the enclosure URLs. (default: false)"
c.option "canonical_link", "--canonical_link", "Add original link as `canonical_url` to post front matter. (default: false)"
end
def self.validate(options)
abort "Missing mandatory option --source." if options["source"].nil?
abort "Provide either --tag or --extract_tags option." if options["extract_tags"] && options["tag"]
end
def self.require_deps
JekyllImport.require_with_fallback(%w(
rss
rss/1.0
rss/2.0
open-uri
fileutils
safe_yaml
))
end
# Process the import.
#
# source - a URL or a local file String.
#
# Returns nothing.
def self.process(options)
source = options.fetch("source")
content = ""
URI.open(source) { |s| content = s.read }
rss = ::RSS::Parser.parse(content, false)
raise "There doesn't appear to be any RSS items at the source (#{source}) provided." unless rss
rss.items.each do |item|
write_rss_item(item, options)
end
end
def self.write_rss_item(item, options)
frontmatter = options.fetch("frontmatter", [])
body = options.fetch("body", ["description"])
render_audio = options.fetch("render_audio", false)
formatted_date = item.date.strftime("%Y-%m-%d")
post_name = Jekyll::Utils.slugify(item.title, :mode => "latin")
name = "#{formatted_date}-#{post_name}"
audio = render_audio && item.enclosure.url
canonical_link = options.fetch("canonical_link", false)
header = {
"layout" => "post",
"title" => item.title,
"canonical_url" => (canonical_link ? item.link : nil),
"tag" => get_tags(item, options),
}.compact
frontmatter.each do |value|
header[value] = item.send(value)
end
output = +""
body.each do |row|
output << item.send(row).to_s
end
output.strip!
output = item.content_encoded if output.empty?
FileUtils.mkdir_p("_posts")
File.open("_posts/#{name}.html", "w") do |f|
f.puts header.to_yaml
f.puts "---\n\n"
if audio
f.puts <<~HTML
<audio controls="">
<source src="#{audio}" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
HTML
end
f.puts output
end
end
def self.get_tags(item, options)
explicit_tag = options["tag"]
return explicit_tag unless explicit_tag.nil? || explicit_tag.empty?
tags_reference = options["extract_tags"]
return unless tags_reference
tags_from_feed = item.instance_variable_get("@#{tags_reference}")
return unless tags_from_feed.is_a?(Array)
tags = tags_from_feed.map { |feed_tag| feed_tag.content.downcase }
tags.empty? ? nil : tags.tap(&:uniq!)
end
private_class_method :get_tags
end
end
end