isodoc 1.6.2 → 1.6.7

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 (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)