isodoc 1.2.4 → 1.3.0

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 +4 -4
  2. data/.github/workflows/rake.yml +69 -0
  3. data/README.adoc +1 -3
  4. data/isodoc.gemspec +3 -1
  5. data/lib/isodoc-yaml/i18n-en.yaml +1 -0
  6. data/lib/isodoc-yaml/i18n-fr.yaml +8 -7
  7. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  8. data/lib/isodoc/base_style/all.css +5 -1
  9. data/lib/isodoc/base_style/blocks.scss +2 -2
  10. data/lib/isodoc/base_style/reset.css +5 -1
  11. data/lib/isodoc/base_style/reset.scss +6 -1
  12. data/lib/isodoc/base_style/typography.scss +1 -1
  13. data/lib/isodoc/convert.rb +12 -97
  14. data/lib/isodoc/css.rb +95 -0
  15. data/lib/isodoc/function/inline.rb +0 -33
  16. data/lib/isodoc/function/lists.rb +2 -1
  17. data/lib/isodoc/function/references.rb +8 -13
  18. data/lib/isodoc/function/to_word_html.rb +2 -2
  19. data/lib/isodoc/html_function/postprocess.rb +12 -3
  20. data/lib/isodoc/i18n.rb +23 -51
  21. data/lib/isodoc/metadata.rb +44 -111
  22. data/lib/isodoc/metadata_contributor.rb +90 -0
  23. data/lib/isodoc/metadata_date.rb +11 -0
  24. data/lib/isodoc/presentation_function/bibdata.rb +96 -0
  25. data/lib/isodoc/presentation_function/block.rb +14 -9
  26. data/lib/isodoc/presentation_function/inline.rb +151 -34
  27. data/lib/isodoc/presentation_xml_convert.rb +6 -0
  28. data/lib/isodoc/version.rb +1 -1
  29. data/lib/isodoc/word_convert.rb +0 -20
  30. data/lib/isodoc/word_function/body.rb +12 -0
  31. data/lib/isodoc/word_function/postprocess.rb +1 -1
  32. data/lib/isodoc/xref/xref_anchor.rb +8 -3
  33. data/lib/isodoc/xref/xref_counter.rb +20 -9
  34. data/lib/isodoc/xref/xref_gen.rb +4 -4
  35. data/lib/isodoc/xref/xref_sect_gen.rb +1 -1
  36. data/lib/isodoc/xslfo_convert.rb +6 -1
  37. data/spec/assets/html.scss +14 -0
  38. data/spec/assets/i18n.yaml +22 -5
  39. data/spec/isodoc/blocks_spec.rb +100 -221
  40. data/spec/isodoc/footnotes_spec.rb +4 -5
  41. data/spec/isodoc/i18n_spec.rb +89 -16
  42. data/spec/isodoc/inline_spec.rb +185 -163
  43. data/spec/isodoc/lists_spec.rb +1 -1
  44. data/spec/isodoc/metadata_spec.rb +69 -19
  45. data/spec/isodoc/postproc_spec.rb +33 -8
  46. data/spec/isodoc/presentation_xml_spec.rb +584 -1
  47. data/spec/isodoc/ref_spec.rb +328 -10
  48. data/spec/isodoc/section_spec.rb +9 -9
  49. data/spec/isodoc/table_spec.rb +1 -1
  50. data/spec/isodoc/terms_spec.rb +1 -1
  51. data/spec/isodoc/xref_spec.rb +35 -35
  52. data/spec/spec_helper.rb +6 -0
  53. metadata +36 -7
  54. data/.github/workflows/macos.yml +0 -42
  55. data/.github/workflows/ubuntu.yml +0 -62
  56. data/.github/workflows/windows.yml +0 -44
@@ -203,7 +203,7 @@ RSpec.describe IsoDoc do
203
203
  <br/>
204
204
  <div>
205
205
  <h1 class="ForewordTitle">Foreword</h1>
206
- <ol type="a" id="_ae34a226-aab4-496d-987b-1aa7b6314026">
206
+ <ol type="I" id="_ae34a226-aab4-496d-987b-1aa7b6314026">
207
207
  <li id="_ae34a226-aab4-496d-987b-1aa7b6314027">
208
208
  <p id="_0091a277-fb0e-424a-aea8-f0001303fe78">all information necessary for the complete identification of the sample;</p>
209
209
  </li>
@@ -7,7 +7,7 @@ RSpec.describe IsoDoc do
7
7
  arr = c.convert_init(<<~"INPUT", "test", false)
8
8
  <iso-standard xmlns="http://riboseinc.com/isoxml">
9
9
  INPUT
10
- expect(Hash[c.info(Nokogiri::XML(<<~"INPUT"), nil).sort]).to be_equivalent_to <<~"OUTPUT"
10
+ expect(metadata(c.info(Nokogiri::XML(<<~"INPUT"), nil))).to be_equivalent_to <<~"OUTPUT"
11
11
  <iso-standard xmlns="http://riboseinc.com/isoxml">
12
12
  <bibdata type="standard">
13
13
  <title>The Incredible Mr Ripley</title>
@@ -18,6 +18,8 @@ RSpec.describe IsoDoc do
18
18
  <uri type="pdf">URL D</uri>
19
19
  <uri type="doc">URL E</uri>
20
20
  <docidentifier>17301-1</docidentifier>
21
+ <docidentifier type="ISBN">ISBN 13</docidentifier>
22
+ <docidentifier type="ISBN10">ISBN 10</docidentifier>
21
23
  <docnumber>17301</docnumber>
22
24
  <date type="published"><on>2011</on></date>
23
25
  <date type="accessed"><on>2012</on></date>
@@ -73,6 +75,9 @@ RSpec.describe IsoDoc do
73
75
  </name>
74
76
  </person>
75
77
  </contributor>
78
+ <note type="title-footnote"><p>A footnote</p></note>
79
+ <note type="iso"><p>A note</p></note>
80
+ <note type="title-footnote"><p>Another footnote</p></note>
76
81
  <language>en</language>
77
82
  <script>Latn</script>
78
83
  <status>
@@ -111,25 +116,32 @@ INPUT
111
116
  :docnumeric=>"17301",
112
117
  :doctitle=>"Cereals and pulses",
113
118
  :doctype=>"International Standard",
119
+ :doctype_display=>"International Standard",
114
120
  :docyear=>"2016",
115
121
  :draft=>"0.4",
116
122
  :draftinfo=>" (draft 0.4, 2016-05-01)",
117
123
  :edition=>"2",
118
124
  :html=>"URL B",
119
125
  :implementeddate=>"XXX",
126
+ :isbn=>"ISBN 13",
127
+ :isbn10=>"ISBN 10",
120
128
  :issueddate=>"XXX",
121
129
  :iteration=>"2",
122
130
  :keywords=>["KW2", "KW1", "KW3"],
131
+ :lang=>"en",
123
132
  :obsoleteddate=>"2014",
124
133
  :pdf=>"URL D",
125
134
  :publisheddate=>"2011",
126
- :publisher=>"",
127
135
  :receiveddate=>"XXX",
128
136
  :revdate=>"2016-05-01",
129
137
  :revdate_monthyear=>"May 2016",
130
- :stage=>"Committee draft",
138
+ :script=>"Latn",
139
+ :stage=>"Committee Draft",
140
+ :stage_display=>"Committee Draft",
131
141
  :stageabbr=>"CD",
132
142
  :substage=>"Withdrawn",
143
+ :substage_display=>"Withdrawn",
144
+ :title_footnote=>["A footnote", "Another footnote"],
133
145
  :transmitteddate=>"2020",
134
146
  :unchangeddate=>"2019",
135
147
  :unpublished=>true,
@@ -146,7 +158,7 @@ OUTPUT
146
158
  arr = c.convert_init(<<~"INPUT", "test", false)
147
159
  <iso-standard xmlns="http://riboseinc.com/isoxml">
148
160
  INPUT
149
- expect(Hash[c.info(Nokogiri::XML(<<~"INPUT"), nil).sort]).to be_equivalent_to <<~"OUTPUT"
161
+ expect(metadata(c.info(Nokogiri::XML(<<~"INPUT"), nil))).to be_equivalent_to <<~"OUTPUT"
150
162
  <iso-standard xmlns="http://riboseinc.com/isoxml">
151
163
  <bibdata type="standard">
152
164
  <title language="fr" format="text/plain">Céréales et légumineuses</ti>
@@ -167,7 +179,15 @@ OUTPUT
167
179
  <role type="publisher"/>
168
180
  <organization>
169
181
  <name>International Organization for Standardization</name>
182
+ <subdivision>Subdivision</subdivision>
170
183
  <abbreviation>ISO</abbreviation>
184
+ <address>
185
+ <formattedAddress>1 Infinity Loop + California</formattedAddress>
186
+ </address>
187
+ <phone>3333333</phone>
188
+ <phone type='fax'>4444444</phone>
189
+ <email>x@example.com</email>
190
+ <uri>http://www.example.com</uri>
171
191
  </organization>
172
192
  </contributor>
173
193
  <contributor>
@@ -213,8 +233,6 @@ OUTPUT
213
233
  INPUT
214
234
  {:accesseddate=>"XXX",
215
235
  :agency=>"ISO/IEC/IEEE",
216
- :authors=>[],
217
- :authors_affiliations=>{},
218
236
  :circulateddate=>"XXX",
219
237
  :confirmeddate=>"XXX",
220
238
  :copieddate=>"XXX",
@@ -223,23 +241,31 @@ INPUT
223
241
  :docnumeric=>"17301",
224
242
  :doctitle=>"Cereals and pulses",
225
243
  :doctype=>"International Standard",
244
+ :doctype_display=>"International Standard",
226
245
  :docyear=>"2016",
227
246
  :draft=>"12",
228
247
  :draftinfo=>" (draft 12, 2016-05)",
229
- :edition=>nil,
230
248
  :implementeddate=>"XXX",
231
249
  :issueddate=>"XXX",
232
- :keywords=>[],
250
+ :lang=>"en",
233
251
  :obsoleteddate=>"XXX",
234
252
  :obsoletes=>"IEC 8121",
235
253
  :obsoletes_part=>"3.1",
236
254
  :partof=>"IEC 8122",
255
+ :pub_address=>"1 Infinity Loop + California",
256
+ :pub_email=>"x@example.com",
257
+ :pub_fax=>"4444444",
258
+ :pub_phone=>"3333333",
259
+ :pub_uri=>"http://www.example.com",
237
260
  :publisheddate=>"2011-01",
238
261
  :publisher=>"International Organization for Standardization, International Electrotechnical Commission and Institute of Electrical and Electronics Engineers",
239
262
  :receiveddate=>"XXX",
240
263
  :revdate=>"2016-05",
241
264
  :revdate_monthyear=>"May 2016",
265
+ :script=>"Latn",
242
266
  :stage=>"Published",
267
+ :stage_display=>"Published",
268
+ :subdivision=>"Subdivision",
243
269
  :transmitteddate=>"XXX",
244
270
  :unchangeddate=>"XXX",
245
271
  :unpublished=>false,
@@ -256,10 +282,21 @@ OUTPUT
256
282
  <bibdata type="standard">
257
283
  <language>fr</language>
258
284
  <script>Latn</script>
285
+ <status>
286
+ <stage lang="">Committee Draft</stage>
287
+ <stage lang=fr">Projet de comité</stage>
288
+ <substage lang="">Withdrawn</substage>
289
+ <substage lang="fr">Rétiré</substage>
290
+ <iteration>2</iteration>
291
+ </status>
292
+ <ext>
293
+ <doctype lang="">international-standard</doctype>
294
+ <doctype lang="fr">Standard international</doctype>
295
+ </ext>
259
296
  </bibdata>
260
297
  </iso-standard>
261
298
  INPUT
262
- expect(Hash[c.info(Nokogiri::XML(<<~"INPUT"), nil).sort]).to be_equivalent_to <<~"OUTPUT"
299
+ expect(metadata(c.info(Nokogiri::XML(<<~"INPUT"), nil))).to be_equivalent_to <<~"OUTPUT"
263
300
  <iso-standard xmlns="http://riboseinc.com/isoxml">
264
301
  <bibdata type="standard">
265
302
  <title language="fr" format="text/plain">Céréales et légumineuses</ti>
@@ -292,7 +329,13 @@ OUTPUT
292
329
  </contributor>
293
330
  <language>fr</language>
294
331
  <script>Latn</script>
295
- <status><stage>Published</stage></status>
332
+ <status>
333
+ <stage language="">Committee Draft</stage>
334
+ <stage language="fr">Projet de comité</stage>
335
+ <substage language="">Withdrawn</substage>
336
+ <substage language="fr">Rétiré</substage>
337
+ <iteration>2</iteration>
338
+ </status>
296
339
  <copyright>
297
340
  <from>2016</from>
298
341
  <owner>
@@ -301,37 +344,44 @@ OUTPUT
301
344
  </organization>
302
345
  </owner>
303
346
  </copyright>
347
+ <ext>
348
+ <doctype language="">international-standard</doctype>
349
+ <doctype language="fr">Standard international</doctype>
350
+ </ext>
304
351
  </bibdata>
305
352
  </iso-standard>
306
353
  INPUT
307
354
  {:accesseddate=>"XXX",
308
355
  :agency=>"ISO/IEC",
309
- :authors=>[],
310
- :authors_affiliations=>{},
311
356
  :circulateddate=>"XXX",
312
357
  :confirmeddate=>"XXX",
313
358
  :copieddate=>"XXX",
314
359
  :createddate=>"XXX",
315
360
  :docnumber=>"17301-1-3",
316
361
  :docnumeric=>"17301",
317
- :doctitle=>"Cereals and pulses",
362
+ :doctitle=>"Céréales et légumineuses",
363
+ :doctype=>"International Standard",
364
+ :doctype_display=>"Standard International",
318
365
  :docyear=>"2016",
319
- :draft=>nil,
320
- :draftinfo=>"",
321
- :edition=>nil,
322
366
  :implementeddate=>"XXX",
323
367
  :issueddate=>"XXX",
324
- :keywords=>[],
368
+ :iteration=>"2",
369
+ :lang=>"fr",
325
370
  :obsoleteddate=>"XXX",
326
371
  :publisheddate=>"2011-01",
327
372
  :publisher=>"International Organization for Standardization et International Electrotechnical Commission",
328
373
  :receiveddate=>"XXX",
329
374
  :revdate=>"2016-05",
330
375
  :revdate_monthyear=>"Mai 2016",
331
- :stage=>"Published",
376
+ :script=>"Latn",
377
+ :stage=>"Committee Draft",
378
+ :stage_display=>"Projet De Comité",
379
+ :stageabbr=>"CD",
380
+ :substage=>"Withdrawn",
381
+ :substage_display=>"Rétiré",
332
382
  :transmitteddate=>"XXX",
333
383
  :unchangeddate=>"XXX",
334
- :unpublished=>false,
384
+ :unpublished=>true,
335
385
  :updateddate=>"XXX",
336
386
  :vote_endeddate=>"XXX",
337
387
  :vote_starteddate=>"XXX"}
@@ -139,7 +139,7 @@ expect(File.exist?("test.doc")).to be true
139
139
  it "generates HTML output docs with complete configuration" do
140
140
  FileUtils.rm_f "test.doc"
141
141
  FileUtils.rm_f "test.html"
142
- IsoDoc::HtmlConvert.new({bodyfont: "Zapf", htmlstylesheet: "spec/assets/html.scss", htmlcoverpage: "spec/assets/htmlcover.html", htmlintropage: "spec/assets/htmlintro.html", scripts: "spec/assets/scripts.html", i18nyaml: "spec/assets/i18n.yaml", ulstyle: "l1", olstyle: "l2"}).convert("test", <<~"INPUT", false)
142
+ IsoDoc::HtmlConvert.new({bodyfont: "Zapf", monospacefont: "Consolas", headerfont: "Comic Sans", normalfontsize: "30pt", monospacefontsize: "29pt", smallerfontsize: "28pt", footnotefontsize: "27pt", htmlstylesheet: "spec/assets/html.scss", htmlcoverpage: "spec/assets/htmlcover.html", htmlintropage: "spec/assets/htmlintro.html", scripts: "spec/assets/scripts.html", i18nyaml: "spec/assets/i18n.yaml", ulstyle: "l1", olstyle: "l2"}).convert("test", <<~"INPUT", false)
143
143
  <iso-standard xmlns="http://riboseinc.com/isoxml">
144
144
  <preface><foreword>
145
145
  <note>
@@ -150,7 +150,13 @@ expect(File.exist?("test.doc")).to be true
150
150
  INPUT
151
151
  html = File.read("test.html")
152
152
  expect(html).to match(/another empty stylesheet/)
153
- expect(html).to match(/font-family: Zapf/)
153
+ expect(html).to match(/p \{[^}]*?font-family: Zapf/m)
154
+ expect(html).to match(/code \{[^}]*?font-family: Consolas/m)
155
+ expect(html).to match(/h1 \{[^}]*?font-family: Comic Sans/m)
156
+ expect(html).to match(/p \{[^}]*?font-size: 30pt/m)
157
+ expect(html).to match(/code \{[^}]*?font-size: 29pt/m)
158
+ expect(html).to match(/p\.note \{[^}]*?font-size: 28pt/m)
159
+ expect(html).to match(/aside \{[^}]*?font-size: 27pt/m)
154
160
  expect(html).to match(/an empty html cover page/)
155
161
  expect(html).to match(/an empty html intro page/)
156
162
  expect(html).to match(/This is > a script/)
@@ -172,7 +178,13 @@ expect(File.exist?("test.doc")).to be true
172
178
  INPUT
173
179
  html = File.read("test.html")
174
180
  expect(html).to match(/another empty stylesheet/)
175
- expect(html).to match(/font-family: Arial/)
181
+ expect(html).to match(/p \{[^}]*?font-family: Arial/m)
182
+ expect(html).to match(/code \{[^}]*?font-family: Courier/m)
183
+ expect(html).to match(/h1 \{[^}]*?font-family: Arial/m)
184
+ expect(html).to match(/p \{[^}]*?font-size: 1em;/m)
185
+ expect(html).to match(/code \{[^}]*?font-size: 0.8em/m)
186
+ expect(html).to match(/p\.note \{[^}]*?font-size: 0.9em/m)
187
+ expect(html).to match(/aside \{[^}]*?font-size: 0.9em/m)
176
188
  expect(html).to match(/an empty html cover page/)
177
189
  expect(html).to match(/an empty html intro page/)
178
190
  expect(html).to match(/This is > a script/)
@@ -183,7 +195,7 @@ expect(File.exist?("test.doc")).to be true
183
195
  it "generates Word output docs with complete configuration" do
184
196
  FileUtils.rm_f "test.doc"
185
197
  FileUtils.rm_f "test.html"
186
- IsoDoc::WordConvert.new({bodyfont: "Zapf", wordstylesheet: "spec/assets/html.scss", standardstylesheet: "spec/assets/std.css", header: "spec/assets/header.html", wordcoverpage: "spec/assets/wordcover.html", wordintropage: "spec/assets/wordintro.html", i18nyaml: "spec/assets/i18n.yaml", ulstyle: "l1", olstyle: "l2"}).convert("test", <<~"INPUT", false)
198
+ IsoDoc::WordConvert.new({bodyfont: "Zapf", monospacefont: "Consolas", headerfont: "Comic Sans", normalfontsize: "30pt", monospacefontsize: "29pt", smallerfontsize: "28pt", footnotefontsize: "27pt", wordstylesheet: "spec/assets/html.scss", standardstylesheet: "spec/assets/std.css", header: "spec/assets/header.html", wordcoverpage: "spec/assets/wordcover.html", wordintropage: "spec/assets/wordintro.html", i18nyaml: "spec/assets/i18n.yaml", ulstyle: "l1", olstyle: "l2"}).convert("test", <<~"INPUT", false)
187
199
  <iso-standard xmlns="http://riboseinc.com/isoxml">
188
200
  <preface><foreword>
189
201
  <note>
@@ -194,7 +206,13 @@ expect(File.exist?("test.doc")).to be true
194
206
  INPUT
195
207
  word = File.read("test.doc")
196
208
  expect(word).to match(/another empty stylesheet/)
197
- expect(word).to match(/font-family: Zapf/)
209
+ expect(word).to match(/p \{[^}]*?font-family: Zapf/m)
210
+ expect(word).to match(/code \{[^}]*?font-family: Consolas/m)
211
+ expect(word).to match(/h1 \{[^}]*?font-family: Comic Sans/m)
212
+ expect(word).to match(/p \{[^}]*?font-size: 30pt/m)
213
+ expect(word).to match(/code \{[^}]*?font-size: 29pt/m)
214
+ expect(word).to match(/p\.note \{[^}]*?font-size: 28pt/m)
215
+ expect(word).to match(/aside \{[^}]*?font-size: 27pt/m)
198
216
  expect(word).to match(/a third empty stylesheet/)
199
217
  #expect(word).to match(/<title>test<\/title>/)
200
218
  expect(word).to match(/test_files\/header.html/)
@@ -217,7 +235,13 @@ expect(File.exist?("test.doc")).to be true
217
235
  INPUT
218
236
  word = File.read("test.doc")
219
237
  expect(word).to match(/another empty stylesheet/)
220
- expect(word).to match(/font-family: Arial/)
238
+ expect(word).to match(/p \{[^}]*?font-family: Arial/m)
239
+ expect(word).to match(/code \{[^}]*?font-family: Courier/m)
240
+ expect(word).to match(/h1 \{[^}]*?font-family: Arial/m)
241
+ expect(word).to match(/p \{[^}]*?font-size: 12pt/m)
242
+ expect(word).to match(/code \{[^}]*?font-size: 11pt/m)
243
+ expect(word).to match(/p\.note \{[^}]*?font-size: 10pt/m)
244
+ expect(word).to match(/aside \{[^}]*?font-size: 9pt/m)
221
245
  expect(word).to match(/a third empty stylesheet/)
222
246
  #expect(word).to match(/<title>test<\/title>/)
223
247
  expect(word).to match(/test_files\/header.html/)
@@ -512,7 +536,7 @@ TOCLEVEL
512
536
  <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6">This is a footnote.</p>
513
537
  </fn><clause id="N" inline-header="false" obligation="normative">
514
538
  <title>Introduction to this<fn reference="2">
515
- <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6">Formerly denoted as 15 % (m/m).</p>
539
+ Formerly denoted as 15 % (m/m).
516
540
  </fn></title>
517
541
  </clause>
518
542
  <clause id="O" inline-header="false" obligation="normative">
@@ -548,7 +572,7 @@ TOCLEVEL
548
572
  </a>This is a footnote.</p>
549
573
  <a href="#fnref:1">&#x21A9;</a></aside>
550
574
  <aside id="fn:2" class="footnote">
551
- <p id="_ff27c067-2785-4551-96cf-0a73530ff1e6"><a class='FootnoteRef' href='#fn:2'><sup>2</sup></a>Formerly denoted as 15 % (m/m).</p>
575
+ <a class='FootnoteRef' href='#fn:2'><sup>2</sup></a>Formerly denoted as 15 % (m/m).
552
576
  <a href="#fnref:2">&#x21A9;</a></aside>
553
577
  </main>
554
578
  OUTPUT
@@ -905,6 +929,7 @@ TOCLEVEL
905
929
  </m:r>
906
930
  </m:oMath>
907
931
  </span>
932
+ <span style='mso-tab-count:1'>&#xA0; </span>
908
933
  </p>
909
934
  </div>
910
935
  </div>
@@ -1,5 +1,5 @@
1
1
  require "spec_helper"
2
-
2
+
3
3
  RSpec.describe IsoDoc do
4
4
  it "generates file based on string input" do
5
5
  FileUtils.rm_f "test.presentation.xml"
@@ -17,4 +17,587 @@ it "generates file based on string input" do
17
17
  INPUT
18
18
  expect(File.exist?("test.presentation.xml")).to be true
19
19
  end
20
+
21
+ it "localises numbers in MathML" do
22
+ expect(xmlpp(IsoDoc::PresentationXMLConvert.new({}).convert("test", <<~INPUT, true)).sub(%r{<localized-strings>.*</localized-strings>}m, "")).to be_equivalent_to xmlpp(<<~OUTPUT)
23
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
24
+ <bibdata>
25
+ <title language="en">test</title>
26
+ </bibdata>
27
+ <preface>
28
+ <p><stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>30000</mn></math></stem>
29
+ <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>P</mi><mfenced open="(" close=")"><mrow><mi>X</mi><mo>≥</mo><msub><mrow><mi>X</mi></mrow><mrow><mo>max</mo></mrow></msub></mrow></mfenced><mo>=</mo><munderover><mrow><mo>∑</mo></mrow><mrow><mrow><mi>j</mi><mo>=</mo><msub><mrow><mi>X</mi></mrow><mrow><mo>max</mo></mrow></msub></mrow></mrow><mrow><mn>1000</mn></mrow></munderover><mfenced open="(" close=")"><mtable><mtr><mtd><mn>1000</mn></mtd></mtr><mtr><mtd><mi>j</mi></mtd></mtr></mtable></mfenced><msup><mrow><mi>p</mi></mrow><mrow><mi>j</mi></mrow></msup><msup><mrow><mfenced open="(" close=")"><mrow><mn>1</mn><mo>−</mo><mi>p</mi></mrow></mfenced></mrow><mrow><mrow><mn>1.003</mn><mo>−</mo><mi>j</mi></mrow></mrow></msup></math></stem></p>
30
+ </preface>
31
+ </iso-standard>
32
+ INPUT
33
+ <iso-standard xmlns='http://riboseinc.com/isoxml' type='presentation'>
34
+ <bibdata>
35
+ <title language='en'>test</title>
36
+ </bibdata>
37
+
38
+ <preface>
39
+ <p>
40
+ <stem type='MathML'>30,000</stem>
41
+ <stem type='MathML'>
42
+ <math xmlns='http://www.w3.org/1998/Math/MathML'>
43
+ <mi>P</mi>
44
+ <mfenced open='(' close=')'>
45
+ <mrow>
46
+ <mi>X</mi>
47
+ <mo>&#x2265;</mo>
48
+ <msub>
49
+ <mrow>
50
+ <mi>X</mi>
51
+ </mrow>
52
+ <mrow>
53
+ <mo>max</mo>
54
+ </mrow>
55
+ </msub>
56
+ </mrow>
57
+ </mfenced>
58
+ <mo>=</mo>
59
+ <munderover>
60
+ <mrow>
61
+ <mo>&#x2211;</mo>
62
+ </mrow>
63
+ <mrow>
64
+ <mrow>
65
+ <mi>j</mi>
66
+ <mo>=</mo>
67
+ <msub>
68
+ <mrow>
69
+ <mi>X</mi>
70
+ </mrow>
71
+ <mrow>
72
+ <mo>max</mo>
73
+ </mrow>
74
+ </msub>
75
+ </mrow>
76
+ </mrow>
77
+ <mrow>
78
+ <mn>1,000</mn>
79
+ </mrow>
80
+ </munderover>
81
+ <mfenced open='(' close=')'>
82
+ <mtable>
83
+ <mtr>
84
+ <mtd>
85
+ <mn>1,000</mn>
86
+ </mtd>
87
+ </mtr>
88
+ <mtr>
89
+ <mtd>
90
+ <mi>j</mi>
91
+ </mtd>
92
+ </mtr>
93
+ </mtable>
94
+ </mfenced>
95
+ <msup>
96
+ <mrow>
97
+ <mi>p</mi>
98
+ </mrow>
99
+ <mrow>
100
+ <mi>j</mi>
101
+ </mrow>
102
+ </msup>
103
+ <msup>
104
+ <mrow>
105
+ <mfenced open='(' close=')'>
106
+ <mrow>
107
+ <mn>1</mn>
108
+ <mo>&#x2212;</mo>
109
+ <mi>p</mi>
110
+ </mrow>
111
+ </mfenced>
112
+ </mrow>
113
+ <mrow>
114
+ <mrow>
115
+ <mn>1.003</mn>
116
+ <mo>&#x2212;</mo>
117
+ <mi>j</mi>
118
+ </mrow>
119
+ </mrow>
120
+ </msup>
121
+ </math>
122
+ </stem>
123
+ </p>
124
+ </preface>
125
+ </iso-standard>
126
+ OUTPUT
127
+ end
128
+
129
+ context 'when twitter_cldr_localiser_symbols has additional options' do
130
+ let(:input) do
131
+ <<~INPUT
132
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
133
+ <bibdata>
134
+ <title language="en">test</title>
135
+ </bibdata>
136
+ <preface>
137
+ <p>
138
+ <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>30000</mn></math></stem>
139
+ <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML">
140
+ <mi>P</mi>
141
+ <mfenced open="(" close=")">
142
+ <mrow>
143
+ <mi>X</mi>
144
+ <mo>≥</mo>
145
+ <msub>
146
+ <mrow>
147
+ <mi>X</mi>
148
+ </mrow>
149
+ <mrow>
150
+ <mo>max</mo>
151
+ </mrow>
152
+ </msub>
153
+ </mrow>
154
+ </mfenced>
155
+ <mo>=</mo>
156
+ <munderover>
157
+ <mrow>
158
+ <mo>∑</mo>
159
+ </mrow>
160
+ <mrow>
161
+ <mrow>
162
+ <mi>j</mi>
163
+ <mo>=</mo>
164
+ <msub>
165
+ <mrow>
166
+ <mi>X</mi>
167
+ </mrow>
168
+ <mrow>
169
+ <mo>max</mo>
170
+ </mrow>
171
+ </msub>
172
+ </mrow>
173
+ </mrow>
174
+ <mrow>
175
+ <mn>1000</mn>
176
+ </mrow>
177
+ </munderover>
178
+ <mfenced open="(" close=")">
179
+ <mtable>
180
+ <mtr>
181
+ <mtd>
182
+ <mn>1000</mn>
183
+ </mtd>
184
+ </mtr>
185
+ <mtr>
186
+ <mtd>
187
+ <mi>j</mi>
188
+ </mtd>
189
+ </mtr>
190
+ </mtable>
191
+ </mfenced>
192
+ <msup>
193
+ <mrow>
194
+ <mi>p</mi>
195
+ </mrow>
196
+ <mrow>
197
+ <mi>j</mi>
198
+ </mrow>
199
+ </msup>
200
+ <msup>
201
+ <mrow>
202
+ <mfenced open="(" close=")">
203
+ <mrow>
204
+ <mn>1</mn>
205
+ <mo>−</mo>
206
+ <mi>p</mi>
207
+ </mrow>
208
+ </mfenced>
209
+ </mrow>
210
+ <mrow>
211
+ <mrow>
212
+ <mn>1.003</mn>
213
+ <mo>−</mo>
214
+ <mi>j</mi>
215
+ </mrow>
216
+ </mrow>
217
+ </msup>
218
+ <msup>
219
+ <mrow>
220
+ <mfenced open="(" close=")">
221
+ <mrow>
222
+ <mn>1</mn>
223
+ <mo>−</mo>
224
+ <mi>p</mi>
225
+ </mrow>
226
+ </mfenced>
227
+ </mrow>
228
+ <mrow>
229
+ <mrow>
230
+ <mn>459384.123456789</mn>
231
+ <mo>−</mo>
232
+ <mi>j</mi>
233
+ </mrow>
234
+ </mrow>
235
+ </msup>
236
+ </math></stem>
237
+ </p>
238
+ </preface>
239
+ </iso-standard>
240
+ INPUT
241
+ end
242
+ let(:output) do
243
+ <<~OUTPUT
244
+ <iso-standard xmlns='http://riboseinc.com/isoxml' type='presentation'>
245
+ <bibdata>
246
+ <title language='en'>test</title>
247
+ </bibdata>
248
+
249
+ <preface>
250
+ <p>
251
+ <stem type='MathML'>30,000</stem>
252
+ <stem type='MathML'>
253
+ <math xmlns='http://www.w3.org/1998/Math/MathML'>
254
+ <mi>P</mi>
255
+ <mfenced open='(' close=')'>
256
+ <mrow>
257
+ <mi>X</mi>
258
+ <mo>&#x2265;</mo>
259
+ <msub>
260
+ <mrow>
261
+ <mi>X</mi>
262
+ </mrow>
263
+ <mrow>
264
+ <mo>max</mo>
265
+ </mrow>
266
+ </msub>
267
+ </mrow>
268
+ </mfenced>
269
+ <mo>=</mo>
270
+ <munderover>
271
+ <mrow>
272
+ <mo>&#x2211;</mo>
273
+ </mrow>
274
+ <mrow>
275
+ <mrow>
276
+ <mi>j</mi>
277
+ <mo>=</mo>
278
+ <msub>
279
+ <mrow>
280
+ <mi>X</mi>
281
+ </mrow>
282
+ <mrow>
283
+ <mo>max</mo>
284
+ </mrow>
285
+ </msub>
286
+ </mrow>
287
+ </mrow>
288
+ <mrow>
289
+ <mn>1,000</mn>
290
+ </mrow>
291
+ </munderover>
292
+ <mfenced open='(' close=')'>
293
+ <mtable>
294
+ <mtr>
295
+ <mtd>
296
+ <mn>1,000</mn>
297
+ </mtd>
298
+ </mtr>
299
+ <mtr>
300
+ <mtd>
301
+ <mi>j</mi>
302
+ </mtd>
303
+ </mtr>
304
+ </mtable>
305
+ </mfenced>
306
+ <msup>
307
+ <mrow>
308
+ <mi>p</mi>
309
+ </mrow>
310
+ <mrow>
311
+ <mi>j</mi>
312
+ </mrow>
313
+ </msup>
314
+ <msup>
315
+ <mrow>
316
+ <mfenced open='(' close=')'>
317
+ <mrow>
318
+ <mn>1</mn>
319
+ <mo>&#x2212;</mo>
320
+ <mi>p</mi>
321
+ </mrow>
322
+ </mfenced>
323
+ </mrow>
324
+ <mrow>
325
+ <mrow>
326
+ <mn>1.00'3</mn>
327
+ <mo>&#x2212;</mo>
328
+ <mi>j</mi>
329
+ </mrow>
330
+ </mrow>
331
+ </msup>
332
+ <msup>
333
+ <mrow>
334
+ <mfenced open='(' close=')'>
335
+ <mrow>
336
+ <mn>1</mn>
337
+ <mo>&#x2212;</mo>
338
+ <mi>p</mi>
339
+ </mrow>
340
+ </mfenced>
341
+ </mrow>
342
+ <mrow>
343
+ <mrow>
344
+ <mn>459,384.12'34'56</mn>
345
+ <mo>&#x2212;</mo>
346
+ <mi>j</mi>
347
+ </mrow>
348
+ </mrow>
349
+ </msup>
350
+ </math>
351
+ </stem>
352
+ </p>
353
+ </preface>
354
+ </iso-standard>
355
+ OUTPUT
356
+ end
357
+ let(:additional_symbols) do
358
+ {
359
+ fraction_group_digits: 2,
360
+ fraction_group: "'",
361
+ precision: 5
362
+ }
363
+ end
364
+
365
+ before do
366
+ allow_any_instance_of(IsoDoc::PresentationXMLConvert)
367
+ .to(receive(:twitter_cldr_localiser_symbols).and_return(additional_symbols))
368
+ end
369
+
370
+ it "Supports twitter_cldr_localiser_symbols fraction options" do
371
+ expect(xmlpp(IsoDoc::PresentationXMLConvert.new({}).convert("test", input, true))
372
+ .sub(%r{<localized-strings>.*</localized-strings>}m, ""))
373
+ .to(be_equivalent_to(xmlpp(output)))
374
+ end
375
+ end
376
+
377
+ it "localises numbers in MathML in French" do
378
+ expect(xmlpp(IsoDoc::PresentationXMLConvert.new({}).convert("test", <<~INPUT, true)).sub(%r{<localized-strings>.*</localized-strings>}m, "")).to be_equivalent_to xmlpp(<<~OUTPUT)
379
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
380
+ <bibdata>
381
+ <title language="en">test</title>
382
+ <language>fr</language>
383
+ </bibdata>
384
+ <preface>
385
+ <p><stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>30000</mn></math></stem>
386
+ <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>P</mi><mfenced open="(" close=")"><mrow><mi>X</mi><mo>≥</mo><msub><mrow><mi>X</mi></mrow><mrow><mo>max</mo></mrow></msub></mrow></mfenced><mo>=</mo><munderover><mrow><mo>∑</mo></mrow><mrow><mrow><mi>j</mi><mo>=</mo><msub><mrow><mi>X</mi></mrow><mrow><mo>max</mo></mrow></msub></mrow></mrow><mrow><mn>1000</mn></mrow></munderover><mfenced open="(" close=")"><mtable><mtr><mtd><mn>1000</mn></mtd></mtr><mtr><mtd><mi>j</mi></mtd></mtr></mtable></mfenced><msup><mrow><mi>p</mi></mrow><mrow><mi>j</mi></mrow></msup><msup><mrow><mfenced open="(" close=")"><mrow><mn>1</mn><mo>−</mo><mi>p</mi></mrow></mfenced></mrow><mrow><mrow><mn>1.003</mn><mo>−</mo><mi>j</mi></mrow></mrow></msup></math></stem></p>
387
+ </preface>
388
+ </iso-standard>
389
+ INPUT
390
+ <iso-standard xmlns='http://riboseinc.com/isoxml' type='presentation'>
391
+ <bibdata>
392
+ <title language='en'>test</title>
393
+ <language current='true'>fr</language>
394
+ </bibdata>
395
+
396
+ <preface>
397
+ <p>
398
+ <stem type='MathML'>30&#x202F;000</stem>
399
+ <stem type='MathML'>
400
+ <math xmlns='http://www.w3.org/1998/Math/MathML'>
401
+ <mi>P</mi>
402
+ <mfenced open='(' close=')'>
403
+ <mrow>
404
+ <mi>X</mi>
405
+ <mo>&#x2265;</mo>
406
+ <msub>
407
+ <mrow>
408
+ <mi>X</mi>
409
+ </mrow>
410
+ <mrow>
411
+ <mo>max</mo>
412
+ </mrow>
413
+ </msub>
414
+ </mrow>
415
+ </mfenced>
416
+ <mo>=</mo>
417
+ <munderover>
418
+ <mrow>
419
+ <mo>&#x2211;</mo>
420
+ </mrow>
421
+ <mrow>
422
+ <mrow>
423
+ <mi>j</mi>
424
+ <mo>=</mo>
425
+ <msub>
426
+ <mrow>
427
+ <mi>X</mi>
428
+ </mrow>
429
+ <mrow>
430
+ <mo>max</mo>
431
+ </mrow>
432
+ </msub>
433
+ </mrow>
434
+ </mrow>
435
+ <mrow>
436
+ <mn>1&#x202F;000</mn>
437
+ </mrow>
438
+ </munderover>
439
+ <mfenced open='(' close=')'>
440
+ <mtable>
441
+ <mtr>
442
+ <mtd>
443
+ <mn>1&#x202F;000</mn>
444
+ </mtd>
445
+ </mtr>
446
+ <mtr>
447
+ <mtd>
448
+ <mi>j</mi>
449
+ </mtd>
450
+ </mtr>
451
+ </mtable>
452
+ </mfenced>
453
+ <msup>
454
+ <mrow>
455
+ <mi>p</mi>
456
+ </mrow>
457
+ <mrow>
458
+ <mi>j</mi>
459
+ </mrow>
460
+ </msup>
461
+ <msup>
462
+ <mrow>
463
+ <mfenced open='(' close=')'>
464
+ <mrow>
465
+ <mn>1</mn>
466
+ <mo>&#x2212;</mo>
467
+ <mi>p</mi>
468
+ </mrow>
469
+ </mfenced>
470
+ </mrow>
471
+ <mrow>
472
+ <mrow>
473
+ <mn>1,003</mn>
474
+ <mo>&#x2212;</mo>
475
+ <mi>j</mi>
476
+ </mrow>
477
+ </mrow>
478
+ </msup>
479
+ </math>
480
+ </stem>
481
+ </p>
482
+ </preface>
483
+ </iso-standard>
484
+ OUTPUT
485
+ end
486
+
487
+ it "customises localisation of numbers" do
488
+ mock_symbols
489
+ expect(xmlpp(IsoDoc::PresentationXMLConvert.new({}).convert("test", <<~INPUT, true)).sub(%r{<localized-strings>.*</localized-strings>}m, "")).to be_equivalent_to xmlpp(<<~OUTPUT)
490
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
491
+ <bibdata>
492
+ <title language="en">test</title>
493
+ <language>fr</language>
494
+ </bibdata>
495
+ <preface>
496
+ <p><stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>30000</mn></math></stem>
497
+ <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>P</mi><mfenced open="(" close=")"><mrow><mi>X</mi><mo>≥</mo><msub><mrow><mi>X</mi></mrow><mrow><mo>max</mo></mrow></msub></mrow></mfenced><mo>=</mo><munderover><mrow><mo>∑</mo></mrow><mrow><mrow><mi>j</mi><mo>=</mo><msub><mrow><mi>X</mi></mrow><mrow><mo>max</mo></mrow></msub></mrow></mrow><mrow><mn>1000</mn></mrow></munderover><mfenced open="(" close=")"><mtable><mtr><mtd><mn>1000</mn></mtd></mtr><mtr><mtd><mi>j</mi></mtd></mtr></mtable></mfenced><msup><mrow><mi>p</mi></mrow><mrow><mi>j</mi></mrow></msup><msup><mrow><mfenced open="(" close=")"><mrow><mn>0.0000032</mn><mo>−</mo><mi>p</mi></mrow></mfenced></mrow><mrow><mrow><mn>1.003</mn><mo>−</mo><mi>j</mi></mrow></mrow></msup></math></stem></p>
498
+ </preface>
499
+ </iso-standard>
500
+ INPUT
501
+ <iso-standard xmlns='http://riboseinc.com/isoxml' type='presentation'>
502
+ <bibdata>
503
+ <title language='en'>test</title>
504
+ <language current='true'>fr</language>
505
+ </bibdata>
506
+
507
+ <preface>
508
+ <p>
509
+ <stem type='MathML'>30'000</stem>
510
+ <stem type='MathML'>
511
+ <math xmlns='http://www.w3.org/1998/Math/MathML'>
512
+ <mi>P</mi>
513
+ <mfenced open='(' close=')'>
514
+ <mrow>
515
+ <mi>X</mi>
516
+ <mo>&#x2265;</mo>
517
+ <msub>
518
+ <mrow>
519
+ <mi>X</mi>
520
+ </mrow>
521
+ <mrow>
522
+ <mo>max</mo>
523
+ </mrow>
524
+ </msub>
525
+ </mrow>
526
+ </mfenced>
527
+ <mo>=</mo>
528
+ <munderover>
529
+ <mrow>
530
+ <mo>&#x2211;</mo>
531
+ </mrow>
532
+ <mrow>
533
+ <mrow>
534
+ <mi>j</mi>
535
+ <mo>=</mo>
536
+ <msub>
537
+ <mrow>
538
+ <mi>X</mi>
539
+ </mrow>
540
+ <mrow>
541
+ <mo>max</mo>
542
+ </mrow>
543
+ </msub>
544
+ </mrow>
545
+ </mrow>
546
+ <mrow>
547
+ <mn>1'000</mn>
548
+ </mrow>
549
+ </munderover>
550
+ <mfenced open='(' close=')'>
551
+ <mtable>
552
+ <mtr>
553
+ <mtd>
554
+ <mn>1'000</mn>
555
+ </mtd>
556
+ </mtr>
557
+ <mtr>
558
+ <mtd>
559
+ <mi>j</mi>
560
+ </mtd>
561
+ </mtr>
562
+ </mtable>
563
+ </mfenced>
564
+ <msup>
565
+ <mrow>
566
+ <mi>p</mi>
567
+ </mrow>
568
+ <mrow>
569
+ <mi>j</mi>
570
+ </mrow>
571
+ </msup>
572
+ <msup>
573
+ <mrow>
574
+ <mfenced open='(' close=')'>
575
+ <mrow>
576
+ <mn>0,0000032</mn>
577
+ <mo>&#x2212;</mo>
578
+ <mi>p</mi>
579
+ </mrow>
580
+ </mfenced>
581
+ </mrow>
582
+ <mrow>
583
+ <mrow>
584
+ <mn>1,003</mn>
585
+ <mo>&#x2212;</mo>
586
+ <mi>j</mi>
587
+ </mrow>
588
+ </mrow>
589
+ </msup>
590
+ </math>
591
+ </stem>
592
+ </p>
593
+ </preface>
594
+ </iso-standard>
595
+ OUTPUT
596
+ end
597
+
598
+ private
599
+
600
+ def mock_symbols
601
+ allow_any_instance_of(::IsoDoc::PresentationXMLConvert).to receive(:twitter_cldr_localiser_symbols).and_return(group: "'")
602
+ end
20
603
  end