metanorma-iec 0.0.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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +7 -0
  3. data/bin/rspec +18 -0
  4. data/lib/asciidoctor/iec/biblio.rng +949 -0
  5. data/lib/asciidoctor/iec/converter.rb +68 -0
  6. data/lib/asciidoctor/iec/iec_intro_en.xml +15 -0
  7. data/lib/asciidoctor/iec/iec_intro_fr.xml +15 -0
  8. data/lib/asciidoctor/iec/isodoc.rng +1132 -0
  9. data/lib/asciidoctor/iec/isostandard.rng +789 -0
  10. data/lib/asciidoctor/iec/reqt.rng +162 -0
  11. data/lib/isodoc/iec/base_convert.rb +69 -0
  12. data/lib/isodoc/iec/html/header.html +160 -0
  13. data/lib/isodoc/iec/html/html_iec_intro.html +34 -0
  14. data/lib/isodoc/iec/html/html_iec_titlepage.html +62 -0
  15. data/lib/isodoc/iec/html/htmlstyle.scss +840 -0
  16. data/lib/isodoc/iec/html/isodoc.scss +785 -0
  17. data/lib/isodoc/iec/html/scripts.html +176 -0
  18. data/lib/isodoc/iec/html/word_iec_intro.html +72 -0
  19. data/lib/isodoc/iec/html/word_iec_titlepage.html +92 -0
  20. data/lib/isodoc/iec/html/wordstyle.scss +1849 -0
  21. data/lib/isodoc/iec/html_convert.rb +33 -0
  22. data/lib/isodoc/iec/i18n-en.yaml +3 -0
  23. data/lib/isodoc/iec/i18n-fr.yaml +3 -0
  24. data/lib/isodoc/iec/i18n-zh-Hans.yaml +3 -0
  25. data/lib/isodoc/iec/metadata.rb +20 -0
  26. data/lib/isodoc/iec/word_convert.rb +165 -0
  27. data/lib/metanorma-iec.rb +12 -0
  28. data/lib/metanorma/iec.rb +8 -0
  29. data/lib/metanorma/iec/processor.rb +40 -0
  30. data/lib/metanorma/iec/version.rb +6 -0
  31. data/metanorma-iec.gemspec +47 -0
  32. data/spec/asciidoctor-iec/base_spec.rb +609 -0
  33. data/spec/asciidoctor-iec/blocks_spec.rb +467 -0
  34. data/spec/asciidoctor-iec/cleanup_spec.rb +766 -0
  35. data/spec/asciidoctor-iec/inline_spec.rb +162 -0
  36. data/spec/asciidoctor-iec/lists_spec.rb +190 -0
  37. data/spec/asciidoctor-iec/macros_spec.rb +21 -0
  38. data/spec/asciidoctor-iec/refs_spec.rb +268 -0
  39. data/spec/asciidoctor-iec/section_spec.rb +341 -0
  40. data/spec/asciidoctor-iec/table_spec.rb +307 -0
  41. data/spec/asciidoctor-iec/validate_spec.rb +132 -0
  42. data/spec/examples/rice.adoc +723 -0
  43. data/spec/examples/rice.doc +19162 -0
  44. data/spec/examples/rice.html +1787 -0
  45. data/spec/examples/rice.xml +1951 -0
  46. data/spec/isodoc/i18n_spec.rb +642 -0
  47. data/spec/isodoc/inline_spec.rb +265 -0
  48. data/spec/isodoc/iso_spec.rb +319 -0
  49. data/spec/isodoc/metadata_spec.rb +153 -0
  50. data/spec/isodoc/postproc_spec.rb +569 -0
  51. data/spec/isodoc/section_spec.rb +686 -0
  52. data/spec/isodoc/terms_spec.rb +206 -0
  53. data/spec/isodoc/xref_spec.rb +1323 -0
  54. data/spec/metanorma/processor_spec.rb +88 -0
  55. data/spec/spec_helper.rb +253 -0
  56. metadata +325 -0
@@ -0,0 +1,153 @@
1
+ require "spec_helper"
2
+ require "nokogiri"
3
+
4
+ RSpec.describe IsoDoc::Iec::Metadata do
5
+ it "processes IsoXML metadata" do
6
+ c = IsoDoc::Iec::HtmlConvert.new({})
7
+ arr = c.convert_init(<<~"INPUT", "test", false)
8
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
9
+ INPUT
10
+ expect(Hash[c.info(Nokogiri::XML(<<~"INPUT"), nil).sort]).to be_equivalent_to <<~"OUTPUT"
11
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
12
+ <bibdata type="standard">
13
+ <title type="title-intro" language="en" format="text/plain">Cereals and pulses</title>
14
+ <title type="title-main" language="en" format="text/plain">Specifications and test methods</title>
15
+ <title type="title-part" language="en" format="text/plain">Rice</title>
16
+ <title type="title-intro" language="fr" format="text/plain">Céréales et légumineuses</title>
17
+ <title type="title-main" language="fr" format="text/plain">Spécification et méthodes d'essai</title>
18
+ <title type="title-part" language="fr" format="text/plain">Riz</title>
19
+ <docidentifier type="iso">ISO/PreCD3 17301-1</docidentifier>
20
+ <docidentifier type="iso-tc">17301</docidentifier>
21
+ <date type="published"><on>2011</on></date>
22
+ <date type="accessed"><on>2012</on></date>
23
+ <date type="created"><from>2010</from><to>2011</to></date>
24
+ <date type="activated"><on>2013</on></date>
25
+ <date type="obsoleted"><on>2014</on></date>
26
+ <edition>2</edition>
27
+ <version>
28
+ <revision-date>2016-05-01</revision-date>
29
+ <draft>0.4</draft>
30
+ </version>
31
+ <contributor>
32
+ <role type="author"/>
33
+ <organization>
34
+ <abbreviation>ISO</abbreviation>
35
+ </organization>
36
+ </contributor>
37
+ <contributor>
38
+ <role type="publisher"/>
39
+ <organization>
40
+ <abbreviation>ISO</abbreviation>
41
+ </organization>
42
+ </contributor>
43
+ <language>en</language>
44
+ <script>Latn</script>
45
+ <status>
46
+ <stage>40</stage>
47
+ <substage>92</substage>
48
+ <iteration>3</iteration>
49
+ </status>
50
+ <copyright>
51
+ <from>2016</from>
52
+ <owner>
53
+ <organization>
54
+ <abbreviation>ISO</abbreviation>
55
+ </organization>
56
+ </owner>
57
+ </copyright>
58
+ <ext>
59
+ <doctype>international-standard</doctype>
60
+ <editorialgroup>
61
+ <technical-committee number="34">Food products</technical-committee>
62
+ <subcommittee number="4">Cereals and pulses</subcommittee>
63
+ <workgroup number="3">Rice Group</workgroup>
64
+ <secretariat>GB</secretariat>
65
+ </editorialgroup>
66
+ <structuredidentifier>
67
+ <project-number part="1">ISO/PreCD3 17301</project-number>
68
+ </structuredidentifier>
69
+ </ext>
70
+ </bibdata>
71
+ </iso-standard>
72
+ INPUT
73
+ {:accesseddate=>"2012", :activateddate=>"2013", :agency=>"ISO", :authors=>[], :authors_affiliations=>{}, :createddate=>"2010&ndash;2011", :docnumber=>"ISO/PreCD3 17301-1", :docsubtitle=>"C&#xe9;r&#xe9;ales et l&#xe9;gumineuses&nbsp;&mdash; Sp&#xe9;cification et m&#xe9;thodes d&#x27;essai&nbsp;&mdash; Partie&nbsp;1: Riz", :docsubtitleintro=>"C&#xe9;r&#xe9;ales et l&#xe9;gumineuses", :docsubtitlemain=>"Sp&#xe9;cification et m&#xe9;thodes d&#x27;essai", :docsubtitlepart=>"Riz", :docsubtitlepartlabel=>"Partie&nbsp;1", :doctitle=>"Cereals and pulses&nbsp;&mdash; Specifications and test methods&nbsp;&mdash; Part&nbsp;1: Rice", :doctitleintro=>"Cereals and pulses", :doctitlemain=>"Specifications and test methods", :doctitlepart=>"Rice", :doctitlepartlabel=>"Part&nbsp;1", :doctype=>"International Standard", :docyear=>"2016", :draft=>"0.4", :draftinfo=>" (draft 0.4, 2016-05-01)", :edition=>"2", :editorialgroup=>["TC 34", "SC 4", "WG 3"], :ics=>"XXX", :obsoleteddate=>"2014", :obsoletes=>nil, :obsoletes_part=>nil, :publisheddate=>"2011", :revdate=>"2016-05-01", :sc=>"SC 4", :secretariat=>"GB", :stage=>"40", :stage_int=>40, :stageabbr=>"PreDIS3", :tc=>"TC 34", :tc_docnumber=>"17301", :unpublished=>true, :wg=>"WG 3"}
74
+ OUTPUT
75
+ end
76
+
77
+ it "processes IsoXML metadata" do
78
+ c = IsoDoc::Iec::HtmlConvert.new({})
79
+ arr = c.convert_init(<<~"INPUT", "test", false)
80
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
81
+ INPUT
82
+ expect(Hash[c.info(Nokogiri::XML(<<~"INPUT"), nil).sort]).to be_equivalent_to <<~"OUTPUT"
83
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
84
+ <bibdata type="standard">
85
+ <title>
86
+ <title type="title-intro" language="en" format="text/plain">Cereals and pulses</title>
87
+ <title type="title-main" language="en" format="text/plain">Specifications and test methods</title>
88
+ <title type="title-part" language="en" format="text/plain">Rice</title>
89
+ </title>
90
+ <title>
91
+ <title type="title-intro" language="fr" format="text/plain">Céréales et légumineuses</title>
92
+ <title type="title-main" language="fr" format="text/plain">Spécification et méthodes d'essai</title>
93
+ <title type="title-part" language="fr" format="text/plain">Riz</title>
94
+ </title>
95
+ <docidentifier type="iso">ISO/IEC/CD 17301-1-3</docidentifier>
96
+ <docidentifier type="iso-tc">17301</docidentifier>
97
+ <contributor>
98
+ <role type="author"/>
99
+ <organization>
100
+ <name>ISO</name>
101
+ </organization>
102
+ </contributor>
103
+ <contributor>
104
+ <role type="publisher"/>
105
+ <organization>
106
+ <abbreviation>ISO</abbreviation>
107
+ </organization>
108
+ </contributor>
109
+ <contributor>
110
+ <role type="publisher"/>
111
+ <organization>
112
+ <abbreviation>IEC</abbreviation>
113
+ </organization>
114
+ </contributor>
115
+ <language>en</language>
116
+ <script>Latn</script>
117
+ <status>
118
+ <stage>60</stage>
119
+ <substage>92</substage>
120
+ </status>
121
+ <copyright>
122
+ <from>2016</from>
123
+ <owner>
124
+ <organization>
125
+ <name>International Organization for Standardization</name>
126
+ </organization>
127
+ </owner>
128
+ </copyright>
129
+ <relation type="obsoletes">
130
+ <locality type="clause"><referenceFrom>3.1</referenceFrom></locality>
131
+ <docidentifier>IEC 8121</docidentifier>
132
+ </relation>
133
+ <ext>
134
+ <doctype>international-standard</doctype>
135
+ <editorialgroup>
136
+ <technical-committee number="34" type="ABC">Food products</technical-committee>
137
+ <subcommittee number="4" type="DEF">Cereals and pulses</subcommittee>
138
+ <workgroup number="3" type="GHI">Rice Group</workgroup>
139
+ </editorialgroup>
140
+ <ics><code>1.2.3</code></ics>
141
+ <ics><code>1.2.3</code></ics>
142
+ <structuredidentifier>
143
+ <project-number part="1" subpart="3">ISO/IEC/CD 17301</project-number>
144
+ </strucuredidentifier>
145
+ </ext>
146
+ </bibdata>
147
+ </iso-standard>
148
+ INPUT
149
+ {:agency=>"ISO/IEC", :authors=>[], :authors_affiliations=>{}, :docnumber=>"ISO/IEC/CD 17301-1-3", :docsubtitle=>"C&#xe9;r&#xe9;ales et l&#xe9;gumineuses&nbsp;&mdash; Sp&#xe9;cification et m&#xe9;thodes d&#x27;essai&nbsp;&mdash; Partie&nbsp;1&ndash;3: Riz", :docsubtitleintro=>"C&#xe9;r&#xe9;ales et l&#xe9;gumineuses", :docsubtitlemain=>"Sp&#xe9;cification et m&#xe9;thodes d&#x27;essai", :docsubtitlepart=>"Riz", :docsubtitlepartlabel=>"Partie&nbsp;1&ndash;3", :doctitle=>"Cereals and pulses&nbsp;&mdash; Specifications and test methods&nbsp;&mdash; Part&nbsp;1&ndash;3: Rice", :doctitleintro=>"Cereals and pulses", :doctitlemain=>"Specifications and test methods", :doctitlepart=>"Rice", :doctitlepartlabel=>"Part&nbsp;1&ndash;3", :doctype=>"International Standard", :docyear=>"2016", :draft=>nil, :draftinfo=>"", :edition=>nil, :editorialgroup=>["ABC 34", "DEF 4", "GHI 3"], :ics=>"1.2.3, 1.2.3", :obsoletes=>"IEC 8121", :obsoletes_part=>"3.1", :revdate=>nil, :sc=>"DEF 4", :secretariat=>"XXXX", :stage=>"60", :stage_int=>60, :stageabbr=>"IS", :tc=>"ABC 34", :tc_docnumber=>"17301", :unpublished=>false, :wg=>"GHI 3"}
150
+ OUTPUT
151
+ end
152
+
153
+ end
@@ -0,0 +1,569 @@
1
+ require "spec_helper"
2
+ require "fileutils"
3
+
4
+ RSpec.describe IsoDoc do
5
+ it "generates file based on string input" do
6
+ FileUtils.rm_f "test.doc"
7
+ FileUtils.rm_f "test.html"
8
+ IsoDoc::Iec::HtmlConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css", filename: "test"}).convert("test", <<~"INPUT", false)
9
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
10
+ <bibdata>
11
+ <title>
12
+ <title type="title-intro" language="en" format="text/plain">Cereals and pulses</title>
13
+ <title type="title-main" language="en" format="text/plain">Specifications and test methods</title>
14
+ <title type="title-part" language="en" format="text/plain">Rice</title>
15
+ </title>
16
+ </bibdata>
17
+ <preface><foreword>
18
+ <note>
19
+ <p id="_f06fd0d1-a203-4f3d-a515-0bdba0f8d83f">These results are based on a study carried out on three different types of kernel.</p>
20
+ </note>
21
+ </foreword></preface>
22
+ </iso-standard>
23
+ INPUT
24
+ expect(File.exist?("test.html")).to be true
25
+ html = File.read("test.html")
26
+ expect(html).to match(%r{<title>Cereals and pulses\&nbsp;\&mdash; Specifications and test methods\&nbsp;\&mdash; Rice</title>})
27
+ expect(html).to match(%r{cdnjs\.cloudflare\.com/ajax/libs/mathjax/})
28
+ expect(html).to match(/delimiters: \[\['\(#\(', '\)#\)'\]\]/)
29
+ end
30
+
31
+ it "generates HTML output docs with null configuration" do
32
+ FileUtils.rm_f "test.doc"
33
+ FileUtils.rm_f "test.html"
34
+ IsoDoc::Iec::HtmlConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("test", <<~"INPUT", false)
35
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
36
+ <bibdata>
37
+ <title>
38
+ <title type="title-intro" language="en" format="text/plain">Cereals and pulses</title>
39
+ <title type="title-main" language="en" format="text/plain">Specifications and test methods</title>
40
+ <title type="title-part" language="en" format="text/plain">Rice</title>
41
+ </title>
42
+ </bibdata>
43
+ <preface><foreword>
44
+ <note>
45
+ <p id="_f06fd0d1-a203-4f3d-a515-0bdba0f8d83f">These results are based on a study carried out on three different types of kernel.</p>
46
+ </note>
47
+ </foreword></preface>
48
+ </iso-standard>
49
+ INPUT
50
+ expect(File.exist?("test.html")).to be true
51
+ html = File.read("test.html")
52
+ expect(html).to match(%r{<title>Cereals and pulses\&nbsp;\&mdash; Specifications and test methods\&nbsp;\&mdash; Rice</title>})
53
+ expect(html).to match(%r{cdnjs\.cloudflare\.com/ajax/libs/mathjax/})
54
+ expect(html).to match(/delimiters: \[\['\(#\(', '\)#\)'\]\]/)
55
+ end
56
+
57
+ it "generates Word output docs with null configuration" do
58
+ FileUtils.rm_f "test.doc"
59
+ FileUtils.rm_f "test.html"
60
+ IsoDoc::Iec::WordConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("test", <<~"INPUT", false)
61
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
62
+ <preface><foreword>
63
+ <note>
64
+ <p id="_f06fd0d1-a203-4f3d-a515-0bdba0f8d83f">These results are based on a study carried out on three different types of kernel.</p>
65
+ </note>
66
+ </foreword></preface>
67
+ </iso-standard>
68
+ INPUT
69
+ expect(File.exist?("test.doc")).to be true
70
+ word = File.read("test.doc")
71
+ expect(word).to match(/<style>/)
72
+ end
73
+
74
+ it "generates HTML output docs with null configuration from file" do
75
+ FileUtils.rm_f "spec/assets/iso.doc"
76
+ FileUtils.rm_f "spec/assets/iso.html"
77
+ IsoDoc::Iec::HtmlConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("spec/assets/iso.xml", nil, false)
78
+ expect(File.exist?("spec/assets/iso.html")).to be true
79
+ html = File.read("spec/assets/iso.html")
80
+ expect(html).to match(/<style>/)
81
+ expect(html).to match(%r{https://use.fontawesome.com})
82
+ expect(html).to match(%r{libs/jquery})
83
+ end
84
+
85
+ it "generates Word output docs with null configuration from file" do
86
+ FileUtils.rm_f "spec/assets/iso.doc"
87
+ IsoDoc::Iec::WordConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("spec/assets/iso.xml", nil, false)
88
+ expect(File.exist?("spec/assets/iso.doc")).to be true
89
+ word = File.read("spec/assets/iso.doc")
90
+ expect(word).to match(/<w:WordDocument>/)
91
+ expect(word).to match(/<style>/)
92
+ end
93
+
94
+ it "converts annex subheadings to h2Annex class for Word" do
95
+ FileUtils.rm_f "test.doc"
96
+ FileUtils.rm_f "test.html"
97
+ IsoDoc::Iec::WordConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("test", <<~"INPUT", false)
98
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
99
+ <annex id="P" inline-header="false" obligation="normative">
100
+ <title>Annex</title>
101
+ <clause id="Q" inline-header="false" obligation="normative">
102
+ <title>Annex A.1</title>
103
+ </clause>
104
+ <appendix id="Q2" inline-header="false" obligation="normative">
105
+ <title>An Appendix</title>
106
+ </appendix>
107
+ </annex>
108
+ </iso-standard>
109
+ INPUT
110
+ word = File.read("test.doc").sub(/^.*<div class="WordSection3">/m, '<div class="WordSection3">').
111
+ sub(%r{<div style="mso-element:footnote-list"/>.*$}m, "")
112
+ expect(word).to be_equivalent_to <<~"OUTPUT"
113
+ <div class="WordSection3">
114
+ #{IEC_TITLE}
115
+ <p class="MsoNormal"><br clear="all" style="mso-special-character:line-break;page-break-before:always"/></p>
116
+ <div class="Section3"><a name="P" id="P"></a>
117
+ <h1 class="Annex"><b>Annex A</b><br/><br/>(normative)<br/><br/><b>Annex</b></h1>
118
+ <div><a name="Q" id="Q"></a>
119
+ <p class="h2Annex">A.1 Annex A.1</p>
120
+ </div>
121
+ <div><a name="Q2" id="Q2"></a>
122
+ <p class="h2Annex">Appendix 1 An Appendix</p>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ <br clear="all" style="page-break-before:left;mso-break-type:section-break"/>
127
+ <div class="colophon"></div>
128
+ OUTPUT
129
+ end
130
+
131
+ it "populates Word template with terms reference labels" do
132
+ FileUtils.rm_f "test.doc"
133
+ FileUtils.rm_f "test.html"
134
+ IsoDoc::Iec::WordConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("test", <<~"INPUT", false)
135
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
136
+ <sections>
137
+ <terms id="_terms_and_definitions" obligation="normative"><title>Terms and Definitions</title>
138
+
139
+ <term id="paddy1"><preferred>paddy</preferred>
140
+ <definition><p id="_eb29b35e-123e-4d1c-b50b-2714d41e747f">rice retaining its husk after threshing</p></definition>
141
+ <termsource status="modified">
142
+ <origin bibitemid="ISO7301" type="inline" citeas="ISO 7301:2011"><locality type="clause"><referenceFrom>3.1</referenceFrom></locality></origin>
143
+ <modification>
144
+ <p id="_e73a417d-ad39-417d-a4c8-20e4e2529489">The term "cargo rice" is shown as deprecated, and Note 1 to entry is not included here</p>
145
+ </modification>
146
+ </termsource></term>
147
+
148
+ </terms>
149
+ </sections>
150
+ </iso-standard>
151
+
152
+ INPUT
153
+ word = File.read("test.doc").sub(/^.*<div class="WordSection3">/m, '<div class="WordSection3">').
154
+ sub(%r{<div style="mso-element:footnote-list"/>.*$}m, "")
155
+ expect(word).to be_equivalent_to <<~"OUTPUT"
156
+ <div class="WordSection3">
157
+ #{IEC_TITLE}
158
+ <div><a name="_terms_and_definitions" id="_terms_and_definitions"></a><h1 class="main">1<span style="mso-tab-count:1">&#xA0; </span>Terms and definitions</h1><p class="MsoNormal">For the purposes of this document,
159
+ the following terms and definitions apply.</p>
160
+ <p class="MsoNormal">ISO and IEC maintain terminological databases for use in
161
+ standardization at the following addresses:</p>
162
+
163
+ <p style="mso-list:l22 level1 lfo1;" class="MsoListParagraphCxSpFirst"> ISO Online browsing platform: available at
164
+ <a href="http://www.iso.org/obp">http://www.iso.org/obp</a> </p>
165
+ <p style="mso-list:l22 level1 lfo1;" class="MsoListParagraphCxSpLast"> IEC Electropedia: available at
166
+ <a href="http://www.electropedia.org">http://www.electropedia.org</a>
167
+ </p>
168
+ <p class="TermNum"><a name="paddy1" id="paddy1"></a>1.1</p><p class="Terms" style="text-align:left;">paddy</p>
169
+ <p class="MsoNormal"><a name="_eb29b35e-123e-4d1c-b50b-2714d41e747f" id="_eb29b35e-123e-4d1c-b50b-2714d41e747f"></a>rice retaining its husk after threshing</p>
170
+ <p class="MsoNormal">[SOURCE: <a href="#ISO7301">ISO 7301:2011, 3.1</a>, modified &mdash; The term "cargo rice" is shown as deprecated, and Note 1 to entry is not included here]</p></div>
171
+ </div>
172
+ <br clear="all" style="page-break-before:left;mso-break-type:section-break"/>
173
+ <div class="colophon"></div>
174
+ OUTPUT
175
+ end
176
+
177
+ it "populates Word header" do
178
+ FileUtils.rm_f "test.doc"
179
+ IsoDoc::Iec::WordConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css", header: "spec/assets/header.html"}).convert("test", <<~"INPUT", false)
180
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
181
+ <bibdata type="article">
182
+ <docidentifier>
183
+ <project-number part="1">1000</project-number>
184
+ </docidentifier>
185
+ </bibdata>
186
+ </iso-standard>
187
+
188
+ INPUT
189
+ word = File.read("test.doc").sub(%r{^.*Content-Location: file:///C:/Doc/test_files/header.html}m, "Content-Location: file:///C:/Doc/test_files/header.html").
190
+ sub(/------=_NextPart.*$/m, "")
191
+ #expect(word).to include(%{Content-Location: file:///C:/Doc/test_files/header.html\nContent-Transfer-Encoding: base64\nContent-Type: text/html charset="utf-8" })
192
+ expect(word).to include(%{Content-Location: file:///C:/Doc/test_files/header.html})
193
+ end
194
+
195
+ it "populates Word ToC" do
196
+ FileUtils.rm_f "test.doc"
197
+ IsoDoc::Iec::WordConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css", wordintropage: "spec/assets/wordintro.html"}).convert("test", <<~"INPUT", false)
198
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
199
+ <sections>
200
+ <clause inline-header="false" obligation="normative"><title>Clause 4</title><clause id="N" inline-header="false" obligation="normative">
201
+
202
+ <title>Introduction<bookmark id="Q"/> to this<fn reference="1">
203
+ <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6">Formerly denoted as 15 % (m/m).</p>
204
+ </fn></title>
205
+ </clause>
206
+ <clause id="O" inline-header="false" obligation="normative">
207
+ <title>Clause 4.2</title>
208
+ <p>A<fn reference="1">
209
+ <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6">Formerly denoted as 15 % (m/m).</p>
210
+ </fn></p>
211
+ </clause></clause>
212
+ </sections>
213
+ </iso-standard>
214
+
215
+ INPUT
216
+ word = File.read("test.doc").sub(/^.*An empty word intro page\./m, '').
217
+ sub(%r{<p class="zzSTDTitle1">.*$}m, "")
218
+ expect(word.gsub(/_Toc\d\d+/, "_Toc")).to be_equivalent_to <<~'OUTPUT'
219
+ <p class="MsoToc1"><span lang="EN-GB" xml:lang="EN-GB"><span style="mso-element:field-begin"></span><span style="mso-spacerun:yes">&#xA0;</span>TOC
220
+ \o "1-2" \h \z \u <span style="mso-element:field-separator"></span></span>
221
+ <span class="MsoHyperlink"><span lang="EN-GB" style="mso-no-proof:yes" xml:lang="EN-GB">
222
+ <a href="#_Toc">FOREWORD<span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">
223
+ <span style="mso-tab-count:1 dotted">. </span>
224
+ </span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">
225
+ <span style="mso-element:field-begin"></span></span>
226
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"> PAGEREF _Toc \h </span>
227
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"><span style="mso-element:field-separator"></span></span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">1</span>
228
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"></span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"><span style="mso-element:field-end"></span></span></a></span></span></p>
229
+
230
+ <p class="MsoToc1">
231
+ <span class="MsoHyperlink">
232
+ <span lang="EN-GB" style="mso-no-proof:yes" xml:lang="EN-GB">
233
+ <a href="#_Toc">1 Clause 4<span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">
234
+ <span style="mso-tab-count:1 dotted">. </span>
235
+ </span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">
236
+ <span style="mso-element:field-begin"></span></span>
237
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"> PAGEREF _Toc \h </span>
238
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"><span style="mso-element:field-separator"></span></span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">1</span>
239
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"></span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"><span style="mso-element:field-end"></span></span></a></span>
240
+ </span>
241
+ </p>
242
+
243
+
244
+ <p class="MsoToc2">
245
+ <span class="MsoHyperlink">
246
+ <span lang="EN-GB" style="mso-no-proof:yes" xml:lang="EN-GB">
247
+ <a href="#_Toc">1.1 Introduction to this<span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">
248
+ <span style="mso-tab-count:1 dotted">. </span>
249
+ </span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">
250
+ <span style="mso-element:field-begin"></span></span>
251
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"> PAGEREF _Toc \h </span>
252
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"><span style="mso-element:field-separator"></span></span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">1</span>
253
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"></span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"><span style="mso-element:field-end"></span></span></a></span>
254
+ </span>
255
+ </p>
256
+
257
+ <p class="MsoToc2">
258
+ <span class="MsoHyperlink">
259
+ <span lang="EN-GB" style="mso-no-proof:yes" xml:lang="EN-GB">
260
+ <a href="#_Toc">1.2 Clause 4.2<span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">
261
+ <span style="mso-tab-count:1 dotted">. </span>
262
+ </span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">
263
+ <span style="mso-element:field-begin"></span></span>
264
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"> PAGEREF _Toc \h </span>
265
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"><span style="mso-element:field-separator"></span></span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB">1</span>
266
+ <span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"></span><span lang="EN-GB" class="MsoTocTextSpan" xml:lang="EN-GB"><span style="mso-element:field-end"></span></span></a></span>
267
+ </span>
268
+ </p>
269
+
270
+ <p class="MsoToc1">
271
+ <span lang="EN-GB" xml:lang="EN-GB">
272
+ <span style="mso-element:field-end"></span>
273
+ </span>
274
+ <span lang="EN-GB" xml:lang="EN-GB">
275
+ <p class="MsoNormal">&#xA0;</p>
276
+ </span>
277
+ </p>
278
+
279
+
280
+ <p class="MsoNormal">
281
+ <br clear="all" style="mso-special-character:line-break;page-break-before:always"/>
282
+ </p>
283
+ OUTPUT
284
+ end
285
+
286
+ it "reorders footnote numbers in HTML" do
287
+ FileUtils.rm_f "test.html"
288
+ IsoDoc::Iec::HtmlConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css", wordintropage: "spec/assets/wordintro.html"}).convert("test", <<~"INPUT", false)
289
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
290
+ <sections>
291
+ <clause inline-header="false" obligation="normative"><title>Clause 4</title><fn reference="3">
292
+ <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6">This is a footnote.</p>
293
+ </fn><clause id="N" inline-header="false" obligation="normative">
294
+
295
+ <title>Introduction to this<fn reference="2">
296
+ <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6">Formerly denoted as 15 % (m/m).</p>
297
+ </fn></title>
298
+ </clause>
299
+ <clause id="O" inline-header="false" obligation="normative">
300
+ <title>Clause 4.2</title>
301
+ <p>A<fn reference="1">
302
+ <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6">Formerly denoted as 15 % (m/m).</p>
303
+ </fn></p>
304
+ </clause></clause>
305
+ </sections>
306
+ </iso-standard>
307
+ INPUT
308
+ html = File.read("test.html").sub(/^.*<main class="main-section">/m, '<main class="main-section">').
309
+ sub(%r{</main>.*$}m, "</main>")
310
+ expect(html).to be_equivalent_to <<~"OUTPUT"
311
+ <main class="main-section"><button onclick="topFunction()" id="myBtn" title="Go to top">Top</button>
312
+ <br/>
313
+ #{IEC_TITLE}
314
+ <div id="">
315
+ <h1 class="ForewordTitle">FOREWORD</h1>
316
+ <div class="boilerplate_legal"></div>
317
+ </div>
318
+ #{IEC_TITLE}
319
+ <div>
320
+ <h1>1&#xA0; Clause 4</h1>
321
+ <a rel="footnote" href="#fn:3" epub:type="footnote" id="fnref:1">
322
+ <sup>1</sup>
323
+ </a>
324
+ <div id="N">
325
+
326
+ <h2>1.1 Introduction to this<a rel="footnote" href="#fn:2" epub:type="footnote" id="fnref:2"><sup>2</sup></a></h2>
327
+ </div>
328
+ <div id="O">
329
+ <h2>1.2 Clause 4.2</h2>
330
+ <p>A<a rel="footnote" href="#fn:2" epub:type="footnote"><sup>2</sup></a></p>
331
+ </div>
332
+ </div>
333
+ <aside id="fn:3" class="footnote">
334
+ <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6"><a rel="footnote" href="#fn:3" epub:type="footnote" id="fnref:1">
335
+ <sup>1</sup>
336
+ </a>This is a footnote.</p>
337
+ <a href="#fnref:1">&#x21A9;</a></aside>
338
+ <aside id="fn:2" class="footnote">
339
+ <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6"><a rel="footnote" href="#fn:2" epub:type="footnote" id="fnref:2"><sup>2</sup></a>Formerly denoted as 15 % (m/m).</p>
340
+ <a href="#fnref:2">&#x21A9;</a></aside>
341
+
342
+ </main>
343
+ OUTPUT
344
+ end
345
+
346
+ it "moves images in HTML" do
347
+ FileUtils.rm_f "test.html"
348
+ FileUtils.rm_rf "_images"
349
+ FileUtils.rm_rf "test_htmlimages"
350
+ IsoDoc::Iec::HtmlConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("test", <<~"INPUT", false)
351
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
352
+ <preface><foreword>
353
+ <figure id="_">
354
+ <name>Split-it-right sample divider</name>
355
+ <image src="spec/assets/rice_image1.png" id="_" imagetype="PNG"/>
356
+ <image src="spec/assets/rice_image1.png" id="_" width="20000" height="300000" imagetype="PNG"/>
357
+ <image src="spec/assets/rice_image1.png" id="_" width="99" height="auto" imagetype="PNG"/>
358
+ </figure>
359
+ </foreword></preface>
360
+ </iso-standard>
361
+ INPUT
362
+ html = File.read("test.html").sub(/^.*<main class="main-section">/m, '<main class="main-section">').
363
+ sub(%r{</main>.*$}m, "</main>")
364
+ expect(`ls test_htmlimages`).to match(/\.png$/)
365
+ expect(html.gsub(/\/[0-9a-f-]+\.png/, "/_.png")).to be_equivalent_to <<~"OUTPUT"
366
+ <main class="main-section"><button onclick="topFunction()" id="myBtn" title="Go to top">Top</button>
367
+ <br />
368
+ #{IEC_TITLE}
369
+ <div>
370
+ <h1 class="ForewordTitle">FOREWORD</h1>
371
+ <div class="boilerplate_legal"></div>
372
+ <div id="_" class="figure">
373
+ <img src="test_htmlimages/_.png" height="776" width="922" />
374
+ <img src="test_htmlimages/_.png" height="800" width="53" />
375
+ <img src="test_htmlimages/_.png" height="83" width="99" />
376
+ <p class="FigureTitle" align="center">Figure 1&#xA0;&#x2014; Split-it-right sample divider</p></div>
377
+ </div>
378
+ #{IEC_TITLE}
379
+ </main>
380
+ OUTPUT
381
+
382
+ end
383
+
384
+ it "processes IsoXML terms for HTML" do
385
+ FileUtils.rm_f "test.html"
386
+ FileUtils.rm_f "test.doc"
387
+ IsoDoc::Iec::HtmlConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("test", <<~"INPUT", false)
388
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
389
+ <sections>
390
+ <terms id="_terms_and_definitions" obligation="normative"><title>Terms and Definitions</title>
391
+
392
+ <term id="paddy1"><preferred>paddy</preferred>
393
+ <domain>rice</domain>
394
+ <definition><p id="_eb29b35e-123e-4d1c-b50b-2714d41e747f">rice retaining its husk after threshing</p></definition>
395
+ <termexample id="_bd57bbf1-f948-4bae-b0ce-73c00431f892">
396
+ <p id="_65c9a509-9a89-4b54-a890-274126aeb55c">Foreign seeds, husks, bran, sand, dust.</p>
397
+ <ul>
398
+ <li>A</li>
399
+ </ul>
400
+ </termexample>
401
+ <termexample id="_bd57bbf1-f948-4bae-b0ce-73c00431f894">
402
+ <ul>
403
+ <li>A</li>
404
+ </ul>
405
+ </termexample>
406
+
407
+ <termsource status="modified">
408
+ <origin bibitemid="ISO7301" type="inline" citeas="ISO 7301:2011"><locality type="clause"><referenceFrom>3.1</referenceFrom></locality></origin>
409
+ <modification>
410
+ <p id="_e73a417d-ad39-417d-a4c8-20e4e2529489">The term "cargo rice" is shown as deprecated, and Note 1 to entry is not included here</p>
411
+ </modification>
412
+ </termsource></term>
413
+
414
+ <term id="paddy"><preferred>paddy</preferred><admitted>paddy rice</admitted>
415
+ <admitted>rough rice</admitted>
416
+ <deprecates>cargo rice</deprecates>
417
+ <definition><p id="_eb29b35e-123e-4d1c-b50b-2714d41e747f">rice retaining its husk after threshing</p></definition>
418
+ <termexample id="_bd57bbf1-f948-4bae-b0ce-73c00431f893">
419
+ <ul>
420
+ <li>A</li>
421
+ </ul>
422
+ </termexample>
423
+ <termnote id="_671a1994-4783-40d0-bc81-987d06ffb74e">
424
+ <p id="_19830f33-e46c-42cc-94ca-a5ef101132d5">The starch of waxy rice consists almost entirely of amylopectin. The kernels have a tendency to stick together after cooking.</p>
425
+ </termnote>
426
+ <termnote id="_671a1994-4783-40d0-bc81-987d06ffb74f">
427
+ <ul><li>A</li></ul>
428
+ <p id="_19830f33-e46c-42cc-94ca-a5ef101132d5">The starch of waxy rice consists almost entirely of amylopectin. The kernels have a tendency to stick together after cooking.</p>
429
+ </termnote>
430
+ <termsource status="identical">
431
+ <origin bibitemid="ISO7301" type="inline" citeas="ISO 7301:2011"><locality type="clause"><referenceFrom>3.1</referenceFrom></locality></origin>
432
+ </termsource></term>
433
+ </terms>
434
+ </sections>
435
+ </iso-standard>
436
+ INPUT
437
+ expect(File.exist?("test.html")).to be true
438
+ html = File.read("test.html")
439
+ expect(html).to match(%r{<h2 class="TermNum" id="paddy1">1\.1</h2>})
440
+ expect(html).to match(%r{<h2 class="TermNum" id="paddy">1\.2</h2>})
441
+ end
442
+
443
+ it "inserts default paragraph between two tables for Word" do
444
+ FileUtils.rm_f "test.doc"
445
+ FileUtils.rm_f "test.html"
446
+ IsoDoc::Iec::WordConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("test", <<~"INPUT", false)
447
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
448
+ <annex id="P" inline-header="false" obligation="normative">
449
+ <example id="_63112cbc-cde0-435f-9553-e0b8c4f5851c">
450
+ <p id="_158d4efa-b1c9-4aec-b325-756de8e4c968">'1M', '01M', and '0001M' all describe the calendar month January.</p>
451
+ </example>
452
+ <example id="_63112cbc-cde0-435f-9553-e0b8c4f5851d">
453
+ <p id="_158d4efa-b1c9-4aec-b325-756de8e4c969">'2M', '02M', and '0002M' all describe the calendar month February.</p>
454
+ </example>
455
+ </annex>
456
+ </iso-standard>
457
+ INPUT
458
+ word = File.read("test.doc").sub(/^.*<div class="WordSection3">/m, '<div class="WordSection3">').
459
+ sub(%r{<div style="mso-element:footnote-list"/>.*$}m, "")
460
+ expect(word).to be_equivalent_to <<~"OUTPUT"
461
+ <div class="WordSection3">
462
+ #{IEC_TITLE}
463
+ <p class="MsoNormal">
464
+ <br clear="all" style="mso-special-character:line-break;page-break-before:always"/>
465
+ </p>
466
+ <div class="Section3"><a name="P" id="P"></a>
467
+ <div class="example"><a name="_63112cbc-cde0-435f-9553-e0b8c4f5851c" id="_63112cbc-cde0-435f-9553-e0b8c4f5851c"></a>
468
+ <p class="MsoNormal"><span class="example_label">EXAMPLE 1</span><span style="mso-tab-count:1">&#xA0; </span>'1M', '01M', and '0001M' all describe the calendar month January.</p>
469
+ </div>
470
+ <div class="example"><a name="_63112cbc-cde0-435f-9553-e0b8c4f5851d" id="_63112cbc-cde0-435f-9553-e0b8c4f5851d"></a>
471
+ <p class="MsoNormal"><span class="example_label">EXAMPLE 2</span><span style="mso-tab-count:1">&#xA0; </span>'2M', '02M', and '0002M' all describe the calendar month February.</p>
472
+ </div>
473
+ </div>
474
+ </div>
475
+ <br clear="all" style="page-break-before:left;mso-break-type:section-break"/>
476
+ <div class="colophon"></div>
477
+
478
+ OUTPUT
479
+ end
480
+
481
+ it "processes figure keys (Word)" do
482
+ FileUtils.rm_f "test.doc"
483
+ FileUtils.rm_f "test.html"
484
+ IsoDoc::Iec::WordConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("test", <<~"INPUT", false)
485
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
486
+ <annex id="P" inline-header="false" obligation="normative">
487
+ <figure id="samplecode">
488
+ <p>Hello</p>
489
+ <p>Key</p>
490
+ <dl>
491
+ <dt><p>A</p></dt>
492
+ <dd><p>B</p></dd>
493
+ </dl>
494
+ </figure>
495
+ </annex>
496
+ </iso-standard>
497
+ INPUT
498
+ word = File.read("test.doc").sub(/^.*<div class="WordSection3">/m, '<div class="WordSection3">').
499
+ sub(%r{<div style="mso-element:footnote-list"/>.*$}m, "")
500
+ expect(word).to be_equivalent_to <<~"OUTPUT"
501
+ <div class="WordSection3">
502
+ #{IEC_TITLE}
503
+ <p class="MsoNormal">
504
+ <br clear="all" style="mso-special-character:line-break;page-break-before:always"/>
505
+ </p>
506
+ <div class="Section3"><a name="P" id="P"></a>
507
+ <div class="figure"><a name="samplecode" id="samplecode"></a>
508
+ <p class="MsoNormal">Hello</p>
509
+ <p class="MsoNormal">Key</p>
510
+ <p class="MsoNormal"><b>Key</b></p><div class="figdl"><table class="figdl"><tr><td valign="top" align="left"><p align="left" style="margin-left:0pt;text-align:left;" class="MsoNormal"><p class="MsoNormal">A</p></p></td><td valign="top"><p class="MsoNormal">B</p></td></tr></table></div>
511
+ <p class="FigureTitle" align="center">Figure A.1</p></div>
512
+ </div>
513
+ </div>
514
+ <br clear="all" style="page-break-before:left;mso-break-type:section-break"/>
515
+ <div class="colophon"></div>
516
+
517
+ OUTPUT
518
+ end
519
+
520
+ it "processes source code in tables (Word)" do
521
+ FileUtils.rm_f "test.doc"
522
+ FileUtils.rm_f "test.html"
523
+ IsoDoc::Iec::WordConvert.new({wordstylesheet: "spec/assets/word.css", htmlstylesheet: "spec/assets/html.css"}).convert("test", <<~"INPUT", false)
524
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
525
+ <annex id="P" inline-header="false" obligation="normative">
526
+ <sourcecode lang="ruby" id="A">puts "Hello, world."</sourcecode>
527
+ <table id="samplecode">
528
+ <tbody>
529
+ <tr><td>
530
+ <sourcecode lang="ruby" id="B">puts "Hello, world."</sourcecode>
531
+ </td></tr>
532
+ </tbody>
533
+ </table>
534
+ </annex>
535
+ </iso-standard>
536
+ INPUT
537
+ word = File.read("test.doc").sub(/^.*<div class="WordSection3">/m, '<div class="WordSection3">').
538
+ sub(%r{<div style="mso-element:footnote-list"/>.*$}m, "")
539
+ expect(word).to be_equivalent_to <<~"OUTPUT"
540
+ <div class="WordSection3">
541
+ #{IEC_TITLE}
542
+ <p class="MsoNormal">
543
+ <br clear="all" style="mso-special-character:line-break;page-break-before:always"/>
544
+ </p>
545
+ <div class="Section3"><a name="P" id="P"></a>
546
+ <p class="Sourcecode"><a name="A" id="A"></a>puts "Hello, world."</p>
547
+ <p class="TableTitle" align="center">Table A.1</p>
548
+ <div align="center">
549
+ <table style="mso-table-lspace:15.0cm;margin-left:423.0pt;mso-table-rspace:15.0cm;margin-right:423.0pt;mso-table-bspace:14.2pt;mso-table-anchor-vertical:paragraph;mso-table-anchor-horizontal:column;mso-table-overlap:never;" class="MsoISOTable" border="1" cellspacing="0" cellpadding="0"><a name="samplecode" id="samplecode"></a>
550
+ <tbody>
551
+ <tr>
552
+ <td style="border-top:solid windowtext 1.5pt;mso-border-top-alt:solid windowtext 1.5pt;border-bottom:solid windowtext 1.5pt;mso-border-bottom-alt:solid windowtext 1.5pt;" class="TABLE-cell">
553
+ <p class="CODE-TableCell"><a name="B" id="B"></a>puts "Hello, world."</p>
554
+ </td>
555
+ </tr>
556
+ </tbody>
557
+ </table>
558
+ </div>
559
+ </div>
560
+ </div>
561
+ <br clear="all" style="page-break-before:left;mso-break-type:section-break"/>
562
+ <div class="colophon"></div>
563
+
564
+ OUTPUT
565
+ end
566
+
567
+
568
+
569
+ end