isodoc 1.2.7 → 1.4.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +14 -9
  3. data/README.adoc +1 -3
  4. data/isodoc.gemspec +1 -1
  5. data/lib/isodoc-yaml/i18n-en.yaml +56 -0
  6. data/lib/isodoc-yaml/i18n-fr.yaml +64 -7
  7. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  8. data/lib/isodoc/base_style/blocks.scss +2 -2
  9. data/lib/isodoc/base_style/typography.scss +1 -1
  10. data/lib/isodoc/convert.rb +13 -85
  11. data/lib/isodoc/css.rb +95 -0
  12. data/lib/isodoc/function/inline.rb +0 -33
  13. data/lib/isodoc/function/inline_simple.rb +10 -1
  14. data/lib/isodoc/function/lists.rb +2 -1
  15. data/lib/isodoc/function/references.rb +8 -13
  16. data/lib/isodoc/function/section.rb +1 -1
  17. data/lib/isodoc/function/table.rb +10 -0
  18. data/lib/isodoc/function/to_word_html.rb +2 -2
  19. data/lib/isodoc/gem_tasks.rb +4 -0
  20. data/lib/isodoc/html_function/html.rb +7 -0
  21. data/lib/isodoc/html_function/mathvariant_to_plain.rb +82 -0
  22. data/lib/isodoc/html_function/postprocess.rb +41 -20
  23. data/lib/isodoc/i18n.rb +15 -2
  24. data/lib/isodoc/metadata_contributor.rb +4 -3
  25. data/lib/isodoc/presentation_function/bibdata.rb +3 -3
  26. data/lib/isodoc/presentation_function/block.rb +14 -9
  27. data/lib/isodoc/presentation_function/inline.rb +126 -22
  28. data/lib/isodoc/presentation_function/section.rb +9 -0
  29. data/lib/isodoc/presentation_xml_convert.rb +5 -0
  30. data/lib/isodoc/version.rb +1 -1
  31. data/lib/isodoc/word_convert.rb +0 -20
  32. data/lib/isodoc/word_function/body.rb +12 -0
  33. data/lib/isodoc/word_function/postprocess.rb +38 -80
  34. data/lib/isodoc/word_function/postprocess_cover.rb +55 -0
  35. data/lib/isodoc/word_function/table.rb +10 -0
  36. data/lib/isodoc/xref.rb +1 -0
  37. data/lib/isodoc/xref/xref_counter.rb +20 -9
  38. data/lib/isodoc/xref/xref_gen.rb +20 -2
  39. data/lib/isodoc/xref/xref_sect_gen.rb +1 -1
  40. data/spec/assets/html.scss +14 -0
  41. data/spec/assets/i18n.yaml +7 -6
  42. data/spec/isodoc/blocks_spec.rb +2 -1
  43. data/spec/isodoc/cleanup_spec.rb +0 -1
  44. data/spec/isodoc/footnotes_spec.rb +4 -5
  45. data/spec/isodoc/i18n_spec.rb +23 -2
  46. data/spec/isodoc/inline_spec.rb +182 -202
  47. data/spec/isodoc/lists_spec.rb +1 -1
  48. data/spec/isodoc/metadata_spec.rb +3 -1
  49. data/spec/isodoc/postproc_spec.rb +472 -11
  50. data/spec/isodoc/presentation_xml_spec.rb +584 -1
  51. data/spec/isodoc/ref_spec.rb +325 -7
  52. data/spec/isodoc/table_spec.rb +28 -0
  53. data/spec/isodoc/xref_spec.rb +162 -17
  54. metadata +18 -16
@@ -67,19 +67,6 @@ module IsoDoc::Function
67
67
  out << "Termbase #{node['base']}, term ID #{node['target']}"
68
68
  end
69
69
 
70
- def concept_parse(node, out)
71
- content = node.first_element_child.children.select do |c|
72
- !%w{locality localityStack}.include? c.name
73
- end.select { |c| !c.text? || /\S/.match(c) }
74
- if content.empty?
75
- out << "[Term defined in "
76
- parse(node.first_element_child, out)
77
- out << "]"
78
- else
79
- content.each { |n| parse(n, out) }
80
- end
81
- end
82
-
83
70
  def stem_parse(node, out)
84
71
  ooml = if node["type"] == "AsciiMath"
85
72
  "#{@openmathdelim}#{HTMLEntities.new.encode(node.text)}"\
@@ -131,25 +118,5 @@ module IsoDoc::Function
131
118
  p.b(**{ role: "strong" }) { |e| e << text }
132
119
  end
133
120
  end
134
-
135
- def variant_parse(node, out)
136
- if node["lang"] == @lang && node["script"] == @script
137
- node.children.each { |n| parse(n, out) }
138
- else
139
- return if found_matching_variant_sibling(node)
140
- return unless !node.at("./preceding-sibling::xmlns:variant")
141
- node.children.each { |n| parse(n, out) }
142
- end
143
- end
144
-
145
- def found_matching_variant_sibling(node)
146
- prev = node.xpath("./preceding-sibling::xmlns:variant")
147
- foll = node.xpath("./following-sibling::xmlns:variant")
148
- found = false
149
- (prev + foll).each do |n|
150
- found = true if n["lang"] == @lang && n["script"] == @script
151
- end
152
- found
153
- end
154
121
  end
155
122
  end
@@ -23,7 +23,10 @@ module IsoDoc::Function
23
23
  def index_parse(node, out)
24
24
  end
25
25
 
26
- def bookmark_parse(node, out)
26
+ def index_xref_parse(node, out)
27
+ end
28
+
29
+ def bookmark_parse(node, out)
27
30
  out.a **attr_code(id: node["id"])
28
31
  end
29
32
 
@@ -68,5 +71,11 @@ module IsoDoc::Function
68
71
  node.children.each { |n| parse(n, e) }
69
72
  end
70
73
  end
74
+
75
+ def underline_parse(node, out)
76
+ out.u do |e|
77
+ node.children.each { |n| parse(n, e) }
78
+ end
79
+ end
71
80
  end
72
81
  end
@@ -38,7 +38,8 @@ module IsoDoc::Function
38
38
  end
39
39
 
40
40
  def ol_attrs(node)
41
- { type: ol_depth(node), id: node["id"], style: keep_style(node) }
41
+ { type: node["type"] ? ol_style(node["type"].to_sym) : ol_depth(node),
42
+ id: node["id"], style: keep_style(node) }
42
43
  end
43
44
 
44
45
  def ol_parse(node, out)
@@ -80,7 +80,8 @@ module IsoDoc::Function
80
80
  end
81
81
 
82
82
  def docid_prefix(prefix, docid)
83
- docid = "#{prefix} #{docid}" if prefix && !omit_docid_prefix(prefix)
83
+ docid = "#{prefix} #{docid}" if prefix && !omit_docid_prefix(prefix) &&
84
+ !/^#{prefix}\b/.match(docid)
84
85
  docid_l10n(docid)
85
86
  end
86
87
 
@@ -90,7 +91,7 @@ module IsoDoc::Function
90
91
  end
91
92
 
92
93
  def date_note_process(b, ref)
93
- date_note = b.at(ns("./note[@type = 'ISO DATE']"))
94
+ date_note = b.at(ns("./note[@type = 'Unpublished-Status']"))
94
95
  return if date_note.nil?
95
96
  date_note.children.first.replace("<p>#{date_note.content}</p>")
96
97
  footnote_parse(date_note, ref)
@@ -111,7 +112,7 @@ module IsoDoc::Function
111
112
  # reference not to be rendered because it is deemed implicit
112
113
  # in the standards environment
113
114
  def implicit_reference(b)
114
- false
115
+ b["hidden"] == "true"
115
116
  end
116
117
 
117
118
  def prefix_bracketed_ref(ref, text)
@@ -160,7 +161,7 @@ module IsoDoc::Function
160
161
  end
161
162
 
162
163
  def norm_ref(isoxml, out, num)
163
- f = isoxml.at(ns(norm_ref_xpath)) or return num
164
+ f = isoxml.at(ns(norm_ref_xpath)) and f["hidden"] != "true" or return num
164
165
  out.div do |div|
165
166
  num = num + 1
166
167
  clause_name(num, f.at(ns("./title")), div, nil)
@@ -180,10 +181,9 @@ module IsoDoc::Function
180
181
  end
181
182
 
182
183
  def bibliography(isoxml, out)
183
- f = isoxml.at(ns(bibliography_xpath)) || return
184
+ f = isoxml.at(ns(bibliography_xpath)) and f["hidden"] != "true" or return
184
185
  page_break(out)
185
186
  out.div do |div|
186
- #div.h1 @bibliography_lbl, **{ class: "Section3" }
187
187
  div.h1 **{class: "Section3"} do |h1|
188
188
  f&.at(ns("./title"))&.children&.each { |c2| parse(c2, h1) }
189
189
  end
@@ -192,6 +192,7 @@ module IsoDoc::Function
192
192
  end
193
193
 
194
194
  def bibliography_parse(node, out)
195
+ node["hidden"] != true or return
195
196
  title = node&.at(ns("./title"))&.text || ""
196
197
  out.div do |div|
197
198
  clause_parse_title(node, div, node.at(ns("./title")), out,
@@ -202,15 +203,9 @@ module IsoDoc::Function
202
203
 
203
204
  def format_ref(ref, prefix, isopub, date, allparts)
204
205
  ref = docid_prefix(prefix, ref)
205
- return "[#{ref}]" if /^\d+$/.match(ref) && !prefix &&
206
+ return "[#{ref}]" if ref && /^\d+$/.match(ref) && !prefix &&
206
207
  !/^\[.*\]$/.match(ref)
207
208
  ref
208
209
  end
209
-
210
- # def ref_names(ref)
211
- # linkend = ref.text
212
- # linkend.gsub!(/[\[\]]/, "") unless /^\[\d+\]$/.match linkend
213
- # @anchors[ref["id"]] = { xref: linkend }
214
- # end
215
210
  end
216
211
  end
@@ -56,7 +56,7 @@ module IsoDoc::Function
56
56
  end
57
57
 
58
58
  def clause(isoxml, out)
59
- isoxml.xpath(ns(middle_clause)).each do |c|
59
+ isoxml.xpath(ns(middle_clause(isoxml))).each do |c|
60
60
  out.div **attr_code(clause_attrs(c)) do |s|
61
61
  clause_name(nil, c&.at(ns("./title")), s, nil)
62
62
  c.elements.reject { |c1| c1.name == "title" }.each do |c1|
@@ -58,11 +58,21 @@ module IsoDoc::Function
58
58
  end
59
59
  end
60
60
 
61
+ def colgroup(node, t)
62
+ colgroup = node.at(ns("./colgroup")) or return
63
+ t.colgroup do |cg|
64
+ colgroup.xpath(ns("./col")).each do |c|
65
+ cg.col **{ style: "width: #{c['width']};" }
66
+ end
67
+ end
68
+ end
69
+
61
70
  def table_parse(node, out)
62
71
  @in_table = true
63
72
  table_title_parse(node, out)
64
73
  out.table **table_attrs(node) do |t|
65
74
  tcaption(node, t)
75
+ colgroup(node, t)
66
76
  thead_parse(node, t)
67
77
  tbody_parse(node, t)
68
78
  tfoot_parse(node, t)
@@ -157,6 +157,7 @@ module IsoDoc::Function
157
157
  when "sub" then sub_parse(node, out)
158
158
  when "tt" then tt_parse(node, out)
159
159
  when "strike" then strike_parse(node, out)
160
+ when "underline" then underline_parse(node, out)
160
161
  when "keyword" then keyword_parse(node, out)
161
162
  when "smallcap" then smallcap_parse(node, out)
162
163
  when "br" then br_parse(node, out)
@@ -215,14 +216,13 @@ module IsoDoc::Function
215
216
  when "verification" then requirement_component_parse(node, out)
216
217
  when "import" then requirement_component_parse(node, out)
217
218
  when "index" then index_parse(node, out)
218
- when "concept" then concept_parse(node, out)
219
+ when "index-xref" then index_xref_parse(node, out)
219
220
  when "termref" then termrefelem_parse(node, out)
220
221
  when "copyright-statement" then copyright_parse(node, out)
221
222
  when "license-statement" then license_parse(node, out)
222
223
  when "legal-statement" then legal_parse(node, out)
223
224
  when "feedback-statement" then feedback_parse(node, out)
224
225
  when "passthrough" then passthrough_parse(node, out)
225
- when "variant" then variant_parse(node, out)
226
226
  when "amend" then amend_parse(node, out)
227
227
  when "tab" then clausedelimspace(out) # in Presentation XML only
228
228
  else
@@ -97,6 +97,10 @@ module IsoDoc
97
97
  $bodyfont: '{{bodyfont}}';
98
98
  $headerfont: '{{headerfont}}';
99
99
  $monospacefont: '{{monospacefont}}';
100
+ $normalfontsize: '{{normalfontsize}}';
101
+ $smallerfontsize: '{{smallerfontsize}}';
102
+ $footnotefontsize: '{{footnotefontsize}}';
103
+ $monospacefontsize: '{{monospacefontsize}}';
100
104
  TEXT
101
105
  end
102
106
 
@@ -60,6 +60,7 @@ module IsoDoc::HtmlFunction
60
60
  <script type="text/javascript">#{toclevel}</script>
61
61
 
62
62
  <!--Google fonts-->
63
+ <link rel="preconnect" href="https://fonts.gstatic.com">
63
64
  #{googlefonts}
64
65
  <!--Font awesome import for the link icon-->
65
66
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/solid.css" integrity="sha384-v2Tw72dyUXeU3y4aM2Y0tBJQkGfplr39mxZqlTBDUZAb9BGoC40+rdFCG0m10lXk" crossorigin="anonymous">
@@ -110,6 +111,12 @@ module IsoDoc::HtmlFunction
110
111
  sourcecode_name_parse(node, out, name)
111
112
  end
112
113
 
114
+ def underline_parse(node, out)
115
+ out.span **{ style: "text-decoration: underline;" } do |e|
116
+ node.children.each { |n| parse(n, e) }
117
+ end
118
+ end
119
+
113
120
  def table_long_strings_cleanup(docxml)
114
121
  end
115
122
  end
@@ -0,0 +1,82 @@
1
+ module IsoDoc
2
+ module HtmlFunction
3
+ # Class for recursively converting mathvariant text into plain text symbols
4
+ class MathvariantToPlain
5
+ MATHML = { "m" => "http://www.w3.org/1998/Math/MathML" }.freeze
6
+ MATHVARIANT_SPECIAL_CASE_MAPPINGS_1 = %w[bold italic sans-serif]
7
+ .permutation
8
+ .each_with_object(:sansbolditalic)
9
+ .map { |n, y| [n, y] }
10
+ .to_h
11
+ .freeze
12
+ MATHVARIANT_SPECIAL_CASE_MAPPINGS_2 = {
13
+ %w[bold fraktur] => :frakturbold,
14
+ %w[bold script] => :scriptbold,
15
+ %w[sans-serif bold] => :sansbold,
16
+ %w[sans-serif italic] => :sansitalic,
17
+ %w[sans-serif bold-italic] => :sansbolditalic,
18
+ %w[bold-sans-serif italic] => :sansbolditalic,
19
+ %w[sans-serif-italic bold] => :sansbolditalic,
20
+ }.freeze
21
+ MATHVARIANT_TO_PLANE_MAPPINGS = {
22
+ %w[double-struck] => :doublestruck,
23
+ %w[bold-fraktur] => :frakturbold,
24
+ %w[script] => :script,
25
+ %w[bold-script] => :scriptbold,
26
+ %w[fraktur] => :fraktur,
27
+ %w[sans-serif] => :sans,
28
+ %w[bold-sans-serif] => :sansbold,
29
+ %w[sans-serif-italic] => :sansitalic,
30
+ %w[sans-serif-bold-italic] => :sansbolditalic,
31
+ %w[monospace] => :monospace,
32
+ }.freeze
33
+
34
+ attr_reader :docxml
35
+
36
+ # @param [Nokogiri::Document] docxml
37
+ def initialize(docxml)
38
+ @docxml = docxml
39
+ end
40
+
41
+ def convert
42
+ docxml.xpath("//m:math", MATHML).each do |elem|
43
+ next if nothing_to_style(elem)
44
+ mathml1(elem)
45
+ end
46
+ docxml
47
+ end
48
+
49
+ private
50
+
51
+ def nothing_to_style(elem)
52
+ !elem.at("./*[@mathvariant][not(@mathvariant = 'normal')][not(@mathvariant = 'italic')]")
53
+ end
54
+
55
+ def mathml1(base_elem)
56
+ MATHVARIANT_SPECIAL_CASE_MAPPINGS_1
57
+ .merge(MATHVARIANT_SPECIAL_CASE_MAPPINGS_2)
58
+ .merge(MATHVARIANT_TO_PLANE_MAPPINGS)
59
+ .each_pair do |mathvariant_list, plain_font|
60
+ base_elem.xpath(mathvariant_xpath(mathvariant_list)).each do |elem|
61
+ toPlane(elem, plain_font)
62
+ end
63
+ end
64
+ end
65
+
66
+ def mathvariant_xpath(list)
67
+ list
68
+ .map { |variant| "//*[@mathvariant = '#{variant}']" }
69
+ .join
70
+ end
71
+
72
+ def toPlane(elem, font)
73
+ elem.traverse do |n|
74
+ next unless n.text?
75
+
76
+ n.replace(Plane1Converter.conv(HTMLEntities.new.decode(n.text), font))
77
+ end
78
+ elem
79
+ end
80
+ end
81
+ end
82
+ end
@@ -1,35 +1,47 @@
1
+ require "isodoc/html_function/mathvariant_to_plain"
2
+
1
3
  module IsoDoc::HtmlFunction
2
4
  module Html
3
- def postprocess(result, filename, dir)
5
+ def postprocess(result, filename, _dir)
4
6
  result = from_xhtml(cleanup(to_xhtml(textcleanup(result))))
5
7
  toHTML(result, filename)
6
8
  @files_to_delete.each { |f| FileUtils.rm_rf f }
7
9
  end
8
10
 
9
11
  def script_cdata(result)
10
- result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>").
11
- gsub(%r{\]\]>\s*</script>}, "</script>").
12
- gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>").
13
- gsub(%r{</script>\s*\]\]>}, "</script>")
12
+ result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>")
13
+ .gsub(%r{\]\]>\s*</script>}, "</script>")
14
+ .gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>")
15
+ .gsub(%r{</script>\s*\]\]>}, "</script>")
14
16
  end
15
17
 
16
18
  def toHTML(result, filename)
17
- result = (from_xhtml(html_cleanup(to_xhtml(result))))
18
- #result = populate_template(result, :html)
19
+ result = from_xhtml(html_cleanup(to_xhtml(result)))
20
+ # result = populate_template(result, :html)
19
21
  result = from_xhtml(move_images(to_xhtml(result)))
20
22
  result = html5(script_cdata(inject_script(result)))
21
23
  File.open(filename, "w:UTF-8") { |f| f.write(result) }
22
24
  end
23
25
 
24
26
  def html5(doc)
25
- doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>").
26
- sub(%r{<\?xml[^>]+>}, "")
27
+ doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>")
28
+ .sub(%r{<\?xml[^>]+>}, "")
27
29
  end
28
30
 
29
31
  def html_cleanup(x)
30
- footnote_format(footnote_backlinks(html_toc(
31
- term_header((html_footnote_filter(html_preface(htmlstyle(x))))))
32
- ))
32
+ mathml(
33
+ footnote_format(
34
+ footnote_backlinks(
35
+ html_toc(
36
+ term_header(html_footnote_filter(html_preface(htmlstyle(x))))
37
+ )
38
+ )
39
+ )
40
+ )
41
+ end
42
+
43
+ def mathml(docxml)
44
+ IsoDoc::HtmlFunction::MathvariantToPlain.new(docxml).convert
33
45
  end
34
46
 
35
47
  def htmlstylesheet
@@ -76,14 +88,14 @@ module IsoDoc::HtmlFunction
76
88
  def html_cover(docxml)
77
89
  doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
78
90
  d = docxml.at('//div[@class="title-section"]')
79
- #d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
91
+ # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
80
92
  d.children.first.add_previous_sibling populate_template(doc.to_xml(encoding: "US-ASCII"), :html)
81
93
  end
82
94
 
83
95
  def html_intro(docxml)
84
96
  doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
85
97
  d = docxml.at('//div[@class="prefatory-section"]')
86
- #d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
98
+ # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
87
99
  d.children.first.add_previous_sibling populate_template(doc.to_xml(encoding: "US-ASCII"), :html)
88
100
  end
89
101
 
@@ -93,19 +105,19 @@ module IsoDoc::HtmlFunction
93
105
  end
94
106
 
95
107
  def toclevel_classes
96
- (1..@htmlToClevels).inject([]) { |m, i| m << "h#{i}" }
108
+ (1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
97
109
  end
98
110
 
99
111
  def toclevel
100
112
  ret = toclevel_classes.map { |l| "#{l}:not(:empty):not(.TermNum):not(.noTOC)" }
101
113
  <<~HEAD.freeze
102
- function toclevel() { return "#{ret.join(',')}";}
114
+ function toclevel() { return "#{ret.join(',')}";}
103
115
  HEAD
104
116
  end
105
117
 
106
118
  # needs to be same output as toclevel
107
119
  def html_toc(docxml)
108
- idx = docxml.at("//div[@id = 'toc']") or return docxml
120
+ (idx = docxml.at("//div[@id = 'toc']")) or (return docxml)
109
121
  toc = "<ul>"
110
122
  path = toclevel_classes.map do |l|
111
123
  "//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][text()]"
@@ -186,14 +198,22 @@ module IsoDoc::HtmlFunction
186
198
  docxml
187
199
  end
188
200
 
201
+ def footnote_backlinks1(x, fn)
202
+ xdup = x.dup
203
+ xdup.remove["id"]
204
+ if fn.elements.empty?
205
+ fn.children.first.previous = xdup
206
+ else
207
+ fn.elements.first.children.first.previous = xdup
208
+ end
209
+ end
210
+
189
211
  def footnote_backlinks(docxml)
190
212
  seen = {}
191
213
  docxml.xpath('//a[@class = "FootnoteRef"]').each_with_index do |x, i|
192
214
  seen[x["href"]] and next or seen[x["href"]] = true
193
215
  fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
194
- xdup = x.dup
195
- xdup.remove["id"]
196
- fn.elements.first.children.first.previous = xdup
216
+ footnote_backlinks1(x, fn)
197
217
  x["id"] ||= "fnref:#{i + 1}"
198
218
  fn.add_child "<a href='##{x['id']}'>&#x21A9;</a>"
199
219
  end
@@ -221,6 +241,7 @@ module IsoDoc::HtmlFunction
221
241
  MATHJAX = <<~"MATHJAX".freeze
222
242
  <script type="text/x-mathjax-config">
223
243
  MathJax.Hub.Config({
244
+ "HTML-CSS": { preferredFont: "STIX" },
224
245
  asciimath2jax: { delimiters: [['OPEN', 'CLOSE']] }
225
246
  });
226
247
  </script>