isodoc 1.0.22 → 1.0.27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +12 -5
  3. data/.github/workflows/ubuntu.yml +27 -6
  4. data/.github/workflows/windows.yml +13 -7
  5. data/README.adoc +3 -2
  6. data/lib/isodoc-yaml/i18n-en.yaml +18 -1
  7. data/lib/isodoc-yaml/i18n-fr.yaml +18 -1
  8. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +18 -1
  9. data/lib/isodoc/base_style/bands.scss +6 -3
  10. data/lib/isodoc/base_style/reset.scss +1 -1
  11. data/lib/isodoc/convert.rb +1 -0
  12. data/lib/isodoc/function/blocks.rb +5 -0
  13. data/lib/isodoc/function/cleanup.rb +12 -1
  14. data/lib/isodoc/function/i18n.rb +5 -5
  15. data/lib/isodoc/function/inline.rb +47 -12
  16. data/lib/isodoc/function/references.rb +47 -33
  17. data/lib/isodoc/function/reqt.rb +21 -6
  18. data/lib/isodoc/function/section.rb +18 -8
  19. data/lib/isodoc/function/table.rb +0 -1
  20. data/lib/isodoc/function/to_word_html.rb +4 -2
  21. data/lib/isodoc/function/utils.rb +10 -4
  22. data/lib/isodoc/function/xref_gen.rb +2 -1
  23. data/lib/isodoc/function/xref_sect_gen.rb +24 -24
  24. data/lib/isodoc/headlesshtml_convert.rb +5 -0
  25. data/lib/isodoc/html_convert.rb +5 -0
  26. data/lib/isodoc/html_function/footnotes.rb +2 -2
  27. data/lib/isodoc/html_function/html.rb +3 -0
  28. data/lib/isodoc/html_function/postprocess.rb +3 -2
  29. data/lib/isodoc/metadata.rb +30 -7
  30. data/lib/isodoc/metadata_date.rb +39 -0
  31. data/lib/isodoc/pdf_convert.rb +5 -0
  32. data/lib/isodoc/version.rb +1 -1
  33. data/lib/isodoc/word_convert.rb +5 -0
  34. data/lib/isodoc/word_function/body.rb +0 -4
  35. data/lib/isodoc/word_function/footnotes.rb +2 -2
  36. data/lib/isodoc/word_function/postprocess.rb +13 -2
  37. data/lib/isodoc/word_function/table.rb +1 -3
  38. data/lib/isodoc/xslfo_convert.rb +5 -0
  39. data/spec/isodoc/blocks_spec.rb +188 -8
  40. data/spec/isodoc/cleanup_spec.rb +181 -18
  41. data/spec/isodoc/i18n_spec.rb +12 -12
  42. data/spec/isodoc/inline_spec.rb +65 -5
  43. data/spec/isodoc/metadata_spec.rb +77 -2
  44. data/spec/isodoc/postproc_spec.rb +33 -11
  45. data/spec/isodoc/ref_spec.rb +12 -6
  46. data/spec/isodoc/section_spec.rb +220 -205
  47. data/spec/isodoc/table_spec.rb +24 -24
  48. data/spec/isodoc/terms_spec.rb +50 -6
  49. data/spec/isodoc/xref_spec.rb +64 -26
  50. metadata +3 -2
@@ -108,7 +108,7 @@ module IsoDoc::HtmlFunction
108
108
  idx = docxml.at("//div[@id = 'toc']") or return docxml
109
109
  toc = "<ul>"
110
110
  path = toclevel_classes.map do |l|
111
- "//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][not(text())]"
111
+ "//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][text()]"
112
112
  end
113
113
  docxml.xpath(path.join(" | ")).each_with_index do |h, tocidx|
114
114
  h["id"] ||= "toc#{tocidx}"
@@ -159,7 +159,8 @@ module IsoDoc::HtmlFunction
159
159
  def inject_script(doc)
160
160
  return doc unless @scripts
161
161
  scripts = File.read(@scripts, encoding: "UTF-8")
162
- doc.sub("</body>", scripts + "\n</body>")
162
+ a = doc.split(%r{</body>})
163
+ a[0] + scripts + "</body>" + a[1]
163
164
  end
164
165
 
165
166
  def update_footnote_filter(fn, x, i, seen)
@@ -1,15 +1,22 @@
1
+ require_relative "./metadata_date"
2
+
1
3
  module IsoDoc
2
4
  class Metadata
3
5
  DATETYPES = %w{published accessed created implemented obsoleted confirmed
4
- updated issued received transmitted copied unchanged circulated}.freeze
6
+ updated issued received transmitted copied unchanged circulated vote-started
7
+ vote-ended}.freeze
5
8
 
6
9
  def ns(xpath)
7
10
  Common::ns(xpath)
8
11
  end
9
12
 
13
+ def l10n(a, b, c)
14
+ IsoDoc::Function::I18n::l10n(a, b, c)
15
+ end
16
+
10
17
  def initialize(lang, script, labels)
11
18
  @metadata = {}
12
- DATETYPES.each { |w| @metadata["#{w}date".to_sym] = "XXX" }
19
+ DATETYPES.each { |w| @metadata["#{w.gsub(/-/, "_")}date".to_sym] = "XXX" }
13
20
  @lang = lang
14
21
  @script = script
15
22
  @c = HTMLEntities.new
@@ -20,6 +27,10 @@ module IsoDoc
20
27
  @metadata
21
28
  end
22
29
 
30
+ def labels
31
+ @labels
32
+ end
33
+
23
34
  def set(key, value)
24
35
  @metadata[key] = value
25
36
  end
@@ -74,7 +85,7 @@ module IsoDoc
74
85
 
75
86
  def bibdate(isoxml, _out)
76
87
  isoxml.xpath(ns("//bibdata/date")).each do |d|
77
- set("#{d['type']}date".to_sym, Common::date_range(d))
88
+ set("#{d['type'].gsub(/-/, "_")}date".to_sym, Common::date_range(d))
78
89
  end
79
90
  end
80
91
 
@@ -93,14 +104,24 @@ module IsoDoc
93
104
 
94
105
  def agency(xml)
95
106
  agency = ""
107
+ publisher = []
96
108
  xml.xpath(ns("//bibdata/contributor[xmlns:role/@type = 'publisher']/"\
97
109
  "organization")).each do |org|
98
110
  name = org&.at(ns("./name"))&.text
99
- abbrev = org&.at(ns("./abbreviation"))&.text
100
- agency1 = abbrev || name
111
+ agency1 = org&.at(ns("./abbreviation"))&.text || name
112
+ publisher << name if name
101
113
  agency = iso?(org) ? "ISO/#{agency}" : "#{agency}#{agency1}/"
102
114
  end
103
115
  set(:agency, agency.sub(%r{/$}, ""))
116
+ set(:publisher, multiple_and(publisher, @labels["and"]))
117
+ end
118
+
119
+ def multiple_and(names, andword)
120
+ return "" if names.length == 0
121
+ return names[0] if names.length == 1
122
+ names.length == 2 and
123
+ return l10n("#{names[0]} #{andword} #{names[1]}", @lang, @script)
124
+ l10n(names[0..-2].join(", ") + " #{andword} #{names[-1]}", @lang, @script)
104
125
  end
105
126
 
106
127
  def docstatus(isoxml, _out)
@@ -148,14 +169,16 @@ module IsoDoc
148
169
  draftinfo += ", #{revdate}" if revdate
149
170
  draftinfo += ")"
150
171
  end
151
- IsoDoc::Function::I18n::l10n(draftinfo, @lang, @script)
172
+ l10n(draftinfo, @lang, @script)
152
173
  end
153
174
 
154
175
  def version(isoxml, _out)
155
176
  set(:edition, isoxml&.at(ns("//bibdata/edition"))&.text)
156
177
  set(:docyear, isoxml&.at(ns("//bibdata/copyright/from"))&.text)
157
178
  set(:draft, isoxml&.at(ns("//version/draft"))&.text)
158
- set(:revdate, isoxml&.at(ns("//version/revision-date"))&.text)
179
+ revdate = isoxml&.at(ns("//version/revision-date"))&.text
180
+ set(:revdate, revdate)
181
+ set(:revdate_monthyear, monthyr(revdate))
159
182
  set(:draftinfo,
160
183
  draftinfo(get[:draft], get[:revdate]))
161
184
  end
@@ -0,0 +1,39 @@
1
+ module IsoDoc
2
+ class Metadata
3
+ def months
4
+ {
5
+ "01": @labels["month_january"],
6
+ "02": @labels["month_february"],
7
+ "03": @labels["month_march"],
8
+ "04": @labels["month_april"],
9
+ "05": @labels["month_may"],
10
+ "06": @labels["month_june"],
11
+ "07": @labels["month_july"],
12
+ "08": @labels["month_august"],
13
+ "09": @labels["month_september"],
14
+ "10": @labels["month_october"],
15
+ "11": @labels["month_november"],
16
+ "12": @labels["month_december"],
17
+ }
18
+ end
19
+
20
+ def monthyr(isodate)
21
+ m = /(?<yr>\d\d\d\d)-(?<mo>\d\d)/.match isodate
22
+ return isodate unless m && m[:yr] && m[:mo]
23
+ IsoDoc::Function::I18n::l10n("#{months[m[:mo].to_sym]} #{m[:yr]}",
24
+ @lang, @script)
25
+ end
26
+
27
+ def MMMddyyyy(isodate)
28
+ return nil if isodate.nil?
29
+ arr = isodate.split("-")
30
+ date = if arr.size == 1 and (/^\d+$/.match isodate)
31
+ Date.new(*arr.map(&:to_i)).strftime("%Y")
32
+ elsif arr.size == 2
33
+ Date.new(*arr.map(&:to_i)).strftime("%B %Y")
34
+ else
35
+ Date.parse(isodate).strftime("%B %d, %Y")
36
+ end
37
+ end
38
+ end
39
+ end
@@ -22,6 +22,11 @@ module IsoDoc
22
22
  "_pdfimages"
23
23
  end
24
24
 
25
+ def initialize(options)
26
+ @format = :pdf
27
+ super
28
+ end
29
+
25
30
  def convert(filename, file = nil, debug = false)
26
31
  file = File.read(filename, encoding: "utf-8") if file.nil?
27
32
  @openmathdelim, @closemathdelim = extract_delims(file)
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "1.0.22".freeze
2
+ VERSION = "1.0.27".freeze
3
3
  end
@@ -30,6 +30,11 @@ module IsoDoc
30
30
  include WordFunction::Body
31
31
  include WordFunction::Postprocess
32
32
 
33
+ def initialize(options)
34
+ @format = :doc
35
+ super
36
+ end
37
+
33
38
  def convert(filename, file = nil, debug = false)
34
39
  ret = super
35
40
  FileUtils.rm_rf tmpimagedir
@@ -204,10 +204,6 @@ module IsoDoc::WordFunction
204
204
  alt: node["alt"],
205
205
  title: node["title"],
206
206
  width: node["width"] }
207
- if node["height"] == "auto" || node["width"] == "auto"
208
- attrs[:height] = nil
209
- attrs[:width] = nil
210
- end
211
207
  out.img **attr_code(attrs)
212
208
  image_title_parse(out, caption)
213
209
  end
@@ -56,7 +56,7 @@ module IsoDoc::WordFunction
56
56
  end
57
57
 
58
58
  def table_footnote_parse(node, out)
59
- fn = node["reference"]
59
+ fn = node["reference"] || UUIDTools::UUID.random_create.to_s
60
60
  tid = get_table_ancestor_id(node)
61
61
  make_table_footnote_link(out, tid + fn, fn)
62
62
  # do not output footnote text if we have already seen it for this table
@@ -80,7 +80,7 @@ module IsoDoc::WordFunction
80
80
  def footnote_parse(node, out)
81
81
  return table_footnote_parse(node, out) if (@in_table || @in_figure) &&
82
82
  !node.ancestors.map {|m| m.name }.include?("name")
83
- fn = node["reference"]
83
+ fn = node["reference"] || UUIDTools::UUID.random_create.to_s
84
84
  return seen_footnote_parse(node, out, fn) if @seen_footnote.include?(fn)
85
85
  @fn_bookmarks[fn] = bookmarkid
86
86
  out.span **{style: "mso-bookmark:_Ref#{@fn_bookmarks[fn]}"} do |s|
@@ -39,7 +39,6 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
39
39
  end
40
40
 
41
41
  def toWord(result, filename, dir, header)
42
- #result = populate_template(result, :word)
43
42
  result = from_xhtml(word_cleanup(to_xhtml(result)))
44
43
  unless @landscapestyle.empty?
45
44
  @wordstylesheet&.open
@@ -196,6 +195,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
196
195
  @landscapestyle = ""
197
196
  word_section_breaks1(docxml, "WordSection2")
198
197
  word_section_breaks1(docxml, "WordSection3")
198
+ word_remove_pb_before_annex(docxml)
199
+ docxml.xpath("//br[@orientation]").each { |br| br.delete("orientation") }
199
200
  end
200
201
 
201
202
  def word_section_breaks1(docxml, sect)
@@ -203,7 +204,6 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
203
204
  each_with_index do |br, i|
204
205
  @landscapestyle += "\ndiv.#{sect}_#{i} {page:#{sect}"\
205
206
  "#{br["orientation"] == "landscape" ? "L" : "P"};}\n"
206
- br.delete("orientation")
207
207
  split_at_section_break(docxml, sect, br, i)
208
208
  end
209
209
  end
@@ -219,6 +219,17 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
219
219
  end
220
220
  end
221
221
 
222
+ # applies for <div class="WordSectionN_M"><p><pagebreak/></p>...
223
+ def word_remove_pb_before_annex(docxml)
224
+ docxml.xpath("//div[p/br]").each do |d|
225
+ /^WordSection\d+_\d+$/.match(d["class"]) or next
226
+ d.elements[0].name == "p" && !d.elements[0].elements.empty? or next
227
+ d.elements[0].elements[0].name == "br" && d.elements[0].elements[0]["style"] ==
228
+ "mso-special-character:line-break;page-break-before:always" or next
229
+ d.elements[0].remove
230
+ end
231
+ end
232
+
222
233
  def word_footnote_format(docxml)
223
234
  # the content is in a[@epub:type = 'footnote']//sup, but in Word,
224
235
  # we need to inject content around the autonumbered footnote reference
@@ -37,9 +37,7 @@ module IsoDoc::WordFunction
37
37
  super.merge(attr_code({
38
38
  summary: node["summary"],
39
39
  width: node["width"],
40
- style: "mso-table-lspace:15.0cm;margin-left:423.0pt;"\
41
- "mso-table-rspace:15.0cm;margin-right:423.0pt;"\
42
- "mso-table-anchor-horizontal:column;"\
40
+ style: "mso-table-anchor-horizontal:column;"\
43
41
  "mso-table-overlap:never;border-spacing:0;border-width:1px;"
44
42
  }))
45
43
  end
@@ -13,6 +13,11 @@ module IsoDoc
13
13
  "_pdfimages"
14
14
  end
15
15
 
16
+ def initialize(options)
17
+ @format = :pdf
18
+ super
19
+ end
20
+
16
21
  def convert(filename, file = nil, debug = false)
17
22
  file = File.read(filename, encoding: "utf-8") if file.nil?
18
23
  docxml, outname_html, dir = convert_init(file, filename, debug)
@@ -417,8 +417,8 @@ B
417
417
  <div id="figureA-1" class="figure">
418
418
 
419
419
  <img src="rice_images/rice_image1.png" height="20" width="30" alt="alttext" title="titletext"/>
420
- <img src="rice_images/rice_image1.png"/>
421
- <img src="_.gif"/>
420
+ <img src="rice_images/rice_image1.png" height='20' width='auto'/>
421
+ <img src='_.gif' height='20' width='auto'/>
422
422
  <a href="#_" class="TableFootnoteRef">a</a><aside><div id="ftn_"><span><span id="_" class="TableFootnoteRef">a</span><span style="mso-tab-count:1">&#160; </span></span>
423
423
  <p id="_">The time <span class="stem">(#(t_90)#)</span> was estimated to be 18,2 min for this example.</p>
424
424
  </div></aside>
@@ -969,7 +969,7 @@ World

969
969
  INPUT
970
970
  #{HTML_HDR}
971
971
  <p class="zzSTDTitle1"/>
972
- <div><h1>1.&#160; Terms and definitions</h1>
972
+ <div><h1>1.&#160; </h1>
973
973
  <p class="TermNum" id="_extraneous_matter">1.1.</p><p class="Terms" style="text-align:left;">extraneous matter</p><p class="AltTerms" style="text-align:left;">EM</p>
974
974
 
975
975
  <p id="_318b3939-be09-46c4-a284-93f9826b981e">&lt;rice&gt; organic and inorganic components other than whole or broken kernels</p>
@@ -987,7 +987,7 @@ World

987
987
  <permission id="_">
988
988
  <label>/ogc/recommendation/wfs/2</label>
989
989
  <inherit>/ss/584/2015/level/1</inherit>
990
- <inherit>/ss/584/2015/level/2</inherit>
990
+ <inherit><eref type="inline" bibitemid="rfc2616" citeas="RFC 2616">RFC 2616 (HTTP/1.1)</eref></inherit>
991
991
  <subject>user</subject>
992
992
  <classification> <tag>control-class</tag> <value>Technical</value> </classification><classification> <tag>priority</tag> <value>P0</value> </classification><classification> <tag>family</tag> <value>System and Communications Protection</value> </classification><classification> <tag>family</tag> <value>System and Communications Protocols</value> </classification>
993
993
  <description>
@@ -1030,6 +1030,12 @@ World

1030
1030
  </import>
1031
1031
  </permission>
1032
1032
  </foreword></preface>
1033
+ <bibliography><references id="_bibliography" obligation="informative" normative="false">
1034
+ <title>Bibliography</title>
1035
+ <bibitem id="rfc2616" type="standard"> <fetched>2020-03-27</fetched> <title format="text/plain" language="en" script="Latn">Hypertext Transfer Protocol — HTTP/1.1</title> <uri type="xml">https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.2616.xml</uri> <uri type="src">https://www.rfc-editor.org/info/rfc2616</uri> <docidentifier type="IETF">RFC 2616</docidentifier> <docidentifier type="rfc-anchor">RFC2616</docidentifier> <docidentifier type="DOI">10.17487/RFC2616</docidentifier> <date type="published"> <on>1999-06</on> </date> <contributor> <role type="author"/> <person> <name> <completename language="en">R. Fielding</completename> </name> <affiliation> <organization> <name>IETF</name> <abbreviation>IETF</abbreviation> </organization> </affiliation> </person> </contributor> <contributor> <role type="author"/> <person> <name> <completename language="en">J. Gettys</completename> </name> <affiliation> <organization> <name>IETF</name> <abbreviation>IETF</abbreviation> </organization> </affiliation> </person> </contributor> <contributor> <role type="author"/> <person> <name> <completename language="en">J. Mogul</completename> </name> <affiliation> <organization> <name>IETF</name> <abbreviation>IETF</abbreviation> </organization> </affiliation> </person> </contributor> <contributor> <role type="author"/> <person> <name> <completename language="en">H. Frystyk</completename> </name> <affiliation> <organization> <name>IETF</name> <abbreviation>IETF</abbreviation> </organization> </affiliation> </person> </contributor> <contributor> <role type="author"/> <person> <name> <completename language="en">L. Masinter</completename> </name> <affiliation> <organization> <name>IETF</name> <abbreviation>IETF</abbreviation> </organization> </affiliation> </person> </contributor> <contributor> <role type="author"/> <person> <name> <completename language="en">P. Leach</completename> </name> <affiliation> <organization> <name>IETF</name> <abbreviation>IETF</abbreviation> </organization> </affiliation> </person> </contributor> <contributor> <role type="author"/> <person> <name> <completename language="en">T. Berners-Lee</completename> </name> <affiliation> <organization> <name>IETF</name> <abbreviation>IETF</abbreviation> </organization> </affiliation> </person> </contributor> <language>en</language> <script>Latn</script> <abstract format="text/plain" language="en" script="Latn">HTTP has been in use by the World-Wide Web global information initiative since 1990. This specification defines the protocol referred to as “HTTP/1.1”, and is an update to RFC 2068. [STANDARDS-TRACK]</abstract> <series type="main"> <title format="text/plain" language="en" script="Latn">RFC</title> <number>2616</number> </series> <place>Fremont, CA</place></bibitem>
1036
+
1037
+
1038
+ </references></bibliography>
1033
1039
  </iso-standard>
1034
1040
  INPUT
1035
1041
  #{HTML_HDR}
@@ -1038,9 +1044,9 @@ World

1038
1044
  <h1 class="ForewordTitle">Foreword</h1>
1039
1045
  <div class="permission"><p class="RecommendationTitle">Permission 1:<br/>/ogc/recommendation/wfs/2</p>
1040
1046
  <p><i>Subject: user<br/>
1041
- Inherit: /ss/584/2015/level/1
1047
+ Inherits: /ss/584/2015/level/1
1042
1048
  <br/>
1043
- Inherit: /ss/584/2015/level/2
1049
+ Inherits: <a href='#rfc2616'>RFC 2616 (HTTP/1.1)</a>
1044
1050
  <br/>Control-class: Technical<br/>Priority: P0<br/>Family: System and Communications Protection<br/>Family: System and Communications Protocols</i></p>
1045
1051
 
1046
1052
  <div class="requirement-description">
@@ -1064,6 +1070,14 @@ Inherit: /ss/584/2015/level/2
1064
1070
  </div>
1065
1071
  </div>
1066
1072
  <p class="zzSTDTitle1"/>
1073
+ <br/>
1074
+ <div>
1075
+ <h1 class='Section3'>Bibliography</h1>
1076
+ <p id='rfc2616' class='Biblio'>
1077
+ [1]&#160; IETF RFC 2616,
1078
+ <i>Hypertext Transfer Protocol&#8201;&#8212;&#8201;HTTP/1.1</i>
1079
+ </p>
1080
+ </div>
1067
1081
  </div>
1068
1082
  </body>
1069
1083
  </html>
@@ -1125,7 +1139,7 @@ Inherit: /ss/584/2015/level/2
1125
1139
  <br/>
1126
1140
  <div>
1127
1141
  <h1 class="ForewordTitle">Foreword</h1>
1128
- <div class="require"><p class="RecommendationTitle">Requirement:<br/>/ogc/recommendation/wfs/2. A New Requirement</p><p><i>Subject: user<br/>Inherit: /ss/584/2015/level/1</i></p>
1142
+ <div class="require"><p class="RecommendationTitle">Requirement:<br/>/ogc/recommendation/wfs/2. A New Requirement</p><p><i>Subject: user<br/>Inherits: /ss/584/2015/level/1</i></p>
1129
1143
 
1130
1144
  <div class="requirement-description">
1131
1145
  <p id="_">I recommend <i>this</i>.</p>
@@ -1154,6 +1168,121 @@ Inherit: /ss/584/2015/level/2
1154
1168
  OUTPUT
1155
1169
  end
1156
1170
 
1171
+ it "processes requirements in French" do
1172
+ expect(xmlpp(IsoDoc::HtmlConvert.new({}).convert("test", <<~"INPUT", true))).to be_equivalent_to xmlpp(<<~"OUTPUT")
1173
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
1174
+ <bibdata>
1175
+ <language>fr</language>
1176
+ <script>Latn</script>
1177
+ </bibdata>
1178
+ <preface><foreword>
1179
+ <requirement id="A" unnumbered="true">
1180
+ <title>A New Requirement</title>
1181
+ <label>/ogc/recommendation/wfs/2</label>
1182
+ <inherit>/ss/584/2015/level/1</inherit>
1183
+ <subject>user</subject>
1184
+ <description>
1185
+ <p id="_">I recommend <em>this</em>.</p>
1186
+ </description>
1187
+ <specification exclude="true" type="tabular">
1188
+ <p id="_">This is the object of the recommendation:</p>
1189
+ <table id="_">
1190
+ <tbody>
1191
+ <tr>
1192
+ <td style="text-align:left;">Object</td>
1193
+ <td style="text-align:left;">Value</td>
1194
+ </tr>
1195
+ <tr>
1196
+ <td style="text-align:left;">Mission</td>
1197
+ <td style="text-align:left;">Accomplished</td>
1198
+ </tr>
1199
+ </tbody>
1200
+ </table>
1201
+ </specification>
1202
+ <description>
1203
+ <p id="_">As for the measurement targets,</p>
1204
+ </description>
1205
+ <measurement-target exclude="false">
1206
+ <p id="_">The measurement target shall be measured as:</p>
1207
+ <formula id="B">
1208
+ <stem type="AsciiMath">r/1 = 0</stem>
1209
+ </formula>
1210
+ </measurement-target>
1211
+ <verification exclude="false">
1212
+ <p id="_">The following code will be run for verification:</p>
1213
+ <sourcecode id="_">CoreRoot(success): HttpResponse
1214
+ if (success)
1215
+ recommendation(label: success-response)
1216
+ end
1217
+ </sourcecode>
1218
+ </verification>
1219
+ <import exclude="true">
1220
+ <sourcecode id="_">success-response()</sourcecode>
1221
+ </import>
1222
+ </requirement>
1223
+ </foreword></preface>
1224
+ </iso-standard>
1225
+ INPUT
1226
+ #{HTML_HDR.gsub(/"en"/, '"fr"')}
1227
+ <br/>
1228
+ <div>
1229
+ <h1 class='ForewordTitle'>Avant-propos</h1>
1230
+ <div class='require'>
1231
+ <p class='RecommendationTitle'>
1232
+ Exigence:
1233
+ <br/>
1234
+ /ogc/recommendation/wfs/2. A New Requirement
1235
+ </p>
1236
+ <p>
1237
+ <i>
1238
+ Sujet: user
1239
+ <br/>
1240
+ H&#233;rite: /ss/584/2015/level/1
1241
+ </i>
1242
+ </p>
1243
+ <div class='requirement-description'>
1244
+ <p id='_'>
1245
+ I recommend
1246
+ <i>this</i>
1247
+ .
1248
+ </p>
1249
+ </div>
1250
+ <div class='requirement-description'>
1251
+ <p id='_'>As for the measurement targets,</p>
1252
+ </div>
1253
+ <div class='requirement-measurement-target'>
1254
+ <p id='_'>The measurement target shall be measured as:</p>
1255
+ <div id='B' class='formula'>
1256
+ <p>
1257
+ <span class='stem'>(#(r/1 = 0)#)</span>
1258
+ &#160; (1)
1259
+ </p>
1260
+ </div>
1261
+ </div>
1262
+ <div class='requirement-verification'>
1263
+ <p id='_'>The following code will be run for verification:</p>
1264
+ <pre id='_' class='prettyprint '>
1265
+ CoreRoot(success): HttpResponse
1266
+ <br/>
1267
+ &#160;&#160;&#160;&#160;&#160; if (success)
1268
+ <br/>
1269
+ &#160;&#160;&#160;&#160;&#160; recommendation(label:
1270
+ success-response)
1271
+ <br/>
1272
+ &#160;&#160;&#160;&#160;&#160; end
1273
+ <br/>
1274
+ &#160;&#160;&#160;
1275
+ </pre>
1276
+ </div>
1277
+ </div>
1278
+ </div>
1279
+ <p class='zzSTDTitle1'/>
1280
+ </div>
1281
+ </body>
1282
+ </html>
1283
+ OUTPUT
1284
+ end
1285
+
1157
1286
  it "processes recommendation" do
1158
1287
  expect(xmlpp(IsoDoc::HtmlConvert.new({}).convert("test", <<~"INPUT", true))).to be_equivalent_to xmlpp(<<~"OUTPUT")
1159
1288
  <iso-standard xmlns="http://riboseinc.com/isoxml">
@@ -1210,7 +1339,7 @@ Inherit: /ss/584/2015/level/2
1210
1339
  <br/>
1211
1340
  <div>
1212
1341
  <h1 class="ForewordTitle">Foreword</h1>
1213
- <div class="recommend"><p class="RecommendationTitle">Recommendation 1:<br/>/ogc/recommendation/wfs/2</p><p><i>Obligation: shall,could<br/>Subject: user<br/>Inherit: /ss/584/2015/level/1<br/>Type: text<br/>Language: BASIC</i></p>
1342
+ <div class="recommend"><p class="RecommendationTitle">Recommendation 1:<br/>/ogc/recommendation/wfs/2</p><p><i>Obligation: shall,could<br/>Subject: user<br/>Inherits: /ss/584/2015/level/1<br/>Type: text<br/>Language: BASIC</i></p>
1214
1343
  <div class="requirement-description">
1215
1344
  <p id="_">I recommend <i>this</i>.</p>
1216
1345
  </div>
@@ -1333,5 +1462,56 @@ INPUT
1333
1462
  OUTPUT
1334
1463
  end
1335
1464
 
1465
+ it "processes passthrough with compatible format" do
1466
+ FileUtils.rm_f "test.html"
1467
+ IsoDoc::HtmlConvert.new({}).convert("test", <<~"INPUT", false)
1468
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
1469
+ <preface><foreword>
1470
+ <passthrough format="html,rfc">&lt;A&gt;</passthrough><em>Hello</em><passthrough format="html,rfc">&lt;/A&gt;</passthrough>
1471
+ </foreword></preface>
1472
+ </iso-standard>
1473
+ INPUT
1474
+ expect(( File.read("test.html").gsub(%r{^.*<h1 class="ForewordTitle">Foreword</h1>}m, "").gsub(%r{</div>.*}m, ""))).to be_equivalent_to xmlpp(<<~"OUTPUT")
1475
+ <A><i>Hello</i></A>
1476
+ OUTPUT
1477
+ end
1478
+
1479
+ it "aborts if passthrough results in malformed XML" do
1480
+ FileUtils.rm_f "test.html"
1481
+ FileUtils.rm_f "test.html.err"
1482
+ begin
1483
+ expect { IsoDoc::HtmlConvert.new({}).convert("test", <<~"INPUT", false) }.to raise_error(SystemExit)
1484
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
1485
+ <preface><foreword>
1486
+ <passthrough format="html,rfc">&lt;A&gt;</passthrough><em>Hello</em>
1487
+ </foreword></preface>
1488
+ </iso-standard>
1489
+ INPUT
1490
+ rescue SystemExit
1491
+ end
1492
+ expect(File.exist?("test.html.err")).to be true
1493
+ end
1494
+
1495
+ it "ignore passthrough with incompatible format" do
1496
+ expect(xmlpp(IsoDoc::HtmlConvert.new({}).convert("test", <<~"INPUT", true))).to be_equivalent_to xmlpp(<<~"OUTPUT")
1497
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
1498
+ <preface><foreword>
1499
+ <passthrough format="doc,rfc">&lt;A&gt;</passthrough>
1500
+ </foreword></preface>
1501
+ </iso-standard>
1502
+ INPUT
1503
+ #{HTML_HDR}
1504
+ <br/>
1505
+ <div>
1506
+ <h1 class='ForewordTitle'>Foreword</h1>
1507
+ </div>
1508
+ <p class='zzSTDTitle1'/>
1509
+ </div>
1510
+ </body>
1511
+ </html>
1512
+ OUTPUT
1513
+ end
1514
+
1515
+
1336
1516
 
1337
1517
  end