isodoc 1.6.0 → 1.6.5

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +2 -12
  3. data/.hound.yml +3 -1
  4. data/.rubocop.yml +4 -8
  5. data/Rakefile +2 -2
  6. data/bin/rspec +1 -2
  7. data/isodoc.gemspec +4 -3
  8. data/lib/isodoc-yaml/i18n-ar.yaml +152 -0
  9. data/lib/isodoc-yaml/i18n-de.yaml +149 -0
  10. data/lib/isodoc-yaml/i18n-en.yaml +1 -0
  11. data/lib/isodoc-yaml/i18n-es.yaml +151 -0
  12. data/lib/isodoc-yaml/i18n-fr.yaml +1 -0
  13. data/lib/isodoc-yaml/i18n-ru.yaml +154 -0
  14. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  15. data/lib/isodoc.rb +0 -2
  16. data/lib/isodoc/common.rb +2 -0
  17. data/lib/isodoc/convert.rb +10 -4
  18. data/lib/isodoc/css.rb +30 -26
  19. data/lib/isodoc/function/blocks.rb +26 -8
  20. data/lib/isodoc/function/blocks_example_note.rb +2 -2
  21. data/lib/isodoc/function/cleanup.rb +53 -45
  22. data/lib/isodoc/function/form.rb +51 -0
  23. data/lib/isodoc/function/inline.rb +8 -7
  24. data/lib/isodoc/function/references.rb +71 -77
  25. data/lib/isodoc/function/section.rb +28 -16
  26. data/lib/isodoc/function/table.rb +22 -22
  27. data/lib/isodoc/function/terms.rb +6 -7
  28. data/lib/isodoc/function/to_word_html.rb +19 -25
  29. data/lib/isodoc/function/utils.rb +180 -160
  30. data/lib/isodoc/gem_tasks.rb +36 -38
  31. data/lib/isodoc/headlesshtml_convert.rb +8 -7
  32. data/lib/isodoc/html_convert.rb +10 -4
  33. data/lib/isodoc/html_function/comments.rb +14 -12
  34. data/lib/isodoc/html_function/footnotes.rb +14 -7
  35. data/lib/isodoc/html_function/form.rb +62 -0
  36. data/lib/isodoc/html_function/html.rb +30 -26
  37. data/lib/isodoc/html_function/postprocess.rb +191 -226
  38. data/lib/isodoc/html_function/postprocess_footnotes.rb +59 -0
  39. data/lib/isodoc/html_function/sectionsplit.rb +230 -0
  40. data/lib/isodoc/i18n.rb +33 -31
  41. data/lib/isodoc/metadata.rb +22 -20
  42. data/lib/isodoc/metadata_contributor.rb +31 -28
  43. data/lib/isodoc/pdf_convert.rb +11 -13
  44. data/lib/isodoc/presentation_function/bibdata.rb +54 -30
  45. data/lib/isodoc/presentation_function/block.rb +17 -8
  46. data/lib/isodoc/presentation_function/inline.rb +72 -120
  47. data/lib/isodoc/presentation_function/math.rb +84 -0
  48. data/lib/isodoc/presentation_function/section.rb +55 -19
  49. data/lib/isodoc/presentation_xml_convert.rb +2 -0
  50. data/lib/isodoc/sassc_importer.rb +1 -1
  51. data/lib/isodoc/version.rb +1 -1
  52. data/lib/isodoc/word_function/body.rb +28 -24
  53. data/lib/isodoc/word_function/footnotes.rb +22 -15
  54. data/lib/isodoc/word_function/postprocess.rb +50 -36
  55. data/lib/isodoc/xref.rb +11 -10
  56. data/lib/isodoc/xref/xref_counter.rb +32 -17
  57. data/lib/isodoc/xref/xref_gen.rb +33 -21
  58. data/lib/isodoc/xref/xref_gen_seq.rb +60 -35
  59. data/lib/isodoc/xref/xref_sect_gen.rb +37 -35
  60. data/spec/assets/scripts_override.html +3 -0
  61. data/spec/isodoc/blocks_spec.rb +2258 -2622
  62. data/spec/isodoc/cleanup_spec.rb +1103 -1107
  63. data/spec/isodoc/form_spec.rb +156 -0
  64. data/spec/isodoc/i18n_spec.rb +802 -917
  65. data/spec/isodoc/inline_spec.rb +1105 -921
  66. data/spec/isodoc/lists_spec.rb +316 -315
  67. data/spec/isodoc/metadata_spec.rb +384 -379
  68. data/spec/isodoc/postproc_spec.rb +1783 -1549
  69. data/spec/isodoc/presentation_xml_spec.rb +355 -278
  70. data/spec/isodoc/ref_spec.rb +718 -723
  71. data/spec/isodoc/section_spec.rb +216 -199
  72. data/spec/isodoc/sectionsplit_spec.rb +190 -0
  73. data/spec/isodoc/table_spec.rb +41 -42
  74. data/spec/isodoc/terms_spec.rb +84 -84
  75. data/spec/isodoc/xref_spec.rb +1024 -930
  76. metadata +33 -7
@@ -1,268 +1,233 @@
1
1
  require "isodoc/html_function/mathvariant_to_plain"
2
+ require_relative "postprocess_footnotes"
3
+
4
+ module IsoDoc
5
+ module HtmlFunction
6
+ module Html
7
+ def postprocess(result, filename, _dir)
8
+ result = from_xhtml(cleanup(to_xhtml(textcleanup(result))))
9
+ toHTML(result, filename)
10
+ @files_to_delete.each { |f| FileUtils.rm_rf f }
11
+ end
2
12
 
3
- module IsoDoc::HtmlFunction
4
- module Html
5
- def postprocess(result, filename, _dir)
6
- result = from_xhtml(cleanup(to_xhtml(textcleanup(result))))
7
- toHTML(result, filename)
8
- @files_to_delete.each { |f| FileUtils.rm_rf f }
9
- end
10
-
11
- def script_cdata(result)
12
- result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>")
13
- .gsub(%r{\]\]>\s*</script>}, "</script>")
14
- .gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>")
15
- .gsub(%r{</script>\s*\]\]>}, "</script>")
16
- end
13
+ def script_cdata(result)
14
+ result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>")
15
+ .gsub(%r{\]\]>\s*</script>}, "</script>")
16
+ .gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>")
17
+ .gsub(%r{</script>\s*\]\]>}, "</script>")
18
+ end
17
19
 
18
- def toHTML(result, filename)
19
- result = from_xhtml(html_cleanup(to_xhtml(result)))
20
- # result = populate_template(result, :html)
21
- result = from_xhtml(move_images(to_xhtml(result)))
22
- result = html5(script_cdata(inject_script(result)))
23
- File.open(filename, "w:UTF-8") { |f| f.write(result) }
24
- end
20
+ def toHTML(result, filename)
21
+ result = from_xhtml(html_cleanup(to_xhtml(result)))
22
+ # result = populate_template(result, :html)
23
+ result = from_xhtml(move_images(to_xhtml(result)))
24
+ result = html5(script_cdata(inject_script(result)))
25
+ File.open(filename, "w:UTF-8") { |f| f.write(result) }
26
+ end
25
27
 
26
- def html5(doc)
27
- doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>")
28
- .sub(%r{<\?xml[^>]+>}, "")
29
- end
28
+ def html5(doc)
29
+ doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>")
30
+ .sub(%r{<\?xml[^>]+>}, "")
31
+ end
30
32
 
31
- def html_cleanup(x)
32
- mathml(
33
- footnote_format(
34
- footnote_backlinks(
35
- html_toc(
36
- term_header(html_footnote_filter(html_preface(htmlstyle(x))))
37
- )
38
- )
39
- )
40
- )
41
- end
33
+ def html_cleanup(html)
34
+ html = term_header(html_footnote_filter(html_preface(htmlstyle(html))))
35
+ html = footnote_format(footnote_backlinks(html_toc(html)))
36
+ mathml(html_list_clean(html))
37
+ end
42
38
 
43
- def mathml(docxml)
44
- IsoDoc::HtmlFunction::MathvariantToPlain.new(docxml).convert
45
- end
39
+ def html_list_clean(html)
40
+ html.xpath("//ol/div | //ul/div").each do |div|
41
+ li = div&.xpath("./preceding-sibling::li")&.last ||
42
+ div.at("./following-sibling::li")
43
+ div.parent = li
44
+ end
45
+ html
46
+ end
46
47
 
47
- def htmlstylesheet(file)
48
- return if file.nil?
49
- file.open if file.is_a?(Tempfile)
50
- stylesheet = file.read
51
- xml = Nokogiri::XML("<style/>")
52
- xml.children.first << Nokogiri::XML::Comment.new(xml, "\n#{stylesheet}\n")
53
- file.close
54
- file.unlink if file.is_a?(Tempfile)
55
- xml.root.to_s
56
- end
48
+ def mathml(docxml)
49
+ IsoDoc::HtmlFunction::MathvariantToPlain.new(docxml).convert
50
+ end
57
51
 
58
- def htmlstyle(docxml)
59
- return docxml unless @htmlstylesheet
60
- title = docxml.at("//*[local-name() = 'head']/*[local-name() = 'title']")
61
- head = docxml.at("//*[local-name() = 'head']")
62
- head << htmlstylesheet(@htmlstylesheet)
63
- s = htmlstylesheet(@htmlstylesheet_override) and head << s
64
- docxml
65
- end
52
+ def htmlstylesheet(file)
53
+ return if file.nil?
54
+
55
+ file.open if file.is_a?(Tempfile)
56
+ stylesheet = file.read
57
+ xml = Nokogiri::XML("<style/>")
58
+ xml.children.first << Nokogiri::XML::Comment
59
+ .new(xml, "\n#{stylesheet}\n")
60
+ file.close
61
+ file.unlink if file.is_a?(Tempfile)
62
+ xml.root.to_s
63
+ end
66
64
 
67
- def html_preface(docxml)
68
- html_cover(docxml) if @htmlcoverpage
69
- html_intro(docxml) if @htmlintropage
70
- docxml.at("//body") << mathjax(@openmathdelim, @closemathdelim)
71
- docxml.at("//body") << sourcecode_highlighter
72
- html_main(docxml)
73
- authority_cleanup(docxml)
74
- docxml
75
- end
65
+ def htmlstyle(docxml)
66
+ return docxml unless @htmlstylesheet
76
67
 
77
- def authority_cleanup1(docxml, klass)
78
- dest = docxml.at("//div[@id = 'boilerplate-#{klass}-destination']")
79
- auth = docxml.at("//div[@id = 'boilerplate-#{klass}' or @class = 'boilerplate-#{klass}']")
80
- auth&.xpath(".//h1[not(text())] | .//h2[not(text())]")&.each { |h| h.remove }
81
- auth&.xpath(".//h1 | .//h2")&.each { |h| h["class"] = "IntroTitle" }
82
- dest and auth and dest.replace(auth.remove)
83
- end
68
+ head = docxml.at("//*[local-name() = 'head']")
69
+ head << htmlstylesheet(@htmlstylesheet)
70
+ s = htmlstylesheet(@htmlstylesheet_override) and head << s
71
+ docxml
72
+ end
84
73
 
85
- def authority_cleanup(docxml)
86
- %w(copyright license legal feedback).each do |t|
87
- authority_cleanup1(docxml, t)
74
+ def html_preface(docxml)
75
+ html_cover(docxml) if @htmlcoverpage && !@bare
76
+ html_intro(docxml) if @htmlintropage && !@bare
77
+ docxml.at("//body") << mathjax(@openmathdelim, @closemathdelim)
78
+ docxml.at("//body") << sourcecode_highlighter
79
+ html_main(docxml)
80
+ authority_cleanup(docxml)
81
+ docxml
88
82
  end
89
- end
90
83
 
91
- def html_cover(docxml)
92
- doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
93
- d = docxml.at('//div[@class="title-section"]')
94
- # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
95
- d.children.first.add_previous_sibling populate_template(doc.to_xml(encoding: "US-ASCII"), :html)
96
- end
84
+ def authority_cleanup1(docxml, klass)
85
+ dest = docxml.at("//div[@id = 'boilerplate-#{klass}-destination']")
86
+ auth = docxml.at("//div[@id = 'boilerplate-#{klass}' or "\
87
+ "@class = 'boilerplate-#{klass}']")
88
+ auth&.xpath(".//h1[not(text())] | .//h2[not(text())]")&.each(&:remove)
89
+ auth&.xpath(".//h1 | .//h2")&.each { |h| h["class"] = "IntroTitle" }
90
+ dest and auth and dest.replace(auth.remove)
91
+ end
97
92
 
98
- def html_intro(docxml)
99
- doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
100
- d = docxml.at('//div[@class="prefatory-section"]')
101
- # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
102
- d.children.first.add_previous_sibling populate_template(doc.to_xml(encoding: "US-ASCII"), :html)
103
- end
93
+ def authority_cleanup(docxml)
94
+ %w(copyright license legal feedback).each do |t|
95
+ authority_cleanup1(docxml, t)
96
+ end
97
+ end
104
98
 
105
- def html_toc_entry(level, header)
106
- %(<li class="#{level}"><a href="##{header['id']}">\
107
- #{header_strip(header)}</a></li>)
108
- end
99
+ def html_cover(docxml)
100
+ doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
101
+ d = docxml.at('//div[@class="title-section"]')
102
+ # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
103
+ d.children.first.add_previous_sibling(
104
+ populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
105
+ )
106
+ end
109
107
 
110
- def toclevel_classes
111
- (1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
112
- end
108
+ def html_intro(docxml)
109
+ doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
110
+ d = docxml.at('//div[@class="prefatory-section"]')
111
+ # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
112
+ d.children.first.add_previous_sibling(
113
+ populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
114
+ )
115
+ end
113
116
 
114
- def toclevel
115
- ret = toclevel_classes.map { |l| "#{l}:not(:empty):not(.TermNum):not(.noTOC)" }
116
- <<~HEAD.freeze
117
- function toclevel() { return "#{ret.join(',')}";}
118
- HEAD
119
- end
117
+ def html_toc_entry(level, header)
118
+ %(<li class="#{level}"><a href="##{header['id']}">\
119
+ #{header_strip(header)}</a></li>)
120
+ end
120
121
 
121
- # needs to be same output as toclevel
122
- def html_toc(docxml)
123
- (idx = docxml.at("//div[@id = 'toc']")) or (return docxml)
124
- toc = "<ul>"
125
- path = toclevel_classes.map do |l|
126
- "//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][text()]"
122
+ def toclevel_classes
123
+ (1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
127
124
  end
128
- docxml.xpath(path.join(" | ")).each_with_index do |h, tocidx|
129
- h["id"] ||= "toc#{tocidx}"
130
- toc += html_toc_entry(h.name, h)
125
+
126
+ def toclevel
127
+ ret = toclevel_classes.map do |l|
128
+ "#{l}:not(:empty):not(.TermNum):not(.noTOC)"
129
+ end
130
+ <<~HEAD.freeze
131
+ function toclevel() { return "#{ret.join(',')}";}
132
+ HEAD
131
133
  end
132
- idx.children = "#{toc}</ul>"
133
- docxml
134
- end
135
134
 
136
- # presupposes that the image source is local
137
- def move_images(docxml)
138
- FileUtils.rm_rf tmpimagedir
139
- FileUtils.mkdir tmpimagedir
140
- docxml.xpath("//*[local-name() = 'img']").each do |i|
141
- i["width"], i["height"] = Html2Doc.image_resize(i, image_localfile(i),
142
- @maxheight, @maxwidth)
143
- next if /^data:/.match i["src"]
144
- @datauriimage ? datauri(i) : move_image1(i)
135
+ # needs to be same output as toclevel
136
+ def html_toc(docxml)
137
+ idx = docxml.at("//div[@id = 'toc']") or return docxml
138
+ toc = "<ul>"
139
+ path = toclevel_classes.map do |l|
140
+ "//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][text()]"
141
+ end
142
+ docxml.xpath(path.join(" | ")).each_with_index do |h, tocidx|
143
+ h["id"] ||= "toc#{tocidx}"
144
+ toc += html_toc_entry(h.name, h)
145
+ end
146
+ idx.children = "#{toc}</ul>"
147
+ docxml
145
148
  end
146
- docxml
147
- end
148
149
 
149
- def datauri(i)
150
- type = i["src"].split(".")[-1]
151
- supertype = type == "xml" ? "application" : "image"
152
- bin = IO.binread(image_localfile(i))
153
- data = Base64.strict_encode64(bin)
154
- i["src"] = "data:#{supertype}/#{type};base64,#{data}"
155
- end
150
+ # presupposes that the image source is local
151
+ def move_images(docxml)
152
+ FileUtils.rm_rf tmpimagedir
153
+ FileUtils.mkdir tmpimagedir
154
+ docxml.xpath("//*[local-name() = 'img']").each do |i|
155
+ i["width"], i["height"] = Html2Doc.image_resize(i, image_localfile(i),
156
+ @maxheight, @maxwidth)
157
+ next if /^data:/.match? i["src"]
156
158
 
157
- def image_suffix(i)
158
- type = i["mimetype"]&.sub(%r{^[^/*]+/}, "")
159
- matched = /\.(?<suffix>[^. \r\n\t]+)$/.match i["src"]
160
- type and !type.empty? and return type
161
- !matched.nil? and matched[:suffix] and return matched[:suffix]
162
- "png"
163
- end
159
+ @datauriimage ? datauri(i) : move_image1(i)
160
+ end
161
+ docxml
162
+ end
164
163
 
165
- def move_image1(i)
166
- suffix = image_suffix(i)
167
- uuid = UUIDTools::UUID.random_create.to_s
168
- fname = "#{uuid}.#{suffix}"
169
- new_full_filename = File.join(tmpimagedir, fname)
170
- local_filename = image_localfile(i)
171
- FileUtils.cp local_filename, new_full_filename
172
- i["src"] = File.join(rel_tmpimagedir, fname)
173
- end
164
+ def datauri(img)
165
+ type = img["src"].split(".")[-1]
166
+ supertype = type == "xml" ? "application" : "image"
167
+ bin = IO.binread(image_localfile(img))
168
+ data = Base64.strict_encode64(bin)
169
+ img["src"] = "data:#{supertype}/#{type};base64,#{data}"
170
+ end
174
171
 
175
- def inject_script(doc)
176
- return doc unless @scripts
177
- scripts = File.read(@scripts, encoding: "UTF-8")
178
- a = doc.split(%r{</body>})
179
- a[0] + scripts + "</body>" + a[1]
180
- end
172
+ def image_suffix(img)
173
+ type = img["mimetype"]&.sub(%r{^[^/*]+/}, "")
174
+ matched = /\.(?<suffix>[^. \r\n\t]+)$/.match img["src"]
175
+ type and !type.empty? and return type
181
176
 
182
- def update_footnote_filter(fn, x, i, seen)
183
- if seen[fn.text]
184
- x.at("./sup").content = seen[fn.text][:num].to_s
185
- fn.remove unless x["href"] == seen[fn.text][:href]
186
- x["href"] = seen[fn.text][:href]
187
- else
188
- seen[fn.text] = { num: i, href: x["href"] }
189
- x.at("./sup").content = i.to_s
190
- i += 1
177
+ !matched.nil? and matched[:suffix] and return matched[:suffix]
178
+ "png"
191
179
  end
192
- [i, seen]
193
- end
194
180
 
195
- def html_footnote_filter(docxml)
196
- seen = {}
197
- i = 1
198
- docxml.xpath('//a[@class = "FootnoteRef"]').each do |x|
199
- fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
200
- i, seen = update_footnote_filter(fn, x, i, seen)
181
+ def move_image1(img)
182
+ suffix = image_suffix(img)
183
+ uuid = UUIDTools::UUID.random_create.to_s
184
+ fname = "#{uuid}.#{suffix}"
185
+ new_full_filename = File.join(tmpimagedir, fname)
186
+ local_filename = image_localfile(img)
187
+ FileUtils.cp local_filename, new_full_filename
188
+ img["src"] = File.join(rel_tmpimagedir, fname)
201
189
  end
202
- docxml
203
- end
204
190
 
205
- def footnote_backlinks1(x, fn)
206
- xdup = x.dup
207
- xdup.remove["id"]
208
- if fn.elements.empty?
209
- fn.children.first.previous = xdup
210
- else
211
- fn.elements.first.children.first.previous = xdup
212
- end
213
- end
191
+ def inject_script(doc)
192
+ return doc unless @scripts
214
193
 
215
- def footnote_backlinks(docxml)
216
- seen = {}
217
- docxml.xpath('//a[@class = "FootnoteRef"]').each_with_index do |x, i|
218
- seen[x["href"]] and next or seen[x["href"]] = true
219
- fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
220
- footnote_backlinks1(x, fn)
221
- x["id"] ||= "fnref:#{i + 1}"
222
- fn.add_child "<a href='##{x['id']}'>&#x21A9;</a>"
194
+ scripts = File.read(@scripts, encoding: "UTF-8")
195
+ scripts_override = ""
196
+ @scripts_override and
197
+ scripts_override = File.read(@scripts_override, encoding: "UTF-8")
198
+ a = doc.split(%r{</body>})
199
+ "#{a[0]}#{scripts}#{scripts_override}</body>#{a[1]}"
223
200
  end
224
- docxml
225
- end
226
201
 
227
- def footnote_format(docxml)
228
- docxml.xpath("//a[@class = 'FootnoteRef']/sup").each do |x|
229
- footnote_reference_format(x)
230
- end
231
- docxml.xpath("//a[@class = 'TableFootnoteRef'] | "\
232
- "//span[@class = 'TableFootnoteRef']").each do |x|
233
- table_footnote_reference_format(x)
202
+ def sourcecode_highlighter
203
+ '<script src="https://cdn.rawgit.com/google/code-prettify/master/'\
204
+ 'loader/run_prettify.js"></script>'
234
205
  end
235
- docxml
236
- end
237
206
 
238
- def sourcecode_highlighter
239
- '<script src="https://cdn.rawgit.com/google/code-prettify/master/'\
240
- 'loader/run_prettify.js"></script>'
241
- end
242
-
243
- MATHJAX_ADDR =
244
- "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js".freeze
245
- MATHJAX = <<~"MATHJAX".freeze
246
- <script type="text/x-mathjax-config">
247
- MathJax.Hub.Config({
248
- "HTML-CSS": { preferredFont: "STIX" },
249
- asciimath2jax: { delimiters: [['OPEN', 'CLOSE']] }
250
- });
251
- </script>
252
- <script src="#{MATHJAX_ADDR}?config=MML_HTMLorMML-full" async="async"></script>
253
- MATHJAX
254
-
255
- def mathjax(open, close)
256
- MATHJAX.gsub("OPEN", open).gsub("CLOSE", close)
257
- end
207
+ MATHJAX_ADDR =
208
+ "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js".freeze
209
+ MATHJAX = <<~"MATHJAX".freeze
210
+ <script type="text/x-mathjax-config">
211
+ MathJax.Hub.Config({
212
+ "HTML-CSS": { preferredFont: "STIX" },
213
+ asciimath2jax: { delimiters: [['OPEN', 'CLOSE']] }
214
+ });
215
+ </script>
216
+ <script src="#{MATHJAX_ADDR}?config=MML_HTMLorMML-full" async="async"></script>
217
+ MATHJAX
218
+
219
+ def mathjax(open, close)
220
+ MATHJAX.gsub("OPEN", open).gsub("CLOSE", close)
221
+ end
258
222
 
259
- def term_header(docxml)
260
- %w(h1 h2 h3 h4 h5 h6 h7 h8).each do |h|
261
- docxml.xpath("//p[@class = 'TermNum'][../#{h}]").each do |p|
262
- p.name = "h#{h[1].to_i + 1}"
223
+ def term_header(docxml)
224
+ %w(h1 h2 h3 h4 h5 h6 h7 h8).each do |h|
225
+ docxml.xpath("//p[@class = 'TermNum'][../#{h}]").each do |p|
226
+ p.name = "h#{h[1].to_i + 1}"
227
+ end
263
228
  end
229
+ docxml
264
230
  end
265
- docxml
266
231
  end
267
232
  end
268
233
  end