kvx 0.9.11 → 1.0.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.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/kvx.rb +192 -136
  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: 9fe4f150a49ff2f1c88b0cf28b7d24cbd04af9fc64cf7ea697fe0e29ab62a67b
4
- data.tar.gz: c2ead702dcf44db16cb10a1866051ceb85d947870f491276c610acff2bf2c5be
3
+ metadata.gz: b7d5de64957cdd3c219a4038db563dc40d2a4491d88f2c9dcf770d6e509a499a
4
+ data.tar.gz: e097440702f891917b7cf2d2e7fd08643509d93862e0547b2db47e23fa420030
5
5
  SHA512:
6
- metadata.gz: abf623624bb8630caa32c5d1893013351e3ec328e188bca05343b51286376387c70006cc70ac265958e4b376b299bacf6578c9dab46113c8f36d98d1ae1422f1
7
- data.tar.gz: 83e9dcbff011d65f72408f1b7b9ab681599eba0057e2ee3bc8b5e78a94a08afbb5b29e01214a08c7e0ee22847c4214398a826c4cd2183c24fae6142285731761
6
+ metadata.gz: c9fbcec52757af9fdbed34f0a25e2cef448634a0bd1dd9576266ed3e24d8d419a0eea28bc7bc650b76245aa4c3580cc7441b93fddbe1973afa117dffd7bacf73
7
+ data.tar.gz: 4ca00225ba83c2f51e3d49d4860a2489b7b5e7bb5bd5b2a8f9559de5a8c4dbf75f6471216bf4c43f2f5ad1a94147dcddcd020f401c8d8e48d99ea5492ae708c4
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,75 @@ 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|
272
328
  define_singleton_method(k){v} unless self.methods.include? k
273
- end
274
-
329
+ end
330
+
275
331
  end
276
332
 
277
333
  def parse_to_h(s, header_pattern: %r(^<\?kvx[\s\?]))
278
334
 
279
335
  raw_txt, _ = RXFHelper.read(s)
280
336
 
281
- # does the raw_txt contain header information?
337
+ # does the raw_txt contain header information?
282
338
  a = s.strip.lines
283
339
 
284
340
  txt = if a[0] =~ header_pattern then
285
-
341
+
286
342
  raw_header = a.shift
287
343
  attr = get_attributes(raw_header)
288
-
344
+
289
345
  if attr[:created] then
290
346
  attr[:last_modified] = Time.now.to_s
291
347
  else
292
- attr[:created] = Time.now.to_s
348
+ attr[:created] = Time.now.to_s
293
349
  end
294
-
350
+
295
351
  @attributes.merge! attr
296
352
  @header = true
297
- body, summary = a.join.strip.split(/^----*$/).reverse
353
+ body, summary = a.join.strip.split(/^----*$/).reverse
298
354
  @summary = scan_to_h summary if summary
299
-
355
+
300
356
  body
301
357
  else
302
358
  raw_txt
303
359
  end
304
-
360
+
305
361
  scan_to_h(txt)
306
362
  end
307
363
 
308
364
  def passthru(x)
309
-
365
+
310
366
  if x[:summary] and x[:body]
311
367
  @summary = deep_clone x[:summary]
312
368
  deep_clone x[:body]
313
- else
369
+ else
314
370
  deep_clone x
315
371
  end
316
-
372
+
317
373
  end
318
-
374
+
319
375
  def pretty_print(a, indent='')
320
-
321
- a.map do |x|
376
+
377
+ a.map do |x|
322
378
  (x.is_a?(String) or x.nil?) ? x.to_s : pretty_print(x, indent + ' ')
323
379
  end.join("\n" + indent)
324
-
380
+
325
381
  end
326
-
327
-
382
+
383
+
328
384
  def scan_to_h(txt)
329
-
385
+
330
386
  txt.gsub!(/^\w+:(?=$)/,'\0 ')
331
387
  puts 'txt:' + txt.inspect if @debug
332
-
388
+
333
389
  # auto indent any multiline values which aren't already indented
334
-
390
+
335
391
  indent = ''
336
392
 
337
393
  lines = txt.gsub(/^-+$/m,'').lines.map do |line|
@@ -343,89 +399,89 @@ class Kvx
343
399
  line
344
400
  end
345
401
 
346
- end
402
+ end
347
403
  puts ('lines: ' + lines.inspect).debug if @debug
348
-
404
+
349
405
  puts ('inside scan_to_h').info if @debug
350
- raw_a = LineTree.new(lines.join.gsub(/(^-*$)|(?<=\S) +#.*/,'').strip,
406
+ raw_a = LineTree.new(lines.join.gsub(/(^-*$)|(?<=\S) +#.*/,'').strip,
351
407
  ignore_blank_lines: @ignore_blank_lines).to_a
352
408
  puts ('raw_a: ' + raw_a.inspect).debug if @debug
353
-
354
- # if there are any orphan lines which aren't nested underneath a
409
+
410
+ # if there are any orphan lines which aren't nested underneath a
355
411
  # label, they will be fixed using the following statement
356
-
412
+
357
413
  a = raw_a.chunk {|x| x[0][/^[^:]+:/]}.inject([]) do |r,y|
358
414
 
359
-
415
+
360
416
  puts 'r: ' + r.inspect if @debug
361
-
417
+
362
418
  if r.last and !y.first[/[^:]+:/] then
363
419
  r.last << y.last[-1]
364
420
  else
365
421
  puts 'y: ' + y.inspect if @debug
366
422
  r << y.last[-1]
367
423
  end
368
-
424
+
369
425
  r
370
-
426
+
371
427
  end
372
428
 
373
429
  @body = a.inject({}) do |r, line|
374
-
430
+
375
431
  s = line.shift
376
432
  puts ('s: ' + s.inspect).debug if @debug
377
-
433
+
378
434
  if line.join.length > 0 then
379
-
435
+
380
436
  puts 'line: ' + line.inspect if @debug
381
-
382
- padding = line[0].length < 2 ? "\n" : "\n "
437
+
438
+ padding = line[0].length < 2 ? "\n" : "\n "
383
439
  s10 = line.map{|x| x.join(padding)}.join("\n")
384
-
440
+
385
441
  r2 = if s10[/^ *\w+:[\n ]/] then
386
-
442
+
387
443
  scan_to_h(s10)
388
-
444
+
389
445
  else
390
446
 
391
- desc = pretty_print(line).split(/\n(?=\w+: )/)
447
+ desc = pretty_print(line).split(/\n(?=\w+: )/)
392
448
 
393
449
  txt2, remaining = desc
394
450
 
395
- h = txt2.lines.inject([]) do |r, x|
451
+ h = txt2.lines.inject([]) do |r, x|
396
452
  x.chomp!
397
453
  x.length > 0 ? r << x : r
398
454
  end
399
-
455
+
400
456
  r3 = {description: txt2, items: h}
401
457
 
402
458
  if remaining then
403
459
  r3.merge!(scan_to_h remaining + "\n ")
404
460
  end
405
-
461
+
406
462
  r3
407
463
  end
408
464
 
409
465
  r.merge({s[/[^:]+/].to_sym => r2})
410
-
466
+
411
467
  else
412
-
468
+
413
469
  value, name = s.split(/: */,2).reverse
414
- name ||= 'description'
470
+ name ||= 'description'
415
471
  v = value =~ /^\{\s*\}$/ ? {} : value.to_s
416
-
472
+
417
473
  r.merge({name.to_sym => v})
418
- end
474
+ end
419
475
 
420
476
  end
421
-
477
+
422
478
  puts ('@body: ' + @body.inspect).debug if @debug
423
479
  @body
424
480
 
425
- end
426
-
427
- def scan_to_s(h, indent='')
428
-
481
+ end
482
+
483
+ def scan_to_s(h, indent='')
484
+
429
485
  a = h.inject([]) do |r, x|
430
486
  if x.last.is_a? Hash then
431
487
  r << x.first.to_s + ":\n" + scan_to_s(x.last, ' ')
@@ -433,27 +489,27 @@ class Kvx
433
489
  r << "%s%s: %s" % [indent, *x]
434
490
  end
435
491
  end
436
-
492
+
437
493
  @to_s = a.join("\n")
438
494
  end
439
-
495
+
440
496
  def xml_to_h(node)
441
-
497
+
442
498
  puts 'node: ' + node.xml.inspect if @debug
443
499
  @attributes = node.attributes.to_h
444
-
500
+
445
501
  summary = node.element('summary')
446
-
502
+
447
503
  if summary then
448
504
 
449
505
  etags = summary.element 'tags'
450
-
506
+
451
507
  if etags then
452
508
 
453
509
  tags = etags.xpath('tag/text()')
454
510
  etags.delete 'tag'
455
511
  etags.text = tags.join(' ') if tags.any?
456
-
512
+
457
513
  end
458
514
 
459
515
  @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.11
4
+ version: 1.0.0
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-06 00:00:00.000000000 Z
38
+ date: 2021-12-29 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