relaton-bib 1.2.4 → 1.5.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ubuntu.yml +1 -0
  3. data/.rubocop.yml +2 -2
  4. data/README.adoc +60 -18
  5. data/grammars/isodoc.rng +130 -21
  6. data/grammars/reqt.rng +2 -8
  7. data/lib/relaton_bib.rb +3 -5
  8. data/lib/relaton_bib/bib_item_locality.rb +13 -1
  9. data/lib/relaton_bib/biblio_note.rb +38 -0
  10. data/lib/relaton_bib/biblio_version.rb +12 -0
  11. data/lib/relaton_bib/bibliographic_date.rb +15 -1
  12. data/lib/relaton_bib/bibliographic_item.rb +134 -58
  13. data/lib/relaton_bib/bibtex_parser.rb +16 -15
  14. data/lib/relaton_bib/classification.rb +11 -0
  15. data/lib/relaton_bib/contribution_info.rb +41 -9
  16. data/lib/relaton_bib/contributor.rb +64 -6
  17. data/lib/relaton_bib/copyright_association.rb +21 -6
  18. data/lib/relaton_bib/document_identifier.rb +49 -9
  19. data/lib/relaton_bib/document_relation.rb +16 -6
  20. data/lib/relaton_bib/document_relation_collection.rb +12 -2
  21. data/lib/relaton_bib/document_status.rb +10 -0
  22. data/lib/relaton_bib/editorial_group.rb +14 -0
  23. data/lib/relaton_bib/formatted_ref.rb +7 -0
  24. data/lib/relaton_bib/formatted_string.rb +11 -0
  25. data/lib/relaton_bib/hash_converter.rb +39 -33
  26. data/lib/relaton_bib/hit.rb +10 -6
  27. data/lib/relaton_bib/hit_collection.rb +8 -3
  28. data/lib/relaton_bib/ics.rb +11 -0
  29. data/lib/relaton_bib/localized_string.rb +23 -6
  30. data/lib/relaton_bib/medium.rb +11 -0
  31. data/lib/relaton_bib/organization.rb +49 -18
  32. data/lib/relaton_bib/person.rb +76 -17
  33. data/lib/relaton_bib/place.rb +14 -2
  34. data/lib/relaton_bib/series.rb +25 -4
  35. data/lib/relaton_bib/structured_identifier.rb +30 -0
  36. data/lib/relaton_bib/technical_committee.rb +11 -0
  37. data/lib/relaton_bib/typed_title_string.rb +80 -7
  38. data/lib/relaton_bib/typed_uri.rb +11 -0
  39. data/lib/relaton_bib/validity.rb +11 -0
  40. data/lib/relaton_bib/version.rb +1 -1
  41. data/lib/relaton_bib/workgroup.rb +10 -0
  42. data/lib/relaton_bib/xml_parser.rb +65 -41
  43. metadata +7 -7
@@ -1,3 +1,4 @@
1
+ require "forwardable"
1
2
  require "relaton_bib/version"
2
3
  require "relaton_bib/deep_dup"
3
4
  require "relaton_bib/bibliographic_item"
@@ -10,11 +11,9 @@ module RelatonBib
10
11
  class RequestError < StandardError; end
11
12
 
12
13
  class << self
13
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
14
-
15
14
  # @param date [String, Integer, Date]
16
15
  # @return [Date, NilClass]
17
- def parse_date(date)
16
+ def parse_date(date) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
18
17
  return date if date.is_a?(Date)
19
18
 
20
19
  sdate = date.to_s
@@ -30,14 +29,13 @@ module RelatonBib
30
29
  when /(?<date>\d{4})/ then Date.strptime $~[:date], "%Y" # 2012
31
30
  end
32
31
  end
33
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
34
32
  end
35
33
 
36
34
  private
37
35
 
38
36
  # @param array [Array]
39
37
  # @return [Array<String>, String]
40
- def single_element_array(array)
38
+ def single_element_array(array) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
41
39
  if array.size > 1
42
40
  array.map { |e| e.is_a?(String) ? e : e.to_hash }
43
41
  else
@@ -17,7 +17,7 @@ module RelatonBib
17
17
  type_ptrn = %r{section|clause|part|paragraph|chapter|page|whole|table|
18
18
  annex|figure|note|list|example|volume|issue|time|
19
19
  locality:[a-zA-Z0-9_]+}x
20
- unless type =~ type_ptrn
20
+ unless type.match? type_ptrn
21
21
  warn "[relaton-bib] WARNING: invalid locality type: #{type}"
22
22
  end
23
23
 
@@ -39,6 +39,18 @@ module RelatonBib
39
39
  hash["reference_to"] = reference_to if reference_to
40
40
  hash
41
41
  end
42
+
43
+ # @param prefix [String]
44
+ # @param count [Integeg] number of localities
45
+ # @return [String]
46
+ def to_asciibib(prefix = "", count = 1)
47
+ pref = prefix.empty? ? prefix : prefix + "."
48
+ out = count > 1 ? "#{prefix}::\n" : ""
49
+ out += "#{pref}type:: #{type}\n"
50
+ out += "#{pref}reference_from:: #{reference_from}\n"
51
+ out += "#{pref}reference_to:: #{reference_to}\n" if reference_to
52
+ out
53
+ end
42
54
  end
43
55
 
44
56
  class Locality < BibItemLocality
@@ -1,4 +1,31 @@
1
1
  module RelatonBib
2
+ class BiblioNoteCollection
3
+ extend Forwardable
4
+
5
+ def_delegators :@array, :[], :first, :last, :empty?, :any?, :size,
6
+ :each, :map, :detect, :length
7
+
8
+ def initialize(notes)
9
+ @array = notes
10
+ end
11
+
12
+ # @param bibnote [RelatonBib::BiblioNote]
13
+ # @return [self]
14
+ def <<(bibnote)
15
+ @array << bibnote
16
+ self
17
+ end
18
+
19
+ # @param opts [Hash]
20
+ # @option opts [Nokogiri::XML::Builder] XML builder
21
+ # @option opts [String] :lang language
22
+ def to_xml(**opts)
23
+ bnc = @array.select { |bn| bn.language&.include? opts[:lang] }
24
+ bnc = @array unless bnc.any?
25
+ bnc.each { |bn| bn.to_xml opts[:builder] }
26
+ end
27
+ end
28
+
2
29
  class BiblioNote < FormattedString
3
30
  # @return [String, NilClass]
4
31
  attr_reader :type
@@ -29,5 +56,16 @@ module RelatonBib
29
56
  hash["type"] = type
30
57
  hash
31
58
  end
59
+
60
+ # @param prefix [String]
61
+ # @param count [Integer] number of notes
62
+ # @return [String]
63
+ def to_asciibib(prefix = "", count = 1)
64
+ pref = prefix.empty? ? prefix : prefix + "."
65
+ out = count > 1 ? "#{pref}biblionote::\n" : ""
66
+ out + "#{pref}biblionote.type:: #{type}\n" if type
67
+ out += super "#{pref}biblionote"
68
+ out
69
+ end
32
70
  end
33
71
  end
@@ -32,6 +32,18 @@ module RelatonBib
32
32
  hash["draft"] = single_element_array(draft) if draft&.any?
33
33
  hash
34
34
  end
35
+
36
+ # @param prefix [String]
37
+ # @return [String]
38
+ def to_asciibib(prefix = "")
39
+ pref = prefix.empty? ? prefix : prefix + "."
40
+ out = ""
41
+ if revision_date
42
+ out += "#{pref}version.revision_date:: #{revision_date}\n"
43
+ end
44
+ draft&.each { |d| out += "#{pref}version.draft:: #{d}\n" }
45
+ out
46
+ end
35
47
  end
36
48
  end
37
49
  end
@@ -6,7 +6,8 @@ module RelatonBib
6
6
  # Bibliographic date.
7
7
  class BibliographicDate
8
8
  TYPES = %w[published accessed created implemented obsoleted confirmed
9
- updated issued transmitted copied unchanged circulated adapted].freeze
9
+ updated issued transmitted copied unchanged circulated adapted
10
+ vote-started vote-ended].freeze
10
11
 
11
12
  # @return [String]
12
13
  attr_reader :type
@@ -60,6 +61,19 @@ module RelatonBib
60
61
  hash
61
62
  end
62
63
 
64
+ # @param prefix [String]
65
+ # @param count [Integer] number of dates
66
+ # @return [String]
67
+ def to_asciibib(prefix = "", count = 1)
68
+ pref = prefix.empty? ? prefix : prefix + "."
69
+ out = count > 1 ? "#{pref}date::\n" : ""
70
+ out += "#{pref}date.type:: #{type}\n"
71
+ out += "#{pref}date.on:: #{on}\n" if on
72
+ out += "#{pref}date.from:: #{from}\n" if from
73
+ out += "#{pref}date.to:: #{to}\n" if to
74
+ out
75
+ end
76
+
63
77
  private
64
78
 
65
79
  # Formats date
@@ -45,7 +45,7 @@ module RelatonBib
45
45
  attr_reader :id, :type, :docnumber, :edition, :doctype
46
46
 
47
47
  # @!attribute [r] title
48
- # @return [Array<RelatonBib::TypedTitleString>]
48
+ # @return [RelatonBib::TypedTitleStringCollection]
49
49
 
50
50
  # @return [Array<RelatonBib::TypedUri>]
51
51
  attr_reader :link
@@ -59,10 +59,10 @@ module RelatonBib
59
59
  # @return [Array<RelatonBib::ContributionInfo>]
60
60
  attr_reader :contributor
61
61
 
62
- # @return [RelatonBib::BibliongraphicItem::Version, NilClass]
62
+ # @return [RelatonBib::BibliographicItem::Version, NilClass]
63
63
  attr_reader :version
64
64
 
65
- # @return [Array<RelatonBib::BiblioNote>]
65
+ # @return [RelatonBib::BiblioNoteCollection]
66
66
  attr_reader :biblionote
67
67
 
68
68
  # @return [Array<String>] language Iso639 code
@@ -126,7 +126,8 @@ module RelatonBib
126
126
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
127
127
 
128
128
  # @param id [String, NilClass]
129
- # @param title [Array<RelatonBib::TypedTitleString>]
129
+ # @param title [RelatonBib::TypedTitleStringCollection,
130
+ # Array<Hash, RelatonBib::TypedTitleString>]
130
131
  # @param formattedref [RelatonBib::FormattedRef, NilClass]
131
132
  # @param type [String, NilClass]
132
133
  # @param docid [Array<RelatonBib::DocumentIdentifier>]
@@ -136,7 +137,7 @@ module RelatonBib
136
137
  # @param docstatus [RelatonBib::DocumentStatus, NilClass]
137
138
  # @param edition [String, NilClass]
138
139
  # @param version [RelatonBib::BibliographicItem::Version, NilClass]
139
- # @param biblionote [Array<RelatonBib::BiblioNote>]
140
+ # @param biblionote [RelatonBib::BiblioNoteCollection]
140
141
  # @param series [Array<RelatonBib::Series>]
141
142
  # @param medium [RelatonBib::Medium, NilClas]
142
143
  # @param place [Array<String, RelatonBib::Place>]
@@ -193,9 +194,7 @@ module RelatonBib
193
194
  warn %{[relaton-bib] document type "#{args[:type]}" is invalid.}
194
195
  end
195
196
 
196
- @title = (args[:title] || []).map do |t|
197
- t.is_a?(Hash) ? TypedTitleString.new(t) : t
198
- end
197
+ @title = TypedTitleStringCollection.new(args[:title])
199
198
 
200
199
  @date = (args[:date] || []).map do |d|
201
200
  d.is_a?(Hash) ? BibliographicDate.new(d) : d
@@ -224,7 +223,7 @@ module RelatonBib
224
223
  @docnumber = args[:docnumber]
225
224
  @edition = args[:edition]
226
225
  @version = args[:version]
227
- @biblionote = args.fetch :biblionote, []
226
+ @biblionote = args.fetch :biblionote, BiblioNoteCollection.new([])
228
227
  @language = args.fetch :language, []
229
228
  @script = args.fetch :script, []
230
229
  @status = args[:docstatus]
@@ -237,13 +236,18 @@ module RelatonBib
237
236
  end
238
237
  @series = args.fetch :series, []
239
238
  @medium = args[:medium]
240
- @place = args.fetch(:place, []).map { |pl| pl.is_a?(String) ? Place.new(name: pl) : pl }
239
+ @place = args.fetch(:place, []).map do |pl|
240
+ pl.is_a?(String) ? Place.new(name: pl) : pl
241
+ end
241
242
  @extent = args[:extent] || []
242
243
  @accesslocation = args.fetch :accesslocation, []
243
244
  @classification = args.fetch :classification, []
244
245
  @validity = args[:validity]
245
- @fetched = args.fetch :fetched, nil # , Date.today # we should pass the fetched arg from scrappers
246
- @keyword = (args[:keyword] || []).map { |kw| LocalizedString.new(kw) }
246
+ # we should pass the fetched arg from scrappers
247
+ @fetched = args.fetch :fetched, nil
248
+ @keyword = (args[:keyword] || []).map do |kw|
249
+ LocalizedString.new(kw)
250
+ end
247
251
  @license = args.fetch :license, []
248
252
  @doctype = args[:doctype]
249
253
  @editorialgroup = args[:editorialgroup]
@@ -257,12 +261,15 @@ module RelatonBib
257
261
  # @return [RelatonBib::FormattedString, Array<RelatonBib::FormattedString>]
258
262
  def abstract(lang: nil)
259
263
  if lang
260
- @abstract.detect { |a| a.language.include? lang }
264
+ @abstract.detect { |a| a.language&.include? lang }
261
265
  else
262
266
  @abstract
263
267
  end
264
268
  end
265
269
 
270
+ # @param id [RelatonBib::DocumentIdentifier]
271
+ # @param attribute [boolean, nil]
272
+ # @return [String]
266
273
  def makeid(id, attribute)
267
274
  return nil if attribute && !@id_attribute
268
275
 
@@ -277,8 +284,12 @@ module RelatonBib
277
284
  idstr.strip
278
285
  end
279
286
 
287
+ # @param identifier [RelatonBib::DocumentIdentifier]
288
+ # @param options [Hash]
289
+ # @option options [boolean, nil] :no_year
290
+ # @option options [boolean, nil] :all_parts
280
291
  # @return [String]
281
- def shortref(identifier, **opts)
292
+ def shortref(identifier, **opts) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/PerceivedComplexity
282
293
  pubdate = date.select { |d| d.type == "published" }
283
294
  year = if opts[:no_year] || pubdate.empty? then ""
284
295
  else ":" + pubdate&.first&.on&.year.to_s
@@ -288,22 +299,24 @@ module RelatonBib
288
299
  "#{makeid(identifier, false)}#{year}"
289
300
  end
290
301
 
291
- # @param builder [Nokogiri::XML::Builder, NillClass] (nil)
292
- # @return [String]
293
- def to_xml(builder = nil, **opts, &block)
294
- if builder
295
- render_xml builder, **opts, &block
302
+ # @param opts [Hash]
303
+ # @option opts [Nokogiri::XML::Builder] :builder XML builder
304
+ # @option opts [Boolean] :bibdata
305
+ # @option opts [Symbol, NilClass] :date_format (:short), :full
306
+ # @option opts [String, Symbol] :lang language
307
+ # @return [String] XML
308
+ def to_xml(**opts, &block)
309
+ if opts[:builder]
310
+ render_xml **opts, &block
296
311
  else
297
312
  Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
298
- render_xml xml, **opts, &block
313
+ render_xml builder: xml, **opts, &block
299
314
  end.doc.root.to_xml
300
315
  end
301
316
  end
302
317
 
303
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
304
-
305
318
  # @return [Hash]
306
- def to_hash
319
+ def to_hash # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
307
320
  hash = {}
308
321
  hash["id"] = id if id
309
322
  hash["title"] = single_element_array(title) if title&.any?
@@ -312,7 +325,9 @@ module RelatonBib
312
325
  hash["docid"] = single_element_array(docidentifier) if docidentifier&.any?
313
326
  hash["docnumber"] = docnumber if docnumber
314
327
  hash["date"] = single_element_array(date) if date&.any?
315
- hash["contributor"] = single_element_array(contributor) if contributor&.any?
328
+ if contributor&.any?
329
+ hash["contributor"] = single_element_array(contributor)
330
+ end
316
331
  hash["edition"] = edition if edition
317
332
  hash["version"] = version.to_hash if version
318
333
  hash["revdate"] = revdate if revdate
@@ -328,25 +343,30 @@ module RelatonBib
328
343
  hash["medium"] = medium.to_hash if medium
329
344
  hash["place"] = single_element_array(place) if place&.any?
330
345
  hash["extent"] = single_element_array(extent) if extent&.any?
331
- hash["accesslocation"] = single_element_array(accesslocation) if accesslocation&.any?
332
- hash["classification"] = single_element_array(classification) if classification&.any?
346
+ if accesslocation&.any?
347
+ hash["accesslocation"] = single_element_array(accesslocation)
348
+ end
349
+ if classification&.any?
350
+ hash["classification"] = single_element_array(classification)
351
+ end
333
352
  hash["validity"] = validity.to_hash if validity
334
353
  hash["fetched"] = fetched.to_s if fetched
335
354
  hash["keyword"] = single_element_array(keyword) if keyword&.any?
336
355
  hash["license"] = single_element_array(license) if license&.any?
337
356
  hash["doctype"] = doctype if doctype
338
- hash["editorialgroup"] = editorialgroup.to_hash if editorialgroup
357
+ if editorialgroup&.presence?
358
+ hash["editorialgroup"] = editorialgroup.to_hash
359
+ end
339
360
  hash["ics"] = single_element_array ics if ics.any?
340
361
  if structuredidentifier&.presence?
341
362
  hash["structuredidentifier"] = structuredidentifier.to_hash
342
363
  end
343
364
  hash
344
365
  end
345
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
346
366
 
347
367
  # @param bibtex [BibTeX::Bibliography, NilClass]
348
368
  # @return [String]
349
- def to_bibtex(bibtex = nil)
369
+ def to_bibtex(bibtex = nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
350
370
  item = BibTeX::Entry.new
351
371
  item.type = bibtex_type
352
372
  item.key = id
@@ -369,14 +389,11 @@ module RelatonBib
369
389
  bibtex << item
370
390
  bibtex.to_s
371
391
  end
372
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
373
392
 
374
- # @param lang [String] language code Iso639
375
- # @return [Array<RelatonIsoBib::TypedTitleString>]
393
+ # @param lang [String, nil] language code Iso639
394
+ # @return [RelatonIsoBib::TypedTitleStringCollection]
376
395
  def title(lang: nil)
377
- if lang then @title.select { |t| t.title.language&.include? lang }
378
- else @title
379
- end
396
+ @title.lang lang
380
397
  end
381
398
 
382
399
  # @param type [Symbol] type of url, can be :src/:obp/:rss
@@ -391,7 +408,7 @@ module RelatonBib
391
408
 
392
409
  def deep_clone
393
410
  dump = Marshal.dump self
394
- Marshal.load dump
411
+ Marshal.load dump # rubocop:disable Security/MarshalLoad
395
412
  end
396
413
 
397
414
  def disable_id_attribute
@@ -399,17 +416,19 @@ module RelatonBib
399
416
  end
400
417
 
401
418
  # remove title part components and abstract
402
- def to_all_parts
419
+ def to_all_parts # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength,Metrics/PerceivedComplexity
403
420
  me = deep_clone
404
421
  me.disable_id_attribute
405
- me.relation << RelatonBib::DocumentRelation.new(
406
- type: "instance", bibitem: self,
407
- )
422
+ me.relation << DocumentRelation.new(type: "instance", bibitem: self)
408
423
  me.language.each do |l|
409
- me.title.delete_if { |t| t.type == "title-part" }
410
- ttl = me.title.select { |t| t.type != "main" && t.title.language&.include?(l) }
424
+ me.title.delete_title_part!
425
+ ttl = me.title.select do |t|
426
+ t.type != "main" && t.title.language&.include?(l)
427
+ end
411
428
  tm_en = ttl.map { |t| t.title.content }.join " – "
412
- me.title.detect { |t| t.type == "main" && t.title.language&.include?(l) }&.title&.content = tm_en
429
+ me.title.detect do |t|
430
+ t.type == "main" && t.title.language&.include?(l)
431
+ end&.title&.content = tm_en
413
432
  end
414
433
  me.abstract = []
415
434
  me.docidentifier.each(&:remove_part)
@@ -440,7 +459,7 @@ module RelatonBib
440
459
 
441
460
  # If revision_date exists then returns it else returns published date or nil
442
461
  # @return [String, NilClass]
443
- def revdate
462
+ def revdate # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
444
463
  @revdate ||= if version&.revision_date
445
464
  version.revision_date
446
465
  else
@@ -448,6 +467,53 @@ module RelatonBib
448
467
  end
449
468
  end
450
469
 
470
+ # @param prefix [String]
471
+ # @return [String]
472
+ def to_asciibib(prefix = "") # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
473
+ pref = prefix.empty? ? prefix : prefix + "."
474
+ out = prefix.empty? ? "[%bibitem]\n== {blank}\n" : ""
475
+ out += "#{pref}id:: #{id}\n" if id
476
+ out += "#{pref}fetched:: #{fetched}\n" if fetched
477
+ title.each { |t| out += t.to_asciibib(prefix, title.size) }
478
+ out += "#{pref}type:: #{type}\n" if type
479
+ docidentifier.each do |di|
480
+ out += di.to_asciibib prefix, docidentifier.size
481
+ end
482
+ out += "#{pref}docnumber:: #{docnumber}\n" if docnumber
483
+ out += "#{pref}edition:: #{edition}\n" if edition
484
+ language.each { |l| out += "#{pref}language:: #{l}\n" }
485
+ script.each { |s| out += "#{pref}script:: #{s}\n" }
486
+ out += version.to_asciibib prefix if version
487
+ biblionote&.each { |b| out += b.to_asciibib prefix, biblionote.size }
488
+ out += status.to_asciibib prefix if status
489
+ date.each { |d| out += d.to_asciibib prefix, date.size }
490
+ abstract.each do |a|
491
+ out += a.to_asciibib "#{pref}abstract", abstract.size
492
+ end
493
+ copyright.each { |c| out += c.to_asciibib prefix, copyright.size }
494
+ link.each { |l| out += l.to_asciibib prefix, link.size }
495
+ out += medium.to_asciibib prefix if medium
496
+ place.each { |pl| out += pl.to_asciibib prefix, place.size }
497
+ extent.each { |ex| out += ex.to_asciibib "#{pref}extent", extent.size }
498
+ accesslocation.each { |al| out += "#{pref}accesslocation:: #{al}\n" }
499
+ classification.each do |cl|
500
+ out += cl.to_asciibib prefix, classification.size
501
+ end
502
+ out += validity.to_asciibib prefix if validity
503
+ contributor.each do |c|
504
+ out += c.to_asciibib "contributor.*", contributor.size
505
+ end
506
+ out += relation.to_asciibib prefix if relation
507
+ series.each { |s| out += s.to_asciibib prefix, series.size }
508
+ out += "#{pref}doctype:: #{doctype}\n" if doctype
509
+ out += "#{pref}formattedref:: #{formattedref}\n" if formattedref
510
+ keyword.each { |kw| out += kw.to_asciibib "#{pref}keyword", keyword.size }
511
+ out += editorialgroup.to_asciibib prefix if editorialgroup
512
+ ics.each { |i| out += i.to_asciibib prefix, ics.size }
513
+ out += structuredidentifier.to_asciibib prefix if structuredidentifier
514
+ out
515
+ end
516
+
451
517
  private
452
518
 
453
519
  # @return [String]
@@ -470,7 +536,7 @@ module RelatonBib
470
536
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
471
537
 
472
538
  # @param [BibTeX::Entry]
473
- def bibtex_author(item)
539
+ def bibtex_author(item) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
474
540
  authors = contributor.select do |c|
475
541
  c.entity.is_a?(Person) && c.role.map(&:type).include?("author")
476
542
  end.map &:entity
@@ -487,7 +553,7 @@ module RelatonBib
487
553
  end
488
554
 
489
555
  # @param [BibTeX::Entry]
490
- def bibtex_contributor(item)
556
+ def bibtex_contributor(item) # rubocop:disable Metrics/CyclomaticComplexity
491
557
  contributor.each do |c|
492
558
  rls = c.role.map(&:type)
493
559
  if rls.include?("publisher") then item.publisher = c.entity.name
@@ -504,7 +570,7 @@ module RelatonBib
504
570
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
505
571
 
506
572
  # @param [BibTeX::Entry]
507
- def bibtex_note(item)
573
+ def bibtex_note(item) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize
508
574
  biblionote.each do |n|
509
575
  case n.type
510
576
  when "annote" then item.annote = n.content
@@ -600,13 +666,16 @@ module RelatonBib
600
666
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
601
667
  # rubocop:disable Style/NestedParenthesizedCalls, Metrics/BlockLength
602
668
 
603
- # @param builder [Nokogiri::XML::Builder]
604
- # @return [String]
605
- def render_xml(builder, **opts)
669
+ # @param opts [Hash]
670
+ # @option opts [Nokogiri::XML::Builder] :builder XML builder
671
+ # @option opts [Boolean] bibdata
672
+ # @option opts [Symbol, NilClass] :date_format (:short), :full
673
+ # @option opts [String] :lang language
674
+ def render_xml(**opts)
606
675
  root = opts[:bibdata] ? :bibdata : :bibitem
607
- xml = builder.send(root) do
676
+ xml = opts[:builder].send(root) do |builder|
608
677
  builder.fetched fetched if fetched
609
- title.each { |t| builder.title { t.to_xml builder } }
678
+ title.to_xml **opts
610
679
  formattedref&.to_xml builder
611
680
  link.each { |s| s.to_xml builder }
612
681
  docidentifier.each { |di| di.to_xml builder }
@@ -614,18 +683,23 @@ module RelatonBib
614
683
  date.each { |d| d.to_xml builder, **opts }
615
684
  contributor.each do |c|
616
685
  builder.contributor do
617
- c.role.each { |r| r.to_xml builder }
618
- c.to_xml builder
686
+ c.role.each { |r| r.to_xml **opts }
687
+ c.to_xml **opts
619
688
  end
620
689
  end
621
690
  builder.edition edition if edition
622
691
  version&.to_xml builder
623
- biblionote.each { |n| n.to_xml builder }
692
+ biblionote.to_xml **opts
693
+ opts[:note]&.each do |n|
694
+ builder.note(n[:text], format: "text/plain", type: n[:type])
695
+ end
624
696
  language.each { |l| builder.language l }
625
697
  script.each { |s| builder.script s }
626
- abstract.each { |a| builder.abstract { a.to_xml(builder) } }
698
+ abstr = abstract.select { |ab| ab.language&.include? opts[:lang] }
699
+ abstr = abstract unless abstr.any?
700
+ abstr.each { |a| builder.abstract { a.to_xml(builder) } }
627
701
  status&.to_xml builder
628
- copyright&.each { |c| c.to_xml builder }
702
+ copyright&.each { |c| c.to_xml **opts }
629
703
  relation.each { |r| r.to_xml builder, **opts }
630
704
  series.each { |s| s.to_xml builder }
631
705
  medium&.to_xml builder
@@ -634,7 +708,9 @@ module RelatonBib
634
708
  accesslocation.each { |al| builder.accesslocation al }
635
709
  license.each { |l| builder.license l }
636
710
  classification.each { |cls| cls.to_xml builder }
637
- keyword.each { |kw| builder.keyword { kw.to_xml(builder) } }
711
+ kwrd = keyword.select { |kw| kw.language&.include? opts[:lang] }
712
+ kwrd = keyword unless kwrd.any?
713
+ kwrd.each { |kw| builder.keyword { kw.to_xml(builder) } }
638
714
  validity&.to_xml builder
639
715
  if block_given? then yield builder
640
716
  elsif opts[:bibdata] && (doctype || editorialgroup || ics&.any? ||