metanorma-standoc 1.10.7 → 1.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +19 -23
  3. data/Rakefile +1 -1
  4. data/lib/asciidoctor/standoc/base.rb +7 -4
  5. data/lib/asciidoctor/standoc/basicdoc.rng +21 -4
  6. data/lib/asciidoctor/standoc/blocks.rb +23 -23
  7. data/lib/asciidoctor/standoc/blocks_notes.rb +17 -22
  8. data/lib/asciidoctor/standoc/cleanup.rb +20 -11
  9. data/lib/asciidoctor/standoc/cleanup_image.rb +6 -7
  10. data/lib/asciidoctor/standoc/cleanup_inline.rb +45 -7
  11. data/lib/asciidoctor/standoc/cleanup_maths.rb +5 -6
  12. data/lib/asciidoctor/standoc/cleanup_ref.rb +5 -0
  13. data/lib/asciidoctor/standoc/cleanup_reqt.rb +2 -21
  14. data/lib/asciidoctor/standoc/cleanup_symbols.rb +48 -0
  15. data/lib/asciidoctor/standoc/cleanup_terms.rb +48 -77
  16. data/lib/asciidoctor/standoc/cleanup_terms_designations.rb +162 -0
  17. data/lib/asciidoctor/standoc/cleanup_text.rb +23 -0
  18. data/lib/asciidoctor/standoc/converter.rb +2 -0
  19. data/lib/asciidoctor/standoc/inline.rb +7 -5
  20. data/lib/asciidoctor/standoc/isodoc.rng +420 -76
  21. data/lib/asciidoctor/standoc/lists.rb +14 -16
  22. data/lib/asciidoctor/standoc/macros_plantuml.rb +29 -14
  23. data/lib/asciidoctor/standoc/macros_terms.rb +55 -8
  24. data/lib/asciidoctor/standoc/ref.rb +1 -1
  25. data/lib/asciidoctor/standoc/ref_sect.rb +26 -18
  26. data/lib/asciidoctor/standoc/reqt.rng +23 -2
  27. data/lib/asciidoctor/standoc/section.rb +13 -12
  28. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +50 -11
  29. data/lib/asciidoctor/standoc/terms.rb +12 -2
  30. data/lib/asciidoctor/standoc/utils.rb +36 -23
  31. data/lib/asciidoctor/standoc/validate.rb +45 -27
  32. data/lib/asciidoctor/standoc/validate_section.rb +5 -2
  33. data/lib/metanorma/standoc/version.rb +1 -1
  34. data/metanorma-standoc.gemspec +1 -1
  35. data/spec/asciidoctor/base_spec.rb +4 -3
  36. data/spec/asciidoctor/blocks_spec.rb +230 -49
  37. data/spec/asciidoctor/cleanup_sections_spec.rb +7 -7
  38. data/spec/asciidoctor/cleanup_spec.rb +105 -286
  39. data/spec/asciidoctor/cleanup_terms_spec.rb +1020 -0
  40. data/spec/asciidoctor/inline_spec.rb +2 -2
  41. data/spec/asciidoctor/lists_spec.rb +6 -6
  42. data/spec/asciidoctor/macros_plantuml_spec.rb +36 -1
  43. data/spec/asciidoctor/macros_spec.rb +190 -113
  44. data/spec/asciidoctor/refs_dl_spec.rb +4 -4
  45. data/spec/asciidoctor/refs_spec.rb +268 -108
  46. data/spec/asciidoctor/section_spec.rb +18 -18
  47. data/spec/asciidoctor/validate_spec.rb +87 -2
  48. data/spec/spec_helper.rb +8 -8
  49. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +50 -50
  50. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +12 -12
  51. data/spec/vcr_cassettes/isobib_get_123.yml +13 -13
  52. data/spec/vcr_cassettes/isobib_get_123_1.yml +25 -25
  53. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +31 -31
  54. data/spec/vcr_cassettes/isobib_get_123_2001.yml +12 -12
  55. data/spec/vcr_cassettes/isobib_get_124.yml +11 -11
  56. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
  57. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +45 -45
  58. metadata +8 -5
@@ -4,21 +4,19 @@ module Asciidoctor
4
4
  def li(xml_ul, item)
5
5
  xml_ul.li do |xml_li|
6
6
  if item.blocks?
7
- xml_li.p(**id_attr(item)) { |t| t << item.text }
7
+ xml_li.p(**attr_code(id_attr(item))) { |t| t << item.text }
8
8
  xml_li << item.content
9
9
  else
10
- xml_li.p(**id_attr(item)) { |p| p << item.text }
10
+ xml_li.p(**attr_code(id_attr(item))) { |p| p << item.text }
11
11
  end
12
12
  end
13
13
  end
14
14
 
15
15
  def ul_li(xml_ul, item)
16
16
  xml_ul.li **ul_li_attrs(item) do |xml_li|
17
+ xml_li.p(**attr_code(id_attr(item))) { |t| t << item.text }
17
18
  if item.blocks?
18
- xml_li.p(**id_attr(item)) { |t| t << item.text }
19
19
  xml_li << item.content
20
- else
21
- xml_li.p(**id_attr(item)) { |p| p << item.text }
22
20
  end
23
21
  end
24
22
  end
@@ -57,9 +55,8 @@ module Asciidoctor
57
55
  end
58
56
 
59
57
  def ol_attrs(node)
60
- attr_code(keep_attrs(node)
61
- .merge(id: Metanorma::Utils::anchor_or_uuid(node),
62
- type: olist_style(node.style)))
58
+ attr_code(id_attr(node).merge(keep_attrs(node)
59
+ .merge(type: olist_style(node.style))))
63
60
  end
64
61
 
65
62
  def olist(node)
@@ -79,22 +76,23 @@ module Asciidoctor
79
76
  end
80
77
  end
81
78
 
82
- def dd(dd, xml_dl)
83
- if dd.nil?
79
+ def dd(ddefn, xml_dl)
80
+ if ddefn.nil?
84
81
  xml_dl.dd
85
82
  return
86
83
  end
87
84
  xml_dl.dd do |xml_dd|
88
- xml_dd.p { |t| t << dd.text } if dd.text?
89
- xml_dd << dd.content if dd.blocks?
85
+ xml_dd.p { |t| t << ddefn.text } if ddefn.text?
86
+ xml_dd << ddefn.content if ddefn.blocks?
90
87
  end
91
88
  end
92
89
 
93
90
  def dl_attrs(node)
94
- attr_code(keep_attrs(node)
95
- .merge(id: Metanorma::Utils::anchor_or_uuid(node),
96
- metadata: node.option?("metadata") ? "true" : nil,
97
- key: node.option?("key") ? "true" : nil))
91
+ attr_code(id_attr(node).merge(keep_attrs(node)
92
+ .merge(
93
+ metadata: node.option?("metadata") ? "true" : nil,
94
+ key: node.option?("key") ? "true" : nil,
95
+ )))
98
96
  end
99
97
 
100
98
  def dlist(node)
@@ -28,32 +28,38 @@ module Asciidoctor
28
28
  # sleep need for windows because dot works in separate process and
29
29
  # plantuml process may finish earlier then dot, as result png file
30
30
  # maybe not created yet after plantuml finish
31
+ #
32
+ # # Warning: metanorma/metanorma-standoc#187
33
+ # Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
34
+ # This is why we need to copy and then unlink.
31
35
  def self.generate_file(parent, reader)
32
36
  localdir = Metanorma::Utils::localdir(parent.document)
33
37
  imagesdir = parent.document.attr("imagesdir")
34
38
  umlfile, outfile = save_plantuml parent, reader, localdir
35
- run(umlfile, outfile) or raise "No image output from PlantUML (#{umlfile}, #{outfile})!"
39
+ run(umlfile, outfile) or
40
+ raise "No image output from PlantUML (#{umlfile}, #{outfile})!"
36
41
  umlfile.unlink
37
42
 
38
- path = Pathname.new(localdir) + (imagesdir || "plantuml")
39
- File.writable?(localdir) or raise "Destination path #{path} not writable for PlantUML!"
40
- path.mkpath
41
- File.writable?(path) or raise "Destination path #{path} not writable for PlantUML!"
42
- # File.exist?(path) or raise "Destination path #{path} already exists for PlantUML!"
43
-
44
- # Warning: metanorma/metanorma-standoc#187
45
- # Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
46
- # This is why we need to copy and then unlink.
43
+ path = path_prep(localdir, imagesdir)
47
44
  filename = File.basename(outfile.to_s)
48
- FileUtils.cp(outfile, path) && outfile.unlink
45
+ FileUtils.cp(outfile, path) and outfile.unlink
49
46
 
50
47
  imagesdir ? filename : File.join(path, filename)
51
48
  end
52
49
 
50
+ def self.path_prep(localdir, imagesdir)
51
+ path = Pathname.new(localdir) + (imagesdir || "plantuml")
52
+ File.writable?(localdir) or
53
+ raise "Destination path #{path} not writable for PlantUML!"
54
+ path.mkpath
55
+ File.writable?(path) or
56
+ raise "Destination path #{path} not writable for PlantUML!"
57
+ # File.exist?(path) or raise "Destination path #{path} already exists for PlantUML!"
58
+ path
59
+ end
60
+
53
61
  def self.save_plantuml(_parent, reader, _localdir)
54
- src = reader.source
55
- reader.lines.first.sub(/\s+$/, "").match /^@startuml($| )/ or
56
- src = "@startuml\n#{src}\n@enduml\n"
62
+ src = prep_source(reader)
57
63
  /^@startuml (?<fn>[^\n]+)\n/ =~ src
58
64
  Tempfile.open(["plantuml", ".pml"], encoding: "utf-8") do |f|
59
65
  f.write(src)
@@ -62,6 +68,15 @@ module Asciidoctor
62
68
  end
63
69
  end
64
70
 
71
+ def self.prep_source(reader)
72
+ src = reader.source
73
+ reader.lines.first.sub(/\s+$/, "").match /^@startuml($| )/ or
74
+ src = "@startuml\n#{src}\n@enduml\n"
75
+ %r{@enduml\s*$}m.match?(src) or
76
+ raise "@startuml without matching @enduml in PlantUML!"
77
+ src
78
+ end
79
+
65
80
  def self.generate_attrs(attrs)
66
81
  %w(id align float title role width height alt)
67
82
  .inject({}) do |memo, key|
@@ -2,6 +2,18 @@ require "csv"
2
2
 
3
3
  module Asciidoctor
4
4
  module Standoc
5
+ class PreferredTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
6
+ use_dsl
7
+ named :preferred
8
+ parse_content_as :text
9
+ using_format :short
10
+
11
+ def process(parent, _target, attrs)
12
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
13
+ %{<preferred><expression><name>#{out}</name></expression></preferred>}
14
+ end
15
+ end
16
+
5
17
  class AltTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
6
18
  use_dsl
7
19
  named :alt
@@ -9,8 +21,9 @@ module Asciidoctor
9
21
  using_format :short
10
22
 
11
23
  def process(parent, _target, attrs)
12
- out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
13
- %{<admitted>#{out}</admitted>}
24
+ out = Asciidoctor::Inline.new(parent, :quoted,
25
+ attrs["text"]).convert
26
+ %{<admitted><expression><name>#{out}</name></expression></admitted>}
14
27
  end
15
28
  end
16
29
 
@@ -21,8 +34,9 @@ module Asciidoctor
21
34
  using_format :short
22
35
 
23
36
  def process(parent, _target, attrs)
24
- out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
25
- %{<deprecates>#{out}</deprecates>}
37
+ out = Asciidoctor::Inline.new(parent, :quoted,
38
+ attrs["text"]).convert
39
+ %{<deprecates><expression><name>#{out}</name></expression></deprecates>}
26
40
  end
27
41
  end
28
42
 
@@ -33,7 +47,8 @@ module Asciidoctor
33
47
  using_format :short
34
48
 
35
49
  def process(parent, _target, attrs)
36
- out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
50
+ out = Asciidoctor::Inline.new(parent, :quoted,
51
+ attrs["text"]).convert
37
52
  %{<domain>#{out}</domain>}
38
53
  end
39
54
  end
@@ -116,9 +131,12 @@ module Asciidoctor
116
131
 
117
132
  def process(parent, target, _attrs)
118
133
  attrs = preprocess_attrs(target)
119
- term = Asciidoctor::Inline.new(parent, :quoted, attrs[:term]).convert
120
- word = Asciidoctor::Inline.new(parent, :quoted, attrs[:word]).convert
121
- xref = Asciidoctor::Inline.new(parent, :quoted, attrs[:render]).convert
134
+ term = Asciidoctor::Inline.new(parent, :quoted,
135
+ attrs[:term]).convert
136
+ word = Asciidoctor::Inline.new(parent, :quoted,
137
+ attrs[:word]).convert
138
+ xref = Asciidoctor::Inline.new(parent, :quoted,
139
+ attrs[:render]).convert
122
140
  opt = generate_attrs(attrs[:opt] || [])
123
141
  if attrs[:id] then "<concept#{opt} key='#{attrs[:id]}'><refterm>"\
124
142
  "#{term}</refterm><renderterm>#{word}</renderterm>"\
@@ -130,5 +148,34 @@ module Asciidoctor
130
148
  raise("processing {{#{target}}}: #{e.message}")
131
149
  end
132
150
  end
151
+
152
+ # Possibilities:
153
+ # related:relation[<<id>>, term]
154
+ # related:relation[<<termbase:id>>, term]
155
+ # related:relation[term] equivalent to a crossreference to term:[term]
156
+ class RelatedTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
157
+ use_dsl
158
+ named :related
159
+ parse_content_as :text
160
+
161
+ def preprocess_attrs(target)
162
+ m = /^(?<id>&lt;&lt;.+?&gt;&gt;, ?)?(?<rest>.*)$/.match(target)
163
+ { id: m[:id]&.sub(/^&lt;&lt;/, "")&.sub(/&gt;&gt;, ?$/, ""),
164
+ term: m[:rest] }
165
+ end
166
+
167
+ def process(parent, target, attrs)
168
+ out = preprocess_attrs(attrs["text"])
169
+ term = Asciidoctor::Inline.new(parent, :quoted,
170
+ out[:term]).convert
171
+ if out[:id] then "<related type='#{target}' key='#{out[:id]}'>"\
172
+ "<refterm>#{term}</refterm></related>"
173
+ else "<related type='#{target}'><termxref>#{term}</termxref>"\
174
+ "<xrefrender>#{term}</xrefrender></related>"
175
+ end
176
+ rescue StandardError => e
177
+ raise("processing related:#{target}[#{attrs['text']}]: #{e.message}")
178
+ end
179
+ end
133
180
  end
134
181
  end
@@ -161,7 +161,7 @@ module Asciidoctor
161
161
 
162
162
  def refitem1(xml, _item, match)
163
163
  code = analyse_ref_code(match[:code])
164
- unless code[:id] && code[:numeric] || code[:nofetch]
164
+ unless (code[:id] && code[:numeric]) || code[:nofetch]
165
165
  ref = fetch_ref(xml, code[:id],
166
166
  match.names.include?("year") ? match[:year] : nil,
167
167
  title: match[:text],
@@ -16,16 +16,14 @@ module Asciidoctor
16
16
  end
17
17
 
18
18
  def bibliography_parse(attrs, xml, node)
19
- node.option? "bibitem" and return bibitem_parse(attrs, xml, node)
20
- node.attr("style") == "bibliography" or
21
- @log.add("AsciiDoc Input", node, "Section not marked up as [bibliography]!")
19
+ x = biblio_prep(attrs, xml, node) and return x
22
20
  @biblio = true
23
- xml.references **attr_code(attrs.merge(
24
- normative: node.attr("normative") || false)) do |xml_section|
25
- xml_section.title { |t| t << node.title }
26
- xml_section << node.content
27
- end
28
- @biblio = false
21
+ attrs = attrs.merge(normative: node.attr("normative") || false)
22
+ xml.references **attr_code(attrs) do |xml_section|
23
+ xml_section.title { |t| t << node.title }
24
+ xml_section << node.content
25
+ end
26
+ @biblio = false
29
27
  end
30
28
 
31
29
  def bibitem_parse(attrs, xml, node)
@@ -33,15 +31,14 @@ module Asciidoctor
33
31
  biblio = @biblio
34
32
  @biblio = false
35
33
  @norm_ref = false
36
- clause_parse(attrs, xml, node)
34
+ ret = clause_parse(attrs, xml, node)
37
35
  @biblio = biblio
38
36
  @norm_ref = norm_ref
37
+ ret
39
38
  end
40
39
 
41
40
  def norm_ref_parse(attrs, xml, node)
42
- node.option? "bibitem" and return bibitem_parse(attrs, xml, node)
43
- node.attr("style") == "bibliography" or
44
- @log.add("AsciiDoc Input", node, "Section not marked up as [bibliography]!")
41
+ x = biblio_prep(attrs, xml, node) and return x
45
42
  @norm_ref = true
46
43
  attrs = attrs.merge(normative: node.attr("normative") || true)
47
44
  xml.references **attr_code(attrs) do |xml_section|
@@ -51,6 +48,17 @@ module Asciidoctor
51
48
  @norm_ref = false
52
49
  end
53
50
 
51
+ def biblio_prep(attrs, xml, node)
52
+ if node.option? "bibitem"
53
+ bibitem_parse(attrs, xml, node)
54
+ else
55
+ node.attr("style") == "bibliography" or
56
+ @log.add("AsciiDoc Input", node,
57
+ "Section not marked up as [bibliography]!")
58
+ nil
59
+ end
60
+ end
61
+
54
62
  def global_ievcache_name
55
63
  "#{Dir.home}/.iev/cache"
56
64
  end
@@ -74,7 +82,7 @@ module Asciidoctor
74
82
  xml
75
83
  rescue RelatonBib::RequestError
76
84
  @log.add("Bibliography", nil, "Could not retrieve #{code}: "\
77
- "no access to online site")
85
+ "no access to online site")
78
86
  nil
79
87
  end
80
88
 
@@ -87,10 +95,10 @@ module Asciidoctor
87
95
  unless xml.at("/bibitem/title[text()]")
88
96
  @log.add("Bibliography", nil,
89
97
  "ERROR: No title retrieved for #{code}")
90
- xml.root << "<title>#{title || "(MISSING TITLE)"}</title>"
98
+ xml.root << "<title>#{title || '(MISSING TITLE)'}</title>"
91
99
  end
92
100
  usrlbl and xml.at("/bibitem/docidentifier").next =
93
- "<docidentifier type='metanorma'>#{mn_code(usrlbl)}</docidentifier>"
101
+ "<docidentifier type='metanorma'>#{mn_code(usrlbl)}</docidentifier>"
94
102
  end
95
103
 
96
104
  def smart_render_xml(xml, code, opts)
@@ -113,7 +121,7 @@ module Asciidoctor
113
121
  @bibdb = Relaton::DbCache.init_bib_caches(
114
122
  local_cache: local,
115
123
  flush_caches: node.attr("flush-caches"),
116
- global_cache: global
124
+ global_cache: global,
117
125
  )
118
126
  end
119
127
 
@@ -128,7 +136,7 @@ module Asciidoctor
128
136
  FileUtils.rm_f @iev_localname unless @iev_localname.nil?
129
137
  end
130
138
  end
131
- #@iev = Iev::Db.new(globalname, localname) unless @no_isobib
139
+ # @iev = Iev::Db.new(globalname, localname) unless @no_isobib
132
140
  end
133
141
  end
134
142
  end
@@ -58,6 +58,14 @@
58
58
  <optional>
59
59
  <attribute name="type"/>
60
60
  </optional>
61
+ <optional>
62
+ <attribute name="tag"/>
63
+ </optional>
64
+ <optional>
65
+ <attribute name="multilingual-rendering">
66
+ <ref name="MultilingualRenderingType"/>
67
+ </attribute>
68
+ </optional>
61
69
  <optional>
62
70
  <ref name="reqtitle"/>
63
71
  </optional>
@@ -101,7 +109,9 @@
101
109
  </define>
102
110
  <define name="label">
103
111
  <element name="label">
104
- <text/>
112
+ <oneOrMore>
113
+ <ref name="TextElement"/>
114
+ </oneOrMore>
105
115
  </element>
106
116
  </define>
107
117
  <define name="subject">
@@ -175,8 +185,19 @@
175
185
  <data type="boolean"/>
176
186
  </attribute>
177
187
  </optional>
188
+ <optional>
189
+ <attribute name="tag"/>
190
+ </optional>
191
+ <optional>
192
+ <attribute name="multilingual-rendering">
193
+ <ref name="MultilingualRenderingType"/>
194
+ </attribute>
195
+ </optional>
178
196
  <oneOrMore>
179
- <ref name="BasicBlock"/>
197
+ <choice>
198
+ <ref name="BasicBlock"/>
199
+ <ref name="component"/>
200
+ </choice>
180
201
  </oneOrMore>
181
202
  </define>
182
203
  <define name="ObligationType">
@@ -18,7 +18,7 @@ module Asciidoctor
18
18
  def sectiontype(node, level = true)
19
19
  ret = sectiontype1(node)
20
20
  ret1 = sectiontype_streamline(ret)
21
- return ret1 if "symbols and abbreviated terms" == ret1
21
+ return ret1 if ret1 == "symbols and abbreviated terms"
22
22
  return nil unless !level || node.level == 1
23
23
  return nil if @seen_headers.include? ret
24
24
 
@@ -49,7 +49,8 @@ module Asciidoctor
49
49
  script: node.attributes["script"],
50
50
  number: node.attributes["number"],
51
51
  type: node.attributes["type"],
52
- annex: (if (node.attr("style") == "appendix" || node.role == "appendix") &&
52
+ annex: (if (node.attr("style") == "appendix" ||
53
+ node.role == "appendix") &&
53
54
  node.level == 1
54
55
  true
55
56
  end),
@@ -84,13 +85,11 @@ module Asciidoctor
84
85
  else
85
86
  if @term_def then term_def_subclause_parse(a, xml, node)
86
87
  elsif @definitions then symbols_parse(a, xml, node)
87
- elsif @norm_ref then norm_ref_parse(a, xml, node)
88
- elsif @biblio then bibliography_parse(a, xml, node)
89
- elsif node.attr("style") == "bibliography" && sectiontype(node, false) == "normative references"
88
+ elsif @norm_ref ||
89
+ (node.attr("style") == "bibliography" &&
90
+ sectiontype(node, false) == "normative references")
90
91
  norm_ref_parse(a, xml, node)
91
- elsif node.attr("style") == "bibliography" && sectiontype(node, false) == "bibliography"
92
- bibliography_parse(a, xml, node)
93
- elsif node.attr("style") == "bibliography"
92
+ elsif @biblio || node.attr("style") == "bibliography"
94
93
  bibliography_parse(a, xml, node)
95
94
  elsif node.attr("style") == "abstract"
96
95
  abstract_parse(a, xml, node)
@@ -118,7 +117,9 @@ module Asciidoctor
118
117
  def preamble(node)
119
118
  noko do |xml|
120
119
  xml.foreword **attr_code(section_attributes(node)) do |xml_abstract|
121
- xml_abstract.title { |t| t << (node.blocks[0].title || @i18n.foreword) }
120
+ xml_abstract.title do |t|
121
+ t << (node.blocks[0].title || @i18n.foreword)
122
+ end
122
123
  content = node.content
123
124
  xml_abstract << content
124
125
  end
@@ -143,7 +144,7 @@ module Asciidoctor
143
144
  end
144
145
 
145
146
  def clause_parse(attrs, xml, node)
146
- attrs["inline-header".to_sym] = node.option? "inline-header"
147
+ attrs[:"inline-header"] = node.option? "inline-header"
147
148
  attrs[:bibitem] = true if node.option? "bibitem"
148
149
  attrs[:level] = node.attr("level")
149
150
  set_obligation(attrs, node)
@@ -154,7 +155,7 @@ module Asciidoctor
154
155
  end
155
156
 
156
157
  def annex_parse(attrs, xml, node)
157
- attrs["inline-header".to_sym] = node.option? "inline-header"
158
+ attrs[:"inline-header"] = node.option? "inline-header"
158
159
  set_obligation(attrs, node)
159
160
  xml.annex **attr_code(attrs) do |xml_section|
160
161
  xml_section.title { |name| name << node.title }
@@ -180,7 +181,7 @@ module Asciidoctor
180
181
 
181
182
  def acknowledgements_parse(attrs, xml, node)
182
183
  xml.acknowledgements **attr_code(attrs) do |xml_section|
183
- xml_section.title { |t| t << node.title || @i18n.acknowledgements }
184
+ xml_section.title { |t| (t << node.title) || @i18n.acknowledgements }
184
185
  content = node.content
185
186
  xml_section << content
186
187
  end
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true.
2
+ require "asciidoctor/standoc/utils"
3
+
2
4
 
3
5
  module Asciidoctor
4
6
  module Standoc
@@ -13,7 +15,7 @@ module Asciidoctor
13
15
  def initialize(xmldoc, log)
14
16
  @xmldoc = xmldoc
15
17
  @log = log
16
- @termlookup = { term: {}, symbol: {} }
18
+ @termlookup = { term: {}, symbol: {}, secondary2primary: {} }
17
19
  @idhash = {}
18
20
  end
19
21
 
@@ -22,6 +24,7 @@ module Asciidoctor
22
24
  @termlookup = replace_automatic_generated_ids_terms
23
25
  set_termxref_tags_target
24
26
  concept_cleanup
27
+ related_cleanup
25
28
  end
26
29
 
27
30
  private
@@ -29,6 +32,19 @@ module Asciidoctor
29
32
  def concept_cleanup
30
33
  xmldoc.xpath("//concept").each do |n|
31
34
  n.delete("type")
35
+ refterm = n.at("./refterm") or next
36
+ p = @termlookup[:secondary2primary][refterm.text] and
37
+ refterm.children = p
38
+ end
39
+ end
40
+
41
+ def related_cleanup
42
+ xmldoc.xpath("//related").each do |n|
43
+ refterm = n.at("./refterm") or next
44
+ p = @termlookup[:secondary2primary][refterm.text] and
45
+ refterm.children = p
46
+ refterm.replace("<preferred><expression><name>#{refterm.children.to_xml}"\
47
+ "</name></expression></preferred>")
32
48
  end
33
49
  end
34
50
 
@@ -47,8 +63,7 @@ module Asciidoctor
47
63
  remove_missing_ref(node, target)
48
64
  next
49
65
  end
50
- x = node.at("../xrefrender")
51
- modify_ref_node(x, target)
66
+ x = node.at("../xrefrender") and modify_ref_node(x, target)
52
67
  node.name = "refterm"
53
68
  end
54
69
  end
@@ -66,12 +81,12 @@ module Asciidoctor
66
81
  %(Error: Term reference in `term[#{target}]` missing: \
67
82
  "#{target}" is not defined in document))
68
83
  node.name = "strong"
69
- node.at("../xrefrender").remove
84
+ node&.at("../xrefrender")&.remove
70
85
  display = node&.at("../renderterm")&.remove&.children
71
86
  display = [] if display.nil? || display&.to_xml == node.text
72
87
  d = display.empty? ? "" : ", display <tt>#{display.to_xml}</tt>"
73
88
  node.children = "term <tt>#{node.text}</tt>#{d} "\
74
- "not resolved via ID <tt>#{target}</tt>"
89
+ "not resolved via ID <tt>#{target}</tt>"
75
90
  end
76
91
 
77
92
  def remove_missing_ref_symbol(node, target)
@@ -79,12 +94,12 @@ module Asciidoctor
79
94
  %(Error: Symbol reference in `symbol[#{target}]` missing: \
80
95
  "#{target}" is not defined in document))
81
96
  node.name = "strong"
82
- node.at("../xrefrender").remove
97
+ node&.at("../xrefrender")&.remove
83
98
  display = node&.at("../renderterm")&.remove&.children
84
99
  display = [] if display.nil? || display&.to_xml == node.text
85
100
  d = display.empty? ? "" : ", display <tt>#{display.to_xml}</tt>"
86
101
  node.children = "symbol <tt>#{node.text}</tt>#{d} "\
87
- "not resolved via ID <tt>#{target}</tt>"
102
+ "not resolved via ID <tt>#{target}</tt>"
88
103
  end
89
104
 
90
105
  def modify_ref_node(node, target)
@@ -92,24 +107,40 @@ module Asciidoctor
92
107
  s = termlookup[:symbol][target]
93
108
  t = termlookup[:term][target]
94
109
  type = node.parent["type"]
95
- if type == "term" || !type && t
110
+ if type == "term" || ((!type || node.parent.name == "related") && t)
96
111
  node["target"] = t
97
- elsif type == "symbol" || !type && s
112
+ elsif type == "symbol" ||
113
+ ((!type || node.parent.name == "related") && s)
98
114
  node["target"] = s
99
115
  end
100
116
  end
101
117
 
102
118
  def replace_automatic_generated_ids_terms
103
119
  r = xmldoc.xpath("//term").each.with_object({}) do |n, res|
104
- normalize_id_and_memorize(n, res, "./preferred", "term")
120
+ normalize_id_and_memorize(n, res, "./preferred//name",
121
+ "term")
105
122
  end
106
123
  s = xmldoc.xpath("//definitions//dt").each.with_object({}) do |n, res|
107
124
  normalize_id_and_memorize(n, res, ".", "symbol")
108
125
  end
109
- { term: r, symbol: s }
126
+ { term: r, symbol: s, secondary2primary: pref_secondary2primary }
127
+ end
128
+
129
+ def pref_secondary2primary
130
+ xmldoc.xpath("//term").each.with_object({}) do |n, res|
131
+ n.xpath("./preferred//name").each_with_index do |p, i|
132
+ i.zero? and term = p.text
133
+ i.positive? and res[p.text] = term
134
+ end
135
+ end
110
136
  end
111
137
 
112
138
  def normalize_id_and_memorize(node, res_table, text_selector, prefix)
139
+ normalize_id_and_memorize_init(node, res_table, text_selector, prefix)
140
+ memorize_other_pref_terms(node, res_table, text_selector)
141
+ end
142
+
143
+ def normalize_id_and_memorize_init(node, res_table, text_selector, prefix)
113
144
  term_text = normalize_ref_id(node.at(text_selector).text)
114
145
  unless AUTOMATIC_GENERATED_ID_REGEXP.match(node["id"]).nil? &&
115
146
  !node["id"].nil?
@@ -120,6 +151,14 @@ module Asciidoctor
120
151
  res_table[term_text] = node["id"]
121
152
  end
122
153
 
154
+ def memorize_other_pref_terms(node, res_table, text_selector)
155
+ node.xpath(text_selector).each_with_index do |p, i|
156
+ next unless i.positive?
157
+
158
+ res_table[normalize_ref_id(p.text)] = node["id"]
159
+ end
160
+ end
161
+
123
162
  def normalize_ref_id(text)
124
163
  Metanorma::Utils::to_ncname(text.downcase.gsub(/[[:space:]]/, "-"))
125
164
  end
@@ -69,7 +69,7 @@ module Asciidoctor
69
69
 
70
70
  def term_def_subclause_parse1(attrs, xml, node)
71
71
  xml.term **attr_code(attrs) do |xml_section|
72
- xml_section.preferred { |name| name << node.title }
72
+ term_designation(xml_section, node, "preferred", node.title)
73
73
  xml_section << node.content
74
74
  end
75
75
  end
@@ -84,6 +84,14 @@ module Asciidoctor
84
84
  end
85
85
  end
86
86
 
87
+ def term_designation(xml, _node, tag, text)
88
+ xml.send tag do |p|
89
+ p.expression do |e|
90
+ e.name { |name| name << text }
91
+ end
92
+ end
93
+ end
94
+
87
95
  def term_source_attrs(_node, seen_xref)
88
96
  { case: seen_xref.children[0]["case"],
89
97
  droploc: seen_xref.children[0]["droploc"],
@@ -124,7 +132,9 @@ module Asciidoctor
124
132
  def termsource(node)
125
133
  matched = extract_termsource_refs(node.content, node) || return
126
134
  noko do |xml|
127
- attrs = { status: matched[:text] ? "modified" : "identical" }
135
+ status = node.attr("status") ||
136
+ (matched[:text] ? "modified" : "identical")
137
+ attrs = { status: status, type: node.attr("type") || "authoritative" }
128
138
  xml.termsource **attrs do |xml_t|
129
139
  seen_xref = Nokogiri::XML.fragment(matched[:xref])
130
140
  add_term_source(node, xml_t, seen_xref, matched)