metanorma-standoc 1.10.7 → 1.11.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 (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)