jekyll-ical-tag 1.2.4 → 1.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56b34cd54ee295b4125928f2d1c0ab010fc73073f013afcd485d3f94f2f7d1e7
4
- data.tar.gz: 6c04c4593314888e2f9f4dfbf13f9b3bd980d0739d5661bbf41243d1d8834cc8
3
+ metadata.gz: d7d1dce12392f01bb0a4d092684ffcec0dd51dd099a5c4d84634c2a4f5873785
4
+ data.tar.gz: 3bea7aac7663335f7df8928a10cff12bdc45a0ed0d59dc98530e18f35ca302ce
5
5
  SHA512:
6
- metadata.gz: 69a6fd90da57c3b2b2a26065f83d4197d82e8e8fcba655acaba83485e56dd26a23dfda4b5353491027146045f740649ce01897552e9a433292fe45f9b88aa0bc
7
- data.tar.gz: dbdbb209e8fdfed7653383ffac23c45b00579a4384789c8e11d01110de3f62fe92dae6701eb8dd231e8ab4f4d48a1979f563474b22895b1b5388b8d148004b2f
6
+ metadata.gz: 422e9632764d6c14a00aabab84592fde181f66782870de1d9eeaee7bdfa2c7531cf262c00ec16d25c13951490a8a937edfc746cd55387870169aebb3687cc58c
7
+ data.tar.gz: 6cc3cb90d9c76cfb50768522dc6c0205fdeab97baf621fe9be7983185724cbd1c79773f5c5027fb5fe527995706b25b186d97327b08399fb45a5caa3ae26fd8f
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  .DS_Store
2
2
  .bundle
3
- *.gem
3
+ *.gem
4
+
5
+ spec/examples.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/Gemfile.lock CHANGED
@@ -43,7 +43,7 @@ GEM
43
43
  sassc (> 2.0.1, < 3.0)
44
44
  jekyll-watch (2.2.1)
45
45
  listen (~> 3.0)
46
- kramdown (2.3.0)
46
+ kramdown (2.3.1)
47
47
  rexml
48
48
  kramdown-parser-gfm (1.1.0)
49
49
  kramdown (~> 2.0)
@@ -52,13 +52,15 @@ GEM
52
52
  rb-fsevent (~> 0.10, >= 0.10.3)
53
53
  rb-inotify (~> 0.9, >= 0.9.10)
54
54
  mercenary (0.3.6)
55
- mini_portile2 (2.4.0)
55
+ mini_portile2 (2.5.0)
56
56
  minitest (5.14.1)
57
- nokogiri (1.10.8)
58
- mini_portile2 (~> 2.4.0)
57
+ nokogiri (1.11.0)
58
+ mini_portile2 (~> 2.5.0)
59
+ racc (~> 1.4)
59
60
  pathutil (0.16.2)
60
61
  forwardable-extended (~> 2.6)
61
62
  public_suffix (4.0.3)
63
+ racc (1.5.2)
62
64
  rb-fsevent (0.10.3)
63
65
  rb-inotify (0.10.1)
64
66
  ffi (~> 1.0)
data/bin/rspec ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rspec-core", "rspec")
@@ -6,15 +6,18 @@ require "jekyll-ical-tag/version"
6
6
 
7
7
  module Jekyll
8
8
  class IcalTag < Liquid::Block
9
- require_relative "jekyll-ical-tag/event"
10
- require_relative "jekyll-ical-tag/calendar_parser"
9
+ require_relative "jekyll-ical-tag/calendar_feed_coordinator"
10
+ require_relative "jekyll-ical-tag/calendar_fetcher"
11
11
  require_relative "jekyll-ical-tag/calendar_limiter"
12
+ require_relative "jekyll-ical-tag/calendar_parser"
13
+ require_relative "jekyll-ical-tag/event"
12
14
 
13
15
  include Convertible
14
16
 
15
17
  def initialize(tag_name, markup, parse_context)
16
18
  super
17
19
  @markup = markup
20
+ @attributes = {}
18
21
 
19
22
  scan_attributes!
20
23
  set_limit!
@@ -31,22 +34,15 @@ module Jekyll
31
34
  result = []
32
35
 
33
36
  context.stack do
34
- url = get_dereferenced_url(context) ||
35
- @url
36
-
37
- raise "No URL provided or in innapropriate form '#{url}'" unless is_valid_url?(url)
38
-
39
- puts "Fetching #{url}"
37
+ url = get_dereferenced_url(context) || @url
40
38
 
41
- parser = CalendarParser.new(url)
42
- parser = CalendarLimiter.new(parser, only: @only)
43
- parser = CalendarLimiter.new(parser, reverse: @reverse)
44
- parser = CalendarLimiter.new(parser, before_date: @before_date)
45
- parser = CalendarLimiter.new(parser, after_date: @after_date)
46
- parser = CalendarLimiter.new(parser, limit: @limit)
47
-
48
- events = parser.events
49
- length = events.length
39
+ calendar_feed_coordinator = CalendarFeedCoordinator.new(
40
+ url: url, only: @only, reverse: @reverse,
41
+ before_date: @before_date, after_date: @after_date,
42
+ limit: @limit
43
+ )
44
+ events = calendar_feed_coordinator.events
45
+ event_count = events.length
50
46
 
51
47
  events.each_with_index do |event, index|
52
48
  # Init
@@ -69,32 +65,15 @@ module Jekyll
69
65
  context["event"]["end_time"] = context["event"]["dtend"]
70
66
  context["event"]["start_time"] = context["event"]["dtstart"]
71
67
 
72
- # Ensure all event values are utf8 encoded strings
73
- # Ensure times (from dates)
74
- # Ensure present
75
- context["event"].transform_values! do |value|
76
- v = case value
77
- when String, Icalendar::Values::Text
78
- value.force_encoding("UTF-8")
79
- when Date, Icalendar::Values::DateTime
80
- value.to_time
81
- when Icalendar::Values::Uri
82
- value.to_s
83
- else
84
- value
85
- end
86
- v.presence
87
- end
88
-
89
68
  context["forloop"] = {
90
69
  "name" => "ical",
91
- "length" => length,
70
+ "length" => event_count,
92
71
  "index" => index + 1,
93
72
  "index0" => index,
94
- "rindex" => length - index,
95
- "rindex0" => length - index - 1,
73
+ "rindex" => event_count - index,
74
+ "rindex0" => event_count - index - 1,
96
75
  "first" => (index == 0),
97
- "last" => (index == length - 1),
76
+ "last" => (index == event_count - 1),
98
77
  }
99
78
 
100
79
  result << nodelist.map do |n|
@@ -112,10 +91,6 @@ module Jekyll
112
91
 
113
92
  private
114
93
 
115
- def is_valid_url?(url)
116
- !!(url =~ URI::regexp)
117
- end
118
-
119
94
  def get_dereferenced_url(context)
120
95
  return unless context.key?(@url)
121
96
 
@@ -123,7 +98,6 @@ module Jekyll
123
98
  end
124
99
 
125
100
  def scan_attributes!
126
- @attributes = {}
127
101
  @markup.scan(Liquid::TagAttributes) do |key, value|
128
102
  @attributes[key] = value
129
103
  end
@@ -135,7 +109,7 @@ module Jekyll
135
109
  end
136
110
 
137
111
  def set_reverse!
138
- @reverse = @attributes["order"] == "reverse"
112
+ @reverse = @attributes["reverse"] == "true"
139
113
  end
140
114
 
141
115
  def set_url!
@@ -147,10 +121,11 @@ module Jekyll
147
121
  only_past = @attributes["only_past"] == "true"
148
122
 
149
123
  raise "Set only_future OR only_past, not both" if only_future && only_past
150
- @only = case
151
- when only_future
124
+
125
+ @only =
126
+ if only_future
152
127
  :future
153
- when only_past
128
+ elsif only_past
154
129
  :past
155
130
  else
156
131
  :all
@@ -158,21 +133,19 @@ module Jekyll
158
133
  end
159
134
 
160
135
  def set_before_date!
161
- @before_date = begin
162
- if @attributes["before_date"]
163
- Time.parse(@attributes["before_date"])
164
- end
165
- rescue => e
136
+ @before_date =
137
+ begin
138
+ Time.parse(@attributes["before_date"])
139
+ rescue
166
140
  nil
167
141
  end
168
142
  end
169
143
 
170
144
  def set_after_date!
171
- @after_date = begin
172
- if @attributes["after_date"]
173
- Time.parse(@attributes["after_date"])
174
- end
175
- rescue => e
145
+ @after_date =
146
+ begin
147
+ Time.parse(@attributes["after_date"])
148
+ rescue
176
149
  nil
177
150
  end
178
151
  end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Jekyll
5
+ class IcalTag
6
+ class CalendarFeedCoordinator
7
+ def initialize(url:, only: nil, reverse: nil, before_date: nil, after_date: nil, limit: nil)
8
+ @url = url
9
+ @only = only
10
+ @reverse = reverse
11
+ @before_date = before_date
12
+ @after_date = after_date
13
+ @limit = limit
14
+ end
15
+
16
+ def events
17
+ parser.events
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :url, :only, :reverse, :before_date, :after_date, :limit
23
+
24
+ def raw_ical
25
+ @raw_ical ||= CalendarFetcher.new(url).fetch
26
+ end
27
+
28
+ def parser
29
+ @parser ||= begin
30
+ parser = CalendarParser.new(raw_ical)
31
+ parser = CalendarLimiter.new(parser, only: only)
32
+ parser = CalendarLimiter.new(parser, reverse: reverse)
33
+ parser = CalendarLimiter.new(parser, before_date: before_date)
34
+ parser = CalendarLimiter.new(parser, after_date: after_date)
35
+ CalendarLimiter.new(parser, limit: limit)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require "cgi"
5
+ require "api_cache"
6
+
7
+ module Jekyll
8
+ class IcalTag
9
+ class CalendarFetcher
10
+ def initialize(url)
11
+ @url = CGI.unescape(url)
12
+
13
+ raise "No URL provided or in innapropriate form '#{url}'" unless is_valid_url?
14
+ end
15
+
16
+ def fetch
17
+ puts "Fetching #{url}"
18
+ @fetch ||= APICache.get(url)
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :url
24
+
25
+ def is_valid_url?
26
+ !!(url =~ URI::regexp)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,29 +1,25 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require "api_cache"
5
4
  require "active_support"
6
5
  require "icalendar"
7
6
 
8
7
  module Jekyll
9
8
  class IcalTag
10
9
  class CalendarParser
11
- def initialize(url)
12
- @url = URI.unescape(url)
10
+ def initialize(raw_feed)
11
+ @raw_feed = raw_feed
13
12
  end
14
13
 
15
14
  def events
16
- @events ||= begin
17
- Icalendar::Event.parse(ics_feed)
18
- .sort { |e1, e2| e1.dtstart <=> e2.dtstart }
19
- .map { |e| Jekyll::IcalTag::Event.new(e) }
20
- end
15
+ @events ||= parsed_feed.sort { |event1, event2| event1.dtstart <=> event2.dtstart }
16
+ .map { |event| Jekyll::IcalTag::Event.new(event) }
21
17
  end
22
18
 
23
19
  private
24
20
 
25
- def ics_feed
26
- @ics_feed ||= APICache.get(@url)
21
+ def parsed_feed
22
+ Icalendar::Event.parse(@raw_feed)
27
23
  end
28
24
  end
29
25
  end
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "uri"
5
+ require "active_support"
5
6
 
6
7
  module Jekyll
7
8
  class IcalTag
@@ -27,52 +28,84 @@ module Jekyll
27
28
  (?::\d{2,5})? # Optional port number
28
29
  (?:\/[^\s"]*)? # Anything that is not a space or a double quote
29
30
  /x
30
- extend Forwardable
31
31
 
32
- def initialize(event)
33
- @event = event
32
+ def initialize(ical_event)
33
+ @ical_event = ical_event
34
+ setup_all_properties!
35
+ setup_property_accessor_methods!
34
36
  end
35
37
 
36
- def_delegators :event, :dtstart, :dtend
37
-
38
- def all_properties
39
- @props ||= begin
40
- props = {}
41
-
42
- # RFC 5545 Properties
43
- event.class.properties.each do |property|
44
- props[property] = event.property(property)
45
- end
46
-
47
- # custom properties
48
- props = props.merge(event.custom_properties)
49
-
50
- props
51
- end
52
- end
38
+ attr_reader :all_properties
53
39
 
54
40
  def simple_html_description
55
41
  @simple_html_description ||= begin
56
- description&.clone.tap do |d|
57
- description_urls.each do |url|
58
- d.force_encoding("UTF-8").gsub! url, %(<a href='#{url}'>#{url}</a>)
59
- end
42
+ description.clone.tap do |description|
43
+ description_urls.each do |url|
44
+ description.gsub! url, %(<a href='#{url}'>#{url}</a>)
60
45
  end
61
46
  end
47
+ end
62
48
  end
63
49
 
64
50
  def attendees
65
- attendee.map(&:to_s).map { |a| a.slice!("mailto:"); a }
51
+ ical_event.attendee.map(&:to_s).map { |a| a.slice!("mailto:"); a }
66
52
  end
67
53
 
68
54
  def description_urls
69
- @description_urls ||= description.to_s.force_encoding("UTF-8").scan(URL_REGEX).to_a
55
+ return [] unless description
56
+
57
+ @description_urls ||= description.scan(URL_REGEX).to_a
70
58
  end
71
59
 
72
60
  private
73
61
 
74
- def_delegators :event, :description, :attendee
75
- attr_reader :event
62
+ attr_reader :ical_event
63
+
64
+ def setup_all_properties!
65
+ @all_properties ||= begin
66
+ props = {}
67
+
68
+ # RFC 5545 Properties
69
+ ical_event.class.properties.each do |property|
70
+ props[property] = ical_event.property(property)
71
+ end
72
+
73
+ # custom properties
74
+ props = props.merge(ical_event.custom_properties)
75
+
76
+ # Ensure all arrays get flattened to utf8 encoded strings
77
+ # Ensure all event values are utf8 encoded strings
78
+ # Ensure times (from dates)
79
+ # Ensure present
80
+ props.transform_values! do |value|
81
+ new_value =
82
+ case value
83
+ when Array, Icalendar::Values::Array
84
+ value.join("\n").force_encoding("UTF-8")
85
+ when String, Icalendar::Values::Text
86
+ value.force_encoding("UTF-8")
87
+ when Date, Icalendar::Values::DateTime
88
+ value.to_time
89
+ when Icalendar::Values::Uri
90
+ value.to_s
91
+ else
92
+ value
93
+ end
94
+
95
+ new_value.presence
96
+ end
97
+
98
+ props
99
+ end
100
+ end
101
+
102
+ def setup_property_accessor_methods!
103
+ all_properties.each do |prop, value|
104
+ define_singleton_method prop do
105
+ all_properties[prop]
106
+ end
107
+ end
108
+ end
76
109
  end
77
110
  end
78
111
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  class IcalTag < Liquid::Block
5
- VERSION = "1.2.4"
5
+ VERSION = "1.3.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-ical-tag
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ricky Chilcott
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-10 00:00:00.000000000 Z
11
+ date: 2021-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -102,13 +102,16 @@ extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
104
  - ".gitignore"
105
+ - ".rspec"
105
106
  - Gemfile
106
107
  - Gemfile.lock
107
108
  - README.md
108
- - _plugins/ical_tag.rb
109
109
  - bin/build-and-publish-gem
110
+ - bin/rspec
110
111
  - jekyll-ical-tag.gemspec
111
112
  - lib/jekyll-ical-tag.rb
113
+ - lib/jekyll-ical-tag/calendar_feed_coordinator.rb
114
+ - lib/jekyll-ical-tag/calendar_fetcher.rb
112
115
  - lib/jekyll-ical-tag/calendar_limiter.rb
113
116
  - lib/jekyll-ical-tag/calendar_parser.rb
114
117
  - lib/jekyll-ical-tag/event.rb
data/_plugins/ical_tag.rb DELETED
@@ -1,187 +0,0 @@
1
- require "api_cache"
2
- require "active_support"
3
- require "icalendar"
4
-
5
- class CalendarParser
6
- def initialize(url)
7
- @url = URI.unescape(url)
8
- end
9
-
10
- def events
11
- @events ||= Icalendar::Event.parse(ics_feed).sort { |e1, e2| e1.dtstart <=> e2.dtstart }
12
- end
13
-
14
- private
15
-
16
- def ics_feed
17
- @ics_feed ||= APICache.get(@url)
18
- end
19
- end
20
-
21
- class CalendarLimiter
22
- def initialize(parser, options = {})
23
- @parser = parser
24
- @options = options
25
- end
26
-
27
- def events
28
- case
29
- when options[:only] == :future
30
- now = Time.now
31
- parser.events.select do |event|
32
- event.dtstart.to_time >= now
33
- end
34
- when options[:only] == :past
35
- now = Time.now
36
- parser.events.select do |event|
37
- event.dtstart.to_time < now
38
- end
39
- when options[:reverse]
40
- parser.events.reverse
41
- when options[:after_date]
42
- parser.events.select do |event|
43
- event.dtstart.to_time >= options[:after_date]
44
- end
45
- when options[:before_date]
46
- parser.events.select do |event|
47
- event.dtstart.to_time < options[:before_date]
48
- end
49
- when options[:limit]
50
- parser.events.first(options[:limit].to_i)
51
- else
52
- parser.events
53
- end
54
- end
55
-
56
- private
57
-
58
- attr_reader :parser, :options
59
- end
60
-
61
- module Jekyll
62
- class CalendarTag < Liquid::Block
63
- include Convertible
64
-
65
- def initialize(tag_name, markup, parse_context)
66
- super
67
-
68
- @markup = markup
69
-
70
- scan_attributes!
71
- set_reverse!
72
- set_url!
73
- set_only!
74
- set_before_date!
75
- set_after_date!
76
- end
77
-
78
- def render(context)
79
- context.registers[:ical] ||= Hash.new(0)
80
-
81
- result = []
82
-
83
- parser = CalendarParser.new(@url)
84
- parser = CalendarLimiter.new(parser, only: @only)
85
- parser = CalendarLimiter.new(parser, reverse: @reverse)
86
- parser = CalendarLimiter.new(parser, before_date: @before_date)
87
- parser = CalendarLimiter.new(parser, after_date: @after_date)
88
-
89
- events = parser.events
90
- length = events.length
91
-
92
- context.stack do
93
- events.each_with_index do |event, index|
94
- attendees = event.attendee.map(&:to_s).map { |a| a.slice!("mailto:"); a }
95
-
96
- context["event"] = {
97
- "index" => index,
98
- "uid" => event.uid,
99
- "summary" => event.summary,
100
- "description" => event.description,
101
- "location" => event.location,
102
- "url" => event.url&.to_s,
103
- "start_time" => event.dtstart&.to_time,
104
- "end_time" => event.dtend&.to_time,
105
- "attendees" => attendees,
106
- }
107
-
108
- context["forloop"] = {
109
- "name" => "calendar",
110
- "length" => length,
111
- "index" => index + 1,
112
- "index0" => index,
113
- "rindex" => length - index,
114
- "rindex0" => length - index - 1,
115
- "first" => (index == 0),
116
- "last" => (index == length - 1),
117
- }
118
-
119
- result << nodelist.map do |n|
120
- if n.respond_to? :render
121
- n.render(context)
122
- else
123
- n
124
- end
125
- end.join
126
- end
127
- end
128
-
129
- result
130
- end
131
-
132
- private
133
-
134
- def scan_attributes!
135
- @attributes = {}
136
- @markup.scan(Liquid::TagAttributes) do |key, value|
137
- @attributes[key] = value
138
- end
139
- end
140
-
141
- def set_reverse!
142
- @reverse = @attributes["order"] == "reverse"
143
- end
144
-
145
- def set_url!
146
- @url = @attributes["url"]
147
- raise "No URL provided" unless @url
148
- end
149
-
150
- def set_only!
151
- only_future = @attributes["only_future"] == "true"
152
- only_past = @attributes["only_past"] == "true"
153
-
154
- raise "Set only_future OR only_past, not both" if only_future && only_past
155
- @only = case
156
- when only_future
157
- :future
158
- when only_past
159
- :past
160
- else
161
- :all
162
- end
163
- end
164
-
165
- def set_before_date!
166
- @before_date = begin
167
- if @attributes["before_date"]
168
- Time.parse(@attributes["before_date"])
169
- end
170
- rescue => e
171
- nil
172
- end
173
- end
174
-
175
- def set_after_date!
176
- @after_date = begin
177
- if @attributes["after_date"]
178
- Time.parse(@attributes["after_date"])
179
- end
180
- rescue => e
181
- nil
182
- end
183
- end
184
- end
185
- end
186
-
187
- Liquid::Template.register_tag("ical", Jekyll::CalendarTag)