isodoc 2.12.0 → 2.12.2

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/isodoc.gemspec +2 -2
  3. data/lib/isodoc/convert.rb +0 -21
  4. data/lib/isodoc/function/blocks.rb +19 -48
  5. data/lib/isodoc/function/blocks_example_note.rb +75 -29
  6. data/lib/isodoc/function/cleanup.rb +3 -40
  7. data/lib/isodoc/function/inline.rb +39 -9
  8. data/lib/isodoc/function/lists.rb +5 -5
  9. data/lib/isodoc/function/references.rb +9 -133
  10. data/lib/isodoc/function/reqt.rb +2 -2
  11. data/lib/isodoc/function/section.rb +25 -28
  12. data/lib/isodoc/function/section_titles.rb +16 -13
  13. data/lib/isodoc/function/table.rb +3 -3
  14. data/lib/isodoc/function/terms.rb +21 -20
  15. data/lib/isodoc/function/to_word_html.rb +8 -5
  16. data/lib/isodoc/function/utils.rb +1 -1
  17. data/lib/isodoc/html_function/footnotes.rb +2 -1
  18. data/lib/isodoc/html_function/html.rb +1 -5
  19. data/lib/isodoc/init.rb +31 -0
  20. data/lib/isodoc/metadata.rb +9 -0
  21. data/lib/isodoc/metadata_contributor.rb +1 -1
  22. data/lib/isodoc/metadata_date.rb +1 -1
  23. data/lib/isodoc/presentation_function/autonum.rb +139 -0
  24. data/lib/isodoc/presentation_function/block.rb +95 -36
  25. data/lib/isodoc/presentation_function/docid.rb +78 -0
  26. data/lib/isodoc/presentation_function/erefs.rb +6 -4
  27. data/lib/isodoc/presentation_function/image.rb +52 -13
  28. data/lib/isodoc/presentation_function/inline.rb +6 -6
  29. data/lib/isodoc/presentation_function/math.rb +0 -14
  30. data/lib/isodoc/presentation_function/metadata.rb +0 -62
  31. data/lib/isodoc/presentation_function/refs.rb +44 -14
  32. data/lib/isodoc/presentation_function/reqt.rb +1 -1
  33. data/lib/isodoc/presentation_function/section.rb +46 -121
  34. data/lib/isodoc/presentation_function/sourcecode.rb +7 -4
  35. data/lib/isodoc/presentation_function/terms.rb +27 -2
  36. data/lib/isodoc/presentation_function/title.rb +107 -0
  37. data/lib/isodoc/presentation_function/xrefs.rb +17 -10
  38. data/lib/isodoc/presentation_xml_convert.rb +6 -2
  39. data/lib/isodoc/version.rb +1 -1
  40. data/lib/isodoc/word_function/body.rb +8 -36
  41. data/lib/isodoc/word_function/footnotes.rb +1 -1
  42. data/lib/isodoc/word_function/lists.rb +12 -10
  43. data/lib/isodoc/word_function/postprocess_cover.rb +0 -2
  44. data/lib/isodoc/word_function/postprocess_table.rb +1 -1
  45. data/lib/isodoc/word_function/table.rb +2 -2
  46. data/lib/isodoc/xref/clause_order.rb +2 -2
  47. data/lib/isodoc/xref/xref_anchor.rb +31 -16
  48. data/lib/isodoc/xref/xref_counter_types.rb +3 -2
  49. data/lib/isodoc/xref/xref_gen.rb +57 -33
  50. data/lib/isodoc/xref/xref_gen_seq.rb +145 -56
  51. data/lib/isodoc/xref/xref_sect_gen.rb +64 -47
  52. data/lib/isodoc/xref/xref_util.rb +49 -1
  53. data/lib/isodoc/xref.rb +3 -0
  54. data/lib/isodoc-yaml/i18n-ar.yaml +9 -9
  55. data/lib/isodoc-yaml/i18n-de.yaml +9 -9
  56. data/lib/isodoc-yaml/i18n-en.yaml +9 -9
  57. data/lib/isodoc-yaml/i18n-es.yaml +9 -9
  58. data/lib/isodoc-yaml/i18n-fr.yaml +9 -9
  59. data/lib/isodoc-yaml/i18n-ja.yaml +10 -10
  60. data/lib/isodoc-yaml/i18n-ru.yaml +9 -9
  61. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +9 -9
  62. data/lib/nokogiri/xml/node.rb +1 -0
  63. metadata +9 -6
@@ -42,7 +42,7 @@ module IsoDoc
42
42
 
43
43
  def bibdate(isoxml, _out)
44
44
  isoxml.xpath(ns("//bibdata/date")).each do |d|
45
- set("#{d['type'].gsub(/-/, '_')}date".to_sym, Common::date_range(d))
45
+ set("#{d['type'].tr('-', '_')}date".to_sym, Common::date_range(d))
46
46
  end
47
47
  end
48
48
  end
@@ -0,0 +1,139 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def prefix_name(node, delims, label, elem)
4
+ label, delims = prefix_name_defaults(node, delims, label)
5
+ name, ins, ids, number = prefix_name_prep(node, elem)
6
+ ins.next = fmt_xref_label(label, number, ids)
7
+ # autonum can be empty, e.g single note in clause: "NOTE []"
8
+ number and node["autonum"] = number.gsub(/<[^>]+>/, "")
9
+ !node.at(ns("./fmt-#{elem}")) &&
10
+ (c = fmt_caption(label, elem, name, ids, delims)) and ins.next = c
11
+ prefix_name_postprocess(node, elem)
12
+ end
13
+
14
+ def prefix_name_defaults(node, delims, label)
15
+ label&.empty? and label = nil
16
+ delims.nil? and delims = {}
17
+ [label, delims]
18
+ end
19
+
20
+ def prefix_name_prep(node, elem)
21
+ lbls = prefix_name_labels(node)
22
+ name = node.at(ns("./#{elem}")) and name["id"] = lbls[:name]
23
+ ins = name || node.add_first_child("<sentinel/>").elements.first
24
+ node["unnumbered"] or
25
+ number = @xrefs.anchor(node["id"], :value, false)&.strip
26
+ [name, ins, lbls, number]
27
+ end
28
+
29
+ def prefix_name_labels(node)
30
+ { elem: node["id"],
31
+ name: "_#{UUIDTools::UUID.random_create}" }
32
+ end
33
+
34
+ def prefix_name_postprocess(node, elem)
35
+ node.at(ns("./sentinel"))&.remove
36
+ strip_duplicate_ids(node, node.at(ns("./#{elem}")),
37
+ node.at(ns("./fmt-#{elem}")))
38
+ end
39
+
40
+ def transfer_id(old, new)
41
+ old["id"] or return
42
+ new["id"] = old["id"]
43
+ old["original-id"] = old["id"]
44
+ old.delete("id")
45
+ end
46
+
47
+ def gather_all_ids(elem)
48
+ elem.xpath(".//*[@id]").each_with_object([]) do |i, m|
49
+ m << i["id"]
50
+ end
51
+ end
52
+
53
+ # remove ids duplicated between title and fmt-title
54
+ # index terms are assumed transferred to fmt-title from title
55
+ def strip_duplicate_ids(_node, sem_title, pres_title)
56
+ sem_title && pres_title or return
57
+ ids = gather_all_ids(pres_title)
58
+ sem_title.xpath(".//*[@id]").each do |x|
59
+ ids.include?(x["id"]) or next
60
+ x["original-id"] = x["id"]
61
+ x.delete("id")
62
+ end
63
+ sem_title.xpath(ns(".//index")).each(&:remove)
64
+ end
65
+
66
+ def semx(node, label, element = "autonum")
67
+ id = node["id"] || node[:id]
68
+ /<semx element='[^']+' source='#{id}'/.match?(label) and return label
69
+ l = stripsemx(label)
70
+ %(<semx element='#{element}' source='#{id}'>#{l}</semx>)
71
+ end
72
+
73
+ def autonum(id, num)
74
+ /<semx/.match?(num) and return num # already contains markup
75
+ "<semx element='autonum' source='#{id}'>#{num}</semx>"
76
+ end
77
+
78
+ def labelled_autonum(label, id, num)
79
+ elem = "<span class='fmt-element-name'>#{label}</span>"
80
+ num.blank? and return elem
81
+ l10n("#{elem} #{autonum(id, num)}")
82
+ end
83
+
84
+ def fmt_xref_label(label, _number, ids)
85
+ label or return ""
86
+ x = @xrefs.anchor(ids[:elem], :xref, false) or return ""
87
+ ret = "<fmt-xref-label>#{x}</fmt-xref-label>"
88
+ container = @xrefs.anchor(ids[:elem], :container, false)
89
+ y = prefix_container_fmt_xref_label(container, x)
90
+ y != x and
91
+ ret += "<fmt-xref-label container='#{container}'>#{y}</fmt-xref-label>"
92
+ ret
93
+ end
94
+
95
+ def prefix_container_fmt_xref_label(container, xref)
96
+ container or return xref
97
+ container_container = @xrefs.anchor(container, :container, false)
98
+ container_label =
99
+ prefix_container_fmt_xref_label(container_container,
100
+ @xrefs.anchor(container, :xref, false))
101
+ l10n(connectives_spans(@i18n.nested_xref
102
+ .sub("%1", "<span class='fmt-xref-container'>#{container_label}</span>")
103
+ .sub("%2", xref)))
104
+ end
105
+
106
+ # detect whether string which may contain XML markup is empty
107
+ def empty_xml?(str)
108
+ str.blank? and return true
109
+ x = Nokogiri::XML::DocumentFragment.parse(str)
110
+ x.to_str.strip.empty?
111
+ end
112
+
113
+ # Remove ".blank?" tests if want empty delim placeholders for manipulation
114
+ def fmt_caption(label, elem, name, ids, delims)
115
+ label = fmt_caption_label_wrap(label)
116
+ c = fmt_caption2(label, elem, name, ids, delims)
117
+ empty_xml?(c) and return
118
+ !delims[:label].blank? and
119
+ f = "<span class='fmt-label-delim'>#{delims[:label]}</span>"
120
+ "<fmt-#{elem}>#{c}#{f}</fmt-#{elem}>"
121
+ end
122
+
123
+ def fmt_caption_label_wrap(label)
124
+ empty_xml?(label) || %r{<span class=['"]fmt-caption-label['"]}.match?(label) or
125
+ label = "<span class='fmt-caption-label'>#{label}</span>"
126
+ label
127
+ end
128
+
129
+ def fmt_caption2(label, elem, name, ids, delims)
130
+ if name && !name.children.empty?
131
+ empty_xml?(label) or
132
+ d = "<span class='fmt-caption-delim'>#{delims[:caption]}</span>"
133
+ attr = " element='#{elem}' source='#{ids[:name]}'"
134
+ "#{label}#{d}<semx #{attr}>#{to_xml(name.children)}</semx>"
135
+ elsif label then label
136
+ end
137
+ end
138
+ end
139
+ end
@@ -1,31 +1,23 @@
1
1
  require_relative "image"
2
2
  require_relative "sourcecode"
3
+ require_relative "autonum"
3
4
  require "rouge"
4
5
 
5
6
  module IsoDoc
6
7
  class PresentationXMLConvert < ::IsoDoc::Convert
7
8
  def lower2cap(text)
8
- /^[[:upper:]][[:upper:]]/.match?(text) and return text
9
- text&.capitalize
9
+ text.nil? and return text
10
+ x = Nokogiri::XML("<a>#{text}</a>")
11
+ firsttext = x.at(".//text()[string-length(normalize-space(.))>0]") or return text
12
+ /^[[:upper:]][[:upper:]]/.match?(firsttext.text) and return text
13
+ firsttext.replace(firsttext.text.capitalize)
14
+ to_xml(x.root.children)
10
15
  end
11
16
 
12
17
  def block_delim
13
18
  "&#xa0;&#x2014; "
14
19
  end
15
20
 
16
- def prefix_name(node, delim, number, elem)
17
- number.nil? || number.empty? and return
18
- unless name = node.at(ns("./#{elem}"))
19
- #(node.children.empty? and node.add_child("<#{elem}></#{elem}>")) or
20
- # node.children.first.previous = "<#{elem}></#{elem}>"
21
- node.add_first_child "<#{elem}></#{elem}>"
22
- name = node.children.first
23
- end
24
- if name.children.empty? then name.add_child(cleanup_entities(number.strip))
25
- else (name.children.first.previous = "#{number.strip}#{delim}")
26
- end
27
- end
28
-
29
21
  def formula(docxml)
30
22
  docxml.xpath(ns("//formula")).each { |f| formula1(f) }
31
23
  end
@@ -33,7 +25,7 @@ module IsoDoc
33
25
  def formula1(elem)
34
26
  formula_where(elem.at(ns("./dl")))
35
27
  lbl = @xrefs.anchor(elem["id"], :label, false)
36
- prefix_name(elem, "", lbl, "name")
28
+ lbl.nil? || lbl.empty? or prefix_name(elem, {}, lbl, "name")
37
29
  end
38
30
 
39
31
  def formula_where(dlist)
@@ -49,25 +41,27 @@ module IsoDoc
49
41
 
50
42
  def example1(elem)
51
43
  n = @xrefs.get[elem["id"]]
52
- lbl = if n.nil? || n[:label].nil? || n[:label].empty?
53
- @i18n.example
54
- else l10n("#{@i18n.example} #{n[:label]}")
55
- end
56
- prefix_name(elem, block_delim, lbl, "name")
44
+ lbl = labelled_autonum(@i18n.example, elem["id"], n&.dig(:label))
45
+ prefix_name(elem, { caption: block_delim }, lbl, "name")
57
46
  end
58
47
 
59
48
  def note(docxml)
60
49
  docxml.xpath(ns("//note")).each { |f| note1(f) }
61
50
  end
62
51
 
52
+ def note_delim(_elem)
53
+ "<tab/>"
54
+ end
55
+
63
56
  def note1(elem)
64
57
  %w(bibdata bibitem).include?(elem.parent.name) ||
65
- elem["notag"] == "true" and return
58
+ elem["notag"] == "true" or lbl = note_label(elem)
59
+ prefix_name(elem, { label: note_delim(elem) }, lbl, "name")
60
+ end
61
+
62
+ def note_label(elem)
66
63
  n = @xrefs.get[elem["id"]]
67
- lbl = @i18n.note
68
- (n.nil? || n[:label].nil? || n[:label].empty?) or
69
- lbl = l10n("#{lbl} #{n[:label]}")
70
- prefix_name(elem, "", lbl, "name")
64
+ labelled_autonum(@i18n.note, elem["id"], n&.dig(:label))
71
65
  end
72
66
 
73
67
  def admonition(docxml)
@@ -77,16 +71,30 @@ module IsoDoc
77
71
  def admonition1(elem)
78
72
  if elem["type"] == "box"
79
73
  admonition_numbered1(elem)
74
+ elsif elem["notag"] == "true" || elem.at(ns("./name"))
75
+ prefix_name(elem, { label: admonition_delim(elem) }, nil, "name")
80
76
  else
81
- elem["notag"] == "true" || elem.at(ns("./name")) and return
82
- prefix_name(elem, "", @i18n.admonition[elem["type"]]&.upcase, "name")
77
+ label = admonition_label(elem, nil)
78
+ prefix_name(elem, { label: admonition_delim(elem) }, label, "name")
83
79
  end
84
80
  end
85
81
 
86
82
  def admonition_numbered1(elem)
87
- elem["unnumbered"] && !elem.at(ns("./name")) and return
88
- n = @xrefs.anchor(elem["id"], :label, false)
89
- prefix_name(elem, block_delim, l10n("#{@i18n.box} #{n}"), "name")
83
+ # elem["unnumbered"] && !elem.at(ns("./name")) and return
84
+ label = admonition_label(elem, @xrefs.anchor(elem["id"], :label, false))
85
+ prefix_name(elem, { caption: block_delim }, label, "name")
86
+ end
87
+
88
+ def admonition_label(elem, num)
89
+ lbl = if elem["type"] == "box" then @i18n.box
90
+ else @i18n.admonition[elem["type"]]&.upcase end
91
+ #lbl &&= "<span class='fmt-element-name'>#{lbl}</span>"
92
+ #num and lbl = l10n("#{lbl} #{autonum(elem['id'], num)}")
93
+ labelled_autonum(lbl, elem["id"], num)
94
+ end
95
+
96
+ def admonition_delim(_elem)
97
+ ""
90
98
  end
91
99
 
92
100
  def table(docxml)
@@ -95,11 +103,18 @@ module IsoDoc
95
103
  end
96
104
 
97
105
  def table1(elem)
106
+ table_fn(elem)
98
107
  labelled_ancestor(elem) and return
99
108
  elem["unnumbered"] && !elem.at(ns("./name")) and return
100
109
  n = @xrefs.anchor(elem["id"], :label, false)
101
- prefix_name(elem, block_delim, l10n("#{lower2cap @i18n.table} #{n}"),
102
- "name")
110
+ #lbl = "<span class='fmt-element-name'>#{lower2cap @i18n.table}</span> "\
111
+ #"#{autonum(elem['id'], n)}"
112
+ lbl = labelled_autonum(lower2cap(@i18n.table), elem["id"], n)
113
+ prefix_name(elem, { caption: table_delim }, l10n(lbl), "name")
114
+ end
115
+
116
+ def table_delim
117
+ block_delim
103
118
  end
104
119
 
105
120
  def table_long_strings_cleanup(docxml)
@@ -113,6 +128,15 @@ module IsoDoc
113
128
  end
114
129
  end
115
130
 
131
+ def table_fn(elem)
132
+ (elem.xpath(ns(".//fn")) - elem.xpath(ns("./name//fn")))
133
+ .each_with_index do |f, i|
134
+ table_fn1(elem, f, i)
135
+ end
136
+ end
137
+
138
+ def table_fn1(table, fnote, idx); end
139
+
116
140
  # we use this to eliminate the semantic amend blocks from rendering
117
141
  def amend(docxml)
118
142
  docxml.xpath(ns("//amend")).each { |f| amend1(f) }
@@ -126,6 +150,24 @@ module IsoDoc
126
150
  elem.replace(elem.children)
127
151
  end
128
152
 
153
+ def dl(docxml)
154
+ docxml.xpath(ns("//dl")).each { |f| dl1(f) }
155
+ end
156
+
157
+ def dl1(elem)
158
+ elem.at(ns("./name")) and
159
+ prefix_name(elem, {}, "", "name") # copy name to fmt-name
160
+ end
161
+
162
+ def ul(docxml)
163
+ docxml.xpath(ns("//ul")).each { |f| ul1(f) }
164
+ end
165
+
166
+ def ul1(elem)
167
+ elem.at(ns("./name")) and
168
+ prefix_name(elem, {}, "", "name") # copy name to fmt-name
169
+ end
170
+
129
171
  def ol(docxml)
130
172
  docxml.xpath(ns("//ol")).each { |f| ol1(f) }
131
173
  @xrefs.list_anchor_names(docxml.xpath(ns(@xrefs.sections_xpath)))
@@ -147,9 +189,8 @@ module IsoDoc
147
189
 
148
190
  def ol1(elem)
149
191
  elem["type"] ||= ol_depth(elem).to_s
150
- elem.xpath(ns("./li")).each do |li|
151
- li["id"] ||= "_#{UUIDTools::UUID.random_create}"
152
- end
192
+ elem.at(ns("./name")) and
193
+ prefix_name(elem, {}, "", "name") # copy name to fmt-name
153
194
  end
154
195
 
155
196
  def ol_label(elem)
@@ -182,5 +223,23 @@ module IsoDoc
182
223
  def source_modification(mod)
183
224
  termsource_modification(mod.parent)
184
225
  end
226
+
227
+ def quote(docxml)
228
+ docxml.xpath(ns("//quote")).each { |f| quote1(f) }
229
+ end
230
+
231
+ def quote1(elem)
232
+ author = elem.at(ns("./author"))
233
+ source = elem.at(ns("./source"))
234
+ author.nil? && source.nil? and return
235
+ p = "&#x2014; "
236
+ p += author.remove.to_xml if author
237
+ p += ", " if author && source
238
+ if source
239
+ source.name = "eref"
240
+ p += source.remove.to_xml
241
+ end
242
+ elem << "<attribution><p>#{l10n p}</p></attribution>"
243
+ end
185
244
  end
186
245
  end
@@ -0,0 +1,78 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def docid_prefixes(docxml)
4
+ docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
5
+ i.children = docid_prefix(i["type"], to_xml(i.children))
6
+ end
7
+ end
8
+
9
+ def pref_ref_code(bib)
10
+ bib["suppress_identifier"] == "true" and return nil
11
+ ret = bib.xpath(ns("./docidentifier[@scope = 'biblio-tag']"))
12
+ ret.empty? or return ret.map(&:text)
13
+ ret = pref_ref_code_parse(bib) or return nil
14
+ ins = bib.at(ns("./docidentifier[last()]"))
15
+ ret.reverse_each do |r|
16
+ ins.next = "<docidentifier scope='biblio-tag'>#{docid_l10n(r)}</docidentifier>"
17
+ end
18
+ ret
19
+ end
20
+
21
+ def pref_ref_code_parse(bib)
22
+ data, = @bibrender.parse(bib)
23
+ ret = data[:authoritative_identifier] or return nil
24
+ ret.empty? and return nil
25
+ ret
26
+ end
27
+
28
+ # returns [metanorma, non-metanorma, DOI/ISSN/ISBN] identifiers
29
+ def bibitem_ref_code(bib)
30
+ id, id1, id2, id3 = bibitem_ref_code_prep(bib)
31
+ id || id1 || id2 || id3 and return [id, id1, id2, id3]
32
+ bib["suppress_identifier"] == "true" and return [nil, nil, nil, nil]
33
+ [nil, no_identifier(bib), nil, nil]
34
+ end
35
+
36
+ def bibitem_ref_code_prep(bib)
37
+ id = bib.at(ns("./docidentifier[@type = 'metanorma']"))
38
+ id1 = pref_ref_code(bib)
39
+ id2 = bib.at(ns("./docidentifier[#{SKIP_DOCID}]"))
40
+ id3 = bib.at(ns("./docidentifier[@type = 'metanorma-ordinal']"))
41
+ [id, id1, id2, id3]
42
+ end
43
+
44
+ def no_identifier(bib)
45
+ @i18n.no_identifier or return nil
46
+ id = Nokogiri::XML::Node.new("docidentifier", bib.document)
47
+ id << @i18n.no_identifier
48
+ id
49
+ end
50
+
51
+ def bracket_if_num(num)
52
+ num.nil? and return nil
53
+ num = num.text.sub(/^\[/, "").sub(/\]$/, "")
54
+ /^\d+$/.match?(num) and return "[#{num}]"
55
+ num
56
+ end
57
+
58
+ def unbracket1(ident)
59
+ ident.nil? and return nil
60
+ ident.is_a?(String) or ident = ident.text
61
+ ident.sub(/^\[/, "").sub(/\]$/, "")
62
+ end
63
+
64
+ def unbracket(ident)
65
+ if ident.respond_to?(:size)
66
+ ident.map { |x| unbracket1(x) }.join("&#xA0;/ ")
67
+ else unbracket1(ident)
68
+ end
69
+ end
70
+
71
+ def render_identifier(ident)
72
+ { metanorma: bracket_if_num(ident[0]),
73
+ sdo: unbracket(ident[1]),
74
+ doi: unbracket(ident[2]),
75
+ ordinal: bracket_if_num(ident[3]) }
76
+ end
77
+ end
78
+ end
@@ -3,9 +3,10 @@ require "metanorma-utils"
3
3
  module IsoDoc
4
4
  class PresentationXMLConvert < ::IsoDoc::Convert
5
5
  def citeas(xmldoc)
6
- xmldoc.xpath(ns("//eref | //origin | //quote/source")).each do |e|
6
+ xmldoc.xpath(ns("//eref | //origin | //quote//source")).each do |e|
7
7
  e["bibitemid"] && e["citeas"] or next
8
- a = @xrefs.anchor(e["bibitemid"], :xref, false) and e["citeas"] = a
8
+ a = @xrefs.anchor(e["bibitemid"], :xref, false) and
9
+ e["citeas"] = a.gsub(%r{</?[^>]+>}, "")
9
10
  end
10
11
  end
11
12
 
@@ -87,7 +88,8 @@ module IsoDoc
87
88
  locs1 = []
88
89
  until locs.empty?
89
90
  if locs[1] == "to"
90
- locs1 << @i18n.chain_to.sub("%1", locs[0]).sub("%2", locs[2])
91
+ locs1 << connectives_spans(@i18n.chain_to.sub("%1", locs[0])
92
+ .sub("%2", locs[2]))
91
93
  locs.shift(3)
92
94
  else locs1 << locs.shift
93
95
  end
@@ -178,7 +180,7 @@ module IsoDoc
178
180
  end
179
181
 
180
182
  def eref2link(docxml)
181
- docxml.xpath(ns("//eref | //origin[not(termref)] | //quote/source"))
183
+ docxml.xpath(ns("//eref | //origin[not(termref)] | //quote//source"))
182
184
  .each do |e|
183
185
  href = eref_target(e) or next
184
186
  e.xpath(ns("./locality | ./localityStack")).each(&:remove)
@@ -43,14 +43,50 @@ module IsoDoc
43
43
  elem.children = x
44
44
  end
45
45
 
46
+ def subfigure_delim
47
+ ""
48
+ # "<span class='fmt-label-delim'>)</span>"
49
+ end
50
+
51
+ def figure_delim(_elem)
52
+ block_delim
53
+ end
54
+
55
+ def figure_name(elem)
56
+ "<span class='fmt-element-name'>#{figure_label(elem)}</span> "
57
+ end
58
+
46
59
  def figure1(elem)
47
60
  elem["class"] == "pseudocode" || elem["type"] == "pseudocode" and
48
61
  return sourcecode1(elem)
49
- figure_label?(elem) or return nil
50
- lbl = @xrefs.anchor(elem["id"], :label, false) or return
51
- # no xref, no label: this can be set in xref
52
- prefix_name(elem, block_delim,
53
- l10n("#{figure_label(elem)} #{lbl}"), "name")
62
+ figure_fn(elem)
63
+ figure_key(elem.at(ns("./dl")))
64
+ lbl = @xrefs.anchor(elem["id"], :label, false)
65
+ lbl and a = autonum(elem["id"], lbl)
66
+ figname = figure_name(elem)
67
+ if elem.parent.name == "figure"
68
+ a += subfigure_delim
69
+ end
70
+ lbl && figure_label?(elem) and s = "#{figname}#{a}"
71
+ prefix_name(elem, { caption: figure_delim(elem) }, l10n(s&.strip), "name")
72
+ end
73
+
74
+ # move footnotes into key, and get rid of footnote reference
75
+ # since it is in diagram
76
+ def figure_fn(elem)
77
+ fn = elem.xpath(ns(".//fn")) - elem.xpath(ns("./name//fn"))
78
+ fn.empty? and return
79
+ dl = figure_key_insert_pt(elem)
80
+ fn.each do |f|
81
+ dl.previous = "<dt><p><sup>#{f['reference']}</sup></p></dt>" \
82
+ "<dd>#{f.remove.children.to_xml}</dd>"
83
+ end
84
+ end
85
+
86
+ def figure_key_insert_pt(elem)
87
+ elem.at(ns("//dl/name"))&.next ||
88
+ elem.at(ns("//dl"))&.children&.first ||
89
+ elem.add_child("<dl> </dl>").first.children.first
54
90
  end
55
91
 
56
92
  def figure_label?(elem)
@@ -64,6 +100,14 @@ module IsoDoc
64
100
  lower2cap klasslbl
65
101
  end
66
102
 
103
+ def figure_key(dlist)
104
+ dlist or return
105
+ dlist["class"] = "formula_dl"
106
+ dlist.at(ns("./name")) and return
107
+ dlist.previous =
108
+ "<p keep-with-next='true'><strong>#{@i18n.key}</strong></p>"
109
+ end
110
+
67
111
  def eps2svg(img)
68
112
  return unless eps?(img["mimetype"])
69
113
 
@@ -77,7 +121,7 @@ module IsoDoc
77
121
  def svg_emf_double(img)
78
122
  if emf?(img["mimetype"])
79
123
  img = emf_encode(img)
80
- #img.children.first.previous = emf_to_svg(img)
124
+ # img.children.first.previous = emf_to_svg(img)
81
125
  img.add_first_child emf_to_svg(img)
82
126
  elsif img["mimetype"] == "image/svg+xml"
83
127
  src = svg_to_emf(img) or return
@@ -127,16 +171,11 @@ module IsoDoc
127
171
 
128
172
  def svg_to_emf(node)
129
173
  @output_formats[:doc] or return
130
-
131
174
  svg_impose_height_attr(node)
132
-
133
- if node.elements&.first&.name == "svg" || %r{^data:}.match?(node["src"])
175
+ node.elements&.first&.name == "svg" || %r{^data:}.match?(node["src"]) and
134
176
  return svg_to_emf_from_node(node)
135
- end
136
-
137
177
  target_path = imgfile_suffix(node["src"], "emf")
138
- return target_path if File.exist?(target_path)
139
-
178
+ File.exist?(target_path) and return target_path
140
179
  svg_to_emf_from_node(node, target_path)
141
180
  end
142
181
 
@@ -13,7 +13,7 @@ module IsoDoc
13
13
  node["style"] == "id" and anchor_id_postprocess(node)
14
14
  xref_empty?(node) or return
15
15
  target = docid_l10n(node["target"]) ||
16
- expand_citeas(docid_l10n(node["citeas"]))
16
+ docid_l10n(expand_citeas(node["citeas"]))
17
17
  link = anchor_linkend(node, target)
18
18
  link += eref_localities(node.xpath(ns("./locality | ./localityStack")),
19
19
  link, node)
@@ -54,8 +54,8 @@ module IsoDoc
54
54
  end
55
55
 
56
56
  def quotesource(docxml)
57
- docxml.xpath(ns("//quote/source")).each { |f| xref1(f) }
58
- docxml.xpath(ns("//quote/source//xref")).each do |f|
57
+ docxml.xpath(ns("//quote//source")).each { |f| xref1(f) }
58
+ docxml.xpath(ns("//quote//source//xref")).each do |f|
59
59
  f.replace(f.children)
60
60
  end
61
61
  end
@@ -164,9 +164,9 @@ module IsoDoc
164
164
  def passthrough1(elem, formats)
165
165
  (elem["formats"] && !elem["formats"].empty?) or elem["formats"] = "all"
166
166
  f = elem["formats"].split(",")
167
- (f - formats).size == f.size or elem["formats"] = "all"
168
- elem["formats"] == "all" and elem["formats"] = formats.join(",")
169
- elem["formats"] = ",#{elem['formats']},"
167
+ (f - formats).size == f.size or f = "all"
168
+ f == ["all"] and f = formats.dup
169
+ elem["formats"] = " #{f.join(' ')} "
170
170
  end
171
171
 
172
172
  def extract_custom_charsets(docxml)
@@ -7,7 +7,6 @@ module IsoDoc
7
7
  MATHML = { "m" => "http://www.w3.org/1998/Math/MathML" }.freeze
8
8
 
9
9
  def mathml(docxml)
10
- docxml.xpath("//m:math", MATHML).each { |f| mathml_linebreak(f) }
11
10
  locale = @lang.to_sym
12
11
  @numfmt = Plurimath::NumberFormatter
13
12
  .new(locale, localize_number: @localizenumber,
@@ -160,19 +159,6 @@ module IsoDoc
160
159
  mathml_number(node, locale)
161
160
  end
162
161
 
163
- def mathml_linebreak(node)
164
- node.at(".//*/@linebreak") or return
165
- m = Plurimath::Math.parse(node.to_xml, :mathml)
166
- .to_mathml(split_on_linebreak: true)
167
- ret = Nokogiri::XML("<m>#{m}</m>").root
168
- ret.elements.each_with_index do |e, i|
169
- i.zero? or e.previous = "<br/>"
170
- end
171
- node.replace(<<~OUTPUT)
172
- <math-with-linebreak>#{ret.children}</math-with-linebreak><math-no-linebreak>#{node.to_xml}</math-no-linebreak>
173
- OUTPUT
174
- end
175
-
176
162
  # convert any Ascii superscripts to correct(ish) MathML
177
163
  # Not bothering to match times, base of 1.0 x 10^-20, just ^-20
178
164
  def mn_to_msup(node)