metanorma-standoc 1.10.5 → 1.10.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd98ba81df1c144552167e677b04d6152d838de0ea2d539a6bc7bde2a4b7f235
4
- data.tar.gz: 68d9afff164047bf12f97ac23735cc1d61503172ae8656795393314d127223b6
3
+ metadata.gz: 5982aeb8f67b56ccf4da3cf8589b3855fda38e646650074f8804d8e94de9a791
4
+ data.tar.gz: 6efa1a3eb9fce06dfcce893c835152a2ee642418cd35f06981d4a3d7e4408832
5
5
  SHA512:
6
- metadata.gz: 611ba153c4160486b0ea51eb1564e09cd81d02f6ca6d5a075e3f38cf321321f2e019ba538341786bd4fe01eac9ef53e71ddc5cc19fdccb4e69189d9e7a720955
7
- data.tar.gz: 0acb358132209888abe3a276c16abcfdf142570fd271712960e64e02db487df9bb39081a1f4e08da7347777a71240b57b2d8f6dda7d980523981efe5a838495c
6
+ metadata.gz: 4d4cd2f1c480899fe9221482e53bff2702d96cc1688937b15b993eddcddbca80cb7c5d931913ceaa5e06f9c0b6a70723fc3a84c275a259c5a9bb21fb8b3d42fe
7
+ data.tar.gz: 61cf1ff021b2f6365ad83311478732ed431dc2f3328e11ec1a96ebfa264c463ded7198779a86928bb3a82ce4153f4934b96aeccccff5d136d3018cd9b6025173
@@ -174,6 +174,10 @@ module Asciidoctor
174
174
  outputs(node, ret) unless node.attr("nodoc") || !node.attr("docfile")
175
175
  clean_exit
176
176
  ret
177
+ rescue StandardError => e
178
+ @log.add("Fatal Error", nil, e.message)
179
+ clean_exit
180
+ raise e
177
181
  end
178
182
 
179
183
  def version
@@ -33,6 +33,7 @@ module Asciidoctor
33
33
  role = node.role || node.attr("style")
34
34
  reqt_subpart(role) and return requirement_subpart(node)
35
35
  role == "form" and return form(node)
36
+ role == "definition" and return termdefinition(node)
36
37
  result = []
37
38
  node.blocks.each do |b|
38
39
  result << send(b.context, b)
@@ -92,7 +93,9 @@ module Asciidoctor
92
93
  return pseudocode_example(node) if role == "pseudocode"
93
94
  return svgmap_example(node) if role == "svgmap"
94
95
  return form(node) if role == "form"
96
+ return termdefinition(node) if role == "definition"
95
97
 
98
+ reqt_subpart(role) and return requirement_subpart(node)
96
99
  example_proper(node)
97
100
  end
98
101
 
@@ -7,7 +7,8 @@ module Asciidoctor
7
7
  def para_cleanup(xmldoc)
8
8
  ["//p[not(ancestor::bibdata)]", "//ol[not(ancestor::bibdata)]",
9
9
  "//ul[not(ancestor::bibdata)]", "//quote[not(ancestor::bibdata)]",
10
- "//note[not(ancestor::bibitem or ancestor::table or ancestor::bibdata)]"].each do |w|
10
+ "//note[not(ancestor::bibitem or "\
11
+ "ancestor::table or ancestor::bibdata)]"].each do |w|
11
12
  inject_id(
12
13
  xmldoc, w
13
14
  )
@@ -73,9 +74,11 @@ module Asciidoctor
73
74
  def notes_table_cleanup(xmldoc)
74
75
  nomatches = false
75
76
  until nomatches
76
- q = "//table/following-sibling::*[1][self::note]"
77
+ q = "//table/following-sibling::*[1]"\
78
+ "[self::note[not(@keep-separate = 'true')]]"
77
79
  nomatches = true
78
80
  xmldoc.xpath(q).each do |n|
81
+ n.delete("keep-separate")
79
82
  n.previous_element << n.remove
80
83
  nomatches = false
81
84
  end
@@ -86,14 +86,19 @@ module Asciidoctor
86
86
  while (m = LOCALITY_RE.match text)
87
87
  ref = m[:ref] ? "<referenceFrom>#{tq m[:ref]}</referenceFrom>" : ""
88
88
  refto = m[:to] ? "<referenceTo>#{tq m[:to]}</referenceTo>" : ""
89
- loc = m[:locality]&.downcase || m[:locality2]&.downcase
90
- b.add_child("<locality type='#{loc}'>#{ref}#{refto}</locality>")
89
+ b.add_child("<locality type='#{locality_label(m)}'>#{ref}#{refto}"\
90
+ "</locality>")
91
91
  text = m[:text]
92
92
  b = elem.add_child("<localityStack/>").first if m[:punct] == ";"
93
93
  end
94
94
  elem.add_child(text) if text
95
95
  end
96
96
 
97
+ def locality_label(match)
98
+ loc = match[:locality] || match[:locality2]
99
+ /^locality:/.match?(loc) ? loc : loc&.downcase
100
+ end
101
+
97
102
  def xref_to_eref(elem)
98
103
  elem["bibitemid"] = elem["target"]
99
104
  unless elem["citeas"] = @anchors&.dig(elem["target"], :xref)
@@ -203,7 +208,8 @@ module Asciidoctor
203
208
  end
204
209
 
205
210
  IDREF = "//*/@id | //review/@from | //review/@to | "\
206
- "//callout/@target | //citation/@bibitemid | //eref/@bibitemid".freeze
211
+ "//callout/@target | //citation/@bibitemid | "\
212
+ "//eref/@bibitemid".freeze
207
213
 
208
214
  def anchor_cleanup(elem)
209
215
  anchor_cleanup1(elem)
@@ -3,37 +3,61 @@ module Asciidoctor
3
3
  module Cleanup
4
4
  def requirement_cleanup(xmldoc)
5
5
  requirement_metadata(xmldoc)
6
- requirement_descriptions(xmldoc)
7
6
  requirement_inherit(xmldoc)
7
+ requirement_descriptions(xmldoc)
8
8
  end
9
9
 
10
10
  REQRECPER = "//requirement | //recommendation | //permission".freeze
11
11
 
12
12
  def requirement_inherit(xmldoc)
13
13
  xmldoc.xpath(REQRECPER).each do |r|
14
- ins = r.at("./classification") ||
15
- r.at("./description | ./measurementtarget | ./specification | "\
16
- "./verification | ./import | ./description | ./requirement | "\
17
- "./recommendation | ./permission | ./component")
14
+ ins = requirement_inherit_insert(r)
18
15
  r.xpath("./*//inherit").each { |i| ins.previous = i }
19
16
  end
20
17
  end
21
18
 
19
+ def requirement_inherit_insert(reqt)
20
+ ins = reqt.at("./classification") || reqt.at(
21
+ "./description | ./measurementtarget | ./specification | "\
22
+ "./verification | ./import | ./description | ./component | "\
23
+ "./requirement | ./recommendation | ./permission",
24
+ ) and return ins
25
+ requirement_inherit_insert1(reqt)
26
+ end
27
+
28
+ def requirement_inherit_insert1(reqt)
29
+ if t = reqt.at("./title")
30
+ t.next = " "
31
+ t.next
32
+ else
33
+ if reqt.children.empty? then reqt.add_child(" ")
34
+ else reqt.children.first.previous = " "
35
+ end
36
+ reqt.children.first
37
+ end
38
+ end
39
+
22
40
  def requirement_descriptions(xmldoc)
23
41
  xmldoc.xpath(REQRECPER).each do |r|
42
+ r.xpath(".//p[not(./*)][normalize-space(.)='']").each(&:remove)
24
43
  r.children.each do |e|
25
- unless e.element? && (reqt_subpart(e.name) ||
26
- %w(requirement recommendation permission).include?(e.name))
27
- next if e.text.strip.empty?
28
- t = Nokogiri::XML::Element.new("description", r)
29
- e.before(t)
30
- t.children = e.remove
31
- end
44
+ requirement_description_wrap(r, e)
32
45
  end
33
46
  requirement_description_cleanup1(r)
34
47
  end
35
48
  end
36
49
 
50
+ def requirement_description_wrap(reqt, text)
51
+ return if text.element? && (reqt_subpart(text.name) ||
52
+ %w(requirement recommendation
53
+ permission).include?(text.name)) ||
54
+ text.text.strip.empty?
55
+
56
+ t = Nokogiri::XML::Element.new("description", reqt)
57
+ text.before(t)
58
+ t.children = text.remove
59
+ end
60
+
37
61
  def requirement_description_cleanup1(reqt)
38
62
  while d = reqt.at("./description[following-sibling::*[1]"\
39
63
  "[self::description]]")
@@ -52,17 +76,30 @@ module Asciidoctor
52
76
  end
53
77
  end
54
78
 
79
+ def requirement_metadata1_tags
80
+ %w(label subject inherit)
81
+ end
82
+
55
83
  def requirement_metadata1(reqt, dlist)
56
84
  unless ins = reqt.at("./title")
57
85
  reqt.children.first.previous = " "
58
86
  ins = reqt.children.first
59
87
  end
60
- %w(label subject inherit).each do |a|
88
+ %w(obligation model type).each do |a|
89
+ reqt_dl_to_attrs(reqt, dlist, a)
90
+ end
91
+ requirement_metadata1_tags.each do |a|
61
92
  ins = reqt_dl_to_elems(ins, reqt, dlist, a)
62
93
  end
63
94
  reqt_dl_to_classif(ins, reqt, dlist)
64
95
  end
65
96
 
97
+ def reqt_dl_to_attrs(reqt, dlist, name)
98
+ e = dlist.at("./dt[text()='#{name}']") or return
99
+ val = e.at("./following::dd/p") || e.at("./following::dd") or return
100
+ reqt[name] = val.text
101
+ end
102
+
66
103
  def reqt_dl_to_elems(ins, reqt, dlist, name)
67
104
  if a = reqt.at("./#{name}[last()]")
68
105
  ins = a
@@ -77,16 +114,16 @@ module Asciidoctor
77
114
  end
78
115
 
79
116
  def reqt_dl_to_classif(ins, reqt, dlist)
80
- if a = reqt.at("./classification[last()]")
81
- ins = a
82
- end
117
+ if a = reqt.at("./classification[last()]") then ins = a end
83
118
  dlist.xpath("./dt[text()='classification']").each do |e|
84
119
  val = e.at("./following::dd/p") || e.at("./following::dd")
85
120
  req_classif_parse(val.text).each do |r|
86
121
  ins.next = "<classification><tag>#{r[0]}</tag>"\
87
122
  "<value>#{r[1]}</value></classification>"
123
+ ins = ins.next
88
124
  end
89
125
  end
126
+ ins
90
127
  end
91
128
  end
92
129
  end
@@ -29,7 +29,7 @@ module Asciidoctor
29
29
  end
30
30
 
31
31
  def termdefinition_cleanup(xmldoc)
32
- xmldoc.xpath("//term").each do |d|
32
+ xmldoc.xpath("//term[not(definition)]").each do |d|
33
33
  first_child = d.at("./p | ./figure | ./formula") || next
34
34
  t = Nokogiri::XML::Element.new("definition", xmldoc)
35
35
  first_child.replace(t)
@@ -50,6 +50,7 @@ module Asciidoctor
50
50
  inline_macro Asciidoctor::Standoc::FormOptionMacro
51
51
  inline_macro Asciidoctor::Standoc::ToCInlineMacro
52
52
  inline_macro Metanorma::Plugin::Lutaml::LutamlFigureInlineMacro
53
+ inline_macro Metanorma::Plugin::Lutaml::LutamlTableInlineMacro
53
54
  block_macro Metanorma::Plugin::Lutaml::LutamlDiagramBlockMacro
54
55
  block Asciidoctor::Standoc::ToDoAdmonitionBlock
55
56
  treeprocessor Asciidoctor::Standoc::ToDoInlineAdmonitionBlock
@@ -990,6 +990,16 @@
990
990
  <data type="boolean"/>
991
991
  </attribute>
992
992
  </optional>
993
+ <optional>
994
+ <attribute name="linkmention">
995
+ <data type="boolean"/>
996
+ </attribute>
997
+ </optional>
998
+ <optional>
999
+ <attribute name="linkref">
1000
+ <data type="boolean"/>
1001
+ </attribute>
1002
+ </optional>
993
1003
  <optional>
994
1004
  <element name="refterm">
995
1005
  <zeroOrMore>
@@ -1700,7 +1710,9 @@
1700
1710
  <zeroOrMore>
1701
1711
  <ref name="termgrammar"/>
1702
1712
  </zeroOrMore>
1703
- <ref name="definition"/>
1713
+ <oneOrMore>
1714
+ <ref name="termdefinition"/>
1715
+ </oneOrMore>
1704
1716
  <zeroOrMore>
1705
1717
  <ref name="termnote"/>
1706
1718
  </zeroOrMore>
@@ -1763,7 +1775,7 @@
1763
1775
  </oneOrMore>
1764
1776
  </element>
1765
1777
  </define>
1766
- <define name="definition">
1778
+ <define name="termdefinition">
1767
1779
  <element name="definition">
1768
1780
  <oneOrMore>
1769
1781
  <choice>
@@ -1772,6 +1784,9 @@
1772
1784
  <ref name="formula"/>
1773
1785
  </choice>
1774
1786
  </oneOrMore>
1787
+ <zeroOrMore>
1788
+ <ref name="termsource"/>
1789
+ </zeroOrMore>
1775
1790
  </element>
1776
1791
  </define>
1777
1792
  <define name="termnote">
@@ -81,15 +81,24 @@ module Asciidoctor
81
81
  def preprocess_attrs(target)
82
82
  m = /^(?<id>&lt;&lt;.+?&gt;&gt;)?(?<rest>.*)$/.match(target)
83
83
  ret = { id: m[:id]&.sub(/^&lt;&lt;/, "")&.sub(/&gt;&gt;$/, "") }
84
- if m2 = /^(?<rest>.*?)(?<opt>,option=.+)$/.match(m[:rest].sub(/^,/, ""))
85
- ret[:opt] = CSV.parse_line(m2[:opt].sub(/^,option=/, "")
84
+ if m2 = /^(?<rest>.*?)(?<opt>,opt(ion)?s=.+)$/
85
+ .match(m[:rest].sub(/^,/, ""))
86
+ ret[:opt] = CSV.parse_line(m2[:opt].sub(/^,opt(ion)?s=/, "")
86
87
  .sub(/^"(.+)"$/, "\\1").sub(/^'(.+)'$/, "\\1"))
87
- attrs = CSV.parse_line(m2[:rest]) || []
88
+ begin
89
+ attrs = CSV.parse_line(m2[:rest]) || []
90
+ rescue StandardError
91
+ raise "error processing #{m2[:rest]} as CSV"
92
+ end
88
93
  else
89
- attrs = CSV.parse_line(m[:rest].sub(/^,/, "")) || []
94
+ begin
95
+ attrs = CSV.parse_line(m[:rest].sub(/^,/, "")) || []
96
+ rescue StandardError
97
+ raise "error processing #{m[:rest]} as CSV"
98
+ end
90
99
  end
91
100
  ret.merge(term: attrs[0], word: attrs[1] || attrs[0],
92
- xrefrender: attrs[2])
101
+ render: attrs[2])
93
102
  end
94
103
 
95
104
  def generate_attrs(opts)
@@ -98,21 +107,27 @@ module Asciidoctor
98
107
  opts.include?("noref") and ret += " ref='false'"
99
108
  opts.include?("ital") and ret += " ital='true'"
100
109
  opts.include?("ref") and ret += " ref='true'"
110
+ opts.include?("nolinkmention") and ret += " linkmention='false'"
111
+ opts.include?("linkmention") and ret += " linkmention='true'"
112
+ opts.include?("nolinkref") and ret += " linkref='false'"
113
+ opts.include?("linkref") and ret += " linkref='true'"
101
114
  ret
102
115
  end
103
116
 
104
117
  def process(parent, target, _attrs)
105
118
  attrs = preprocess_attrs(target)
106
- termout = Asciidoctor::Inline.new(parent, :quoted, attrs[:term]).convert
107
- wordout = Asciidoctor::Inline.new(parent, :quoted, attrs[:word]).convert
108
- xrefout = Asciidoctor::Inline.new(parent, :quoted,
109
- attrs[:xrefrender]).convert
110
- optout = generate_attrs(attrs[:opt] || [])
111
- attrs[:id] and return "<concept#{optout} key='#{attrs[:id]}'><refterm>"\
112
- "#{termout}</refterm><renderterm>#{wordout}</renderterm>"\
113
- "<xrefrender>#{xrefout}</xrefrender></concept>"
114
- "<concept#{optout}><termxref>#{termout}</termxref><renderterm>"\
115
- "#{wordout}</renderterm><xrefrender>#{xrefout}</xrefrender></concept>"
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
122
+ opt = generate_attrs(attrs[:opt] || [])
123
+ if attrs[:id] then "<concept#{opt} key='#{attrs[:id]}'><refterm>"\
124
+ "#{term}</refterm><renderterm>#{word}</renderterm>"\
125
+ "<xrefrender>#{xref}</xrefrender></concept>"
126
+ else "<concept#{opt}><termxref>#{term}</termxref><renderterm>"\
127
+ "#{word}</renderterm><xrefrender>#{xref}</xrefrender></concept>"
128
+ end
129
+ rescue StandardError => e
130
+ raise("processing {{#{target}}}: #{e.message}")
116
131
  end
117
132
  end
118
133
  end
@@ -7,8 +7,8 @@ module Asciidoctor
7
7
  module Standoc
8
8
  module Blocks
9
9
  def reqt_subpart(name)
10
- %w(specification measurement-target verification import label
11
- component subject inherit classification title).include? name
10
+ %w(specification measurement-target verification import label title
11
+ description component subject inherit classification).include? name
12
12
  end
13
13
 
14
14
  def reqt_subpart_attrs(node, name)
@@ -77,7 +77,7 @@ module Asciidoctor
77
77
  def term_def_parse(attrs, xml, node, _toplevel)
78
78
  xml.terms **attr_code(attrs) do |section|
79
79
  section.title { |t| t << node.title }
80
- (s = node.attr("source")) && s.split(/,/).each do |s1|
80
+ (s = node.attr("source")) && s.split(",").each do |s1|
81
81
  section.termdocsource(nil, **attr_code(bibitemid: s1))
82
82
  end
83
83
  section << node.content
@@ -131,6 +131,14 @@ module Asciidoctor
131
131
  end
132
132
  end.join("\n")
133
133
  end
134
+
135
+ def termdefinition(node)
136
+ noko do |xml|
137
+ xml.definition do |d|
138
+ d << node.content
139
+ end
140
+ end.join("\n")
141
+ end
134
142
  end
135
143
  end
136
144
  end
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "1.10.5".freeze
22
+ VERSION = "1.10.6".freeze
23
23
  end
24
24
  end
@@ -317,6 +317,88 @@ RSpec.describe Asciidoctor::Standoc do
317
317
  .to be_equivalent_to xmlpp(output)
318
318
  end
319
319
 
320
+ it "processes multiple term definitions" do
321
+ input = <<~INPUT
322
+ #{ASCIIDOC_BLANK_HDR}
323
+ == Terms and Definitions
324
+
325
+ === Term1
326
+
327
+ [.definition]
328
+ --
329
+ first definition
330
+
331
+ [.source]
332
+ <<ISO2191,section=1>>
333
+ --
334
+
335
+ [.definition]
336
+ --
337
+ second definition
338
+
339
+ [.source]
340
+ <<ISO2191,section=2>>
341
+ --
342
+
343
+ NOTE: This is a note
344
+
345
+ [.source]
346
+ <<ISO2191,section=3>>
347
+
348
+ INPUT
349
+ output = <<~OUTPUT
350
+ #{BLANK_HDR}
351
+ <sections>
352
+ <terms id='_' obligation='normative'>
353
+ <title>Terms and definitions</title>
354
+ <p id='_'>For the purposes of this document, the following terms and definitions apply.</p>
355
+ <term id='term-term1'>
356
+ <preferred>Term1</preferred>
357
+ <definition>
358
+ <p id='_'>first definition</p>
359
+ <termsource status='identical'>
360
+ <origin bibitemid='ISO2191' type='inline' citeas=''>
361
+ <localityStack>
362
+ <locality type='section'>
363
+ <referenceFrom>1</referenceFrom>
364
+ </locality>
365
+ </localityStack>
366
+ </origin>
367
+ </termsource>
368
+ </definition>
369
+ <definition>
370
+ <p id='_'>second definition</p>
371
+ <termsource status='identical'>
372
+ <origin bibitemid='ISO2191' type='inline' citeas=''>
373
+ <localityStack>
374
+ <locality type='section'>
375
+ <referenceFrom>2</referenceFrom>
376
+ </locality>
377
+ </localityStack>
378
+ </origin>
379
+ </termsource>
380
+ </definition>
381
+ <termnote id='_'>
382
+ <p id='_'>This is a note</p>
383
+ </termnote>
384
+ <termsource status='identical'>
385
+ <origin bibitemid='ISO2191' type='inline' citeas=''>
386
+ <localityStack>
387
+ <locality type='section'>
388
+ <referenceFrom>3</referenceFrom>
389
+ </locality>
390
+ </localityStack>
391
+ </origin>
392
+ </termsource>
393
+ </term>
394
+ </terms>
395
+ </sections>
396
+ </standard-document>
397
+ OUTPUT
398
+ expect(xmlpp(strip_guid(Asciidoctor.convert(input, *OPTIONS))))
399
+ .to be_equivalent_to xmlpp(output)
400
+ end
401
+
320
402
  it "processes term notes" do
321
403
  input = <<~INPUT
322
404
  #{ASCIIDOC_BLANK_HDR}
@@ -1264,10 +1346,14 @@ RSpec.describe Asciidoctor::Standoc do
1264
1346
  =====
1265
1347
  I also permit this
1266
1348
  =====
1349
+
1350
+ [requirement,type="general",label="/req/core/quantities-uom"]
1351
+ ======
1352
+ ======
1267
1353
  ====
1268
1354
  INPUT
1269
1355
  output = <<~"OUTPUT"
1270
- #{BLANK_HDR}
1356
+ #{BLANK_HDR}
1271
1357
  <sections>
1272
1358
  <permission id="_"><description><p id="_">I permit this</p>
1273
1359
  <example id="_">
@@ -1275,7 +1361,11 @@ RSpec.describe Asciidoctor::Standoc do
1275
1361
  </example></description>
1276
1362
  <permission id="_">
1277
1363
  <description><p id="_">I also permit this</p></description>
1278
- </permission></permission>
1364
+ </permission>
1365
+ <requirement id='_' type='general'>
1366
+ <label>/req/core/quantities-uom</label>
1367
+ </requirement>
1368
+ </permission>
1279
1369
  </sections>
1280
1370
  </standard-document>
1281
1371
  OUTPUT