vcardigan 0.0.2

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.
@@ -0,0 +1,3 @@
1
+ module VCardigan
2
+ EncodingError = Class.new(StandardError)
3
+ end
@@ -0,0 +1,17 @@
1
+ module VCardigan
2
+
3
+ class NameProperty < Property
4
+
5
+ def setup
6
+ @values = ['', '', '', '', '']
7
+ end
8
+
9
+ private
10
+
11
+ def add_value(value, idx)
12
+ @values[idx] = value if value
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,222 @@
1
+ module VCardigan
2
+
3
+ class Property
4
+
5
+ APPLE_LABEL = /_\$!<(.*?)>!\$_/
6
+
7
+ attr_accessor :group
8
+ attr_reader :name
9
+ attr_reader :params
10
+ attr_reader :values
11
+
12
+ def initialize(vcard, name, *args)
13
+ @vcard = vcard
14
+ @params = {}
15
+ @values = []
16
+ @group = nil
17
+
18
+ setup if respond_to? :setup
19
+
20
+ # Determine whether this property name has a group
21
+ name_parts = name.to_s.split('.', 2)
22
+
23
+ # If it has a group, set it
24
+ if name_parts.length > 1
25
+ @group = name_parts.first
26
+ end
27
+
28
+ # Set the name
29
+ @name = name_parts.last.downcase
30
+
31
+ # Build out the values/params from the passed arguments
32
+ valueIdx = 0
33
+ args.each do |arg|
34
+ if arg.is_a? Hash
35
+ arg.each do |param, value|
36
+ param = param_name(param.to_s.downcase, value)
37
+ value = param_value(param, value)
38
+ add_param(param, value)
39
+ end
40
+ else
41
+ value = parse_value(arg.to_s)
42
+ add_value(value, valueIdx)
43
+ valueIdx += 1
44
+ end
45
+ end
46
+ end
47
+
48
+ def self.create(vcard, name, *args)
49
+ name = name.to_s.downcase
50
+ classname = ''
51
+
52
+ case name
53
+ when 'n'
54
+ className = 'NameProperty'
55
+ else
56
+ className = 'Property'
57
+ end
58
+
59
+ cls = Module.const_get('VCardigan').const_get(className)
60
+ cls.new(vcard, name, *args)
61
+ end
62
+
63
+ def self.parse(vcard, data)
64
+ # Gather the parts
65
+ data = data.strip
66
+ parts = data.split(':', 2)
67
+ values = parts.last.split(';')
68
+ params = parts.first.split(';')
69
+ name = params.shift
70
+
71
+ # Create argument array
72
+ args = [vcard, name]
73
+
74
+ # Add values to array
75
+ args.concat(values)
76
+
77
+ # Add params to array
78
+ params.each do |param|
79
+ keyval = param.split('=')
80
+ hash = Hash[keyval.first, keyval.last]
81
+ args.push(hash)
82
+ end
83
+
84
+ # Instantiate a new class with the argument array
85
+ self.create(*args)
86
+ end
87
+
88
+ def value(idx = 0)
89
+ @values[idx]
90
+ end
91
+
92
+ def param(name)
93
+ name ? @params[name.to_s.downcase] : nil
94
+ end
95
+
96
+ def to_s
97
+ # Name/Group
98
+ name = @name.upcase
99
+ property = @group ? "#{@group}.#{name}" : name.upcase
100
+
101
+ # Params
102
+ @params.each do |param, value|
103
+ str = param_to_s(param, value)
104
+ property << ';' << str if str
105
+ end
106
+
107
+ # Split with colon
108
+ property << ':'
109
+
110
+ # Values
111
+ @values.each_with_index do |value, idx|
112
+ property << ';' unless idx === 0
113
+ property << value
114
+ end
115
+
116
+ line_fold(property)
117
+ end
118
+
119
+ private
120
+
121
+ def version
122
+ @vcard.version
123
+ end
124
+
125
+ def v3?
126
+ version == '3.0'
127
+ end
128
+
129
+ def v4?
130
+ version == '4.0'
131
+ end
132
+
133
+ def param_name(name, value)
134
+ case name
135
+ when 'type'
136
+ if value == 'pref'
137
+ name = 'preferred'
138
+ end
139
+ when 'pref'
140
+ name = 'preferred'
141
+ end
142
+ name
143
+ end
144
+
145
+ def param_value(name, value)
146
+ case name
147
+ when 'preferred'
148
+ value = value.to_s
149
+ number = value.to_i
150
+ if number > 0
151
+ value = number
152
+ else
153
+ value = nil if value.downcase == 'false' or value == '0'
154
+ value = 1 if value
155
+ end
156
+ end
157
+ value
158
+ end
159
+
160
+ def parse_value(value)
161
+ # Parse Apple labels
162
+ match = value.match(APPLE_LABEL)
163
+ if match
164
+ value = match[1]
165
+ end
166
+ value
167
+ end
168
+
169
+ def add_value(value, idx)
170
+ @values.push(value)
171
+ end
172
+
173
+ def add_param(name, value)
174
+ name = name.to_s.downcase
175
+ if @params[name]
176
+ # Create array of param values if we have an existing param name
177
+ # present in the hash
178
+ unless @params[name].is_a? Array
179
+ @params[name] = [@params[name]]
180
+ end
181
+ @params[name].push(value)
182
+ else
183
+ # Default is to just set the param to the value
184
+ @params[name] = value
185
+ end
186
+ end
187
+
188
+ def param_to_s(name, value)
189
+ case name
190
+ when 'preferred'
191
+ if !value or value === 0
192
+ return nil
193
+ end
194
+ name = v3? ? 'type' : 'pref'
195
+ value = v3? ? 'pref' : value.is_a?(Numeric) ? value : 1
196
+ else
197
+ end
198
+ value = value.to_s
199
+ name.upcase << '=' << value unless value.empty?
200
+ end
201
+
202
+ def line_fold(string)
203
+ chars = @vcard.chars
204
+ if chars == 0
205
+ out = string
206
+ else
207
+ out = ''
208
+ while string.length > 0
209
+ if string.length >= chars
210
+ amount = out.empty? ? chars : chars - 1
211
+ out += "#{string.slice!(0, amount)}\n "
212
+ else
213
+ out += string.slice!(0, string.length)
214
+ end
215
+ end
216
+ end
217
+ out
218
+ end
219
+
220
+ end
221
+
222
+ end
@@ -0,0 +1,165 @@
1
+ module VCardigan
2
+
3
+ class VCard
4
+
5
+ VCARD_PATTERN = /BEGIN:VCARD\s+(.*?)VERSION:(.+?)\s+(.+?)END:VCARD/m;
6
+
7
+ attr_accessor :version
8
+ attr_accessor :chars
9
+
10
+ def initialize(options = {})
11
+ # Backwards compatibility
12
+ if options.is_a? String
13
+ options = { :version => options }
14
+ end
15
+
16
+ # Default options
17
+ @version = options[:version] || '4.0'
18
+ @chars = options[:chars] || 75
19
+
20
+ @fields = {}
21
+ @groups = {}
22
+ @group = nil
23
+ end
24
+
25
+ def parse(data)
26
+ match = VCARD_PATTERN.match(data)
27
+ if match
28
+ # Set version number
29
+ @version = match[2]
30
+ lines = "#{match[1].strip}#{match[3].strip}"
31
+
32
+ # Add the parsed properties to this vCard
33
+ lines.each_line do |line|
34
+ property = VCardigan::Property.parse(self, line)
35
+ add_prop(property)
36
+ end
37
+ end
38
+ self
39
+ end
40
+
41
+ def [](group)
42
+ @group = group
43
+ self
44
+ end
45
+
46
+ def method_missing(method, *args)
47
+ if args.empty?
48
+ # Return the field property/properties when no arguments are passed
49
+ field(method)
50
+ else
51
+ # Add property to vCard
52
+ add(method, *args)
53
+ end
54
+ end
55
+
56
+ def add(name, *args)
57
+ if @group
58
+ # If there's a group, add it to the name
59
+ name = "#{@group}.#{name}"
60
+
61
+ # Reset group to nil
62
+ @group = nil
63
+ end
64
+
65
+ # Build the property and add it to the vCard
66
+ property = build_prop(name, *args)
67
+ add_prop(property)
68
+ end
69
+
70
+ def field(name)
71
+ name = name.to_s.downcase
72
+ if @group and @fields[name]
73
+ # Finds all items that match the prop type in the group
74
+ fields = @fields[name].find_all do |prop|
75
+ prop.group == @group.to_s
76
+ end
77
+
78
+ # Reset the group to nil and return the fields
79
+ @group = nil
80
+ fields
81
+ else
82
+ @fields[name]
83
+ end
84
+ end
85
+
86
+ def group(name)
87
+ @groups[name]
88
+ end
89
+
90
+ def to_s
91
+ # Raise errors if invalid
92
+ validate
93
+
94
+ # Start vCard
95
+ vcard = build_prop(:begin, 'VCARD').to_s << "\n"
96
+
97
+ # Add version
98
+ vcard << build_prop(:version, @version).to_s << "\n"
99
+
100
+ # Add the properties
101
+ @fields.each do |field, properties|
102
+ properties.each do |property|
103
+ vcard << property.to_s << "\n"
104
+ end
105
+ end
106
+
107
+ # END
108
+ vcard << build_prop(:end, 'VCARD').to_s << "\n"
109
+
110
+ # Return vCard
111
+ return vcard
112
+ end
113
+
114
+ # Aliases ##########
115
+
116
+ def name(*args)
117
+ n(*args)
118
+ end
119
+
120
+ def fullname(*args)
121
+ fn(*args)
122
+ end
123
+
124
+ # Private ##########
125
+ private
126
+
127
+ def build_prop(name, *args)
128
+ VCardigan::Property.create(self, name, *args)
129
+ end
130
+
131
+ def add_prop(property)
132
+ name = property.name
133
+ group = property.group
134
+
135
+ # Create a field on the fields hash, if not already present, to house
136
+ # the property
137
+ unless @fields.has_key? name
138
+ @fields[name] = []
139
+ end
140
+
141
+ # Add the property to the field array
142
+ @fields[name].push(property)
143
+
144
+ if group
145
+ # Add a field on the groups hash, if not already present, to house the
146
+ # group properties
147
+ unless @groups.has_key? group
148
+ @groups[group] = []
149
+ end
150
+
151
+ # Add the property to the groups array
152
+ @groups[group].push(property)
153
+ end
154
+ end
155
+
156
+ def validate
157
+ unless @fields['fn']
158
+ raise VCardigan::EncodingError,
159
+ "vCards must include an FN field"
160
+ end
161
+ end
162
+
163
+ end
164
+
165
+ end
@@ -0,0 +1,5 @@
1
+ module VCardigan
2
+
3
+ VERSION = '0.0.2'
4
+
5
+ end
data/lib/vcardigan.rb ADDED
@@ -0,0 +1,21 @@
1
+ require_relative 'vcardigan/version'
2
+ require_relative 'vcardigan/vcard'
3
+ require_relative 'vcardigan/property'
4
+ require_relative 'vcardigan/properties/name_property'
5
+ require_relative 'vcardigan/errors'
6
+
7
+ module VCardigan
8
+
9
+ class << self
10
+
11
+ def create(*args)
12
+ VCardigan::VCard.new(*args)
13
+ end
14
+
15
+ def parse(*args)
16
+ VCardigan::VCard.new.parse(*args)
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,122 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe VCardigan::Property do
4
+
5
+ describe '#init' do
6
+ let(:vcard) { VCardigan.create }
7
+
8
+ context 'without a group' do
9
+ let(:name) { :email }
10
+ let(:value) { 'joe@strummer.com' }
11
+ let(:params) { { :type => 'uri' } }
12
+ let(:prop) { VCardigan::Property.create(vcard, name, value, params) }
13
+
14
+ it 'should set the name' do
15
+ prop.name.should == name.to_s.downcase
16
+ end
17
+
18
+ it 'should set the value' do
19
+ prop.values.first.should == value
20
+ end
21
+ end
22
+ end
23
+
24
+ describe '#values' do
25
+ let(:vcard) { VCardigan.create }
26
+ let(:name) { :email }
27
+ let(:value) { 'joe@strummer.com' }
28
+ let(:prop) { VCardigan::Property.create(vcard, name, value) }
29
+
30
+ it 'should return the values array' do
31
+ prop.values.should == prop.instance_variable_get(:@values)
32
+ end
33
+ end
34
+
35
+ describe '#value' do
36
+ let(:vcard) { VCardigan.create }
37
+ let(:name) { :n }
38
+ let(:value1) { 'Strummer' }
39
+ let(:value2) { 'Joe' }
40
+ let(:prop) { VCardigan::Property.create(vcard, name, value1, value2) }
41
+
42
+ context 'without an index' do
43
+ it 'should return the first item from the values array' do
44
+ prop.value.should == prop.instance_variable_get(:@values).first
45
+ end
46
+ end
47
+
48
+ context 'with an index' do
49
+ it 'should return the item corresponding to the index' do
50
+ prop.value(1).should == prop.instance_variable_get(:@values)[1]
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#params' do
56
+ let(:vcard) { VCardigan.create }
57
+ let(:name) { :email }
58
+ let(:value) { 'joe@strummer.com' }
59
+ let(:params) { { :type => 'uri' } }
60
+ let(:prop) { VCardigan::Property.create(vcard, name, value, params) }
61
+
62
+ it 'should return the params array' do
63
+ prop.params.should == prop.instance_variable_get(:@params)
64
+ end
65
+ end
66
+
67
+ describe '#param' do
68
+ let(:vcard) { VCardigan.create }
69
+ let(:name) { :email }
70
+ let(:value) { 'joe@strummer.com' }
71
+ let(:params) { { :type => 'uri' } }
72
+ let(:prop) { VCardigan::Property.create(vcard, name, value, params) }
73
+
74
+ context 'with a param that exists' do
75
+ it 'should return the param' do
76
+ prop.param(:type).should == params[:type]
77
+ end
78
+ end
79
+
80
+ context 'with a param that does not exist' do
81
+ it 'should return nil' do
82
+ prop.param(:random).should == nil
83
+ end
84
+ end
85
+ end
86
+
87
+ describe '#to_s' do
88
+ let(:vcard) { VCardigan.create }
89
+ let(:name) { :email }
90
+ let(:group) { :item1 }
91
+ let(:value) { 'joe@strummer.com' }
92
+ let(:params) { { :type => 'uri' } }
93
+ let(:prop) { VCardigan::Property.create(vcard, "#{group}.#{name}", value, params) }
94
+
95
+ it 'should return the property vCard formatted' do
96
+ prop.to_s.should == "#{group}.#{name.upcase};TYPE=#{params[:type]}:#{value}"
97
+ end
98
+ end
99
+
100
+ describe '#parse' do
101
+ let(:vcard) { VCardigan.create }
102
+ let(:name) { :email }
103
+ let(:group) { :item1 }
104
+ let(:value) { 'joe@strummer.com' }
105
+ let(:params) { { :type => 'uri' } }
106
+ let(:string) { "#{group}.#{name.upcase};TYPE=#{params[:type]}:#{value}" }
107
+ let(:prop) { VCardigan::Property.parse(vcard, string) }
108
+
109
+ it 'should set the group' do
110
+ prop.group.should == group.to_s.downcase
111
+ end
112
+
113
+ it 'should set the name' do
114
+ prop.name.should == name.to_s.downcase
115
+ end
116
+
117
+ it 'should set the values' do
118
+ prop.values.should == [value]
119
+ end
120
+ end
121
+
122
+ end
@@ -0,0 +1,250 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe VCardigan::VCard do
4
+
5
+ describe '#init' do
6
+ context 'no options' do
7
+ let(:vcard) { VCardigan.create }
8
+
9
+ it 'should set default version' do
10
+ vcard.version.should == '4.0'
11
+ end
12
+
13
+ it 'should set default line char limit' do
14
+ vcard.chars.should == 75
15
+ end
16
+ end
17
+
18
+ context 'version number for args (backward compat)' do
19
+ let(:version) { '3.0' }
20
+ let(:vcard) { VCardigan.create(version) }
21
+
22
+ it 'should set version' do
23
+ vcard.version.should == version
24
+ end
25
+ end
26
+
27
+ context 'passed options args' do
28
+ let(:version) { '3.0' }
29
+ let(:chars) { 100 }
30
+ let(:vcard) { VCardigan.create(:version => version, :chars => chars) }
31
+
32
+ it 'should set version' do
33
+ vcard.version.should == version
34
+ end
35
+
36
+ it 'should set line char limit' do
37
+ vcard.chars.should == chars
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '#[]' do
43
+ let(:group) { :item1 }
44
+ let(:vcard) { VCardigan.create }
45
+
46
+ before do
47
+ vcard[group]
48
+ end
49
+
50
+ it 'should return vcard' do
51
+ vcard.should be_an_instance_of(VCardigan::VCard)
52
+ end
53
+
54
+ it 'should set group' do
55
+ vcard.instance_variable_get(:@group).should == group
56
+ end
57
+ end
58
+
59
+ describe '#add' do
60
+ let(:name) { :email }
61
+ let(:value) { 'joe@strummer.com' }
62
+ let(:vcard) { VCardigan.create }
63
+ let(:fields) { vcard.instance_variable_get(:@fields) }
64
+
65
+ context 'with no group' do
66
+ before do
67
+ vcard.add(name, value)
68
+ end
69
+
70
+ it 'should add field name (as string) to fields hash' do
71
+ fields.should have_key(name.to_s)
72
+ end
73
+
74
+ it 'should create array on field name' do
75
+ fields[name.to_s].should be_an_instance_of(Array)
76
+ end
77
+
78
+ it 'should have single item in array' do
79
+ fields[name.to_s].length.should == 1
80
+ end
81
+
82
+ it 'should add property to field name array' do
83
+ fields[name.to_s].first.should be_an_instance_of(VCardigan::Property)
84
+ end
85
+ end
86
+
87
+ context 'with group' do
88
+ let(:group) { :item1 }
89
+ let(:groups) { vcard.instance_variable_get(:@groups) }
90
+
91
+ before do
92
+ vcard[group].add(name, value)
93
+ end
94
+
95
+ it 'should add group name (as string) to groups hash' do
96
+ groups.should have_key(group.to_s)
97
+ end
98
+
99
+ it 'should create array on group name' do
100
+ groups[group.to_s].should be_an_instance_of(Array)
101
+ end
102
+
103
+ it 'should have single item in array' do
104
+ groups[group.to_s].length.should == 1
105
+ end
106
+
107
+ it 'should add property group name array' do
108
+ groups[group.to_s].first.should be_an_instance_of(VCardigan::Property)
109
+ end
110
+ end
111
+ end
112
+
113
+ describe '#method_missing' do
114
+ let(:vcard) { VCardigan.create }
115
+
116
+ context 'with args' do
117
+ let(:name) { :email }
118
+ let(:email) { 'joe@strummer.com' }
119
+ let(:params) { { :type => 'uri' } }
120
+
121
+ it 'should call #add' do
122
+ vcard.should_receive(:add).with(name, email, params)
123
+ vcard.send(name, email, params)
124
+ end
125
+ end
126
+
127
+ context 'without args' do
128
+ let(:name) { :email }
129
+
130
+ it 'should call #field' do
131
+ vcard.should_receive(:field).with(name)
132
+ vcard.send(name)
133
+ end
134
+ end
135
+ end
136
+
137
+ describe '#field' do
138
+ let(:vcard) { VCardigan.create }
139
+ let(:fields) { vcard.instance_variable_get(:@fields) }
140
+ let(:name) { :email }
141
+ let(:value) { 'joe@strummer.com' }
142
+
143
+ context 'no group' do
144
+ before do
145
+ vcard.send(name, value)
146
+ end
147
+
148
+ it 'should return field name array' do
149
+ vcard.field(name).should == fields[name.to_s]
150
+ end
151
+
152
+ it 'should have correct property in array' do
153
+ vcard.field(name).first.value.should == value
154
+ end
155
+ end
156
+
157
+ context 'with group' do
158
+ let(:group) { :item1 }
159
+ let(:value2) { 'joestrummer@strummer.com' }
160
+
161
+ before do
162
+ vcard.send(name, value)
163
+ vcard[group].send(name, value2)
164
+ end
165
+
166
+ it 'should return field name array with props within group' do
167
+ vcard[group].field(name).should == fields[name.to_s].find_all do |prop|
168
+ prop.group == group.to_s
169
+ end
170
+ end
171
+
172
+ it 'should have correct property in array' do
173
+ vcard[group].field(name).first.value.should == value2
174
+ end
175
+ end
176
+ end
177
+
178
+ describe 'Aliases' do
179
+ let(:vcard) { VCardigan.create }
180
+
181
+ context '#name' do
182
+ it 'should call method_missing with method n' do
183
+ vcard.should_receive(:method_missing).with(:n)
184
+ vcard.name
185
+ end
186
+ end
187
+
188
+ context '#fullname' do
189
+ it 'should call method_missing with method fn' do
190
+ vcard.should_receive(:method_missing).with(:fn)
191
+ vcard.fullname
192
+ end
193
+ end
194
+ end
195
+
196
+ describe '#to_s' do
197
+ let(:vcard) { VCardigan.create }
198
+
199
+ context 'with no FN' do
200
+ it 'should raise an error' do
201
+ expect { vcard.to_s }.to raise_error(VCardigan::EncodingError)
202
+ end
203
+ end
204
+
205
+ context 'with an FN and N' do
206
+ before do
207
+ vcard.name('Strummer', 'Joe')
208
+ vcard.fullname('Joe Strummer')
209
+ end
210
+
211
+ it 'should have BEGIN on first line' do
212
+ vcard.to_s.split("\n").first.should == 'BEGIN:VCARD'
213
+ end
214
+
215
+ it 'should proceed with VERSION' do
216
+ vcard.to_s.split("\n")[1].should == 'VERSION:4.0'
217
+ end
218
+
219
+ it 'should include the N field' do
220
+ vcard.to_s.split("\n")[2].should == 'N:Strummer;Joe;;;'
221
+ end
222
+
223
+ it 'should include the FN field' do
224
+ vcard.to_s.split("\n")[3].should == 'FN:Joe Strummer'
225
+ end
226
+
227
+ it 'should end with END' do
228
+ vcard.to_s.split("\n").last.should == 'END:VCARD'
229
+ end
230
+ end
231
+ end
232
+
233
+ describe '#parse' do
234
+ context 'valid 4.0 vCard' do
235
+ let(:data) { File.read(File.dirname(__FILE__) + '/../helpers/joe.vcf') }
236
+ let(:vcard) { VCardigan.parse(data) }
237
+ let(:fields) { vcard.instance_variable_get(:@fields) }
238
+
239
+ it 'should set the version' do
240
+ vcard.version.should == '4.0'
241
+ end
242
+
243
+ it 'should add the properties to the fields array' do
244
+ fields.should have_key('n')
245
+ fields.should have_key('fn')
246
+ end
247
+ end
248
+ end
249
+
250
+ end
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + '/../lib/vcardigan'
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vcardigan
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Matt Morgan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
30
+ description: vCardigan is a ruby library for building and parsing vCards that supports
31
+ both v3.0 and v4.0.
32
+ email: matt@mlmorg.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - lib/vcardigan/errors.rb
38
+ - lib/vcardigan/properties/name_property.rb
39
+ - lib/vcardigan/property.rb
40
+ - lib/vcardigan/vcard.rb
41
+ - lib/vcardigan/version.rb
42
+ - lib/vcardigan.rb
43
+ - spec/examples/property_spec.rb
44
+ - spec/examples/vcard_spec.rb
45
+ - spec/spec_helper.rb
46
+ homepage: http://github.com/brewster/vcardigan
47
+ licenses:
48
+ - MIT
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.24
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Ruby vCard Builder/Parser
71
+ test_files:
72
+ - spec/examples/property_spec.rb
73
+ - spec/examples/vcard_spec.rb
74
+ - spec/spec_helper.rb