metanorma-standoc 1.10.5 → 1.10.6

Sign up to get free protection for your applications and to get access to all the features.
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