simplevpim 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0df24d09c743af64bf2d92cddeb6cddd562983a2
4
- data.tar.gz: 8bd4c70e5aedacd6123231ba34cafe33e0620935
3
+ metadata.gz: 8410d4ea911c6e28edddd2e82a69bde5b3264352
4
+ data.tar.gz: 0c5ae0d7732a08e0e676bfa507a3e5be9e7cefc0
5
5
  SHA512:
6
- metadata.gz: 15d735c9463a72ad18e245465c99f36b131f2b0d371835885ce8451f87b0ec26a7792c66578a27f8dd2ab5507eb983c51e32eb3551fe7546bb877314d72223ba
7
- data.tar.gz: c4acec171f6316d6067a48f59a132f21dbe812238ffdf3eb890ad0adcc9ac33c1c3951fd5cecdd31b0ee4e92725c2799421cfb1f6d10a4f85734623b84c14dd4
6
+ metadata.gz: 89a1aaf2c31b1d89650c673ab9433b2d400bb3fbfe9245129a750c28e47810fcede685d024c74544cdfefac288c3977938523b1b7c426c038366f6607eb13393
7
+ data.tar.gz: 3154f9e48af76784731fa4adb79492c3930ca949b50bb1f0853633ac442990df4d2fb562c8e9f308b4c22cda3907eaf9fcf1e4ab1be0f5dac571922d78e82ab2
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -2,6 +2,7 @@
2
2
 
3
3
  # file: simplevpim.rb
4
4
 
5
+ require 'hlt'
5
6
  require 'nokogiri'
6
7
  require 'vpim/vcard'
7
8
  require 'rexle-builder'
@@ -14,20 +15,25 @@ class SimpleVpim
14
15
 
15
16
  def initialize(s)
16
17
 
17
- h = SimpleConfig.new(s).to_h
18
+ @h = SimpleConfig.new(s).to_h
18
19
 
19
- if h[:name] then
20
- @to_vcard = make_vcard h
21
- @to_xml = vcard_xml h
20
+ if @h[:name] then
21
+ @to_vcard = make_vcard @h
22
+ @to_xml = vcard_xml @h
22
23
  end
23
24
 
24
25
  end
25
26
 
26
27
  alias to_vcf to_vcard
27
28
 
29
+ def to_hcard(layout=nil)
30
+ make_hcard layout, @h
31
+ end
32
+
28
33
  def to_xcard()
29
34
  make_xcard @to_xml
30
35
  end
36
+
31
37
 
32
38
  private
33
39
 
@@ -150,16 +156,122 @@ class SimpleVpim
150
156
 
151
157
  end
152
158
  end
159
+
160
+ def make_hcard(raw_s, h)
161
+
162
+ raw_s ||= %q(
163
+ # hcard
164
+
165
+ img.photo
166
+ h1.fn
167
+ .email
168
+ .n
169
+
170
+ home:
171
+ .label
172
+ .adr
173
+ .tel
174
+
175
+ work:
176
+ .label
177
+ .adr
178
+ .tel
179
+ )
180
+
181
+ s = raw_s.split(/\n(?=\w+:?)/).inject('') do |r, x|
182
+
183
+ x.sub!(/^\s*#\s+.*/,'') # ignore comments
184
+
185
+ lines = x.lines
186
+ type = lines[0][/^(\w+):/,1]
187
+
188
+ if type then
189
+
190
+ lines.shift
191
+
192
+ r << lines.map do |line|
193
+
194
+ if line[/\s*\.\w+/] then
195
+ indent = line[/^ +/].to_s
196
+ "%s%sspan.type %s" % [line.sub(/^ {2}/,''), indent, type]
197
+ else
198
+ line
199
+ end
200
+
201
+ end.join("\n") + "\n"
202
+
203
+ else
204
+
205
+ r << x + "\n"
206
+ end
207
+
208
+ r
209
+
210
+ end
211
+
212
+ html_string = Hlt.new(s).to_html
213
+ html_template = <<EOF
214
+ <html>
215
+ <head>
216
+ <link rel="profile" href="http://microformats.org/profile/hcard" />
217
+ </head>
218
+ <body>
219
+ <div class='vcard'>#{html_string}</div>
220
+ </body>
221
+ </html>
222
+ EOF
223
+ doc = Rexle.new(html_template)
224
+
225
+ def doc.set(selector, val=nil)
226
+
227
+ e = self.at_css selector
228
+ return unless e
229
+ block_given? ? yield(e) : e.text = val
230
+
231
+ end
232
+
233
+ firstname, middlename, surname, fullname = extract_names(h[:name])
234
+ doc.set '.fn', fullname
235
+
236
+ #-- name ---------
237
+
238
+ e = doc.at_css '.n'
239
+ e.text = 'First Name:'
240
+ fname = Rexle::Element.new('span')
241
+ fname.attributes[:class] = 'given-name'
242
+ fname.text = firstname
243
+ e.add_element fname
244
+ e.add_element Rexle::Element.new('br')
245
+ e.add_text 'Last Name:'
246
+ lname = Rexle::Element.new('span')
247
+ lname.attributes[:class] = 'family-name'
248
+ lname.text = surname
249
+ e.add_element lname
250
+
251
+ doc.at_css('.photo').delete unless h[:photo]
252
+ doc.css('.tel').each(&:delete) unless h[:tel]
253
+ doc.css('.adr').each(&:delete) unless h[:adr]
254
+ doc.css('.label').each(&:delete) unless h[:label]
255
+
256
+ if h[:email].is_a? String then
257
+ e = doc.at_css '.email'
258
+ e.text = 'Email:'
259
+ alink = Rexle::Element.new('a')
260
+ alink.attributes[:class] = 'value'
261
+ alink.attributes[:href] = 'mailto:' + h[:email]
262
+ alink.text = h[:email]
263
+ e.add_element alink
264
+ end
265
+ [doc, h]
266
+
267
+ end
153
268
 
154
269
  def make_xcard(xml)
155
-
156
270
  lib = File.dirname(__FILE__)
157
- xsl = File.read File.join(lib,'xcard.xsl')
271
+ xsl = open(lib + '/xcard.xsl','UserAgent' => 'SimplevPim').read
158
272
  doc = Nokogiri::XML(xml)
159
-
160
273
  xslt = Nokogiri::XSLT(xsl)
161
274
  xslt.transform(doc).to_s
162
-
163
275
  end
164
276
 
165
277
  def vcard_xml(h)
@@ -0,0 +1,374 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # file: simplevpim.rb
4
+
5
+ require 'hlt'
6
+ require 'nokogiri'
7
+ require 'vpim/vcard'
8
+ require 'rexle-builder'
9
+ require 'simple-config'
10
+
11
+
12
+ class SimpleVpim
13
+
14
+ attr_reader :to_vcard, :to_xml
15
+
16
+ def initialize(s)
17
+
18
+ @h = SimpleConfig.new(s).to_h
19
+
20
+ if @h[:name] then
21
+ @to_vcard = make_vcard @h
22
+ @to_xml = vcard_xml @h
23
+ end
24
+
25
+ end
26
+
27
+ alias to_vcf to_vcard
28
+
29
+ def to_hcard(layout=nil)
30
+ make_hcard layout, @h
31
+ end
32
+
33
+ def to_xcard()
34
+ make_xcard @to_xml
35
+ end
36
+
37
+
38
+ private
39
+
40
+ def extract_names(name)
41
+
42
+ a = name.split
43
+
44
+ if a.length == 2 then
45
+
46
+ firstname, surname = a[0],nil,a[-1], name
47
+
48
+ elsif a[0][/^Mrs?|Ms|Miss|Dr/] then
49
+
50
+ prefix = a.shift
51
+
52
+ if a.length == 2 then
53
+ firstname, surname = a[0],nil,a[-1], name
54
+ else
55
+ [*a, a.join(' ')]
56
+ end
57
+
58
+ else
59
+ [*a, a.join(' ')]
60
+ end
61
+ end
62
+
63
+ def make_vcard(h)
64
+
65
+ card = Vpim::Vcard::Maker.make2 do |maker|
66
+
67
+ def maker.add(field_name, value, params={})
68
+
69
+ field = Vpim::DirectoryInfo::Field.create field_name, value, params
70
+ add_field field
71
+
72
+ end
73
+
74
+ prefix = h[:prefix]
75
+ suffix = h[:suffix]
76
+
77
+ firstname, middlename, surname, fullname = extract_names(h[:name])
78
+
79
+ maker.add_name do |name|
80
+ name.prefix = prefix if prefix
81
+ name.given = firstname
82
+ name.family = surname
83
+ name.suffix = suffix if suffix
84
+ name.fullname = fullname if fullname
85
+ end
86
+
87
+ # -- email -----------------------------
88
+
89
+ e = h[:email]
90
+
91
+ if e then
92
+
93
+ if e.is_a? String then
94
+ maker.add_email e
95
+ else
96
+ eh = h[:email][:home]
97
+ ew = h[:email][:work]
98
+ maker.add_email(ew) { |e| e.location = 'work' } if ew
99
+ maker.add_email(eh) { |e| e.location = 'home' } if eh
100
+ end
101
+ end
102
+
103
+ # -- urls ---------------------------------
104
+
105
+ h[:url] ||= h[:urls]
106
+
107
+ if h[:url] then
108
+
109
+ if h[:url].is_a? String then
110
+ maker.add_url h[:url]
111
+ else
112
+
113
+ # unfortunately vPim doesn't use a block with the add_url method
114
+ #maker.add_url (h[:url][:work]){|e| e.location = 'work'} if h[:url][:work]
115
+
116
+ h[:url][:items].each {|url| maker.add_url url }
117
+
118
+ end
119
+
120
+ end
121
+
122
+ # -- photos
123
+
124
+ maker.add_photo {|photo| photo.link = h[:photo] } if h[:photo]
125
+
126
+ # -- telephone
127
+
128
+ tel = h[:tel]
129
+
130
+ if tel then
131
+
132
+ if tel.is_a? String then
133
+
134
+ maker.add_tel tel
135
+
136
+ else
137
+ th = h[:tel][:home]
138
+ tw = h[:tel][:work]
139
+ maker.add_tel(tw) { |e| e.location = 'work' } if tw
140
+ maker.add_tel(th) { |e| e.location = 'home' } if th
141
+ end
142
+ end
143
+
144
+ # -- categories ------------
145
+ maker.add 'CATEGORIES', h[:categories].split(/\s*,\s*/) if h[:categories]
146
+
147
+ # -- source ------------
148
+ maker.add 'SOURCE', h[:source] if h[:source]
149
+
150
+ # -- Twitter ------------
151
+ maker.add 'X-TWITTER', h[:twitter] if h[:twitter]
152
+
153
+ # -- XMPP
154
+ xmpp = h[:jabber] || h[:xmpp]
155
+ maker.add 'X-JABBER', xmpp, 'TYPE' => 'im' if xmpp
156
+
157
+ end
158
+ end
159
+
160
+ def make_hcard(raw_s, h)
161
+
162
+ raw_s ||= %q(
163
+ # hcard
164
+
165
+ img.photo
166
+ h1.fn
167
+ .email
168
+ .n
169
+
170
+ home:
171
+ .label
172
+ .adr
173
+ .tel
174
+
175
+ work:
176
+ .label
177
+ .adr
178
+ .tel
179
+ )
180
+
181
+ s = raw_s.split(/\n(?=\w+:?)/).inject('') do |r, x|
182
+
183
+ x.sub!(/^\s*#\s+.*/,'') # ignore comments
184
+
185
+ lines = x.lines
186
+ type = lines[0][/^(\w+):/,1]
187
+
188
+ if type then
189
+
190
+ lines.shift
191
+
192
+ r << lines.map do |line|
193
+
194
+ if line[/\s*\.\w+/] then
195
+ indent = line[/^ +/].to_s
196
+ "%s%sspan.type %s" % [line.sub(/^ {2}/,''), indent, type]
197
+ else
198
+ line
199
+ end
200
+
201
+ end.join("\n") + "\n"
202
+
203
+ else
204
+
205
+ r << x + "\n"
206
+ end
207
+
208
+ r
209
+
210
+ end
211
+
212
+ html_string = Hlt.new(s).to_html
213
+ html_template = <<EOF
214
+ <html>
215
+ <head>
216
+ <link rel="profile" href="http://microformats.org/profile/hcard" />
217
+ </head>
218
+ <body>
219
+ <div class='vcard'>#{html_string}</div>
220
+ </body>
221
+ </html>
222
+ EOF
223
+ doc = Rexle.new(html_template)
224
+
225
+ def doc.set(selector, val=nil)
226
+
227
+ e = self.at_css selector
228
+ return unless e
229
+ block_given? ? yield(e) : e.text = val
230
+
231
+ end
232
+
233
+ firstname, middlename, surname, fullname = extract_names(h[:name])
234
+ doc.set '.fn', fullname
235
+
236
+ #-- name ---------
237
+
238
+ e = doc.at_css '.n'
239
+ e.text = 'First Name:'
240
+ fname = Rexle::Element.new('span')
241
+ fname.attributes[:class] = 'given-name'
242
+ fname.text = firstname
243
+ e.add_element fname
244
+ e.add_element Rexle::Element.new('br')
245
+ e.add_text 'Last Name:'
246
+ lname = Rexle::Element.new('span')
247
+ lname.attributes[:class] = 'family-name'
248
+ lname.text = surname
249
+ e.add_element lname
250
+
251
+ doc.at_css('.photo').delete unless h[:photo]
252
+ doc.css('.tel').each(&:delete) unless h[:tel]
253
+ doc.css('.adr').each(&:delete) unless h[:adr]
254
+ doc.css('.label').each(&:delete) unless h[:label]
255
+
256
+ if h[:email].is_a? String then
257
+ e = doc.at_css '.email'
258
+ e.text = 'Email:'
259
+ alink = Rexle::Element.new('a')
260
+ alink.attributes[:class] = 'value'
261
+ alink.attributes[:href] = 'mailto:' + h[:email]
262
+ alink.text = h[:email]
263
+ e.add_element alink
264
+ end
265
+ [doc, h]
266
+
267
+ end
268
+
269
+ def make_xcard(xml)
270
+ lib = 'http://rorbuilder.info/r/ruby/simplevpim'
271
+ xsl = open(lib + '/xcard.xsl','UserAgent' => 'SimplevPim').read
272
+ doc = Nokogiri::XML(xml)
273
+ xslt = Nokogiri::XSLT(xsl)
274
+ xslt.transform(doc).to_s
275
+ end
276
+
277
+ def vcard_xml(h)
278
+
279
+ prefix = h[:prefix]
280
+ suffix = h[:suffix]
281
+
282
+ firstname, middlename, surname, fullname = extract_names(h[:name])
283
+
284
+ xml = RexleBuilder.new
285
+
286
+ a = xml.vcard do
287
+
288
+ xml.name do
289
+
290
+ xml.prefix prefix if prefix
291
+ xml.given firstname
292
+ xml.family surname
293
+ xml.suffix suffix if suffix
294
+ xml.fullname fullname if fullname
295
+ end
296
+
297
+ # -- email -----------------------------
298
+
299
+ e = h[:email]
300
+
301
+ if e then
302
+
303
+ if e.is_a? String then
304
+
305
+ xml.email e
306
+
307
+ else
308
+ eh = h[:email][:home]
309
+ ew = h[:email][:work]
310
+ xml.email({location: 'work'}, ew) if ew
311
+ xml.email({location: 'home'}, eh) if eh
312
+ end
313
+ end
314
+
315
+ # -- urls ---------------------------------
316
+
317
+ h[:url] ||= h[:urls]
318
+
319
+ if h[:url] then
320
+
321
+ if h[:url].is_a? String then
322
+ xml.url h[:url]
323
+ else
324
+
325
+ # unfortunately vPim doesn't use a block with the add_url method
326
+ #maker.add_url (h[:url][:work]){|e| e.location = 'work'} if h[:url][:work]
327
+
328
+ h[:url][:items].each {|url| xml.url url }
329
+
330
+ end
331
+
332
+ end
333
+
334
+ # -- photos
335
+
336
+ xml.photo link: h[:photo] if h[:photo]
337
+
338
+ # -- telephone
339
+
340
+ tel = h[:tel]
341
+
342
+ if tel then
343
+
344
+ if tel.is_a? String then
345
+
346
+ xml.tel tel
347
+
348
+ else
349
+ th = h[:tel][:home]
350
+ tw = h[:tel][:work]
351
+ xml.tel({location: 'work'}, tw) if tw
352
+ xml.tel({location: 'home'}, th) if th
353
+ end
354
+ end
355
+
356
+ # -- categories ------------
357
+ xml.categories h[:categories].split(/\s*,\s*/) if h[:categories]
358
+
359
+ # -- source ------------
360
+ xml.source h[:source] if h[:source]
361
+
362
+ # -- Twitter ------------
363
+ xml.x_twitter h[:twitter] if h[:twitter]
364
+
365
+ # -- XMPP
366
+ xmpp = h[:jabber] || h[:xmpp]
367
+ xml.x_jabber({type: 'im'}, xmpp) if xmpp
368
+
369
+ end
370
+
371
+ Rexle.new(a)
372
+ end
373
+
374
+ end
@@ -0,0 +1,49 @@
1
+ <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
2
+ <xsl:output method='xml' indent='yes'/>
3
+
4
+
5
+ <xsl:template match='vcard'>
6
+ <xsl:element name='vcards'>
7
+ <xsl:attribute name='xmlns'>urn:ietf:params:xml:ns:vcard-4.0</xsl:attribute>
8
+ <xsl:element name='vcard'>
9
+
10
+ <xsl:apply-templates select='name' />
11
+ <xsl:apply-templates select='email' />
12
+ </xsl:element>
13
+ </xsl:element>
14
+
15
+ </xsl:template>
16
+
17
+ <xsl:template match='name'>
18
+ <xsl:element name='fn'>
19
+ <xsl:element name='text'><xsl:value-of select='fullname'/></xsl:element></xsl:element>
20
+ <xsl:element name='n'>
21
+ <xsl:element name="surname"><xsl:value-of select='family' /></xsl:element>
22
+ <xsl:element name="given"><xsl:value-of select='given' /></xsl:element>
23
+ <xsl:element name="additional"><xsl:value-of select='middlename' /></xsl:element>
24
+ <xsl:element name="prefix"><xsl:value-of select='prefix' /></xsl:element>
25
+ <xsl:element name="suffix"><xsl:value-of select='suffix' /></xsl:element>
26
+ </xsl:element>
27
+
28
+ </xsl:template>
29
+
30
+
31
+ <xsl:template match='email'>
32
+
33
+ <xsl:element name='email'>
34
+ <xsl:element name="parameters">
35
+ <xsl:element name='type'>
36
+ <xsl:element name='text'>
37
+ <xsl:value-of select='@location'/>
38
+ </xsl:element>
39
+ </xsl:element>
40
+ </xsl:element>
41
+ <xsl:element name='text'>
42
+ <xsl:value-of select='.' />
43
+ </xsl:element>
44
+
45
+ </xsl:element>
46
+
47
+ </xsl:template>
48
+
49
+ </xsl:stylesheet>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simplevpim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -31,7 +31,7 @@ cert_chain:
31
31
  h7sjjIWKCtgcFF+5Gf5AtJf6C0PlDSh7mc8uoo2XSef/GV6YvwUrQbPtFakM7LDs
32
32
  a3f37q6Z/UCE6w==
33
33
  -----END CERTIFICATE-----
34
- date: 2014-11-10 00:00:00.000000000 Z
34
+ date: 2014-11-22 00:00:00.000000000 Z
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: simple-config
@@ -113,6 +113,26 @@ dependencies:
113
113
  - - ">="
114
114
  - !ruby/object:Gem::Version
115
115
  version: 1.6.2.1
116
+ - !ruby/object:Gem::Dependency
117
+ name: hlt
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '0.3'
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: 0.3.2
126
+ type: :runtime
127
+ prerelease: false
128
+ version_requirements: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: '0.3'
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: 0.3.2
116
136
  description:
117
137
  email: james@r0bertson.co.uk
118
138
  executables: []
@@ -120,6 +140,8 @@ extensions: []
120
140
  extra_rdoc_files: []
121
141
  files:
122
142
  - lib/simplevpim.rb
143
+ - lib/simplevpim.rb~
144
+ - lib/xdata.xsl
123
145
  homepage: https://github.com/jrobertson/simplevpim
124
146
  licenses:
125
147
  - MIT
metadata.gz.sig CHANGED
Binary file