metanorma-standoc 1.10.6 → 1.11.0.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 (63) 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 +10 -17
  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 +46 -12
  9. data/lib/asciidoctor/standoc/cleanup_block.rb +3 -71
  10. data/lib/asciidoctor/standoc/cleanup_image.rb +6 -7
  11. data/lib/asciidoctor/standoc/cleanup_inline.rb +42 -106
  12. data/lib/asciidoctor/standoc/cleanup_maths.rb +5 -6
  13. data/lib/asciidoctor/standoc/cleanup_ref.rb +5 -0
  14. data/lib/asciidoctor/standoc/cleanup_reqt.rb +5 -24
  15. data/lib/asciidoctor/standoc/cleanup_section_names.rb +5 -5
  16. data/lib/asciidoctor/standoc/cleanup_symbols.rb +48 -0
  17. data/lib/asciidoctor/standoc/cleanup_table.rb +68 -0
  18. data/lib/asciidoctor/standoc/cleanup_terms.rb +37 -77
  19. data/lib/asciidoctor/standoc/cleanup_terms_designations.rb +162 -0
  20. data/lib/asciidoctor/standoc/cleanup_text.rb +5 -2
  21. data/lib/asciidoctor/standoc/cleanup_xref.rb +107 -0
  22. data/lib/asciidoctor/standoc/converter.rb +14 -0
  23. data/lib/asciidoctor/standoc/inline.rb +7 -5
  24. data/lib/asciidoctor/standoc/isodoc.rng +419 -77
  25. data/lib/asciidoctor/standoc/lists.rb +15 -15
  26. data/lib/asciidoctor/standoc/macros.rb +14 -43
  27. data/lib/asciidoctor/standoc/macros_note.rb +45 -0
  28. data/lib/asciidoctor/standoc/macros_plantuml.rb +29 -14
  29. data/lib/asciidoctor/standoc/macros_terms.rb +55 -8
  30. data/lib/asciidoctor/standoc/ref_sect.rb +26 -18
  31. data/lib/asciidoctor/standoc/reqt.rng +23 -2
  32. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +50 -11
  33. data/lib/asciidoctor/standoc/terms.rb +12 -2
  34. data/lib/asciidoctor/standoc/utils.rb +36 -23
  35. data/lib/asciidoctor/standoc/validate.rb +45 -27
  36. data/lib/asciidoctor/standoc/validate_section.rb +5 -2
  37. data/lib/metanorma/standoc/version.rb +1 -1
  38. data/metanorma-standoc.gemspec +1 -1
  39. data/spec/asciidoctor/base_spec.rb +4 -36
  40. data/spec/asciidoctor/blank_spec.rb +37 -0
  41. data/spec/asciidoctor/blocks_spec.rb +208 -49
  42. data/spec/asciidoctor/cleanup_sections_spec.rb +153 -12
  43. data/spec/asciidoctor/cleanup_spec.rb +104 -285
  44. data/spec/asciidoctor/cleanup_terms_spec.rb +990 -0
  45. data/spec/asciidoctor/inline_spec.rb +38 -2
  46. data/spec/asciidoctor/lists_spec.rb +6 -6
  47. data/spec/asciidoctor/macros_plantuml_spec.rb +37 -2
  48. data/spec/asciidoctor/macros_spec.rb +191 -114
  49. data/spec/asciidoctor/refs_spec.rb +12 -30
  50. data/spec/asciidoctor/section_spec.rb +18 -18
  51. data/spec/asciidoctor/validate_spec.rb +87 -2
  52. data/spec/fixtures/datamodel_description_sections_tree.xml +3 -2
  53. data/spec/spec_helper.rb +6 -7
  54. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +51 -51
  55. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +13 -13
  56. data/spec/vcr_cassettes/isobib_get_123.yml +13 -13
  57. data/spec/vcr_cassettes/isobib_get_123_1.yml +26 -26
  58. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +34 -34
  59. data/spec/vcr_cassettes/isobib_get_123_2001.yml +12 -12
  60. data/spec/vcr_cassettes/isobib_get_124.yml +13 -13
  61. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +16 -16
  62. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +51 -49
  63. metadata +12 -5
@@ -0,0 +1,162 @@
1
+ module Asciidoctor
2
+ module Standoc
3
+ module Cleanup
4
+ def termdef_stem_cleanup(xmldoc)
5
+ xmldoc.xpath("//term/p/stem").each do |a|
6
+ if a.parent.elements.size == 1 # para contains just a stem expression
7
+ parent = a.parent
8
+ parent.replace("<admitted>#{term_expr(a.to_xml)}</admitted>")
9
+ end
10
+ end
11
+ xmldoc.xpath("//term//expression/name[stem]").each do |n|
12
+ n.parent.name = "letter-symbol"
13
+ end
14
+ end
15
+
16
+ # release termdef tags from surrounding paras
17
+ def termdef_unnest_cleanup(xmldoc)
18
+ desgn = "//p/admitted | //p/deprecates | //p/preferred | //p//related"
19
+ nodes = xmldoc.xpath(desgn)
20
+ while !nodes.empty?
21
+ nodes[0].parent.replace(nodes[0].parent.children)
22
+ nodes = xmldoc.xpath(desgn)
23
+ end
24
+ end
25
+
26
+ def term_dl_to_metadata(xmldoc)
27
+ xmldoc.xpath("//term[dl[@metadata = 'true']]").each do |t|
28
+ t.xpath("./dl[@metadata = 'true']").each do |dl|
29
+ prev = dl_to_designation(dl) or next
30
+ term_dl_to_designation_metadata(prev, dl)
31
+ term_dl_to_term_metadata(prev, dl)
32
+ term_dl_to_expression_metadata(prev, dl)
33
+ dl.remove
34
+ end
35
+ end
36
+ end
37
+
38
+ def term_dl_to_term_metadata(prev, dlist)
39
+ return unless prev.name == "preferred" &&
40
+ prev.at("./preceding-sibling::preferred").nil?
41
+
42
+ ins = term_element_insert_point(prev)
43
+ %w(domain subject usageinfo).each do |a|
44
+ ins = dl_to_elems(ins, prev.parent, dlist, a)
45
+ end
46
+ end
47
+
48
+ def term_dl_to_designation_metadata(prev, dlist)
49
+ %w(absent geographicArea).each { |a| dl_to_attrs(related2pref(prev), dlist, a) }
50
+ end
51
+
52
+ def term_element_insert_point(prev)
53
+ ins = prev
54
+ while %w(preferred admitted deprecates related domain dl)
55
+ .include? ins&.next_element&.name
56
+ ins = ins.next_element
57
+ end
58
+ ins
59
+ end
60
+
61
+ def term_dl_to_expression_metadata(prev, dlist)
62
+ %w(language script type isInternational).each do |a|
63
+ dl_to_attrs(prev, dlist, a)
64
+ end
65
+ %w(abbreviationType pronunciation).reverse.each do |a|
66
+ dl_to_elems(prev.at("./expression/name"), prev, dlist, a)
67
+ end
68
+ g = dlist.at("./dt[text()='grammar']/following::dd//dl") and
69
+ term_dl_to_expression_grammar(prev, g)
70
+ term_to_letter_symbol(prev, dlist)
71
+ end
72
+
73
+ def term_dl_to_expression_grammar(prev, dlist)
74
+ prev.at(".//expression") or return
75
+ prev.at(".//expression") << "<grammar><sentinel/></grammar>"
76
+ %w(gender isPreposition isParticiple isAdjective isAdverb isNoun
77
+ grammarValue).reverse.each do |a|
78
+ dl_to_elems(prev.at(".//expression/grammar/*"), prev.elements.last,
79
+ dlist, a)
80
+ end
81
+ term_dl_to_designation_gender(prev)
82
+ end
83
+
84
+ def term_dl_to_designation_gender(prev)
85
+ gender = prev.at(".//expression/grammar/gender")
86
+ /,/.match?(gender&.text) and
87
+ gender.replace(gender.text.split(/,\s*/)
88
+ .map { |x| "<gender>#{x}</gender>" }.join)
89
+ prev.at(".//expression/grammar/sentinel").remove
90
+ end
91
+
92
+ def term_to_letter_symbol(prev, dlist)
93
+ ls = dlist.at("./dt[text()='letter-symbol']/following::dd/p")
94
+ return unless ls&.text == "true"
95
+
96
+ prev.at(".//expression").name = "letter-symbol"
97
+ end
98
+
99
+ def dl_to_designation(dlist)
100
+ prev = dlist.previous_element
101
+ unless %w(preferred admitted deprecates related).include? prev&.name
102
+ @log.add("AsciiDoc Input", dlist, "Metadata definition list does "\
103
+ "not follow a term designation")
104
+ return nil
105
+ end
106
+ prev
107
+ end
108
+
109
+ def term_nonverbal_designations(xmldoc)
110
+ xmldoc.xpath("//term/preferred | //term/admitted | //term/deprecates")
111
+ .each do |d|
112
+ d.text.strip.empty? or next
113
+ n = d.next_element
114
+ if %w(formula figure).include?(n&.name)
115
+ term_nonverbal_designations1(d, n)
116
+ else d.at("./expression/name") or
117
+ d.children = term_expr("")
118
+ end
119
+ end
120
+ end
121
+
122
+ def term_nonverbal_designations1(desgn, elem)
123
+ desgn = related2pref(desgn)
124
+ if elem.name == "figure"
125
+ elem.at("./name").remove
126
+ desgn.children =
127
+ "<graphical-symbol>#{elem.remove.to_xml}</graphical-symbol>"
128
+ else
129
+ desgn.children = term_expr(elem.at("./stem").to_xml)
130
+ elem.remove
131
+ end
132
+ end
133
+
134
+ def term_termsource_to_designation(xmldoc)
135
+ xmldoc.xpath("//term/termsource").each do |t|
136
+ p = t.previous_element
137
+ while %w(domain subject usageinfo).include? p&.name
138
+ p = p.previous_element
139
+ end
140
+ %w(preferred admitted deprecates related).include?(p&.name) or
141
+ next
142
+ related2pref(p) << t.remove
143
+ end
144
+ end
145
+
146
+ def term_designation_reorder(xmldoc)
147
+ xmldoc.xpath("//term").each do |t|
148
+ %w(preferred admitted deprecates related)
149
+ .each_with_object([]) do |tag, m|
150
+ t.xpath("./#{tag}").each { |x| m << x.remove }
151
+ end.reverse.each do |x|
152
+ t.children.first.previous = x
153
+ end
154
+ end
155
+ end
156
+
157
+ def related2pref(elem)
158
+ elem.name == "related" ? elem = elem.at("./preferred") : elem
159
+ end
160
+ end
161
+ end
162
+ end
@@ -9,7 +9,8 @@ module Asciidoctor
9
9
  </passthrough>}mx) { HTMLEntities.new.decode($1) }
10
10
  end
11
11
 
12
- IGNORE_DUMBQUOTES = "//pre | //pre//* | //tt | //tt//* | "\
12
+ IGNORE_DUMBQUOTES =
13
+ "//pre | //pre//* | //tt | //tt//* | "\
13
14
  "//sourcecode | //sourcecode//* | //bibdata//* | //stem | "\
14
15
  "//stem//* | //figure[@class = 'pseudocode'] | "\
15
16
  "//figure[@class = 'pseudocode']//*".freeze
@@ -32,6 +33,7 @@ module Asciidoctor
32
33
  "[starts-with(., '\"') or starts-with(., \"'\")]]")
33
34
  .each do |x|
34
35
  next if !x.ancestors("pre, tt, sourcecode, stem, figure").empty?
36
+
35
37
  uninterrupt_quotes_around_xml1(x)
36
38
  end
37
39
  end
@@ -40,7 +42,8 @@ module Asciidoctor
40
42
  prev = elem.at(".//preceding::text()[1]") or return
41
43
  /\S$/.match?(prev.text) or return
42
44
  foll = elem.at(".//following::text()[1]")
43
- m = /^(["'][[:punct:]]*)(\s|$)/.match(HTMLEntities.new.decode(foll&.text)) or return
45
+ m = /^(["'][[:punct:]]*)(\s|$)/
46
+ .match(HTMLEntities.new.decode(foll&.text)) or return
44
47
  foll.content = foll.text.sub(/^(["'][[:punct:]]*)/, "")
45
48
  prev.content = "#{prev.text}#{m[1]}"
46
49
  end
@@ -0,0 +1,107 @@
1
+ module Asciidoctor
2
+ module Standoc
3
+ module Cleanup
4
+ # extending localities to cover ISO referencing
5
+ LOCALITY_REGEX_STR = <<~REGEXP.freeze
6
+ ^((?<locality>section|clause|part|paragraph|chapter|page|
7
+ table|annex|figure|example|note|formula|list|time|anchor|
8
+ locality:[^ \\t\\n\\r:,;=]+)(\\s+|=)
9
+ (?<ref>[^"][^ \\t\\n,:-]*|"[^"]+")
10
+ (-(?<to>[^"][^ \\t\\n,:-]*|"[^"]"))?|
11
+ (?<locality2>whole|locality:[^ \\t\\n\\r:,;=]+))(?<punct>[,:;]?)\\s*
12
+ (?<text>.*)$
13
+ REGEXP
14
+ LOCALITY_RE = Regexp.new(LOCALITY_REGEX_STR.gsub(/\s/, ""),
15
+ Regexp::IGNORECASE | Regexp::MULTILINE)
16
+
17
+ def tq(text)
18
+ text.sub(/^"/, "").sub(/"$/, "")
19
+ end
20
+
21
+ def extract_localities(elem)
22
+ f = elem&.children&.first or return
23
+ f.text? or return
24
+ head = f.remove.text
25
+ tail = elem&.children&.remove
26
+ extract_localities1(elem, head)
27
+ tail and elem << tail
28
+ end
29
+
30
+ def extract_localities1(elem, text)
31
+ b = elem.add_child("<localityStack/>").first if LOCALITY_RE.match text
32
+ while (m = LOCALITY_RE.match text)
33
+ ref = m[:ref] ? "<referenceFrom>#{tq m[:ref]}</referenceFrom>" : ""
34
+ refto = m[:to] ? "<referenceTo>#{tq m[:to]}</referenceTo>" : ""
35
+ b.add_child("<locality type='#{locality_label(m)}'>#{ref}#{refto}"\
36
+ "</locality>")
37
+ text = m[:text]
38
+ b = elem.add_child("<localityStack/>").first if m[:punct] == ";"
39
+ end
40
+ elem.add_child(text) if text
41
+ end
42
+
43
+ def locality_label(match)
44
+ loc = match[:locality] || match[:locality2]
45
+ /^locality:/.match?(loc) ? loc : loc&.downcase
46
+ end
47
+
48
+ def xref_to_eref(elem)
49
+ elem["bibitemid"] = elem["target"]
50
+ unless elem["citeas"] = @anchors&.dig(elem["target"], :xref)
51
+ @internal_eref_namespaces.include?(elem["type"]) or
52
+ @log.add("Crossreferences", elem,
53
+ "#{elem['target']} does not have a corresponding "\
54
+ "anchor ID in the bibliography!")
55
+ end
56
+ elem.delete("target")
57
+ extract_localities(elem) unless elem.children.empty?
58
+ end
59
+
60
+ def xref_cleanup(xmldoc)
61
+ xmldoc.xpath("//xref").each do |x|
62
+ /:/.match(x["target"]) and xref_to_internal_eref(x)
63
+ next unless x.name == "xref"
64
+
65
+ if refid? x["target"]
66
+ x.name = "eref"
67
+ xref_to_eref(x)
68
+ else x.delete("type")
69
+ end
70
+ end
71
+ end
72
+
73
+ def xref_to_internal_eref(elem)
74
+ a = elem["target"].split(":", 3)
75
+ unless a.size < 2 || a[0].empty? || a[1].empty?
76
+ elem["target"] = "#{a[0]}_#{a[1]}"
77
+ a.size > 2 and
78
+ elem.children = %{anchor="#{a[2..-1].join}",#{elem&.children&.text}}
79
+ elem["type"] = a[0]
80
+ @internal_eref_namespaces << a[0]
81
+ elem.name = "eref"
82
+ xref_to_eref(elem)
83
+ end
84
+ end
85
+
86
+ def quotesource_cleanup(xmldoc)
87
+ xmldoc.xpath("//quote/source | //terms/source").each do |x|
88
+ xref_to_eref(x)
89
+ end
90
+ end
91
+
92
+ def origin_cleanup(xmldoc)
93
+ xmldoc.xpath("//origin/concept[termref]").each do |x|
94
+ t = x.at("./termref")
95
+ x.replace(t)
96
+ end
97
+ xmldoc.xpath("//origin").each do |x|
98
+ x["citeas"] = @anchors&.dig(x["bibitemid"], :xref) or
99
+ @log.add("Crossreferences", x,
100
+ "#{x['bibitemid']} does not have a corresponding anchor "\
101
+ "ID in the bibliography!")
102
+ extract_localities(x) unless x.children.empty?
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -28,8 +28,10 @@ module Asciidoctor
28
28
  preprocessor Metanorma::Plugin::Lutaml::LutamlPreprocessor
29
29
  preprocessor Metanorma::Plugin::Lutaml::LutamlUmlAttributesTablePreprocessor
30
30
  preprocessor Metanorma::Plugin::Lutaml::LutamlUmlDatamodelDescriptionPreprocessor
31
+ inline_macro Asciidoctor::Standoc::PreferredTermInlineMacro
31
32
  inline_macro Asciidoctor::Standoc::AltTermInlineMacro
32
33
  inline_macro Asciidoctor::Standoc::DeprecatedTermInlineMacro
34
+ inline_macro Asciidoctor::Standoc::RelatedTermInlineMacro
33
35
  inline_macro Asciidoctor::Standoc::DomainTermInlineMacro
34
36
  inline_macro Asciidoctor::Standoc::InheritInlineMacro
35
37
  inline_macro Asciidoctor::Standoc::HTML5RubyMacro
@@ -49,6 +51,7 @@ module Asciidoctor
49
51
  inline_macro Asciidoctor::Standoc::FormSelectMacro
50
52
  inline_macro Asciidoctor::Standoc::FormOptionMacro
51
53
  inline_macro Asciidoctor::Standoc::ToCInlineMacro
54
+ inline_macro Asciidoctor::Standoc::PassInlineMacro
52
55
  inline_macro Metanorma::Plugin::Lutaml::LutamlFigureInlineMacro
53
56
  inline_macro Metanorma::Plugin::Lutaml::LutamlTableInlineMacro
54
57
  block_macro Metanorma::Plugin::Lutaml::LutamlDiagramBlockMacro
@@ -98,6 +101,17 @@ module Asciidoctor
98
101
  File.join(@libdir, "../../isodoc/html", file)
99
102
  end
100
103
 
104
+ def content(node)
105
+ node.content
106
+ end
107
+
108
+ def skip(node, name = nil)
109
+ name = name || node.node_name
110
+ w = "converter missing for #{name} node in Metanorma backend"
111
+ @log.add("AsciiDoc Input", node, w)
112
+ nil
113
+ end
114
+
101
115
  alias_method :embedded, :content
102
116
  alias_method :verse, :quote
103
117
  alias_method :audio, :skip
@@ -170,8 +170,10 @@ module Asciidoctor
170
170
  else
171
171
  case node.role
172
172
  # the following three are legacy, they are now handled by macros
173
- when "alt" then xml.admitted { |a| a << node.text }
174
- when "deprecated" then xml.deprecates { |a| a << node.text }
173
+ when "alt"
174
+ term_designation(xml, node, "admitted", node.text)
175
+ when "deprecated"
176
+ term_designation(xml, node, "deprecates", node.text)
175
177
  when "domain" then xml.domain { |a| a << node.text }
176
178
 
177
179
  when "strike" then xml.strike { |s| s << node.text }
@@ -209,7 +211,7 @@ module Asciidoctor
209
211
  def inline_image(node)
210
212
  noko do |xml|
211
213
  xml.image **image_attributes(node)
212
- end.join("")
214
+ end.join
213
215
  end
214
216
 
215
217
  def inline_indexterm(node)
@@ -218,8 +220,8 @@ module Asciidoctor
218
220
  terms = (node.attr("terms") || [node.text]).map { |x| xml_encode(x) }
219
221
  xml.index do |i|
220
222
  i.primary { |x| x << terms[0] }
221
- a = terms.dig(1) and i.secondary { |x| x << a }
222
- a = terms.dig(2) and i.tertiary { |x| x << a }
223
+ a = terms[1] and i.secondary { |x| x << a }
224
+ a = terms[2] and i.tertiary { |x| x << a }
223
225
  end
224
226
  end.join
225
227
  end