html2doc 1.1.0 → 1.1.1
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/.rubocop.yml +0 -2
- data/Gemfile +2 -2
- data/Rakefile +1 -1
- data/bin/html2doc +2 -3
- data/lib/html2doc/base.rb +45 -44
- data/lib/html2doc/lists.rb +33 -25
- data/lib/html2doc/math.rb +71 -67
- data/lib/html2doc/mime.rb +28 -20
- data/lib/html2doc/notes.rb +34 -31
- data/lib/html2doc/version.rb +1 -1
- data/spec/html2doc_spec.rb +495 -496
- metadata +2 -2
data/lib/html2doc/mime.rb
CHANGED
@@ -7,20 +7,20 @@ require "fileutils"
|
|
7
7
|
module Html2Doc
|
8
8
|
def self.mime_preamble(boundary, filename, result)
|
9
9
|
<<~"PREAMBLE"
|
10
|
-
|
11
|
-
|
10
|
+
MIME-Version: 1.0
|
11
|
+
Content-Type: multipart/related; boundary="#{boundary}"
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
--#{boundary}
|
14
|
+
Content-ID: <#{File.basename(filename)}>
|
15
|
+
Content-Disposition: inline; filename="#{File.basename(filename)}"
|
16
|
+
Content-Type: text/html; charset="utf-8"
|
17
17
|
|
18
|
-
|
18
|
+
#{result}
|
19
19
|
|
20
20
|
PREAMBLE
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.mime_attachment(boundary,
|
23
|
+
def self.mime_attachment(boundary, _filename, item, dir)
|
24
24
|
content_type = mime_type(item)
|
25
25
|
text_mode = %w[text application].any? { |p| content_type.start_with? p }
|
26
26
|
|
@@ -29,13 +29,13 @@ module Html2Doc
|
|
29
29
|
|
30
30
|
encoded_file = Base64.strict_encode64(content).gsub(/(.{76})/, "\\1\n")
|
31
31
|
<<~"FILE"
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
--#{boundary}
|
33
|
+
Content-ID: <#{File.basename(item)}>
|
34
|
+
Content-Disposition: inline; filename="#{File.basename(item)}"
|
35
|
+
Content-Transfer-Encoding: base64
|
36
|
+
Content-Type: #{content_type}
|
37
37
|
|
38
|
-
|
38
|
+
#{encoded_file}
|
39
39
|
|
40
40
|
FILE
|
41
41
|
end
|
@@ -59,6 +59,7 @@ module Html2Doc
|
|
59
59
|
Dir.foreach(dir) do |item|
|
60
60
|
next if item == "." || item == ".." || /^\./.match(item) ||
|
61
61
|
item == "filelist.xml"
|
62
|
+
|
62
63
|
mhtml += mime_attachment(boundary, "#{filename}.htm", item, dir)
|
63
64
|
end
|
64
65
|
mhtml += "--#{boundary}--"
|
@@ -69,6 +70,9 @@ module Html2Doc
|
|
69
70
|
mhtml.gsub %r{(<img[^>]*?src=")([^\"']+)(['"])}m do |m|
|
70
71
|
repl = "#{$1}cid:#{File.basename($2)}#{$3}"
|
71
72
|
/^data:|^https?:/.match($2) ? m : repl
|
73
|
+
end.gsub %r{(<v:imagedata[^>]*?src=")([^\"']+)(['"])}m do |m|
|
74
|
+
repl = "#{$1}cid:#{File.basename($2)}#{$3}"
|
75
|
+
/^data:|^https?:/.match($2) ? m : repl
|
72
76
|
end
|
73
77
|
end
|
74
78
|
|
@@ -78,6 +82,7 @@ module Html2Doc
|
|
78
82
|
s = [i["width"].to_i, i["height"].to_i]
|
79
83
|
s = realSize if s[0].zero? && s[1].zero?
|
80
84
|
return [nil, nil] if realSize.nil? || realSize[0].nil? || realSize[1].nil?
|
85
|
+
|
81
86
|
s[1] = s[0] * realSize[1] / realSize[0] if s[1].zero? && !s[0].zero?
|
82
87
|
s[0] = s[1] * realSize[0] / realSize[1] if s[0].zero? && !s[1].zero?
|
83
88
|
s = [(s[0] * maxheight / s[1]).ceil, maxheight] if s[1] > maxheight
|
@@ -92,7 +97,7 @@ module Html2Doc
|
|
92
97
|
end
|
93
98
|
|
94
99
|
def self.warnsvg(src)
|
95
|
-
warn "#{src}: SVG not supported" if /\.svg$/i.match(src)
|
100
|
+
warn "#{src}: SVG not supported" if /\.svg$/i.match?(src)
|
96
101
|
end
|
97
102
|
|
98
103
|
# only processes locally stored images
|
@@ -101,10 +106,11 @@ module Html2Doc
|
|
101
106
|
next unless i.element? && %w(img v:imagedata).include?(i.name)
|
102
107
|
#warnsvg(i["src"])
|
103
108
|
next if /^http/.match i["src"]
|
104
|
-
next if %r{^data:(image|application)/[^;]+;base64}.match i["src"]
|
109
|
+
next if %r{^data:(image|application)/[^;]+;base64}.match? i["src"]
|
110
|
+
|
105
111
|
local_filename = %r{^([A-Z]:)?/}.match(i["src"]) ? i["src"] :
|
106
112
|
File.join(localdir, i["src"])
|
107
|
-
new_filename = "#{mkuuid}#{File.extname(i[
|
113
|
+
new_filename = "#{mkuuid}#{File.extname(i['src'])}"
|
108
114
|
FileUtils.cp local_filename, File.join(dir, new_filename)
|
109
115
|
i["width"], i["height"] = image_resize(i, local_filename, 680, 400)
|
110
116
|
i["src"] = File.join(File.basename(dir), new_filename)
|
@@ -112,7 +118,7 @@ module Html2Doc
|
|
112
118
|
docxml
|
113
119
|
end
|
114
120
|
|
115
|
-
# do not parse the header through Nokogiri, since it will contain
|
121
|
+
# do not parse the header through Nokogiri, since it will contain
|
116
122
|
# non-XML like <![if !supportFootnotes]>
|
117
123
|
def self.header_image_cleanup(doc, dir, filename, localdir)
|
118
124
|
doc.split(%r{(<img [^>]*>|<v:imagedata [^>]*>)}).each_slice(2).map do |a|
|
@@ -120,14 +126,15 @@ module Html2Doc
|
|
120
126
|
end.join
|
121
127
|
end
|
122
128
|
|
123
|
-
def self.header_image_cleanup1(a, dir,
|
129
|
+
def self.header_image_cleanup1(a, dir, _filename, localdir)
|
124
130
|
if a.size == 2 && !(/ src="https?:/.match a[1]) &&
|
125
131
|
!(%r{ src="data:(image|application)/[^;]+;base64}.match a[1])
|
126
132
|
m = / src=['"](?<src>[^"']+)['"]/.match a[1]
|
127
133
|
#warnsvg(m[:src])
|
128
134
|
m2 = /\.(?<suffix>[a-zA-Z_0-9]+)$/.match m[:src]
|
129
135
|
new_filename = "#{mkuuid}.#{m2[:suffix]}"
|
130
|
-
old_filename = %r{^([A-Z]:)?/}.match(m[:src]) ? m[:src] :
|
136
|
+
old_filename = %r{^([A-Z]:)?/}.match?(m[:src]) ? m[:src] :
|
137
|
+
File.join(localdir, m[:src])
|
131
138
|
FileUtils.cp old_filename, File.join(dir, new_filename)
|
132
139
|
a[1].sub!(%r{ src=['"](?<src>[^"']+)['"]}, " src='cid:#{new_filename}'")
|
133
140
|
end
|
@@ -140,6 +147,7 @@ module Html2Doc
|
|
140
147
|
<o:MainFile HRef="../#{filename}.htm"/>}
|
141
148
|
Dir.entries(dir).sort.each do |item|
|
142
149
|
next if item == "." || item == ".." || /^\./.match(item)
|
150
|
+
|
143
151
|
f.write %{ <o:File HRef="#{item}"/>\n}
|
144
152
|
end
|
145
153
|
f.write("</xml>\n")
|
data/lib/html2doc/notes.rb
CHANGED
@@ -6,6 +6,7 @@ module Html2Doc
|
|
6
6
|
fn = []
|
7
7
|
docxml.xpath("//a").each do |a|
|
8
8
|
next unless process_footnote_link(docxml, a, i, fn)
|
9
|
+
|
9
10
|
i += 1
|
10
11
|
end
|
11
12
|
process_footnote_texts(docxml, fn)
|
@@ -22,13 +23,13 @@ module Html2Doc
|
|
22
23
|
footnote_cleanup(docxml)
|
23
24
|
end
|
24
25
|
|
25
|
-
def self.footnote_div_to_p(
|
26
|
-
if %w{div aside}.include?
|
27
|
-
if
|
28
|
-
|
26
|
+
def self.footnote_div_to_p(elem)
|
27
|
+
if %w{div aside}.include? elem.name
|
28
|
+
if elem.at(".//p")
|
29
|
+
elem.replace(elem.children)
|
29
30
|
else
|
30
|
-
|
31
|
-
|
31
|
+
elem.name = "p"
|
32
|
+
elem["class"] = "MsoFootnoteText"
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -36,34 +37,36 @@ module Html2Doc
|
|
36
37
|
FN = "<span class='MsoFootnoteReference'>"\
|
37
38
|
"<span style='mso-special-character:footnote'/></span>".freeze
|
38
39
|
|
39
|
-
def self.footnote_container(docxml,
|
40
|
-
ref = docxml&.at("//a[@href='#_ftn#{
|
41
|
-
gsub(/>\n</, "><") || FN
|
40
|
+
def self.footnote_container(docxml, idx)
|
41
|
+
ref = docxml&.at("//a[@href='#_ftn#{idx}']")&.children&.to_xml(indent: 0)
|
42
|
+
&.gsub(/>\n</, "><") || FN
|
42
43
|
<<~DIV
|
43
|
-
<div style='mso-element:footnote' id='ftn#{
|
44
|
-
<a style='mso-footnote-id:ftn#{
|
45
|
-
name='_ftnref#{
|
44
|
+
<div style='mso-element:footnote' id='ftn#{idx}'>
|
45
|
+
<a style='mso-footnote-id:ftn#{idx}' href='#_ftn#{idx}'
|
46
|
+
name='_ftnref#{idx}' title='' id='_ftnref#{idx}'>#{ref.strip}</a></div>
|
46
47
|
DIV
|
47
48
|
end
|
48
49
|
|
49
|
-
def self.process_footnote_link(docxml,
|
50
|
-
return false unless footnote?(
|
51
|
-
|
50
|
+
def self.process_footnote_link(docxml, elem, idx, footnote)
|
51
|
+
return false unless footnote?(elem)
|
52
|
+
|
53
|
+
href = elem["href"].gsub(/^#/, "")
|
52
54
|
note = docxml.at("//*[@name = '#{href}' or @id = '#{href}']")
|
53
55
|
return false if note.nil?
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
56
|
+
|
57
|
+
set_footnote_link_attrs(elem, idx)
|
58
|
+
if elem.at("./span[@class = 'MsoFootnoteReference']")
|
59
|
+
elem.children.each do |c|
|
60
|
+
if c.name == "span" && c["class"] == "MsoFootnoteReference"
|
58
61
|
c.replace(FN)
|
59
62
|
else
|
60
63
|
c.wrap("<span class='MsoFootnoteReference'></span>")
|
61
64
|
end
|
62
65
|
end
|
63
66
|
else
|
64
|
-
|
67
|
+
elem.children = FN
|
65
68
|
end
|
66
|
-
|
69
|
+
footnote << transform_footnote_text(note)
|
67
70
|
end
|
68
71
|
|
69
72
|
def self.transform_footnote_text(note)
|
@@ -76,16 +79,16 @@ module Html2Doc
|
|
76
79
|
note.remove
|
77
80
|
end
|
78
81
|
|
79
|
-
def self.footnote?(
|
80
|
-
|
81
|
-
|
82
|
+
def self.footnote?(elem)
|
83
|
+
elem["epub:type"]&.casecmp("footnote")&.zero? ||
|
84
|
+
elem["class"]&.casecmp("footnote")&.zero?
|
82
85
|
end
|
83
86
|
|
84
|
-
def self.set_footnote_link_attrs(
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
87
|
+
def self.set_footnote_link_attrs(elem, idx)
|
88
|
+
elem["style"] = "mso-footnote-id:ftn#{idx}"
|
89
|
+
elem["href"] = "#_ftn#{idx}"
|
90
|
+
elem["name"] = "_ftnref#{idx}"
|
91
|
+
elem["title"] = ""
|
89
92
|
end
|
90
93
|
|
91
94
|
# We expect that the content of the footnote text received is one or
|
@@ -94,8 +97,8 @@ module Html2Doc
|
|
94
97
|
# are present in the HTML, they need to have been cleaned out before
|
95
98
|
# passing to this gem
|
96
99
|
def self.footnote_cleanup(docxml)
|
97
|
-
docxml.xpath('//div[@style="mso-element:footnote"]/a')
|
98
|
-
each do |x|
|
100
|
+
docxml.xpath('//div[@style="mso-element:footnote"]/a')
|
101
|
+
.each do |x|
|
99
102
|
n = x.next_element
|
100
103
|
n&.children&.first&.add_previous_sibling(x.remove)
|
101
104
|
end
|
data/lib/html2doc/version.rb
CHANGED
data/spec/html2doc_spec.rb
CHANGED
@@ -1,275 +1,276 @@
|
|
1
1
|
require "base64"
|
2
2
|
|
3
|
-
def html_input(
|
3
|
+
def html_input(xml)
|
4
4
|
<<~HTML
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
<html><head><title>blank</title>
|
6
|
+
<meta name="Originator" content="Me"/>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
#{xml}
|
10
|
+
</body></html>
|
11
11
|
HTML
|
12
12
|
end
|
13
13
|
|
14
|
-
def html_input_no_title(
|
14
|
+
def html_input_no_title(xml)
|
15
15
|
<<~HTML
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
<html><head>
|
17
|
+
<meta name="Originator" content="Me"/>
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
#{xml}
|
21
|
+
</body></html>
|
22
22
|
HTML
|
23
23
|
end
|
24
24
|
|
25
|
-
def html_input_empty_head(
|
25
|
+
def html_input_empty_head(xml)
|
26
26
|
<<~HTML
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
<html><head></head>
|
28
|
+
<body>
|
29
|
+
#{xml}
|
30
|
+
</body></html>
|
31
31
|
HTML
|
32
32
|
end
|
33
33
|
|
34
|
-
WORD_HDR = <<~HDR
|
35
|
-
MIME-Version: 1.0
|
36
|
-
Content-Type: multipart/related; boundary="----=_NextPart_"
|
37
|
-
|
38
|
-
------=_NextPart_
|
39
|
-
Content-ID: <test.htm>
|
40
|
-
Content-Disposition: inline; filename="test.htm"
|
41
|
-
Content-Type: text/html; charset="utf-8"
|
42
|
-
|
43
|
-
<?xml version="1.0"?>
|
44
|
-
<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]>
|
45
|
-
<xml>
|
46
|
-
<w:WordDocument>
|
47
|
-
<w:View>Print</w:View>
|
48
|
-
<w:Zoom>100</w:Zoom>
|
49
|
-
<w:DoNotOptimizeForBrowser/>
|
50
|
-
</w:WordDocument>
|
51
|
-
</xml>
|
52
|
-
<![endif]-->
|
53
|
-
<meta http-equiv=Content-Type content="text/html; charset=utf-8"/>
|
54
|
-
|
55
|
-
|
56
|
-
<title>blank</title><style><![CDATA[
|
57
|
-
|
34
|
+
WORD_HDR = <<~HDR.freeze
|
35
|
+
MIME-Version: 1.0
|
36
|
+
Content-Type: multipart/related; boundary="----=_NextPart_"
|
37
|
+
|
38
|
+
------=_NextPart_
|
39
|
+
Content-ID: <test.htm>
|
40
|
+
Content-Disposition: inline; filename="test.htm"
|
41
|
+
Content-Type: text/html; charset="utf-8"
|
42
|
+
|
43
|
+
<?xml version="1.0"?>
|
44
|
+
<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]>
|
45
|
+
<xml>
|
46
|
+
<w:WordDocument>
|
47
|
+
<w:View>Print</w:View>
|
48
|
+
<w:Zoom>100</w:Zoom>
|
49
|
+
<w:DoNotOptimizeForBrowser/>
|
50
|
+
</w:WordDocument>
|
51
|
+
</xml>
|
52
|
+
<![endif]-->
|
53
|
+
<meta http-equiv=Content-Type content="text/html; charset=utf-8"/>
|
54
|
+
|
55
|
+
<link rel=File-List href="cid:filelist.xml"/>
|
56
|
+
<title>blank</title><style><![CDATA[
|
57
|
+
<!--
|
58
58
|
HDR
|
59
59
|
|
60
|
-
WORD_HDR_END = <<~HDR
|
61
|
-
-->
|
62
|
-
]]></style>
|
63
|
-
<meta name="Originator" content="Me"/>
|
64
|
-
</head>
|
60
|
+
WORD_HDR_END = <<~HDR.freeze
|
61
|
+
-->
|
62
|
+
]]></style>
|
63
|
+
<meta name="Originator" content="Me"/>
|
64
|
+
</head>
|
65
65
|
HDR
|
66
66
|
|
67
67
|
def word_body(x, fn)
|
68
68
|
<<~BODY
|
69
|
-
<body>
|
70
|
-
|
71
|
-
|
69
|
+
<body>
|
70
|
+
#{x}
|
71
|
+
#{fn}</body></html>
|
72
72
|
BODY
|
73
73
|
end
|
74
74
|
|
75
|
-
WORD_FTR1 = <<~FTR
|
75
|
+
WORD_FTR1 = <<~FTR.freeze
|
76
76
|
------=_NextPart_
|
77
|
-
Content-ID: <filelist.xml>
|
78
|
-
Content-Disposition: inline; filename="filelist.xml"
|
79
|
-
Content-Transfer-Encoding: base64
|
80
|
-
Content-Type: #{Html2Doc::mime_type('filelist.xml')}
|
77
|
+
Content-ID: <filelist.xml>
|
78
|
+
Content-Disposition: inline; filename="filelist.xml"
|
79
|
+
Content-Transfer-Encoding: base64
|
80
|
+
Content-Type: #{Html2Doc::mime_type('filelist.xml')}
|
81
81
|
|
82
|
-
PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
|
83
|
-
ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9ImZp
|
84
|
-
bGVsaXN0LnhtbCIvPgo8L3htbD4K
|
82
|
+
PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
|
83
|
+
ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9ImZp
|
84
|
+
bGVsaXN0LnhtbCIvPgo8L3htbD4K
|
85
85
|
|
86
|
-
------=_NextPart_--
|
86
|
+
------=_NextPart_--
|
87
87
|
FTR
|
88
88
|
|
89
|
-
WORD_FTR2 = <<~FTR
|
89
|
+
WORD_FTR2 = <<~FTR.freeze
|
90
|
+
------=_NextPart_
|
91
|
+
Content-ID: <filelist.xml>
|
92
|
+
Content-Disposition: inline; filename="filelist.xml"
|
93
|
+
Content-Transfer-Encoding: base64
|
94
|
+
Content-Type: #{Html2Doc::mime_type('filelist.xml')}
|
95
|
+
PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
|
96
|
+
ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9ImZp
|
97
|
+
bGVsaXN0LnhtbCIvPgogIDxvOkZpbGUgSFJlZj0iaGVhZGVyLmh0bWwiLz4KPC94bWw+Cg==
|
90
98
|
------=_NextPart_
|
91
|
-
Content-ID: <filelist.xml>
|
92
|
-
Content-Disposition: inline; filename="filelist.xml"
|
93
|
-
Content-Transfer-Encoding: base64
|
94
|
-
Content-Type: #{Html2Doc::mime_type('filelist.xml')}
|
95
|
-
PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
|
96
|
-
ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9ImZp
|
97
|
-
bGVsaXN0LnhtbCIvPgogIDxvOkZpbGUgSFJlZj0iaGVhZGVyLmh0bWwiLz4KPC94bWw+Cg==
|
98
|
-
------=_NextPart_
|
99
99
|
FTR
|
100
100
|
|
101
|
-
WORD_FTR3 = <<~FTR
|
102
|
-
------=_NextPart_
|
103
|
-
Content-ID: <filelist.xml>
|
104
|
-
Content-Disposition: inline; filename="filelist.xml"
|
105
|
-
Content-Transfer-Encoding: base64
|
106
|
-
Content-Type: #{Html2Doc::mime_type('filelist.xml')}
|
107
|
-
|
108
|
-
PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
|
109
|
-
ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9IjFh
|
110
|
-
YzIwNjVmLTAzZjAtNGM3YS1iOWE2LTkyZTgyMDU5MWJmMC5wbmciLz4KICA8bzpGaWxlIEhSZWY9
|
111
|
-
ImZpbGVsaXN0LnhtbCIvPgo8L3htbD4K
|
112
|
-
------=_NextPart_
|
113
|
-
Content-ID: <cb7b0d19-891e-4634-815a-570d019d454c.png>
|
114
|
-
Content-Disposition: inline; filename="cb7b0d19-891e-4634-815a-570d019d454c.png"
|
115
|
-
Content-Transfer-Encoding: base64
|
116
|
-
Content-Type: image/png
|
117
|
-
------=_NextPart_--
|
101
|
+
WORD_FTR3 = <<~FTR.freeze
|
102
|
+
------=_NextPart_
|
103
|
+
Content-ID: <filelist.xml>
|
104
|
+
Content-Disposition: inline; filename="filelist.xml"
|
105
|
+
Content-Transfer-Encoding: base64
|
106
|
+
Content-Type: #{Html2Doc::mime_type('filelist.xml')}
|
107
|
+
|
108
|
+
PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
|
109
|
+
ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9IjFh
|
110
|
+
YzIwNjVmLTAzZjAtNGM3YS1iOWE2LTkyZTgyMDU5MWJmMC5wbmciLz4KICA8bzpGaWxlIEhSZWY9
|
111
|
+
ImZpbGVsaXN0LnhtbCIvPgo8L3htbD4K
|
112
|
+
------=_NextPart_
|
113
|
+
Content-ID: <cb7b0d19-891e-4634-815a-570d019d454c.png>
|
114
|
+
Content-Disposition: inline; filename="cb7b0d19-891e-4634-815a-570d019d454c.png"
|
115
|
+
Content-Transfer-Encoding: base64
|
116
|
+
Content-Type: image/png
|
117
|
+
------=_NextPart_--
|
118
118
|
FTR
|
119
119
|
|
120
|
-
HEADERHTML
|
121
|
-
<html xmlns:v="urn:schemas-microsoft-com:vml"
|
122
|
-
xmlns:o="urn:schemas-microsoft-com:office:office"
|
123
|
-
xmlns:w="urn:schemas-microsoft-com:office:word"
|
124
|
-
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
|
125
|
-
xmlns:mv="http://macVmlSchemaUri" xmlns="http://www.w3.org/TR/REC-html40">
|
126
|
-
<head>
|
127
|
-
<meta name=Title content="">
|
128
|
-
<meta name=Keywords content="">
|
129
|
-
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
|
130
|
-
<meta name=ProgId content=Word.Document>
|
131
|
-
<meta name=Generator content="Microsoft Word 15">
|
132
|
-
<meta name=Originator content="Microsoft Word 15">
|
133
|
-
<link id=Main-File rel=Main-File href="FILENAME.html">
|
134
|
-
<!--[if gte mso 9]><xml>
|
135
|
-
<o:shapedefaults v:ext="edit" spidmax="2049"/>
|
136
|
-
</xml><![endif]-->
|
137
|
-
</head>
|
138
|
-
<body lang=EN link=blue vlink="#954F72">
|
139
|
-
<div style='mso-element:footnote-separator' id=fs>
|
140
|
-
<p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
|
141
|
-
normal'><span lang=EN-GB><span style='mso-special-character:footnote-separator'><![if !supportFootnotes]>
|
142
|
-
<hr align=left size=1 width="33%">
|
143
|
-
<![endif]></span></span></p>
|
144
|
-
</div>
|
145
|
-
<div style='mso-element:footnote-continuation-separator' id=fcs>
|
146
|
-
<p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
|
147
|
-
normal'><span lang=EN-GB><span style='mso-special-character:footnote-continuation-separator'><![if !supportFootnotes]>
|
148
|
-
<hr align=left size=1>
|
149
|
-
<![endif]></span></span></p>
|
150
|
-
</div>
|
151
|
-
<div style='mso-element:endnote-separator' id=es>
|
152
|
-
<p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
|
153
|
-
normal'><span lang=EN-GB><span style='mso-special-character:footnote-separator'><![if !supportFootnotes]>
|
154
|
-
<hr align=left size=1 width="33%">
|
155
|
-
<![endif]></span></span></p>
|
156
|
-
</div>
|
157
|
-
<div style='mso-element:endnote-continuation-separator' id=ecs>
|
158
|
-
<p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
|
159
|
-
normal'><span lang=EN-GB><span style='mso-special-character:footnote-continuation-separator'><![if !supportFootnotes]>
|
160
|
-
<hr align=left size=1>
|
161
|
-
<![endif]></span></span></p>
|
162
|
-
</div>
|
163
|
-
<div style='mso-element:header' id=eh1>
|
164
|
-
<p class=MsoHeader align=left style='text-align:left;line-height:12.0pt;
|
165
|
-
mso-line-height-rule:exactly'><span lang=EN-GB>ISO/IEC&nbsp;CD 17301-1:2016(E)</span></p>
|
166
|
-
</div>
|
167
|
-
<div style='mso-element:header' id=h1>
|
168
|
-
<p class=MsoHeader style='margin-bottom:18.0pt'><span lang=EN-GB
|
169
|
-
style='font-size:10.0pt;mso-bidi-font-size:11.0pt;font-weight:normal'>©
|
170
|
-
ISO/IEC&nbsp;2016&nbsp;– All rights reserved</span><span lang=EN-GB
|
171
|
-
style='font-weight:normal'><o:p></o:p></span></p>
|
172
|
-
</div>
|
173
|
-
<div style='mso-element:footer' id=ef1>
|
174
|
-
<p class=MsoFooter style='margin-top:12.0pt;line-height:12.0pt;mso-line-height-rule:
|
175
|
-
exactly'><!--[if supportFields]><b style='mso-bidi-font-weight:normal'><span
|
176
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
177
|
-
style='mso-element:field-begin'></span><span
|
178
|
-
style='mso-spacerun:yes'> </span>PAGE<span style='mso-spacerun:yes'>  
|
179
|
-
</span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span></b><![endif]--><b
|
180
|
-
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
181
|
-
mso-bidi-font-size:11.0pt'><span style='mso-no-proof:yes'>2</span></span></b><!--[if supportFields]><b
|
182
|
-
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
183
|
-
mso-bidi-font-size:11.0pt'><span style='mso-element:field-end'></span></span></b><![endif]--><span
|
184
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
185
|
-
style='mso-tab-count:1'>                                                                                                                                                                           </span>©
|
186
|
-
ISO/IEC&nbsp;2016&nbsp;– All rights reserved<o:p></o:p></span></p>
|
187
|
-
</div>
|
188
|
-
<div style='mso-element:header' id=eh2>
|
189
|
-
<p class=MsoHeader align=left style='text-align:left;line-height:12.0pt;
|
190
|
-
mso-line-height-rule:exactly'><span lang=EN-GB>ISO/IEC&nbsp;CD 17301-1:2016(E)</span></p>
|
191
|
-
</div>
|
192
|
-
<div style='mso-element:header' id=h2>
|
193
|
-
<p class=MsoHeader align=right style='text-align:right;line-height:12.0pt;
|
194
|
-
mso-line-height-rule:exactly'><span lang=EN-GB>ISO/IEC&nbsp;CD 17301-1:2016(E)</span></p>
|
195
|
-
</div>
|
196
|
-
<div style='mso-element:footer' id=ef2>
|
197
|
-
<p class=MsoFooter style='line-height:12.0pt;mso-line-height-rule:exactly'><!--[if supportFields]><span
|
198
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
199
|
-
style='mso-element:field-begin'></span><span
|
200
|
-
style='mso-spacerun:yes'> </span>PAGE<span style='mso-spacerun:yes'>  
|
201
|
-
</span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span><![endif]--><span
|
202
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
203
|
-
style='mso-no-proof:yes'>ii</span></span><!--[if supportFields]><span
|
204
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
205
|
-
style='mso-element:field-end'></span></span><![endif]--><span lang=EN-GB
|
206
|
-
style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span style='mso-tab-count:
|
207
|
-
1'>                                                                                                                                                                           </span>©
|
208
|
-
ISO/IEC&nbsp;2016&nbsp;– All rights reserved<o:p></o:p></span></p>
|
209
|
-
</div>
|
210
|
-
<div style='mso-element:footer' id=f2>
|
211
|
-
<p class=MsoFooter style='line-height:12.0pt'><span lang=EN-GB
|
212
|
-
style='font-size:10.0pt;mso-bidi-font-size:11.0pt'>© ISO/IEC&nbsp;2016&nbsp;– All
|
213
|
-
rights reserved<span style='mso-tab-count:1'>                                                                                                                                                                          </span></span><!--[if supportFields]><span
|
214
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
215
|
-
style='mso-element:field-begin'></span> PAGE<span style='mso-spacerun:yes'>  
|
216
|
-
</span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span><![endif]--><span
|
217
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
218
|
-
style='mso-no-proof:yes'>iii</span></span><!--[if supportFields]><span
|
219
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
220
|
-
style='mso-element:field-end'></span></span><![endif]--><span lang=EN-GB
|
221
|
-
style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><o:p></o:p></span></p>
|
222
|
-
</div>
|
223
|
-
<div style='mso-element:footer' id=ef3>
|
224
|
-
<p class=MsoFooter style='margin-top:12.0pt;line-height:12.0pt;mso-line-height-rule:
|
225
|
-
exactly'><!--[if supportFields]><b style='mso-bidi-font-weight:normal'><span
|
226
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
227
|
-
style='mso-element:field-begin'></span><span
|
228
|
-
style='mso-spacerun:yes'> </span>PAGE<span style='mso-spacerun:yes'>  
|
229
|
-
</span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span></b><![endif]--><b
|
230
|
-
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
231
|
-
mso-bidi-font-size:11.0pt'><span style='mso-no-proof:yes'>2</span></span></b><!--[if supportFields]><b
|
232
|
-
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
233
|
-
mso-bidi-font-size:11.0pt'><span style='mso-element:field-end'></span></span></b><![endif]--><span
|
234
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
235
|
-
style='mso-tab-count:1'>                                                                                                                                                                           </span>©
|
236
|
-
ISO/IEC&nbsp;2016&nbsp;– All rights reserved<o:p></o:p></span></p>
|
237
|
-
</div>
|
238
|
-
<div style='mso-element:footer' id=f3>
|
239
|
-
<p class=MsoFooter style='line-height:12.0pt'><span lang=EN-GB
|
240
|
-
style='font-size:10.0pt;mso-bidi-font-size:11.0pt'>© ISO/IEC&nbsp;2016&nbsp;– All
|
241
|
-
rights reserved<span style='mso-tab-count:1'>                                                                                                                                                                           </span></span><!--[if supportFields]><b
|
242
|
-
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
243
|
-
mso-bidi-font-size:11.0pt'><span style='mso-element:field-begin'></span>
|
244
|
-
PAGE<span style='mso-spacerun:yes'>   </span>\\* MERGEFORMAT <span
|
245
|
-
style='mso-element:field-separator'></span></span></b><![endif]--><b
|
246
|
-
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
247
|
-
mso-bidi-font-size:11.0pt'><span style='mso-no-proof:yes'>3</span></span></b><!--[if supportFields]><b
|
248
|
-
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
249
|
-
mso-bidi-font-size:11.0pt'><span style='mso-element:field-end'></span></span></b><![endif]--><span
|
250
|
-
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><o:p></o:p></span></p>
|
251
|
-
</div>
|
252
|
-
</body>
|
253
|
-
</html>
|
120
|
+
HEADERHTML = <<~FTR.freeze
|
121
|
+
<html xmlns:v="urn:schemas-microsoft-com:vml"
|
122
|
+
xmlns:o="urn:schemas-microsoft-com:office:office"
|
123
|
+
xmlns:w="urn:schemas-microsoft-com:office:word"
|
124
|
+
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
|
125
|
+
xmlns:mv="http://macVmlSchemaUri" xmlns="http://www.w3.org/TR/REC-html40">
|
126
|
+
<head>
|
127
|
+
<meta name=Title content="">
|
128
|
+
<meta name=Keywords content="">
|
129
|
+
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
|
130
|
+
<meta name=ProgId content=Word.Document>
|
131
|
+
<meta name=Generator content="Microsoft Word 15">
|
132
|
+
<meta name=Originator content="Microsoft Word 15">
|
133
|
+
<link id=Main-File rel=Main-File href="FILENAME.html">
|
134
|
+
<!--[if gte mso 9]><xml>
|
135
|
+
<o:shapedefaults v:ext="edit" spidmax="2049"/>
|
136
|
+
</xml><![endif]-->
|
137
|
+
</head>
|
138
|
+
<body lang=EN link=blue vlink="#954F72">
|
139
|
+
<div style='mso-element:footnote-separator' id=fs>
|
140
|
+
<p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
|
141
|
+
normal'><span lang=EN-GB><span style='mso-special-character:footnote-separator'><![if !supportFootnotes]>
|
142
|
+
<hr align=left size=1 width="33%">
|
143
|
+
<![endif]></span></span></p>
|
144
|
+
</div>
|
145
|
+
<div style='mso-element:footnote-continuation-separator' id=fcs>
|
146
|
+
<p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
|
147
|
+
normal'><span lang=EN-GB><span style='mso-special-character:footnote-continuation-separator'><![if !supportFootnotes]>
|
148
|
+
<hr align=left size=1>
|
149
|
+
<![endif]></span></span></p>
|
150
|
+
</div>
|
151
|
+
<div style='mso-element:endnote-separator' id=es>
|
152
|
+
<p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
|
153
|
+
normal'><span lang=EN-GB><span style='mso-special-character:footnote-separator'><![if !supportFootnotes]>
|
154
|
+
<hr align=left size=1 width="33%">
|
155
|
+
<![endif]></span></span></p>
|
156
|
+
</div>
|
157
|
+
<div style='mso-element:endnote-continuation-separator' id=ecs>
|
158
|
+
<p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
|
159
|
+
normal'><span lang=EN-GB><span style='mso-special-character:footnote-continuation-separator'><![if !supportFootnotes]>
|
160
|
+
<hr align=left size=1>
|
161
|
+
<![endif]></span></span></p>
|
162
|
+
</div>
|
163
|
+
<div style='mso-element:header' id=eh1>
|
164
|
+
<p class=MsoHeader align=left style='text-align:left;line-height:12.0pt;
|
165
|
+
mso-line-height-rule:exactly'><span lang=EN-GB>ISO/IEC&nbsp;CD 17301-1:2016(E)</span></p>
|
166
|
+
</div>
|
167
|
+
<div style='mso-element:header' id=h1>
|
168
|
+
<p class=MsoHeader style='margin-bottom:18.0pt'><span lang=EN-GB
|
169
|
+
style='font-size:10.0pt;mso-bidi-font-size:11.0pt;font-weight:normal'>©
|
170
|
+
ISO/IEC&nbsp;2016&nbsp;– All rights reserved</span><span lang=EN-GB
|
171
|
+
style='font-weight:normal'><o:p></o:p></span></p>
|
172
|
+
</div>
|
173
|
+
<div style='mso-element:footer' id=ef1>
|
174
|
+
<p class=MsoFooter style='margin-top:12.0pt;line-height:12.0pt;mso-line-height-rule:
|
175
|
+
exactly'><!--[if supportFields]><b style='mso-bidi-font-weight:normal'><span
|
176
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
177
|
+
style='mso-element:field-begin'></span><span
|
178
|
+
style='mso-spacerun:yes'> </span>PAGE<span style='mso-spacerun:yes'>  
|
179
|
+
</span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span></b><![endif]--><b
|
180
|
+
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
181
|
+
mso-bidi-font-size:11.0pt'><span style='mso-no-proof:yes'>2</span></span></b><!--[if supportFields]><b
|
182
|
+
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
183
|
+
mso-bidi-font-size:11.0pt'><span style='mso-element:field-end'></span></span></b><![endif]--><span
|
184
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
185
|
+
style='mso-tab-count:1'>                                                                                                                                                                           </span>©
|
186
|
+
ISO/IEC&nbsp;2016&nbsp;– All rights reserved<o:p></o:p></span></p>
|
187
|
+
</div>
|
188
|
+
<div style='mso-element:header' id=eh2>
|
189
|
+
<p class=MsoHeader align=left style='text-align:left;line-height:12.0pt;
|
190
|
+
mso-line-height-rule:exactly'><span lang=EN-GB>ISO/IEC&nbsp;CD 17301-1:2016(E)</span></p>
|
191
|
+
</div>
|
192
|
+
<div style='mso-element:header' id=h2>
|
193
|
+
<p class=MsoHeader align=right style='text-align:right;line-height:12.0pt;
|
194
|
+
mso-line-height-rule:exactly'><span lang=EN-GB>ISO/IEC&nbsp;CD 17301-1:2016(E)</span></p>
|
195
|
+
</div>
|
196
|
+
<div style='mso-element:footer' id=ef2>
|
197
|
+
<p class=MsoFooter style='line-height:12.0pt;mso-line-height-rule:exactly'><!--[if supportFields]><span
|
198
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
199
|
+
style='mso-element:field-begin'></span><span
|
200
|
+
style='mso-spacerun:yes'> </span>PAGE<span style='mso-spacerun:yes'>  
|
201
|
+
</span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span><![endif]--><span
|
202
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
203
|
+
style='mso-no-proof:yes'>ii</span></span><!--[if supportFields]><span
|
204
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
205
|
+
style='mso-element:field-end'></span></span><![endif]--><span lang=EN-GB
|
206
|
+
style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span style='mso-tab-count:
|
207
|
+
1'>                                                                                                                                                                           </span>©
|
208
|
+
ISO/IEC&nbsp;2016&nbsp;– All rights reserved<o:p></o:p></span></p>
|
209
|
+
</div>
|
210
|
+
<div style='mso-element:footer' id=f2>
|
211
|
+
<p class=MsoFooter style='line-height:12.0pt'><span lang=EN-GB
|
212
|
+
style='font-size:10.0pt;mso-bidi-font-size:11.0pt'>© ISO/IEC&nbsp;2016&nbsp;– All
|
213
|
+
rights reserved<span style='mso-tab-count:1'>                                                                                                                                                                          </span></span><!--[if supportFields]><span
|
214
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
215
|
+
style='mso-element:field-begin'></span> PAGE<span style='mso-spacerun:yes'>  
|
216
|
+
</span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span><![endif]--><span
|
217
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
218
|
+
style='mso-no-proof:yes'>iii</span></span><!--[if supportFields]><span
|
219
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
220
|
+
style='mso-element:field-end'></span></span><![endif]--><span lang=EN-GB
|
221
|
+
style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><o:p></o:p></span></p>
|
222
|
+
</div>
|
223
|
+
<div style='mso-element:footer' id=ef3>
|
224
|
+
<p class=MsoFooter style='margin-top:12.0pt;line-height:12.0pt;mso-line-height-rule:
|
225
|
+
exactly'><!--[if supportFields]><b style='mso-bidi-font-weight:normal'><span
|
226
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
227
|
+
style='mso-element:field-begin'></span><span
|
228
|
+
style='mso-spacerun:yes'> </span>PAGE<span style='mso-spacerun:yes'>  
|
229
|
+
</span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span></b><![endif]--><b
|
230
|
+
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
231
|
+
mso-bidi-font-size:11.0pt'><span style='mso-no-proof:yes'>2</span></span></b><!--[if supportFields]><b
|
232
|
+
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
233
|
+
mso-bidi-font-size:11.0pt'><span style='mso-element:field-end'></span></span></b><![endif]--><span
|
234
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
|
235
|
+
style='mso-tab-count:1'>                                                                                                                                                                           </span>©
|
236
|
+
ISO/IEC&nbsp;2016&nbsp;– All rights reserved<o:p></o:p></span></p>
|
237
|
+
</div>
|
238
|
+
<div style='mso-element:footer' id=f3>
|
239
|
+
<p class=MsoFooter style='line-height:12.0pt'><span lang=EN-GB
|
240
|
+
style='font-size:10.0pt;mso-bidi-font-size:11.0pt'>© ISO/IEC&nbsp;2016&nbsp;– All
|
241
|
+
rights reserved<span style='mso-tab-count:1'>                                                                                                                                                                           </span></span><!--[if supportFields]><b
|
242
|
+
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
243
|
+
mso-bidi-font-size:11.0pt'><span style='mso-element:field-begin'></span>
|
244
|
+
PAGE<span style='mso-spacerun:yes'>   </span>\\* MERGEFORMAT <span
|
245
|
+
style='mso-element:field-separator'></span></span></b><![endif]--><b
|
246
|
+
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
247
|
+
mso-bidi-font-size:11.0pt'><span style='mso-no-proof:yes'>3</span></span></b><!--[if supportFields]><b
|
248
|
+
style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
|
249
|
+
mso-bidi-font-size:11.0pt'><span style='mso-element:field-end'></span></span></b><![endif]--><span
|
250
|
+
lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><o:p></o:p></span></p>
|
251
|
+
</div>
|
252
|
+
</body>
|
253
|
+
</html>
|
254
254
|
FTR
|
255
255
|
|
256
|
-
ASCII_MATH='<m:nary><m:naryPr><m:chr m:val="∑"></m:chr><m:limLoc m:val="undOvr"></m:limLoc><m:grow m:val="on"></m:grow><m:subHide m:val="off"></m:subHide><m:supHide m:val="off"></m:supHide></m:naryPr><m:sub><m:r><m:t>i=1</m:t></m:r></m:sub><m:sup><m:r><m:t>n</m:t></m:r></m:sup><m:e><m:sSup><m:e><m:r><m:t>i</m:t></m:r></m:e><m:sup><m:r><m:t>3</m:t></m:r></m:sup></m:sSup></m:e></m:nary><m:r><m:t>=</m:t></m:r><m:sSup><m:e><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:f><m:fPr><m:type m:val="bar"></m:type></m:fPr><m:num><m:r><m:t>n</m:t></m:r><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:r><m:t>n+1</m:t></m:r></m:e></m:d></m:num><m:den><m:r><m:t>2</m:t></m:r></m:den></m:f></m:e></m:d></m:e><m:sup><m:r><m:t>2</m:t></m:r></m:sup></m:sSup>'
|
256
|
+
ASCII_MATH = '<m:nary><m:naryPr><m:chr m:val="∑"></m:chr><m:limLoc m:val="undOvr"></m:limLoc><m:grow m:val="on"></m:grow><m:subHide m:val="off"></m:subHide><m:supHide m:val="off"></m:supHide></m:naryPr><m:sub><m:r><m:t>i=1</m:t></m:r></m:sub><m:sup><m:r><m:t>n</m:t></m:r></m:sup><m:e><m:sSup><m:e><m:r><m:t>i</m:t></m:r></m:e><m:sup><m:r><m:t>3</m:t></m:r></m:sup></m:sSup></m:e></m:nary><m:r><m:t>=</m:t></m:r><m:sSup><m:e><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:f><m:fPr><m:type m:val="bar"></m:type></m:fPr><m:num><m:r><m:t>n</m:t></m:r><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:r><m:t>n+1</m:t></m:r></m:e></m:d></m:num><m:den><m:r><m:t>2</m:t></m:r></m:den></m:f></m:e></m:d></m:e><m:sup><m:r><m:t>2</m:t></m:r></m:sup></m:sSup>'.freeze
|
257
257
|
|
258
|
-
DEFAULT_STYLESHEET = File.read("lib/html2doc/wordstyle.css",
|
258
|
+
DEFAULT_STYLESHEET = File.read("lib/html2doc/wordstyle.css",
|
259
|
+
encoding: "utf-8").freeze
|
259
260
|
|
260
|
-
def guid_clean(
|
261
|
-
|
261
|
+
def guid_clean(xml)
|
262
|
+
xml.gsub(/NextPart_[0-9a-f.]+/, "NextPart_")
|
262
263
|
end
|
263
264
|
|
264
|
-
def image_clean(
|
265
|
-
|
266
|
-
gsub(%r{[0-9a-f-]+\.gif}, "image.gif")
|
267
|
-
gsub(%r{[0-9a-f-]+\.(jpeg|jpg)}, "image.jpg")
|
268
|
-
gsub(%r{------=_NextPart_\s+Content-Location: file:///C:/Doc/test_files/image\.(png|gif).*?\s-----=_NextPart_}m, "------=_NextPart_")
|
269
|
-
gsub(%r{Content-Type: image/(png|gif|jpeg)[^-]*------=_NextPart_-?-?}m, "")
|
270
|
-
gsub(%r{ICAgICAg[^-]*-----}m, "-----")
|
271
|
-
gsub(%r{\s*</img>\s*}m, "</img>")
|
272
|
-
gsub(%r{</body>\s*</html>}m, "</body></html>")
|
265
|
+
def image_clean(xml)
|
266
|
+
xml.gsub(%r{[0-9a-f-]+\.png}, "image.png")
|
267
|
+
.gsub(%r{[0-9a-f-]+\.gif}, "image.gif")
|
268
|
+
.gsub(%r{[0-9a-f-]+\.(jpeg|jpg)}, "image.jpg")
|
269
|
+
.gsub(%r{------=_NextPart_\s+Content-Location: file:///C:/Doc/test_files/image\.(png|gif).*?\s-----=_NextPart_}m, "------=_NextPart_")
|
270
|
+
.gsub(%r{Content-Type: image/(png|gif|jpeg)[^-]*------=_NextPart_-?-?}m, "")
|
271
|
+
.gsub(%r{ICAgICAg[^-]*-----}m, "-----")
|
272
|
+
.gsub(%r{\s*</img>\s*}m, "</img>")
|
273
|
+
.gsub(%r{</body>\s*</html>}m, "</body></html>")
|
273
274
|
end
|
274
275
|
|
275
276
|
RSpec.describe Html2Doc do
|
@@ -279,11 +280,11 @@ RSpec.describe Html2Doc do
|
|
279
280
|
|
280
281
|
it "processes a blank document" do
|
281
282
|
Html2Doc.process(html_input(""), filename: "test")
|
282
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
283
|
-
to match_fuzzy(<<~OUTPUT)
|
284
|
-
|
285
|
-
|
286
|
-
|
283
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
284
|
+
.to match_fuzzy(<<~OUTPUT)
|
285
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
286
|
+
#{word_body('', '<div style="mso-element:footnote-list"/>')} #{WORD_FTR1}
|
287
|
+
OUTPUT
|
287
288
|
end
|
288
289
|
|
289
290
|
it "removes any temp files" do
|
@@ -295,50 +296,52 @@ RSpec.describe Html2Doc do
|
|
295
296
|
end
|
296
297
|
|
297
298
|
it "processes a stylesheet in an HTML document with a title" do
|
298
|
-
Html2Doc.process(html_input(""),
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
299
|
+
Html2Doc.process(html_input(""),
|
300
|
+
filename: "test", stylesheet: "lib/html2doc/wordstyle.css")
|
301
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
302
|
+
.to match_fuzzy(<<~OUTPUT)
|
303
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
304
|
+
#{word_body('', '<div style="mso-element:footnote-list"/>')} #{WORD_FTR1}
|
305
|
+
OUTPUT
|
304
306
|
end
|
305
307
|
|
306
308
|
it "processes a stylesheet in an HTML document without a title" do
|
307
|
-
Html2Doc.process(html_input_no_title(""),
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
309
|
+
Html2Doc.process(html_input_no_title(""),
|
310
|
+
filename: "test", stylesheet: "lib/html2doc/wordstyle.css")
|
311
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
312
|
+
.to match_fuzzy(<<~OUTPUT)
|
313
|
+
#{WORD_HDR.sub('<title>blank</title>', '')}
|
314
|
+
#{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
315
|
+
#{word_body('', '<div style="mso-element:footnote-list"/>')} #{WORD_FTR1}
|
316
|
+
OUTPUT
|
314
317
|
end
|
315
318
|
|
316
319
|
it "processes a stylesheet in an HTML document with an empty head" do
|
317
320
|
Html2Doc.process(html_input_empty_head(""), filename: "test", stylesheet: "lib/html2doc/wordstyle.css")
|
318
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
319
|
-
to match_fuzzy(<<~OUTPUT)
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
321
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
322
|
+
.to match_fuzzy(<<~OUTPUT)
|
323
|
+
#{WORD_HDR.sub('<title>blank</title>', '')}
|
324
|
+
#{DEFAULT_STYLESHEET}
|
325
|
+
#{WORD_HDR_END.sub('<meta name="Originator" content="Me"/>' + "\n", '').sub("</style>\n</head>", '</style></head>')}
|
326
|
+
#{word_body('', '<div style="mso-element:footnote-list"/>')} #{WORD_FTR1}
|
327
|
+
OUTPUT
|
325
328
|
end
|
326
329
|
|
327
330
|
it "processes a header" do
|
328
331
|
Html2Doc.process(html_input(""), filename: "test", header_file: "spec/header.html")
|
329
332
|
html = guid_clean(File.read("test.doc", encoding: "utf-8"))
|
330
|
-
hdr = Base64.decode64(html.sub(%r{^.*Content-Location: file:///C:/Doc/test_files/header.html}, "")
|
331
|
-
sub(%r{^.*Content-Type: text/html charset="utf-8"}m, "")
|
332
|
-
sub(%r{------=_NextPart_--.*$}m, "")).force_encoding("UTF-8")
|
333
|
-
#expect(hdr.gsub(/\xa0/, " ")).to match_fuzzy(HEADERHTML)
|
334
|
-
expect(HTMLEntities.new.encode(hdr, :hexadecimal)
|
335
|
-
gsub(
|
336
|
-
gsub(
|
337
|
-
expect(html.sub(%r{Content-ID: <header.html>.*$}m, ""))
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
333
|
+
hdr = Base64.decode64(html.sub(%r{^.*Content-Location: file:///C:/Doc/test_files/header.html}, "")
|
334
|
+
.sub(%r{^.*Content-Type: text/html charset="utf-8"}m, "")
|
335
|
+
.sub(%r{------=_NextPart_--.*$}m, "")).force_encoding("UTF-8")
|
336
|
+
# expect(hdr.gsub(/\xa0/, " ")).to match_fuzzy(HEADERHTML)
|
337
|
+
expect(HTMLEntities.new.encode(hdr, :hexadecimal)
|
338
|
+
.gsub(/</, "<").gsub(/>/, ">").gsub(/'/, "'").gsub(/"/, '"')
|
339
|
+
.gsub(/
/, "
").gsub(/
/, "\n")).to match_fuzzy(HEADERHTML)
|
340
|
+
expect(html.sub(%r{Content-ID: <header.html>.*$}m, ""))
|
341
|
+
.to match_fuzzy(<<~OUTPUT)
|
342
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET.gsub(/url\("[^"]+"\)/, 'url(cid:header.html)')}
|
343
|
+
#{WORD_HDR_END} #{word_body('', '<div style="mso-element:footnote-list"/>')} #{WORD_FTR2}
|
344
|
+
OUTPUT
|
342
345
|
end
|
343
346
|
|
344
347
|
it "processes a header with an image" do
|
@@ -359,150 +362,149 @@ RSpec.describe Html2Doc do
|
|
359
362
|
expect(doc).to match(%r{iVBORw0KGgoAAAANSUhEUgAAA5cAAAN7CAYAAADRE24cAAAgAElEQVR4XuydB5gUxdaGC65gTogB})
|
360
363
|
end
|
361
364
|
|
362
|
-
|
363
365
|
it "processes a populated document" do
|
364
366
|
simple_body = "<h1>Hello word!</h1>
|
365
367
|
<div>This is a very simple document</div>"
|
366
368
|
Html2Doc.process(html_input(simple_body), filename: "test")
|
367
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
368
|
-
to match_fuzzy(<<~OUTPUT)
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
369
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
370
|
+
.to match_fuzzy(<<~OUTPUT)
|
371
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
372
|
+
#{word_body(simple_body, '<div style="mso-element:footnote-list"/>')}
|
373
|
+
#{WORD_FTR1}
|
374
|
+
OUTPUT
|
373
375
|
end
|
374
376
|
|
375
377
|
it "processes AsciiMath" do
|
376
378
|
Html2Doc.process(html_input(%[<div>{{sum_(i=1)^n i^3=((n(n+1))/2)^2 text("integer"))}}</div>]), filename: "test", asciimathdelims: ["{{", "}}"])
|
377
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
378
|
-
to match_fuzzy(<<~OUTPUT)
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
end
|
388
|
-
|
389
|
-
|
379
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
380
|
+
.to match_fuzzy(<<~OUTPUT)
|
381
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
382
|
+
#{word_body(%{
|
383
|
+
<div><m:oMath>
|
384
|
+
<m:nary><m:naryPr><m:chr m:val="∑"></m:chr><m:limLoc m:val="undOvr"></m:limLoc><m:grow m:val="on"></m:grow><m:subHide m:val="off"></m:subHide><m:supHide m:val="off"></m:supHide></m:naryPr><m:sub><m:r><m:t>i=1</m:t></m:r></m:sub><m:sup><m:r><m:t>n</m:t></m:r></m:sup><m:e><m:sSup><m:e><m:r><m:t>i</m:t></m:r></m:e><m:sup><m:r><m:t>3</m:t></m:r></m:sup></m:sSup></m:e></m:nary><span style="font-style:normal;"><m:r><m:rPr><m:sty m:val="p"></m:sty></m:rPr><m:t>=</m:t></m:r></span><m:sSup><m:e><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:f><m:fPr><m:type m:val="bar"></m:type></m:fPr><m:num><m:r><m:t>n</m:t></m:r><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:r><m:t>n+1</m:t></m:r></m:e></m:d></m:num><m:den><m:r><m:t>2</m:t></m:r></m:den></m:f></m:e></m:d></m:e><m:sup><m:r><m:t>2</m:t></m:r></m:sup></m:sSup><m:r><m:rPr><m:nor></m:nor></m:rPr><m:t>"integer"</m:t></m:r><span style="font-style:normal;"><m:r><m:rPr><m:sty m:val="p"></m:sty></m:rPr><m:t>)</m:t></m:r></span>
|
385
|
+
</m:oMath>
|
386
|
+
</div>}, '<div style="mso-element:footnote-list"/>')}
|
387
|
+
#{WORD_FTR1}
|
388
|
+
OUTPUT
|
389
|
+
end
|
390
|
+
|
391
|
+
it "processes mstyle" do
|
390
392
|
Html2Doc.process(html_input(%[<div>{{bb (-log_2 (p_u)) bb "BB" bbb "BBB" cc "CC" bcc "BCC" tt "TT" fr "FR" bfr "BFR" sf "SF" bsf "BSFα" sfi "SFI" sfbi "SFBIα" bii "BII" ii "II"}}</div>]), filename: "test", asciimathdelims: ["{{", "}}"])
|
391
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
392
|
-
to match_fuzzy(<<~OUTPUT)
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
393
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
394
|
+
.to match_fuzzy(<<~OUTPUT)
|
395
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
396
|
+
#{word_body(%{
|
397
|
+
<div><m:oMath>
|
398
|
+
<span style="font-style:normal;font-weight:bold;"><m:r><m:rPr><m:sty m:val="b"></m:sty></m:rPr><m:t>−</m:t></m:r></span><m:sSub><m:e><span style="font-style:normal;font-weight:bold;"><m:r><m:rPr><m:sty m:val="b"></m:sty></m:rPr><m:t>log</m:t></m:r></span></m:e><m:sub><span style="font-style:normal;font-weight:bold;"><m:r><m:rPr><m:sty m:val="b"></m:sty></m:rPr><m:t>2</m:t></m:r></span></m:sub></m:sSub><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:sSub><m:e><span style="font-style:normal;font-weight:bold;"><m:r><m:rPr><m:sty m:val="b"></m:sty></m:rPr><m:t>p</m:t></m:r></span></m:e><m:sub><span style="font-style:normal;font-weight:bold;"><m:r><m:rPr><m:sty m:val="b"></m:sty></m:rPr><m:t>u</m:t></m:r></span></m:sub></m:sSub></m:e></m:d><span style="font-style:normal;font-weight:bold;"><m:r><m:rPr><m:nor></m:nor><m:sty m:val="b"></m:sty></m:rPr><m:t>BB</m:t></m:r></span><m:r><m:rPr><m:nor></m:nor><m:scr m:val="double-struck"></m:scr><m:sty m:val="p"></m:sty></m:rPr><m:t>𝔹𝔹𝔹</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="script"></m:scr></m:rPr><m:t>𝒞𝒞</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="script"></m:scr><m:sty m:val="b"></m:sty></m:rPr><m:t>𝓑𝓒𝓒</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="monospace"></m:scr><m:sty m:val="p"></m:sty></m:rPr><m:t>𝚃𝚃</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="fraktur"></m:scr><m:sty m:val="p"></m:sty></m:rPr><m:t>𝔉ℜ</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="fraktur"></m:scr><m:sty m:val="b"></m:sty></m:rPr><m:t>𝕭𝕱𝕽</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="sans-serif"></m:scr><m:sty m:val="p"></m:sty></m:rPr><m:t>𝖲𝖥</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="sans-serif"></m:scr><m:sty m:val="b"></m:sty></m:rPr><m:t>𝗕𝗦𝗙𝝰</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="sans-serif"></m:scr></m:rPr><m:t>𝖲𝖥𝖨</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="sans-serif"></m:scr><m:sty m:val="bi"></m:sty></m:rPr><m:t>𝙎𝙁𝘽𝙄𝞪</m:t></m:r><span class="nostem" style="font-weight:bold;"><em></em><m:r><m:rPr><m:nor></m:nor><m:sty m:val="bi"></m:sty></m:rPr><m:t>BII</m:t></m:r></span><span class="nostem"><em></em><m:r><m:rPr><m:nor></m:nor><m:sty m:val="i"></m:sty></m:rPr><m:t>II</m:t></m:r></span>
|
399
|
+
</m:oMath>
|
400
|
+
</div>}, '<div style="mso-element:footnote-list"/>')}
|
401
|
+
#{WORD_FTR1}
|
402
|
+
OUTPUT
|
401
403
|
end
|
402
404
|
|
403
405
|
it "processes spaces in AsciiMath" do
|
404
406
|
Html2Doc.process(html_input(%[<div>{{text " integer ")}}</div>]), filename: "test", asciimathdelims: ["{{", "}}"])
|
405
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
406
|
-
to match_fuzzy(<<~OUTPUT)
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
407
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
408
|
+
.to match_fuzzy(<<~OUTPUT)
|
409
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
410
|
+
#{word_body('
|
411
|
+
<div><m:oMath>
|
412
|
+
<m:r><m:t>text</m:t></m:r><m:r><m:rPr><m:nor></m:nor></m:rPr><m:t> integer </m:t></m:r><span style="font-style:normal;"><m:r><m:rPr><m:sty m:val="p"></m:sty></m:rPr><m:t>)</m:t></m:r></span>
|
413
|
+
</m:oMath>
|
414
|
+
</div>', '<div style="mso-element:footnote-list"/>')}
|
415
|
+
#{WORD_FTR1}
|
416
|
+
OUTPUT
|
415
417
|
end
|
416
418
|
|
417
419
|
it "processes spaces in MathML mtext" do
|
418
420
|
Html2Doc.process(html_input("<div><math xmlns='http://www.w3.org/1998/Math/MathML'>
|
419
421
|
<mrow><mi>H</mi><mtext> original </mtext><mi>J</mi></mrow>
|
420
422
|
</math></div>"), filename: "test", asciimathdelims: ["{{", "}}"])
|
421
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
422
|
-
to match_fuzzy(<<~OUTPUT)
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
423
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
424
|
+
.to match_fuzzy(<<~OUTPUT)
|
425
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
426
|
+
#{word_body('<div><m:oMath>
|
427
|
+
<m:r><m:t>H</m:t></m:r><m:r><m:rPr><m:nor></m:nor></m:rPr><m:t> original </m:t></m:r><m:r><m:t>J</m:t></m:r>
|
428
|
+
</m:oMath>
|
429
|
+
</div>', '<div style="mso-element:footnote-list"/>')}
|
430
|
+
#{WORD_FTR1}
|
431
|
+
OUTPUT
|
430
432
|
end
|
431
433
|
|
432
434
|
it "unwraps accent in MathML" do
|
433
435
|
Html2Doc.process(html_input("<div><math xmlns='http://www.w3.org/1998/Math/MathML'>
|
434
436
|
<mover accent='true'><mrow><mi>p</mi></mrow><mrow><mo>^</mo></mrow></mover>
|
435
437
|
</math></div>"), filename: "test", asciimathdelims: ["{{", "}}"])
|
436
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
437
|
-
to match_fuzzy(<<~OUTPUT)
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
438
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
439
|
+
.to match_fuzzy(<<~OUTPUT)
|
440
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
441
|
+
#{word_body('<div><m:oMath>
|
442
|
+
<m:acc><m:accPr><m:chr m:val="^"></m:chr></m:accPr><m:e><m:r><m:t>p</m:t></m:r></m:e></m:acc>
|
443
|
+
</m:oMath>
|
444
|
+
</div>', '<div style="mso-element:footnote-list"/>')}
|
445
|
+
#{WORD_FTR1}
|
446
|
+
OUTPUT
|
445
447
|
end
|
446
448
|
|
447
449
|
it "left-aligns AsciiMath" do
|
448
450
|
Html2Doc.process(html_input("<div style='text-align:left;'>{{sum_(i=1)^n i^3=((n(n+1))/2)^2}}</div>"), filename: "test", asciimathdelims: ["{{", "}}"])
|
449
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
450
|
-
to match_fuzzy(<<~OUTPUT)
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
451
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
452
|
+
.to match_fuzzy(<<~OUTPUT)
|
453
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
454
|
+
#{word_body(%{
|
455
|
+
<div style="text-align:left;"><m:oMathPara><m:oMathParaPr><m:jc m:val="left"/></m:oMathParaPr><m:oMath>
|
456
|
+
<m:nary><m:naryPr><m:chr m:val="∑"></m:chr><m:limLoc m:val="undOvr"></m:limLoc><m:grow m:val="on"></m:grow><m:subHide m:val="off"></m:subHide><m:supHide m:val="off"></m:supHide></m:naryPr><m:sub><m:r><m:t>i=1</m:t></m:r></m:sub><m:sup><m:r><m:t>n</m:t></m:r></m:sup><m:e><m:sSup><m:e><m:r><m:t>i</m:t></m:r></m:e><m:sup><m:r><m:t>3</m:t></m:r></m:sup></m:sSup></m:e></m:nary><span style="font-style:normal;"><m:r><m:rPr><m:sty m:val="p"></m:sty></m:rPr><m:t>=</m:t></m:r></span><m:sSup><m:e><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:f><m:fPr><m:type m:val="bar"></m:type></m:fPr><m:num><m:r><m:t>n</m:t></m:r><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:r><m:t>n+1</m:t></m:r></m:e></m:d></m:num><m:den><m:r><m:t>2</m:t></m:r></m:den></m:f></m:e></m:d></m:e><m:sup><m:r><m:t>2</m:t></m:r></m:sup></m:sSup>
|
457
|
+
</m:oMath>
|
458
|
+
</m:oMathPara></div>}, '<div style="mso-element:footnote-list"/>')}
|
459
|
+
#{WORD_FTR1}
|
460
|
+
OUTPUT
|
459
461
|
end
|
460
462
|
|
461
463
|
it "right-aligns AsciiMath" do
|
462
464
|
Html2Doc.process(html_input("<div style='text-align:right;'>{{sum_(i=1)^n i^3=((n(n+1))/2)^2}}</div>"), filename: "test", asciimathdelims: ["{{", "}}"])
|
463
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
464
|
-
to match_fuzzy(<<~OUTPUT)
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
465
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
466
|
+
.to match_fuzzy(<<~OUTPUT)
|
467
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
468
|
+
#{word_body(%{
|
469
|
+
<div style="text-align:right;"><m:oMathPara><m:oMathParaPr><m:jc m:val="right"/></m:oMathParaPr><m:oMath>
|
470
|
+
<m:nary><m:naryPr><m:chr m:val="∑"></m:chr><m:limLoc m:val="undOvr"></m:limLoc><m:grow m:val="on"></m:grow><m:subHide m:val="off"></m:subHide><m:supHide m:val="off"></m:supHide></m:naryPr><m:sub><m:r><m:t>i=1</m:t></m:r></m:sub><m:sup><m:r><m:t>n</m:t></m:r></m:sup><m:e><m:sSup><m:e><m:r><m:t>i</m:t></m:r></m:e><m:sup><m:r><m:t>3</m:t></m:r></m:sup></m:sSup></m:e></m:nary><span style="font-style:normal;"><m:r><m:rPr><m:sty m:val="p"></m:sty></m:rPr><m:t>=</m:t></m:r></span><m:sSup><m:e><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:f><m:fPr><m:type m:val="bar"></m:type></m:fPr><m:num><m:r><m:t>n</m:t></m:r><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:r><m:t>n+1</m:t></m:r></m:e></m:d></m:num><m:den><m:r><m:t>2</m:t></m:r></m:den></m:f></m:e></m:d></m:e><m:sup><m:r><m:t>2</m:t></m:r></m:sup></m:sSup>
|
471
|
+
</m:oMath>
|
472
|
+
</m:oMathPara></div>}, '<div style="mso-element:footnote-list"/>')}
|
473
|
+
#{WORD_FTR1}
|
474
|
+
OUTPUT
|
473
475
|
end
|
474
476
|
|
475
477
|
it "raises error in processing of broken AsciiMath" do
|
476
478
|
begin
|
477
|
-
|
479
|
+
expect { Html2Doc.process(html_input(%[<div style='text-align:right;'>{{u_c = 6.6"unitsml(kHz)}}</div>]), filename: "test", asciimathdelims: ["{{", "}}"]) }.to output('parsing: u_c = 6.6"unitsml(kHz)').to_stderr
|
478
480
|
rescue StandardError
|
479
481
|
end
|
480
|
-
expect{ Html2Doc.process(html_input(%[<div style='text-align:right;'>{{u_c = 6.6"unitsml(kHz)}}</div>]), filename: "test", asciimathdelims: ["{{", "}}"]) }.to raise_error(StandardError)
|
482
|
+
expect { Html2Doc.process(html_input(%[<div style='text-align:right;'>{{u_c = 6.6"unitsml(kHz)}}</div>]), filename: "test", asciimathdelims: ["{{", "}}"]) }.to raise_error(StandardError)
|
481
483
|
end
|
482
484
|
|
483
485
|
it "wraps msup after munderover in MathML" do
|
484
486
|
Html2Doc.process(html_input("<div><math xmlns='http://www.w3.org/1998/Math/MathML'>
|
485
487
|
<munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>0</mn></mrow><mrow><mi>n</mi></mrow></munderover><msup><mn>2</mn><mrow><mi>i</mi></mrow></msup></math></div>"), filename: "test", asciimathdelims: ["{{", "}}"])
|
486
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
487
|
-
to match_fuzzy(<<~OUTPUT)
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
488
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
489
|
+
.to match_fuzzy(<<~OUTPUT)
|
490
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
491
|
+
#{word_body('<div><m:oMath>
|
492
|
+
<m:nary><m:naryPr><m:chr m:val="∑"></m:chr><m:limLoc m:val="undOvr"></m:limLoc><m:grow m:val="on"></m:grow><m:subHide m:val="off"></m:subHide><m:supHide m:val="off"></m:supHide></m:naryPr><m:sub><m:r><m:t>i=0</m:t></m:r></m:sub><m:sup><m:r><m:t>n</m:t></m:r></m:sup><m:e><m:sSup><m:e><m:r><m:t>2</m:t></m:r></m:e><m:sup><m:r><m:t>i</m:t></m:r></m:sup></m:sSup></m:e></m:nary></m:oMath>
|
493
|
+
</div>', '<div style="mso-element:footnote-list"/>')}
|
494
|
+
#{WORD_FTR1}
|
495
|
+
OUTPUT
|
494
496
|
end
|
495
497
|
|
496
498
|
it "processes tabs" do
|
497
499
|
simple_body = "<h1>Hello word!</h1>
|
498
500
|
<div>This is a very &tab; simple document</div>"
|
499
501
|
Html2Doc.process(html_input(simple_body), filename: "test")
|
500
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
501
|
-
to match_fuzzy(<<~OUTPUT)
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
502
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
503
|
+
.to match_fuzzy(<<~OUTPUT)
|
504
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
505
|
+
#{word_body(simple_body.gsub(/&tab;/, %[<span style="mso-tab-count:1">  </span>]), '<div style="mso-element:footnote-list"/>')}
|
506
|
+
#{WORD_FTR1}
|
507
|
+
OUTPUT
|
506
508
|
end
|
507
509
|
|
508
510
|
it "makes unstyled paragraphs be MsoNormal" do
|
@@ -510,12 +512,12 @@ RSpec.describe Html2Doc do
|
|
510
512
|
<p>This is a very simple document</p>
|
511
513
|
<p class="x">This style stays</p>'
|
512
514
|
Html2Doc.process(html_input(simple_body), filename: "test")
|
513
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
514
|
-
to match_fuzzy(<<~OUTPUT)
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
515
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
516
|
+
.to match_fuzzy(<<~OUTPUT)
|
517
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
518
|
+
#{word_body(simple_body.gsub(/<p>/, %[<p class="MsoNormal">]), '<div style="mso-element:footnote-list"/>')}
|
519
|
+
#{WORD_FTR1}
|
520
|
+
OUTPUT
|
519
521
|
end
|
520
522
|
|
521
523
|
it "makes unstyled list entries be MsoNormal" do
|
@@ -525,12 +527,12 @@ RSpec.describe Html2Doc do
|
|
525
527
|
<li class="x">This style stays</li>
|
526
528
|
</ul>'
|
527
529
|
Html2Doc.process(html_input(simple_body), filename: "test")
|
528
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
529
|
-
to match_fuzzy(<<~OUTPUT)
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
530
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
531
|
+
.to match_fuzzy(<<~OUTPUT)
|
532
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
533
|
+
#{word_body(simple_body.gsub(/<li>/, %[<li class="MsoNormal">]), '<div style="mso-element:footnote-list"/>')}
|
534
|
+
#{WORD_FTR1}
|
535
|
+
OUTPUT
|
534
536
|
end
|
535
537
|
|
536
538
|
it "resizes images for height, in a file in a subdirectory" do
|
@@ -539,9 +541,9 @@ RSpec.describe Html2Doc do
|
|
539
541
|
testdoc = File.read("spec/test.doc", encoding: "utf-8")
|
540
542
|
expect(testdoc).to match(%r{Content-Type: image/png})
|
541
543
|
expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
|
542
|
-
|
543
|
-
|
544
|
-
|
544
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
545
|
+
#{image_clean(word_body('<img src="cid:cb7b0d19-891e-4634-815a-570d019d454c.png" width="400" height="388"></img>', '<div style="mso-element:footnote-list"/>'))}
|
546
|
+
#{image_clean(WORD_FTR3)}
|
545
547
|
OUTPUT
|
546
548
|
end
|
547
549
|
|
@@ -551,9 +553,9 @@ RSpec.describe Html2Doc do
|
|
551
553
|
testdoc = File.read("test.doc", encoding: "utf-8")
|
552
554
|
expect(testdoc).to match(%r{Content-Type: image/gif})
|
553
555
|
expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
|
554
|
-
|
555
|
-
|
556
|
-
|
556
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
557
|
+
#{image_clean(word_body('<img src="cid:cb7b0d19-891e-4634-815a-570d019d454c.gif" width="400" height="118"></img>', '<div style="mso-element:footnote-list"/>'))}
|
558
|
+
#{image_clean(WORD_FTR3).gsub(/image\.png/, 'image.gif')}
|
557
559
|
OUTPUT
|
558
560
|
end
|
559
561
|
|
@@ -563,9 +565,9 @@ RSpec.describe Html2Doc do
|
|
563
565
|
testdoc = File.read("test.doc", encoding: "utf-8")
|
564
566
|
expect(testdoc).to match(%r{Content-Type: image/jpeg})
|
565
567
|
expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
|
566
|
-
|
567
|
-
|
568
|
-
|
568
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
569
|
+
#{image_clean(word_body('<img src="cid:cb7b0d19-891e-4634-815a-570d019d454c.jpg" width="208" height="680"></img>', '<div style="mso-element:footnote-list"/>'))}
|
570
|
+
#{image_clean(WORD_FTR3).gsub(/image\.png/, 'image.jpg')}
|
569
571
|
OUTPUT
|
570
572
|
end
|
571
573
|
|
@@ -605,49 +607,47 @@ RSpec.describe Html2Doc do
|
|
605
607
|
Html2Doc.process(html_input(simple_body), filename: "test")
|
606
608
|
testdoc = File.read("test.doc", encoding: "utf-8")
|
607
609
|
expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
|
608
|
-
|
609
|
-
|
610
|
-
|
610
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
611
|
+
#{image_clean(word_body('<img src="https://example.com/19160-6.png"></img>', '<div style="mso-element:footnote-list"/>'))}
|
612
|
+
#{image_clean(WORD_FTR1)}
|
611
613
|
OUTPUT
|
612
614
|
end
|
613
615
|
|
614
616
|
it "deals with absolute image locations" do
|
615
|
-
simple_body = %{<img src="#{
|
617
|
+
simple_body = %{<img src="#{__dir__}/19160-6.png">}
|
616
618
|
Html2Doc.process(html_input(simple_body), filename: "spec/test")
|
617
619
|
testdoc = File.read("spec/test.doc", encoding: "utf-8")
|
618
620
|
expect(testdoc).to match(%r{Content-Type: image/png})
|
619
621
|
expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
|
620
|
-
|
621
|
-
|
622
|
-
|
622
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
623
|
+
#{image_clean(word_body('<img src="cid:cb7b0d19-891e-4634-815a-570d019d454c.png" width="400" height="388"></img>', '<div style="mso-element:footnote-list"/>'))}
|
624
|
+
#{image_clean(WORD_FTR3)}
|
623
625
|
OUTPUT
|
624
626
|
end
|
625
627
|
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
end
|
631
|
-
=end
|
628
|
+
# it "warns about SVG" do
|
629
|
+
# simple_body = '<img src="https://example.com/19160-6.svg">'
|
630
|
+
# expect{ Html2Doc.process(html_input(simple_body), filename: "test") }.to output("https://example.com/19160-6.svg: SVG not supported\n").to_stderr
|
631
|
+
# end
|
632
632
|
|
633
633
|
it "processes epub:type footnotes" do
|
634
|
-
simple_body = '<div>This is a very simple
|
634
|
+
simple_body = '<div>This is a very simple
|
635
635
|
document<a epub:type="footnote" href="#a1">1</a> allegedly<a epub:type="footnote" href="#a2">2</a></div>
|
636
636
|
<aside id="a1">Footnote</aside>
|
637
637
|
<aside id="a2">Other Footnote</aside>'
|
638
638
|
Html2Doc.process(html_input(simple_body), filename: "test")
|
639
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
640
|
-
to match_fuzzy(<<~OUTPUT)
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn1" href="#_ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Footnote</p></div>
|
646
|
-
<div style="mso-element:footnote" id="ftn2">
|
647
|
-
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn2" href="#_ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Other Footnote</p></div>
|
648
|
-
</div>')}
|
649
|
-
|
650
|
-
|
639
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
640
|
+
.to match_fuzzy(<<~OUTPUT)
|
641
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
642
|
+
#{word_body('<div>This is a very simple
|
643
|
+
document<a epub:type="footnote" href="#_ftn1" style="mso-footnote-id:ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a> allegedly<a epub:type="footnote" href="#_ftn2" style="mso-footnote-id:ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a></div>',
|
644
|
+
'<div style="mso-element:footnote-list"><div style="mso-element:footnote" id="ftn1">
|
645
|
+
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn1" href="#_ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Footnote</p></div>
|
646
|
+
<div style="mso-element:footnote" id="ftn2">
|
647
|
+
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn2" href="#_ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Other Footnote</p></div>
|
648
|
+
</div>')}
|
649
|
+
#{WORD_FTR1}
|
650
|
+
OUTPUT
|
651
651
|
end
|
652
652
|
|
653
653
|
it "processes class footnotes" do
|
@@ -656,38 +656,38 @@ RSpec.describe Html2Doc do
|
|
656
656
|
<aside id="a1">Footnote</aside>
|
657
657
|
<aside id="a2">Other Footnote</aside>'
|
658
658
|
Html2Doc.process(html_input(simple_body), filename: "test")
|
659
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
660
|
-
to match_fuzzy(<<~OUTPUT)
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn1" href="#_ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Footnote</p></div>
|
666
|
-
<div style="mso-element:footnote" id="ftn2">
|
667
|
-
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn2" href="#_ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Other Footnote</p></div>
|
668
|
-
</div>')}
|
669
|
-
|
670
|
-
|
659
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
660
|
+
.to match_fuzzy(<<~OUTPUT)
|
661
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
662
|
+
#{word_body('<div>This is a very simple
|
663
|
+
document<a class="footnote" href="#_ftn1" style="mso-footnote-id:ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a> allegedly<a class="footnote" href="#_ftn2" style="mso-footnote-id:ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a></div>',
|
664
|
+
'<div style="mso-element:footnote-list"><div style="mso-element:footnote" id="ftn1">
|
665
|
+
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn1" href="#_ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Footnote</p></div>
|
666
|
+
<div style="mso-element:footnote" id="ftn2">
|
667
|
+
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn2" href="#_ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Other Footnote</p></div>
|
668
|
+
</div>')}
|
669
|
+
#{WORD_FTR1}
|
670
|
+
OUTPUT
|
671
671
|
end
|
672
672
|
|
673
673
|
it "processes footnotes with text wrapping the footnote reference" do
|
674
|
-
|
674
|
+
simple_body = '<div>This is a very simple
|
675
675
|
document<a class="footnote" href="#a1">(<span class="MsoFootnoteReference">1</span>)</a> allegedly<a class="footnote" href="#a2">2</a></div>
|
676
676
|
<aside id="a1">Footnote</aside>
|
677
677
|
<aside id="a2">Other Footnote</aside>'
|
678
678
|
Html2Doc.process(html_input(simple_body), filename: "test")
|
679
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
680
|
-
to match_fuzzy(<<~OUTPUT)
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn1" href="#_ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference">(</span><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span><span class="MsoFootnoteReference">)</span></a>Footnote</p></div>
|
686
|
-
<div style="mso-element:footnote" id="ftn2">
|
687
|
-
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn2" href="#_ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Other Footnote</p></div>
|
688
|
-
</div>')}
|
689
|
-
|
690
|
-
|
679
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
680
|
+
.to match_fuzzy(<<~OUTPUT)
|
681
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
682
|
+
#{word_body('<div>This is a very simple
|
683
|
+
document<a class="footnote" href="#_ftn1" style="mso-footnote-id:ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference">(</span><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span><span class="MsoFootnoteReference">)</span></a> allegedly<a class="footnote" href="#_ftn2" style="mso-footnote-id:ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a></div>',
|
684
|
+
'<div style="mso-element:footnote-list"><div style="mso-element:footnote" id="ftn1">
|
685
|
+
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn1" href="#_ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference">(</span><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span><span class="MsoFootnoteReference">)</span></a>Footnote</p></div>
|
686
|
+
<div style="mso-element:footnote" id="ftn2">
|
687
|
+
<p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn2" href="#_ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Other Footnote</p></div>
|
688
|
+
</div>')}
|
689
|
+
#{WORD_FTR1}
|
690
|
+
OUTPUT
|
691
691
|
end
|
692
692
|
|
693
693
|
it "extracts paragraphs from footnotes" do
|
@@ -696,18 +696,18 @@ RSpec.describe Html2Doc do
|
|
696
696
|
<aside id="a1"><p>Footnote</p></aside>
|
697
697
|
<div id="a2"><p>Other Footnote</p></div>'
|
698
698
|
Html2Doc.process(html_input(simple_body), filename: "test")
|
699
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
700
|
-
to match_fuzzy(<<~OUTPUT)
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
<p class="MsoFootnoteText"><a style="mso-footnote-id:ftn1" href="#_ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Footnote</p></div>
|
706
|
-
<div style="mso-element:footnote" id="ftn2">
|
707
|
-
<p class="MsoFootnoteText"><a style="mso-footnote-id:ftn2" href="#_ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Other Footnote</p></div>
|
708
|
-
</div>')}
|
709
|
-
|
710
|
-
|
699
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
700
|
+
.to match_fuzzy(<<~OUTPUT)
|
701
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
702
|
+
#{word_body('<div>This is a very simple
|
703
|
+
document<a class="footnote" href="#_ftn1" style="mso-footnote-id:ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a> allegedly<a class="footnote" href="#_ftn2" style="mso-footnote-id:ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a></div>',
|
704
|
+
'<div style="mso-element:footnote-list"><div style="mso-element:footnote" id="ftn1">
|
705
|
+
<p class="MsoFootnoteText"><a style="mso-footnote-id:ftn1" href="#_ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Footnote</p></div>
|
706
|
+
<div style="mso-element:footnote" id="ftn2">
|
707
|
+
<p class="MsoFootnoteText"><a style="mso-footnote-id:ftn2" href="#_ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Other Footnote</p></div>
|
708
|
+
</div>')}
|
709
|
+
#{WORD_FTR1}
|
710
|
+
OUTPUT
|
711
711
|
end
|
712
712
|
|
713
713
|
it "labels lists with list styles" do
|
@@ -715,38 +715,37 @@ RSpec.describe Html2Doc do
|
|
715
715
|
<div><ul id="0">
|
716
716
|
<li><div><p><ol id="1"><li><ul id="2"><li><p><ol id="3"><li><ol id="4"><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li><div><ul id="5"><li>C</li></ul></div>
|
717
717
|
BODY
|
718
|
-
Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2"})
|
719
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
720
|
-
to match_fuzzy(<<~OUTPUT)
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
718
|
+
Html2Doc.process(html_input(simple_body), filename: "test", liststyles: { ul: "l1", ol: "l2" })
|
719
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
720
|
+
.to match_fuzzy(<<~OUTPUT)
|
721
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
722
|
+
#{word_body('<div>
|
723
|
+
<p style="mso-list:l1 level1 lfo1;" class="MsoListParagraphCxSpFirst"><div><p class="MsoNormal"><p style="mso-list:l2 level2 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level4 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpFirst">A</p><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpMiddle">B<p class="MsoListParagraphCxSpMiddle">B2</p></p><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpLast">C</p></p></p></p></div></p><div><p style="mso-list:l1 level1 lfo2;" class="MsoListParagraphCxSpFirst">C</p></div>
|
724
|
+
</div>',
|
725
|
+
'<div style="mso-element:footnote-list"/>')}
|
726
|
+
#{WORD_FTR1}
|
727
|
+
OUTPUT
|
728
728
|
end
|
729
729
|
|
730
|
-
|
731
730
|
it "restarts numbering of lists with list styles" do
|
732
731
|
simple_body = <<~BODY
|
733
732
|
<div>
|
734
733
|
<ol id="1"><li><div><p><ol id="2"><li><ul id="3"><li><p><ol id="4"><li><ol id="5"><li>A</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ol>
|
735
734
|
<ol id="6"><li><div><p><ol id="7"><li><ul id="8"><li><p><ol id="9"><li><ol id="10"><li>A</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ol></div>
|
736
735
|
BODY
|
737
|
-
Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2"})
|
738
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
739
|
-
to match_fuzzy(<<~OUTPUT)
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
end
|
748
|
-
|
749
|
-
|
736
|
+
Html2Doc.process(html_input(simple_body), filename: "test", liststyles: { ul: "l1", ol: "l2" })
|
737
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
738
|
+
.to match_fuzzy(<<~OUTPUT)
|
739
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
740
|
+
#{word_body('<div>
|
741
|
+
<p style="mso-list:l2 level1 lfo1;" class="MsoListParagraphCxSpFirst"><div><p class="MsoNormal"><p style="mso-list:l2 level2 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level4 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpFirst">A</p></p></p></p></div></p>
|
742
|
+
<p style="mso-list:l2 level1 lfo2;" class="MsoListParagraphCxSpFirst"><div><p class="MsoNormal"><p style="mso-list:l2 level2 lfo2;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level4 lfo2;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level5 lfo2;" class="MsoListParagraphCxSpFirst">A</p></p></p></p></div></p></div>',
|
743
|
+
'<div style="mso-element:footnote-list"/>')}
|
744
|
+
#{WORD_FTR1}
|
745
|
+
OUTPUT
|
746
|
+
end
|
747
|
+
|
748
|
+
it "labels lists with multiple list styles" do
|
750
749
|
simple_body = <<~BODY
|
751
750
|
<div><ul class="steps" id="0">
|
752
751
|
<li><div><p><ol id="1"><li><ul id="2"><li><p><ol id="3"><li><ol id="4"><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ul></div>
|
@@ -755,19 +754,19 @@ RSpec.describe Html2Doc do
|
|
755
754
|
<div><ul class="other" id="10">
|
756
755
|
<li><div><p><ol id="11"><li><ul id="12"><li><p><ol id="13"><li><ol id="14"><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ul></div>
|
757
756
|
BODY
|
758
|
-
Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2", steps: "l3"})
|
759
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
760
|
-
to match_fuzzy(<<~OUTPUT)
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
757
|
+
Html2Doc.process(html_input(simple_body), filename: "test", liststyles: { ul: "l1", ol: "l2", steps: "l3" })
|
758
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
759
|
+
.to match_fuzzy(<<~OUTPUT)
|
760
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
761
|
+
#{word_body('<div>
|
762
|
+
<p style="mso-list:l3 level1 lfo2;" class="MsoListParagraphCxSpFirst"><div><p class="MsoNormal"><p style="mso-list:l3 level2 lfo2;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l3 level4 lfo2;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l3 level5 lfo2;" class="MsoListParagraphCxSpFirst">A</p><p style="mso-list:l3 level5 lfo2;" class="MsoListParagraphCxSpMiddle">B<p class="MsoListParagraphCxSpMiddle">B2</p></p><p style="mso-list:l3 level5 lfo2;" class="MsoListParagraphCxSpLast">C</p></p></p></p></div></p></div>
|
763
|
+
<div>
|
764
|
+
<p style="mso-list:l1 level1 lfo1;" class="MsoListParagraphCxSpFirst"><div><p class="MsoNormal"><p style="mso-list:l2 level2 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level4 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpFirst">A</p><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpMiddle">B<p class="MsoListParagraphCxSpMiddle">B2</p></p><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpLast">C</p></p></p></p></div></p></div>
|
765
|
+
<div>
|
766
|
+
<p style="mso-list:l1 level1 lfo3;" class="MsoListParagraphCxSpFirst"><div><p class="MsoNormal"><p style="mso-list:l2 level2 lfo3;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level4 lfo3;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level5 lfo3;" class="MsoListParagraphCxSpFirst">A</p><p style="mso-list:l2 level5 lfo3;" class="MsoListParagraphCxSpMiddle">B<p class="MsoListParagraphCxSpMiddle">B2</p></p><p style="mso-list:l2 level5 lfo3;" class="MsoListParagraphCxSpLast">C</p></p></p></p></div></p></div>',
|
767
|
+
'<div style="mso-element:footnote-list"/>')}
|
768
|
+
#{WORD_FTR1}
|
769
|
+
OUTPUT
|
771
770
|
end
|
772
771
|
|
773
772
|
it "replaces id attributes with explicit a@name bookmarks" do
|
@@ -777,17 +776,17 @@ RSpec.describe Html2Doc do
|
|
777
776
|
<p id="b"/>
|
778
777
|
</div>
|
779
778
|
BODY
|
780
|
-
Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2"})
|
781
|
-
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
782
|
-
to match_fuzzy(<<~OUTPUT)
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
779
|
+
Html2Doc.process(html_input(simple_body), filename: "test", liststyles: { ul: "l1", ol: "l2" })
|
780
|
+
expect(guid_clean(File.read("test.doc", encoding: "utf-8")))
|
781
|
+
.to match_fuzzy(<<~OUTPUT)
|
782
|
+
#{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
|
783
|
+
#{word_body('<div>
|
784
|
+
<p class="MsoNormal"><a name="a" id="a"></a>Hello</p>
|
785
|
+
<p class="MsoNormal"><a name="b" id="b"></a></p>
|
786
|
+
</div>',
|
787
|
+
'<div style="mso-element:footnote-list"/>')}
|
788
|
+
#{WORD_FTR1}
|
789
|
+
OUTPUT
|
791
790
|
end
|
792
791
|
|
793
792
|
it "test image base64 image encoding" do
|