metanorma-standoc 2.1.5 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metanorma/standoc/base.rb +1 -0
  3. data/lib/metanorma/standoc/blocks.rb +1 -2
  4. data/lib/metanorma/standoc/cleanup.rb +1 -1
  5. data/lib/metanorma/standoc/cleanup_biblio.rb +204 -0
  6. data/lib/metanorma/standoc/cleanup_block.rb +6 -4
  7. data/lib/metanorma/standoc/cleanup_maths.rb +2 -15
  8. data/lib/metanorma/standoc/cleanup_ref.rb +22 -13
  9. data/lib/metanorma/standoc/cleanup_reqt.rb +37 -4
  10. data/lib/metanorma/standoc/cleanup_symbols.rb +1 -1
  11. data/lib/metanorma/standoc/cleanup_text.rb +10 -8
  12. data/lib/metanorma/standoc/cleanup_xref.rb +1 -2
  13. data/lib/metanorma/standoc/converter.rb +2 -0
  14. data/lib/metanorma/standoc/front.rb +1 -1
  15. data/lib/metanorma/standoc/inline.rb +8 -4
  16. data/lib/metanorma/standoc/isodoc.rng +6 -1
  17. data/lib/metanorma/standoc/macros.rb +1 -180
  18. data/lib/metanorma/standoc/macros_inline.rb +194 -0
  19. data/lib/metanorma/standoc/ref_sect.rb +2 -2
  20. data/lib/metanorma/standoc/ref_utility.rb +1 -1
  21. data/lib/metanorma/standoc/reqt.rb +5 -5
  22. data/lib/metanorma/standoc/reqt.rng +1 -1
  23. data/lib/metanorma/standoc/version.rb +1 -1
  24. data/metanorma-standoc.gemspec +2 -3
  25. data/spec/metanorma/{refs_dl_spec.rb → biblio_spec.rb} +84 -1
  26. data/spec/metanorma/blocks_spec.rb +18 -8
  27. data/spec/metanorma/cleanup_blocks_spec.rb +24 -27
  28. data/spec/metanorma/inline_spec.rb +4 -0
  29. data/spec/metanorma/macros_spec.rb +2 -0
  30. data/spec/vcr_cassettes/bsi16341.yml +55 -55
  31. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +45 -45
  32. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +12 -12
  33. data/spec/vcr_cassettes/hide_refs.yml +59 -59
  34. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  35. data/spec/vcr_cassettes/isobib_get_123_1.yml +25 -25
  36. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +32 -32
  37. data/spec/vcr_cassettes/isobib_get_123_2.yml +22 -22
  38. data/spec/vcr_cassettes/isobib_get_123_2001.yml +13 -13
  39. data/spec/vcr_cassettes/isobib_get_124.yml +12 -12
  40. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +24 -24
  41. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +45 -45
  42. data/spec/vcr_cassettes/std-link.yml +11 -11
  43. metadata +7 -6
  44. data/lib/metanorma/standoc/cleanup_ref_dl.rb +0 -113
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9487b5701cc86946c27e560e244cc4f84fceb61b0a93dd271068875654eb49a0
4
- data.tar.gz: c647cf6fb530aba3bc96c9087e7a9d49408ce239a6c6aa3a4a46a0e8cf1a5763
3
+ metadata.gz: 2d1015766df2dd6accbfd8de285d762403a1d874fcac93a3d6829055602f2904
4
+ data.tar.gz: b185321cbbbcb6de4bfb9cea996dec314e585f54fbdf7baf31fcce616be60ef5
5
5
  SHA512:
6
- metadata.gz: c8356539be6d28f5dc6d4d148cfcabb8ed7dbc033392544d382d36e1e392e33da6b29a64b535f6c24cdab85a4d17d1dc5698367f0edff8f45eb02b1f8ed97330
7
- data.tar.gz: 13c49550edea0d6169fef67357a5030e146cdf62fec3cb41900db7490d95c09f9dbb1c4f4b55bea4836651ba11fcaf0714b20f37fc3a96a48dd31596cf564549
6
+ metadata.gz: 9aa957125f263ab18defd53ff0086519c43de991346bbf1775ae10907a9a06e551b3b3ddc5bf078dc968f6cbbfb863f6690643d093ad8d29b22f490815e745cc
7
+ data.tar.gz: d687658d8b5d8e6194655f3e40605d9f5e610c599631e5bf13de586daaeefa0f57a22614884e71321abdc248f55dd42113fdc068e4ceb296cc88102f27db6acf
@@ -50,6 +50,7 @@ module Metanorma
50
50
  @index_terms = node.attr("index-terms")
51
51
  @boilerplateauthority = node.attr("boilerplate-authority")
52
52
  @embed_hdr = node.attr("embed_hdr")
53
+ @document_scheme = node.attr("document-scheme")
53
54
  end
54
55
 
55
56
  def init_processing(node)
@@ -238,11 +238,10 @@ module Metanorma
238
238
  end
239
239
 
240
240
  def pass(node)
241
- c = HTMLEntities.new
242
241
  noko do |xml|
243
242
  xml.passthrough **attr_code(formats:
244
243
  node.attr("format") || "metanorma") do |p|
245
- p << c.encode(c.decode(node.content), :basic, :hexadecimal)
244
+ p << @c.encode(@c.decode(node.content), :basic, :hexadecimal)
246
245
  end
247
246
  end
248
247
  end
@@ -5,7 +5,7 @@ require_relative "./cleanup_block"
5
5
  require_relative "./cleanup_table"
6
6
  require_relative "./cleanup_footnotes"
7
7
  require_relative "./cleanup_ref"
8
- require_relative "./cleanup_ref_dl"
8
+ require_relative "./cleanup_biblio"
9
9
  require_relative "./cleanup_boilerplate"
10
10
  require_relative "./cleanup_section"
11
11
  require_relative "./cleanup_terms"
@@ -0,0 +1,204 @@
1
+ require "set"
2
+ require "relaton_bib"
3
+
4
+ module Metanorma
5
+ module Standoc
6
+ module Cleanup
7
+ def ref_dl_cleanup(xmldoc)
8
+ xmldoc.xpath("//clause[@bibitem = 'true']").each do |c|
9
+ bib = dl_bib_extract(c) or next
10
+ validate_ref_dl(bib, c)
11
+ bibitemxml = RelatonBib::BibliographicItem.from_hash(bib).to_xml or next
12
+ bibitem = Nokogiri::XML(bibitemxml)
13
+ bibitem.root["id"] = c["id"] if c["id"] && !/^_/.match(c["id"])
14
+ c.replace(bibitem.root)
15
+ end
16
+ end
17
+
18
+ # do not accept implicit id
19
+ def validate_ref_dl(bib, clause)
20
+ id = bib["id"]
21
+ id ||= clause["id"] unless /^_/.match?(clause["id"])
22
+ unless id
23
+ @log.add("Anchors", clause,
24
+ "The following reference is missing an anchor:\n"\
25
+ "#{clause.to_xml}")
26
+ return
27
+ end
28
+ @refids << id
29
+ validate_ref_dl1(bib, id, clause)
30
+ end
31
+
32
+ def validate_ref_dl1(bib, id, clause)
33
+ bib["title"] or
34
+ @log.add("Bibliography", clause, "Reference #{id} is missing a title")
35
+ bib["docid"] or
36
+ @log.add("Bibliography", clause,
37
+ "Reference #{id} is missing a document identifier (docid)")
38
+ end
39
+
40
+ def extract_from_p(tag, bib, key)
41
+ return unless bib[tag]
42
+
43
+ "<#{key}>#{bib[tag].at('p').children}</#{key}>"
44
+ end
45
+
46
+ # if the content is a single paragraph, replace it with its children
47
+ # single links replaced with uri
48
+ def p_unwrap(para)
49
+ elems = para.elements
50
+ if elems.size == 1 && elems[0].name == "p"
51
+ link_unwrap(elems[0]).children.to_xml.strip
52
+ else
53
+ para.to_xml.strip
54
+ end
55
+ end
56
+
57
+ def link_unwrap(para)
58
+ elems = para.elements
59
+ if elems.size == 1 && elems[0].name == "link"
60
+ para.at("./link").replace(elems[0]["target"].strip)
61
+ end
62
+ para
63
+ end
64
+
65
+ def dd_bib_extract(dtd)
66
+ return nil if dtd.children.empty?
67
+
68
+ dtd.at("./dl") and return dl_bib_extract(dtd)
69
+ elems = dtd.remove.elements
70
+ return p_unwrap(dtd) unless elems.size == 1 &&
71
+ %w(ol ul).include?(elems[0].name)
72
+
73
+ elems[0].xpath("./li").each_with_object([]) do |li, ret|
74
+ ret << p_unwrap(li)
75
+ end
76
+ end
77
+
78
+ def add_to_hash(bib, key, val)
79
+ Metanorma::Utils::set_nested_value(bib, key.split("."), val)
80
+ end
81
+
82
+ # definition list, with at most one level of unordered lists
83
+ def dl_bib_extract(clause, nested = false)
84
+ dl = clause.at("./dl") or return
85
+ key = ""
86
+ bib = dl.xpath("./dt | ./dd").each_with_object({}) do |dtd, m|
87
+ (dtd.name == "dt" and key = dtd.text.sub(/:+$/, "")) or
88
+ add_to_hash(m, key, dd_bib_extract(dtd))
89
+ end
90
+ clause.xpath("./clause").each do |c1|
91
+ key = c1&.at("./title")&.text&.downcase&.strip
92
+ next unless %w(contributor relation series).include? key
93
+
94
+ add_to_hash(bib, key, dl_bib_extract(c1, true))
95
+ end
96
+ dl_bib_extract_title(bib, clause, nested)
97
+ end
98
+
99
+ def dl_bib_extract_title(bib, clause, nested)
100
+ (!nested && clause.at("./title")) or return bib
101
+ title = clause.at("./title").remove.children.to_xml
102
+ bib["title"] = [bib["title"]] if bib["title"].is_a?(Hash) ||
103
+ bib["title"].is_a?(String)
104
+ bib["title"] ||= []
105
+ bib["title"] << title if !title.empty?
106
+ bib
107
+ end
108
+
109
+ # ---
110
+
111
+ def formattedref_spans(xmldoc)
112
+ xmldoc.xpath("//bibitem[formattedref//span]").each do |b|
113
+ spans_to_bibitem(b, spans_preprocess(extract_content(b)))
114
+ end
115
+ end
116
+
117
+ def extract_content(bib)
118
+ extract_docid(bib) + extract_spans(bib)
119
+ end
120
+
121
+ def extract_spans(bib)
122
+ bib.xpath("./formattedref//span").each_with_object([]) do |s, m|
123
+ keys = s["class"].split(".", 2)
124
+ m << { key: keys[0], type: keys[1],
125
+ val: s.children.to_xml }
126
+ (s["class"] == "type" and s.remove) or s.replace(s.children)
127
+ end
128
+ end
129
+
130
+ def extract_docid(bib)
131
+ bib.xpath("./docidentifier").each_with_object([]) do |d, m|
132
+ m << { key: "docid", type: d["type"], val: d.text }
133
+ d.remove
134
+ end
135
+ end
136
+
137
+ def spans_preprocess(spans)
138
+ ret = { contributor: [], docid: [], uri: [], date: [] }
139
+ spans.each do |s|
140
+ case s[:key]
141
+ when "uri", "docid"
142
+ ret[s[:key].to_sym] << { type: s[:type], val: s[:val] }
143
+ when "pubyear" then ret[:date] << { type: "published", val: s[:val] }
144
+ when "pubplace", "title", "type" then ret[s[:key].to_sym] = s[:val]
145
+ when "publisher"
146
+ ret[:contributor] << { role: "publisher", entity: "organization",
147
+ name: s[:val] }
148
+ when "surname", "initials", "givenname"
149
+ ret[:contributor] = spans_preprocess_contrib(s, ret[:contributor])
150
+ end
151
+ end
152
+ ret
153
+ end
154
+
155
+ def spans_preprocess_contrib(span, contrib)
156
+ spans_preprocess_new_contrib?(span, contrib) and
157
+ contrib << { role: span[:type] || "author", entity: "person" }
158
+ contrib[-1][span[:key].to_sym] = span[:val]
159
+ contrib
160
+ end
161
+
162
+ def spans_preprocess_new_contrib?(span, contrib)
163
+ contrib.empty? ||
164
+ (if span[:key] == "surname" then contrib[-1][:surname]
165
+ else (contrib[-1][:initials] || contrib[-1][:givenname])
166
+ end) ||
167
+ contrib[-1][:role] != (span[:type] || "author")
168
+ end
169
+
170
+ def spans_to_bibitem(bib, spans)
171
+ ret = ""
172
+ spans[:title] and ret += "<title>#{spans[:title]}</title>"
173
+ spans[:uri].each { |s| ret += span_to_docid(s, "uri") }
174
+ spans[:docid].each { |s| ret += span_to_docid(s, "docidentifier") }
175
+ spans[:date].each { |s| ret += span_to_docid(s, "date") }
176
+ spans[:contributor].each { |s| ret += span_to_contrib(s) }
177
+ spans[:pubplace] and ret += "<place>#{spans[:place]}</place>"
178
+ spans[:type] and bib["type"] = spans[:type]
179
+ bib << ret
180
+ end
181
+
182
+ def span_to_docid(span, key)
183
+ if span[:type]
184
+ "<#{key} type='#{span[:type]}'>#{span[:val]}</#{key}>"
185
+ else
186
+ "<#{key}>#{span[:val]}</#{key}>"
187
+ end
188
+ end
189
+
190
+ def span_to_contrib(span)
191
+ e = if span[:entity] == "organization"
192
+ "<organization><name>#{span[:name]}</name></organization>"
193
+ else
194
+ pre = (span[:initials] and
195
+ "<initial>#{span[:initials]}</initial>") ||
196
+ "<forename>#{span[:givenname]}</forename>"
197
+ "<person><name>#{pre}<surname>#{span[:surname]}</surname></name>"\
198
+ "</person>"
199
+ end
200
+ "<contributor><role type='#{span[:role]}'/>#{e}</contributor>"
201
+ end
202
+ end
203
+ end
204
+ end
@@ -45,7 +45,8 @@ module Metanorma
45
45
 
46
46
  def figure_dl_cleanup1(xmldoc)
47
47
  q = "//figure/following-sibling::*[self::dl]"
48
- xmldoc.xpath(q).each do |s|
48
+ q1 = "//figure/figure/following-sibling::*[self::dl]"
49
+ (xmldoc.xpath(q) - xmldoc.xpath(q1)).each do |s|
49
50
  s["key"] == "true" and s.previous_element << s.remove
50
51
  end
51
52
  end
@@ -65,8 +66,9 @@ module Metanorma
65
66
  # examples containing only figures become subfigures of figures
66
67
  def subfigure_cleanup(xmldoc)
67
68
  xmldoc.xpath("//example[figure]").each do |e|
68
- next unless e.elements.map(&:name).reject do |m|
69
- %w(name figure index).include? m
69
+ next unless e.elements.reject do |m|
70
+ %w(name figure index note).include?(m.name) ||
71
+ (m.name == "dl" && m["key"] == "true")
70
72
  end.empty?
71
73
 
72
74
  e.name = "figure"
@@ -84,9 +86,9 @@ module Metanorma
84
86
 
85
87
  def figure_cleanup(xmldoc)
86
88
  figure_footnote_cleanup(xmldoc)
89
+ subfigure_cleanup(xmldoc)
87
90
  figure_dl_cleanup1(xmldoc)
88
91
  figure_dl_cleanup2(xmldoc)
89
- subfigure_cleanup(xmldoc)
90
92
  single_subfigure_cleanup(xmldoc)
91
93
  end
92
94
 
@@ -1,24 +1,11 @@
1
- require "nokogiri"
2
- require "pathname"
3
- require "html2doc"
4
1
  require "asciimath2unitsml"
5
- require_relative "./cleanup_block"
6
- require_relative "./cleanup_footnotes"
7
- require_relative "./cleanup_ref"
8
- require_relative "./cleanup_ref_dl"
9
- require_relative "./cleanup_boilerplate"
10
- require_relative "./cleanup_section"
11
- require_relative "./cleanup_terms"
12
- require_relative "./cleanup_inline"
13
- require_relative "./cleanup_amend"
14
- require "relaton_iev"
15
2
 
16
3
  module Metanorma
17
4
  module Standoc
18
5
  module Cleanup
19
6
  def asciimath2mathml(text)
20
7
  text = text.gsub(%r{<stem type="AsciiMath">(.+?)</stem>}m) do
21
- "<amathstem>#{HTMLEntities.new.decode($1)}</amathstem>"
8
+ "<amathstem>#{@c.decode($1)}</amathstem>"
22
9
  end
23
10
  text = Html2Doc.new({})
24
11
  .asciimath_to_mathml(text, ["<amathstem>", "</amathstem>"])
@@ -60,7 +47,7 @@ module Metanorma
60
47
  def mathml_italicise(xml)
61
48
  xml.xpath(".//m:mi[not(ancestor::*[@mathvariant])]",
62
49
  "m" => MATHML_NS).each do |i|
63
- char = HTMLEntities.new.decode(i.text)
50
+ char = @c.decode(i.text)
64
51
  i["mathvariant"] = "normal" if mi_italicise?(char)
65
52
  end
66
53
  end
@@ -153,29 +153,28 @@ module Metanorma
153
153
 
154
154
  def reference_names(xmldoc)
155
155
  xmldoc.xpath("//bibitem[not(ancestor::bibitem)]").each do |ref|
156
- docid = ref.at("./docidentifier[@type = 'metanorma']") ||
157
- ref.at("./docidentifier[@primary = 'true'][@language = '#{@lang}']") ||
158
- ref.at("./docidentifier[@primary = 'true'][not(@language)]") ||
159
- ref.at("./docidentifier[@primary = 'true']") ||
160
- ref.at("./docidentifier[not(@type = 'DOI')][@language = '#{@lang}']") ||
161
- ref.at("./docidentifier[not(@type = 'DOI')][not(@language)]") ||
162
- ref.at("./docidentifier[not(@type = 'DOI')]") or next
156
+ docid = select_docid(ref) or next
163
157
  reference = format_ref(docid.children.to_xml, docid["type"])
164
158
  @anchors[ref["id"]] = { xref: reference }
165
159
  end
166
160
  end
167
161
 
162
+ def select_docid(ref)
163
+ ref.at("./docidentifier[@type = 'metanorma']") ||
164
+ ref.at("./docidentifier[@primary = 'true'][@language = '#{@lang}']") ||
165
+ ref.at("./docidentifier[@primary = 'true'][not(@language)]") ||
166
+ ref.at("./docidentifier[@primary = 'true']") ||
167
+ ref.at("./docidentifier[not(@type = 'DOI')][@language = '#{@lang}']") ||
168
+ ref.at("./docidentifier[not(@type = 'DOI')][not(@language)]") ||
169
+ ref.at("./docidentifier[not(@type = 'DOI')]")
170
+ end
171
+
168
172
  def fetch_termbase(_termbase, _id)
169
173
  ""
170
174
  end
171
175
 
172
176
  def read_local_bibitem(uri)
173
- return nil if %r{^https?://}.match?(uri)
174
-
175
- file = "#{@localdir}#{uri}.rxl"
176
- File.file?(file) or file = "#{@localdir}#{uri}.xml"
177
- File.file?(file) or return nil
178
- xml = Nokogiri::XML(File.read(file, encoding: "utf-8"))
177
+ xml = read_local_bibitem_file(uri) or return nil
179
178
  ret = xml.at("//*[local-name() = 'bibdata']") or return nil
180
179
  ret = Nokogiri::XML(ret.to_xml
181
180
  .sub(%r{(<bibdata[^>]*?) xmlns=("[^"]+"|'[^']+')}, "\\1")).root
@@ -186,6 +185,15 @@ module Metanorma
186
185
  ret
187
186
  end
188
187
 
188
+ def read_local_bibitem_file(uri)
189
+ return nil if %r{^https?://}.match?(uri)
190
+
191
+ file = "#{@localdir}#{uri}.rxl"
192
+ File.file?(file) or file = "#{@localdir}#{uri}.xml"
193
+ File.file?(file) or return nil
194
+ Nokogiri::XML(File.read(file, encoding: "utf-8"))
195
+ end
196
+
189
197
  # if citation uri points to local file, get bibitem from it
190
198
  def fetch_local_bibitem(xmldoc)
191
199
  xmldoc.xpath("//bibitem[formattedref][uri[@type = 'citation']]")
@@ -206,6 +214,7 @@ module Metanorma
206
214
  def bibitem_cleanup(xmldoc)
207
215
  bibitem_nested_id(xmldoc)
208
216
  ref_dl_cleanup(xmldoc)
217
+ formattedref_spans(xmldoc)
209
218
  fetch_local_bibitem(xmldoc)
210
219
  end
211
220
  end
@@ -5,10 +5,19 @@ module Metanorma
5
5
  requirement_metadata(xmldoc)
6
6
  requirement_inherit(xmldoc)
7
7
  requirement_descriptions(xmldoc)
8
+ requirement_identifier(xmldoc)
8
9
  end
9
10
 
10
11
  REQRECPER = "//requirement | //recommendation | //permission".freeze
11
12
 
13
+ def requirement_identifier(xmldoc)
14
+ xmldoc.xpath(REQRECPER).each do |r|
15
+ r.xpath("./identifier[link] | ./inherit[link]").each do |i|
16
+ i.children = i.at("./link/@target").text
17
+ end
18
+ end
19
+ end
20
+
12
21
  def requirement_inherit(xmldoc)
13
22
  xmldoc.xpath(REQRECPER).each do |r|
14
23
  ins = requirement_inherit_insert(r)
@@ -76,8 +85,16 @@ module Metanorma
76
85
  end
77
86
  end
78
87
 
88
+ def requirement_metadata1_attrs
89
+ %w(obligation model type)
90
+ end
91
+
79
92
  def requirement_metadata1_tags
80
- %w(label subject inherit)
93
+ %w(identifier subject inherit)
94
+ end
95
+
96
+ def requirement_metadata_component_tags
97
+ []
81
98
  end
82
99
 
83
100
  def requirement_metadata1(reqt, dlist, ins)
@@ -85,20 +102,21 @@ module Metanorma
85
102
  reqt.children.first.previous = " "
86
103
  ins = reqt.children.first
87
104
  end
88
- %w(obligation model type).each do |a|
105
+ requirement_metadata1_attrs.each do |a|
89
106
  dl_to_attrs(reqt, dlist, a)
90
107
  end
91
108
  requirement_metadata1_tags.each do |a|
92
109
  ins = dl_to_elems(ins, reqt, dlist, a)
93
110
  end
94
- reqt_dl_to_classif(ins, reqt, dlist)
111
+ ins = reqt_dl_to_classif(ins, reqt, dlist)
112
+ reqt_dl_to_classif1(ins, reqt, dlist)
95
113
  end
96
114
 
97
115
  def reqt_dl_to_classif(ins, reqt, dlist)
98
116
  if a = reqt.at("./classification[last()]") then ins = a end
99
117
  dlist.xpath("./dt[text()='classification']").each do |e|
100
118
  val = e.at("./following::dd/p") || e.at("./following::dd")
101
- req_classif_parse(val.text).each do |r|
119
+ req_classif_parse(val.children.to_xml).each do |r|
102
120
  ins.next = "<classification><tag>#{r[0]}</tag>"\
103
121
  "<value>#{r[1]}</value></classification>"
104
122
  ins = ins.next
@@ -106,6 +124,21 @@ module Metanorma
106
124
  end
107
125
  ins
108
126
  end
127
+
128
+ def reqt_dl_to_classif1(ins, reqt, dlist)
129
+ if a = reqt.at("./classification[last()]") then ins = a end
130
+ dlist.xpath("./dt").each do |e|
131
+ next if (requirement_metadata1_attrs + requirement_metadata1_tags +
132
+ requirement_metadata_component_tags + %w(classification))
133
+ .include?(e.text)
134
+
135
+ val = e.at("./following::dd/p") || e.at("./following::dd")
136
+ ins.next = "<classification><tag>#{e.text}</tag>"\
137
+ "<value>#{val.children.to_xml}</value></classification>"
138
+ ins = ins.next
139
+ end
140
+ ins
141
+ end
109
142
  end
110
143
  end
111
144
  end
@@ -11,7 +11,7 @@ module Metanorma
11
11
  n.replace(grkletters(MathML2AsciiMath.m2a(n.to_xml)))
12
12
  end
13
13
  ret = Nokogiri::XML(key.to_xml)
14
- HTMLEntities.new.decode(ret.text.downcase)
14
+ @c.decode(ret.text.downcase)
15
15
  .gsub(/[\[\]{}<>()]/, "").gsub(/\s/m, "")
16
16
  .gsub(/[[:punct:]]|[_^]/, ":\\0").gsub(/`/, "")
17
17
  .gsub(/[0-9]+/, "þ\\0")
@@ -7,7 +7,7 @@ module Metanorma
7
7
  text = text.gsub(/\s+<fn /, "<fn ")
8
8
  %w(passthrough passthrough-inline).each do |v|
9
9
  text.gsub!(%r{<#{v}\s+formats="metanorma">([^<]*)
10
- </#{v}>}mx) { HTMLEntities.new.decode($1) }
10
+ </#{v}>}mx) { @c.decode($1) }
11
11
  end
12
12
  text
13
13
  end
@@ -34,11 +34,13 @@ module Metanorma
34
34
  end
35
35
  end
36
36
 
37
+ IGNORE_QUOTES_ELEMENTS =
38
+ %w(pre tt sourcecode stem figure bibdata passthrough identifier).freeze
39
+
37
40
  def uninterrupt_quotes_around_xml_skip(elem)
38
41
  !(/\A['"]/.match?(elem.text) &&
39
- elem.previous.ancestors("pre, tt, sourcecode, stem, figure, bibdata,
40
- passthrough, identifer")
41
- .empty? &&
42
+ elem.previous.path.split(%r{/})[1..-2]
43
+ .intersection(IGNORE_QUOTES_ELEMENTS).empty? &&
42
44
  ((elem.previous.text.strip.empty? &&
43
45
  !empty_tag_with_text_content?(elem.previous)) ||
44
46
  elem.previous.name == "index"))
@@ -49,7 +51,7 @@ module Metanorma
49
51
  /\S\Z/.match?(prev.text) or return
50
52
  foll = elem.at(".//following::text()[1]")
51
53
  m = /\A(["'][[:punct:]]*)(\s|\Z)/
52
- .match(HTMLEntities.new.decode(foll&.text)) or return
54
+ .match(@c.decode(foll&.text)) or return
53
55
  foll.content = foll.text.sub(/\A(["'][[:punct:]]*)/, "")
54
56
  prev.content = "#{prev.text}#{m[1]}"
55
57
  end
@@ -74,10 +76,10 @@ module Metanorma
74
76
  empty_tag_with_text_content?(x) and prev = "dummy"
75
77
  next unless x.text?
76
78
 
77
- x.ancestors("pre, tt, sourcecode, stem, figure, bibdata, passthrough,
78
- identifier").empty? and
79
+ ancestors = x.path.split(%r{/})[1..-2]
80
+ ancestors.intersection(IGNORE_QUOTES_ELEMENTS).empty? and
79
81
  dumb2smart_quotes1(x, prev)
80
- prev = x.text if x.ancestors("index").empty?
82
+ prev = x.text unless ancestors.include?("index")
81
83
  end
82
84
  end
83
85
 
@@ -68,10 +68,9 @@ module Metanorma
68
68
  end
69
69
 
70
70
  def xref_to_eref(elem)
71
- c = HTMLEntities.new
72
71
  elem["bibitemid"] = elem["target"]
73
72
  if ref = @anchors&.dig(elem["target"], :xref)
74
- elem["citeas"] = c.decode(ref)
73
+ elem["citeas"] = @c.decode(ref)
75
74
  else
76
75
  elem["citeas"] = ""
77
76
  xref_to_eref1(elem)
@@ -29,6 +29,7 @@ module Metanorma
29
29
  preprocessor Metanorma::Plugin::Lutaml::LutamlUmlAttributesTablePreprocessor
30
30
  preprocessor Metanorma::Plugin::Lutaml::LutamlUmlDatamodelDescriptionPreprocessor
31
31
  inline_macro Metanorma::Standoc::PreferredTermInlineMacro
32
+ inline_macro Metanorma::Standoc::SpanInlineMacro
32
33
  inline_macro Metanorma::Standoc::AltTermInlineMacro
33
34
  inline_macro Metanorma::Standoc::AdmittedTermInlineMacro
34
35
  inline_macro Metanorma::Standoc::DeprecatedTermInlineMacro
@@ -93,6 +94,7 @@ module Metanorma
93
94
  basebackend "html"
94
95
  outfilesuffix ".xml"
95
96
  @libdir = File.dirname(self.class::_file || __FILE__)
97
+ @c = HTMLEntities.new
96
98
  end
97
99
 
98
100
  class << self
@@ -121,7 +121,7 @@ module Metanorma
121
121
 
122
122
  def metadata_getrelation(node, xml, type, desc = nil)
123
123
  docs = node.attr(desc || type) or return
124
- HTMLEntities.new.decode(docs).split(/;\s*/).each do |d|
124
+ @c.decode(docs).split(/;\s*/).each do |d|
125
125
  metadata_getrelation1(d, xml, type, desc)
126
126
  end
127
127
  end
@@ -79,8 +79,8 @@ module Metanorma
79
79
  end
80
80
 
81
81
  def inline_anchor_bibref(node)
82
- eref_contents = HTMLEntities.new
83
- .decode(node.text || node.target || node.id)
82
+ eref_contents =
83
+ @c.decode(node.text || node.target || node.id)
84
84
  &.sub(/^\[?([^\[\]]+?)\]?$/, "[\\1]")
85
85
  @refids << (node.target || node.id)
86
86
  noko do |xml|
@@ -125,14 +125,14 @@ module Metanorma
125
125
  end
126
126
 
127
127
  def xml_encode(text)
128
- HTMLEntities.new.encode(text, :basic, :hexadecimal)
128
+ @c.encode(text, :basic, :hexadecimal)
129
129
  .gsub(/&amp;gt;/, ">").gsub(/&amp;lt;/, "<").gsub(/&amp;amp;/, "&")
130
130
  .gsub(/&gt;/, ">").gsub(/&lt;/, "<").gsub(/&amp;/, "&")
131
131
  .gsub(/&quot;/, '"').gsub(/&#xa;/, "\n").gsub(/&amp;#/, "&#")
132
132
  end
133
133
 
134
134
  def latex_parse1(text)
135
- lxm_input = Unicode2LaTeX.unicode2latex(HTMLEntities.new.decode(text))
135
+ lxm_input = Unicode2LaTeX.unicode2latex(@c.decode(text))
136
136
  results = Latexmath.parse(lxm_input).to_mathml
137
137
  results.nil? and
138
138
  @log.add("Math", nil,
@@ -191,6 +191,10 @@ module Metanorma
191
191
  when "underline" then xml.underline { |s| s << node.text }
192
192
  when "smallcap" then xml.smallcap { |s| s << node.text }
193
193
  when "keyword" then xml.keyword { |s| s << node.text }
194
+ when /^css /
195
+ xml.span **{ style: node.role.sub(/^css /, "") } do |s|
196
+ s << node.text
197
+ end
194
198
  else
195
199
  xml << node.text
196
200
  end
@@ -1285,7 +1285,12 @@
1285
1285
  </define>
1286
1286
  <define name="span">
1287
1287
  <element name="span">
1288
- <attribute name="class"/>
1288
+ <optional>
1289
+ <attribute name="class"/>
1290
+ </optional>
1291
+ <optional>
1292
+ <attribute name="style"/>
1293
+ </optional>
1289
1294
  <oneOrMore>
1290
1295
  <ref name="TextElement"/>
1291
1296
  </oneOrMore>