metanorma-standoc 1.5.0 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +4 -9
  3. data/.github/workflows/ubuntu.yml +1 -5
  4. data/.github/workflows/windows.yml +2 -12
  5. data/lib/asciidoctor/standoc/base.rb +7 -2
  6. data/lib/asciidoctor/standoc/basicdoc.rng +23 -0
  7. data/lib/asciidoctor/standoc/cleanup.rb +32 -12
  8. data/lib/asciidoctor/standoc/cleanup_amend.rb +54 -0
  9. data/lib/asciidoctor/standoc/cleanup_block.rb +0 -2
  10. data/lib/asciidoctor/standoc/cleanup_footnotes.rb +11 -3
  11. data/lib/asciidoctor/standoc/cleanup_inline.rb +62 -1
  12. data/lib/asciidoctor/standoc/cleanup_ref.rb +11 -8
  13. data/lib/asciidoctor/standoc/cleanup_section.rb +19 -3
  14. data/lib/asciidoctor/standoc/cleanup_terms.rb +2 -2
  15. data/lib/asciidoctor/standoc/converter.rb +4 -2
  16. data/lib/asciidoctor/standoc/front.rb +3 -15
  17. data/lib/asciidoctor/standoc/front_contributor.rb +79 -14
  18. data/lib/asciidoctor/standoc/inline.rb +21 -31
  19. data/lib/asciidoctor/standoc/isodoc.rng +124 -15
  20. data/lib/asciidoctor/standoc/log.rb +10 -1
  21. data/lib/asciidoctor/standoc/macros.rb +44 -33
  22. data/lib/asciidoctor/standoc/ref.rb +39 -44
  23. data/lib/asciidoctor/standoc/ref_sect.rb +12 -5
  24. data/lib/asciidoctor/standoc/section.rb +15 -12
  25. data/lib/asciidoctor/standoc/table.rb +3 -2
  26. data/lib/asciidoctor/standoc/utils.rb +2 -1
  27. data/lib/asciidoctor/standoc/validate.rb +30 -18
  28. data/lib/asciidoctor/standoc/validate_section.rb +1 -1
  29. data/lib/asciidoctor/standoc/views/datamodel/model_representation.adoc.erb +10 -10
  30. data/lib/liquid/custom_blocks/key_iterator.rb +21 -0
  31. data/lib/liquid/custom_blocks/with_json_nested_context.rb +18 -0
  32. data/lib/liquid/custom_blocks/with_yaml_nested_context.rb +19 -0
  33. data/lib/liquid/custom_filters/values.rb +7 -0
  34. data/lib/metanorma/standoc.rb +0 -5
  35. data/lib/metanorma/standoc/version.rb +20 -1
  36. data/metanorma-standoc.gemspec +4 -4
  37. data/spec/asciidoctor-standoc/base_spec.rb +257 -10
  38. data/spec/asciidoctor-standoc/blocks_spec.rb +263 -144
  39. data/spec/asciidoctor-standoc/cleanup_spec.rb +199 -50
  40. data/spec/asciidoctor-standoc/inline_spec.rb +132 -5
  41. data/spec/asciidoctor-standoc/isobib_cache_spec.rb +13 -27
  42. data/spec/asciidoctor-standoc/macros_json2text_spec.rb +10 -0
  43. data/spec/asciidoctor-standoc/macros_spec.rb +43 -23
  44. data/spec/asciidoctor-standoc/macros_yaml2text_spec.rb +6 -561
  45. data/spec/asciidoctor-standoc/refs_dl_spec.rb +7 -5
  46. data/spec/asciidoctor-standoc/refs_spec.rb +268 -57
  47. data/spec/asciidoctor-standoc/section_spec.rb +0 -1
  48. data/spec/asciidoctor-standoc/table_spec.rb +119 -113
  49. data/spec/asciidoctor-standoc/validate_spec.rb +45 -1
  50. data/spec/examples/codes_table.html +1365 -1365
  51. data/spec/fixtures/macros_datamodel/address_class_profile.xml +46 -46
  52. data/spec/fixtures/macros_datamodel/address_component_profile.xml +21 -21
  53. data/spec/fixtures/macros_datamodel/blank_definition_profile.xml +21 -21
  54. data/spec/spec_helper.rb +110 -109
  55. data/spec/support/shared_examples/structured_data_2_text_preprocessor.rb +781 -0
  56. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +159 -159
  57. data/spec/vcr_cassettes/isobib_get_123.yml +11 -57
  58. data/spec/vcr_cassettes/isobib_get_123_1.yml +90 -90
  59. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +361 -0
  60. data/spec/vcr_cassettes/isobib_get_123_2001.yml +45 -45
  61. data/spec/vcr_cassettes/isobib_get_124.yml +45 -45
  62. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +8 -8
  63. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +32 -30
  64. metadata +41 -8
  65. data/lib/asciidoctor/standoc/macros_yaml2text.rb +0 -165
  66. data/lib/metanorma/standoc/latexml_requirement.rb +0 -62
  67. data/lib/metanorma/standoc/requirement.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76c3b117ea592275339f9ee8103f17645d9675f45635abfbc8e5333fc512af1c
4
- data.tar.gz: a345b19a2657f356225f2087e17a7dba7bd4720389cf44487892d3f1e1bc5345
3
+ metadata.gz: 11adce8b2fe42f3e2b4db51088b5818f5cff207a62cc19e33b27cf5a53160c47
4
+ data.tar.gz: 17967efeb1bc5c518a9498ec8329d7ae0fb6c77cb19bb911527aa15efd2f0881
5
5
  SHA512:
6
- metadata.gz: 630d1159cc78920d3bab3e73a2577b54d00bb966b0faa15166ff1af832656ab985e55f8fa830d40a2fbec96a8cf8555880f89f0e73d749dc73540e6cd8303469
7
- data.tar.gz: f3c46604bb69f1e34eb8b2af182e198e99a6f2cae3bce808a9547e096b1852b4868c00a8522370a52c92ad5f263ab2f7e5ee348196fffbe1084ef1c666900080
6
+ metadata.gz: 6bef6b7fb5db91fd23d039a2e01d69685ba049b3ef34ebb2c4eaafa2e144b54c6c948b1c0a91796b700c2c18494c048d79d71b21fe58e1437f994a296d950785
7
+ data.tar.gz: 6c4d35c69f213280a58dd8b5e53da18c4947cc5de3210397f35f19726dbcceb2a3ea4f26066f86ee2fca2e0d0a37d9941e6cb092a7625d557dfba25eb4367812
@@ -29,18 +29,13 @@ jobs:
29
29
  uses: actions/setup-ruby@v1
30
30
  with:
31
31
  ruby-version: ${{ matrix.ruby }}
32
- - name: Install LaTeXML
33
- run: |
34
- brew install libxml2 cpanminus
35
- env PATH=$(brew --prefix libxml2)/bin:$PATH \
36
- cpanm --notest XML::LibXSLT@1.96 git://github.com/brucemiller/LaTeXML.git@9a0e7dc5
37
- - name: Install PlantUML
38
- run: |
39
- brew install plantuml
40
32
  - name: Update gems
41
33
  run: |
42
34
  sudo gem install bundler --force
43
35
  bundle install --jobs 4 --retry 3
36
+ - name: Install PlantUML
37
+ run: |
38
+ brew install plantuml
44
39
  - name: Run specs
45
40
  run: |
46
- env PATH=$(brew --prefix perl)/bin:$PATH bundle exec rake
41
+ bundle exec rake
@@ -33,17 +33,13 @@ jobs:
33
33
  run: |
34
34
  gem install bundler
35
35
  bundle install --jobs 4 --retry 3
36
- - name: Install LaTeXML
37
- run: |
38
- sudo snap install latexml --edge
39
- echo "::add-path::/snap/bin"
40
36
  - name: Install PlantUML
41
37
  uses: nick-invision/retry@v1
42
38
  with:
43
39
  polling_interval_seconds: 5
44
40
  timeout_minutes: 5
45
41
  max_attempts: 3
46
- command: sudo bash -c "curl -L https://github.com/metanorma/plantuml-install/raw/master/ubuntu.sh | bash"
42
+ command: sudo apt-get update -y && sudo bash -c "curl -L https://github.com/metanorma/plantuml-install/raw/master/ubuntu.sh | bash"
47
43
  - name: Run specs
48
44
  run: |
49
45
  bundle exec rake
@@ -29,25 +29,15 @@ jobs:
29
29
  uses: actions/setup-ruby@v1
30
30
  with:
31
31
  ruby-version: ${{ matrix.ruby }}
32
- - name: Install MN Windows dependencies
33
- shell: pwsh
34
- run: |
35
- choco install --no-progress plantuml make sed gnuwin32-coreutils.install grep
36
32
  - name: Update gems
37
33
  shell: pwsh
38
34
  run: |
39
35
  gem install bundler
40
36
  bundle config --local path vendor/bundle
41
37
  bundle install --jobs 4 --retry 3
42
- - name: Install LaTeXML
43
- shell: cmd
38
+ - name: Install PlantUML
44
39
  run: |
45
- cinst -y latexml
46
- refreshenv
47
- set PATH=C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin;%PATH%
48
- where latexmlmath
40
+ cinst -y plantuml
49
41
  - name: Run specs
50
- shell: pwsh
51
42
  run: |
52
- $env:Path = "C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin;$env:Path"
53
43
  bundle exec rake
@@ -143,6 +143,11 @@ module Asciidoctor
143
143
  ret
144
144
  end
145
145
 
146
+ def version
147
+ flavour = self.class.name.sub(/::Converter$/, "").sub(/^.+::/, "")
148
+ Metanorma.versioned(Metanorma, flavour)[-1]::VERSION
149
+ end
150
+
146
151
  def clean_exit
147
152
  @log.write(@output_dir + @filename + ".err") unless @novalid
148
153
  @files_to_delete.each { |f| FileUtils.rm f }
@@ -150,7 +155,7 @@ module Asciidoctor
150
155
 
151
156
  def makexml1(node)
152
157
  result = ["<?xml version='1.0' encoding='UTF-8'?>",
153
- "<#{xml_root_tag}>"]
158
+ "<#{xml_root_tag} type='semantic' version='#{version}'>"]
154
159
  result << noko { |ixml| front node, ixml }
155
160
  result << noko { |ixml| middle node, ixml }
156
161
  result << "</#{xml_root_tag}>"
@@ -170,7 +175,7 @@ module Asciidoctor
170
175
  end
171
176
 
172
177
  def doctype(node)
173
- node.attr("doctype")
178
+ node.attr("doctype")&.gsub(/\s+/, "-")&.downcase
174
179
  end
175
180
 
176
181
  def front(node, xml)
@@ -402,6 +402,16 @@
402
402
  </choice>
403
403
  </attribute>
404
404
  </optional>
405
+ <optional>
406
+ <attribute name="valign">
407
+ <choice>
408
+ <value>top</value>
409
+ <value>middle</value>
410
+ <value>bottom</value>
411
+ <value>baseline</value>
412
+ </choice>
413
+ </attribute>
414
+ </optional>
405
415
  <choice>
406
416
  <zeroOrMore>
407
417
  <ref name="TextElement"/>
@@ -429,6 +439,16 @@
429
439
  </choice>
430
440
  </attribute>
431
441
  </optional>
442
+ <optional>
443
+ <attribute name="valign">
444
+ <choice>
445
+ <value>top</value>
446
+ <value>middle</value>
447
+ <value>bottom</value>
448
+ <value>baseline</value>
449
+ </choice>
450
+ </attribute>
451
+ </optional>
432
452
  <choice>
433
453
  <zeroOrMore>
434
454
  <ref name="TextElement"/>
@@ -998,6 +1018,9 @@
998
1018
  <value>alphabet_upper</value>
999
1019
  </choice>
1000
1020
  </attribute>
1021
+ <optional>
1022
+ <attribute name="start"/>
1023
+ </optional>
1001
1024
  <oneOrMore>
1002
1025
  <ref name="li"/>
1003
1026
  </oneOrMore>
@@ -9,6 +9,7 @@ require_relative "./cleanup_boilerplate.rb"
9
9
  require_relative "./cleanup_section.rb"
10
10
  require_relative "./cleanup_terms.rb"
11
11
  require_relative "./cleanup_inline.rb"
12
+ require_relative "./cleanup_amend.rb"
12
13
  require "relaton_iev"
13
14
 
14
15
  module Asciidoctor
@@ -71,6 +72,7 @@ module Asciidoctor
71
72
  para_cleanup(xmldoc)
72
73
  empty_element_cleanup(xmldoc)
73
74
  img_cleanup(xmldoc)
75
+ anchor_cleanup(xmldoc)
74
76
  xmldoc
75
77
  end
76
78
 
@@ -79,12 +81,13 @@ module Asciidoctor
79
81
  xmldoc.traverse do |n|
80
82
  next unless n.text?
81
83
  if @smartquotes
82
- next unless /[-'"(<>]|\.\.|\dx/.match(n)
83
- next unless n.ancestors("pre, tt, sourcecode, bibdata, on, "\
84
- "stem, figure[@class = 'pseudocode']").empty?
84
+ /[-'"(<>]|\.\.|\dx/.match(n) or next
85
+ n.ancestors("pre, tt, sourcecode, bibdata, on, "\
86
+ "stem, figure[@class = 'pseudocode']").empty? or next
85
87
  n.replace(Utils::smartformat(n.text))
86
88
  else
87
- n.replace(n.text.gsub(/(?<=\p{Alnum})\u2019(?=\p{Alpha})/, "'"))
89
+ n.replace(n.text.gsub(/(?<=\p{Alnum})\u2019(?=\p{Alpha})/, "'"))#.
90
+ #gsub(/</, "&lt;").gsub(/>/, "&gt;"))
88
91
  end
89
92
  end
90
93
  end
@@ -144,16 +147,33 @@ module Asciidoctor
144
147
  align_callouts_to_annotations(xmldoc)
145
148
  end
146
149
 
150
+ def xml_unescape_mathml(x)
151
+ return if x.children.any? { |y| y.element? }
152
+ math = x.text.gsub(/&lt;/, "<").gsub(/&gt;/, ">").gsub(/&quot;/, '"').
153
+ gsub(/&apos;/, "'").gsub(/&amp;/, "&").
154
+ gsub(/<[^: \r\n\t\/]+:/, "<").gsub(/<\/[^ \r\n\t:]+:/, "</")
155
+ x.children = math
156
+ end
157
+
158
+ def mathml_preserve_space(m)
159
+ m.xpath(".//m:mtext",
160
+ "m" => "http://www.w3.org/1998/Math/MathML").each do |x|
161
+ x.children = x.children.to_xml.gsub(/^\s/, "&#xA0;").
162
+ gsub(/\s$/, "&#xA0;")
163
+ end
164
+ end
165
+
166
+ def mathml_namespace(stem)
167
+ stem.xpath("./math", ).each do |x|
168
+ x.default_namespace = "http://www.w3.org/1998/Math/MathML"
169
+ end
170
+ end
171
+
147
172
  def mathml_cleanup(xmldoc)
148
173
  xmldoc.xpath("//stem[@type = 'MathML']").each do |x|
149
- next if x.children.any? { |y| y.element? }
150
- math = x.text.gsub(/&lt;/, "<").gsub(/&gt;/, ">").gsub(/&quot;/, '"').
151
- gsub(/&apos;/, "'").gsub(/&amp;/, "&").
152
- gsub(/<[^: \r\n\t\/]+:/, "<").gsub(/<\/[^ \r\n\t:]+:/, "</").
153
- gsub(/ xmlns[^>"']+/, "").
154
- gsub(/<math /, '<math xmlns="http://www.w3.org/1998/Math/MathML" ').
155
- gsub(/<math>/, '<math xmlns="http://www.w3.org/1998/Math/MathML">')
156
- x.children = math
174
+ xml_unescape_mathml(x)
175
+ mathml_namespace(x)
176
+ mathml_preserve_space(x)
157
177
  end
158
178
  end
159
179
 
@@ -0,0 +1,54 @@
1
+ module Asciidoctor
2
+ module Standoc
3
+ module Cleanup
4
+ def change_clauses(x)
5
+ x.xpath("//clause[@change]").each do |c|
6
+ a = create_amend(c)
7
+ end
8
+ end
9
+
10
+ def create_amend(c)
11
+ a = c.add_child("<amend id='_#{UUIDTools::UUID.random_create}'/>").first
12
+ c.elements.each do |e|
13
+ e.parent = a unless %w(amend title).include? e.name
14
+ end
15
+ create_amend1(c, a)
16
+ end
17
+
18
+ def create_amend1(c, a)
19
+ create_amend2(c, a)
20
+ d = a.at("./description")
21
+ d.xpath(".//autonumber").each { |e| d.previous = e }
22
+ d.xpath(".//p[normalize-space(.)='']").each { |e| e.remove }
23
+ move_attrs_to_amend(c, a)
24
+ a
25
+ end
26
+
27
+ def create_amend2(c, a)
28
+ q = a.at("./quote") and q.name = "newcontent"
29
+ if q.nil?
30
+ a.children = "<description>#{a.children.to_xml}</description>"
31
+ else
32
+ pre = q&.xpath("./preceding-sibling::*")&.remove
33
+ post = q&.xpath("./following-sibling::*")&.remove
34
+ pre.empty? or a << "<description>#{pre.to_xml}</description>"
35
+ a << q.remove
36
+ post.empty? or a << "<description>#{post.to_xml}</description>"
37
+ end
38
+ end
39
+
40
+ def move_attrs_to_amend(c, a)
41
+ %w(change path path_end title).each do |e|
42
+ next unless c[e]
43
+ a[e] = c[e]
44
+ c.delete(e)
45
+ end
46
+ return unless a["locality"]
47
+ loc = a.children.add_previous_sibling("<location/>")
48
+ extract_localities1(loc, a["locality"])
49
+ loc1 = loc.at("./localityStack") and loc.replace(loc1.elements)
50
+ a.delete("locality")
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,8 +1,6 @@
1
1
  require "date"
2
- require "nokogiri"
3
2
  require "htmlentities"
4
3
  require "json"
5
- require "pathname"
6
4
  require "open-uri"
7
5
 
8
6
  module Asciidoctor
@@ -1,10 +1,7 @@
1
1
  require "date"
2
- require "nokogiri"
3
2
  require "htmlentities"
4
3
  require "json"
5
- require "pathname"
6
4
  require "open-uri"
7
- require "pp"
8
5
 
9
6
  module Asciidoctor
10
7
  module Standoc
@@ -75,7 +72,18 @@ module Asciidoctor
75
72
  end
76
73
  end
77
74
 
75
+ def title_footnote_move(xmldoc)
76
+ ins = xmldoc.at("//bibdata/language")
77
+ xmldoc.xpath("//bibdata/title//fn").each do |f|
78
+ f.name = "note"
79
+ f["type"] = "title-footnote"
80
+ f.delete("reference")
81
+ ins.previous = f.remove
82
+ end
83
+ end
84
+
78
85
  def footnote_cleanup(xmldoc)
86
+ title_footnote_move(xmldoc)
79
87
  table_footnote_renumber(xmldoc)
80
88
  other_footnote_renumber(xmldoc)
81
89
  xmldoc.xpath("//fn").each do |fn|
@@ -50,6 +50,10 @@ module Asciidoctor
50
50
 
51
51
  def extract_localities(x)
52
52
  text = x&.children&.first&.remove&.text
53
+ extract_localities1(x, text)
54
+ end
55
+
56
+ def extract_localities1(x, text)
53
57
  b = x.add_child("<localityStack/>").first if LOCALITY_RE.match text
54
58
  while (m = LOCALITY_RE.match text)
55
59
  ref = m[:ref] ? "<referenceFrom>#{tq m[:ref]}</referenceFrom>" : ""
@@ -117,7 +121,8 @@ module Asciidoctor
117
121
  def concept_termbase_cleanup(x)
118
122
  text = x&.children&.first&.remove&.text
119
123
  termbase, key = x["key"].split(/:/, 2)
120
- x.add_child(%(<termref base="#{termbase}" target="#{key}">#{text}</termref>))
124
+ x.add_child(%(<termref base="#{termbase}" target="#{key}">) +
125
+ "#{text}</termref>")
121
126
  end
122
127
 
123
128
  def concept_xref_cleanup(x)
@@ -129,6 +134,62 @@ module Asciidoctor
129
134
  x.children = "<eref>#{x.children.to_xml}</eref>"
130
135
  extract_localities(x.first_element_child)
131
136
  end
137
+
138
+ NAMECHAR = "\u0000-\u0022\u0024\u002c\u002f\u003a-\u0040\\u005b-\u005e"\
139
+ "\u0060\u007b-\u00b6\u00b8-\u00bf\u00d7\u00f7\u037e\u2000-\u200b"\
140
+ "\u200e-\u203e\u2041-\u206f\u2190-\u2bff\u2ff0-\u3000".freeze
141
+ #"\ud800-\uf8ff\ufdd0-\ufdef\ufffe-\uffff".freeze
142
+ NAMESTARTCHAR = "\\u002d\u002e\u0030-\u0039\u00b7\u0300-\u036f"\
143
+ "\u203f-\u2040".freeze
144
+
145
+ def to_ncname(s)
146
+ start = s[0]
147
+ ret1 = %r([#{NAMECHAR}#]).match(start) ? "_" :
148
+ (%r([#{NAMESTARTCHAR}#]).match(start) ? "_#{start}" : start)
149
+ ret2 = s[1..-1] || ""
150
+ ret = (ret1 || "") + ret2.gsub(%r([#{NAMECHAR}#]), "_")
151
+ ret
152
+ end
153
+
154
+ def to_xreftarget(s)
155
+ return to_ncname(s) unless /^[^#]+#.+$/.match(s)
156
+ /^(?<pref>[^#]+)#(?<suff>.+)$/ =~ s
157
+ pref = pref.gsub(%r([#{NAMECHAR}]), "_")
158
+ suff = suff.gsub(%r([#{NAMECHAR}]), "_")
159
+ "#{pref}##{suff}"
160
+ end
161
+
162
+ IDREF = "//*/@id | //review/@from | //review/@to | "\
163
+ "//callout/@target | //citation/@bibitemid | //eref/@bibitemid".freeze
164
+
165
+ def anchor_cleanup(x)
166
+ anchor_cleanup1(x)
167
+ xreftarget_cleanup(x)
168
+ end
169
+
170
+ def anchor_cleanup1(x)
171
+ x.xpath(IDREF).each do |s|
172
+ if (ret = to_ncname(s.value)) != (orig = s.value)
173
+ s.value = ret
174
+ output = s.parent.dup
175
+ output.children.remove
176
+ @log.add("Anchors", s.parent, "normalised identifier in #{output} "\
177
+ "from #{orig}")
178
+ end
179
+ end
180
+ end
181
+
182
+ def xreftarget_cleanup(x)
183
+ x.xpath("//xref/@target").each do |s|
184
+ if (ret = to_xreftarget(s.value)) != (orig = s.value)
185
+ s.value = ret
186
+ output = s.parent.dup
187
+ output.children.remove
188
+ @log.add("Anchors", s.parent, "normalised identifier in #{output} "\
189
+ "from #{orig}")
190
+ end
191
+ end
192
+ end
132
193
  end
133
194
  end
134
195
  end
@@ -49,9 +49,8 @@ module Asciidoctor
49
49
  # consecutively, but that standards codes are preserved as is:
50
50
  # only numeric references are renumbered
51
51
  def biblio_renumber(xmldoc)
52
- r = xmldoc.at("//references[@normative = 'false'] | "\
53
- "//clause[.//references[@normative = 'false']] | "\
54
- "//annex[.//references[@normative = 'false']]") or return
52
+ r = xmldoc.at("//references | //clause[.//references] | "\
53
+ "//annex[.//references]") or return
55
54
  r.xpath(".//bibitem[not(ancestor::bibitem)]").each_with_index do |b, i|
56
55
  next unless docid = b.at("./docidentifier[@type = 'metanorma']")
57
56
  next unless /^\[\d+\]$/.match(docid.text)
@@ -127,20 +126,22 @@ module Asciidoctor
127
126
  bibitemxml = RelatonBib::BibliographicItem.new(
128
127
  RelatonBib::HashConverter::hash_to_bib(bib)).to_xml or next
129
128
  bibitem = Nokogiri::XML(bibitemxml)
130
- bibitem["id"] = c["id"] if c["id"]
129
+ bibitem.root["id"] = c["id"] if c["id"] && !/^_/.match(c["id"])
131
130
  c.replace(bibitem.root)
132
131
  end
133
132
  end
134
133
 
135
134
  def validate_ref_dl(bib, c)
136
- unless bib["id"]
135
+ id = bib["id"]
136
+ id ||= c["id"] unless /^_/.match(c["id"]) # do not accept implicit id
137
+ unless id
137
138
  @log.add("Anchors", c, "The following reference is missing "\
138
139
  "an anchor:\n" + c.to_xml)
139
140
  return
140
141
  end
141
- bib["title"] or @log.add("Bibliography", c, "Reference #{bib['id']} "\
142
+ bib["title"] or @log.add("Bibliography", c, "Reference #{id} "\
142
143
  "is missing a title")
143
- bib["docid"] or @log.add("Bibliography", c, "Reference #{bib['id']} "\
144
+ bib["docid"] or @log.add("Bibliography", c, "Reference #{id} "\
144
145
  "is missing a document identifier (docid)")
145
146
  end
146
147
 
@@ -201,7 +202,9 @@ module Asciidoctor
201
202
  end
202
203
  if !nested and c.at("./title")
203
204
  title = c.at("./title").remove.children.to_xml
204
- bib["title"] = bib["title"] ? Array(bib["title"]) : []
205
+ bib["title"] = [bib["title"]] if bib["title"].is_a? Hash
206
+ bib["title"] = [bib["title"]] if bib["title"].is_a? String
207
+ bib["title"] = [] unless bib["title"]
205
208
  bib["title"] << title if !title.empty?
206
209
  end
207
210
  bib