metanorma-standoc 1.6.5 → 1.8.1

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