isodoc 1.6.2 → 1.6.7
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.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +2 -12
- data/.hound.yml +3 -1
- data/.rubocop.yml +4 -6
- data/Rakefile +2 -2
- data/isodoc.gemspec +3 -2
- data/lib/isodoc-yaml/i18n-en.yaml +1 -0
- data/lib/isodoc-yaml/i18n-fr.yaml +1 -0
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
- data/lib/isodoc.rb +0 -2
- data/lib/isodoc/convert.rb +7 -1
- data/lib/isodoc/function/blocks.rb +5 -4
- data/lib/isodoc/function/cleanup.rb +52 -43
- data/lib/isodoc/function/inline.rb +7 -7
- data/lib/isodoc/function/references.rb +32 -51
- data/lib/isodoc/function/section.rb +28 -16
- data/lib/isodoc/function/table.rb +21 -22
- data/lib/isodoc/function/terms.rb +6 -7
- data/lib/isodoc/function/to_word_html.rb +6 -3
- data/lib/isodoc/function/utils.rb +181 -163
- data/lib/isodoc/gem_tasks.rb +8 -9
- data/lib/isodoc/headlesshtml_convert.rb +8 -7
- data/lib/isodoc/html_convert.rb +5 -1
- data/lib/isodoc/html_function/comments.rb +14 -12
- data/lib/isodoc/html_function/footnotes.rb +14 -7
- data/lib/isodoc/html_function/html.rb +30 -26
- data/lib/isodoc/html_function/postprocess.rb +191 -182
- data/lib/isodoc/html_function/sectionsplit.rb +230 -0
- data/lib/isodoc/metadata.rb +22 -20
- data/lib/isodoc/metadata_contributor.rb +31 -28
- data/lib/isodoc/pdf_convert.rb +11 -13
- data/lib/isodoc/presentation_function/bibdata.rb +61 -30
- data/lib/isodoc/presentation_function/inline.rb +34 -27
- data/lib/isodoc/presentation_function/section.rb +54 -19
- data/lib/isodoc/presentation_xml_convert.rb +2 -0
- data/lib/isodoc/sassc_importer.rb +1 -1
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_function/postprocess.rb +50 -36
- data/lib/isodoc/xref.rb +2 -0
- data/lib/isodoc/xref/xref_counter.rb +1 -2
- data/lib/isodoc/xref/xref_gen.rb +21 -14
- data/lib/isodoc/xref/xref_gen_seq.rb +60 -35
- data/lib/isodoc/xref/xref_sect_gen.rb +15 -15
- data/spec/assets/scripts_override.html +3 -0
- data/spec/isodoc/blocks_spec.rb +624 -997
- data/spec/isodoc/cleanup_spec.rb +40 -42
- data/spec/isodoc/i18n_spec.rb +694 -821
- data/spec/isodoc/inline_spec.rb +482 -328
- data/spec/isodoc/metadata_spec.rb +384 -379
- data/spec/isodoc/postproc_spec.rb +163 -55
- data/spec/isodoc/presentation_xml_spec.rb +355 -278
- data/spec/isodoc/ref_spec.rb +5 -5
- data/spec/isodoc/section_spec.rb +216 -199
- data/spec/isodoc/sectionsplit_spec.rb +190 -0
- data/spec/isodoc/table_spec.rb +41 -42
- data/spec/isodoc/terms_spec.rb +84 -84
- data/spec/isodoc/xref_spec.rb +974 -932
- metadata +22 -5
data/lib/isodoc/html_convert.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
require_relative "html_function/comments"
|
2
2
|
require_relative "html_function/footnotes"
|
3
3
|
require_relative "html_function/html"
|
4
|
-
require_relative "html_function/form"
|
5
4
|
require_relative "html_function/postprocess"
|
5
|
+
require_relative "html_function/sectionsplit"
|
6
|
+
require_relative "html_function/form"
|
6
7
|
|
7
8
|
module IsoDoc
|
8
9
|
class HtmlConvert < ::IsoDoc::Convert
|
@@ -23,6 +24,9 @@ module IsoDoc
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def convert(filename, file = nil, debug = false, output_filename = nil)
|
27
|
+
@sectionsplit and
|
28
|
+
return sectionsplit_convert(filename, file, debug, output_filename)
|
29
|
+
|
26
30
|
ret = super
|
27
31
|
Dir.exists?(tmpimagedir) and Dir["#{tmpimagedir}/*"].empty? and
|
28
32
|
FileUtils.rm_r tmpimagedir
|
@@ -24,16 +24,16 @@ module IsoDoc::HtmlFunction
|
|
24
24
|
=end
|
25
25
|
end
|
26
26
|
|
27
|
-
def comment_link_attrs(
|
28
|
-
{ style: "MsoCommentReference", target:
|
27
|
+
def comment_link_attrs(fnote, node)
|
28
|
+
{ style: "MsoCommentReference", target: fnote,
|
29
29
|
class: "commentLink", from: node["from"],
|
30
30
|
to: node["to"] }
|
31
31
|
end
|
32
32
|
|
33
33
|
# add in from and to links to move the comment into place
|
34
|
-
def make_comment_link(out,
|
35
|
-
out.span(**comment_link_attrs(
|
36
|
-
s1.a **{ style: "mso-comment-reference:SMC_#{
|
34
|
+
def make_comment_link(out, fnote, node)
|
35
|
+
out.span(**comment_link_attrs(fnote, node)) do |s1|
|
36
|
+
s1.a **{ style: "mso-comment-reference:SMC_#{fnote};"\
|
37
37
|
"mso-comment-date:#{node['date'].gsub(/[-:Z]/, '')}" }
|
38
38
|
end
|
39
39
|
end
|
@@ -44,9 +44,9 @@ module IsoDoc::HtmlFunction
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
def make_comment_text(node,
|
47
|
+
def make_comment_text(node, fnote)
|
48
48
|
noko do |xml|
|
49
|
-
xml.div **{ style: "mso-element:comment", id:
|
49
|
+
xml.div **{ style: "mso-element:comment", id: fnote } do |div|
|
50
50
|
div.span **{ style: %{mso-comment-author:"#{node['reviewer']}"} }
|
51
51
|
make_comment_target(div)
|
52
52
|
node.children.each { |n| parse(n, div) }
|
@@ -84,6 +84,7 @@ module IsoDoc::HtmlFunction
|
|
84
84
|
def comment_attributes(docxml, x)
|
85
85
|
fromlink = docxml.at("//*[@id='#{x['from']}']")
|
86
86
|
return(nil) if fromlink.nil?
|
87
|
+
|
87
88
|
tolink = docxml.at("//*[@id='#{x['to']}']") || fromlink
|
88
89
|
target = docxml.at("//*[@id='#{x['target']}']")
|
89
90
|
{ from: fromlink, to: tolink, target: target }
|
@@ -98,13 +99,13 @@ module IsoDoc::HtmlFunction
|
|
98
99
|
from["style"] != "mso-special-character:comment"
|
99
100
|
end
|
100
101
|
|
101
|
-
def insert_comment_cont(from,
|
102
|
-
# includes_to = from.at(".//*[@id='#{
|
103
|
-
while !from.nil? && from["id"] !=
|
102
|
+
def insert_comment_cont(from, upto, target)
|
103
|
+
# includes_to = from.at(".//*[@id='#{upto}']")
|
104
|
+
while !from.nil? && from["id"] != upto
|
104
105
|
following = from.xpath("./following::*")
|
105
|
-
(from = following.shift) && incl_to = from.at(".//*[@id='#{
|
106
|
+
(from = following.shift) && incl_to = from.at(".//*[@id='#{upto}']")
|
106
107
|
while !incl_to.nil? && !from.nil? && skip_comment_wrap(from)
|
107
|
-
(from = following.shift) && incl_to = from.at(".//*[@id='#{
|
108
|
+
(from = following.shift) && incl_to = from.at(".//*[@id='#{upto}']")
|
108
109
|
end
|
109
110
|
wrap_comment_cont(from, target) if !from.nil?
|
110
111
|
end
|
@@ -122,6 +123,7 @@ module IsoDoc::HtmlFunction
|
|
122
123
|
comments = []
|
123
124
|
docxml.xpath("//div[@style='mso-element:comment']").each do |c|
|
124
125
|
next unless c["id"] && !link_order[c["id"]].nil?
|
126
|
+
|
125
127
|
comments << { text: c.remove.to_s, id: c["id"] }
|
126
128
|
end
|
127
129
|
comments.sort! { |a, b| link_order[a[:id]] <=> link_order[b[:id]] }
|
@@ -3,6 +3,7 @@ module IsoDoc::HtmlFunction
|
|
3
3
|
|
4
4
|
def footnotes(div)
|
5
5
|
return if @footnotes.empty?
|
6
|
+
|
6
7
|
@footnotes.each { |fn| div.parent << fn }
|
7
8
|
end
|
8
9
|
|
@@ -44,15 +45,19 @@ module IsoDoc::HtmlFunction
|
|
44
45
|
def get_table_ancestor_id(node)
|
45
46
|
table = node.ancestors("table") || node.ancestors("figure")
|
46
47
|
return UUIDTools::UUID.random_create.to_s if table.empty?
|
48
|
+
|
47
49
|
table.last["id"]
|
48
50
|
end
|
49
51
|
|
52
|
+
# @seen_footnote:
|
53
|
+
# do not output footnote text if we have already seen it for this table
|
54
|
+
|
50
55
|
def table_footnote_parse(node, out)
|
51
56
|
fn = node["reference"] || UUIDTools::UUID.random_create.to_s
|
52
57
|
tid = get_table_ancestor_id(node)
|
53
58
|
make_table_footnote_link(out, tid + fn, fn)
|
54
|
-
# do not output footnote text if we have already seen it for this table
|
55
59
|
return if @seen_footnote.include?(tid + fn)
|
60
|
+
|
56
61
|
@in_footnote = true
|
57
62
|
out.aside **{ class: "footnote" } do |a|
|
58
63
|
a << make_table_footnote_text(node, tid + fn, fn)
|
@@ -62,8 +67,9 @@ module IsoDoc::HtmlFunction
|
|
62
67
|
end
|
63
68
|
|
64
69
|
def footnote_parse(node, out)
|
65
|
-
|
66
|
-
!node.ancestors.map
|
70
|
+
return table_footnote_parse(node, out) if (@in_table || @in_figure) &&
|
71
|
+
!node.ancestors.map(&:name).include?("name")
|
72
|
+
|
67
73
|
fn = node["reference"] || UUIDTools::UUID.random_create.to_s
|
68
74
|
attrs = { class: "FootnoteRef", href: "#fn:#{fn}" }
|
69
75
|
out.a **attrs do |a|
|
@@ -72,12 +78,13 @@ module IsoDoc::HtmlFunction
|
|
72
78
|
make_footnote(node, fn)
|
73
79
|
end
|
74
80
|
|
75
|
-
def make_footnote(node,
|
76
|
-
return if @seen_footnote.include?(
|
81
|
+
def make_footnote(node, fnote)
|
82
|
+
return if @seen_footnote.include?(fnote)
|
83
|
+
|
77
84
|
@in_footnote = true
|
78
|
-
@footnotes << make_generic_footnote_text(node,
|
85
|
+
@footnotes << make_generic_footnote_text(node, fnote)
|
79
86
|
@in_footnote = false
|
80
|
-
@seen_footnote <<
|
87
|
+
@seen_footnote << fnote
|
81
88
|
end
|
82
89
|
end
|
83
90
|
end
|
@@ -5,9 +5,9 @@ module IsoDoc::HtmlFunction
|
|
5
5
|
module Html
|
6
6
|
def convert1(docxml, filename, dir)
|
7
7
|
noko do |xml|
|
8
|
-
xml.html **{ lang:
|
8
|
+
xml.html **{ lang: @lang.to_s } do |html|
|
9
9
|
info docxml, nil
|
10
|
-
populate_css
|
10
|
+
populate_css
|
11
11
|
html.head { |head| define_head head, filename, dir }
|
12
12
|
make_body(html, docxml)
|
13
13
|
end
|
@@ -15,13 +15,17 @@ module IsoDoc::HtmlFunction
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def make_body1(body, _docxml)
|
18
|
+
return if @bare
|
19
|
+
|
18
20
|
body.div **{ class: "title-section" } do |div1|
|
19
21
|
div1.p { |p| p << " " } # placeholder
|
20
22
|
end
|
21
23
|
section_break(body)
|
22
24
|
end
|
23
25
|
|
24
|
-
def make_body2(body,
|
26
|
+
def make_body2(body, _docxml)
|
27
|
+
return if @bare
|
28
|
+
|
25
29
|
body.div **{ class: "prefatory-section" } do |div2|
|
26
30
|
div2.p { |p| p << " " } # placeholder
|
27
31
|
end
|
@@ -43,46 +47,47 @@ module IsoDoc::HtmlFunction
|
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
46
|
-
def googlefonts
|
50
|
+
def googlefonts
|
47
51
|
<<~HEAD.freeze
|
48
|
-
|
49
|
-
|
52
|
+
<link href="https://fonts.googleapis.com/css?family=Overpass:300,300i,600,900" rel="stylesheet">
|
53
|
+
<link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700,900" rel="stylesheet">
|
50
54
|
HEAD
|
51
55
|
end
|
52
56
|
|
53
|
-
def html_head
|
57
|
+
def html_head
|
54
58
|
<<~HEAD.freeze
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
59
|
+
<title>#{@meta&.get&.dig(:doctitle)}</title>
|
60
|
+
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
61
|
+
|
62
|
+
<!--TOC script import-->
|
63
|
+
<script type="text/javascript" src="https://cdn.rawgit.com/jgallen23/toc/0.3.2/dist/toc.min.js"></script>
|
64
|
+
<script type="text/javascript">#{toclevel}</script>
|
65
|
+
|
66
|
+
<!--Google fonts-->
|
67
|
+
<link rel="preconnect" href="https://fonts.gstatic.com">#{' '}
|
68
|
+
#{googlefonts}
|
69
|
+
<!--Font awesome import for the link icon-->
|
70
|
+
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/solid.css" integrity="sha384-v2Tw72dyUXeU3y4aM2Y0tBJQkGfplr39mxZqlTBDUZAb9BGoC40+rdFCG0m10lXk" crossorigin="anonymous">
|
71
|
+
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/fontawesome.css" integrity="sha384-q3jl8XQu1OpdLgGFvNRnPdj5VIlCvgsDQTQB6owSOHWlAurxul7f+JpUOVdAiJ5P" crossorigin="anonymous">
|
72
|
+
<style class="anchorjs"></style>
|
69
73
|
HEAD
|
70
74
|
end
|
71
75
|
|
72
|
-
def html_button
|
76
|
+
def html_button
|
73
77
|
'<button onclick="topFunction()" id="myBtn" '\
|
74
78
|
'title="Go to top">Top</button>'.freeze
|
75
79
|
end
|
76
80
|
|
77
81
|
def html_main(docxml)
|
78
|
-
docxml.at("//head").add_child(html_head
|
82
|
+
docxml.at("//head").add_child(html_head)
|
79
83
|
d = docxml.at('//div[@class="main-section"]')
|
80
84
|
d.name = "main"
|
81
|
-
d.children.empty? or d.children.first.previous = html_button
|
85
|
+
d.children.empty? or d.children.first.previous = html_button
|
82
86
|
end
|
83
87
|
|
84
88
|
def sourcecodelang(lang)
|
85
89
|
return unless lang
|
90
|
+
|
86
91
|
case lang.downcase
|
87
92
|
when "javascript" then "lang-js"
|
88
93
|
when "c" then "lang-c"
|
@@ -117,7 +122,6 @@ module IsoDoc::HtmlFunction
|
|
117
122
|
end
|
118
123
|
end
|
119
124
|
|
120
|
-
def table_long_strings_cleanup(docxml)
|
121
|
-
end
|
125
|
+
def table_long_strings_cleanup(docxml); end
|
122
126
|
end
|
123
127
|
end
|
@@ -1,224 +1,233 @@
|
|
1
1
|
require "isodoc/html_function/mathvariant_to_plain"
|
2
2
|
require_relative "postprocess_footnotes"
|
3
3
|
|
4
|
-
module IsoDoc
|
5
|
-
module
|
6
|
-
|
7
|
-
result
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def html5(doc)
|
29
|
+
doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>")
|
30
|
+
.sub(%r{<\?xml[^>]+>}, "")
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
footnote_format(
|
35
|
-
|
36
|
-
|
37
|
-
term_header(html_footnote_filter(html_preface(htmlstyle(x))))
|
38
|
-
)
|
39
|
-
)
|
40
|
-
)
|
41
|
-
)
|
42
|
-
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
|
43
38
|
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
def mathml(docxml)
|
49
|
+
IsoDoc::HtmlFunction::MathvariantToPlain.new(docxml).convert
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
59
64
|
|
60
|
-
|
61
|
-
|
65
|
+
def htmlstyle(docxml)
|
66
|
+
return docxml unless @htmlstylesheet
|
62
67
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
68
|
+
head = docxml.at("//*[local-name() = 'head']")
|
69
|
+
head << htmlstylesheet(@htmlstylesheet)
|
70
|
+
s = htmlstylesheet(@htmlstylesheet_override) and head << s
|
71
|
+
docxml
|
72
|
+
end
|
69
73
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
82
|
+
end
|
79
83
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
87
92
|
|
88
|
-
|
89
|
-
|
90
|
-
|
93
|
+
def authority_cleanup(docxml)
|
94
|
+
%w(copyright license legal feedback).each do |t|
|
95
|
+
authority_cleanup1(docxml, t)
|
96
|
+
end
|
91
97
|
end
|
92
|
-
end
|
93
98
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
102
107
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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
|
111
116
|
|
112
|
-
|
113
|
-
|
117
|
+
def html_toc_entry(level, header)
|
118
|
+
%(<li class="#{level}"><a href="##{header['id']}">\
|
114
119
|
#{header_strip(header)}</a></li>)
|
115
|
-
|
116
|
-
|
117
|
-
def toclevel_classes
|
118
|
-
(1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
|
119
|
-
end
|
120
|
+
end
|
120
121
|
|
121
|
-
|
122
|
-
|
123
|
-
"#{l}:not(:empty):not(.TermNum):not(.noTOC)"
|
122
|
+
def toclevel_classes
|
123
|
+
(1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
|
124
124
|
end
|
125
|
-
<<~HEAD.freeze
|
126
|
-
function toclevel() { return "#{ret.join(',')}";}
|
127
|
-
HEAD
|
128
|
-
end
|
129
125
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
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
|
136
133
|
end
|
137
|
-
|
138
|
-
|
139
|
-
|
134
|
+
|
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
|
140
148
|
end
|
141
|
-
idx.children = "#{toc}</ul>"
|
142
|
-
docxml
|
143
|
-
end
|
144
149
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
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"]
|
153
158
|
|
154
|
-
|
159
|
+
@datauriimage ? datauri(i) : move_image1(i)
|
160
|
+
end
|
161
|
+
docxml
|
155
162
|
end
|
156
|
-
docxml
|
157
|
-
end
|
158
163
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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
|
166
171
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
171
176
|
|
172
|
-
|
173
|
-
|
174
|
-
|
177
|
+
!matched.nil? and matched[:suffix] and return matched[:suffix]
|
178
|
+
"png"
|
179
|
+
end
|
175
180
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
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)
|
189
|
+
end
|
185
190
|
|
186
|
-
|
187
|
-
|
191
|
+
def inject_script(doc)
|
192
|
+
return doc unless @scripts
|
188
193
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
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]}"
|
200
|
+
end
|
193
201
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
202
|
+
def sourcecode_highlighter
|
203
|
+
'<script src="https://cdn.rawgit.com/google/code-prettify/master/'\
|
204
|
+
'loader/run_prettify.js"></script>'
|
205
|
+
end
|
198
206
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
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
|
214
222
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
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
|
219
228
|
end
|
229
|
+
docxml
|
220
230
|
end
|
221
|
-
docxml
|
222
231
|
end
|
223
232
|
end
|
224
233
|
end
|