isodoc 1.6.2 → 1.6.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +2 -12
  3. data/.hound.yml +3 -1
  4. data/.rubocop.yml +4 -6
  5. data/Rakefile +2 -2
  6. data/isodoc.gemspec +3 -2
  7. data/lib/isodoc-yaml/i18n-en.yaml +1 -0
  8. data/lib/isodoc-yaml/i18n-fr.yaml +1 -0
  9. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  10. data/lib/isodoc.rb +0 -2
  11. data/lib/isodoc/convert.rb +7 -1
  12. data/lib/isodoc/function/blocks.rb +5 -4
  13. data/lib/isodoc/function/cleanup.rb +52 -43
  14. data/lib/isodoc/function/inline.rb +7 -7
  15. data/lib/isodoc/function/references.rb +32 -51
  16. data/lib/isodoc/function/section.rb +28 -16
  17. data/lib/isodoc/function/table.rb +21 -22
  18. data/lib/isodoc/function/terms.rb +6 -7
  19. data/lib/isodoc/function/to_word_html.rb +6 -3
  20. data/lib/isodoc/function/utils.rb +181 -163
  21. data/lib/isodoc/gem_tasks.rb +8 -9
  22. data/lib/isodoc/headlesshtml_convert.rb +8 -7
  23. data/lib/isodoc/html_convert.rb +5 -1
  24. data/lib/isodoc/html_function/comments.rb +14 -12
  25. data/lib/isodoc/html_function/footnotes.rb +14 -7
  26. data/lib/isodoc/html_function/html.rb +30 -26
  27. data/lib/isodoc/html_function/postprocess.rb +191 -182
  28. data/lib/isodoc/html_function/sectionsplit.rb +230 -0
  29. data/lib/isodoc/metadata.rb +22 -20
  30. data/lib/isodoc/metadata_contributor.rb +31 -28
  31. data/lib/isodoc/pdf_convert.rb +11 -13
  32. data/lib/isodoc/presentation_function/bibdata.rb +61 -30
  33. data/lib/isodoc/presentation_function/inline.rb +34 -27
  34. data/lib/isodoc/presentation_function/section.rb +54 -19
  35. data/lib/isodoc/presentation_xml_convert.rb +2 -0
  36. data/lib/isodoc/sassc_importer.rb +1 -1
  37. data/lib/isodoc/version.rb +1 -1
  38. data/lib/isodoc/word_function/postprocess.rb +50 -36
  39. data/lib/isodoc/xref.rb +2 -0
  40. data/lib/isodoc/xref/xref_counter.rb +1 -2
  41. data/lib/isodoc/xref/xref_gen.rb +21 -14
  42. data/lib/isodoc/xref/xref_gen_seq.rb +60 -35
  43. data/lib/isodoc/xref/xref_sect_gen.rb +15 -15
  44. data/spec/assets/scripts_override.html +3 -0
  45. data/spec/isodoc/blocks_spec.rb +624 -997
  46. data/spec/isodoc/cleanup_spec.rb +40 -42
  47. data/spec/isodoc/i18n_spec.rb +694 -821
  48. data/spec/isodoc/inline_spec.rb +482 -328
  49. data/spec/isodoc/metadata_spec.rb +384 -379
  50. data/spec/isodoc/postproc_spec.rb +163 -55
  51. data/spec/isodoc/presentation_xml_spec.rb +355 -278
  52. data/spec/isodoc/ref_spec.rb +5 -5
  53. data/spec/isodoc/section_spec.rb +216 -199
  54. data/spec/isodoc/sectionsplit_spec.rb +190 -0
  55. data/spec/isodoc/table_spec.rb +41 -42
  56. data/spec/isodoc/terms_spec.rb +84 -84
  57. data/spec/isodoc/xref_spec.rb +974 -932
  58. metadata +22 -5
@@ -1,11 +1,10 @@
1
- require_relative "html_function/comments.rb"
2
- require_relative "html_function/footnotes.rb"
3
- require_relative "html_function/html.rb"
1
+ require_relative "html_function/comments"
2
+ require_relative "html_function/footnotes"
3
+ require_relative "html_function/html"
4
4
  require "metanorma"
5
5
 
6
6
  module IsoDoc
7
7
  class PdfConvert < ::IsoDoc::Convert
8
-
9
8
  include HtmlFunction::Comments
10
9
  include HtmlFunction::Footnotes
11
10
  include HtmlFunction::Html
@@ -13,6 +12,8 @@ module IsoDoc
13
12
  def initialize(options)
14
13
  @standardstylesheet = nil
15
14
  super
15
+ @format = :pdf
16
+ @suffix = "pdf"
16
17
  @scripts = @scripts_pdf if @scripts_pdf
17
18
  @maxwidth = 500
18
19
  @maxheight = 800
@@ -22,22 +23,19 @@ module IsoDoc
22
23
  "_pdfimages"
23
24
  end
24
25
 
25
- def initialize(options)
26
- @format = :pdf
27
- @suffix = "pdf"
28
- super
29
- end
30
-
31
26
  def convert(input_filename, file = nil, debug = false, output_filename = nil)
32
27
  file = File.read(input_filename, encoding: "utf-8") if file.nil?
33
28
  @openmathdelim, @closemathdelim = extract_delims(file)
34
29
  docxml, filename, dir = convert_init(file, input_filename, debug)
35
30
  result = convert1(docxml, filename, dir)
36
31
  return result if debug
37
- postprocess(result, filename + ".tmp.html", dir)
32
+
33
+ postprocess(result, "#{filename}.tmp.html", dir)
38
34
  FileUtils.rm_rf dir
39
- ::Metanorma::Output::Pdf.new.convert("#{filename}.tmp.html",
40
- output_filename || "#{filename}.#{@suffix}")
35
+ ::Metanorma::Output::Pdf.new.convert(
36
+ "#{filename}.tmp.html",
37
+ output_filename || "#{filename}.#{@suffix}",
38
+ )
41
39
  FileUtils.rm_rf ["#{filename}.tmp.html", tmpimagedir]
42
40
  end
43
41
 
@@ -1,13 +1,40 @@
1
1
  module IsoDoc
2
2
  class PresentationXMLConvert < ::IsoDoc::Convert
3
3
  def bibdata(docxml)
4
+ docid_prefixes(docxml)
4
5
  a = bibdata_current(docxml) or return
6
+ address_precompose(a)
5
7
  bibdata_i18n(a)
6
8
  a.next =
7
- "<localized-strings>#{i8n_name(trim_hash(@i18n.get), "").join("")}"\
9
+ "<localized-strings>#{i8n_name(trim_hash(@i18n.get), '').join('')}"\
8
10
  "</localized-strings>"
9
11
  end
10
12
 
13
+ def docid_prefixes(docxml)
14
+ docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
15
+ i.children = @xrefs.klass.docid_prefix(i["type"], i.text)
16
+ end
17
+ end
18
+
19
+ def address_precompose(bib)
20
+ bib.xpath(ns("//bibdata//address")).each do |b|
21
+ next if b.at(ns("./formattedAddress"))
22
+
23
+ x = address_precompose1(b)
24
+ b.children = "<formattedAddress>#{x}</formattedAddress>"
25
+ end
26
+ end
27
+
28
+ def address_precompose1(addr)
29
+ ret = []
30
+ addr.xpath(ns("./street")).each { |s| ret << s.children.to_xml }
31
+ a = addr.at(ns("./city")) and ret << a.children.to_xml
32
+ addr.xpath(ns("./state")).each { |s| ret << s.children.to_xml }
33
+ a = addr.at(ns("./country")) and ret << a.children.to_xml
34
+ a = addr.at(ns("./postcode")) and ret[-1] += " #{a.children.to_xml}"
35
+ ret.join("<br/>")
36
+ end
37
+
11
38
  def bibdata_current(docxml)
12
39
  a = docxml.at(ns("//bibdata")) or return
13
40
  a.xpath(ns("./language")).each do |l|
@@ -19,10 +46,10 @@ module IsoDoc
19
46
  a
20
47
  end
21
48
 
22
- def bibdata_i18n(b)
23
- hash_translate(b, @i18n.get["doctype_dict"], "./ext/doctype")
24
- hash_translate(b, @i18n.get["stage_dict"], "./status/stage")
25
- hash_translate(b, @i18n.get["substage_dict"], "./status/substage")
49
+ def bibdata_i18n(bib)
50
+ hash_translate(bib, @i18n.get["doctype_dict"], "./ext/doctype")
51
+ hash_translate(bib, @i18n.get["stage_dict"], "./status/stage")
52
+ hash_translate(bib, @i18n.get["substage_dict"], "./status/substage")
26
53
  end
27
54
 
28
55
  def hash_translate(bibdata, hash, xpath, lang = @lang)
@@ -35,58 +62,62 @@ module IsoDoc
35
62
  x.next.children = hash[x.text]
36
63
  end
37
64
 
38
- def i18n_tag(k, v)
39
- "<localized-string key='#{k}' language='#{@lang}'>#{v}</localized-string>"
65
+ def i18n_tag(key, value)
66
+ "<localized-string key='#{key}' language='#{@lang}'>#{value}"\
67
+ "</localized-string>"
40
68
  end
41
69
 
42
- def i18n_safe(k)
43
- k.to_s.gsub(/\s|\./, "_")
70
+ def i18n_safe(key)
71
+ key.to_s.gsub(/\s|\./, "_")
44
72
  end
45
73
 
46
- def i8n_name(h, pref)
47
- if h.is_a? Hash then i8n_name1(h, pref)
48
- elsif h.is_a? Array
49
- h.reject { |a| blank?(a) }.each_with_object([]).
50
- with_index do |(v1, g), i|
74
+ def i8n_name(hash, pref)
75
+ if hash.is_a? Hash then i8n_name1(hash, pref)
76
+ elsif hash.is_a? Array
77
+ hash.reject { |a| blank?(a) }.each_with_object([])
78
+ .with_index do |(v1, g), i|
51
79
  i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
52
80
  end
53
- else [i18n_tag(pref, h)]
81
+ else [i18n_tag(pref, hash)]
54
82
  end
55
83
  end
56
84
 
57
- def i8n_name1(h, pref)
58
- h.reject { |k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
85
+ def i8n_name1(hash, pref)
86
+ hash.reject { |_k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
59
87
  if v.is_a? Hash then i8n_name(v, i18n_safe(k)).each { |x| g << x }
60
88
  elsif v.is_a? Array
61
89
  v.reject { |a| blank?(a) }.each_with_index do |v1, i|
62
90
  i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
63
91
  end
64
92
  else
65
- g << i18n_tag("#{pref}#{pref.empty? ? "" : "."}#{i18n_safe(k)}", v)
93
+ g << i18n_tag("#{pref}#{pref.empty? ? '' : '.'}#{i18n_safe(k)}", v)
66
94
  end
67
95
  end
68
96
  end
69
97
 
70
- #https://stackoverflow.com/a/31822406
71
- def blank?(v)
72
- v.nil? || v.respond_to?(:empty?) && v.empty?
98
+ # https://stackoverflow.com/a/31822406
99
+ def blank?(elem)
100
+ elem.nil? || elem.respond_to?(:empty?) && elem.empty?
73
101
  end
74
102
 
75
- def trim_hash(h)
103
+ def trim_hash(hash)
76
104
  loop do
77
- h_new = trim_hash1(h)
78
- break h if h==h_new
79
- h = h_new
105
+ h_new = trim_hash1(hash)
106
+ break hash if hash == h_new
107
+
108
+ hash = h_new
80
109
  end
81
110
  end
82
111
 
83
- def trim_hash1(h)
84
- return h unless h.is_a? Hash
85
- h.each_with_object({}) do |(k,v), g|
112
+ def trim_hash1(hash)
113
+ return hash unless hash.is_a? Hash
114
+
115
+ hash.each_with_object({}) do |(k, v), g|
86
116
  next if blank?(v)
87
- g[k] = if v.is_a? Hash then trim_hash1(h[k])
117
+
118
+ g[k] = if v.is_a? Hash then trim_hash1(hash[k])
88
119
  elsif v.is_a? Array
89
- h[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
120
+ hash[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
90
121
  else
91
122
  v
92
123
  end
@@ -9,8 +9,8 @@ module IsoDoc
9
9
  return @xrefs.anchor(node["bibitemid"], :xref) || "???"
10
10
  elsif node["target"] && node["droploc"]
11
11
  return @xrefs.anchor(node["target"], :value) ||
12
- @xrefs.anchor(node["target"], :label) ||
13
- @xrefs.anchor(node["target"], :xref) || "???"
12
+ @xrefs.anchor(node["target"], :label) ||
13
+ @xrefs.anchor(node["target"], :xref) || "???"
14
14
  elsif node["target"] && !/.#./.match(node["target"])
15
15
  linkend = anchor_linkend1(node)
16
16
  end
@@ -33,6 +33,10 @@ module IsoDoc
33
33
  return linkend&.downcase if node["case"] == "lowercase"
34
34
  return linkend if linkend[0, 1].match?(/\p{Upper}/)
35
35
 
36
+ capitalise_xref1(node, linkend)
37
+ end
38
+
39
+ def capitalise_xref1(node, linkend)
36
40
  prec = nearest_block_parent(node).xpath("./descendant-or-self::text()") &
37
41
  node.xpath("./preceding::text()")
38
42
  if prec.empty? || /(?!<[^.].)\.\s+$/.match(prec.map(&:text).join)
@@ -43,8 +47,8 @@ module IsoDoc
43
47
 
44
48
  def nearest_block_parent(node)
45
49
  until %w(p title td th name formula li dt dd sourcecode pre)
46
- .include?(node.name)
47
- node = node.parent
50
+ .include?(node.name)
51
+ node = node.parent
48
52
  end
49
53
  node
50
54
  end
@@ -68,55 +72,55 @@ module IsoDoc
68
72
  # so not <origin bibitemid="ISO7301" citeas="ISO 7301">
69
73
  # <locality type="section"><reference>3.1</reference></locality></origin>
70
74
 
71
- def eref_localities(refs, target, n)
75
+ def eref_localities(refs, target, node)
72
76
  ret = ""
73
77
  refs.each_with_index do |r, i|
74
78
  delim = ","
75
79
  delim = ";" if r.name == "localityStack" && i.positive?
76
- ret = eref_locality_stack(r, i, target, delim, ret, n)
80
+ ret = eref_locality_stack(r, i, target, delim, ret, node)
77
81
  end
78
82
  ret
79
83
  end
80
84
 
81
- def eref_locality_stack(r, idx, target, delim, ret, n)
82
- if r.name == "localityStack"
83
- r.elements.each_with_index do |rr, j|
84
- ret += eref_localities0(rr, j, target, delim, n)
85
+ def eref_locality_stack(ref, idx, target, delim, ret, node)
86
+ if ref.name == "localityStack"
87
+ ref.elements.each_with_index do |rr, j|
88
+ ret += eref_localities0(rr, j, target, delim, node)
85
89
  delim = ","
86
90
  end
87
91
  else
88
- ret += eref_localities0(r, idx, target, delim, n)
92
+ ret += eref_localities0(ref, idx, target, delim, node)
89
93
  end
90
94
  ret
91
95
  end
92
96
 
93
- def eref_localities0(r, _i, target, delim, n)
94
- if r["type"] == "whole" then l10n("#{delim} #{@i18n.wholeoftext}")
97
+ def eref_localities0(ref, _idx, target, delim, node)
98
+ if ref["type"] == "whole" then l10n("#{delim} #{@i18n.wholeoftext}")
95
99
  else
96
- eref_localities1(target, r["type"], r.at(ns("./referenceFrom")),
97
- r.at(ns("./referenceTo")), delim, n, @lang)
100
+ eref_localities1(target, ref["type"], ref.at(ns("./referenceFrom")),
101
+ ref.at(ns("./referenceTo")), delim, node, @lang)
98
102
  end
99
103
  end
100
104
 
101
105
  # TODO: move to localization file
102
- def eref_localities1_zh(_target, type, from, to, n, delim)
106
+ def eref_localities1_zh(_target, type, from, upto, node, delim)
103
107
  ret = "#{delim} 第#{from.text}" if from
104
- ret += "&ndash;#{to.text}" if to
108
+ ret += "&ndash;#{upto.text}" if upto
105
109
  loc = (@i18n.locality[type] || type.sub(/^locality:/, "").capitalize)
106
- ret += " #{loc}" unless n["droploc"] == "true"
110
+ ret += " #{loc}" unless node["droploc"] == "true"
107
111
  ret
108
112
  end
109
113
 
110
114
  # TODO: move to localization file
111
- def eref_localities1(target, type, from, to, delim, n, lang = "en")
115
+ def eref_localities1(target, type, from, upto, delim, node, lang = "en")
112
116
  return "" if type == "anchor"
113
117
 
114
118
  lang == "zh" and
115
- return l10n(eref_localities1_zh(target, type, from, to, n, delim))
119
+ return l10n(eref_localities1_zh(target, type, from, upto, node, delim))
116
120
  ret = delim
117
- ret += eref_locality_populate(type, n)
121
+ ret += eref_locality_populate(type, node)
118
122
  ret += " #{from.text}" if from
119
- ret += "&ndash;#{to.text}" if to
123
+ ret += "&ndash;#{upto.text}" if upto
120
124
  l10n(ret)
121
125
  end
122
126
 
@@ -158,12 +162,15 @@ module IsoDoc
158
162
  end
159
163
 
160
164
  def concept1(node)
161
- content = node.first_element_child.children.select do |c|
162
- !%w{locality localityStack}.include? c.name
165
+ content = node.first_element_child.children.reject do |c|
166
+ %w{locality localityStack}.include? c.name
163
167
  end.select { |c| !c.text? || /\S/.match(c) }
164
- node.replace content.empty? ?
165
- @i18n.term_defined_in.sub(/%/, node.first_element_child.to_xml) :
166
- "<em>#{node.children.to_xml}</em>"
168
+ n = if content.empty?
169
+ @i18n.term_defined_in.sub(/%/, node.first_element_child.to_xml)
170
+ else
171
+ "<em>#{node.children.to_xml}</em>"
172
+ end
173
+ node.replace(n)
167
174
  end
168
175
 
169
176
  def variant(docxml)
@@ -2,20 +2,21 @@ module IsoDoc
2
2
  class PresentationXMLConvert < ::IsoDoc::Convert
3
3
  def clause(docxml)
4
4
  docxml.xpath(ns("//clause | "\
5
- "//terms | //definitions | //references")).
6
- each do |f|
5
+ "//terms | //definitions | //references"))
6
+ .each do |f|
7
7
  clause1(f)
8
8
  end
9
9
  end
10
10
 
11
- def clause1(f)
12
- level = @xrefs.anchor(f['id'], :level, false) || "1"
13
- t = f.at(ns("./title")) and t["depth"] = level
14
- return if !f.ancestors("boilerplate").empty?
15
- return if @suppressheadingnumbers || f["unnumbered"]
16
- lbl = @xrefs.anchor(f['id'], :label,
17
- f.parent.name != "sections") or return
18
- prefix_name(f, "<tab/>", "#{lbl}#{clausedelim}", "title")
11
+ def clause1(elem)
12
+ level = @xrefs.anchor(elem["id"], :level, false) || "1"
13
+ t = elem.at(ns("./title")) and t["depth"] = level
14
+ return if !elem.ancestors("boilerplate").empty? ||
15
+ @suppressheadingnumbers || elem["unnumbered"]
16
+
17
+ lbl = @xrefs.anchor(elem["id"], :label,
18
+ elem.parent.name != "sections") or return
19
+ prefix_name(elem, "<tab/>", "#{lbl}#{clausedelim}", "title")
19
20
  end
20
21
 
21
22
  def annex(docxml)
@@ -24,12 +25,12 @@ module IsoDoc
24
25
  end
25
26
  end
26
27
 
27
- def annex1(f)
28
- lbl = @xrefs.anchor(f['id'], :label)
29
- if t = f.at(ns("./title"))
28
+ def annex1(elem)
29
+ lbl = @xrefs.anchor(elem["id"], :label)
30
+ if t = elem.at(ns("./title"))
30
31
  t.children = "<strong>#{t.children.to_xml}</strong>"
31
32
  end
32
- prefix_name(f, "<br/><br/>", lbl, "title")
33
+ prefix_name(elem, "<br/><br/>", lbl, "title")
33
34
  end
34
35
 
35
36
  def term(docxml)
@@ -38,18 +39,52 @@ module IsoDoc
38
39
  end
39
40
  end
40
41
 
41
- def term1(f)
42
- lbl = @xrefs.get[f["id"]][:label] or return
43
- prefix_name(f, "", "#{lbl}#{clausedelim}", "name")
42
+ def term1(elem)
43
+ lbl = @xrefs.get[elem["id"]][:label] or return
44
+ prefix_name(elem, "", "#{lbl}#{clausedelim}", "name")
44
45
  end
45
46
 
46
47
  def references(docxml)
47
48
  end
48
49
 
50
+ def docid_prefixes(docxml)
51
+ docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
52
+ i.children = @xrefs.klass.docid_prefix(i["type"], i.text)
53
+ end
54
+ end
55
+
49
56
  def index(docxml)
50
- docxml.xpath(ns("//index | //index-xref | //indexsect")).each do |f|
51
- f.remove
57
+ docxml.xpath(ns("//index | //index-xref | //indexsect")).each(&:remove)
58
+ end
59
+
60
+ def display_order_at(docxml, xpath, idx)
61
+ return idx unless c = docxml.at(ns(xpath))
62
+
63
+ idx += 1
64
+ c["displayorder"] = idx
65
+ idx
66
+ end
67
+
68
+ def display_order_xpath(docxml, xpath, idx)
69
+ docxml.xpath(ns(xpath)).each do |c|
70
+ idx += 1
71
+ c["displayorder"] = idx
52
72
  end
73
+ idx
74
+ end
75
+
76
+ def display_order(docxml)
77
+ i = 0
78
+ i = display_order_xpath(docxml, "//preface/*", i)
79
+ i = display_order_at(docxml, "//clause[@type = 'scope']", i)
80
+ i = display_order_at(docxml, @xrefs.klass.norm_ref_xpath, i)
81
+ i = display_order_at(docxml, "//sections/terms | "\
82
+ "//sections/clause[descendant::terms]", i)
83
+ i = display_order_at(docxml, "//sections/definitions", i)
84
+ i = display_order_xpath(docxml, @xrefs.klass.middle_clause(docxml), i)
85
+ i = display_order_xpath(docxml, "//annex", i)
86
+ i = display_order_xpath(docxml, @xrefs.klass.bibliography_xpath, i)
87
+ display_order_xpath(docxml, "//indexsect", i)
53
88
  end
54
89
  end
55
90
  end
@@ -22,12 +22,14 @@ module IsoDoc
22
22
 
23
23
  def conversions(docxml)
24
24
  bibdata docxml
25
+ @xrefs.parse docxml
25
26
  section docxml
26
27
  block docxml
27
28
  inline docxml
28
29
  end
29
30
 
30
31
  def section(docxml)
32
+ display_order docxml
31
33
  clause docxml
32
34
  annex docxml
33
35
  term docxml
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sassc'
3
+ require "sassc"
4
4
 
5
5
  class SasscImporter < SassC::Importer
6
6
  def imports(path, _parent_path)