kvx 0.9.11 → 1.0.0

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