metanorma-standoc 2.4.9 → 2.5.1

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: 70483d0ae3e7369ea535a02fed125b9b073c2792cc9a589c22cd94ea98948d1e
4
- data.tar.gz: 9fb3bcbfb78079b25cbdfb6f49fdefc4df8928a8d0782878396be6a6f286374c
3
+ metadata.gz: 5ccb10f13350a471175edadd3a93a922226bf6f383faa3b4bcceff74735ff5e8
4
+ data.tar.gz: c7e6f17307599cc0ae13f88868aba8c8168c1e9a638b57a8a8c325e33cf2f0be
5
5
  SHA512:
6
- metadata.gz: f2b70e60bd3f83f8218c16bf24d9ff8a164b4a0467cf6f47e4090da745034f048a5dd91d813e0242f365eccf52ab71e2af1b477b320d1e310412c8065b02742b
7
- data.tar.gz: 2008df0fab61498838336fa8ddbf94efa3845583ed1740223a877b8ad27ccfc8d257553067f3a84226ff41ef0cc2bda91b2fd90e88a2d8be2aaf3032688bebef
6
+ metadata.gz: ae8763f5ae8953bf858720cc6ab658281299794fb24a172957d144564d1ac55432a0f08611b9ab243f9f87ebf568edd508f199442ad9c4e675775d4f40cae4aa
7
+ data.tar.gz: 4e4fcee2168ab3218355a73075c50d3f42ba6d1068839dbe2260e60a8c65a25f113d55576db49e5a436ef6757a90915cc60b59150dfa30747469d898ac6fcf6d
@@ -76,7 +76,7 @@ module Metanorma
76
76
  def stem(node)
77
77
  noko do |xml|
78
78
  xml.formula **formula_attrs(node) do |s|
79
- stem_parse(node.lines.join("\n"), s, node.style.to_sym)
79
+ stem_parse(node.lines.join("\n"), s, node.style.to_sym, node.block?)
80
80
  end
81
81
  end
82
82
  end
@@ -1,24 +1,24 @@
1
1
  require "nokogiri"
2
2
  require "pathname"
3
3
  require "html2doc"
4
- require_relative "./cleanup_block"
5
- require_relative "./cleanup_table"
6
- require_relative "./cleanup_footnotes"
7
- require_relative "./cleanup_ref"
8
- require_relative "./cleanup_asciibib"
9
- require_relative "./cleanup_boilerplate"
10
- require_relative "./cleanup_bibdata"
11
- require_relative "./cleanup_section"
12
- require_relative "./cleanup_terms"
13
- require_relative "./cleanup_symbols"
14
- require_relative "./cleanup_xref"
15
- require_relative "./cleanup_inline"
16
- require_relative "./cleanup_amend"
17
- require_relative "./cleanup_maths"
18
- require_relative "./cleanup_image"
19
- require_relative "./cleanup_reqt"
20
- require_relative "./cleanup_text"
21
- require_relative "./cleanup_toc"
4
+ require_relative "cleanup_block"
5
+ require_relative "cleanup_table"
6
+ require_relative "cleanup_footnotes"
7
+ require_relative "cleanup_ref"
8
+ require_relative "cleanup_asciibib"
9
+ require_relative "cleanup_boilerplate"
10
+ require_relative "cleanup_bibdata"
11
+ require_relative "cleanup_section"
12
+ require_relative "cleanup_terms"
13
+ require_relative "cleanup_symbols"
14
+ require_relative "cleanup_xref"
15
+ require_relative "cleanup_inline"
16
+ require_relative "cleanup_amend"
17
+ require_relative "cleanup_maths"
18
+ require_relative "cleanup_image"
19
+ require_relative "cleanup_reqt"
20
+ require_relative "cleanup_text"
21
+ require_relative "cleanup_toc"
22
22
  require "relaton_iev"
23
23
 
24
24
  module Metanorma
@@ -51,6 +51,7 @@ module Metanorma
51
51
  normref_cleanup(xmldoc)
52
52
  biblio_cleanup(xmldoc)
53
53
  reference_names(xmldoc)
54
+ asciimath_cleanup(xmldoc) # feeds: mathml_cleanup, termdef_cleanup, symbols_cleanup
54
55
  symbols_cleanup(xmldoc) # feeds: termdef_cleanup
55
56
  xref_cleanup(xmldoc) # feeds: concept_cleanup, origin_cleanup
56
57
  concept_cleanup(xmldoc) # feeds: related_cleanup, termdef_cleanup
@@ -79,6 +80,7 @@ module Metanorma
79
80
  empty_element_cleanup(xmldoc)
80
81
  img_cleanup(xmldoc)
81
82
  anchor_cleanup(xmldoc)
83
+ link_cleanup(xmldoc)
82
84
  xmldoc
83
85
  end
84
86
 
@@ -107,7 +109,7 @@ module Metanorma
107
109
  end
108
110
 
109
111
  def element_name_cleanup(xmldoc)
110
- xmldoc.traverse { |n| n.name = n.name.gsub(/_/, "-") }
112
+ xmldoc.traverse { |n| n.name = n.name.gsub("_", "-") }
111
113
  end
112
114
 
113
115
  # allows us to deal with doc relation localities,
@@ -1,5 +1,6 @@
1
1
  require "metanorma-utils"
2
2
  require "digest"
3
+ require "addressable/uri"
3
4
 
4
5
  module Metanorma
5
6
  module Standoc
@@ -78,7 +79,7 @@ module Metanorma
78
79
  def concept_cleanup1(elem)
79
80
  elem.children.remove if elem&.children&.text&.strip&.empty?
80
81
  key_extract_locality(elem)
81
- if /:/.match?(elem["key"]) then concept_termbase_cleanup(elem)
82
+ if elem["key"].include?(":") then concept_termbase_cleanup(elem)
82
83
  elsif refid? elem["key"] then concept_eref_cleanup(elem)
83
84
  else concept_xref_cleanup(elem)
84
85
  end
@@ -95,15 +96,14 @@ module Metanorma
95
96
  end
96
97
 
97
98
  def key_extract_locality(elem)
98
- return unless /,/.match?(elem["key"])
99
-
99
+ elem["key"].include?(",") or return
100
100
  elem.add_child("<locality>#{elem['key'].sub(/^[^,]+,/, '')}</locality>")
101
101
  elem["key"] = elem["key"].sub(/,.*$/, "")
102
102
  end
103
103
 
104
104
  def concept_termbase_cleanup(elem)
105
105
  t = elem&.at("./xrefrender")&.remove&.children
106
- termbase, key = elem["key"].split(/:/, 2)
106
+ termbase, key = elem["key"].split(":", 2)
107
107
  elem.add_child(%(<termref base="#{termbase}" target="#{key}">) +
108
108
  "#{t&.to_xml}</termref>")
109
109
  end
@@ -207,6 +207,21 @@ module Metanorma
207
207
  end
208
208
  end
209
209
 
210
+ def link_cleanup(xmldoc)
211
+ xmldoc.xpath("//link[@target]").each do |l|
212
+ l["target"] = Addressable::URI.parse(l["target"]).to_s
213
+ rescue Addressable::URI::InvalidURIError
214
+ err = "Malformed URI: #{l['target']}"
215
+ @log.add("Anchors", l, err)
216
+ @fatalerror << err
217
+ warn err
218
+ end
219
+ end
220
+
221
+ def uri_component_encode(comp)
222
+ CGI.escape(comp).gsub("+", "%20")
223
+ end
224
+
210
225
  private
211
226
 
212
227
  # skip ZWNJ inserted to prevent regexes operating in asciidoctor
@@ -3,17 +3,28 @@ require "asciimath2unitsml"
3
3
  module Metanorma
4
4
  module Standoc
5
5
  module Cleanup
6
- def asciimath2mathml(text)
7
- text = text.gsub(%r{<stem type="AsciiMath">(.+?)</stem>}m) do
8
- "<amathstem>#{@c.decode($1)}</amathstem>"
6
+ def asciimath_cleanup(xml)
7
+ !@keepasciimath and asciimath2mathml(xml)
8
+ end
9
+
10
+ def asciimath2mathml(xml)
11
+ xpath = xml.xpath("//stem[@type = 'AsciiMath']")
12
+ xpath.each_with_index do |x, i|
13
+ progress_conv(i, 500, xpath.size, 1000, "AsciiMath")
14
+ asciimath2mathml_indiv(x)
9
15
  end
10
- text = Html2Doc.new({})
11
- .asciimath_to_mathml(text, ["<amathstem>", "</amathstem>"],
12
- retain_asciimath: true)
13
- asciimath2mathml_wrap(text)
16
+ asciimath2mathml_wrap(xml)
17
+ end
18
+
19
+ def asciimath2mathml_indiv(elem)
20
+ elem["type"] = "MathML"
21
+ expr = @c.decode(elem.text)
22
+ ret = Plurimath::Math.parse(expr, "asciimath")
23
+ .to_mathml(display_style: elem["block"])
24
+ ret += "<asciimath>#{@c.encode(@c.decode(expr), :basic)}</asciimath>"
25
+ elem.children = ret
14
26
  rescue StandardError => e
15
- asciimath2mathml_err(text, e)
16
- text
27
+ asciimath2mathml_err(elem.to_xml, e)
17
28
  end
18
29
 
19
30
  def asciimath2mathml_err(text, expr)
@@ -23,25 +34,27 @@ module Metanorma
23
34
  warn err
24
35
  end
25
36
 
26
- def asciimath2mathml_wrap(text)
27
- x = Nokogiri::XML(text)
28
- x.xpath("//*[local-name() = 'math'][@display]").each do |y|
37
+ def asciimath2mathml_wrap(xml)
38
+ xml.xpath("//*[local-name() = 'math'][@display]").each do |y|
29
39
  y.delete("display")
30
40
  end
31
- x.xpath("//*[local-name() = 'math'][not(parent::stem)]").each do |y|
32
- y.wrap("<stem type='MathML'></stem>")
33
- end
34
- x.xpath("//stem").each do |y|
35
- y.next_element&.name == "asciimath" and y << y.next_element
36
- end
37
- to_xml(x)
41
+ # x.xpath("//stem").each do |y|
42
+ # y.next_element&.name == "asciimath" and y << y.next_element
43
+ # end
44
+ xml
45
+ end
46
+
47
+ def progress_conv(idx, step, total, threshold, msg)
48
+ return unless (idx % step).zero? && total > threshold && idx.positive?
49
+
50
+ warn "#{msg} #{idx} of #{total}"
38
51
  end
39
52
 
40
53
  def xml_unescape_mathml(xml)
41
54
  return if xml.children.any?(&:element?)
42
55
 
43
- math = xml.text.gsub(/&lt;/, "<").gsub(/&gt;/, ">")
44
- .gsub(/&quot;/, '"').gsub(/&apos;/, "'").gsub(/&amp;/, "&")
56
+ math = xml.text.gsub("&lt;", "<").gsub("&gt;", ">")
57
+ .gsub("&quot;", '"').gsub("&apos;", "'").gsub("&amp;", "&")
45
58
  .gsub(/<[^: \r\n\t\/]+:/, "<").gsub(/<\/[^ \r\n\t:]+:/, "</")
46
59
  xml.children = math
47
60
  end
@@ -1,3 +1,5 @@
1
+ require "metanorma/standoc/utils"
2
+
1
3
  module Metanorma
2
4
  module Standoc
3
5
  module Cleanup
@@ -8,31 +10,12 @@ module Metanorma
8
10
  def symbol_key(sym)
9
11
  @c.decode(asciimath_key(sym).text)
10
12
  .gsub(/[\[\]{}<>()]/, "").gsub(/\s/m, "")
11
- .gsub(/[[:punct:]]|[_^]/, ":\\0").gsub(/`/, "")
13
+ .gsub(/[[:punct:]]|[_^]/, ":\\0").gsub("`", "")
12
14
  .gsub(/[0-9]+/, "þ\\0")
13
15
  .tr("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",
14
16
  "ABCFEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
15
17
  end
16
18
 
17
- def asciimath_key(sym)
18
- key = sym.dup
19
- key.traverse do |n|
20
- if n.name == "stem" && a = n.at(".//asciimath")
21
- n.children = @c.encode(
22
- @c.decode(grkletters(a.text)), :basic
23
- )
24
- end
25
- end
26
- key.xpath(".//asciimath").each(&:remove)
27
- Nokogiri::XML(key.to_xml)
28
- end
29
-
30
- def grkletters(text)
31
- text.gsub(/\b(alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|
32
- lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|
33
- psi|omega)\b/xi, "&\\1;")
34
- end
35
-
36
19
  def extract_symbols_list(dlist)
37
20
  dl_out = []
38
21
  dlist.xpath("./dt | ./dd").each do |dtd|
@@ -3,7 +3,6 @@ module Metanorma
3
3
  module Cleanup
4
4
  def textcleanup(result)
5
5
  text = result.flatten.map { |l| l.sub(/\s*\Z/, "") } * "\n"
6
- !@keepasciimath and text = asciimath2mathml(text)
7
6
  text = text.gsub(/\s+<fn /, "<fn ")
8
7
  %w(passthrough passthrough-inline).each do |v|
9
8
  text.gsub!(%r{<#{v}\s+formats="metanorma">([^<]*)
@@ -12,7 +12,7 @@ require_relative "validate"
12
12
  require_relative "utils"
13
13
  require_relative "cleanup"
14
14
  require_relative "reqt"
15
- require_relative "./macros"
15
+ require_relative "macros"
16
16
 
17
17
  module Metanorma
18
18
  module Standoc
@@ -22,6 +22,7 @@ module Metanorma
22
22
  Asciidoctor::Extensions.register do
23
23
  preprocessor Metanorma::Standoc::EmbedIncludeProcessor
24
24
  preprocessor Metanorma::Standoc::NamedEscapePreprocessor
25
+ preprocessor Metanorma::Standoc::LinkProtectPreprocessor
25
26
  preprocessor Metanorma::Standoc::Datamodel::AttributesTablePreprocessor
26
27
  preprocessor Metanorma::Standoc::Datamodel::DiagramPreprocessor
27
28
  preprocessor Metanorma::Plugin::Datastruct::Json2TextPreprocessor
@@ -138,9 +138,10 @@ module Metanorma
138
138
  noko { |xml| xml.hr }.join
139
139
  end
140
140
 
141
- def latex_parse1(text)
141
+ def latex_parse1(text, block)
142
142
  lxm_input = Unicode2LaTeX.unicode2latex(@c.decode(text))
143
- results = Plurimath::Math.parse(lxm_input, "latex").to_mathml
143
+ results = Plurimath::Math.parse(lxm_input, "latex")
144
+ .to_mathml(display_style: block)
144
145
  if results.nil?
145
146
  @log.add("Math", nil,
146
147
  "latexmlmath failed to process equation:\n#{lxm_input}")
@@ -149,22 +150,23 @@ module Metanorma
149
150
  results.sub(%r{<math ([^>]+ )?display="block"}, "<math \\1")
150
151
  end
151
152
 
152
- def stem_parse(text, xml, style)
153
+ def stem_parse(text, xml, style, block)
153
154
  if /&lt;([^:>&]+:)?math(\s+[^>&]+)?&gt; |
154
155
  <([^:>&]+:)?math(\s+[^>&]+)?>/x.match? text
155
156
  math = xml_encode(text)
156
- xml.stem type: "MathML" do |s|
157
+ xml.stem type: "MathML", block: block do |s|
157
158
  s << math
158
159
  end
159
- elsif style == :latexmath then latex_parse(text, xml)
160
+ elsif style == :latexmath then latex_parse(text, xml, block)
160
161
  else
161
- xml.stem text&.gsub(/&amp;#/, "&#"), type: "AsciiMath"
162
+ xml.stem text&.gsub("&amp;#", "&#"), type: "AsciiMath", block: block
162
163
  end
163
164
  end
164
165
 
165
- def latex_parse(text, xml)
166
- latex = latex_parse1(text) or return xml.stem type: "MathML"
167
- xml.stem type: "MathML" do |s|
166
+ def latex_parse(text, xml, block)
167
+ latex = latex_parse1(text, block) or
168
+ return xml.stem type: "MathML", block: block
169
+ xml.stem type: "MathML", block: block do |s|
168
170
  math = Nokogiri::XML.fragment(latex.sub(/<\?[^>]+>/, ""))
169
171
  .elements[0]
170
172
  math.delete("alttext")
@@ -187,8 +189,8 @@ module Metanorma
187
189
  when :single then xml << "'#{node.text}'"
188
190
  when :superscript then xml.sup { |s| s << node.text }
189
191
  when :subscript then xml.sub { |s| s << node.text }
190
- when :asciimath then stem_parse(node.text, xml, :asciimath)
191
- when :latexmath then stem_parse(node.text, xml, :latexmath)
192
+ when :asciimath then stem_parse(node.text, xml, :asciimath, false)
193
+ when :latexmath then stem_parse(node.text, xml, :latexmath, false)
192
194
  when :mark then highlight_parse(node.text, xml)
193
195
  else
194
196
  case node.role
@@ -17,7 +17,7 @@
17
17
  these elements; we just want one namespace for any child grammars
18
18
  of this.
19
19
  -->
20
- <!-- VERSION v1.2.2 -->
20
+ <!-- VERSION v1.2.3 -->
21
21
  <grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
22
22
  <include href="reqt.rng"/>
23
23
  <include href="basicdoc.rng">
@@ -192,9 +192,11 @@
192
192
  </attribute>
193
193
  </optional>
194
194
  <attribute name="citeas"/>
195
- <attribute name="type">
196
- <ref name="ReferenceFormat"/>
197
- </attribute>
195
+ <optional>
196
+ <attribute name="type">
197
+ <ref name="ReferenceFormat"/>
198
+ </attribute>
199
+ </optional>
198
200
  <optional>
199
201
  <attribute name="alt"/>
200
202
  </optional>
@@ -836,6 +838,26 @@
836
838
  <ref name="paragraph"/>
837
839
  </element>
838
840
  </define>
841
+ <define name="stem">
842
+ <element name="stem">
843
+ <attribute name="type">
844
+ <choice>
845
+ <value>MathML</value>
846
+ <value>AsciiMath</value>
847
+ <value>LatexMath</value>
848
+ </choice>
849
+ </attribute>
850
+ <attribute name="block">
851
+ <data type="boolean"/>
852
+ </attribute>
853
+ <oneOrMore>
854
+ <choice>
855
+ <text/>
856
+ <ref name="AnyElement"/>
857
+ </choice>
858
+ </oneOrMore>
859
+ </element>
860
+ </define>
839
861
  <define name="em">
840
862
  <element name="em">
841
863
  <zeroOrMore>
@@ -1,14 +1,14 @@
1
1
  require "uuidtools"
2
2
  require "yaml"
3
3
  require "csv"
4
- require_relative "./macros_inline"
5
- require_relative "./macros_plantuml"
6
- require_relative "./macros_terms"
7
- require_relative "./macros_form"
8
- require_relative "./macros_note"
9
- require_relative "./macros_embed"
10
- require_relative "./datamodel/attributes_table_preprocessor"
11
- require_relative "./datamodel/diagram_preprocessor"
4
+ require_relative "macros_inline"
5
+ require_relative "macros_plantuml"
6
+ require_relative "macros_terms"
7
+ require_relative "macros_form"
8
+ require_relative "macros_note"
9
+ require_relative "macros_embed"
10
+ require_relative "datamodel/attributes_table_preprocessor"
11
+ require_relative "datamodel/diagram_preprocessor"
12
12
  require "metanorma-plugin-datastruct"
13
13
  require "metanorma-plugin-glossarist"
14
14
  require "metanorma-plugin-lutaml"
@@ -22,7 +22,7 @@ module Metanorma
22
22
 
23
23
  def init_indent(line)
24
24
  /^(?<prefix>[ \t]*)(?<suffix>.*)$/ =~ line
25
- prefix = prefix.gsub(/\t/, "\u00a0\u00a0\u00a0\u00a0")
25
+ prefix = prefix.gsub("\t", "\u00a0\u00a0\u00a0\u00a0")
26
26
  .gsub(/ /, "\u00a0")
27
27
  prefix + suffix
28
28
  end
@@ -31,9 +31,9 @@ module Metanorma
31
31
  ignore = false
32
32
  lines.each_with_index do |l, i|
33
33
  /^(--+|====+|\|===|\.\.\.\.+|\*\*\*\*+|\+\+\+\++|````+|____\+)$/
34
- .match(l) && (ignore = !ignore)
35
- next if l.empty? || l.match(/ \+$/) || /^\[.*\]$/.match?(l) || ignore
36
- next if i == lines.size - 1 ||
34
+ .match(l) and (ignore = !ignore)
35
+ next if l.empty? || l.match(/ \+$/) || /^\[.*\]$/.match?(l) ||
36
+ ignore || i == lines.size - 1 ||
37
37
  (i < lines.size - 1 && lines[i + 1].empty?)
38
38
 
39
39
  lines[i] += " +"
@@ -60,5 +60,111 @@ module Metanorma
60
60
  ::Asciidoctor::Reader.new lines
61
61
  end
62
62
  end
63
+
64
+ # refer https://github.com/asciidoctor/asciidoctor/blob/main/lib/asciidoctor/substitutors.rb
65
+ # Not using TreeProcessor because that is still too close to
66
+ # inline expressions being processed on access (e.g. titles)
67
+ class LinkProtectPreprocessor < Asciidoctor::Extensions::Preprocessor
68
+ def init
69
+ pass = true # process as passthrough: init = true until
70
+ # hit end of doc header
71
+ is_delim = false # current line is a no-substititon block delimiter
72
+ pass_delim = false # current line is a passthrough delimiter
73
+ delimln = "" # delimiter line of current block(s);
74
+ # init value looks for end of doc header
75
+ { pass: pass, is_delim: is_delim, pass_delim: pass_delim,
76
+ delimln: delimln }
77
+ end
78
+
79
+ def process(_document, reader)
80
+ p = init
81
+ lines = reader.readlines.map do |t|
82
+ p = pass_status(p, t.rstrip)
83
+ !p[:pass] && t.include?(":") and t = inlinelinkmacro(inlinelink(t))
84
+ t
85
+ end
86
+ ::Asciidoctor::Reader.new lines
87
+ end
88
+
89
+ def pass_status(status, text)
90
+ text == "++++" && !status[:delimln] and status[:pass] = !status[:pass]
91
+ if status[:is_delim] && /^(-+|\*+|=+|_+)$/.match?(text)
92
+ status[:delimln] = text
93
+ status[:pass] = true
94
+ elsif status[:pass_delim]
95
+ status[:delimln] = "" # end of paragraph for paragraph with [pass]
96
+ elsif status[:delimln] && text == status[:delimln]
97
+ status[:pass] = false
98
+ status[:delimln] = nil
99
+ end
100
+ status[:is_delim] = /^\[(source|listing|literal|pass)\b/.match?(text)
101
+ status[:pass_delim] = /^\[(pass)\b/.match?(text)
102
+ status
103
+ end
104
+
105
+ PASS_INLINE_MACROS = %w(pass pass-format identifier std-link stem)
106
+ .join("|").freeze
107
+
108
+ PASS_INLINE_MACRO_STR = <<~REGEX.freeze
109
+ (
110
+ \\b(?<!-) # word-separator, no hyphen
111
+ (?: # don't capture these!
112
+ (?:#{PASS_INLINE_MACROS}):[^\\s\\[]* | # macro name, :, second key. OR:
113
+ span:uri \\b [^\\s\\[]* # span:uri, third key
114
+ )
115
+ \\[.*?(?<!\\\\)\\] # [ ... ] not preceded by \\
116
+ )
117
+ REGEX
118
+ PASS_INLINE_MACRO_RX = /#{PASS_INLINE_MACRO_STR}/xo.freeze
119
+
120
+ def pass_inline_split(text)
121
+ text.split(PASS_INLINE_MACRO_RX).each.map do |x|
122
+ PASS_INLINE_MACRO_RX.match?(x) ? x : yield(x)
123
+ end
124
+ end
125
+
126
+ # InlineLinkRx = %r((^|link:|#{CG_BLANK}|&lt;|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)\[(|#{CC_ALL}*?[^\\])\]|([^\s\[\]<]*([^\s,.?!\[\]<\)]))))m
127
+ #
128
+ InlineLinkRx = %r((^|(?<!-)\blink:(?!\+)|\p{Blank}|&lt;|[<>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)(?:(\[(|.*?[^\\])\])|([^\s\[\]<]*([^\s,.?!\[\]<\)])))))m.freeze
129
+
130
+ def inlinelink(text)
131
+ text.include?("://") or return text
132
+ pass_inline_split(text) do |x|
133
+ inlinelink_escape(x)
134
+ end.join
135
+ end
136
+
137
+ def inlinelink_escape(text)
138
+ text.gsub(InlineLinkRx) do
139
+ body, suffix = $4.nil? ? [$3 + $6, "[]"] : [$3, ""]
140
+ p = $1 and s = $2 and b = $4
141
+ if p == "link:" then "#{p}++#{s}#{body}++#{b}#{suffix}"
142
+ elsif p == "<"
143
+ "#{p}link:++#{s}#{body.sub(/>$/, '')}++#{b}#{suffix}>"
144
+ else "#{p}link:++#{s}#{body}++#{b}#{suffix}"
145
+ end
146
+ end
147
+ end
148
+
149
+ # InlineLinkMacroRx = /\\?(?:link|(mailto)):(|[^:\s\[][^\s\[]*)\[(|#{CC_ALL}*?[^\\])\]/m
150
+ InlineLinkMacroRx1 = <<~REGEX.freeze
151
+ (\\\\?\\b(?<!-) # optional backslash, no hyphen, word boundary
152
+ (?:link|mailto):) # link: or mailto:
153
+ (?!\\+) # no link:+ passthrough
154
+ (|[^:\\s\\[][^\\s\\[]*) # link: ... up to [
155
+ (\\[(|.*?[^\\\\])\\]) # [ ... ], no ]
156
+ REGEX
157
+ InlineLinkMacroRx = /#{InlineLinkMacroRx1}/x.freeze
158
+
159
+ def inlinelinkmacro(text)
160
+ (text.include?("[") &&
161
+ ((text.include? "link:") || (text.include? "ilto:"))) or return text
162
+ pass_inline_split(text) do |x|
163
+ x.gsub(InlineLinkMacroRx) do
164
+ "#{$1}++#{$2}++#{$3}"
165
+ end
166
+ end.join
167
+ end
168
+ end
63
169
  end
64
170
  end
@@ -44,7 +44,7 @@ module Metanorma
44
44
  text = attr["text"]
45
45
  text = "((#{text}))" unless /^\(\(.+\)\)$/.match?(text)
46
46
  out = parent.sub_macros(text)
47
- out.sub(/<index>/, "<index to='#{target}'>")
47
+ out.sub("<index>", "<index to='#{target}'>")
48
48
  end
49
49
  end
50
50
 
@@ -148,7 +148,7 @@ module Metanorma
148
148
  content = CSV.parse_line(out).map do |x|
149
149
  x.sub!(/^(["'])(.+)\1/, "\\2")
150
150
  m = /^(.*?)(:\d+)?$/.match(x)
151
- %{<toc-xpath depth='#{m[2]&.sub(/:/, '') || 1}'>#{m[1]}</toc-xpath>}
151
+ %{<toc-xpath depth='#{m[2]&.sub(':', '') || 1}'>#{m[1]}</toc-xpath>}
152
152
  end.join
153
153
  "<toc>#{content}</toc>"
154
154
  end
@@ -49,7 +49,8 @@ module Metanorma
49
49
  def concept_cleanup
50
50
  xmldoc.xpath("//concept").each do |n|
51
51
  refterm = n.at("./refterm") or next
52
- p = @termlookup[:secondary2primary][@c.encode(refterm.text)] and
52
+ lookup = normalize_ref_id_text(refterm.text.strip)
53
+ p = @termlookup[:secondary2primary][lookup] and
53
54
  refterm.children = @c.encode(p)
54
55
  end
55
56
  end
@@ -61,7 +62,7 @@ module Metanorma
61
62
  def related_cleanup
62
63
  xmldoc.xpath("//related").each do |n|
63
64
  refterm = n.at("./refterm") or next
64
- lookup = @c.encode(refterm.text)
65
+ lookup = normalize_ref_id_text(refterm.text.strip)
65
66
  p = @termlookup[:secondary2primary][lookup] and
66
67
  refterm.children = @c.encode(p)
67
68
  p || @termlookup[:term][lookup] and
@@ -133,7 +134,7 @@ module Metanorma
133
134
  end
134
135
 
135
136
  def remove_missing_ref_msg1(_node, target, ret)
136
- target2 = "_#{target.downcase.gsub(/-/, '_')}"
137
+ target2 = "_#{target.downcase.gsub('-', '_')}"
137
138
  if @terms_tags[target] || @terms_tags[target2]
138
139
  ret.strip!
139
140
  ret += ". Did you mean to point to a subterm?"
@@ -185,17 +186,20 @@ module Metanorma
185
186
 
186
187
  def pref_secondary2primary_preferred(term, res, primary)
187
188
  term.xpath("./preferred//name").each_with_index do |p, i|
188
- i.positive? and res[domain_prefix(term, p.text)] = primary
189
- @unique_designs[p.text] && term.at(".//domain") and
190
- res[p.text] = primary
189
+ t = p.text.strip
190
+ i.positive? and
191
+ res[normalize_ref_id_text(domain_prefix(term, t))] = primary
192
+ @unique_designs[t] && term.at(".//domain") and
193
+ res[normalize_ref_id_text(t)] = primary
191
194
  end
192
195
  end
193
196
 
194
197
  def pref_secondary2primary_admitted(term, res, primary)
195
198
  term.xpath("./admitted//name").each do |p|
196
- res[domain_prefix(term, p.text)] = primary
197
- @unique_designs[p.text] && term.at(".//domain") and
198
- res[p.text] = primary
199
+ t = p.text.strip
200
+ res[normalize_ref_id_text(domain_prefix(term, t))] = primary
201
+ @unique_designs[t] && term.at(".//domain") and
202
+ res[normalize_ref_id_text(t)] = primary
199
203
  end
200
204
  end
201
205
 
@@ -234,9 +238,13 @@ module Metanorma
234
238
  def normalize_ref_id1(term, node = nil)
235
239
  t = term.dup
236
240
  t.xpath(".//index").map(&:remove)
237
- ret = t.text.strip
241
+ ret = asciimath_key(t).text.strip
238
242
  node and ret = domain_prefix(node, ret)
239
- Metanorma::Utils::to_ncname(ret.gsub(/[[:space:]]+/, "-"))
243
+ normalize_ref_id_text(ret)
244
+ end
245
+
246
+ def normalize_ref_id_text(text)
247
+ Metanorma::Utils::to_ncname(text.gsub(/[[:space:]]+/, "-"))
240
248
  end
241
249
 
242
250
  def unique_text_id(text, prefix)
@@ -248,6 +256,8 @@ module Metanorma
248
256
  end
249
257
  end
250
258
  end
259
+
260
+ include ::Metanorma::Standoc::Utils
251
261
  end
252
262
  end
253
263
  end
@@ -70,10 +70,10 @@ module Metanorma
70
70
 
71
71
  def xml_encode(text)
72
72
  @c.encode(text, :basic, :hexadecimal)
73
- .gsub(/&amp;gt;/, ">").gsub(/&amp;lt;/, "<").gsub(/&amp;amp;/, "&")
74
- .gsub(/&gt;/, ">").gsub(/&lt;/, "<").gsub(/&amp;/, "&")
75
- .gsub(/&quot;/, '"').gsub(/&#xa;/, "\n").gsub(/&amp;#/, "&#")
76
- .gsub(/&apos;/, "'")
73
+ .gsub("&amp;gt;", ">").gsub("&amp;lt;", "<").gsub("&amp;amp;", "&")
74
+ .gsub("&gt;", ">").gsub("&lt;", "<").gsub("&amp;", "&")
75
+ .gsub("&quot;", '"').gsub("&#xa;", "\n").gsub("&amp;#", "&#")
76
+ .gsub("&apos;", "'")
77
77
  end
78
78
 
79
79
  # wrapped in <sections>
@@ -85,6 +85,25 @@ module Metanorma
85
85
  Nokogiri::XML(c).at("//xmlns:sections")
86
86
  end
87
87
 
88
+ def asciimath_key(sym)
89
+ key = sym.dup
90
+ key.traverse do |n|
91
+ if n.name == "stem" && a = n.at(".//asciimath")
92
+ n.children = @c.encode(
93
+ @c.decode(grkletters(a.text)), :basic
94
+ )
95
+ end
96
+ end
97
+ key.xpath(".//asciimath").each(&:remove)
98
+ Nokogiri::XML(key.to_xml)
99
+ end
100
+
101
+ def grkletters(text)
102
+ text.gsub(/\b(alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|
103
+ lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|
104
+ psi|omega)\b/xi, "&\\1;")
105
+ end
106
+
88
107
  module_function :adoc2xml
89
108
 
90
109
  class EmptyAttr
@@ -1,7 +1,7 @@
1
1
  require "metanorma/standoc/utils"
2
- require_relative "./validate_section"
3
- require_relative "./validate_table"
4
- require_relative "./validate_term"
2
+ require_relative "validate_section"
3
+ require_relative "validate_table"
4
+ require_relative "validate_term"
5
5
  require "nokogiri"
6
6
  require "jing"
7
7
  require "iev"
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "2.4.9".freeze
22
+ VERSION = "2.5.1".freeze
23
23
  end
24
24
  end
@@ -28,10 +28,11 @@ Gem::Specification.new do |spec|
28
28
  end
29
29
  spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
30
30
 
31
+ spec.add_dependency "addressable", "~> 2.8.0"
31
32
  spec.add_dependency "asciidoctor", "~> 2.0.0"
32
33
  spec.add_dependency "iev", "~> 0.3.0"
33
- spec.add_dependency "isodoc", "~> 2.5.4"
34
- spec.add_dependency "metanorma", ">= 1.5.0"
34
+ spec.add_dependency "isodoc", "~> 2.6.0"
35
+ spec.add_dependency "metanorma", ">= 1.6.0"
35
36
  spec.add_dependency "metanorma-plugin-datastruct", "~> 0.2.0"
36
37
  spec.add_dependency "metanorma-plugin-glossarist", "~> 0.1.1"
37
38
  spec.add_dependency "metanorma-plugin-lutaml"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-standoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.9
4
+ version: 2.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-24 00:00:00.000000000 Z
11
+ date: 2023-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: addressable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.8.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.8.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: asciidoctor
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,28 +58,28 @@ dependencies:
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: 2.5.4
61
+ version: 2.6.0
48
62
  type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: 2.5.4
68
+ version: 2.6.0
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: metanorma
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
60
74
  - !ruby/object:Gem::Version
61
- version: 1.5.0
75
+ version: 1.6.0
62
76
  type: :runtime
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - ">="
67
81
  - !ruby/object:Gem::Version
68
- version: 1.5.0
82
+ version: 1.6.0
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: metanorma-plugin-datastruct
71
85
  requirement: !ruby/object:Gem::Requirement