kvx 0.9.9 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/kvx.rb +200 -137
  4. data.tar.gz.sig +0 -0
  5. metadata +11 -10
  6. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15f341e0536edd706c0b9fcaef3f72644aa71ddada69de76d4a79d223b9b5ec6
4
- data.tar.gz: 7bd3ba8db13f0dfa1369d4694fc4ef5d6e7159b9494ef1cb7c792b6a2a1c9d0b
3
+ metadata.gz: 208bf787222760936ba3417f92f4fe08ce9ed20266f086752f883b6ea7059402
4
+ data.tar.gz: 9d884980abc91dea4943ded6d77d6eb3a430a0ad9689cb4eff23b453ae6b4946
5
5
  SHA512:
6
- metadata.gz: a57d322f8186ea30dbe81b657192dee6729d6dce7026f8ca96fef38199dcff3bf7158c122aa9a8181759360b50d4813a5a62a5cdb81767e4f81566a0ae495f0f
7
- data.tar.gz: 7058b1386cd2045b6871848c8ae140ebe498cc50e7c8c356a5f6d003f3e74d9334533d727ec595cfebfe769c673c4da5cd5fda555d89ae2147918b5777bbd53e
6
+ metadata.gz: 9709a0f035f13ca6b16782ce3b8c57f23fdbf53ce893ef827ca34bec6c0d14499d2093a4871b7f18b81204d506281674b4d9f1b513aff080087a212b4b49c436
7
+ data.tar.gz: 5349dc1b0f3025838a7f9b890730e1bbf91838571038fed6f1b880e97101aa4b4b0e0219f48436432e5e769f4b044efa7b082c00aeb9cff0a84e80f6950479ef
checksums.yaml.gz.sig CHANGED
Binary file
data/lib/kvx.rb CHANGED
@@ -16,7 +16,7 @@ hkey_gems
16
16
  require kvx
17
17
  class Kvx
18
18
  media_type kvx
19
- '
19
+ '
20
20
  end
21
21
  end
22
22
 
@@ -40,19 +40,19 @@ class Kvx
40
40
  @identifier = 'kvx'
41
41
  @summary = {}
42
42
  @ignore_blank_lines ||= false
43
-
43
+
44
44
  @attributes, @debug = attributes, debug
45
-
45
+
46
46
  h = {
47
- hash: :passthru,
48
- :'rexle::element' => :xml_to_h,
47
+ hash: :passthru,
48
+ :'rexle::element' => :xml_to_h,
49
49
  string: :parse_string,
50
50
  rexle: :doc_to_h,
51
51
  :"rexle::element::value" => :parse_string
52
52
  }
53
-
53
+
54
54
  if x then
55
-
55
+
56
56
  sym = h[x.class.to_s.downcase.to_sym]
57
57
  puts 'sym: ' + sym.inspect if @debug
58
58
  @body = method(sym).call x
@@ -60,132 +60,188 @@ class Kvx
60
60
  end
61
61
 
62
62
  end
63
-
63
+
64
64
  def import(s)
65
65
  @body = parse_string(s)
66
66
  methodize(@body)
67
67
  end
68
-
68
+
69
69
  def item()
70
70
  @body
71
71
  end
72
-
73
- alias body item
74
-
72
+
73
+ alias body item
74
+
75
75
  def save(filename)
76
76
  FileX.write filename, self.to_s
77
77
  end
78
-
79
- # flattening is helpful when passing the Hash object to
78
+
79
+ # flattening is helpful when passing the Hash object to
80
80
  # RecordX as a new record
81
81
  #
82
82
  def to_h(flatten: false)
83
-
83
+
84
84
  if @summary.empty? then
85
-
85
+
86
86
  deep_clone @body
87
-
87
+
88
88
  else
89
-
89
+
90
90
  if flatten then
91
91
  @summary.merge @body
92
92
  else
93
93
  {summary: deep_clone(@summary), body: deep_clone(@body)}
94
94
  end
95
-
95
+
96
96
  end
97
-
97
+
98
98
  end
99
-
99
+
100
100
  def to_doc()
101
-
101
+
102
102
  a = if @summary.empty? then
103
-
104
- [self.class.to_s.downcase, @attributes, '', *make_xml(@body)]
105
-
103
+
104
+ [self.class.to_s.downcase, @attributes, '', *make_xml(@body)]
105
+
106
106
  else
107
-
107
+
108
108
  summary = make_xml(@summary)
109
-
109
+
110
110
  tags_found = summary.assoc(:tags)
111
-
111
+
112
112
  if tags_found then
113
113
  tags = tags_found.pop
114
- tags_found.push *tags.split.map {|x| [:tag,{},x]}
114
+ tags_found.push *tags.split.map {|x| [:tag,{},x]}
115
115
  end
116
116
 
117
117
  summary = [:summary, {}, *summary]
118
-
118
+
119
119
  # -- use the nested description Hash object if there are multiple lines
120
120
  h = {}
121
-
121
+
122
122
  @body.each do |key, value|
123
-
123
+
124
124
  h[key] = value.is_a?(String) ? value : value[:description]
125
-
125
+
126
126
  end
127
-
127
+
128
128
  body = [:body, {}, *make_xml(h)]
129
- [self.class.to_s.downcase, @attributes, '', summary, body]
130
-
131
- end
132
-
129
+ [self.class.to_s.downcase, @attributes, '', summary, body]
130
+
131
+ end
132
+
133
133
  puts 'a: ' + a.inspect if @debug
134
134
  doc = Rexle.new a
135
135
  doc.instructions = @instructions || []
136
136
  doc
137
-
137
+
138
138
  end
139
-
139
+
140
140
  def to_s()
141
-
141
+
142
142
  header = ''
143
-
143
+
144
144
  if @header or (@summary and @summary.any?) then
145
-
145
+
146
146
  attr = @attributes ? ' ' + @attributes\
147
147
  .map {|x| "%s='%s'" % x }.join(' ') : ''
148
148
  header = '<?' + @identifier
149
149
  header += attr
150
150
  header += "?>\n"
151
-
151
+
152
152
  if @summary and @summary.any? then
153
153
  header += scan_to_s @summary
154
154
  header += "\n----------------------------------\n\n"
155
155
  end
156
-
156
+
157
157
  end
158
158
 
159
159
  # -- use the nested description Hash object if there are multiple lines
160
160
  h = {}
161
-
161
+
162
162
  @body.each do |key, value|
163
-
163
+
164
164
  h[key] = if value.is_a?(String) then
165
-
165
+
166
166
  if value.lines.length < 2 then
167
- value
167
+ value
168
168
  else
169
- "\n" + value.lines.map {|x| ' ' + x }.join
169
+ "\n" + value.lines.map {|x| ' ' + x }.join
170
170
  end
171
-
171
+
172
172
  else
173
173
  "\n" + value[:description].lines.map {|x| ' ' + x }.join
174
174
  end
175
-
176
- end
177
-
175
+
176
+ end
177
+
178
178
  header + scan_to_s(h)
179
179
 
180
- end
180
+ end
181
181
 
182
182
  def to_xml(options={pretty: true})
183
-
183
+
184
184
  doc = self.to_doc
185
185
  doc.xml(options)
186
186
 
187
187
  end
188
-
188
+
189
+ def to_xslt()
190
+
191
+ summary = self.summary.keys.map do |key|
192
+ " <xsl:element name='#{key}'><xsl:value-of select='#{key}' /></xsl:element>"
193
+ end.join("\n")
194
+
195
+ body = self.body.keys.map do |key|
196
+ " <xsl:element name='#{key}'><xsl:value-of select='#{key}' /></xsl:element>"
197
+ end.join("\n")
198
+
199
+ s = "
200
+ <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
201
+
202
+ <xsl:template match='kvx'>
203
+
204
+ <xsl:element name='kvx'>
205
+
206
+ <xsl:attribute name='created'>
207
+ <xsl:value-of select='@created'/>
208
+ </xsl:attribute>
209
+ <xsl:attribute name='last_modified'>
210
+ <xsl:value-of select='@last_modified'/>
211
+ </xsl:attribute>
212
+
213
+ <xsl:apply-templates select='summary' />
214
+ <xsl:apply-templates select='body' />
215
+
216
+ </xsl:element>
217
+
218
+ </xsl:template>
219
+
220
+ <xsl:template match='summary'>
221
+
222
+ <xsl:element name='summary'>
223
+
224
+ #{summary}
225
+
226
+ </xsl:element>
227
+
228
+ </xsl:template>
229
+
230
+ <xsl:template match='body'>
231
+
232
+ <xsl:element name='body'>
233
+
234
+ #{body}
235
+
236
+ </xsl:element>
237
+
238
+ </xsl:template>
239
+
240
+ </xsl:stylesheet>
241
+ "
242
+
243
+ end
244
+
189
245
  # used by RecordX to update a KVX record
190
246
  # id is unnecssary because there is only 1 record mapped to RecordX
191
247
  #
@@ -194,9 +250,9 @@ class Kvx
194
250
  end
195
251
 
196
252
  private
197
-
253
+
198
254
  def deep_clone(h)
199
-
255
+
200
256
  h.inject({}) do |r, x|
201
257
 
202
258
  h2 = if x.last.is_a? Hash then
@@ -206,31 +262,31 @@ class Kvx
206
262
  end
207
263
  r.merge h2[0] => h2[1]
208
264
  end
209
-
210
- end
211
-
265
+
266
+ end
267
+
212
268
  def doc_to_h(doc)
213
269
  xml_to_h(doc.root)
214
270
  end
215
271
 
216
272
  def get_attributes(raw_attributes)
217
- #
273
+ #
218
274
  r1 = /([\w\-:]+\='[^']*)'/
219
275
  r2 = /([\w\-:]+\="[^"]*)"/
220
-
276
+
221
277
  r = raw_attributes.scan(/#{r1}|#{r2}/).map(&:compact)\
222
278
  .flatten.inject(Attributes.new) do |r, x|
223
- attr_name, raw_val = x.split(/=/,2)
279
+ attr_name, raw_val = x.split(/=/,2)
224
280
  val = attr_name != 'class' ? raw_val[1..-1] : raw_val[1..-1].split
225
281
  r.merge(attr_name.to_sym => val)
226
282
  end
227
283
 
228
284
  return r
229
285
  end
230
-
286
+
231
287
  def hashify(e)
232
288
 
233
- v = if e.has_elements? then
289
+ v = if e.has_elements? then
234
290
  e.elements.inject({}) do |r, x|
235
291
  r.merge hashify(x)
236
292
  end
@@ -239,22 +295,22 @@ class Kvx
239
295
  end
240
296
 
241
297
  {e.name.to_sym => v}
242
- end
298
+ end
243
299
 
244
300
  def make_xml(h)
245
-
301
+
246
302
  puts 'inside make_xml: ' + h.inspect if @debug
247
303
  h2 = h.clone
248
304
  h2.each {|key,value| value.delete :items if value.is_a?(Hash) }
249
305
 
250
306
  RexleBuilder.new(h2, debug: false).to_a[3..-1]
251
307
  end
252
-
308
+
253
309
  def parse_string(s)
254
-
310
+
255
311
  buffer, type = RXFHelper.read(s)
256
312
  puts ('buffer: ' + buffer.inspect).debug if @debug
257
-
313
+
258
314
  if buffer.lstrip =~ /^<\?xml/ then
259
315
  doc = Rexle.new(buffer)
260
316
  @instructions = doc.instructions
@@ -263,75 +319,81 @@ class Kvx
263
319
  else
264
320
  parse_to_h(buffer)
265
321
  end
266
-
322
+
267
323
  end
268
-
324
+
269
325
  def methodize(h)
270
-
326
+
271
327
  h.each do |k,v|
328
+
272
329
  define_singleton_method(k){v} unless self.methods.include? k
273
- end
274
-
330
+
331
+ unless self.methods.include? (k.to_s + '=').to_sym then
332
+ define_singleton_method((k.to_s + '=').to_sym){|x| h[k] = x}
333
+ end
334
+
335
+ end
336
+
275
337
  end
276
338
 
277
339
  def parse_to_h(s, header_pattern: %r(^<\?kvx[\s\?]))
278
340
 
279
341
  raw_txt, _ = RXFHelper.read(s)
280
342
 
281
- # does the raw_txt contain header information?
343
+ # does the raw_txt contain header information?
282
344
  a = s.strip.lines
283
345
 
284
346
  txt = if a[0] =~ header_pattern then
285
-
347
+
286
348
  raw_header = a.shift
287
349
  attr = get_attributes(raw_header)
288
-
350
+
289
351
  if attr[:created] then
290
352
  attr[:last_modified] = Time.now.to_s
291
353
  else
292
- attr[:created] = Time.now.to_s
354
+ attr[:created] = Time.now.to_s
293
355
  end
294
-
356
+
295
357
  @attributes.merge! attr
296
358
  @header = true
297
- body, summary = a.join.strip.split(/^----*$/).reverse
359
+ body, summary = a.join.strip.split(/^----*$/).reverse
298
360
  @summary = scan_to_h summary if summary
299
-
361
+
300
362
  body
301
363
  else
302
364
  raw_txt
303
365
  end
304
-
366
+
305
367
  scan_to_h(txt)
306
368
  end
307
369
 
308
370
  def passthru(x)
309
-
371
+
310
372
  if x[:summary] and x[:body]
311
373
  @summary = deep_clone x[:summary]
312
374
  deep_clone x[:body]
313
- else
375
+ else
314
376
  deep_clone x
315
377
  end
316
-
378
+
317
379
  end
318
-
380
+
319
381
  def pretty_print(a, indent='')
320
-
321
- a.map do |x|
382
+
383
+ a.map do |x|
322
384
  (x.is_a?(String) or x.nil?) ? x.to_s : pretty_print(x, indent + ' ')
323
385
  end.join("\n" + indent)
324
-
386
+
325
387
  end
326
-
327
-
388
+
389
+
328
390
  def scan_to_h(txt)
329
-
391
+
330
392
  txt.gsub!(/^\w+:(?=$)/,'\0 ')
331
393
  puts 'txt:' + txt.inspect if @debug
332
-
394
+
333
395
  # auto indent any multiline values which aren't already indented
334
-
396
+
335
397
  indent = ''
336
398
 
337
399
  lines = txt.gsub(/^-+$/m,'').lines.map do |line|
@@ -343,88 +405,89 @@ class Kvx
343
405
  line
344
406
  end
345
407
 
346
- end
408
+ end
347
409
  puts ('lines: ' + lines.inspect).debug if @debug
348
-
410
+
349
411
  puts ('inside scan_to_h').info if @debug
350
- raw_a = LineTree.new(lines.join.gsub(/(^-*$)|(?<=\S) +#.*/,'').strip,
412
+ raw_a = LineTree.new(lines.join.gsub(/(^-*$)|(?<=\S) +#.*/,'').strip,
351
413
  ignore_blank_lines: @ignore_blank_lines).to_a
352
414
  puts ('raw_a: ' + raw_a.inspect).debug if @debug
353
-
354
- # if there are any orphan lines which aren't nested underneath a
415
+
416
+ # if there are any orphan lines which aren't nested underneath a
355
417
  # label, they will be fixed using the following statement
356
-
418
+
357
419
  a = raw_a.chunk {|x| x[0][/^[^:]+:/]}.inject([]) do |r,y|
358
-
420
+
421
+
359
422
  puts 'r: ' + r.inspect if @debug
360
-
423
+
361
424
  if r.last and !y.first[/[^:]+:/] then
362
425
  r.last << y.last[-1]
363
426
  else
364
427
  puts 'y: ' + y.inspect if @debug
365
428
  r << y.last[-1]
366
429
  end
367
-
430
+
368
431
  r
369
-
432
+
370
433
  end
371
434
 
372
435
  @body = a.inject({}) do |r, line|
373
-
436
+
374
437
  s = line.shift
375
438
  puts ('s: ' + s.inspect).debug if @debug
376
-
439
+
377
440
  if line.join.length > 0 then
378
-
441
+
379
442
  puts 'line: ' + line.inspect if @debug
380
-
381
- padding = line[0].length < 2 ? "\n" : "\n "
443
+
444
+ padding = line[0].length < 2 ? "\n" : "\n "
382
445
  s10 = line.map{|x| x.join(padding)}.join("\n")
383
-
384
- r2 = if s10[/^[^:]+:[\n ]/] then
385
-
446
+
447
+ r2 = if s10[/^ *\w+:[\n ]/] then
448
+
386
449
  scan_to_h(s10)
387
-
450
+
388
451
  else
389
452
 
390
- desc = pretty_print(line).split(/\n(?=\w+: )/)
453
+ desc = pretty_print(line).split(/\n(?=\w+: )/)
391
454
 
392
455
  txt2, remaining = desc
393
456
 
394
- h = txt2.lines.inject([]) do |r, x|
457
+ h = txt2.lines.inject([]) do |r, x|
395
458
  x.chomp!
396
459
  x.length > 0 ? r << x : r
397
460
  end
398
-
461
+
399
462
  r3 = {description: txt2, items: h}
400
463
 
401
464
  if remaining then
402
465
  r3.merge!(scan_to_h remaining + "\n ")
403
466
  end
404
-
467
+
405
468
  r3
406
469
  end
407
470
 
408
471
  r.merge({s[/[^:]+/].to_sym => r2})
409
-
472
+
410
473
  else
411
-
474
+
412
475
  value, name = s.split(/: */,2).reverse
413
- name ||= 'description'
476
+ name ||= 'description'
414
477
  v = value =~ /^\{\s*\}$/ ? {} : value.to_s
415
-
478
+
416
479
  r.merge({name.to_sym => v})
417
- end
480
+ end
418
481
 
419
482
  end
420
-
483
+
421
484
  puts ('@body: ' + @body.inspect).debug if @debug
422
485
  @body
423
486
 
424
- end
425
-
426
- def scan_to_s(h, indent='')
427
-
487
+ end
488
+
489
+ def scan_to_s(h, indent='')
490
+
428
491
  a = h.inject([]) do |r, x|
429
492
  if x.last.is_a? Hash then
430
493
  r << x.first.to_s + ":\n" + scan_to_s(x.last, ' ')
@@ -432,27 +495,27 @@ class Kvx
432
495
  r << "%s%s: %s" % [indent, *x]
433
496
  end
434
497
  end
435
-
498
+
436
499
  @to_s = a.join("\n")
437
500
  end
438
-
501
+
439
502
  def xml_to_h(node)
440
-
503
+
441
504
  puts 'node: ' + node.xml.inspect if @debug
442
505
  @attributes = node.attributes.to_h
443
-
506
+
444
507
  summary = node.element('summary')
445
-
508
+
446
509
  if summary then
447
510
 
448
511
  etags = summary.element 'tags'
449
-
512
+
450
513
  if etags then
451
514
 
452
515
  tags = etags.xpath('tag/text()')
453
516
  etags.delete 'tag'
454
517
  etags.text = tags.join(' ') if tags.any?
455
-
518
+
456
519
  end
457
520
 
458
521
  @summary = hashify(summary)[:summary]
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kvx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.9
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -35,7 +35,7 @@ cert_chain:
35
35
  m/+jxdgFjKKGxeZqunu9cp5ca9wSjjtKh/VA/3xZtPwokCa7vCMB+ZxUP0jvd++u
36
36
  OTXy8k/zqddw/VfD/It1UUK4
37
37
  -----END CERTIFICATE-----
38
- date: 2021-06-05 00:00:00.000000000 Z
38
+ date: 2022-01-03 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: line-tree
@@ -46,7 +46,7 @@ dependencies:
46
46
  version: '0.9'
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 0.9.1
49
+ version: 0.9.3
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
@@ -56,29 +56,29 @@ dependencies:
56
56
  version: '0.9'
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 0.9.1
59
+ version: 0.9.3
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: rxfhelper
62
62
  requirement: !ruby/object:Gem::Requirement
63
63
  requirements:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
- version: '1.0'
66
+ version: '1.1'
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 1.0.0
69
+ version: 1.1.3
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: '1.0'
76
+ version: '1.1'
77
77
  - - ">="
78
78
  - !ruby/object:Gem::Version
79
- version: 1.0.0
79
+ version: 1.1.3
80
80
  description:
81
- email: james@jamesrobertson.eu
81
+ email: digital.robertson@gmail.com
82
82
  executables: []
83
83
  extensions: []
84
84
  extra_rdoc_files: []
@@ -103,7 +103,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
103
  - !ruby/object:Gem::Version
104
104
  version: '0'
105
105
  requirements: []
106
- rubygems_version: 3.1.2
106
+ rubyforge_project:
107
+ rubygems_version: 2.7.10
107
108
  signing_key:
108
109
  specification_version: 4
109
110
  summary: Kvx (Keys, Values, and XML) makes it convenient to store and retrieve the
metadata.gz.sig CHANGED
Binary file