icalendar 2.2.2 → 2.3.0
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 +4 -4
- data/History.txt +6 -0
- data/lib/icalendar/downcased_hash.rb +40 -0
- data/lib/icalendar/has_components.rb +1 -1
- data/lib/icalendar/parser.rb +30 -17
- data/lib/icalendar/value.rb +9 -4
- data/lib/icalendar/values/array.rb +15 -3
- data/lib/icalendar/values/date_time.rb +3 -1
- data/lib/icalendar/values/time_with_zone.rb +2 -1
- data/lib/icalendar/version.rb +1 -1
- data/spec/downcased_hash_spec.rb +52 -0
- data/spec/fixtures/recurrence.ics +18 -0
- data/spec/fixtures/single_event_bad_dtstart.ics +21 -0
- data/spec/parser_spec.rb +34 -14
- data/spec/roundtrip_spec.rb +8 -0
- data/spec/values/date_time_spec.rb +9 -0
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ed623b569af5c7f68aa5917f19acedb5a11f7e8
|
4
|
+
data.tar.gz: 3293337f990892e2c07cc9c8d23f5bf4b86e5a37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a95ab23132eeffa95b42b1c2da033aa46b92775caf43928458ffd048685f66095855235b1b951f1bb18a1a33b7fb817cc1e4fc3f1b4917a277a3f18306dc592
|
7
|
+
data.tar.gz: 8d77c499752d3f589b9dca961d61df24f9b67a89f4764c462e71bcedd313a0f8d3b1aace26849bbe183a415235e4c6b159b8ea4b194b37cf9b202a73f001c568
|
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 2.3.0 2015-04-26
|
2
|
+
* fix value parameter for properties with multiple values
|
3
|
+
* fix error when assigning Icalendar::Values::Array to a component
|
4
|
+
* Fall back to Icalendar::Values::Date if Icalendar::Values::DateTime is not given a properly formatted value
|
5
|
+
* Downcase the keys in ical_params to ensure we aren't assigning both tzid and TZID
|
6
|
+
|
1
7
|
=== 2.2.2 2014-12-27
|
2
8
|
* add a `has_#{component}?` method for testing if component exists - John Hope
|
3
9
|
* add documentation & tests for organizer attribute - Ben Walding
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Icalendar
|
4
|
+
class DowncasedHash < ::SimpleDelegator
|
5
|
+
|
6
|
+
def initialize(base)
|
7
|
+
super Hash.new
|
8
|
+
base.each do |key, value|
|
9
|
+
self[key] = value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(key, value)
|
14
|
+
__getobj__[key.to_s.downcase] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](key)
|
18
|
+
__getobj__[key.to_s.downcase]
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_key?(key)
|
22
|
+
__getobj__.has_key? key.to_s.downcase
|
23
|
+
end
|
24
|
+
alias_method :include?, :has_key?
|
25
|
+
alias_method :member?, :has_key?
|
26
|
+
|
27
|
+
def delete(key, &block)
|
28
|
+
__getobj__.delete key.to_s.downcase, &block
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.DowncasedHash(base)
|
33
|
+
case base
|
34
|
+
when Icalendar::DowncasedHash then base
|
35
|
+
when Hash then Icalendar::DowncasedHash.new(base)
|
36
|
+
else
|
37
|
+
fail ArgumentError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/icalendar/parser.rb
CHANGED
@@ -32,23 +32,7 @@ module Icalendar
|
|
32
32
|
|
33
33
|
def parse_property(component, fields = nil)
|
34
34
|
fields = next_fields if fields.nil?
|
35
|
-
|
36
|
-
if !fields[:params]['value'].nil?
|
37
|
-
klass_name = fields[:params].delete('value').first
|
38
|
-
unless klass_name.upcase == klass.value_type
|
39
|
-
klass_name = klass_name.downcase.gsub(/(?:\A|-)(.)/) { |m| m[-1].upcase }
|
40
|
-
klass = Icalendar::Values.const_get klass_name if Icalendar::Values.const_defined?(klass_name)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
if klass.value_type != 'RECUR' && fields[:value] =~ /(?<!\\)([,;])/
|
44
|
-
delimiter = $1
|
45
|
-
prop_value = Icalendar::Values::Array.new fields[:value].split(/(?<!\\)[;,]/),
|
46
|
-
klass,
|
47
|
-
fields[:params],
|
48
|
-
delimiter: delimiter
|
49
|
-
else
|
50
|
-
prop_value = klass.new fields[:value], fields[:params]
|
51
|
-
end
|
35
|
+
prop_value = wrap_property_value component, fields
|
52
36
|
prop_name = %w(class method).include?(fields[:name]) ? "ip_#{fields[:name]}" : fields[:name]
|
53
37
|
begin
|
54
38
|
method_name = if component.class.multiple_properties.include? prop_name
|
@@ -68,6 +52,35 @@ module Icalendar
|
|
68
52
|
end
|
69
53
|
end
|
70
54
|
|
55
|
+
def wrap_property_value(component, fields)
|
56
|
+
klass = get_wrapper_class component, fields
|
57
|
+
if klass.value_type != 'RECUR' && fields[:value] =~ /(?<!\\)([,;])/
|
58
|
+
delimiter = $1
|
59
|
+
Icalendar::Values::Array.new fields[:value].split(/(?<!\\)[;,]/),
|
60
|
+
klass,
|
61
|
+
fields[:params],
|
62
|
+
delimiter: delimiter
|
63
|
+
else
|
64
|
+
klass.new fields[:value], fields[:params]
|
65
|
+
end
|
66
|
+
rescue Icalendar::Values::DateTime::FormatError => fe
|
67
|
+
raise fe if strict?
|
68
|
+
fields[:params]['value'] = ['DATE']
|
69
|
+
retry
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_wrapper_class(component, fields)
|
73
|
+
klass = component.class.default_property_types[fields[:name]]
|
74
|
+
if !fields[:params]['value'].nil?
|
75
|
+
klass_name = fields[:params].delete('value').first
|
76
|
+
unless klass_name.upcase == klass.value_type
|
77
|
+
klass_name = klass_name.downcase.gsub(/(?:\A|-)(.)/) { |m| m[-1].upcase }
|
78
|
+
klass = Icalendar::Values.const_get klass_name if Icalendar::Values.const_defined?(klass_name)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
klass
|
82
|
+
end
|
83
|
+
|
71
84
|
def strict?
|
72
85
|
!!@strict
|
73
86
|
end
|
data/lib/icalendar/value.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'delegate'
|
2
|
+
require 'icalendar/downcased_hash'
|
2
3
|
|
3
4
|
module Icalendar
|
4
5
|
|
@@ -7,12 +8,12 @@ module Icalendar
|
|
7
8
|
attr_accessor :ical_params
|
8
9
|
|
9
10
|
def initialize(value, params = {})
|
10
|
-
@ical_params = params
|
11
|
+
@ical_params = Icalendar::DowncasedHash(params)
|
11
12
|
super value
|
12
13
|
end
|
13
14
|
|
14
15
|
def ical_param(key, value)
|
15
|
-
@ical_params[key
|
16
|
+
@ical_params[key] = value
|
16
17
|
end
|
17
18
|
|
18
19
|
def value
|
@@ -20,7 +21,7 @@ module Icalendar
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def to_ical(default_type)
|
23
|
-
ical_param 'value', self.
|
24
|
+
ical_param 'value', self.value_type if needs_value_type?(default_type)
|
24
25
|
"#{params_ical}:#{value_ical}"
|
25
26
|
end
|
26
27
|
|
@@ -34,6 +35,10 @@ module Icalendar
|
|
34
35
|
name.gsub(/\A.*::/, '').gsub(/(?<!\A)[A-Z]/, '-\0').upcase
|
35
36
|
end
|
36
37
|
|
38
|
+
def value_type
|
39
|
+
self.class.value_type
|
40
|
+
end
|
41
|
+
|
37
42
|
private
|
38
43
|
|
39
44
|
def needs_value_type?(default_type)
|
@@ -77,4 +82,4 @@ require_relative 'values/uri'
|
|
77
82
|
require_relative 'values/utc_offset'
|
78
83
|
|
79
84
|
# further refine above classes
|
80
|
-
require_relative 'values/cal_address'
|
85
|
+
require_relative 'values/cal_address'
|
@@ -3,10 +3,18 @@ module Icalendar
|
|
3
3
|
|
4
4
|
class Array < Value
|
5
5
|
|
6
|
+
attr_reader :value_delimiter
|
7
|
+
|
6
8
|
def initialize(value, klass, params = {}, options = {})
|
7
9
|
@value_delimiter = options[:delimiter] || ','
|
8
10
|
mapped = if value.is_a? ::Array
|
9
|
-
value.map
|
11
|
+
value.map do |v|
|
12
|
+
if v.is_a? Icalendar::Values::Array
|
13
|
+
Icalendar::Values::Array.new v.value, klass, v.ical_params, delimiter: v.value_delimiter
|
14
|
+
else
|
15
|
+
klass.new v, params
|
16
|
+
end
|
17
|
+
end
|
10
18
|
else
|
11
19
|
[klass.new(value, params)]
|
12
20
|
end
|
@@ -23,7 +31,7 @@ module Icalendar
|
|
23
31
|
def value_ical
|
24
32
|
value.map do |v|
|
25
33
|
v.value_ical
|
26
|
-
end.join
|
34
|
+
end.join value_delimiter
|
27
35
|
end
|
28
36
|
|
29
37
|
def valid?
|
@@ -31,6 +39,10 @@ module Icalendar
|
|
31
39
|
!value.all? { |v| v.class == klass }
|
32
40
|
end
|
33
41
|
|
42
|
+
def value_type
|
43
|
+
value.first.value_type
|
44
|
+
end
|
45
|
+
|
34
46
|
private
|
35
47
|
|
36
48
|
def needs_value_type?(default_type)
|
@@ -40,4 +52,4 @@ module Icalendar
|
|
40
52
|
end
|
41
53
|
|
42
54
|
end
|
43
|
-
end
|
55
|
+
end
|
@@ -16,7 +16,7 @@ module Icalendar
|
|
16
16
|
begin
|
17
17
|
parsed_date = ::DateTime.strptime(value, FORMAT)
|
18
18
|
rescue ArgumentError => e
|
19
|
-
raise
|
19
|
+
raise FormatError.new("Failed to parse \"#{value}\" - #{e.message}")
|
20
20
|
end
|
21
21
|
|
22
22
|
super parsed_date, params
|
@@ -43,6 +43,8 @@ module Icalendar
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
class FormatError < ArgumentError
|
47
|
+
end
|
46
48
|
end
|
47
49
|
|
48
50
|
end
|
@@ -14,6 +14,7 @@ module Icalendar
|
|
14
14
|
attr_reader :tz_utc
|
15
15
|
|
16
16
|
def initialize(value, params = {})
|
17
|
+
params = Icalendar::DowncasedHash(params)
|
17
18
|
@tz_utc = params['tzid'] == 'UTC'
|
18
19
|
|
19
20
|
if defined?(ActiveSupport::TimeZone) && defined?(ActiveSupportTimeWithZoneAdapter) && !params['tzid'].nil?
|
@@ -22,7 +23,7 @@ module Icalendar
|
|
22
23
|
value = ActiveSupportTimeWithZoneAdapter.new nil, zone, value unless zone.nil?
|
23
24
|
super value, params
|
24
25
|
else
|
25
|
-
super
|
26
|
+
super value, params
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
data/lib/icalendar/version.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Icalendar::DowncasedHash do
|
4
|
+
|
5
|
+
subject { described_class.new base }
|
6
|
+
let(:base) { {'hello' => 'world'} }
|
7
|
+
|
8
|
+
describe '#[]=' do
|
9
|
+
it 'sets a new value' do
|
10
|
+
subject['FOO'] = 'bar'
|
11
|
+
expect(subject['foo']).to eq 'bar'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#[]' do
|
16
|
+
it 'gets an already set value' do
|
17
|
+
subject['foo'] = 'bar'
|
18
|
+
expect(subject['FOO']).to eq 'bar'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#has_key?' do
|
23
|
+
it 'correctly identifies keys in the hash' do
|
24
|
+
expect(subject.has_key? 'hello').to be true
|
25
|
+
expect(subject.has_key? 'HELLO').to be true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#delete' do
|
30
|
+
context 'no block' do
|
31
|
+
it 'removes the key' do
|
32
|
+
subject.delete 'HELLO'
|
33
|
+
expect(subject.has_key? 'hello').to be false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
context 'with a block' do
|
37
|
+
it 'calls the block when the key is not found' do
|
38
|
+
expect { |b| subject.delete 'nokey', &b }.to yield_with_args('nokey')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'DowncasedHash()' do
|
44
|
+
it 'returns self when passed an DowncasedHash' do
|
45
|
+
expect(Icalendar::DowncasedHash(subject)).to be subject
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'wraps a hash in an downcased hash' do
|
49
|
+
expect(Icalendar::DowncasedHash(base)).to be_kind_of Icalendar::DowncasedHash
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
BEGIN:VCALENDAR
|
2
|
+
VERSION:2.0
|
3
|
+
PRODID:bsprodidfortestabc123
|
4
|
+
CALSCALE:GREGORIAN
|
5
|
+
BEGIN:VEVENT
|
6
|
+
DTSTAMP:20050118T211523Z
|
7
|
+
UID:bsuidfortestabc123
|
8
|
+
DTSTART;VALUE=DATE:20050323
|
9
|
+
DTEND;VALUE=DATE:20050323
|
10
|
+
CLASS:PRIVATE
|
11
|
+
ORGANIZER:mailto:joebob@random.net
|
12
|
+
PRIORITY:2
|
13
|
+
SUMMARY:This is a really long summary to test the method of unfolding lines
|
14
|
+
\, so I'm just going to make it a whole bunch of lines.
|
15
|
+
EXDATE;VALUE=DATE:20120323,20130323
|
16
|
+
RRULE:FREQ=YEARLY
|
17
|
+
END:VEVENT
|
18
|
+
END:VCALENDAR
|
@@ -0,0 +1,21 @@
|
|
1
|
+
BEGIN:VCALENDAR
|
2
|
+
VERSION:2.0
|
3
|
+
PRODID:bsprodidfortestabc123
|
4
|
+
CALSCALE:GREGORIAN
|
5
|
+
BEGIN:VEVENT
|
6
|
+
DTSTAMP:20050118T211523Z
|
7
|
+
UID:bsuidfortestabc123
|
8
|
+
DTSTART:20050120
|
9
|
+
DTEND;TZID=US-Mountain:20050120T184500
|
10
|
+
CLASS:PRIVATE
|
11
|
+
GEO:37.386013;-122.0829322
|
12
|
+
ORGANIZER:mailto:joebob@random.net
|
13
|
+
PRIORITY:2
|
14
|
+
SUMMARY:This is a really long summary to test the method of unfolding lines
|
15
|
+
\, so I'm just going to make it a whole bunch of lines.
|
16
|
+
ATTACH:http://bush.sucks.org/impeach/him.rhtml
|
17
|
+
ATTACH:http://corporations-dominate.existence.net/why.rhtml
|
18
|
+
RDATE;TZID=US-Mountain:20050121T170000,20050122T170000
|
19
|
+
X-TEST-COMPONENT;QTEST="Hello, World":Shouldn't double double quotes
|
20
|
+
END:VEVENT
|
21
|
+
END:VCALENDAR
|
data/spec/parser_spec.rb
CHANGED
@@ -2,29 +2,40 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Icalendar::Parser do
|
4
4
|
subject { described_class.new source, false }
|
5
|
+
let(:source) { File.read File.join(File.dirname(__FILE__), 'fixtures', fn) }
|
5
6
|
|
6
7
|
describe '#parse' do
|
7
|
-
|
8
|
+
context 'single_event.ics' do
|
9
|
+
let(:fn) { 'single_event.ics' }
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
it 'returns an array of calendars' do
|
12
|
+
expect(subject.parse).to be_instance_of Array
|
13
|
+
expect(subject.parse.count).to eq 1
|
14
|
+
expect(subject.parse[0]).to be_instance_of Icalendar::Calendar
|
15
|
+
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
it 'properly splits multi-valued lines' do
|
18
|
+
event = subject.parse.first.events.first
|
19
|
+
expect(event.geo).to eq [37.386013,-122.0829322]
|
20
|
+
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
it 'saves params' do
|
23
|
+
event = subject.parse.first.events.first
|
24
|
+
expect(event.dtstart.ical_params).to eq('tzid' => ['US-Mountain'])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
context 'recurrence.ics' do
|
28
|
+
let(:fn) { 'recurrence.ics' }
|
29
|
+
it 'correctly parses the exdate array' do
|
30
|
+
event = subject.parse.first.events.first
|
31
|
+
ics = event.to_ical
|
32
|
+
expect(ics).to match 'EXDATE;VALUE=DATE:20120323,20130323'
|
33
|
+
end
|
23
34
|
end
|
24
35
|
end
|
25
36
|
|
26
37
|
describe '#parse with bad line' do
|
27
|
-
let(:
|
38
|
+
let(:fn) { 'single_event_bad_line.ics' }
|
28
39
|
|
29
40
|
it 'returns an array of calendars' do
|
30
41
|
expect(subject.parse).to be_instance_of Array
|
@@ -42,4 +53,13 @@ describe Icalendar::Parser do
|
|
42
53
|
expect(event.dtstart.ical_params).to eq('tzid' => ['US-Mountain'])
|
43
54
|
end
|
44
55
|
end
|
56
|
+
|
57
|
+
describe 'missing date value parameter' do
|
58
|
+
let(:fn) { 'single_event_bad_dtstart.ics' }
|
59
|
+
|
60
|
+
it 'falls back to date type for dtstart' do
|
61
|
+
event = subject.parse.first.events.first
|
62
|
+
expect(event.dtstart).to be_kind_of Icalendar::Values::Date
|
63
|
+
end
|
64
|
+
end
|
45
65
|
end
|
data/spec/roundtrip_spec.rb
CHANGED
@@ -8,6 +8,14 @@ describe Icalendar do
|
|
8
8
|
it 'will generate the same file as is parsed' do
|
9
9
|
expect(Icalendar.parse(source, true).to_ical).to eq source
|
10
10
|
end
|
11
|
+
|
12
|
+
it 'array properties can be assigned to a new event' do
|
13
|
+
event = Icalendar::Event.new
|
14
|
+
parsed = Icalendar.parse source, true
|
15
|
+
event.rdate = parsed.events.first.rdate
|
16
|
+
expect(event.rdate.first).to be_kind_of Icalendar::Values::Array
|
17
|
+
expect(event.rdate.first.ical_params).to eq 'tzid' => ['US-Mountain']
|
18
|
+
end
|
11
19
|
end
|
12
20
|
|
13
21
|
describe 'timezone round trip' do
|
@@ -56,6 +56,15 @@ describe Icalendar::Values::DateTime do
|
|
56
56
|
expect(subject.to_ical described_class).to eq ":#{value}"
|
57
57
|
end
|
58
58
|
|
59
|
+
context 'manually set UTC' do
|
60
|
+
let(:value) { '20140209T194355' }
|
61
|
+
let(:params) { {'TZID' => 'UTC'} }
|
62
|
+
|
63
|
+
it 'does not add a tzid parameter, but does add a Z' do
|
64
|
+
expect(subject.to_ical described_class).to eq ":#{value}Z"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
59
68
|
context 'local time' do
|
60
69
|
let(:value) { '20140209T160652' }
|
61
70
|
let(:params) { {'tzid' => 'America/Denver'} }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icalendar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Ahearn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -159,6 +159,7 @@ files:
|
|
159
159
|
- lib/icalendar/alarm.rb
|
160
160
|
- lib/icalendar/calendar.rb
|
161
161
|
- lib/icalendar/component.rb
|
162
|
+
- lib/icalendar/downcased_hash.rb
|
162
163
|
- lib/icalendar/event.rb
|
163
164
|
- lib/icalendar/freebusy.rb
|
164
165
|
- lib/icalendar/has_components.rb
|
@@ -190,10 +191,13 @@ files:
|
|
190
191
|
- lib/icalendar/version.rb
|
191
192
|
- spec/alarm_spec.rb
|
192
193
|
- spec/calendar_spec.rb
|
194
|
+
- spec/downcased_hash_spec.rb
|
193
195
|
- spec/event_spec.rb
|
194
196
|
- spec/fixtures/nondefault_values.ics
|
195
197
|
- spec/fixtures/nonstandard.ics
|
198
|
+
- spec/fixtures/recurrence.ics
|
196
199
|
- spec/fixtures/single_event.ics
|
200
|
+
- spec/fixtures/single_event_bad_dtstart.ics
|
197
201
|
- spec/fixtures/single_event_bad_line.ics
|
198
202
|
- spec/fixtures/timezone.ics
|
199
203
|
- spec/fixtures/two_date_time_events.ics
|
@@ -238,17 +242,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
238
242
|
version: '0'
|
239
243
|
requirements: []
|
240
244
|
rubyforge_project:
|
241
|
-
rubygems_version: 2.
|
245
|
+
rubygems_version: 2.4.5
|
242
246
|
signing_key:
|
243
247
|
specification_version: 4
|
244
248
|
summary: A ruby implementation of the iCalendar specification (RFC-5545).
|
245
249
|
test_files:
|
246
250
|
- spec/alarm_spec.rb
|
247
251
|
- spec/calendar_spec.rb
|
252
|
+
- spec/downcased_hash_spec.rb
|
248
253
|
- spec/event_spec.rb
|
249
254
|
- spec/fixtures/nondefault_values.ics
|
250
255
|
- spec/fixtures/nonstandard.ics
|
256
|
+
- spec/fixtures/recurrence.ics
|
251
257
|
- spec/fixtures/single_event.ics
|
258
|
+
- spec/fixtures/single_event_bad_dtstart.ics
|
252
259
|
- spec/fixtures/single_event_bad_line.ics
|
253
260
|
- spec/fixtures/timezone.ics
|
254
261
|
- spec/fixtures/two_date_time_events.ics
|