metanorma-iso 2.0.7 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/asciidoctor/iso/base.rb +0 -1
  3. data/lib/asciidoctor/iso/cleanup.rb +0 -1
  4. data/lib/asciidoctor/iso/converter.rb +0 -1
  5. data/lib/asciidoctor/iso/deprecated.rb +4 -2
  6. data/lib/asciidoctor/iso/front.rb +0 -1
  7. data/lib/asciidoctor/iso/front_id.rb +0 -1
  8. data/lib/asciidoctor/iso/section.rb +0 -1
  9. data/lib/asciidoctor/iso/validate.rb +0 -1
  10. data/lib/asciidoctor/iso/validate_image.rb +0 -1
  11. data/lib/asciidoctor/iso/validate_requirements.rb +0 -1
  12. data/lib/asciidoctor/iso/validate_section.rb +0 -1
  13. data/lib/asciidoctor/iso/validate_style.rb +0 -1
  14. data/lib/asciidoctor/iso/validate_title.rb +0 -1
  15. data/lib/html2doc/lists.rb +37 -0
  16. data/lib/isodoc/iso/html/html_iso_titlepage.html +7 -2
  17. data/lib/isodoc/iso/html/isodoc-dis.css +196 -156
  18. data/lib/isodoc/iso/html/isodoc-dis.scss +193 -156
  19. data/lib/isodoc/iso/html/word_iso_intro-dis.html +7 -0
  20. data/lib/isodoc/iso/html/word_iso_titlepage-dis.html +3 -2
  21. data/lib/isodoc/iso/html/word_iso_titlepage.html +8 -2
  22. data/lib/isodoc/iso/html/wordstyle-dis.css +204 -34
  23. data/lib/isodoc/iso/html/wordstyle-dis.scss +198 -34
  24. data/lib/isodoc/iso/i18n-en.yaml +2 -1
  25. data/lib/isodoc/iso/i18n-fr.yaml +1 -0
  26. data/lib/isodoc/iso/i18n-ru.yaml +1 -0
  27. data/lib/isodoc/iso/i18n-zh-Hans.yaml +1 -0
  28. data/lib/isodoc/iso/index.rb +1 -1
  29. data/lib/isodoc/iso/init.rb +17 -1
  30. data/lib/isodoc/iso/iso.amendment.xsl +726 -299
  31. data/lib/isodoc/iso/iso.international-standard.xsl +726 -299
  32. data/lib/isodoc/iso/metadata.rb +75 -63
  33. data/lib/isodoc/iso/presentation_inline.rb +90 -0
  34. data/lib/isodoc/iso/presentation_xml_convert.rb +39 -100
  35. data/lib/isodoc/iso/presentation_xref.rb +126 -0
  36. data/lib/isodoc/iso/word_cleanup.rb +16 -2
  37. data/lib/isodoc/iso/word_convert.rb +27 -10
  38. data/lib/isodoc/iso/word_dis_convert.rb +174 -0
  39. data/lib/isodoc/iso/xref.rb +50 -30
  40. data/lib/metanorma/iso/biblio.rng +62 -10
  41. data/lib/metanorma/iso/boilerplate-fr.xml +1 -1
  42. data/lib/metanorma/iso/boilerplate-ru.xml +1 -3
  43. data/lib/metanorma/iso/boilerplate.xml +1 -3
  44. data/lib/metanorma/iso/cleanup.rb +7 -6
  45. data/lib/metanorma/iso/front_id.rb +28 -11
  46. data/lib/metanorma/iso/isodoc.rng +56 -0
  47. data/lib/metanorma/iso/version.rb +1 -1
  48. data/lib/metanorma-iso.rb +1 -0
  49. data/lib/relaton/render/config.yml +4 -0
  50. data/lib/relaton/render/general.rb +13 -0
  51. data/metanorma-iso.gemspec +1 -1
  52. data/spec/isodoc/amd_spec.rb +15 -14
  53. data/spec/isodoc/blocks_spec.rb +286 -179
  54. data/spec/isodoc/i18n_spec.rb +296 -133
  55. data/spec/isodoc/inline_spec.rb +35 -42
  56. data/spec/isodoc/iso_spec.rb +43 -27
  57. data/spec/isodoc/postproc_spec.rb +25 -0
  58. data/spec/isodoc/ref_spec.rb +66 -69
  59. data/spec/isodoc/section_spec.rb +78 -76
  60. data/spec/isodoc/table_spec.rb +2 -2
  61. data/spec/isodoc/terms_spec.rb +2 -2
  62. data/spec/isodoc/word_dis_spec.rb +760 -0
  63. data/spec/isodoc/xref_spec.rb +51 -51
  64. data/spec/metanorma/amd_spec.rb +39 -16
  65. data/spec/metanorma/base_spec.rb +17 -9
  66. data/spec/metanorma/blocks_spec.rb +4 -4
  67. data/spec/metanorma/cleanup_spec.rb +11 -11
  68. data/spec/metanorma/section_spec.rb +3 -3
  69. data/spec/spec_helper.rb +5 -2
  70. data/spec/vcr_cassettes/withdrawn_iso.yml +26 -26
  71. metadata +11 -5
  72. data/spec/vcr_cassettes/docrels.yml +0 -385
@@ -0,0 +1,760 @@
1
+ require "spec_helper"
2
+ require "fileutils"
3
+
4
+ RSpec.describe IsoDoc do
5
+ it "maps styles for DIS" do
6
+ FileUtils.rm_f "test.doc"
7
+ IsoDoc::Iso::WordConvert
8
+ .new({})
9
+ .convert("test", <<~"INPUT", false)
10
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
11
+ <bibdata>
12
+ <status><stage>30</stage></status>
13
+ </bibdata>
14
+ <sections>
15
+ <terms id="A">
16
+ <term id="B">
17
+ <preferred><expression><name>First</name></expression></preferred>
18
+ <admitted><expression><name>Second</name></expression></admitted>
19
+ </term>
20
+ </terms>
21
+ </sections>
22
+ </iso-standard>
23
+ INPUT
24
+ expect(File.exist?("test.doc")).to be true
25
+ html = File.read("test.doc", encoding: "UTF-8")
26
+ expect(html).to include 'class="AltTerms"'
27
+ expect(html).not_to include 'class="AdmittedTerm"'
28
+
29
+ FileUtils.rm_f "test.doc"
30
+ IsoDoc::Iso::WordConvert
31
+ .new({})
32
+ .convert("test", <<~"INPUT", false)
33
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
34
+ <bibdata>
35
+ <status><stage>50</stage></status>
36
+ </bibdata>
37
+ <sections>
38
+ <terms id="A">
39
+ <term id="B">
40
+ <preferred><expression><name>First</name></expression></preferred>
41
+ <admitted><expression><name>Second</name></expression></admitted>
42
+ </term>
43
+ </terms>
44
+ </sections>
45
+ </iso-standard>
46
+ INPUT
47
+ expect(File.exist?("test.doc")).to be true
48
+ html = File.read("test.doc", encoding: "UTF-8")
49
+ expect(html).not_to include 'class="AltTerms"'
50
+ expect(html).to include 'class="AdmittedTerm"'
51
+ end
52
+
53
+ it "deals with span" do
54
+ input = <<~INPUT
55
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
56
+ <bibdata>
57
+ <status><stage>30</stage></status>
58
+ </bibdata>
59
+ <sections>
60
+ <clause id="A"><p><span class="C"><em>H</em> I</em></span></p></clause>
61
+ </sections>
62
+ </iso-standard>
63
+ INPUT
64
+ word = <<~OUTPUT
65
+ <div class='WordSection3'>
66
+ <p class='zzSTDTitle1'/>
67
+ <div id='A'>
68
+ <h1/>
69
+ <p>
70
+ <i>H</i>
71
+ I
72
+ </p>
73
+ </div>
74
+ </div>
75
+ OUTPUT
76
+ output = IsoDoc::Iso::WordConvert.new({}).convert("test", input, true)
77
+ expect(xmlpp(Nokogiri::XML(output)
78
+ .at("//div[@class = 'WordSection3']").to_xml))
79
+ .to be_equivalent_to xmlpp(word)
80
+
81
+ input = <<~INPUT
82
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
83
+ <bibdata>
84
+ <status><stage>50</stage></status>
85
+ </bibdata>
86
+ <sections>
87
+ <clause id="A"><p><span class="C"><em>H</em> I</em></span></p></clause>
88
+ </sections>
89
+ </iso-standard>
90
+ INPUT
91
+ word = <<~OUTPUT
92
+ <div class='WordSection3'>
93
+ <p class='zzSTDTitle1'/>
94
+ <div id='A'>
95
+ <h1/>
96
+ <p>
97
+ <span class='C'>
98
+ <i>H</i>
99
+ I
100
+ </span>
101
+ </p>
102
+ </div>
103
+ </div>
104
+ OUTPUT
105
+ output = IsoDoc::Iso::WordConvert.new({}).convert("test", input, true)
106
+ expect(xmlpp(Nokogiri::XML(output)
107
+ .at("//div[@class = 'WordSection3']").to_xml))
108
+ .to be_equivalent_to xmlpp(word)
109
+ end
110
+
111
+ it "deals with foreword and intro" do
112
+ input = <<~INPUT
113
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
114
+ <bibdata>
115
+ <status><stage>30</stage></status>
116
+ </bibdata>
117
+ <preface>
118
+ <foreword><title>Foreword</title><p>Para</p></foreword>
119
+ <introduction><title>Foreword</title><p>Para</p></introduction>
120
+ </preface>
121
+ </iso-standard>
122
+ INPUT
123
+ word = <<~OUTPUT
124
+ <div class='WordSection2'>
125
+ <div style='mso-element:para-border-div;border:solid windowtext 1.0pt;
126
+ border-bottom-alt:solid windowtext .5pt;mso-border-top-alt:solid windowtext .5pt;mso-border-left-alt:
127
+ solid windowtext .5pt;mso-border-right-alt:solid windowtext .5pt;padding:1.0pt 4.0pt 0cm 4.0pt;
128
+ margin-left:5.1pt;margin-right:5.1pt'>
129
+ <div>
130
+ <a name='boilerplate-copyright-destination' id='boilerplate-copyright-destination'/>
131
+ </div>
132
+ </div>
133
+ <p class='zzContents' style='margin-top:0cm'>
134
+ <span lang='EN-GB' xml:lang='EN-GB'>Contents</span>
135
+ </p>
136
+ <p class='MsoNormal'>
137
+ <br clear='all' style='mso-special-character:line-break;page-break-before:always'/>
138
+ </p>
139
+ <div>
140
+ <p class='ForewordTitle'>Foreword</p>
141
+ <p class='ForewordText'>Para</p>
142
+ </div>
143
+ <p class='MsoNormal'>
144
+ <br clear='all' style='mso-special-character:line-break;page-break-before:always'/>
145
+ </p>
146
+ <div class='Section3' id=''>
147
+ <p class='IntroTitle'>Foreword</p>
148
+ <p class='MsoNormal'>Para</p>
149
+ </div>
150
+ <p class='MsoNormal'> </p>
151
+ </div>
152
+ OUTPUT
153
+ FileUtils.rm_f "test.doc"
154
+ IsoDoc::Iso::WordConvert.new({}).convert("test", input, false)
155
+ expect(File.exist?("test.doc")).to be true
156
+ output = File.read("test.doc", encoding: "UTF-8")
157
+ .sub(/^.*<html/m, "<html")
158
+ .sub(/<\/html>.*$/m, "</html>")
159
+ doc = Nokogiri::XML(output)
160
+ .xpath("//xmlns:p[@class = 'MsoToc1']").each(&:remove)
161
+ .at("//xmlns:div[@class = 'WordSection2']")
162
+ expect(xmlpp(doc.to_xml))
163
+ .to be_equivalent_to xmlpp(word)
164
+
165
+ input = <<~INPUT
166
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
167
+ <bibdata>
168
+ <status><stage>50</stage></status>
169
+ </bibdata>
170
+ <preface>
171
+ <foreword><title>Foreword</title><p>Para</p></foreword>
172
+ <introduction><title>Foreword</title><p>Para</p></introduction>
173
+ </preface>
174
+ </iso-standard>
175
+ INPUT
176
+ word = <<~OUTPUT
177
+ <div class='WordSection2'>
178
+ <div style='mso-element:para-border-div;border:solid windowtext 1.0pt;
179
+ border-bottom-alt:solid windowtext .5pt;mso-border-top-alt:solid windowtext .5pt;mso-border-left-alt:
180
+ solid windowtext .5pt;mso-border-right-alt:solid windowtext .5pt;padding:1.0pt 4.0pt 0cm 4.0pt;
181
+ margin-left:5.1pt;margin-right:5.1pt'>
182
+ <div>
183
+ <a name='boilerplate-copyright-destination' id='boilerplate-copyright-destination'/>
184
+ </div>
185
+ </div>
186
+ <p class='zzContents' style='margin-top:0cm'>
187
+ <span lang='EN-GB' xml:lang='EN-GB'>Contents</span>
188
+ </p>
189
+ <p class='MsoBodyText'>
190
+ <br clear='all' style='mso-special-character:line-break;page-break-before:always'/>
191
+ </p>
192
+ <div>
193
+ <p class='ForewordTitle'>Foreword</p>
194
+ <p class='ForewordText'>Para</p>
195
+ </div>
196
+ <p class='MsoBodyText'>
197
+ <br clear='all' style='mso-special-character:line-break;page-break-before:always'/>
198
+ </p>
199
+ <div class='Section3' id=''>
200
+ <p class='IntroTitle'>Foreword</p>
201
+ <p class='MsoBodyText'>Para</p>
202
+ </div>
203
+ <p class='MsoBodyText'> </p>
204
+ </div>
205
+ OUTPUT
206
+ FileUtils.rm_f "test.doc"
207
+ IsoDoc::Iso::WordConvert.new({}).convert("test", input, false)
208
+ expect(File.exist?("test.doc")).to be true
209
+ output = File.read("test.doc", encoding: "UTF-8")
210
+ .sub(/^.*<html/m, "<html")
211
+ .sub(/<\/html>.*$/m, "</html>")
212
+ doc = Nokogiri::XML(output)
213
+ .xpath("//xmlns:p[@class = 'MsoToc1']").each(&:remove)
214
+ .at("//xmlns:div[@class = 'WordSection2']")
215
+ expect(xmlpp(doc.to_xml))
216
+ .to be_equivalent_to xmlpp(word)
217
+ end
218
+
219
+ it "formats references" do
220
+ input = <<~INPUT
221
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
222
+ <bibdata>
223
+ <status><stage>50</stage></status>
224
+ </bibdata>
225
+ <bibliography>
226
+ <references id="_normative_references" normative="true" obligation="informative">
227
+ <title>Normative References</title>
228
+ <p>The following documents are referred to in the text in such a way that some or all of their content constitutes requirements of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.</p>
229
+ <bibitem id="ISO712" type="standard">
230
+ <formattedref>ALUFFI, Paolo, ed. (2022). <em><span class="std_class">Facets of Algebraic Geometry: A Collection in Honor of William Fulton's 80th Birthday</span></em>, 1st edition. Cambridge, UK: CUP.</formattedref>
231
+ <docidentifier type="ISO">ISO/IEC 712-3:2022</docidentifier>
232
+ </bibitem>
233
+ </references>
234
+ </bibliography>
235
+ </iso-standard>
236
+ INPUT
237
+ word = <<~OUTPUT
238
+ <div class='WordSection3'>
239
+ <p class='zzSTDTitle1'/>
240
+ <div>
241
+ <h1>Normative References</h1>
242
+ <p class='MsoBodyText'>
243
+ The following documents are referred to in the text in such a way that
244
+ some or all of their content constitutes requirements of this document.
245
+ For dated references, only the edition cited applies. For undated
246
+ references, the latest edition of the referenced document (including any
247
+ amendments) applies.
248
+ </p>
249
+ <p class='RefNorm'>
250
+ <a name='ISO712' id='ISO712'/>
251
+ <span class='stdpublisher'>ISO/IEC</span> <span class='stddocNumber'>712</span>-<span class='stddocPartNumber'>3</span>:<span class='stdyear'>2022</span>, ALUFFI, Paolo, ed. (2022).
252
+ <i>
253
+ <span class='std_class'>
254
+ Facets of Algebraic Geometry: A Collection in Honor of William
255
+ Fulton's 80th Birthday
256
+ </span>
257
+ </i>
258
+ , 1st edition. Cambridge, UK: CUP.
259
+ </p>
260
+ </div>
261
+ </div>
262
+ OUTPUT
263
+ FileUtils.rm_f "test.doc"
264
+ IsoDoc::Iso::WordConvert.new({}).convert("test", input, false)
265
+ expect(File.exist?("test.doc")).to be true
266
+ output = File.read("test.doc", encoding: "UTF-8")
267
+ .sub(/^.*<html/m, "<html")
268
+ .sub(/<\/html>.*$/m, "</html>")
269
+ doc = Nokogiri::XML(output)
270
+ .at("//xmlns:div[@class = 'WordSection3']")
271
+ expect(xmlpp(doc.to_xml))
272
+ .to be_equivalent_to xmlpp(word)
273
+ end
274
+
275
+ it "formats tt" do
276
+ input = <<~INPUT
277
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
278
+ <bibdata>
279
+ <status><stage>50</stage></status>
280
+ </bibdata>
281
+ <preface>
282
+ <foreword>
283
+ <p><tt>A <strong>B</strong> <em>C</em> <strong>D<em>E</em>F</strong> <em>G<strong>H</strong>I</em></tt></p>
284
+ <p><strong>A <tt>B</tt> <em>C<tt>D</tt>E</em></strong></p>
285
+ <p><em>A <tt>B</tt> <strong>C<tt>D</tt>E</strong></em></p>
286
+ </foreword>
287
+ </preface>
288
+ </iso-standard>
289
+ INPUT
290
+ word = <<~OUTPUT
291
+ <div class='WordSection2'>
292
+ <div style='mso-element:para-border-div;border:solid windowtext 1.0pt;
293
+ border-bottom-alt:solid windowtext .5pt;mso-border-top-alt:solid windowtext .5pt;mso-border-left-alt:
294
+ solid windowtext .5pt;mso-border-right-alt:solid windowtext .5pt;padding:1.0pt 4.0pt 0cm 4.0pt;
295
+ margin-left:5.1pt;margin-right:5.1pt'>
296
+ <div>
297
+ <a name='boilerplate-copyright-destination' id='boilerplate-copyright-destination'/>
298
+ </div>
299
+ </div>
300
+ <p class='zzContents' style='margin-top:0cm'>
301
+ <span lang='EN-GB' xml:lang='EN-GB'>Contents</span>
302
+ </p>
303
+ <p class='MsoBodyText'>
304
+ <br clear='all' style='mso-special-character:line-break;page-break-before:always'/>
305
+ </p>
306
+ <div>
307
+ <p class='ForewordTitle'>Foreword</p>
308
+ <p class='ForewordText'>
309
+ <span class='ISOCode'>
310
+ A
311
+ <span class='ISOCodebold'>B</span>
312
+ <span class='ISOCodeitalic'>C</span>
313
+ <span class='ISOCodebold'>
314
+ D
315
+ <span class='ISOCodeitalic'>E</span>
316
+ F
317
+ </span>
318
+ <span class='ISOCodeitalic'>
319
+ G
320
+ <b>H</b>
321
+ I
322
+ </span>
323
+ </span>
324
+ </p>
325
+ <p class='ForewordText'>
326
+ <b>
327
+ A
328
+ <span class='ISOCodebold'>B</span>
329
+ <i>
330
+ C
331
+ <span class='ISOCodeitalic'>D</span>
332
+ E
333
+ </i>
334
+ </b>
335
+ </p>
336
+ <p class='ForewordText'>
337
+ <i>
338
+ A
339
+ <span class='ISOCodeitalic'>B</span>
340
+ <b>
341
+ C
342
+ <span class='ISOCodebold'>D</span>
343
+ E
344
+ </b>
345
+ </i>
346
+ </p>
347
+ </div>
348
+ <p class='MsoBodyText'> </p>
349
+ </div>
350
+ OUTPUT
351
+ FileUtils.rm_f "test.doc"
352
+ IsoDoc::Iso::WordConvert.new({}).convert("test", input, false)
353
+ expect(File.exist?("test.doc")).to be true
354
+ output = File.read("test.doc", encoding: "UTF-8")
355
+ .sub(/^.*<html/m, "<html")
356
+ .sub(/<\/html>.*$/m, "</html>")
357
+ doc = Nokogiri::XML(output)
358
+ .xpath("//xmlns:p[@class = 'MsoToc1']").each(&:remove)
359
+ .at("//xmlns:div[@class = 'WordSection2']")
360
+ expect(xmlpp(doc.to_xml))
361
+ .to be_equivalent_to xmlpp(word)
362
+ end
363
+
364
+ it "deals with lists" do
365
+ input = <<~INPUT
366
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
367
+ <bibdata>
368
+ <status><stage>50</stage></status>
369
+ </bibdata>
370
+ <sections>
371
+ <clause id="A"><p>
372
+ <ol>
373
+ <li><p>A</p></li>
374
+ <li><p>A</p></li>
375
+ <ol>
376
+ <li>A</li>
377
+ <li>A</li>
378
+ <li><ol>
379
+ <li>A</li>
380
+ <li>A</li>
381
+ <li><ol>
382
+ <li>A</li>
383
+ <li>A</li>
384
+ <li><ol>
385
+ <li>A</li>
386
+ <li>A</li>
387
+ <li><ol>
388
+ <li>A</li>
389
+ <li>A</li>
390
+ <li>A</li>
391
+ </ol></li>
392
+ <li>A</li>
393
+ </ol></li>
394
+ <li>A</li>
395
+ </ol></li>
396
+ <li>A</li>
397
+ </ol></li>
398
+ <li>A</li>
399
+ </ol></li>
400
+ <li>A</li>
401
+ </ol>
402
+ <ul>
403
+ <li><p>A</p></li>
404
+ <li><p>A</p></li>
405
+ <li><ul>
406
+ <li>A</li>
407
+ <li>A</li>
408
+ <li><ul>
409
+ <li>A</li>
410
+ <li>A</li>
411
+ <li><ul>
412
+ <li>A</li>
413
+ <li>A</li>
414
+ <li><ul>
415
+ <li>A</li>
416
+ <li>A</li>
417
+ <li><ul>
418
+ <li>A</li>
419
+ <li>A</li>
420
+ <li>A</li>
421
+ </ul></li>
422
+ <li>A</li>
423
+ </ul></li>
424
+ <li>A</li>
425
+ </ul></li>
426
+ <li>A</li>
427
+ </ul></li>
428
+ <li>A</li>
429
+ </ul></li>
430
+ <li>A</li>
431
+ </ul>
432
+ </p></clause>
433
+ </sections>
434
+ </iso-standard>
435
+ INPUT
436
+ word = <<~OUTPUT
437
+ <div class='WordSection3'>
438
+ <p class='zzSTDTitle1'/>
439
+ <div>
440
+ <a name='A' id='A'/>
441
+ <h1/>
442
+ <p class='MsoBodyText'>
443
+ <p style='mso-list:l2 level1 lfo2;' class='ListNumber1'>A</p>
444
+ <p style='mso-list:l2 level1 lfo2;' class='ListNumber1'>A</p>
445
+ <p style='mso-list:l2 level1 lfo3;' class='ListNumber1'>A</p>
446
+ <p style='mso-list:l2 level1 lfo3;' class='ListNumber1'>A</p>
447
+ <p style='mso-list:l2 level1 lfo3;' class='ListNumber1'>
448
+ <p style='mso-list:l2 level2 lfo3;' class='MsoListNumber2'>A</p>
449
+ <p style='mso-list:l2 level2 lfo3;' class='MsoListNumber2'>A</p>
450
+ <p style='mso-list:l2 level2 lfo3;' class='MsoListNumber2'>
451
+ <p style='mso-list:l2 level3 lfo3;' class='MsoListNumber3'>A</p>
452
+ <p style='mso-list:l2 level3 lfo3;' class='MsoListNumber3'>A</p>
453
+ <p style='mso-list:l2 level3 lfo3;' class='MsoListNumber3'>
454
+ <p style='mso-list:l2 level4 lfo3;' class='MsoListNumber4'>A</p>
455
+ <p style='mso-list:l2 level4 lfo3;' class='MsoListNumber4'>A</p>
456
+ <p style='mso-list:l2 level4 lfo3;' class='MsoListNumber4'>
457
+ <p style='mso-list:l2 level5 lfo3;' class='MsoListNumber5'>A</p>
458
+ <p style='mso-list:l2 level5 lfo3;' class='MsoListNumber5'>A</p>
459
+ <p style='mso-list:l2 level5 lfo3;' class='MsoListNumber5'>A</p>
460
+ </p>
461
+ <p style='mso-list:l2 level4 lfo3;' class='MsoListNumber4'>A</p>
462
+ </p>
463
+ <p style='mso-list:l2 level3 lfo3;' class='MsoListNumber3'>A</p>
464
+ </p>
465
+ <p style='mso-list:l2 level2 lfo3;' class='MsoListNumber2'>A</p>
466
+ </p>
467
+ <p style='mso-list:l2 level1 lfo3;' class='ListNumber1'>A</p>
468
+ <li class='MsoNormal'>A</li>
469
+ </p>
470
+ <p style='mso-list:l3 level1 lfo1;' class='ListContinue1'>A</p>
471
+ <p style='mso-list:l3 level1 lfo1;' class='ListContinue1'>A</p>
472
+ <p style='mso-list:l3 level1 lfo1;' class='ListContinue1'>
473
+ <p style='mso-list:l3 level2 lfo1;' class='MsoListContinue2'>A</p>
474
+ <p style='mso-list:l3 level2 lfo1;' class='MsoListContinue2'>A</p>
475
+ <p style='mso-list:l3 level2 lfo1;' class='MsoListContinue2'>
476
+ <p style='mso-list:l3 level3 lfo1;' class='MsoListContinue3'>A</p>
477
+ <p style='mso-list:l3 level3 lfo1;' class='MsoListContinue3'>A</p>
478
+ <p style='mso-list:l3 level3 lfo1;' class='MsoListContinue3'>
479
+ <p style='mso-list:l3 level4 lfo1;' class='MsoListContinue4'>A</p>
480
+ <p style='mso-list:l3 level4 lfo1;' class='MsoListContinue4'>A</p>
481
+ <p style='mso-list:l3 level4 lfo1;' class='MsoListContinue4'>
482
+ <p style='mso-list:l3 level5 lfo1;' class='MsoListContinue5'>A</p>
483
+ <p style='mso-list:l3 level5 lfo1;' class='MsoListContinue5'>A</p>
484
+ <p style='mso-list:l3 level5 lfo1;' class='MsoListContinue5'>
485
+ <p style='mso-list:l3 level6 lfo1;' class='MsoListContinue5'>A</p>
486
+ <p style='mso-list:l3 level6 lfo1;' class='MsoListContinue5'>A</p>
487
+ <p style='mso-list:l3 level6 lfo1;' class='MsoListContinue5'>A</p>
488
+ </p>
489
+ <p style='mso-list:l3 level5 lfo1;' class='MsoListContinue5'>A</p>
490
+ </p>
491
+ <p style='mso-list:l3 level4 lfo1;' class='MsoListContinue4'>A</p>
492
+ </p>
493
+ <p style='mso-list:l3 level3 lfo1;' class='MsoListContinue3'>A</p>
494
+ </p>
495
+ <p style='mso-list:l3 level2 lfo1;' class='MsoListContinue2'>A</p>
496
+ </p>
497
+ <p style='mso-list:l3 level1 lfo1;' class='ListContinue1'>A</p>
498
+ </div>
499
+ </div>
500
+ OUTPUT
501
+ FileUtils.rm_f "test.doc"
502
+ IsoDoc::Iso::WordConvert.new({}).convert("test", input, false)
503
+ expect(File.exist?("test.doc")).to be true
504
+ output = File.read("test.doc", encoding: "UTF-8")
505
+ .sub(/^.*<html/m, "<html")
506
+ .sub(/<\/html>.*$/m, "</html>")
507
+ expect(xmlpp(Nokogiri::XML(output)
508
+ .at("//xmlns:div[@class = 'WordSection3']").to_xml))
509
+ .to be_equivalent_to xmlpp(word)
510
+ end
511
+
512
+ it "deals with tables" do
513
+ input = <<~INPUT
514
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
515
+ <bibdata>
516
+ <status><stage>50</stage></status>
517
+ </bibdata>
518
+ <sections>
519
+ <clause id="A">
520
+ <table id="B">
521
+ <name>Table1</name>
522
+ <thead>
523
+ <tr>
524
+ <th>A</th><th><p>B</p></th>
525
+ </tr>
526
+ </thead>
527
+ <tbody>
528
+ <tr>
529
+ <th>C</th><td><p>D</p></td>
530
+ </tr>
531
+ </tbody>
532
+ <tfoot>
533
+ <tr>
534
+ <th>E</th><td><p>F</p></td>
535
+ </tr>
536
+ </tfoot>
537
+ </table>
538
+ </clause>
539
+ </sections>
540
+ </iso-standard>
541
+ INPUT
542
+ word = <<~WORD
543
+ <div class='WordSection3'>
544
+ <p class='zzSTDTitle1'/>
545
+ <div>
546
+ <a name='A' id='A'/>
547
+ <h1/>
548
+ <p class='Tabletitle' style='text-align:center;'>Table1</p>
549
+ <div align='center' class='table_container'>
550
+ <table class='MsoISOTable' style='mso-table-anchor-horizontal:column;mso-table-overlap:never;border-spacing:0;border-width:1px;'>
551
+ <a name='B' id='B'/>
552
+ <thead>
553
+ <tr>
554
+ <th style='font-weight:bold;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;' align='center' valign='middle'>
555
+ <div class='Tableheader'>A</div>
556
+ </th>
557
+ <th style='font-weight:bold;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;' align='center' valign='middle'>
558
+ <p class='Tableheader' style='text-align: center'>B</p>
559
+ </th>
560
+ </tr>
561
+ </thead>
562
+ <tbody>
563
+ <tr>
564
+ <th style='font-weight:bold;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;'>
565
+ <div class='Tablebody'>C</div>
566
+ </th>
567
+ <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;'>
568
+ <p class='Tablebody'>D</p>
569
+ </td>
570
+ </tr>
571
+ </tbody>
572
+ <tfoot>
573
+ <tr>
574
+ <th style='font-weight:bold;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;'>
575
+ <div class='Tablebody'>E</div>
576
+ </th>
577
+ <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;'>
578
+ <p class='Tablebody'>F</p>
579
+ </td>
580
+ </tr>
581
+ </tfoot>
582
+ </table>
583
+ </div>
584
+ </div>
585
+ </div>
586
+ WORD
587
+ FileUtils.rm_f "test.doc"
588
+ IsoDoc::Iso::WordConvert.new({}).convert("test", input, false)
589
+ expect(File.exist?("test.doc")).to be true
590
+ output = File.read("test.doc", encoding: "UTF-8")
591
+ .sub(/^.*<html/m, "<html")
592
+ .sub(/<\/html>.*$/m, "</html>")
593
+ expect(xmlpp(Nokogiri::XML(output)
594
+ .at("//xmlns:div[@class = 'WordSection3']").to_xml))
595
+ .to be_equivalent_to xmlpp(word)
596
+ end
597
+
598
+ it "deals with figures" do
599
+ input = <<~INPUT
600
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
601
+ <bibdata>
602
+ <status><stage>50</stage></status>
603
+ </bibdata>
604
+ <sections>
605
+ <clause id="A">
606
+ <figure id="B">
607
+ <name>Table1</name>
608
+ <image src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" height="20" width="auto"/>
609
+ <note id="C"><p>Note</p></note>
610
+ <example id="D"><p>Example</p></example>
611
+ </figure>
612
+ </clause>
613
+ </sections>
614
+ </iso-standard>
615
+ INPUT
616
+ word = <<~WORD
617
+ <div class='WordSection3'>
618
+ <p class='zzSTDTitle1'/>
619
+ <div>
620
+ <a name='A' id='A'/>
621
+ <h1/>
622
+ <div class='figure'>
623
+ <a name='B' id='B'/>
624
+ <p class='FigureGraphic'>
625
+ <img src='_.gif' height='20' width='20'/>
626
+ </p>
627
+ <div class='Figurenote'>
628
+ <a name='C' id='C'/>
629
+ <p class='Figurenote'>
630
+ <span class='note_label'/>
631
+ <span style='mso-tab-count:1'>  </span>
632
+ Note
633
+ </p>
634
+ </div>
635
+ <div class='Example' style='page-break-after:avoid;'>
636
+ <a name='D' id='D'/>
637
+ <p class='Example'>
638
+ <span style='mso-tab-count:1'>  </span>
639
+ Example
640
+ </p>
641
+ </div>
642
+ <p class='Figuretitle' style='text-align:center;'>Table1</p>
643
+ </div>
644
+ </div>
645
+ </div>
646
+ WORD
647
+ FileUtils.rm_f "test.doc"
648
+ IsoDoc::Iso::WordConvert.new({}).convert("test", input, false)
649
+ expect(File.exist?("test.doc")).to be true
650
+ output = File.read("test.doc", encoding: "UTF-8")
651
+ .sub(/^.*<html/m, "<html")
652
+ .sub(/<\/html>.*$/m, "</html>")
653
+ expect(strip_guid(xmlpp(Nokogiri::XML(output)
654
+ .at("//xmlns:div[@class = 'WordSection3']").to_xml)))
655
+ .to be_equivalent_to xmlpp(word)
656
+ end
657
+
658
+ it "deals with examples" do
659
+ input = <<~INPUT
660
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
661
+ <bibdata>
662
+ <status><stage>50</stage></status>
663
+ </bibdata>
664
+ <sections>
665
+ <clause id="A">
666
+ <example id="B">
667
+ <p>First example</p>
668
+ </example>
669
+ <example id="C">
670
+ <p>Second example</p>
671
+ <ul>
672
+ <li>A</li>
673
+ </ul>
674
+ <p>Continuation</p>
675
+ </example>
676
+ </clause>
677
+ </sections>
678
+ </iso-standard>
679
+ INPUT
680
+ word = <<~WORD
681
+ <div class='WordSection3'>
682
+ <p class='zzSTDTitle1'/>
683
+ <div>
684
+ <a name='A' id='A'/>
685
+ <h1/>
686
+ <div class='Example'>
687
+ <a name='B' id='B'/>
688
+ <p class='Example'>
689
+ <span style='mso-tab-count:1'>  </span>
690
+ First example
691
+ </p>
692
+ </div>
693
+ <div class='Example'>
694
+ <a name='C' id='C'/>
695
+ <p class='Example'>
696
+ <span style='mso-tab-count:1'>  </span>
697
+ Second example
698
+ </p>
699
+ <p style='mso-list:l3 level1 lfo1;' class='ListContinue1'>A</p>
700
+ <p class='Examplecontinued'>Continuation</p>
701
+ </div>
702
+ </div>
703
+ </div>
704
+ WORD
705
+ FileUtils.rm_f "test.doc"
706
+ IsoDoc::Iso::WordConvert.new({}).convert("test", input, false)
707
+ expect(File.exist?("test.doc")).to be true
708
+ output = File.read("test.doc", encoding: "UTF-8")
709
+ .sub(/^.*<html/m, "<html")
710
+ .sub(/<\/html>.*$/m, "</html>")
711
+ expect(strip_guid(xmlpp(Nokogiri::XML(output)
712
+ .at("//xmlns:div[@class = 'WordSection3']").to_xml)))
713
+ .to be_equivalent_to xmlpp(word)
714
+ end
715
+
716
+ it "deals with annexes" do
717
+ input = <<~INPUT
718
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
719
+ <bibdata>
720
+ <status><stage>50</stage></status>
721
+ </bibdata>
722
+ <annex id="A"><title>Annex</title>
723
+ <clause id="B"><title>Subannex</title>
724
+ <clause id="C"><title>Subsubannex</title>
725
+ </clause>
726
+ </clause>
727
+ </annex>
728
+ </iso-standard>
729
+ INPUT
730
+ word = <<~WORD
731
+ <div class='WordSection3'>
732
+ <p class='zzSTDTitle1'/>
733
+ <p class='MsoBodyText'>
734
+ <br clear='all' style='mso-special-character:line-break;page-break-before:always'/>
735
+ </p>
736
+ <div class='Section3'>
737
+ <a name='A' id='A'/>
738
+ <p class='ANNEX'>Annex</p>
739
+ <div>
740
+ <a name='B' id='B'/>
741
+ <p class='a2'>Subannex</p>
742
+ <div>
743
+ <a name='C' id='C'/>
744
+ <p class='a3'>Subsubannex</p>
745
+ </div>
746
+ </div>
747
+ </div>
748
+ </div>
749
+ WORD
750
+ FileUtils.rm_f "test.doc"
751
+ IsoDoc::Iso::WordConvert.new({}).convert("test", input, false)
752
+ expect(File.exist?("test.doc")).to be true
753
+ output = File.read("test.doc", encoding: "UTF-8")
754
+ .sub(/^.*<html/m, "<html")
755
+ .sub(/<\/html>.*$/m, "</html>")
756
+ expect(strip_guid(xmlpp(Nokogiri::XML(output)
757
+ .at("//xmlns:div[@class = 'WordSection3']").to_xml)))
758
+ .to be_equivalent_to xmlpp(word)
759
+ end
760
+ end