html2doc 1.0.5 → 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.
data/lib/html2doc/mime.rb CHANGED
@@ -7,19 +7,20 @@ require "fileutils"
7
7
  module Html2Doc
8
8
  def self.mime_preamble(boundary, filename, result)
9
9
  <<~"PREAMBLE"
10
- MIME-Version: 1.0
11
- Content-Type: multipart/related; boundary="#{boundary}"
10
+ MIME-Version: 1.0
11
+ Content-Type: multipart/related; boundary="#{boundary}"
12
12
 
13
- --#{boundary}
14
- Content-Location: file:///C:/Doc/#{File.basename(filename)}.htm
15
- Content-Type: text/html; charset="utf-8"
13
+ --#{boundary}
14
+ Content-ID: <#{File.basename(filename)}>
15
+ Content-Disposition: inline; filename="#{File.basename(filename)}"
16
+ Content-Type: text/html; charset="utf-8"
16
17
 
17
- #{result}
18
+ #{result}
18
19
 
19
20
  PREAMBLE
20
21
  end
21
22
 
22
- def self.mime_attachment(boundary, filename, item, dir)
23
+ def self.mime_attachment(boundary, _filename, item, dir)
23
24
  content_type = mime_type(item)
24
25
  text_mode = %w[text application].any? { |p| content_type.start_with? p }
25
26
 
@@ -28,12 +29,13 @@ module Html2Doc
28
29
 
29
30
  encoded_file = Base64.strict_encode64(content).gsub(/(.{76})/, "\\1\n")
30
31
  <<~"FILE"
31
- --#{boundary}
32
- Content-Location: file:///C:/Doc/#{File.basename(filename)}_files/#{item}
33
- Content-Transfer-Encoding: base64
34
- Content-Type: #{content_type}
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}
35
37
 
36
- #{encoded_file}
38
+ #{encoded_file}
37
39
 
38
40
  FILE
39
41
  end
@@ -52,15 +54,26 @@ module Html2Doc
52
54
 
53
55
  def self.mime_package(result, filename, dir)
54
56
  boundary = mime_boundary
55
- mhtml = mime_preamble(boundary, filename, result)
56
- mhtml += mime_attachment(boundary, filename, "filelist.xml", dir)
57
+ mhtml = mime_preamble(boundary, "#{filename}.htm", result)
58
+ mhtml += mime_attachment(boundary, "#{filename}.htm", "filelist.xml", dir)
57
59
  Dir.foreach(dir) do |item|
58
60
  next if item == "." || item == ".." || /^\./.match(item) ||
59
61
  item == "filelist.xml"
60
- mhtml += mime_attachment(boundary, filename, item, dir)
62
+
63
+ mhtml += mime_attachment(boundary, "#{filename}.htm", item, dir)
61
64
  end
62
65
  mhtml += "--#{boundary}--"
63
- File.open("#{filename}.doc", "w:UTF-8") { |f| f.write mhtml }
66
+ File.open("#{filename}.doc", "w:UTF-8") { |f| f.write contentid(mhtml) }
67
+ end
68
+
69
+ def self.contentid(mhtml)
70
+ mhtml.gsub %r{(<img[^>]*?src=")([^\"']+)(['"])}m do |m|
71
+ repl = "#{$1}cid:#{File.basename($2)}#{$3}"
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
76
+ end
64
77
  end
65
78
 
66
79
  # max width for Word document is 400, max height is 680
@@ -68,7 +81,8 @@ module Html2Doc
68
81
  realSize = ImageSize.path(path).size
69
82
  s = [i["width"].to_i, i["height"].to_i]
70
83
  s = realSize if s[0].zero? && s[1].zero?
71
- return [nil, nil] if realSize[0].nil? || realSize[1].nil?
84
+ return [nil, nil] if realSize.nil? || realSize[0].nil? || realSize[1].nil?
85
+
72
86
  s[1] = s[0] * realSize[1] / realSize[0] if s[1].zero? && !s[0].zero?
73
87
  s[0] = s[1] * realSize[0] / realSize[1] if s[0].zero? && !s[1].zero?
74
88
  s = [(s[0] * maxheight / s[1]).ceil, maxheight] if s[1] > maxheight
@@ -83,7 +97,7 @@ module Html2Doc
83
97
  end
84
98
 
85
99
  def self.warnsvg(src)
86
- warn "#{src}: SVG not supported" if /\.svg$/i.match(src)
100
+ warn "#{src}: SVG not supported" if /\.svg$/i.match?(src)
87
101
  end
88
102
 
89
103
  # only processes locally stored images
@@ -92,10 +106,11 @@ module Html2Doc
92
106
  next unless i.element? && %w(img v:imagedata).include?(i.name)
93
107
  #warnsvg(i["src"])
94
108
  next if /^http/.match i["src"]
95
- next if %r{^data:image/[^;]+;base64}.match i["src"]
109
+ next if %r{^data:(image|application)/[^;]+;base64}.match? i["src"]
110
+
96
111
  local_filename = %r{^([A-Z]:)?/}.match(i["src"]) ? i["src"] :
97
112
  File.join(localdir, i["src"])
98
- new_filename = "#{mkuuid}#{File.extname(i["src"])}"
113
+ new_filename = "#{mkuuid}#{File.extname(i['src'])}"
99
114
  FileUtils.cp local_filename, File.join(dir, new_filename)
100
115
  i["width"], i["height"] = image_resize(i, local_filename, 680, 400)
101
116
  i["src"] = File.join(File.basename(dir), new_filename)
@@ -103,7 +118,7 @@ module Html2Doc
103
118
  docxml
104
119
  end
105
120
 
106
- # do not parse the header through Nokogiri, since it will contain
121
+ # do not parse the header through Nokogiri, since it will contain
107
122
  # non-XML like <![if !supportFootnotes]>
108
123
  def self.header_image_cleanup(doc, dir, filename, localdir)
109
124
  doc.split(%r{(<img [^>]*>|<v:imagedata [^>]*>)}).each_slice(2).map do |a|
@@ -111,16 +126,17 @@ module Html2Doc
111
126
  end.join
112
127
  end
113
128
 
114
- def self.header_image_cleanup1(a, dir, filename, localdir)
129
+ def self.header_image_cleanup1(a, dir, _filename, localdir)
115
130
  if a.size == 2 && !(/ src="https?:/.match a[1]) &&
116
- !(%r{ src="data:image/[^;]+;base64}.match a[1])
131
+ !(%r{ src="data:(image|application)/[^;]+;base64}.match a[1])
117
132
  m = / src=['"](?<src>[^"']+)['"]/.match a[1]
118
133
  #warnsvg(m[:src])
119
134
  m2 = /\.(?<suffix>[a-zA-Z_0-9]+)$/.match m[:src]
120
135
  new_filename = "#{mkuuid}.#{m2[:suffix]}"
121
- old_filename = %r{^([A-Z]:)?/}.match(m[:src]) ? m[:src] : File.join(localdir, m[:src])
136
+ old_filename = %r{^([A-Z]:)?/}.match?(m[:src]) ? m[:src] :
137
+ File.join(localdir, m[:src])
122
138
  FileUtils.cp old_filename, File.join(dir, new_filename)
123
- a[1].sub!(%r{ src=['"](?<src>[^"']+)['"]}, " src='file:///C:/Doc/#{filename}_files/#{new_filename}'")
139
+ a[1].sub!(%r{ src=['"](?<src>[^"']+)['"]}, " src='cid:#{new_filename}'")
124
140
  end
125
141
  a.join
126
142
  end
@@ -131,6 +147,7 @@ module Html2Doc
131
147
  <o:MainFile HRef="../#{filename}.htm"/>}
132
148
  Dir.entries(dir).sort.each do |item|
133
149
  next if item == "." || item == ".." || /^\./.match(item)
150
+
134
151
  f.write %{ <o:File HRef="#{item}"/>\n}
135
152
  end
136
153
  f.write("</xml>\n")
@@ -1087,8 +1087,16 @@
1087
1087
  <xsl:attribute name="m:val">bi</xsl:attribute>
1088
1088
  </sty>
1089
1089
  </xsl:when>
1090
- <xsl:when test="$font='monospace'"/>
1090
+ <xsl:when test="$font='monospace'">
1091
1091
  <!-- We can't do monospace, so leave empty -->
1092
+ <!-- NN 2020 https://github.com/metanorma/html2doc/issues/47 no, we will -->
1093
+ <scr>
1094
+ <xsl:attribute name="m:val">monospace</xsl:attribute>
1095
+ </scr>
1096
+ <sty>
1097
+ <xsl:attribute name="m:val">p</xsl:attribute>
1098
+ </sty>
1099
+ </xsl:when>
1092
1100
  <xsl:when test="$font='bold'">
1093
1101
  <sty>
1094
1102
  <xsl:attribute name="m:val">b</xsl:attribute>
@@ -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(f)
26
- if %w{div aside}.include? f.name
27
- if f.at(".//p")
28
- f.replace(f.children)
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
- f.name = "p"
31
- f["class"] = "MsoFootnoteText"
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, i)
40
- ref = docxml&.at("//a[@href='#_ftn#{i}']")&.children&.to_xml(indent: 0).
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#{i}'>
44
- <a style='mso-footnote-id:ftn#{i}' href='#_ftn#{i}'
45
- name='_ftnref#{i}' title='' id='_ftnref#{i}'>#{ref.strip}</a></div>
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, a, i, fn)
50
- return false unless footnote?(a)
51
- href = a["href"].gsub(/^#/, "")
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
- set_footnote_link_attrs(a, i)
55
- if a.at("./span[@class = 'MsoFootnoteReference']")
56
- a.children.each do |c|
57
- if c.name == "span" and c["class"] == "MsoFootnoteReference"
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
- a.children = FN
67
+ elem.children = FN
65
68
  end
66
- fn << transform_footnote_text(note)
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?(a)
80
- a["epub:type"]&.casecmp("footnote")&.zero? ||
81
- a["class"]&.casecmp("footnote")&.zero?
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(a, i)
85
- a["style"] = "mso-footnote-id:ftn#{i}"
86
- a["href"] = "#_ftn#{i}"
87
- a["name"] = "_ftnref#{i}"
88
- a["title"] = ""
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
@@ -1,3 +1,3 @@
1
1
  module Html2Doc
2
- VERSION = "1.0.5".freeze
2
+ VERSION = "1.1.1".freeze
3
3
  end
@@ -1,270 +1,276 @@
1
1
  require "base64"
2
2
 
3
- def html_input(x)
3
+ def html_input(xml)
4
4
  <<~HTML
5
- <html><head><title>blank</title>
6
- <meta name="Originator" content="Me"/>
7
- </head>
8
- <body>
9
- #{x}
10
- </body></html>
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(x)
14
+ def html_input_no_title(xml)
15
15
  <<~HTML
16
- <html><head>
17
- <meta name="Originator" content="Me"/>
18
- </head>
19
- <body>
20
- #{x}
21
- </body></html>
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(x)
25
+ def html_input_empty_head(xml)
26
26
  <<~HTML
27
- <html><head></head>
28
- <body>
29
- #{x}
30
- </body></html>
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-Location: file:///C:/Doc/test.htm
40
- Content-Type: text/html; charset="utf-8"
41
-
42
- <?xml version="1.0"?>
43
- <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]>
44
- <xml>
45
- <w:WordDocument>
46
- <w:View>Print</w:View>
47
- <w:Zoom>100</w:Zoom>
48
- <w:DoNotOptimizeForBrowser/>
49
- </w:WordDocument>
50
- </xml>
51
- <![endif]-->
52
- <meta http-equiv=Content-Type content="text/html; charset=utf-8"/>
53
-
54
- <link rel=File-List href="test_files/filelist.xml"/>
55
- <title>blank</title><style><![CDATA[
56
- <!--
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
+ <!--
57
58
  HDR
58
59
 
59
- WORD_HDR_END = <<~HDR
60
- -->
61
- ]]></style>
62
- <meta name="Originator" content="Me"/>
63
- </head>
60
+ WORD_HDR_END = <<~HDR.freeze
61
+ -->
62
+ ]]></style>
63
+ <meta name="Originator" content="Me"/>
64
+ </head>
64
65
  HDR
65
66
 
66
67
  def word_body(x, fn)
67
68
  <<~BODY
68
- <body>
69
- #{x}
70
- #{fn}</body></html>
69
+ <body>
70
+ #{x}
71
+ #{fn}</body></html>
71
72
  BODY
72
73
  end
73
74
 
74
- WORD_FTR1 = <<~FTR
75
+ WORD_FTR1 = <<~FTR.freeze
75
76
  ------=_NextPart_
76
- Content-Location: file:///C:/Doc/test_files/filelist.xml
77
- Content-Transfer-Encoding: base64
78
- 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')}
79
81
 
80
- PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
81
- ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9ImZp
82
- bGVsaXN0LnhtbCIvPgo8L3htbD4K
82
+ PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
83
+ ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9ImZp
84
+ bGVsaXN0LnhtbCIvPgo8L3htbD4K
83
85
 
84
- ------=_NextPart_--
86
+ ------=_NextPart_--
85
87
  FTR
86
88
 
87
- 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==
88
98
  ------=_NextPart_
89
- Content-Location: file:///C:/Doc/test_files/filelist.xml
90
- Content-Transfer-Encoding: base64
91
- Content-Type: #{Html2Doc::mime_type('filelist.xml')}
92
- PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
93
- ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9ImZp
94
- bGVsaXN0LnhtbCIvPgogIDxvOkZpbGUgSFJlZj0iaGVhZGVyLmh0bWwiLz4KPC94bWw+Cg==
95
- ------=_NextPart_
96
99
  FTR
97
100
 
98
- WORD_FTR3 = <<~FTR
99
- ------=_NextPart_
100
- Content-Location: file:///C:/Doc/test_files/filelist.xml
101
- Content-Transfer-Encoding: base64
102
- Content-Type: #{Html2Doc::mime_type('filelist.xml')}
103
-
104
- PHhtbCB4bWxuczpvPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpvZmZpY2UiPgog
105
- ICAgICAgIDxvOk1haW5GaWxlIEhSZWY9Ii4uL3Rlc3QuaHRtIi8+ICA8bzpGaWxlIEhSZWY9IjFh
106
- YzIwNjVmLTAzZjAtNGM3YS1iOWE2LTkyZTgyMDU5MWJmMC5wbmciLz4KICA8bzpGaWxlIEhSZWY9
107
- ImZpbGVsaXN0LnhtbCIvPgo8L3htbD4K
108
- ------=_NextPart_
109
- Content-Location: file:///C:/Doc/test_files/cb7b0d19-891e-4634-815a-570d019d454c.png
110
- Content-Transfer-Encoding: base64
111
- Content-Type: image/png
112
- ------=_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_--
113
118
  FTR
114
119
 
115
- HEADERHTML = <<~FTR
116
- <html xmlns:v="urn:schemas-microsoft-com:vml"
117
- xmlns:o="urn:schemas-microsoft-com:office:office"
118
- xmlns:w="urn:schemas-microsoft-com:office:word"
119
- xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
120
- xmlns:mv="http://macVmlSchemaUri" xmlns="http://www.w3.org/TR/REC-html40">
121
- <head>
122
- <meta name=Title content="">
123
- <meta name=Keywords content="">
124
- <meta http-equiv=Content-Type content="text/html; charset=utf-8">
125
- <meta name=ProgId content=Word.Document>
126
- <meta name=Generator content="Microsoft Word 15">
127
- <meta name=Originator content="Microsoft Word 15">
128
- <link id=Main-File rel=Main-File href="FILENAME.html">
129
- <!--[if gte mso 9]><xml>
130
- <o:shapedefaults v:ext="edit" spidmax="2049"/>
131
- </xml><![endif]-->
132
- </head>
133
- <body lang=EN link=blue vlink="#954F72">
134
- <div style='mso-element:footnote-separator' id=fs>
135
- <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
136
- normal'><span lang=EN-GB><span style='mso-special-character:footnote-separator'><![if !supportFootnotes]>
137
- <hr align=left size=1 width="33%">
138
- <![endif]></span></span></p>
139
- </div>
140
- <div style='mso-element:footnote-continuation-separator' id=fcs>
141
- <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
142
- normal'><span lang=EN-GB><span style='mso-special-character:footnote-continuation-separator'><![if !supportFootnotes]>
143
- <hr align=left size=1>
144
- <![endif]></span></span></p>
145
- </div>
146
- <div style='mso-element:endnote-separator' id=es>
147
- <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
148
- normal'><span lang=EN-GB><span style='mso-special-character:footnote-separator'><![if !supportFootnotes]>
149
- <hr align=left size=1 width="33%">
150
- <![endif]></span></span></p>
151
- </div>
152
- <div style='mso-element:endnote-continuation-separator' id=ecs>
153
- <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height:
154
- normal'><span lang=EN-GB><span style='mso-special-character:footnote-continuation-separator'><![if !supportFootnotes]>
155
- <hr align=left size=1>
156
- <![endif]></span></span></p>
157
- </div>
158
- <div style='mso-element:header' id=eh1>
159
- <p class=MsoHeader align=left style='text-align:left;line-height:12.0pt;
160
- mso-line-height-rule:exactly'><span lang=EN-GB>ISO/IEC&#x26;nbsp;CD 17301-1:2016(E)</span></p>
161
- </div>
162
- <div style='mso-element:header' id=h1>
163
- <p class=MsoHeader style='margin-bottom:18.0pt'><span lang=EN-GB
164
- style='font-size:10.0pt;mso-bidi-font-size:11.0pt;font-weight:normal'>&#xa9;
165
- ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; All rights reserved</span><span lang=EN-GB
166
- style='font-weight:normal'><o:p></o:p></span></p>
167
- </div>
168
- <div style='mso-element:footer' id=ef1>
169
- <p class=MsoFooter style='margin-top:12.0pt;line-height:12.0pt;mso-line-height-rule:
170
- exactly'><!--[if supportFields]><b style='mso-bidi-font-weight:normal'><span
171
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
172
- style='mso-element:field-begin'></span><span
173
- style='mso-spacerun:yes'>&#xa0;</span>PAGE<span style='mso-spacerun:yes'>&#xa0;&#xa0;
174
- </span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span></b><![endif]--><b
175
- style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
176
- mso-bidi-font-size:11.0pt'><span style='mso-no-proof:yes'>2</span></span></b><!--[if supportFields]><b
177
- style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
178
- mso-bidi-font-size:11.0pt'><span style='mso-element:field-end'></span></span></b><![endif]--><span
179
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
180
- style='mso-tab-count:1'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span>&#xa9;
181
- ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; All rights reserved<o:p></o:p></span></p>
182
- </div>
183
- <div style='mso-element:header' id=eh2>
184
- <p class=MsoHeader align=left style='text-align:left;line-height:12.0pt;
185
- mso-line-height-rule:exactly'><span lang=EN-GB>ISO/IEC&#x26;nbsp;CD 17301-1:2016(E)</span></p>
186
- </div>
187
- <div style='mso-element:header' id=h2>
188
- <p class=MsoHeader align=right style='text-align:right;line-height:12.0pt;
189
- mso-line-height-rule:exactly'><span lang=EN-GB>ISO/IEC&#x26;nbsp;CD 17301-1:2016(E)</span></p>
190
- </div>
191
- <div style='mso-element:footer' id=ef2>
192
- <p class=MsoFooter style='line-height:12.0pt;mso-line-height-rule:exactly'><!--[if supportFields]><span
193
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
194
- style='mso-element:field-begin'></span><span
195
- style='mso-spacerun:yes'>&#xa0;</span>PAGE<span style='mso-spacerun:yes'>&#xa0;&#xa0;
196
- </span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span><![endif]--><span
197
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
198
- style='mso-no-proof:yes'>ii</span></span><!--[if supportFields]><span
199
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
200
- style='mso-element:field-end'></span></span><![endif]--><span lang=EN-GB
201
- style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span style='mso-tab-count:
202
- 1'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span>&#xa9;
203
- ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; All rights reserved<o:p></o:p></span></p>
204
- </div>
205
- <div style='mso-element:footer' id=f2>
206
- <p class=MsoFooter style='line-height:12.0pt'><span lang=EN-GB
207
- style='font-size:10.0pt;mso-bidi-font-size:11.0pt'>&#xa9; ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; All
208
- rights reserved<span style='mso-tab-count:1'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span></span><!--[if supportFields]><span
209
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
210
- style='mso-element:field-begin'></span> PAGE<span style='mso-spacerun:yes'>&#xa0;&#xa0;
211
- </span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span><![endif]--><span
212
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
213
- style='mso-no-proof:yes'>iii</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-end'></span></span><![endif]--><span lang=EN-GB
216
- style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><o:p></o:p></span></p>
217
- </div>
218
- <div style='mso-element:footer' id=ef3>
219
- <p class=MsoFooter style='margin-top:12.0pt;line-height:12.0pt;mso-line-height-rule:
220
- exactly'><!--[if supportFields]><b style='mso-bidi-font-weight:normal'><span
221
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
222
- style='mso-element:field-begin'></span><span
223
- style='mso-spacerun:yes'>&#xa0;</span>PAGE<span style='mso-spacerun:yes'>&#xa0;&#xa0;
224
- </span>\\* MERGEFORMAT <span style='mso-element:field-separator'></span></span></b><![endif]--><b
225
- style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
226
- mso-bidi-font-size:11.0pt'><span style='mso-no-proof:yes'>2</span></span></b><!--[if supportFields]><b
227
- style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
228
- mso-bidi-font-size:11.0pt'><span style='mso-element:field-end'></span></span></b><![endif]--><span
229
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><span
230
- style='mso-tab-count:1'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span>&#xa9;
231
- ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; All rights reserved<o:p></o:p></span></p>
232
- </div>
233
- <div style='mso-element:footer' id=f3>
234
- <p class=MsoFooter style='line-height:12.0pt'><span lang=EN-GB
235
- style='font-size:10.0pt;mso-bidi-font-size:11.0pt'>&#xa9; ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; All
236
- rights reserved<span style='mso-tab-count:1'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span></span><!--[if supportFields]><b
237
- style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
238
- mso-bidi-font-size:11.0pt'><span style='mso-element:field-begin'></span>
239
- PAGE<span style='mso-spacerun:yes'>&#xa0;&#xa0; </span>\\* MERGEFORMAT <span
240
- style='mso-element:field-separator'></span></span></b><![endif]--><b
241
- style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
242
- mso-bidi-font-size:11.0pt'><span style='mso-no-proof:yes'>3</span></span></b><!--[if supportFields]><b
243
- style='mso-bidi-font-weight:normal'><span lang=EN-GB style='font-size:10.0pt;
244
- mso-bidi-font-size:11.0pt'><span style='mso-element:field-end'></span></span></b><![endif]--><span
245
- lang=EN-GB style='font-size:10.0pt;mso-bidi-font-size:11.0pt'><o:p></o:p></span></p>
246
- </div>
247
- </body>
248
- </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&#x26;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'>&#xa9;
170
+ ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; 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'>&#xa0;</span>PAGE<span style='mso-spacerun:yes'>&#xa0;&#xa0;
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'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span>&#xa9;
186
+ ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; 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&#x26;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&#x26;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'>&#xa0;</span>PAGE<span style='mso-spacerun:yes'>&#xa0;&#xa0;
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'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span>&#xa9;
208
+ ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; 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'>&#xa9; ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; All
213
+ rights reserved<span style='mso-tab-count:1'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </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'>&#xa0;&#xa0;
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'>&#xa0;</span>PAGE<span style='mso-spacerun:yes'>&#xa0;&#xa0;
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'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span>&#xa9;
236
+ ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; 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'>&#xa9; ISO/IEC&#x26;nbsp;2016&#x26;nbsp;&#x2013; All
241
+ rights reserved<span style='mso-tab-count:1'>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </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'>&#xa0;&#xa0; </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>
249
254
  FTR
250
255
 
251
- ASCII_MATH='<m:nary><m:naryPr><m:chr m:val="&#x2211;"></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="&#x2211;"></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
252
257
 
253
- DEFAULT_STYLESHEET = File.read("lib/html2doc/wordstyle.css", encoding: "utf-8").freeze
258
+ DEFAULT_STYLESHEET = File.read("lib/html2doc/wordstyle.css",
259
+ encoding: "utf-8").freeze
254
260
 
255
- def guid_clean(x)
256
- x.gsub(/NextPart_[0-9a-f.]+/, "NextPart_")
261
+ def guid_clean(xml)
262
+ xml.gsub(/NextPart_[0-9a-f.]+/, "NextPart_")
257
263
  end
258
264
 
259
- def image_clean(x)
260
- x.gsub(%r{[0-9a-f-]+\.png}, "image.png").
261
- gsub(%r{[0-9a-f-]+\.gif}, "image.gif").
262
- gsub(%r{[0-9a-f-]+\.(jpeg|jpg)}, "image.jpg").
263
- gsub(%r{------=_NextPart_\s+Content-Location: file:///C:/Doc/test_files/image\.(png|gif).*?\s-----=_NextPart_}m, "------=_NextPart_").
264
- gsub(%r{Content-Type: image/(png|gif|jpeg)[^-]*------=_NextPart_-?-?}m, "").
265
- gsub(%r{ICAgICAg[^-]*-----}m, "-----").
266
- gsub(%r{\s*</img>\s*}m, "</img>").
267
- 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>")
268
274
  end
269
275
 
270
276
  RSpec.describe Html2Doc do
@@ -274,11 +280,11 @@ RSpec.describe Html2Doc do
274
280
 
275
281
  it "processes a blank document" do
276
282
  Html2Doc.process(html_input(""), filename: "test")
277
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
278
- to match_fuzzy(<<~OUTPUT)
279
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
280
- #{word_body("", '<div style="mso-element:footnote-list"/>')} #{WORD_FTR1}
281
- OUTPUT
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
282
288
  end
283
289
 
284
290
  it "removes any temp files" do
@@ -290,57 +296,59 @@ RSpec.describe Html2Doc do
290
296
  end
291
297
 
292
298
  it "processes a stylesheet in an HTML document with a title" do
293
- Html2Doc.process(html_input(""), filename: "test", stylesheet: "lib/html2doc/wordstyle.css")
294
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
295
- to match_fuzzy(<<~OUTPUT)
296
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
297
- #{word_body("", '<div style="mso-element:footnote-list"/>')} #{WORD_FTR1}
298
- OUTPUT
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
299
306
  end
300
307
 
301
308
  it "processes a stylesheet in an HTML document without a title" do
302
- Html2Doc.process(html_input_no_title(""), filename: "test", stylesheet: "lib/html2doc/wordstyle.css")
303
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
304
- to match_fuzzy(<<~OUTPUT)
305
- #{WORD_HDR.sub("<title>blank</title>", "")}
306
- #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
307
- #{word_body("", '<div style="mso-element:footnote-list"/>')} #{WORD_FTR1}
308
- OUTPUT
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
309
317
  end
310
318
 
311
319
  it "processes a stylesheet in an HTML document with an empty head" do
312
320
  Html2Doc.process(html_input_empty_head(""), filename: "test", stylesheet: "lib/html2doc/wordstyle.css")
313
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
314
- to match_fuzzy(<<~OUTPUT)
315
- #{WORD_HDR.sub("<title>blank</title>", "")}
316
- #{DEFAULT_STYLESHEET}
317
- #{WORD_HDR_END.sub('<meta name="Originator" content="Me"/>'+"\n", "").sub("</style>\n</head>", "</style></head>")}
318
- #{word_body("", '<div style="mso-element:footnote-list"/>')} #{WORD_FTR1}
319
- OUTPUT
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
320
328
  end
321
329
 
322
330
  it "processes a header" do
323
331
  Html2Doc.process(html_input(""), filename: "test", header_file: "spec/header.html")
324
332
  html = guid_clean(File.read("test.doc", encoding: "utf-8"))
325
- hdr = Base64.decode64(html.sub(%r{^.*Content-Location: file:///C:/Doc/test_files/header.html}, "").
326
- sub(%r{^.*Content-Type: text/html charset="utf-8"}m, "").
327
- sub(%r{------=_NextPart_--.*$}m, "")).force_encoding("UTF-8")
328
- #expect(hdr.gsub(/\xa0/, " ")).to match_fuzzy(HEADERHTML)
329
- expect(HTMLEntities.new.encode(hdr, :hexadecimal).
330
- gsub(/\&#x3c;/, "<").gsub(/\&#x3e;/, ">").gsub(/\&#x27;/, "'").gsub(/\&#x22;/, '"').
331
- gsub(/\&#xd;/, "&#xa;").gsub(/\&#xa;/, "\n")).to match_fuzzy(HEADERHTML)
332
- expect(html.sub(%r{Content-Location: file:///C:/Doc/test_files/header.html.*$}m, "")).
333
- to match_fuzzy(<<~OUTPUT)
334
- #{WORD_HDR} #{DEFAULT_STYLESHEET.gsub(/FILENAME/, "test")}
335
- #{WORD_HDR_END} #{word_body("", '<div style="mso-element:footnote-list"/>')} #{WORD_FTR2}
336
- OUTPUT
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(/&#x3c;/, "<").gsub(/&#x3e;/, ">").gsub(/&#x27;/, "'").gsub(/&#x22;/, '"')
339
+ .gsub(/&#xd;/, "&#xa;").gsub(/&#xa;/, "\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
337
345
  end
338
346
 
339
347
  it "processes a header with an image" do
340
348
  Html2Doc.process(html_input(""), filename: "test", header_file: "spec/header_img.html")
341
349
  doc = guid_clean(File.read("test.doc", encoding: "utf-8"))
342
350
  expect(doc).to match(%r{Content-Type: image/png})
343
- expect(doc).to match(%r{file:///C:/Doc/test_files/[^.]+\.png})
351
+ expect(doc).to match(%r{iVBORw0KGgoAAAANSUhEUgAAA5cAAAN7CAYAAADRE24cAAAgAElEQVR4XuydB5gUxdaGC65gTogB})
344
352
  end
345
353
 
346
354
  it "processes a header with an image with absolute path" do
@@ -351,130 +359,152 @@ RSpec.describe Html2Doc do
351
359
  Html2Doc.process(html_input(""), filename: "test", header_file: "spec/header_img1.html")
352
360
  doc = guid_clean(File.read("test.doc", encoding: "utf-8"))
353
361
  expect(doc).to match(%r{Content-Type: image/png})
354
- expect(doc).to match(%r{file:///C:/Doc/test_files/[^.]+\.png})
362
+ expect(doc).to match(%r{iVBORw0KGgoAAAANSUhEUgAAA5cAAAN7CAYAAADRE24cAAAgAElEQVR4XuydB5gUxdaGC65gTogB})
355
363
  end
356
364
 
357
-
358
365
  it "processes a populated document" do
359
366
  simple_body = "<h1>Hello word!</h1>
360
367
  <div>This is a very simple document</div>"
361
368
  Html2Doc.process(html_input(simple_body), filename: "test")
362
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
363
- to match_fuzzy(<<~OUTPUT)
364
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
365
- #{word_body(simple_body, '<div style="mso-element:footnote-list"/>')}
366
- #{WORD_FTR1}
367
- OUTPUT
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
368
375
  end
369
376
 
370
377
  it "processes AsciiMath" do
371
378
  Html2Doc.process(html_input(%[<div>{{sum_(i=1)^n i^3=((n(n+1))/2)^2 text("integer"))}}</div>]), filename: "test", asciimathdelims: ["{{", "}}"])
372
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
373
- to match_fuzzy(<<~OUTPUT)
374
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
375
- #{word_body(%{
376
- <div><m:oMath>
377
- <m:nary><m:naryPr><m:chr m:val="&#x2211;"></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>
378
- </m:oMath>
379
- </div>}, '<div style="mso-element:footnote-list"/>')}
380
- #{WORD_FTR1}
381
- OUTPUT
382
- end
383
-
384
- it "processes mstyle" do
385
- Html2Doc.process(html_input(%[<div>{{bb (-log_2 (p_u)) bb "AA" bbb "AA" cc "AA" tt "AA" fr "AA" sf "AA" ii "AA"}}</div>]), filename: "test", asciimathdelims: ["{{", "}}"])
386
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
387
- to match_fuzzy(<<~OUTPUT)
388
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
389
- #{word_body(%{
390
- <div><m:oMath>
391
- <span style="font-style:normal;font-weight:bold;"><m:r><m:rPr><m:sty m:val="b"></m:sty></m:rPr><m:t>&#x2212;</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>AA</m:t></m:r></span><span style="font-style:normal;"><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>AA</m:t></m:r></span><m:r><m:rPr><m:nor></m:nor><m:scr m:val="script"></m:scr></m:rPr><m:t>AA</m:t></m:r><m:r><m:rPr><m:nor></m:nor></m:rPr><m:t>AA</m:t></m:r><span style="font-style:normal;"><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>AA</m:t></m:r></span><span style="font-style:normal;"><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>AA</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>AA</m:t></m:r></span>
392
- </m:oMath>
393
- </div>}, '<div style="mso-element:footnote-list"/>')}
394
- #{WORD_FTR1}
395
- OUTPUT
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="&#x2211;"></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
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: ["{{", "}}"])
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>&#x2212;</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>&#x1D539;&#x1D539;&#x1D539;</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="script"></m:scr></m:rPr><m:t>&#x1D49E;&#x1D49E;</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>&#x1D4D1;&#x1D4D2;&#x1D4D2;</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>&#x1D683;&#x1D683;</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>&#x1D509;&#x211C;</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>&#x1D56D;&#x1D571;&#x1D57D;</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>&#x1D5B2;&#x1D5A5;</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>&#x1D5D5;&#x1D5E6;&#x1D5D9;&#x1D770;</m:t></m:r><m:r><m:rPr><m:nor></m:nor><m:scr m:val="sans-serif"></m:scr></m:rPr><m:t>&#x1D5B2;&#x1D5A5;&#x1D5A8;</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>&#x1D64E;&#x1D641;&#x1D63D;&#x1D644;&#x1D7AA;</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
396
403
  end
397
404
 
398
405
  it "processes spaces in AsciiMath" do
399
406
  Html2Doc.process(html_input(%[<div>{{text " integer ")}}</div>]), filename: "test", asciimathdelims: ["{{", "}}"])
400
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
401
- to match_fuzzy(<<~OUTPUT)
402
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
403
- #{word_body('
404
- <div><m:oMath>
405
- <m:r><m:t>text</m:t></m:r><m:r><m:rPr><m:nor></m:nor></m:rPr><m:t>&#xA0;integer&#xA0;</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>
406
- </m:oMath>
407
- </div>', '<div style="mso-element:footnote-list"/>')}
408
- #{WORD_FTR1}
409
- OUTPUT
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>&#xA0;integer&#xA0;</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
410
417
  end
411
418
 
412
419
  it "processes spaces in MathML mtext" do
413
420
  Html2Doc.process(html_input("<div><math xmlns='http://www.w3.org/1998/Math/MathML'>
414
421
  <mrow><mi>H</mi><mtext> original </mtext><mi>J</mi></mrow>
415
422
  </math></div>"), filename: "test", asciimathdelims: ["{{", "}}"])
416
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
417
- to match_fuzzy(<<~OUTPUT)
418
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
419
- #{word_body('<div><m:oMath>
420
- <m:r><m:t>H</m:t></m:r><m:r><m:rPr><m:nor></m:nor></m:rPr><m:t>&#xA0;original&#xA0;</m:t></m:r><m:r><m:t>J</m:t></m:r>
421
- </m:oMath>
422
- </div>', '<div style="mso-element:footnote-list"/>')}
423
- #{WORD_FTR1}
424
- OUTPUT
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>&#xA0;original&#xA0;</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
432
+ end
433
+
434
+ it "unwraps accent in MathML" do
435
+ Html2Doc.process(html_input("<div><math xmlns='http://www.w3.org/1998/Math/MathML'>
436
+ <mover accent='true'><mrow><mi>p</mi></mrow><mrow><mo>^</mo></mrow></mover>
437
+ </math></div>"), filename: "test", asciimathdelims: ["{{", "}}"])
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
425
447
  end
426
448
 
427
449
  it "left-aligns AsciiMath" do
428
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: ["{{", "}}"])
429
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
430
- to match_fuzzy(<<~OUTPUT)
431
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
432
- #{word_body(%{
433
- <div style="text-align:left;"><m:oMathPara><m:oMathParaPr><m:jc m:val="left"/></m:oMathParaPr><m:oMath>
434
- <m:nary><m:naryPr><m:chr m:val="&#x2211;"></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>
435
- </m:oMath>
436
- </m:oMathPara></div>}, '<div style="mso-element:footnote-list"/>')}
437
- #{WORD_FTR1}
438
- OUTPUT
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="&#x2211;"></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
439
461
  end
440
462
 
441
463
  it "right-aligns AsciiMath" do
442
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: ["{{", "}}"])
443
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
444
- to match_fuzzy(<<~OUTPUT)
445
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
446
- #{word_body(%{
447
- <div style="text-align:right;"><m:oMathPara><m:oMathParaPr><m:jc m:val="right"/></m:oMathParaPr><m:oMath>
448
- <m:nary><m:naryPr><m:chr m:val="&#x2211;"></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>
449
- </m:oMath>
450
- </m:oMathPara></div>}, '<div style="mso-element:footnote-list"/>')}
451
- #{WORD_FTR1}
452
- OUTPUT
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="&#x2211;"></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
475
+ end
476
+
477
+ it "raises error in processing of broken AsciiMath" do
478
+ begin
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
480
+ rescue StandardError
481
+ end
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)
453
483
  end
454
484
 
455
485
  it "wraps msup after munderover in MathML" do
456
486
  Html2Doc.process(html_input("<div><math xmlns='http://www.w3.org/1998/Math/MathML'>
457
487
  <munderover><mo>&#x2211;</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: ["{{", "}}"])
458
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
459
- to match_fuzzy(<<~OUTPUT)
460
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
461
- #{word_body('<div><m:oMath>
462
- <m:nary><m:naryPr><m:chr m:val="&#x2211;"></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>
463
- </div>', '<div style="mso-element:footnote-list"/>')}
464
- #{WORD_FTR1}
465
- OUTPUT
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="&#x2211;"></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
466
496
  end
467
497
 
468
498
  it "processes tabs" do
469
499
  simple_body = "<h1>Hello word!</h1>
470
500
  <div>This is a very &tab; simple document</div>"
471
501
  Html2Doc.process(html_input(simple_body), filename: "test")
472
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
473
- to match_fuzzy(<<~OUTPUT)
474
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
475
- #{word_body(simple_body.gsub(/\&tab;/, %[<span style="mso-tab-count:1">&#xA0; </span>]), '<div style="mso-element:footnote-list"/>')}
476
- #{WORD_FTR1}
477
- OUTPUT
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">&#xA0; </span>]), '<div style="mso-element:footnote-list"/>')}
506
+ #{WORD_FTR1}
507
+ OUTPUT
478
508
  end
479
509
 
480
510
  it "makes unstyled paragraphs be MsoNormal" do
@@ -482,12 +512,12 @@ RSpec.describe Html2Doc do
482
512
  <p>This is a very simple document</p>
483
513
  <p class="x">This style stays</p>'
484
514
  Html2Doc.process(html_input(simple_body), filename: "test")
485
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
486
- to match_fuzzy(<<~OUTPUT)
487
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
488
- #{word_body(simple_body.gsub(/<p>/, %[<p class="MsoNormal">]), '<div style="mso-element:footnote-list"/>')}
489
- #{WORD_FTR1}
490
- OUTPUT
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
491
521
  end
492
522
 
493
523
  it "makes unstyled list entries be MsoNormal" do
@@ -497,12 +527,12 @@ RSpec.describe Html2Doc do
497
527
  <li class="x">This style stays</li>
498
528
  </ul>'
499
529
  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
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
503
- #{word_body(simple_body.gsub(/<li>/, %[<li class="MsoNormal">]), '<div style="mso-element:footnote-list"/>')}
504
- #{WORD_FTR1}
505
- OUTPUT
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
506
536
  end
507
537
 
508
538
  it "resizes images for height, in a file in a subdirectory" do
@@ -511,9 +541,9 @@ RSpec.describe Html2Doc do
511
541
  testdoc = File.read("spec/test.doc", encoding: "utf-8")
512
542
  expect(testdoc).to match(%r{Content-Type: image/png})
513
543
  expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
514
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
515
- #{image_clean(word_body('<img src="test_files/cb7b0d19-891e-4634-815a-570d019d454c.png" width="400" height="388"></img>', '<div style="mso-element:footnote-list"/>'))}
516
- #{image_clean(WORD_FTR3)}
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)}
517
547
  OUTPUT
518
548
  end
519
549
 
@@ -523,9 +553,9 @@ RSpec.describe Html2Doc do
523
553
  testdoc = File.read("test.doc", encoding: "utf-8")
524
554
  expect(testdoc).to match(%r{Content-Type: image/gif})
525
555
  expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
526
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
527
- #{image_clean(word_body('<img src="test_files/cb7b0d19-891e-4634-815a-570d019d454c.gif" width="400" height="118"></img>', '<div style="mso-element:footnote-list"/>'))}
528
- #{image_clean(WORD_FTR3).gsub(/image\.png/, "image.gif")}
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')}
529
559
  OUTPUT
530
560
  end
531
561
 
@@ -535,9 +565,9 @@ RSpec.describe Html2Doc do
535
565
  testdoc = File.read("test.doc", encoding: "utf-8")
536
566
  expect(testdoc).to match(%r{Content-Type: image/jpeg})
537
567
  expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
538
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
539
- #{image_clean(word_body('<img src="test_files/cb7b0d19-891e-4634-815a-570d019d454c.jpg" width="208" height="680"></img>', '<div style="mso-element:footnote-list"/>'))}
540
- #{image_clean(WORD_FTR3).gsub(/image\.png/, "image.jpg")}
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')}
541
571
  OUTPUT
542
572
  end
543
573
 
@@ -577,49 +607,47 @@ RSpec.describe Html2Doc do
577
607
  Html2Doc.process(html_input(simple_body), filename: "test")
578
608
  testdoc = File.read("test.doc", encoding: "utf-8")
579
609
  expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
580
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
581
- #{image_clean(word_body('<img src="https://example.com/19160-6.png"></img>', '<div style="mso-element:footnote-list"/>'))}
582
- #{image_clean(WORD_FTR1)}
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)}
583
613
  OUTPUT
584
614
  end
585
615
 
586
616
  it "deals with absolute image locations" do
587
- simple_body = %{<img src="#{File.expand_path(File.dirname(__FILE__))}/19160-6.png">}
617
+ simple_body = %{<img src="#{__dir__}/19160-6.png">}
588
618
  Html2Doc.process(html_input(simple_body), filename: "spec/test")
589
619
  testdoc = File.read("spec/test.doc", encoding: "utf-8")
590
620
  expect(testdoc).to match(%r{Content-Type: image/png})
591
621
  expect(image_clean(guid_clean(testdoc))).to match_fuzzy(<<~OUTPUT)
592
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
593
- #{image_clean(word_body('<img src="test_files/cb7b0d19-891e-4634-815a-570d019d454c.png" width="400" height="388"></img>', '<div style="mso-element:footnote-list"/>'))}
594
- #{image_clean(WORD_FTR3)}
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)}
595
625
  OUTPUT
596
626
  end
597
627
 
598
- =begin
599
- it "warns about SVG" do
600
- simple_body = '<img src="https://example.com/19160-6.svg">'
601
- expect{ Html2Doc.process(html_input(simple_body), filename: "test") }.to output("https://example.com/19160-6.svg: SVG not supported\n").to_stderr
602
- end
603
- =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
604
632
 
605
633
  it "processes epub:type footnotes" do
606
- simple_body = '<div>This is a very simple
634
+ simple_body = '<div>This is a very simple
607
635
  document<a epub:type="footnote" href="#a1">1</a> allegedly<a epub:type="footnote" href="#a2">2</a></div>
608
636
  <aside id="a1">Footnote</aside>
609
637
  <aside id="a2">Other Footnote</aside>'
610
638
  Html2Doc.process(html_input(simple_body), filename: "test")
611
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
612
- to match_fuzzy(<<~OUTPUT)
613
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
614
- #{word_body('<div>This is a very simple
615
- 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>',
616
- '<div style="mso-element:footnote-list"><div style="mso-element:footnote" id="ftn1">
617
- <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>
618
- <div style="mso-element:footnote" id="ftn2">
619
- <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>
620
- </div>')}
621
- #{WORD_FTR1}
622
- OUTPUT
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
623
651
  end
624
652
 
625
653
  it "processes class footnotes" do
@@ -628,38 +656,38 @@ RSpec.describe Html2Doc do
628
656
  <aside id="a1">Footnote</aside>
629
657
  <aside id="a2">Other Footnote</aside>'
630
658
  Html2Doc.process(html_input(simple_body), filename: "test")
631
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
632
- to match_fuzzy(<<~OUTPUT)
633
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
634
- #{word_body('<div>This is a very simple
635
- 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>',
636
- '<div style="mso-element:footnote-list"><div style="mso-element:footnote" id="ftn1">
637
- <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>
638
- <div style="mso-element:footnote" id="ftn2">
639
- <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>
640
- </div>')}
641
- #{WORD_FTR1}
642
- OUTPUT
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
643
671
  end
644
672
 
645
673
  it "processes footnotes with text wrapping the footnote reference" do
646
- simple_body = '<div>This is a very simple
674
+ simple_body = '<div>This is a very simple
647
675
  document<a class="footnote" href="#a1">(<span class="MsoFootnoteReference">1</span>)</a> allegedly<a class="footnote" href="#a2">2</a></div>
648
676
  <aside id="a1">Footnote</aside>
649
677
  <aside id="a2">Other Footnote</aside>'
650
678
  Html2Doc.process(html_input(simple_body), filename: "test")
651
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
652
- to match_fuzzy(<<~OUTPUT)
653
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
654
- #{word_body('<div>This is a very simple
655
- 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>',
656
- '<div style="mso-element:footnote-list"><div style="mso-element:footnote" id="ftn1">
657
- <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>
658
- <div style="mso-element:footnote" id="ftn2">
659
- <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>
660
- </div>')}
661
- #{WORD_FTR1}
662
- OUTPUT
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
663
691
  end
664
692
 
665
693
  it "extracts paragraphs from footnotes" do
@@ -668,18 +696,18 @@ RSpec.describe Html2Doc do
668
696
  <aside id="a1"><p>Footnote</p></aside>
669
697
  <div id="a2"><p>Other Footnote</p></div>'
670
698
  Html2Doc.process(html_input(simple_body), filename: "test")
671
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
672
- to match_fuzzy(<<~OUTPUT)
673
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
674
- #{word_body('<div>This is a very simple
675
- 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>',
676
- '<div style="mso-element:footnote-list"><div style="mso-element:footnote" id="ftn1">
677
- <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>
678
- <div style="mso-element:footnote" id="ftn2">
679
- <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>
680
- </div>')}
681
- #{WORD_FTR1}
682
- OUTPUT
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
683
711
  end
684
712
 
685
713
  it "labels lists with list styles" do
@@ -687,38 +715,37 @@ RSpec.describe Html2Doc do
687
715
  <div><ul id="0">
688
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>
689
717
  BODY
690
- Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2"})
691
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
692
- to match_fuzzy(<<~OUTPUT)
693
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
694
- #{word_body('<div>
695
- <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>
696
- </div>',
697
- '<div style="mso-element:footnote-list"/>')}
698
- #{WORD_FTR1}
699
- OUTPUT
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
700
728
  end
701
729
 
702
-
703
730
  it "restarts numbering of lists with list styles" do
704
731
  simple_body = <<~BODY
705
732
  <div>
706
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>
707
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>
708
735
  BODY
709
- Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2"})
710
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
711
- to match_fuzzy(<<~OUTPUT)
712
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
713
- #{word_body('<div>
714
- <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>
715
- <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>',
716
- '<div style="mso-element:footnote-list"/>')}
717
- #{WORD_FTR1}
718
- OUTPUT
719
- end
720
-
721
- it "labels lists with multiple list styles" do
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
722
749
  simple_body = <<~BODY
723
750
  <div><ul class="steps" id="0">
724
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>
@@ -727,19 +754,19 @@ RSpec.describe Html2Doc do
727
754
  <div><ul class="other" id="10">
728
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>
729
756
  BODY
730
- Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2", steps: "l3"})
731
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
732
- to match_fuzzy(<<~OUTPUT)
733
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
734
- #{word_body('<div>
735
- <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>
736
- <div>
737
- <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>
738
- <div>
739
- <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>',
740
- '<div style="mso-element:footnote-list"/>')}
741
- #{WORD_FTR1}
742
- OUTPUT
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
743
770
  end
744
771
 
745
772
  it "replaces id attributes with explicit a@name bookmarks" do
@@ -749,17 +776,17 @@ RSpec.describe Html2Doc do
749
776
  <p id="b"/>
750
777
  </div>
751
778
  BODY
752
- Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2"})
753
- expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
754
- to match_fuzzy(<<~OUTPUT)
755
- #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
756
- #{word_body('<div>
757
- <p class="MsoNormal"><a name="a" id="a"></a>Hello</p>
758
- <p class="MsoNormal"><a name="b" id="b"></a></p>
759
- </div>',
760
- '<div style="mso-element:footnote-list"/>')}
761
- #{WORD_FTR1}
762
- OUTPUT
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
763
790
  end
764
791
 
765
792
  it "test image base64 image encoding" do
@@ -767,7 +794,7 @@ RSpec.describe Html2Doc do
767
794
  Html2Doc.process(html_input(simple_body), filename: "spec/test", debug: true)
768
795
  testdoc = File.read("spec/test.doc", encoding: "utf-8")
769
796
  base64_image = testdoc[/image\/png\n\n(.*?)\n\n----/m, 1].gsub!("\n", "")
770
- base64_image_basename = testdoc[%r{Content-Location: file:///C:/Doc/test_files/([0-9a-z\-]+)\.png}m, 1]
797
+ base64_image_basename = testdoc[%r{Content-ID: <([0-9a-z\-]+)\.png}m, 1]
771
798
  doc_bin_image = Base64.strict_decode64(base64_image)
772
799
  file_bin_image = IO.read("spec/test_files/#{base64_image_basename}.png", mode: "rb")
773
800
  expect(doc_bin_image).to eq file_bin_image