kvx 0.9.9 → 1.0.1

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 +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