metanorma-standoc 1.8.2 → 1.8.7

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +11 -41
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +6 -2
  5. data/lib/asciidoctor/standoc/base.rb +3 -1
  6. data/lib/asciidoctor/standoc/biblio.rng +4 -6
  7. data/lib/asciidoctor/standoc/blocks.rb +35 -12
  8. data/lib/asciidoctor/standoc/cleanup.rb +2 -1
  9. data/lib/asciidoctor/standoc/cleanup_block.rb +73 -22
  10. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +3 -3
  11. data/lib/asciidoctor/standoc/cleanup_inline.rb +4 -3
  12. data/lib/asciidoctor/standoc/cleanup_maths.rb +37 -0
  13. data/lib/asciidoctor/standoc/cleanup_ref.rb +4 -13
  14. data/lib/asciidoctor/standoc/cleanup_section.rb +5 -0
  15. data/lib/asciidoctor/standoc/cleanup_terms.rb +2 -2
  16. data/lib/asciidoctor/standoc/inline.rb +7 -15
  17. data/lib/asciidoctor/standoc/isodoc.rng +105 -2
  18. data/lib/asciidoctor/standoc/ref_sect.rb +12 -12
  19. data/lib/asciidoctor/standoc/section.rb +9 -0
  20. data/lib/asciidoctor/standoc/utils.rb +0 -24
  21. data/lib/asciidoctor/standoc/validate.rb +16 -1
  22. data/lib/metanorma/standoc/version.rb +1 -1
  23. data/metanorma-standoc.gemspec +5 -5
  24. data/spec/{asciidoctor-standoc → asciidoctor}/base_spec.rb +4 -0
  25. data/spec/{asciidoctor-standoc → asciidoctor}/blocks_spec.rb +0 -0
  26. data/spec/{asciidoctor-standoc → asciidoctor}/cleanup_sections_spec.rb +14 -14
  27. data/spec/{asciidoctor-standoc → asciidoctor}/cleanup_spec.rb +242 -11
  28. data/spec/{asciidoctor-standoc → asciidoctor}/datamodel/attributes_table_preprocessor_spec.rb +0 -0
  29. data/spec/{asciidoctor-standoc → asciidoctor}/datamodel/diagram_preprocessor_spec.rb +0 -0
  30. data/spec/{asciidoctor-standoc → asciidoctor}/inline_spec.rb +2 -0
  31. data/spec/{asciidoctor-standoc → asciidoctor}/isobib_cache_spec.rb +0 -0
  32. data/spec/{asciidoctor-standoc → asciidoctor}/lists_spec.rb +0 -0
  33. data/spec/{asciidoctor-standoc → asciidoctor}/macros_json2text_spec.rb +0 -0
  34. data/spec/{asciidoctor-standoc → asciidoctor}/macros_plantuml_spec.rb +0 -0
  35. data/spec/{asciidoctor-standoc → asciidoctor}/macros_spec.rb +0 -0
  36. data/spec/{asciidoctor-standoc → asciidoctor}/macros_yaml2text_spec.rb +0 -0
  37. data/spec/{asciidoctor-standoc → asciidoctor}/refs_dl_spec.rb +0 -0
  38. data/spec/{asciidoctor-standoc → asciidoctor}/refs_spec.rb +297 -147
  39. data/spec/{asciidoctor-standoc → asciidoctor}/section_spec.rb +17 -0
  40. data/spec/{asciidoctor-standoc → asciidoctor}/table_spec.rb +0 -0
  41. data/spec/{asciidoctor-standoc → asciidoctor}/validate_spec.rb +20 -0
  42. data/spec/assets/html-override.css +1 -0
  43. data/spec/assets/word-override.css +1 -0
  44. data/spec/fixtures/action_schemaexpg1.svg +122 -0
  45. data/spec/spec_helper.rb +8 -0
  46. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +62 -62
  47. data/spec/vcr_cassettes/isobib_get_123.yml +15 -15
  48. data/spec/vcr_cassettes/isobib_get_123_1.yml +30 -30
  49. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +42 -42
  50. data/spec/vcr_cassettes/isobib_get_123_2001.yml +15 -15
  51. data/spec/vcr_cassettes/isobib_get_124.yml +16 -16
  52. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +94 -30
  53. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +59 -57
  54. metadata +41 -41
  55. data/.rubocop.ribose.yml +0 -66
  56. data/.rubocop.tb.yml +0 -650
  57. data/spec/asciidoctor-standoc/macros_lutaml_spec.rb +0 -80
@@ -106,7 +106,7 @@ module Asciidoctor
106
106
  def bibdata_cleanup(xmldoc)
107
107
  bibdata_anchor_cleanup(xmldoc)
108
108
  bibdata_docidentifier_cleanup(xmldoc)
109
- biblio_indirect_erefs(xmldoc, @internal_eref_namespaces&.uniq)
109
+ biblio_indirect_erefs(xmldoc, @internal_eref_namespaces&.uniq)
110
110
  end
111
111
 
112
112
  def bibdata_anchor_cleanup(xmldoc)
@@ -124,7 +124,7 @@ module Asciidoctor
124
124
  end
125
125
  end
126
126
 
127
- def gather_indirect_erefs(xmldoc, prefix)
127
+ def gather_indirect_erefs(xmldoc, prefix)
128
128
  xmldoc.xpath("//eref[@type = '#{prefix}']").each_with_object({}) do |e, m|
129
129
  e.delete("type")
130
130
  m[e["bibitemid"]] = true
@@ -160,7 +160,7 @@ module Asciidoctor
160
160
  def resolve_local_indirect_erefs(xmldoc, refs, prefix)
161
161
  refs.each_with_object([]) do |r, m|
162
162
  id = r.sub(/^#{prefix}_/, "")
163
- if xmldoc.at("//*[@id = '#{id}'][@type = '#{prefix}']")
163
+ if n = xmldoc.at("//*[@id = '#{id}']") and n.at("./ancestor-or-self::*[@type = '#{prefix}']")
164
164
  xmldoc.xpath("//eref[@bibitemid = '#{r}']").each do |e|
165
165
  indirect_eref_to_xref(e, id)
166
166
  end
@@ -74,10 +74,11 @@ module Asciidoctor
74
74
 
75
75
  def xref_to_eref(x)
76
76
  x["bibitemid"] = x["target"]
77
- x["citeas"] = @anchors&.dig(x["target"], :xref) ||
77
+ unless x["citeas"] = @anchors&.dig(x["target"], :xref)
78
+ @internal_eref_namespaces.include?(x["type"]) or
78
79
  @log.add("Crossreferences", x,
79
- "#{x['target']} does not have a corresponding anchor ID "\
80
- "in the bibliography!")
80
+ "#{x['target']} does not have a corresponding anchor ID in the bibliography!")
81
+ end
81
82
  x.delete("target")
82
83
  extract_localities(x) unless x.children.empty?
83
84
  end
@@ -2,6 +2,7 @@ require "nokogiri"
2
2
  require "pathname"
3
3
  require "open-uri"
4
4
  require "html2doc"
5
+ require "asciimath2unitsml"
5
6
  require_relative "./cleanup_block.rb"
6
7
  require_relative "./cleanup_footnotes.rb"
7
8
  require_relative "./cleanup_ref.rb"
@@ -73,13 +74,49 @@ module Asciidoctor
73
74
  end
74
75
  end
75
76
 
77
+ UNITSML_NS = "https://schema.unitsml.org/unitsml/1.0".freeze
78
+
79
+ def add_misc_container(xmldoc)
80
+ unless ins = xmldoc.at("//misc-container")
81
+ a = xmldoc.at("//termdocsource") || xmldoc.at("//bibdata")
82
+ a.next = "<misc-container/>"
83
+ ins = xmldoc.at("//misc-container")
84
+ end
85
+ ins
86
+ end
87
+
88
+ def mathml_unitsML(xmldoc)
89
+ return unless xmldoc.at(".//m:*", "m" => UNITSML_NS)
90
+ misc = add_misc_container(xmldoc)
91
+ unitsml = misc.add_child("<UnitsML xmlns='#{UNITSML_NS}'/>").first
92
+ %w(Unit CountedItem Quantity Dimension Prefix).each do |t|
93
+ gather_unitsml(unitsml, xmldoc, t)
94
+ end
95
+ end
96
+
97
+ def gather_unitsml(unitsml, xmldoc, t)
98
+ tags = xmldoc.xpath(".//m:#{t}", "m" => UNITSML_NS).each_with_object({}) do |x, m|
99
+ m[x["id"]] = x.remove
100
+ end
101
+ return if tags.empty?
102
+ set = unitsml.add_child("<#{t}Set/>").first
103
+ tags.values.each { |v| set << v }
104
+ end
105
+
106
+ def asciimath2unitsml_options
107
+ { multiplier: :space }
108
+ end
109
+
76
110
  def mathml_cleanup(xmldoc)
111
+ unitsml = Asciimath2UnitsML::Conv.new(asciimath2unitsml_options)
77
112
  xmldoc.xpath("//stem[@type = 'MathML']").each do |x|
78
113
  xml_unescape_mathml(x)
79
114
  mathml_namespace(x)
80
115
  mathml_preserve_space(x)
81
116
  mathml_italicise(x)
117
+ unitsml.MathML2UnitsML(x)
82
118
  end
119
+ mathml_unitsML(xmldoc)
83
120
  end
84
121
  end
85
122
  end
@@ -50,6 +50,7 @@ module Asciidoctor
50
50
  def biblio_renumber(xmldoc)
51
51
  i = 0
52
52
  xmldoc.xpath("//bibliography//references | //clause//references | //annex//references").each do |r|
53
+ next if r["normative"] == "true"
53
54
  r.xpath("./bibitem").each do |b|
54
55
  i += 1
55
56
  next unless docid = b.at("./docidentifier[@type = 'metanorma']")
@@ -88,18 +89,8 @@ module Asciidoctor
88
89
  end
89
90
  end
90
91
 
91
- def docid_prefix(prefix, docid)
92
- docid = "#{prefix} #{docid}" unless omit_docid_prefix(prefix)
93
- docid
94
- end
95
-
96
- def omit_docid_prefix(prefix)
97
- return true if prefix.nil? || prefix.empty?
98
- %(ISO IEC IEV ITU metanorma).include? prefix
99
- end
100
-
101
- def format_ref(ref, type, isopub)
102
- return docid_prefix(type, ref) if isopub
92
+ def format_ref(ref, type)
93
+ return @isodoc.docid_prefix(type, ref) if type != "metanorma"
103
94
  return "[#{ref}]" if /^\d+$/.match(ref) && !/^\[.*\]$/.match(ref)
104
95
  ref
105
96
  end
@@ -115,7 +106,7 @@ module Asciidoctor
115
106
  isopub = ref.at(ISO_PUBLISHER_XPATH)
116
107
  docid = ref.at("./docidentifier[@type = 'metanorma']") ||
117
108
  ref.at("./docidentifier[not(@type = 'DOI')]") or next
118
- reference = format_ref(docid.text, docid["type"], isopub)
109
+ reference = format_ref(docid.text, docid["type"])
119
110
  @anchors[ref["id"]] = { xref: reference }
120
111
  end
121
112
  end
@@ -62,10 +62,15 @@ module Asciidoctor
62
62
  end
63
63
  end
64
64
 
65
+ def make_indexsect(x, s)
66
+ x.xpath("//sections/indexsect").reverse_each { |r| s.next = r.remove }
67
+ end
68
+
65
69
  def sections_order_cleanup(x)
66
70
  s = x.at("//sections")
67
71
  make_preface(x, s)
68
72
  make_annexes(x)
73
+ make_indexsect(x, s)
69
74
  make_bibliography(x, s)
70
75
  x.xpath("//sections/annex").reverse_each { |r| s.next = r.remove }
71
76
  end
@@ -97,7 +97,7 @@ module Asciidoctor
97
97
  termdocsource_cleanup(xmldoc)
98
98
  end
99
99
 
100
- # Indices sort after letter but before any following
100
+ # Indices sort after letter but before any following
101
101
  # letter (x, x_m, x_1, xa); we use colon to force that sort order.
102
102
  # Numbers sort *after* letters; we use thorn to force that sort order.
103
103
  def symbol_key(x)
@@ -107,7 +107,7 @@ module Asciidoctor
107
107
  n.replace(grkletters(MathML2AsciiMath.m2a(n.to_xml)))
108
108
  end
109
109
  ret = Nokogiri::XML(key.to_xml)
110
- HTMLEntities.new.decode(ret.text).
110
+ HTMLEntities.new.decode(ret.text.downcase).
111
111
  gsub(/[\[\]\{\}<>\(\)]/, "").gsub(/\s/m, "").
112
112
  gsub(/[[:punct:]]|[_^]/, ":\\0").gsub(/`/, "").
113
113
  gsub(/[0-9]+/, "þ\\0")
@@ -145,6 +145,10 @@ module Asciidoctor
145
145
  end
146
146
  end
147
147
 
148
+ def highlight_parse(text, xml)
149
+ xml << text
150
+ end
151
+
148
152
  def inline_quoted(node)
149
153
  noko do |xml|
150
154
  case node.type
@@ -157,6 +161,7 @@ module Asciidoctor
157
161
  when :subscript then xml.sub { |s| s << node.text }
158
162
  when :asciimath then stem_parse(node.text, xml, :asciimath)
159
163
  when :latexmath then stem_parse(node.text, xml, :latexmath)
164
+ when :mark then highlight_parse(node.text, xml)
160
165
  else
161
166
  case node.role
162
167
  # the following three are legacy, they are now handled by macros
@@ -175,25 +180,12 @@ module Asciidoctor
175
180
  end.join
176
181
  end
177
182
 
178
- def datauri(uri)
179
- return uri if /^data:/.match(uri)
180
- types = MIME::Types.type_for(@localdir + uri)
181
- type = types ? types.first.to_s : 'text/plain; charset="utf-8"'
182
- # FIXME: nested uri path error(
183
- # sources/plantuml/plantuml20200524-90467-1iqek5i.png ->
184
- # sources/sources/plantuml/plantuml20200524-90467-1iqek5i.png)
185
- path = File.file?(uri) ? uri : @localdir + uri
186
- bin = File.open(path, 'rb', &:read)
187
- data = Base64.strict_encode64(bin)
188
- "data:#{type};base64,#{data}"
189
- end
190
-
191
183
  def image_attributes(node)
192
184
  uri = node.image_uri (node.attr("target") || node.target)
193
- types = /^data:/.match(uri) ? datauri2mime(uri) : MIME::Types.type_for(uri)
185
+ types = /^data:/.match(uri) ? Metanorma::Utils::datauri2mime(uri) : MIME::Types.type_for(uri)
194
186
  type = types.first.to_s
195
187
  uri = uri.sub(%r{^data:image/\*;}, "data:#{type};")
196
- attr_code(src: uri, #@datauriimage ? datauri(uri) : uri,
188
+ attr_code(src: uri,
197
189
  id: Metanorma::Utils::anchor_or_uuid,
198
190
  mimetype: type,
199
191
  height: node.attr("height") || "auto",
@@ -102,7 +102,7 @@
102
102
  </attribute>
103
103
  </optional>
104
104
  <oneOrMore>
105
- <ref name="li"/>
105
+ <ref name="ul_li"/>
106
106
  </oneOrMore>
107
107
  <zeroOrMore>
108
108
  <ref name="note"/>
@@ -812,6 +812,8 @@
812
812
  <ref name="requirement"/>
813
813
  <ref name="recommendation"/>
814
814
  <ref name="permission"/>
815
+ <ref name="imagemap"/>
816
+ <ref name="svgmap"/>
815
817
  </choice>
816
818
  </define>
817
819
  <define name="bibliography">
@@ -917,6 +919,9 @@
917
919
  </choice>
918
920
  </attribute>
919
921
  <ref name="bibdata"/>
922
+ <optional>
923
+ <ref name="misccontainer"/>
924
+ </optional>
920
925
  <optional>
921
926
  <ref name="boilerplate"/>
922
927
  </optional>
@@ -927,11 +932,21 @@
927
932
  <zeroOrMore>
928
933
  <ref name="annex"/>
929
934
  </zeroOrMore>
935
+ <optional>
936
+ <ref name="bibliography"/>
937
+ </optional>
930
938
  <zeroOrMore>
931
- <ref name="references"/>
939
+ <ref name="indexsect"/>
932
940
  </zeroOrMore>
933
941
  </element>
934
942
  </define>
943
+ <define name="misccontainer">
944
+ <element name="misc-container">
945
+ <oneOrMore>
946
+ <ref name="AnyElement"/>
947
+ </oneOrMore>
948
+ </element>
949
+ </define>
935
950
  <define name="preface">
936
951
  <element name="preface">
937
952
  <oneOrMore>
@@ -955,6 +970,11 @@
955
970
  <ref name="Content-Section"/>
956
971
  </element>
957
972
  </define>
973
+ <define name="indexsect">
974
+ <element name="indexsect">
975
+ <ref name="Content-Section"/>
976
+ </element>
977
+ </define>
958
978
  <define name="boilerplate">
959
979
  <element name="boilerplate">
960
980
  <optional>
@@ -1635,4 +1655,87 @@
1635
1655
  <text/>
1636
1656
  </element>
1637
1657
  </define>
1658
+ <define name="imagemap">
1659
+ <element name="imagemap">
1660
+ <ref name="figure"/>
1661
+ <zeroOrMore>
1662
+ <element name="area">
1663
+ <attribute name="type">
1664
+ <choice>
1665
+ <value>rect</value>
1666
+ <value>circle</value>
1667
+ <value>ellipse</value>
1668
+ <value>poly</value>
1669
+ </choice>
1670
+ </attribute>
1671
+ <choice>
1672
+ <ref name="xref"/>
1673
+ <ref name="hyperlink"/>
1674
+ <ref name="eref"/>
1675
+ </choice>
1676
+ <oneOrMore>
1677
+ <element name="coords">
1678
+ <attribute name="x">
1679
+ <data type="float"/>
1680
+ </attribute>
1681
+ <attribute name="y">
1682
+ <data type="float"/>
1683
+ </attribute>
1684
+ </element>
1685
+ </oneOrMore>
1686
+ <optional>
1687
+ <element name="radius">
1688
+ <attribute name="x">
1689
+ <data type="float"/>
1690
+ </attribute>
1691
+ <optional>
1692
+ <attribute name="y">
1693
+ <data type="float"/>
1694
+ </attribute>
1695
+ </optional>
1696
+ </element>
1697
+ </optional>
1698
+ </element>
1699
+ </zeroOrMore>
1700
+ </element>
1701
+ </define>
1702
+ <define name="svgmap">
1703
+ <element name="svgmap">
1704
+ <ref name="figure"/>
1705
+ <zeroOrMore>
1706
+ <element name="target">
1707
+ <attribute name="href">
1708
+ <data type="anyURI"/>
1709
+ </attribute>
1710
+ <choice>
1711
+ <ref name="xref"/>
1712
+ <ref name="hyperlink"/>
1713
+ <ref name="eref"/>
1714
+ </choice>
1715
+ </element>
1716
+ </zeroOrMore>
1717
+ </element>
1718
+ </define>
1719
+ <define name="ul_li">
1720
+ <element name="li">
1721
+ <optional>
1722
+ <attribute name="id">
1723
+ <data type="ID"/>
1724
+ </attribute>
1725
+ </optional>
1726
+ <optional>
1727
+ <attribute name="uncheckedcheckbox">
1728
+ <data type="boolean"/>
1729
+ </attribute>
1730
+ </optional>
1731
+ <optional>
1732
+ <attribute name="checkedcheckbox">
1733
+ <data type="boolean"/>
1734
+ </attribute>
1735
+ </optional>
1736
+ <oneOrMore>
1737
+ <ref name="BasicBlock"/>
1738
+ </oneOrMore>
1739
+ </element>
1740
+ </define>
1638
1741
  </grammar>
@@ -20,12 +20,12 @@ module Asciidoctor
20
20
  node.attr("style") == "bibliography" or
21
21
  @log.add("AsciiDoc Input", node, "Section not marked up as [bibliography]!")
22
22
  @biblio = true
23
- xml.references **attr_code(attrs.merge(normative: false)) do |xml_section|
24
- #title = node.level == 1 ? "Bibliography" : node.title
25
- xml_section.title { |t| t << node.title }
26
- xml_section << node.content
27
- end
28
- @biblio = false
23
+ xml.references **attr_code(attrs.merge(
24
+ normative: node.attr("normative") || false)) do |xml_section|
25
+ xml_section.title { |t| t << node.title }
26
+ xml_section << node.content
27
+ end
28
+ @biblio = false
29
29
  end
30
30
 
31
31
  def bibitem_parse(attrs, xml, node)
@@ -43,12 +43,12 @@ module Asciidoctor
43
43
  node.attr("style") == "bibliography" or
44
44
  @log.add("AsciiDoc Input", node, "Section not marked up as [bibliography]!")
45
45
  @norm_ref = true
46
- xml.references **attr_code(attrs.merge(normative: true)) do |xml_section|
47
- #xml_section.title { |t| t << "Normative References" }
48
- xml_section.title { |t| t << node.title }
49
- xml_section << node.content
50
- end
51
- @norm_ref = false
46
+ xml.references **attr_code(attrs.merge(
47
+ normative: node.attr("normative") || true)) do |xml_section|
48
+ xml_section.title { |t| t << node.title }
49
+ xml_section << node.content
50
+ end
51
+ @norm_ref = false
52
52
  end
53
53
 
54
54
  def global_ievcache_name
@@ -88,6 +88,8 @@ module Asciidoctor
88
88
  bibliography_parse(a, xml, node)
89
89
  elsif node.attr("style") == "abstract"
90
90
  abstract_parse(a, xml, node)
91
+ elsif node.attr("style") == "index"
92
+ indexsect_parse(a, xml, node)
91
93
  elsif node.attr("style") == "appendix" && node.level == 1
92
94
  annex_parse(a, xml, node)
93
95
  else
@@ -114,6 +116,13 @@ module Asciidoctor
114
116
  end.join("\n")
115
117
  end
116
118
 
119
+ def indexsect_parse(attrs, xml, node)
120
+ xml.indexsect **attr_code(attrs) do |xml_section|
121
+ xml_section.title { |name| name << node.title }
122
+ xml_section << node.content
123
+ end
124
+ end
125
+
117
126
  def abstract_parse(attrs, xml, node)
118
127
  xml.abstract **attr_code(attrs) do |xml_section|
119
128
  xml_section << node.content
@@ -5,7 +5,6 @@ require "json"
5
5
  require "pathname"
6
6
  require "open-uri"
7
7
  require "uuidtools"
8
- require "mimemagic"
9
8
 
10
9
  module Asciidoctor
11
10
  module Standoc
@@ -57,29 +56,6 @@ module Asciidoctor
57
56
  end
58
57
  end
59
58
 
60
- def datauri2mime(uri)
61
- %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
62
- type = nil
63
- imgtype = "png" unless /^[a-z0-9]+$/.match imgtype
64
- Tempfile.open(["imageuri", ".#{imgtype}"]) do |file|
65
- type = datauri2mime1(file, imgdata)
66
- end
67
- [type]
68
- end
69
-
70
- def datauri2mime1(file, imgdata)
71
- type = nil
72
- begin
73
- file.binmode
74
- file.write(Base64.strict_decode64(imgdata))
75
- file.rewind
76
- type = MimeMagic.by_magic(file)
77
- ensure
78
- file.close!
79
- end
80
- type
81
- end
82
-
83
59
  SUBCLAUSE_XPATH = "//clause[not(parent::sections)]"\
84
60
  "[not(ancestor::boilerplate)]".freeze
85
61