icalendar2 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +4 -1
- data/README.md +2 -0
- data/lib/icalendar2/calendar.rb +10 -7
- data/lib/icalendar2/calendar_property.rb +2 -1
- data/lib/icalendar2/component/alarm.rb +9 -0
- data/lib/icalendar2/component/base.rb +8 -7
- data/lib/icalendar2/component/freebusy.rb +16 -0
- data/lib/icalendar2/component/journal.rb +18 -0
- data/lib/icalendar2/component/timezone.rb +9 -0
- data/lib/icalendar2/component/todo.rb +19 -0
- data/lib/icalendar2/component.rb +2 -1
- data/lib/icalendar2/property/base.rb +9 -3
- data/lib/icalendar2/property.rb +1 -1
- data/lib/icalendar2/tokens.rb +1 -1
- data/lib/icalendar2/value/text_value.rb +5 -8
- data/lib/icalendar2/value.rb +2 -1
- data/lib/icalendar2/version.rb +1 -1
- data/lib/icalendar2.rb +5 -0
- metadata +54 -34
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# icalendar2 - generate, consume and validate iCalendar feeds
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/ericcf/icalendar2.png?branch=master)](https://travis-ci.org/ericcf/icalendar2)
|
4
|
+
|
3
5
|
## Warning
|
4
6
|
|
5
7
|
This is NOT production ready yet. It has not been extensively tested, and you
|
data/lib/icalendar2/calendar.rb
CHANGED
@@ -8,10 +8,10 @@ module Icalendar2
|
|
8
8
|
Event::VALUE => []
|
9
9
|
}
|
10
10
|
@properties = {
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
"calscale" => Property::Nil.new,
|
12
|
+
"method" => Property::Nil.new,
|
13
|
+
"prodid" => Property::Nil.new,
|
14
|
+
"version" => Property::Nil.new
|
15
15
|
}
|
16
16
|
end
|
17
17
|
|
@@ -32,7 +32,7 @@ module Icalendar2
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def set_property(property_name, value, parameters = {})
|
35
|
-
property = property_name.downcase
|
35
|
+
property = property_name.to_s.downcase
|
36
36
|
if value.nil?
|
37
37
|
@properties[property].value.to_s
|
38
38
|
elsif (factory = CalendarProperty.get_factory(property_name))
|
@@ -64,7 +64,9 @@ module Icalendar2
|
|
64
64
|
str = "#{Tokens::COMPONENT_BEGIN}:#{VALUE}#{Tokens::CRLF}"
|
65
65
|
str << body_to_ical
|
66
66
|
str << "#{Tokens::COMPONENT_END}:#{VALUE}#{Tokens::CRLF}"
|
67
|
-
str.encode("UTF-8")
|
67
|
+
str = str.encode("UTF-8") if str.respond_to?(:encode)
|
68
|
+
|
69
|
+
str
|
68
70
|
end
|
69
71
|
|
70
72
|
def add_component(component)
|
@@ -78,7 +80,8 @@ module Icalendar2
|
|
78
80
|
private
|
79
81
|
|
80
82
|
def body_to_ical
|
81
|
-
|
83
|
+
sorted_properties = @properties.zip.map(&:first).sort
|
84
|
+
str = sorted_properties.map { |p| p[1] && p[1].to_ical }.join
|
82
85
|
str << events.map(&:to_ical).join
|
83
86
|
end
|
84
87
|
end
|
@@ -3,7 +3,8 @@ module Icalendar2
|
|
3
3
|
def self.get_factory(calendar_property_name)
|
4
4
|
# "VERSION" => CalendarProperty::Version, etc.
|
5
5
|
begin
|
6
|
-
|
6
|
+
property_class_name = calendar_property_name.to_s.capitalize
|
7
|
+
const_get(property_class_name) if const_defined?(property_class_name)
|
7
8
|
rescue NameError
|
8
9
|
nil
|
9
10
|
end
|
@@ -31,7 +31,7 @@ module Icalendar2
|
|
31
31
|
def valid?
|
32
32
|
present_property_names = @properties.keys
|
33
33
|
@properties.values.flatten.all?(&:valid?) &&
|
34
|
-
self.class.required_property_names.all? { |p| present_property_names.include?(p) }
|
34
|
+
self.class.required_property_names.all? { |p| present_property_names.include?(p.to_s) }
|
35
35
|
end
|
36
36
|
|
37
37
|
def set_property(property_name, value, parameters = {})
|
@@ -61,9 +61,9 @@ module Icalendar2
|
|
61
61
|
define_method(property_sym) do |*args|
|
62
62
|
value, parameters = *args
|
63
63
|
if value.nil?
|
64
|
-
@properties[property_sym]
|
64
|
+
@properties[property_sym.to_s]
|
65
65
|
else
|
66
|
-
@properties[property_sym] = Property.get_factory(property_sym).new(value, parameters)
|
66
|
+
@properties[property_sym.to_s] = Property.get_factory(property_sym).new(value, parameters)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
alias_method "#{property_sym}=", property_sym
|
@@ -72,18 +72,19 @@ module Icalendar2
|
|
72
72
|
def self.define_multiple_accessor(property_sym)
|
73
73
|
property_factory = Property.get_factory(property_sym)
|
74
74
|
define_method(property_factory::PLURAL) do
|
75
|
-
@properties[property_sym]
|
75
|
+
@properties[property_sym.to_s]
|
76
76
|
end
|
77
77
|
define_method(property_sym) do |*args|
|
78
78
|
value, parameters = *args
|
79
|
-
@properties[property_sym] ||= []
|
80
|
-
@properties[property_sym] << property_factory.new(value, parameters)
|
79
|
+
@properties[property_sym.to_s] ||= []
|
80
|
+
@properties[property_sym.to_s] << property_factory.new(value, parameters)
|
81
81
|
end
|
82
82
|
alias_method "#{property_sym}=", property_sym
|
83
83
|
end
|
84
84
|
|
85
85
|
def properties_to_ical
|
86
|
-
@properties.
|
86
|
+
sorted_properties = @properties.zip.map(&:first).sort
|
87
|
+
sorted_properties.map { |p| p[1] && p[1].to_ical }.join
|
87
88
|
end
|
88
89
|
end
|
89
90
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Icalendar2
|
2
|
+
# See http://tools.ietf.org/html/rfc5545#section-3.6.4
|
3
|
+
class Freebusy < Component::Base
|
4
|
+
VALUE = "VFREEBUSY"
|
5
|
+
|
6
|
+
requires :exactly_one => [:dtstamp, :uid]
|
7
|
+
accepts :exactly_one => [:contact, :dtstart, :dtend, :organizer, :url],
|
8
|
+
:one_or_more => [:attendee, :comment, :freebusy, :rstatus]
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
super
|
12
|
+
self.uid = new_uid
|
13
|
+
self.dtstamp = new_timestamp
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Icalendar2
|
2
|
+
# See http://tools.ietf.org/html/rfc5545#section-3.6.3
|
3
|
+
class Journal < Component::Base
|
4
|
+
VALUE = "VJOURNAL"
|
5
|
+
|
6
|
+
requires :exactly_one => [:dtstamp, :uid]
|
7
|
+
accepts :exactly_one => [:klass, :created, :dtstart, :last_mod, :organizer,
|
8
|
+
:recurid, :seq, :status, :summary, :url],
|
9
|
+
:one_or_more => [:rrule, :attach, :attendee, :categories, :comment,
|
10
|
+
:contact, :description, :exdate, :related_to, :rdate, :rstatus]
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
super
|
14
|
+
self.uid = new_uid
|
15
|
+
self.dtstamp = new_timestamp
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Icalendar2
|
2
|
+
# See http://tools.ietf.org/html/rfc5545#section-3.6.2
|
3
|
+
class Todo < Component::Base
|
4
|
+
VALUE = "VTODO"
|
5
|
+
|
6
|
+
requires :exactly_one => [:dtstamp, :uid]
|
7
|
+
accepts :exactly_one => [:klass, :completed, :created, :description,
|
8
|
+
:dtstart, :geo, :last_mod, :location, :organizer, :percent, :priority,
|
9
|
+
:recurid, :seq, :status, :summary, :url, :due, :duration],
|
10
|
+
:one_or_more => [:rrule, :attach, :attendee, :categories, :comment,
|
11
|
+
:contact, :exdate, :rstatus, :related_to, :resources, :rdate]
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
super
|
15
|
+
self.uid = new_uid
|
16
|
+
self.dtstamp = new_timestamp
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/icalendar2/component.rb
CHANGED
@@ -2,7 +2,8 @@ module Icalendar2
|
|
2
2
|
module Component
|
3
3
|
def self.get_factory(component_name)
|
4
4
|
# "VFOO" => "Foo", etc.
|
5
|
-
|
5
|
+
component_class_name = component_name.gsub(/^V/, "").capitalize
|
6
|
+
Icalendar2.const_get(component_class_name) if Icalendar2.const_defined?(component_class_name)
|
6
7
|
end
|
7
8
|
end
|
8
9
|
end
|
@@ -2,7 +2,6 @@ module Icalendar2
|
|
2
2
|
module Property
|
3
3
|
class Base
|
4
4
|
MAX_LINE_LENGTH = 75
|
5
|
-
LIST_SEPARATOR = /(?<!\\),/
|
6
5
|
|
7
6
|
attr_reader :value, :parameters
|
8
7
|
|
@@ -26,7 +25,7 @@ module Icalendar2
|
|
26
25
|
|
27
26
|
def initialize(value, parameters = {})
|
28
27
|
@value = if list?
|
29
|
-
value_list = value.respond_to?(:
|
28
|
+
value_list = value.respond_to?(:gsub) ? split_list(value) : value
|
30
29
|
value_list.map { |v| value_object(v) }
|
31
30
|
else
|
32
31
|
value_object(value)
|
@@ -55,9 +54,11 @@ module Icalendar2
|
|
55
54
|
|
56
55
|
private
|
57
56
|
|
57
|
+
LIST_SEPARATOR = /([^\\]),/
|
58
|
+
|
58
59
|
def validate
|
59
60
|
@valid = if @value.is_a? Array
|
60
|
-
@value.all?(&:valid?)
|
61
|
+
@value.compact.all?(&:valid?)
|
61
62
|
else
|
62
63
|
@value.valid?
|
63
64
|
end
|
@@ -75,6 +76,11 @@ module Icalendar2
|
|
75
76
|
def fold(str)
|
76
77
|
str.scan(/.{1,#{MAX_LINE_LENGTH}}/).join("#{Tokens::CRLF} ")
|
77
78
|
end
|
79
|
+
|
80
|
+
def split_list(str)
|
81
|
+
# Ruby 1.8.7 doesn't support negative lookbehind, so using this hack...
|
82
|
+
str.gsub(LIST_SEPARATOR, "\\1x,").split(/x,/)
|
83
|
+
end
|
78
84
|
end
|
79
85
|
end
|
80
86
|
end
|
data/lib/icalendar2/property.rb
CHANGED
@@ -3,7 +3,7 @@ module Icalendar2
|
|
3
3
|
def self.get_factory(property_sym)
|
4
4
|
# :foo => "Foo", :bar_baz => "BarBaz", etc.
|
5
5
|
property_name = property_sym.to_s.split(/_/).map(&:capitalize).join('')
|
6
|
-
const_get(property_name
|
6
|
+
const_get(property_name) if const_defined?(property_name)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
data/lib/icalendar2/tokens.rb
CHANGED
@@ -13,7 +13,7 @@ module Icalendar2
|
|
13
13
|
QSAFE_CHAR = /[^"#{CONTROL_CHARS}]/
|
14
14
|
SAFE_CHAR = /[^"#{CONTROL_CHARS};:,]/
|
15
15
|
VALUE_CHAR = /[^#{CONTROL_CHARS}]/
|
16
|
-
NON_US_ASCII_CHARS = "\x80-\xFF"
|
16
|
+
NON_US_ASCII_CHARS = "\x80-\xFF"
|
17
17
|
QUOTED_STRING = /#{DQUOTE}(?:#{SAFE_CHAR})*#{DQUOTE}/
|
18
18
|
PARAM_VALUE = "(?:#{SAFE_CHAR})*|#{QUOTED_STRING}"
|
19
19
|
IANA_TOKEN = "[-a-zA-Z0-9]+"
|
@@ -4,14 +4,11 @@ module Icalendar2
|
|
4
4
|
class TextValue < Value
|
5
5
|
|
6
6
|
def initialize(value)
|
7
|
-
|
8
|
-
'
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
"\r" => "\n"
|
13
|
-
}
|
14
|
-
super(value.respond_to?(:gsub) ? value.gsub(/\\|;|,|\r\n|\r/, replacements) : value)
|
7
|
+
if value.respond_to?(:gsub)
|
8
|
+
super(value.gsub(/\\/, "\\\\\\").gsub(';', '\;').gsub(',', '\,').gsub("\r\n", "\n").gsub("\r", "\n"))
|
9
|
+
else
|
10
|
+
super(value)
|
11
|
+
end
|
15
12
|
end
|
16
13
|
end
|
17
14
|
end
|
data/lib/icalendar2/value.rb
CHANGED
@@ -13,7 +13,8 @@ module Icalendar2
|
|
13
13
|
def self.get_factory(value_sym)
|
14
14
|
# :foo => "Foo", :bar_baz => "BarBaz", etc.
|
15
15
|
value_name = value_sym.to_s.split(/_/).map(&:capitalize).join('')
|
16
|
-
|
16
|
+
value_class_name = "#{value_name}Value"
|
17
|
+
Icalendar2.const_get(value_class_name) if Icalendar2.const_defined?(value_class_name)
|
17
18
|
end
|
18
19
|
|
19
20
|
def initialize(value)
|
data/lib/icalendar2/version.rb
CHANGED
data/lib/icalendar2.rb
CHANGED
@@ -8,6 +8,11 @@ module Icalendar2
|
|
8
8
|
|
9
9
|
autoload :Component, "icalendar2/component"
|
10
10
|
autoload :Event, "icalendar2/component/event"
|
11
|
+
autoload :Todo, "icalendar2/component/todo"
|
12
|
+
autoload :Journal, "icalendar2/component/journal"
|
13
|
+
autoload :Freebusy, "icalendar2/component/freebusy"
|
14
|
+
autoload :Timezone, "icalendar2/component/timezone"
|
15
|
+
autoload :Alarm, "icalendar2/component/alarm"
|
11
16
|
module Component
|
12
17
|
autoload :Base, "icalendar2/component/base"
|
13
18
|
end
|
metadata
CHANGED
@@ -1,50 +1,60 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: icalendar2
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Eric Carty-Fickes
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-12-13 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: rspec
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '2'
|
22
|
-
type: :development
|
23
22
|
prerelease: false
|
24
|
-
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
24
|
none: false
|
26
|
-
requirements:
|
25
|
+
requirements:
|
27
26
|
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 7
|
29
|
+
segments:
|
30
|
+
- 2
|
31
|
+
version: "2"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Borrows fromt the API used by the icalendar Ruby gem. Outputs iCalendar (RFC 5545) formatted text.
|
35
|
+
email:
|
33
36
|
- ericcf@northwestern.edu
|
34
37
|
executables: []
|
38
|
+
|
35
39
|
extensions: []
|
36
|
-
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
37
42
|
- CHANGELOG.md
|
38
43
|
- README.md
|
39
|
-
files:
|
44
|
+
files:
|
40
45
|
- lib/icalendar2/calendar.rb
|
41
46
|
- lib/icalendar2/calendar_property/calscale.rb
|
42
47
|
- lib/icalendar2/calendar_property/method.rb
|
43
48
|
- lib/icalendar2/calendar_property/prodid.rb
|
44
49
|
- lib/icalendar2/calendar_property/version.rb
|
45
50
|
- lib/icalendar2/calendar_property.rb
|
51
|
+
- lib/icalendar2/component/alarm.rb
|
46
52
|
- lib/icalendar2/component/base.rb
|
47
53
|
- lib/icalendar2/component/event.rb
|
54
|
+
- lib/icalendar2/component/freebusy.rb
|
55
|
+
- lib/icalendar2/component/journal.rb
|
56
|
+
- lib/icalendar2/component/timezone.rb
|
57
|
+
- lib/icalendar2/component/todo.rb
|
48
58
|
- lib/icalendar2/component.rb
|
49
59
|
- lib/icalendar2/parameter/altrep.rb
|
50
60
|
- lib/icalendar2/parameter/base.rb
|
@@ -106,26 +116,36 @@ files:
|
|
106
116
|
- README.md
|
107
117
|
homepage: https://github.com/ericcf/icalendar2
|
108
118
|
licenses: []
|
119
|
+
|
109
120
|
post_install_message:
|
110
121
|
rdoc_options: []
|
111
|
-
|
122
|
+
|
123
|
+
require_paths:
|
112
124
|
- lib
|
113
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
126
|
none: false
|
115
|
-
requirements:
|
116
|
-
- -
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
|
119
|
-
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
hash: 3
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
version: "0"
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
135
|
none: false
|
121
|
-
requirements:
|
122
|
-
- -
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
hash: 3
|
140
|
+
segments:
|
141
|
+
- 0
|
142
|
+
version: "0"
|
125
143
|
requirements: []
|
144
|
+
|
126
145
|
rubyforge_project:
|
127
146
|
rubygems_version: 1.8.24
|
128
147
|
signing_key:
|
129
148
|
specification_version: 3
|
130
149
|
summary: iCalendar (RFC 5545) Ruby library
|
131
150
|
test_files: []
|
151
|
+
|