feedjira 2.2.0 → 3.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.rubocop.yml +635 -6
- data/.travis.yml +1 -1
- data/CHANGELOG.md +6 -12
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -5
- data/README.md +37 -99
- data/Rakefile +5 -5
- data/feedjira.gemspec +27 -19
- data/lib/feedjira.rb +69 -41
- data/lib/feedjira/configuration.rb +3 -8
- data/lib/feedjira/core_ext.rb +3 -3
- data/lib/feedjira/core_ext/date.rb +1 -1
- data/lib/feedjira/core_ext/time.rb +2 -2
- data/lib/feedjira/date_time_utilities.rb +2 -2
- data/lib/feedjira/date_time_utilities/date_time_pattern_parser.rb +2 -2
- data/lib/feedjira/feed.rb +10 -80
- data/lib/feedjira/feed_entry_utilities.rb +4 -4
- data/lib/feedjira/parser.rb +4 -1
- data/lib/feedjira/parser/atom.rb +3 -3
- data/lib/feedjira/parser/atom_entry.rb +1 -1
- data/lib/feedjira/parser/atom_feed_burner.rb +4 -4
- data/lib/feedjira/parser/atom_feed_burner_entry.rb +1 -1
- data/lib/feedjira/parser/atom_youtube.rb +2 -2
- data/lib/feedjira/parser/atom_youtube_entry.rb +1 -1
- data/lib/feedjira/parser/google_docs_atom.rb +3 -3
- data/lib/feedjira/parser/google_docs_atom_entry.rb +1 -1
- data/lib/feedjira/parser/itunes_rss_item.rb +1 -1
- data/lib/feedjira/parser/json_feed.rb +39 -0
- data/lib/feedjira/parser/json_feed_item.rb +51 -0
- data/lib/feedjira/parser/podlove_chapter.rb +1 -1
- data/lib/feedjira/parser/rss.rb +1 -1
- data/lib/feedjira/parser/rss_entry.rb +5 -1
- data/lib/feedjira/parser/rss_feed_burner.rb +1 -1
- data/lib/feedjira/preprocessor.rb +1 -1
- data/lib/feedjira/version.rb +1 -1
- data/spec/feedjira/configuration_spec.rb +9 -16
- data/spec/feedjira/date_time_utilities_spec.rb +20 -20
- data/spec/feedjira/feed_entry_utilities_spec.rb +18 -18
- data/spec/feedjira/feed_spec.rb +15 -229
- data/spec/feedjira/feed_utilities_spec.rb +72 -72
- data/spec/feedjira/parser/atom_entry_spec.rb +34 -34
- data/spec/feedjira/parser/atom_feed_burner_entry_spec.rb +16 -16
- data/spec/feedjira/parser/atom_feed_burner_spec.rb +121 -119
- data/spec/feedjira/parser/atom_spec.rb +78 -76
- data/spec/feedjira/parser/atom_youtube_entry_spec.rb +38 -38
- data/spec/feedjira/parser/atom_youtube_spec.rb +15 -15
- data/spec/feedjira/parser/google_docs_atom_entry_spec.rb +8 -8
- data/spec/feedjira/parser/google_docs_atom_spec.rb +23 -21
- data/spec/feedjira/parser/itunes_rss_item_spec.rb +37 -37
- data/spec/feedjira/parser/itunes_rss_owner_spec.rb +5 -5
- data/spec/feedjira/parser/itunes_rss_spec.rb +118 -116
- data/spec/feedjira/parser/json_feed_item_spec.rb +79 -0
- data/spec/feedjira/parser/json_feed_spec.rb +53 -0
- data/spec/feedjira/parser/podlove_chapter_spec.rb +12 -12
- data/spec/feedjira/parser/rss_entry_spec.rb +30 -30
- data/spec/feedjira/parser/rss_feed_burner_entry_spec.rb +32 -32
- data/spec/feedjira/parser/rss_feed_burner_spec.rb +47 -45
- data/spec/feedjira/parser/rss_spec.rb +36 -36
- data/spec/feedjira/preprocessor_spec.rb +6 -6
- data/spec/feedjira_spec.rb +145 -0
- data/spec/sample_feeds.rb +27 -26
- data/spec/sample_feeds/HuffPostCanada.xml +279 -0
- data/spec/sample_feeds/json_feed.json +156 -0
- data/spec/spec_helper.rb +5 -5
- metadata +31 -49
- data/fixtures/vcr_cassettes/fetch_failure.yml +0 -62
- data/fixtures/vcr_cassettes/parse_error.yml +0 -222
- data/fixtures/vcr_cassettes/success.yml +0 -281
- data/spec/sample_feeds/InvalidDateFormat.xml +0 -20
@@ -8,12 +8,9 @@ module Feedjira
|
|
8
8
|
# end
|
9
9
|
module Configuration
|
10
10
|
attr_accessor(
|
11
|
-
:follow_redirect_limit,
|
12
11
|
:logger,
|
13
12
|
:parsers,
|
14
|
-
:request_timeout,
|
15
13
|
:strip_whitespace,
|
16
|
-
:user_agent
|
17
14
|
)
|
18
15
|
|
19
16
|
# Modify Feedjira's current configuration
|
@@ -42,12 +39,9 @@ module Feedjira
|
|
42
39
|
|
43
40
|
# @private
|
44
41
|
def set_default_configuration
|
45
|
-
self.follow_redirect_limit = 3
|
46
42
|
self.logger = default_logger
|
47
43
|
self.parsers = default_parsers
|
48
|
-
self.request_timeout = 30
|
49
44
|
self.strip_whitespace = false
|
50
|
-
self.user_agent = "Feedjira #{Feedjira::VERSION}"
|
51
45
|
end
|
52
46
|
|
53
47
|
private
|
@@ -55,7 +49,7 @@ module Feedjira
|
|
55
49
|
# @private
|
56
50
|
def default_logger
|
57
51
|
Logger.new(STDOUT).tap do |logger|
|
58
|
-
logger.progname =
|
52
|
+
logger.progname = "Feedjira"
|
59
53
|
logger.level = Logger::WARN
|
60
54
|
end
|
61
55
|
end
|
@@ -69,7 +63,8 @@ module Feedjira
|
|
69
63
|
Feedjira::Parser::AtomFeedBurner,
|
70
64
|
Feedjira::Parser::Atom,
|
71
65
|
Feedjira::Parser::ITunesRSS,
|
72
|
-
Feedjira::Parser::RSS
|
66
|
+
Feedjira::Parser::RSS,
|
67
|
+
Feedjira::Parser::JSONFeed,
|
73
68
|
]
|
74
69
|
end
|
75
70
|
end
|
data/lib/feedjira/core_ext.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "feedjira/core_ext/time"
|
2
|
+
require "feedjira/core_ext/date"
|
3
|
+
require "feedjira/core_ext/string"
|
@@ -7,14 +7,14 @@ module Feedjira
|
|
7
7
|
DateTimePatternParser,
|
8
8
|
DateTimeLanguageParser,
|
9
9
|
DateTimeEpochParser,
|
10
|
-
DateTime
|
10
|
+
DateTime,
|
11
11
|
].freeze
|
12
12
|
|
13
13
|
# Parse the given string starting with the most common parser (default ruby)
|
14
14
|
# and going over all other available parsers
|
15
15
|
# rubocop:disable Metrics/MethodLength
|
16
16
|
def parse_datetime(string)
|
17
|
-
res = DATE_PARSERS.
|
17
|
+
res = DATE_PARSERS.detect do |parser|
|
18
18
|
begin
|
19
19
|
return parser.parse(string).feed_utils_to_gm_time
|
20
20
|
rescue StandardError => e
|
@@ -7,7 +7,7 @@ module Feedjira
|
|
7
7
|
# Japanese Symbols are required for strange Date Strings like
|
8
8
|
# '水, 31 8 2016 07:37:00 PDT'
|
9
9
|
JAPANESE_SYMBOLS = %w(日 月 火 水 木 金 土).freeze
|
10
|
-
PATTERNS = [
|
10
|
+
PATTERNS = ["%m/%d/%Y %T %p", "%d %m %Y %T %Z"].freeze
|
11
11
|
|
12
12
|
# rubocop:disable Metrics/MethodLength
|
13
13
|
def self.parse(string)
|
@@ -26,7 +26,7 @@ module Feedjira
|
|
26
26
|
|
27
27
|
def self.prepare(string)
|
28
28
|
rgx = Regexp.new("^(#{JAPANESE_SYMBOLS.join('|')}),\s")
|
29
|
-
string.gsub(rgx,
|
29
|
+
string.gsub(rgx, "")
|
30
30
|
end
|
31
31
|
private_class_method :prepare
|
32
32
|
end
|
data/lib/feedjira/feed.rb
CHANGED
@@ -3,58 +3,33 @@
|
|
3
3
|
module Feedjira
|
4
4
|
class Feed
|
5
5
|
class << self
|
6
|
-
def parse_with(parser, xml, &block)
|
7
|
-
parser.parse xml, &block
|
8
|
-
end
|
9
|
-
|
10
|
-
def parse(xml, &block)
|
11
|
-
parser = determine_feed_parser_for_xml(xml)
|
12
|
-
raise NoParserAvailable, 'No valid parser for XML.' unless parser
|
13
|
-
parse_with parser, xml, &block
|
14
|
-
end
|
15
|
-
|
16
|
-
def determine_feed_parser_for_xml(xml)
|
17
|
-
start_of_doc = xml.slice(0, 2000)
|
18
|
-
feed_classes.detect { |klass| klass.able_to_parse?(start_of_doc) }
|
19
|
-
end
|
20
|
-
|
21
|
-
def add_feed_class(klass)
|
22
|
-
feed_classes.unshift klass
|
23
|
-
end
|
24
|
-
|
25
|
-
def feed_classes
|
26
|
-
@feed_classes ||= Feedjira.parsers
|
27
|
-
end
|
28
|
-
|
29
|
-
def reset_parsers!
|
30
|
-
@feed_classes = nil
|
31
|
-
end
|
32
|
-
|
33
6
|
def add_common_feed_element(element_tag, options = {})
|
34
|
-
|
35
|
-
k.element
|
7
|
+
Feedjira.parsers.each do |k|
|
8
|
+
k.element(element_tag, options)
|
36
9
|
end
|
37
10
|
end
|
38
11
|
|
39
12
|
def add_common_feed_elements(element_tag, options = {})
|
40
|
-
|
41
|
-
k.elements
|
13
|
+
Feedjira.parsers.each do |k|
|
14
|
+
k.elements(element_tag, options)
|
42
15
|
end
|
43
16
|
end
|
44
17
|
|
45
18
|
def add_common_feed_entry_element(element_tag, options = {})
|
46
|
-
call_on_each_feed_entry
|
19
|
+
call_on_each_feed_entry(:element, element_tag, options)
|
47
20
|
end
|
48
21
|
|
49
22
|
def add_common_feed_entry_elements(element_tag, options = {})
|
50
|
-
call_on_each_feed_entry
|
23
|
+
call_on_each_feed_entry(:elements, element_tag, options)
|
51
24
|
end
|
52
25
|
|
26
|
+
private
|
27
|
+
|
53
28
|
def call_on_each_feed_entry(method, *parameters)
|
54
|
-
|
29
|
+
Feedjira.parsers.each do |klass|
|
55
30
|
klass.sax_config.collection_elements.each_value do |value|
|
56
31
|
collection_configs = value.select do |v|
|
57
|
-
v.accessor ==
|
32
|
+
v.accessor == "entries" && v.data_class.class == Class
|
58
33
|
end
|
59
34
|
|
60
35
|
collection_configs.each do |config|
|
@@ -63,51 +38,6 @@ module Feedjira
|
|
63
38
|
end
|
64
39
|
end
|
65
40
|
end
|
66
|
-
|
67
|
-
def fetch_and_parse(url)
|
68
|
-
response = connection(url).get
|
69
|
-
unless response.success?
|
70
|
-
raise FetchFailure, "Fetch failed - #{response.status}"
|
71
|
-
end
|
72
|
-
feed = parse response.body
|
73
|
-
feed.feed_url = url
|
74
|
-
feed.etag = response.headers['etag'].to_s.delete '"'
|
75
|
-
|
76
|
-
feed.last_modified = parse_last_modified(response)
|
77
|
-
feed
|
78
|
-
end
|
79
|
-
|
80
|
-
# rubocop:disable LineLength
|
81
|
-
def connection(url)
|
82
|
-
Faraday.new(url: url, headers: headers, request: request_options) do |conn|
|
83
|
-
conn.use FaradayMiddleware::FollowRedirects, limit: Feedjira.follow_redirect_limit
|
84
|
-
conn.adapter(*Faraday.default_adapter)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
# rubocop:enable LineLength
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
def headers
|
92
|
-
{
|
93
|
-
user_agent: Feedjira.user_agent
|
94
|
-
}
|
95
|
-
end
|
96
|
-
|
97
|
-
def request_options
|
98
|
-
{
|
99
|
-
timeout: Feedjira.request_timeout
|
100
|
-
}
|
101
|
-
end
|
102
|
-
|
103
|
-
def parse_last_modified(response)
|
104
|
-
lm = response.headers['last-modified']
|
105
|
-
DateTime.parse(lm).to_time
|
106
|
-
rescue StandardError => e
|
107
|
-
Feedjira.logger.warn { "Failed to parse last modified '#{lm}'" }
|
108
|
-
Feedjira.logger.debug(e)
|
109
|
-
nil
|
110
|
-
end
|
111
41
|
end
|
112
42
|
end
|
113
43
|
end
|
@@ -13,7 +13,7 @@ module Feedjira
|
|
13
13
|
DateTime.parse(string).feed_utils_to_gm_time
|
14
14
|
rescue StandardError => e
|
15
15
|
Feedjira.logger.warn { "Failed to parse date #{string.inspect}" }
|
16
|
-
Feedjira.logger.
|
16
|
+
Feedjira.logger.warn(e)
|
17
17
|
nil
|
18
18
|
end
|
19
19
|
|
@@ -28,14 +28,14 @@ module Feedjira
|
|
28
28
|
# Writer for published. By default, we keep the "oldest" publish time found.
|
29
29
|
def published=(val)
|
30
30
|
parsed = parse_datetime(val)
|
31
|
-
@published = parsed if
|
31
|
+
@published = parsed if !@published || parsed < @published
|
32
32
|
end
|
33
33
|
|
34
34
|
##
|
35
35
|
# Writer for updated. By default, we keep the most recent update time found.
|
36
36
|
def updated=(val)
|
37
37
|
parsed = parse_datetime(val)
|
38
|
-
@updated = parsed if
|
38
|
+
@updated = parsed if !@updated || parsed > @updated
|
39
39
|
end
|
40
40
|
|
41
41
|
def sanitize!
|
@@ -52,7 +52,7 @@ module Feedjira
|
|
52
52
|
@rss_fields ||= instance_variables
|
53
53
|
|
54
54
|
@rss_fields.each do |field|
|
55
|
-
yield(field.to_s.sub(
|
55
|
+
yield(field.to_s.sub("@", ""), instance_variable_get(field))
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
data/lib/feedjira/parser.rb
CHANGED
data/lib/feedjira/parser/atom.rb
CHANGED
@@ -8,10 +8,10 @@ module Feedjira
|
|
8
8
|
|
9
9
|
element :title
|
10
10
|
element :subtitle, as: :description
|
11
|
-
element :link, as: :url, value: :href, with: { type:
|
12
|
-
element :link, as: :feed_url, value: :href, with: { rel:
|
11
|
+
element :link, as: :url, value: :href, with: { type: "text/html" }
|
12
|
+
element :link, as: :feed_url, value: :href, with: { rel: "self" }
|
13
13
|
elements :link, as: :links, value: :href
|
14
|
-
elements :link, as: :hubs, value: :href, with: { rel:
|
14
|
+
elements :link, as: :hubs, value: :href, with: { rel: "hub" }
|
15
15
|
elements :entry, as: :entries, class: AtomEntry
|
16
16
|
|
17
17
|
def self.able_to_parse?(xml)
|
@@ -7,7 +7,7 @@ module Feedjira
|
|
7
7
|
include FeedEntryUtilities
|
8
8
|
|
9
9
|
element :title
|
10
|
-
element :link, as: :url, value: :href, with: { type:
|
10
|
+
element :link, as: :url, value: :href, with: { type: "text/html", rel: "alternate" } # rubocop:disable Metrics/LineLength
|
11
11
|
element :name, as: :author
|
12
12
|
element :content
|
13
13
|
element :summary
|
@@ -9,12 +9,12 @@ module Feedjira
|
|
9
9
|
element :title
|
10
10
|
element :subtitle, as: :description
|
11
11
|
element :link, as: :url_text_html, value: :href,
|
12
|
-
with: { type:
|
12
|
+
with: { type: "text/html" }
|
13
13
|
element :link, as: :url_notype, value: :href, with: { type: nil }
|
14
|
-
element :link, as: :feed_url_link, value: :href, with: { type:
|
14
|
+
element :link, as: :feed_url_link, value: :href, with: { type: "application/atom+xml" } # rubocop:disable Metrics/LineLength
|
15
15
|
element :"atom10:link", as: :feed_url_atom10_link, value: :href,
|
16
|
-
with: { type:
|
17
|
-
elements :"atom10:link", as: :hubs, value: :href, with: { rel:
|
16
|
+
with: { type: "application/atom+xml" }
|
17
|
+
elements :"atom10:link", as: :hubs, value: :href, with: { rel: "hub" }
|
18
18
|
elements :entry, as: :entries, class: AtomFeedBurnerEntry
|
19
19
|
|
20
20
|
attr_writer :url, :feed_url
|
@@ -8,7 +8,7 @@ module Feedjira
|
|
8
8
|
|
9
9
|
element :title
|
10
10
|
element :name, as: :author
|
11
|
-
element :link, as: :url, value: :href, with: { type:
|
11
|
+
element :link, as: :url, value: :href, with: { type: "text/html", rel: "alternate" } # rubocop:disable Metrics/LineLength
|
12
12
|
element :"feedburner:origLink", as: :url
|
13
13
|
element :summary
|
14
14
|
element :content
|
@@ -6,8 +6,8 @@ module Feedjira
|
|
6
6
|
include SAXMachine
|
7
7
|
include FeedUtilities
|
8
8
|
element :title
|
9
|
-
element :link, as: :url, value: :href, with: { rel:
|
10
|
-
element :link, as: :feed_url, value: :href, with: { rel:
|
9
|
+
element :link, as: :url, value: :href, with: { rel: "alternate" }
|
10
|
+
element :link, as: :feed_url, value: :href, with: { rel: "self" }
|
11
11
|
element :name, as: :author
|
12
12
|
element :"yt:channelId", as: :youtube_channel_id
|
13
13
|
|
@@ -6,7 +6,7 @@ module Feedjira
|
|
6
6
|
include FeedEntryUtilities
|
7
7
|
|
8
8
|
element :title
|
9
|
-
element :link, as: :url, value: :href, with: { rel:
|
9
|
+
element :link, as: :url, value: :href, with: { rel: "alternate" }
|
10
10
|
element :name, as: :author
|
11
11
|
element :"media:description", as: :content
|
12
12
|
element :summary
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.expand_path(
|
1
|
+
require File.expand_path("./atom", File.dirname(__FILE__))
|
2
2
|
# rubocop:disable Style/Documentation
|
3
3
|
# rubocop:disable Style/DocumentationMethod
|
4
4
|
module Feedjira
|
@@ -8,8 +8,8 @@ module Feedjira
|
|
8
8
|
include FeedUtilities
|
9
9
|
element :title
|
10
10
|
element :subtitle, as: :description
|
11
|
-
element :link, as: :url, value: :href, with: { type:
|
12
|
-
element :link, as: :feed_url, value: :href, with: { type:
|
11
|
+
element :link, as: :url, value: :href, with: { type: "text/html" }
|
12
|
+
element :link, as: :feed_url, value: :href, with: { type: "application/atom+xml" } # rubocop:disable Metrics/LineLength
|
13
13
|
elements :link, as: :links, value: :href
|
14
14
|
elements :entry, as: :entries, class: GoogleDocsAtomEntry
|
15
15
|
|
@@ -7,7 +7,7 @@ module Feedjira
|
|
7
7
|
include FeedEntryUtilities
|
8
8
|
|
9
9
|
element :title
|
10
|
-
element :link, as: :url, value: :href, with: { type:
|
10
|
+
element :link, as: :url, value: :href, with: { type: "text/html", rel: "alternate" } # rubocop:disable Metrics/LineLength
|
11
11
|
element :name, as: :author
|
12
12
|
element :content
|
13
13
|
element :summary
|
@@ -34,7 +34,7 @@ module Feedjira
|
|
34
34
|
element :enclosure, value: :length, as: :enclosure_length
|
35
35
|
element :enclosure, value: :type, as: :enclosure_type
|
36
36
|
element :enclosure, value: :url, as: :enclosure_url
|
37
|
-
elements
|
37
|
+
elements "psc:chapter", as: :raw_chapters, class: Feedjira::Parser::PodloveChapter # rubocop:disable Metrics/LineLength
|
38
38
|
|
39
39
|
# Podlove requires clients to re-order by start time in the
|
40
40
|
# event the publisher doesn't provide them in that
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Feedjira
|
2
|
+
module Parser
|
3
|
+
# Parser for dealing with JSON Feeds.
|
4
|
+
class JSONFeed
|
5
|
+
include SAXMachine
|
6
|
+
include FeedUtilities
|
7
|
+
|
8
|
+
def self.able_to_parse?(json)
|
9
|
+
%r{https:\/\/jsonfeed.org\/version\/} =~ json
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.parse(json)
|
13
|
+
new(JSON.parse(json))
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :json, :version, :title, :url, :feed_url, :description,
|
17
|
+
:expired, :entries
|
18
|
+
|
19
|
+
def initialize(json)
|
20
|
+
@json = json
|
21
|
+
@version = json.fetch("version")
|
22
|
+
@title = json.fetch("title")
|
23
|
+
@url = json.fetch("home_page_url", nil)
|
24
|
+
@feed_url = json.fetch("feed_url", nil)
|
25
|
+
@description = json.fetch("description", nil)
|
26
|
+
@expired = json.fetch("expired", nil)
|
27
|
+
@entries = parse_items(json["items"])
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def parse_items(items)
|
33
|
+
items.map do |item|
|
34
|
+
Feedjira::Parser::JSONFeedItem.new(item)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Feedjira
|
2
|
+
module Parser
|
3
|
+
# Parser for dealing with JSON Feed items.
|
4
|
+
class JSONFeedItem
|
5
|
+
include FeedEntryUtilities
|
6
|
+
|
7
|
+
attr_reader :json, :entry_id, :url, :external_url, :title, :content, :summary,
|
8
|
+
:published, :updated, :image, :banner_image, :author, :categories
|
9
|
+
|
10
|
+
def initialize(json)
|
11
|
+
@json = json
|
12
|
+
@entry_id = json.fetch("id")
|
13
|
+
@url = json.fetch("url")
|
14
|
+
@external_url = json.fetch("external_url", nil)
|
15
|
+
@title = json.fetch("title", nil)
|
16
|
+
@content = parse_content(json.fetch("content_html", nil), json.fetch("content_text", nil))
|
17
|
+
@summary = json.fetch("summary", nil)
|
18
|
+
@image = json.fetch("image", nil)
|
19
|
+
@banner_image = json.fetch("banner_image", nil)
|
20
|
+
@published = parse_published(json.fetch("date_published", nil))
|
21
|
+
@updated = parse_updated(json.fetch("date_modified", nil))
|
22
|
+
@author = author_name(json.fetch("author", nil))
|
23
|
+
@categories = json.fetch("tags", [])
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def parse_published(date_published)
|
29
|
+
return nil unless date_published
|
30
|
+
Time.parse_safely(date_published)
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_updated(date_modified)
|
34
|
+
return nil unless date_modified
|
35
|
+
Time.parse_safely(date_modified)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Convenience method to return the included content type.
|
39
|
+
# Prefer content_html unless it isn't included.
|
40
|
+
def parse_content(content_html, content_text)
|
41
|
+
return content_html unless content_html.nil?
|
42
|
+
content_text
|
43
|
+
end
|
44
|
+
|
45
|
+
def author_name(author_obj)
|
46
|
+
return nil if author_obj.nil?
|
47
|
+
author_obj["name"]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|