jekyll-ical-tag 1.2.4 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
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)