Module: IsoDoc::HtmlFunction::Html

Included in:
IsoDoc::HeadlessHtmlConvert, IsoDoc::HtmlConvert, PdfConvert
Defined in:
lib/isodoc/html_function/html.rb

Constant Summary collapse

MATHJAX_ADDR =
"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js".freeze
MATHJAX =
<<~"MATHJAX".freeze
  <script type="text/x-mathjax-config">
    MathJax.Hub.Config({
      asciimath2jax: {
        delimiters: [['OPEN', 'CLOSE']]
      }
   });
  </script>
  <script src="#{MATHJAX_ADDR}?config=AM_HTMLorMML" async="async"></script>
MATHJAX

Instance Method Summary collapse

Instance Method Details

#datauri(i) ⇒ Object



278
279
280
281
282
283
# File 'lib/isodoc/html_function/html.rb', line 278

def datauri(i)
  type = i["src"].split(".")[-1]
  bin = IO.binread(File.join(@localdir, i["src"]))
  data = Base64.strict_encode64(bin)
  i["src"] = "data:image/#{type};base64,#{data}"
end


244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/isodoc/html_function/html.rb', line 244

def footnote_backlinks(docxml)
  seen = {}
  docxml.xpath('//a[@epub:type = "footnote"]').each_with_index do |x, i|
    next if seen[x["href"]]
    seen[x["href"]] = true
    fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
    x["id"] || x["id"] = "fnref:#{i + 1}"
    fn.elements.first.children.first.previous = x.dup
    fn.add_child "<a href='##{x['id']}'>&#x21A9;</a>"
  end
  docxml
end

#googlefontsObject



87
88
89
90
91
92
# File 'lib/isodoc/html_function/html.rb', line 87

def googlefonts()
  <<~HEAD.freeze
  <link href="https://fonts.googleapis.com/css?family=Overpass:300,300i,600,900" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700,900" rel="stylesheet">
  HEAD
end

#html_buttonObject



121
122
123
124
# File 'lib/isodoc/html_function/html.rb', line 121

def html_button()
  '<button onclick="topFunction()" id="myBtn" '\
    'title="Go to top">Top</button>'.freeze
end

#html_cleanup(x) ⇒ Object



55
56
57
58
59
# File 'lib/isodoc/html_function/html.rb', line 55

def html_cleanup(x)
  footnote_backlinks(html_toc(
    term_header((html_footnote_filter(html_preface(htmlstyle(x))))))
                    )
end

#html_cover(docxml) ⇒ Object



188
189
190
191
192
193
# File 'lib/isodoc/html_function/html.rb', line 188

def html_cover(docxml)
  cover = File.read(@htmlcoverpage, encoding: "UTF-8")
  coverxml = to_xhtml_fragment(cover)
  d = docxml.at('//div[@class="title-section"]')
  d.children.first.add_previous_sibling coverxml.to_xml(encoding: "US-ASCII")
end

#html_footnote_filter(docxml) ⇒ Object



234
235
236
237
238
239
240
241
242
# File 'lib/isodoc/html_function/html.rb', line 234

def html_footnote_filter(docxml)
  seen = {}
  i = 1
  docxml.xpath('//a[@epub:type = "footnote"]').each do |x|
    fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
    i, seen = update_footnote_filter(fn, x, i, seen)
  end
  docxml
end

#html_headObject



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/isodoc/html_function/html.rb', line 103

def html_head()
  <<~HEAD.freeze
<title>{{ doctitle }}</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!--TOC script import-->
<script type="text/javascript"  src="https://cdn.rawgit.com/jgallen23/toc/0.3.2/dist/toc.min.js"></script>
<script type="text/javascript">#{toclevel}</script>

<!--Google fonts-->
  #{googlefonts}
<!--Font awesome import for the link icon-->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/solid.css" integrity="sha384-v2Tw72dyUXeU3y4aM2Y0tBJQkGfplr39mxZqlTBDUZAb9BGoC40+rdFCG0m10lXk" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/fontawesome.css" integrity="sha384-q3jl8XQu1OpdLgGFvNRnPdj5VIlCvgsDQTQB6owSOHWlAurxul7f+JpUOVdAiJ5P" crossorigin="anonymous">
<style class="anchorjs"></style>
  HEAD
end

#html_intro(docxml) ⇒ Object



195
196
197
198
199
200
# File 'lib/isodoc/html_function/html.rb', line 195

def html_intro(docxml)
  intro = File.read(@htmlintropage, encoding: "UTF-8")
  introxml = to_xhtml_fragment(intro)
  d = docxml.at('//div[@class="prefatory-section"]')
  d.children.first.add_previous_sibling introxml.to_xml(encoding: "US-ASCII")
end

#html_main(docxml) ⇒ Object



126
127
128
129
130
131
# File 'lib/isodoc/html_function/html.rb', line 126

def html_main(docxml)
  docxml.at("//head").add_child(html_head())
  d = docxml.at('//div[@class="main-section"]')
  d.name = "main"
  d.children.empty? or d.children.first.previous = html_button()
end

#html_preface(docxml) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/isodoc/html_function/html.rb', line 169

def html_preface(docxml)
  html_cover(docxml) if @htmlcoverpage
  html_intro(docxml) if @htmlintropage
  docxml.at("//body") << mathjax(@openmathdelim, @closemathdelim)
  docxml.at("//body") << sourcecode_highlighter
  #if @scripts
  #  scripts = File.read(@scripts, encoding: "UTF-8")
  #  a = docxml.at("//body").add_child docxml.create_cdata(scripts)
  #end
  html_main(docxml)
  docxml
end

#html_toc(docxml) ⇒ Object



299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/isodoc/html_function/html.rb', line 299

def html_toc(docxml)
=begin
  idx = docxml.at("//div[@id = 'toc']") or return docxml
  toc = "<ul>"
  tocidx = 0
  docxml.xpath("//main//h1 | //main//h2[not(@class = 'TermNum')]").each do |h|
    h["id"] ||= "toc#{tocidx}"
    toc += html_toc_entry(h.name == "h1" ? 1 : 2, h)
    tocidx += 1
  end
  idx.children = "#{toc}</ul>"
=end
  docxml
end

#html_toc_entry(level, header) ⇒ Object



295
296
297
# File 'lib/isodoc/html_function/html.rb', line 295

def html_toc_entry(level, header)
  %(<li class="h#{level}"><a href="##{header['id']}">#{header_strip(header)}</a></li>)
end

#htmlstyle(docxml) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
# File 'lib/isodoc/html_function/html.rb', line 209

def htmlstyle(docxml)
  return docxml unless @htmlstylesheet
  title = docxml.at("//*[local-name() = 'head']/*[local-name() = 'title']")
  head = docxml.at("//*[local-name() = 'head']")
  css = htmlstylesheet
  if title.nil? then head.children.first.add_previous_sibling css
  else
    title.add_next_sibling css
  end
  docxml
end

#htmlstylesheetObject



202
203
204
205
206
207
# File 'lib/isodoc/html_function/html.rb', line 202

def htmlstylesheet
  stylesheet = File.read(@htmlstylesheet, encoding: "UTF-8")
  xml = Nokogiri::XML("<style/>")
  xml.children.first << Nokogiri::XML::Comment.new(xml, "\n#{stylesheet}\n")
  xml.root.to_s
end

#image_localfile(i) ⇒ Object



270
271
272
273
274
275
276
# File 'lib/isodoc/html_function/html.rb', line 270

def image_localfile(i)
  if /^data:image/.match i["src"]
    save_dataimage(i["src"], false)
  else
    File.join(@localdir, i["src"])
  end
end

#inject_script(doc) ⇒ Object



182
183
184
185
186
# File 'lib/isodoc/html_function/html.rb', line 182

def inject_script(doc)
  return doc unless @scripts
  scripts = File.read(@scripts, encoding: "UTF-8")
  doc.sub("</body>", scripts + "\n</body>")
end

#make_body1(body, _docxml) ⇒ Object



6
7
8
9
10
11
# File 'lib/isodoc/html_function/html.rb', line 6

def make_body1(body, _docxml)
  body.div **{ class: "title-section" } do |div1|
    div1.p { |p| p << "&nbsp;" } # placeholder
  end
  section_break(body)
end

#make_body2(body, docxml) ⇒ Object



13
14
15
16
17
18
# File 'lib/isodoc/html_function/html.rb', line 13

def make_body2(body, docxml)
  body.div **{ class: "prefatory-section" } do |div2|
    div2.p { |p| p << "&nbsp;" } # placeholder
  end
  section_break(body)
end

#make_body3(body, docxml) ⇒ Object



20
21
22
23
24
25
26
27
28
29
# File 'lib/isodoc/html_function/html.rb', line 20

def make_body3(body, docxml)
  body.div **{ class: "main-section" } do |div3|
    abstract docxml, div3
    foreword docxml, div3
    introduction docxml, div3
    middle docxml, div3
    footnotes div3
    comments div3
  end
end

#mathjax(open, close) ⇒ Object



74
75
76
# File 'lib/isodoc/html_function/html.rb', line 74

def mathjax(open, close)
  MATHJAX.gsub("OPEN", open).gsub("CLOSE", close)
end

#move_image1(i) ⇒ Object



285
286
287
288
289
290
291
292
293
# File 'lib/isodoc/html_function/html.rb', line 285

def move_image1(i)
  matched = /\.(?<suffix>[^. \r\n\t]+)$/.match i["src"]
  uuid = UUIDTools::UUID.random_create.to_s
  fname = "#{uuid}.#{matched[:suffix]}"
  new_full_filename = File.join(tmpimagedir, fname)
  local_filename = image_localfile(i)
  FileUtils.cp local_filename, new_full_filename
  i["src"] = File.join(rel_tmpimagedir, fname)
end

#move_images(docxml) ⇒ Object

presupposes that the image source is local



258
259
260
261
262
263
264
265
266
267
268
# File 'lib/isodoc/html_function/html.rb', line 258

def move_images(docxml)
  FileUtils.rm_rf tmpimagedir
  FileUtils.mkdir tmpimagedir
  docxml.xpath("//*[local-name() = 'img']").each do |i|
    i["width"], i["height"] = Html2Doc.image_resize(i, image_localfile(i),
                                                    @maxheight, @maxwidth)
    next if /^data:image/.match i["src"]
    @datauriimage ? datauri(i) : move_image1(i)
  end
  docxml
end

#postprocess(result, filename, dir) ⇒ Object



31
32
33
34
35
# File 'lib/isodoc/html_function/html.rb', line 31

def postprocess(result, filename, dir)
  result = from_xhtml(cleanup(to_xhtml(result)))
  toHTML(result, filename)
  @files_to_delete.each { |f| FileUtils.rm_rf f }
end

#script_cdata(result) ⇒ Object



37
38
39
40
41
42
# File 'lib/isodoc/html_function/html.rb', line 37

def script_cdata(result)
  result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>").
    gsub(%r{\]\]>\s*</script>}, "</script>").
    gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>").
    gsub(%r{</script>\s*\]\]>}, "</script>")
end

#sourcecode_highlighterObject



133
134
135
# File 'lib/isodoc/html_function/html.rb', line 133

def sourcecode_highlighter
  '<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>'
end

#sourcecode_parse(node, out) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/isodoc/html_function/html.rb', line 156

def sourcecode_parse(node, out)
  name = node.at(ns("./name"))
  out.pre **attr_code(id: node["id"], 
                      class: "prettyprint #{sourcecodelang(node&.at(ns('./@lang'))&.value)}") do |div|
    @sourcecode = true
    node.children.each do |n|
      parse(n, div) unless n.name == "name"
    end
    @sourcecode = false
    sourcecode_name_parse(node, div, name) if name
  end
end

#sourcecodelang(lang) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/isodoc/html_function/html.rb', line 137

def sourcecodelang(lang)
  return unless lang
  case lang.downcase
  when "javascript" then "lang-js"
  when "c" then "lang-c"
  when "c+" then "lang-cpp"
  when "console" then "lang-bsh"
  when "ruby" then "lang-rb"
  when "html" then "lang-html"
  when "java" then "lang-java"
  when "xml" then "lang-xml"
  when "perl" then "lang-perl"
  when "python" then "lang-py"
  when "xsl" then "lang-xsl"
  else
    ""
  end
end

#term_header(docxml) ⇒ Object



78
79
80
81
82
83
84
85
# File 'lib/isodoc/html_function/html.rb', line 78

def term_header(docxml)
  %w(h1 h2 h3 h4 h5 h6 h7 h8).each do |h|
    docxml.xpath("//p[@class = 'TermNum'][../#{h}]").each do |p|
      p.name = "h#{h[1].to_i + 1}"
    end
  end
  docxml
end

#toclevelObject



94
95
96
97
98
99
100
101
# File 'lib/isodoc/html_function/html.rb', line 94

def toclevel
  <<~HEAD.freeze
function toclevel() { var i; var text = "";
  for(i = 1; i <= #{@htmlToClevels}; i++) {
    if (i > 1) { text += ","; } text += "h" + i + ":not(:empty):not(.TermNum)"; } 
  return text;}
  HEAD
end

#toHTML(result, filename) ⇒ Object



44
45
46
47
48
49
50
51
52
53
# File 'lib/isodoc/html_function/html.rb', line 44

def toHTML(result, filename)
  result = (from_xhtml(html_cleanup(to_xhtml(result))))
  result = populate_template(result, :html)
  #result = script_cdata(from_xhtml(move_images(to_xhtml(result))))
  result = from_xhtml(move_images(to_xhtml(result)))
  result = script_cdata(inject_script(result))
  File.open("#{filename}.html", "w:UTF-8") do |f|
    f.write(result)
  end
end

#update_footnote_filter(fn, x, i, seen) ⇒ Object



221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/isodoc/html_function/html.rb', line 221

def update_footnote_filter(fn, x, i, seen)
  if seen[fn.text]
    x.at("./sup").content = seen[fn.text][:num].to_s
    fn.remove unless x["href"] == seen[fn.text][:href]
    x["href"] = seen[fn.text][:href]
  else
    seen[fn.text] = { num: i, href: x["href"] }
    x.at("./sup").content = i.to_s
    i += 1
  end
  [i, seen]
end