metanorma-standoc 1.6.5 → 1.8.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +17 -0
  3. data/lib/asciidoctor/standoc/base.rb +31 -44
  4. data/lib/asciidoctor/standoc/basicdoc.rng +20 -3
  5. data/lib/asciidoctor/standoc/blocks.rb +7 -7
  6. data/lib/asciidoctor/standoc/blocks_notes.rb +2 -2
  7. data/lib/asciidoctor/standoc/cleanup.rb +5 -6
  8. data/lib/asciidoctor/standoc/cleanup_block.rb +3 -11
  9. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +89 -20
  10. data/lib/asciidoctor/standoc/cleanup_inline.rb +23 -25
  11. data/lib/asciidoctor/standoc/cleanup_ref.rb +0 -85
  12. data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +94 -0
  13. data/lib/asciidoctor/standoc/cleanup_terms.rb +1 -6
  14. data/lib/asciidoctor/standoc/converter.rb +2 -51
  15. data/lib/asciidoctor/standoc/front.rb +2 -2
  16. data/lib/asciidoctor/standoc/front_contributor.rb +8 -4
  17. data/lib/asciidoctor/standoc/inline.rb +8 -6
  18. data/lib/asciidoctor/standoc/isodoc.rng +36 -3
  19. data/lib/asciidoctor/standoc/lists.rb +2 -2
  20. data/lib/asciidoctor/standoc/macros.rb +14 -1
  21. data/lib/asciidoctor/standoc/macros_plantuml.rb +1 -1
  22. data/lib/asciidoctor/standoc/ref_sect.rb +2 -2
  23. data/lib/asciidoctor/standoc/reqt.rb +6 -1
  24. data/lib/asciidoctor/standoc/section.rb +14 -89
  25. data/lib/asciidoctor/standoc/table.rb +1 -1
  26. data/lib/asciidoctor/standoc/terms.rb +125 -0
  27. data/lib/asciidoctor/standoc/utils.rb +2 -94
  28. data/lib/metanorma/standoc/version.rb +1 -1
  29. data/metanorma-standoc.gemspec +2 -3
  30. data/spec/asciidoctor-standoc/base_spec.rb +44 -9
  31. data/spec/asciidoctor-standoc/blocks_spec.rb +6 -1
  32. data/spec/asciidoctor-standoc/cleanup_sections_spec.rb +12 -7
  33. data/spec/asciidoctor-standoc/cleanup_spec.rb +116 -4
  34. data/spec/asciidoctor-standoc/inline_spec.rb +4 -5
  35. data/spec/asciidoctor-standoc/isobib_cache_spec.rb +4 -4
  36. data/spec/asciidoctor-standoc/macros_lutaml_spec.rb +1 -1
  37. data/spec/asciidoctor-standoc/macros_spec.rb +30 -0
  38. data/spec/asciidoctor-standoc/refs_dl_spec.rb +17 -5
  39. data/spec/asciidoctor-standoc/refs_spec.rb +12 -12
  40. data/spec/asciidoctor-standoc/section_spec.rb +149 -4
  41. data/spec/asciidoctor-standoc/table_spec.rb +60 -0
  42. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +48 -48
  43. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  44. data/spec/vcr_cassettes/isobib_get_123_1.yml +26 -26
  45. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +36 -36
  46. data/spec/vcr_cassettes/isobib_get_123_2001.yml +14 -14
  47. data/spec/vcr_cassettes/isobib_get_124.yml +14 -14
  48. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +8 -8
  49. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +65 -59
  50. metadata +18 -31
  51. data/lib/asciidoctor/standoc/log.rb +0 -59
@@ -55,6 +55,13 @@
55
55
  <param name="pattern">\i\c*|\c+#\c+</param>
56
56
  </data>
57
57
  </attribute>
58
+ <optional>
59
+ <attribute name="to">
60
+ <data type="string">
61
+ <param name="pattern">\i\c*|\c+#\c+</param>
62
+ </data>
63
+ </attribute>
64
+ </optional>
58
65
  <optional>
59
66
  <attribute name="type">
60
67
  <ref name="ReferenceFormat"/>
@@ -246,6 +253,9 @@
246
253
  <data type="boolean"/>
247
254
  </attribute>
248
255
  </optional>
256
+ <optional>
257
+ <attribute name="width"/>
258
+ </optional>
249
259
  <optional>
250
260
  <ref name="colgroup"/>
251
261
  </optional>
@@ -779,6 +789,9 @@
779
789
  <attribute name="width"/>
780
790
  </element>
781
791
  </define>
792
+ <define name="BibItemType" combine="choice">
793
+ <value>internal</value>
794
+ </define>
782
795
  <define name="TextElement" combine="choice">
783
796
  <ref name="concept"/>
784
797
  </define>
@@ -829,6 +842,9 @@
829
842
  <data type="boolean"/>
830
843
  </attribute>
831
844
  </optional>
845
+ <optional>
846
+ <attribute name="number"/>
847
+ </optional>
832
848
  <optional>
833
849
  <attribute name="obligation">
834
850
  <choice>
@@ -884,9 +900,11 @@
884
900
  <element name="code">
885
901
  <text/>
886
902
  </element>
887
- <element name="text">
888
- <text/>
889
- </element>
903
+ <optional>
904
+ <element name="text">
905
+ <text/>
906
+ </element>
907
+ </optional>
890
908
  </element>
891
909
  </define>
892
910
  <define name="standard-document">
@@ -1056,6 +1074,9 @@
1056
1074
  </choice>
1057
1075
  </attribute>
1058
1076
  </optional>
1077
+ <optional>
1078
+ <attribute name="number"/>
1079
+ </optional>
1059
1080
  <optional>
1060
1081
  <attribute name="type"/>
1061
1082
  </optional>
@@ -1109,6 +1130,9 @@
1109
1130
  <optional>
1110
1131
  <attribute name="type"/>
1111
1132
  </optional>
1133
+ <optional>
1134
+ <attribute name="number"/>
1135
+ </optional>
1112
1136
  <optional>
1113
1137
  <ref name="section-title"/>
1114
1138
  </optional>
@@ -1211,6 +1235,9 @@
1211
1235
  <optional>
1212
1236
  <attribute name="type"/>
1213
1237
  </optional>
1238
+ <optional>
1239
+ <attribute name="number"/>
1240
+ </optional>
1214
1241
  <optional>
1215
1242
  <attribute name="obligation">
1216
1243
  <choice>
@@ -1539,6 +1566,7 @@
1539
1566
  <value>add</value>
1540
1567
  <value>modify</value>
1541
1568
  <value>delete</value>
1569
+ <value>replace</value>
1542
1570
  </choice>
1543
1571
  </attribute>
1544
1572
  <optional>
@@ -1569,6 +1597,11 @@
1569
1597
  </optional>
1570
1598
  <optional>
1571
1599
  <element name="newcontent">
1600
+ <optional>
1601
+ <attribute name="id">
1602
+ <data type="ID"/>
1603
+ </attribute>
1604
+ </optional>
1572
1605
  <zeroOrMore>
1573
1606
  <ref name="BasicBlock"/>
1574
1607
  </zeroOrMore>
@@ -54,7 +54,7 @@ module Asciidoctor
54
54
  end
55
55
 
56
56
  def ol_attrs(node)
57
- attr_code(keep_attrs(node).merge(id: Utils::anchor_or_uuid(node),
57
+ attr_code(keep_attrs(node).merge(id: Metanorma::Utils::anchor_or_uuid(node),
58
58
  type: olist_style(node.style)))
59
59
  end
60
60
 
@@ -88,7 +88,7 @@ module Asciidoctor
88
88
 
89
89
  def dl_attrs(node)
90
90
  attr_code(keep_attrs(node).
91
- merge(id: Utils::anchor_or_uuid(node),
91
+ merge(id: Metanorma::Utils::anchor_or_uuid(node),
92
92
  key: node.option?("key") ? "true" : nil))
93
93
  end
94
94
 
@@ -23,7 +23,7 @@ module Asciidoctor
23
23
  end
24
24
  end
25
25
 
26
- class IndexInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
26
+ class IndexXrefInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
27
27
  use_dsl
28
28
  named :index
29
29
 
@@ -44,6 +44,19 @@ module Asciidoctor
44
44
  end
45
45
  end
46
46
 
47
+ class IndexRangeInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
48
+ use_dsl
49
+ named "index-range".to_sym
50
+ parse_content_as :text
51
+
52
+ def process(parent, target, attr)
53
+ text = attr["text"]
54
+ text = "((#{text}))" unless /^\(\(.+\)\)$/.match(text)
55
+ out = parent.sub_macros(text)
56
+ out.sub(/<index>/, "<index to='#{target}'>")
57
+ end
58
+ end
59
+
47
60
  class PseudocodeBlockMacro < Asciidoctor::Extensions::BlockProcessor
48
61
  use_dsl
49
62
  named :pseudocode
@@ -30,7 +30,7 @@ module Asciidoctor
30
30
  # plantuml process may finish earlier then dot, as result png file
31
31
  # maybe not created yet after plantuml finish
32
32
  def self.generate_file parent, reader
33
- localdir = Utils::localdir(parent.document)
33
+ localdir = Metanorma::Utils::localdir(parent.document)
34
34
  imagesdir = parent.document.attr('imagesdir')
35
35
  umlfile, outfile = save_plantuml parent, reader, localdir
36
36
  run(umlfile, outfile) or raise "No image output from PlantUML (#{umlfile}, #{outfile})!"
@@ -96,9 +96,9 @@ module Asciidoctor
96
96
  xstr = x.to_xml(lang: opts[:lang])
97
97
  xml = Nokogiri::XML(xstr)
98
98
  emend_biblio(xml, code, opts[:title], opts[:usrlbl])
99
- xml.xpath("//date").each { |d| Utils::endash_date(d) }
99
+ xml.xpath("//date").each { |d| Metanorma::Utils::endash_date(d) }
100
100
  xml.traverse do |n|
101
- n.text? and n.replace(Utils::smartformat(n.text))
101
+ n.text? and n.replace(Metanorma::Utils::smartformat(n.text))
102
102
  end
103
103
  xml.to_xml.sub(/<\?[^>]+>/, "")
104
104
  end
@@ -6,6 +6,11 @@ require "base64"
6
6
  module Asciidoctor
7
7
  module Standoc
8
8
  module Blocks
9
+ def reqt_subpart(x)
10
+ %w(specification measurement-target verification import label
11
+ subject inherit classification title).include? x
12
+ end
13
+
9
14
  def reqt_subpart_attrs(node)
10
15
  attr_code(keep_attrs(node).merge(exclude: node.option?("exclude"),
11
16
  type: node.attr("type")))
@@ -41,7 +46,7 @@ module Asciidoctor
41
46
 
42
47
  def reqt_attrs(node)
43
48
  attr_code(keep_attrs(node).merge(id_unnum_attrs(node)).merge(
44
- id: Utils::anchor_or_uuid(node),
49
+ id: Metanorma::Utils::anchor_or_uuid(node),
45
50
  unnumbered: node.option?("unnumbered") ? "true" : nil,
46
51
  number: node.attr("number"),
47
52
  subsequence: node.attr("subsequence"),
@@ -1,6 +1,6 @@
1
- require "htmlentities"
2
1
  require "uri"
3
2
  require_relative "ref_sect"
3
+ require_relative "terms"
4
4
 
5
5
  module Asciidoctor
6
6
  module Standoc
@@ -9,13 +9,8 @@ module Asciidoctor
9
9
  @term_def = false
10
10
  @norm_ref = false
11
11
 
12
- def in_terms?
13
- @term_def
14
- end
15
-
16
12
  def sectiontype1(node)
17
- node&.attr("heading")&.downcase ||
18
- node.title.gsub(/<[^>]+>/, "").downcase
13
+ node&.attr("heading")&.downcase || node.title.gsub(/<[^>]+>/, "").downcase
19
14
  end
20
15
 
21
16
  def sectiontype(node, level = true)
@@ -46,16 +41,15 @@ module Asciidoctor
46
41
  end
47
42
 
48
43
  def section_attributes(node)
49
- ret = { id: Utils::anchor_or_uuid(node),
50
- language: node.attributes["language"],
51
- script: node.attributes["script"],
52
- annex: (
53
- ((node.attr("style") == "appendix" || node.role == "appendix") &&
54
- node.level == 1) ? true : nil
55
- ),
56
- preface: (
57
- (node.role == "preface" || node.attr("style") == "preface") ?
58
- true : nil) }
44
+ ret = { id: Metanorma::Utils::anchor_or_uuid(node),
45
+ language: node.attributes["language"],
46
+ script: node.attributes["script"],
47
+ number: node.attributes["number"],
48
+ type: node.attributes["type"],
49
+ annex: ( ((node.attr("style") == "appendix" || node.role == "appendix") &&
50
+ node.level == 1) ? true : nil),
51
+ preface: (
52
+ (node.role == "preface" || node.attr("style") == "preface") ? true : nil) }
59
53
  return ret unless node.attributes["change"]
60
54
  ret.merge(change: node.attributes["change"],
61
55
  path: node.attributes["path"],
@@ -105,9 +99,9 @@ module Asciidoctor
105
99
 
106
100
  def set_obligation(attrs, node)
107
101
  attrs[:obligation] = node.attributes.has_key?("obligation") ?
108
- node.attr("obligation") :
109
- node.parent.attributes.has_key?("obligation") ?
110
- node.parent.attr("obligation") : "normative"
102
+ node.attr("obligation") :
103
+ node.parent.attributes.has_key?("obligation") ?
104
+ node.parent.attr("obligation") : "normative"
111
105
  end
112
106
 
113
107
  def preamble(node)
@@ -150,75 +144,6 @@ module Asciidoctor
150
144
  end
151
145
  end
152
146
 
153
- def nonterm_symbols_parse(attrs, xml, node)
154
- defs = @definitions
155
- @definitions = false
156
- clause_parse(attrs, xml, node)
157
- @definitions = defs
158
- end
159
-
160
- def symbols_attrs(node, a)
161
- case sectiontype1(node)
162
- when "symbols" then a.merge(type: "symbols")
163
- when "abbreviated terms", "abbreviations" then a.merge(type: "abbreviated_terms")
164
- else
165
- a
166
- end
167
- end
168
-
169
- def symbols_parse(attr, xml, node)
170
- node.role == "nonterm" and return nonterm_symbols_parse(attr, xml, node)
171
- xml.definitions **attr_code(attr) do |xml_section|
172
- xml_section.title { |t| t << node.title }
173
- defs = @definitions
174
- termdefs = @term_def
175
- @definitions = true
176
- @term_def = false
177
- xml_section << node.content
178
- @definitions = defs
179
- @term_def = termdefs
180
- end
181
- end
182
-
183
- def nonterm_term_def_subclause_parse(attrs, xml, node)
184
- defs = @term_def
185
- @term_def = false
186
- clause_parse(attrs, xml, node)
187
- @term_def = defs
188
- end
189
-
190
- # subclause contains subclauses
191
- def term_def_subclause_parse(attrs, xml, node)
192
- node.role == "nonterm" and
193
- return nonterm_term_def_subclause_parse(attrs, xml, node)
194
- st = sectiontype(node, false)
195
- return symbols_parse(attrs, xml, node) if @definitions
196
- sub = node.find_by(context: :section) { |s| s.level == node.level + 1 }
197
- sub.empty? || (return term_def_parse(attrs, xml, node, false))
198
- st == "symbols and abbreviated terms" and
199
- (return symbols_parse(attrs, xml, node))
200
- st == "terms and definitions" and
201
- return clause_parse(attrs, xml, node)
202
- term_def_subclause_parse1(attrs, xml, node)
203
- end
204
-
205
- def term_def_subclause_parse1(attrs, xml, node)
206
- xml.term **attr_code(attrs) do |xml_section|
207
- xml_section.preferred { |name| name << node.title }
208
- xml_section << node.content
209
- end
210
- end
211
-
212
- def term_def_parse(attrs, xml, node, toplevel)
213
- xml.terms **attr_code(attrs) do |section|
214
- section.title { |t| t << node.title }
215
- (s = node.attr("source")) && s.split(/,/).each do |s1|
216
- section.termdocsource(nil, **attr_code(bibitemid: s1))
217
- end
218
- section << node.content
219
- end
220
- end
221
-
222
147
  def introduction_parse(attrs, xml, node)
223
148
  xml.introduction **attr_code(attrs) do |xml_section|
224
149
  xml_section.title { |t| t << @i18n.introduction }
@@ -2,7 +2,7 @@ module Asciidoctor
2
2
  module Standoc
3
3
  module Table
4
4
  def table_attrs(node)
5
- keep_attrs(node).merge( id: Utils::anchor_or_uuid(node),
5
+ keep_attrs(node).merge( id: Metanorma::Utils::anchor_or_uuid(node),
6
6
  headerrows: node.attr("headerrows"),
7
7
  unnumbered: node.option?("unnumbered") ? "true" : nil,
8
8
  number: node.attr("number"),
@@ -0,0 +1,125 @@
1
+ module Asciidoctor
2
+ module Standoc
3
+ module Section
4
+ def in_terms?
5
+ @term_def
6
+ end
7
+
8
+ def nonterm_symbols_parse(attrs, xml, node)
9
+ defs = @definitions
10
+ @definitions = false
11
+ clause_parse(attrs, xml, node)
12
+ @definitions = defs
13
+ end
14
+
15
+ def symbols_attrs(node, a)
16
+ case sectiontype1(node)
17
+ when "symbols" then a.merge(type: "symbols")
18
+ when "abbreviated terms", "abbreviations" then a.merge(type: "abbreviated_terms")
19
+ else
20
+ a
21
+ end
22
+ end
23
+
24
+ def symbols_parse(attr, xml, node)
25
+ node.role == "nonterm" and return nonterm_symbols_parse(attr, xml, node)
26
+ xml.definitions **attr_code(attr) do |xml_section|
27
+ xml_section.title { |t| t << node.title }
28
+ defs = @definitions
29
+ termdefs = @term_def
30
+ @definitions = true
31
+ @term_def = false
32
+ xml_section << node.content
33
+ @definitions = defs
34
+ @term_def = termdefs
35
+ end
36
+ end
37
+
38
+ def nonterm_term_def_subclause_parse(attrs, xml, node)
39
+ defs = @term_def
40
+ @term_def = false
41
+ clause_parse(attrs, xml, node)
42
+ @term_def = defs
43
+ end
44
+
45
+ def terms_boilerplate_parse(attrs, xml, node)
46
+ defs = @term_def
47
+ @term_def = false
48
+ clause_parse(attrs.merge(type: "boilerplate"), xml, node)
49
+ @term_def = defs
50
+ end
51
+
52
+ # subclause contains subclauses
53
+ def term_def_subclause_parse(attrs, xml, node)
54
+ node.role == "nonterm" and return nonterm_term_def_subclause_parse(attrs, xml, node)
55
+ node.role == "boilerplate" and return terms_boilerplate_parse(attrs, xml, node)
56
+ st = sectiontype(node, false)
57
+ return symbols_parse(attrs, xml, node) if @definitions
58
+ sub = node.find_by(context: :section) { |s| s.level == node.level + 1 }
59
+ sub.empty? || (return term_def_parse(attrs, xml, node, false))
60
+ st == "symbols and abbreviated terms" and (return symbols_parse(attrs, xml, node))
61
+ st == "terms and definitions" and return clause_parse(attrs, xml, node)
62
+ term_def_subclause_parse1(attrs, xml, node)
63
+ end
64
+
65
+ def term_def_subclause_parse1(attrs, xml, node)
66
+ xml.term **attr_code(attrs) do |xml_section|
67
+ xml_section.preferred { |name| name << node.title }
68
+ xml_section << node.content
69
+ end
70
+ end
71
+
72
+ def term_def_parse(attrs, xml, node, toplevel)
73
+ xml.terms **attr_code(attrs) do |section|
74
+ section.title { |t| t << node.title }
75
+ (s = node.attr("source")) && s.split(/,/).each do |s1|
76
+ section.termdocsource(nil, **attr_code(bibitemid: s1))
77
+ end
78
+ section << node.content
79
+ end
80
+ end
81
+
82
+ def term_source_attrs(seen_xref)
83
+ { bibitemid: seen_xref.children[0]["target"],
84
+ format: seen_xref.children[0]["format"], type: "inline" }
85
+ end
86
+
87
+ def add_term_source(xml_t, seen_xref, m)
88
+ if seen_xref.children[0].name == "concept"
89
+ xml_t.origin { |o| o << seen_xref.children[0].to_xml }
90
+ else
91
+ xml_t.origin seen_xref.children[0].content, **attr_code(term_source_attrs(seen_xref))
92
+ end
93
+ m[:text] && xml_t.modification do |mod|
94
+ mod.p { |p| p << m[:text].sub(/^\s+/, "") }
95
+ end
96
+ end
97
+
98
+ TERM_REFERENCE_RE_STR = <<~REGEXP.freeze
99
+ ^(?<xref><(xref|concept)[^>]+>([^<]*</(xref|concept)>)?)
100
+ (,\s(?<text>.*))?
101
+ $
102
+ REGEXP
103
+ TERM_REFERENCE_RE =
104
+ Regexp.new(TERM_REFERENCE_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"),
105
+ Regexp::IGNORECASE | Regexp::MULTILINE)
106
+
107
+ def extract_termsource_refs(text, node)
108
+ matched = TERM_REFERENCE_RE.match text
109
+ matched.nil? and @log.add("AsciiDoc Input", node, "term reference not in expected format: #{text}")
110
+ matched
111
+ end
112
+
113
+ def termsource(node)
114
+ matched = extract_termsource_refs(node.content, node) || return
115
+ noko do |xml|
116
+ attrs = { status: matched[:text] ? "modified" : "identical" }
117
+ xml.termsource **attrs do |xml_t|
118
+ seen_xref = Nokogiri::XML.fragment(matched[:xref])
119
+ add_term_source(xml_t, seen_xref, matched)
120
+ end
121
+ end.join("\n")
122
+ end
123
+ end
124
+ end
125
+ end