isodoc 1.6.3 → 1.6.7.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 +2 -12
  3. data/.hound.yml +3 -1
  4. data/.rubocop.yml +4 -6
  5. data/isodoc.gemspec +3 -2
  6. data/lib/isodoc-yaml/i18n-en.yaml +1 -0
  7. data/lib/isodoc-yaml/i18n-fr.yaml +1 -0
  8. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  9. data/lib/isodoc.rb +0 -2
  10. data/lib/isodoc/convert.rb +7 -1
  11. data/lib/isodoc/function/blocks.rb +5 -4
  12. data/lib/isodoc/function/cleanup.rb +52 -43
  13. data/lib/isodoc/function/inline.rb +7 -7
  14. data/lib/isodoc/function/references.rb +33 -52
  15. data/lib/isodoc/function/section.rb +28 -16
  16. data/lib/isodoc/function/table.rb +21 -22
  17. data/lib/isodoc/function/terms.rb +6 -7
  18. data/lib/isodoc/function/to_word_html.rb +6 -3
  19. data/lib/isodoc/function/utils.rb +181 -163
  20. data/lib/isodoc/gem_tasks.rb +8 -9
  21. data/lib/isodoc/headlesshtml_convert.rb +8 -7
  22. data/lib/isodoc/html_convert.rb +5 -1
  23. data/lib/isodoc/html_function/comments.rb +14 -12
  24. data/lib/isodoc/html_function/footnotes.rb +14 -7
  25. data/lib/isodoc/html_function/html.rb +30 -26
  26. data/lib/isodoc/html_function/postprocess.rb +191 -182
  27. data/lib/isodoc/html_function/sectionsplit.rb +230 -0
  28. data/lib/isodoc/metadata.rb +22 -20
  29. data/lib/isodoc/metadata_contributor.rb +31 -28
  30. data/lib/isodoc/pdf_convert.rb +11 -13
  31. data/lib/isodoc/presentation_function/bibdata.rb +50 -22
  32. data/lib/isodoc/presentation_function/inline.rb +20 -15
  33. data/lib/isodoc/presentation_function/section.rb +38 -1
  34. data/lib/isodoc/presentation_xml_convert.rb +2 -0
  35. data/lib/isodoc/version.rb +1 -1
  36. data/lib/isodoc/word_function/postprocess.rb +50 -36
  37. data/lib/isodoc/xref.rb +2 -0
  38. data/lib/isodoc/xref/xref_gen_seq.rb +60 -35
  39. data/lib/isodoc/xref/xref_sect_gen.rb +4 -4
  40. data/spec/assets/scripts_override.html +3 -0
  41. data/spec/isodoc/blocks_spec.rb +373 -685
  42. data/spec/isodoc/cleanup_spec.rb +40 -42
  43. data/spec/isodoc/i18n_spec.rb +694 -821
  44. data/spec/isodoc/inline_spec.rb +482 -328
  45. data/spec/isodoc/metadata_spec.rb +384 -379
  46. data/spec/isodoc/postproc_spec.rb +163 -55
  47. data/spec/isodoc/presentation_xml_spec.rb +355 -278
  48. data/spec/isodoc/ref_spec.rb +5 -5
  49. data/spec/isodoc/section_spec.rb +216 -199
  50. data/spec/isodoc/sectionsplit_spec.rb +190 -0
  51. data/spec/isodoc/table_spec.rb +41 -42
  52. data/spec/isodoc/terms_spec.rb +84 -84
  53. data/spec/isodoc/xref_spec.rb +974 -932
  54. metadata +22 -5
@@ -8,11 +8,11 @@ module IsoDoc::Function
8
8
  insert_tab(out, 1)
9
9
  end
10
10
 
11
- def inline_header_title(out, node, title)
11
+ def inline_header_title(out, _node, title)
12
12
  out.span **{ class: "zzMoveToFollowing" } do |s|
13
13
  s.b do |b|
14
14
  title&.children&.each { |c2| parse(c2, b) }
15
- clausedelimspace(out) if /\S/.match(title&.text)
15
+ clausedelimspace(out) if /\S/.match?(title&.text)
16
16
  end
17
17
  end
18
18
  end
@@ -20,12 +20,14 @@ module IsoDoc::Function
20
20
  # used for subclauses
21
21
  def clause_parse_title(node, div, title, out, header_class = {})
22
22
  return if title.nil?
23
+
23
24
  if node["inline-header"] == "true"
24
25
  inline_header_title(out, node, title)
25
26
  else
26
- depth = (title && title["depth"]) ? title["depth"] :
27
- node.ancestors("clause, annex, terms, references, definitions, "\
28
- "acknowledgements, introduction, foreword").size + 1
27
+ depth = if title && title["depth"] then title["depth"]
28
+ else node.ancestors("clause, annex, terms, references, definitions, "\
29
+ "acknowledgements, introduction, foreword").size + 1
30
+ end
29
31
  div.send "h#{depth}", **attr_code(header_class) do |h|
30
32
  title&.children&.each { |c2| parse(c2, h) }
31
33
  end
@@ -49,8 +51,11 @@ module IsoDoc::Function
49
51
  def clause_name(_num, title, div, header_class)
50
52
  header_class = {} if header_class.nil?
51
53
  div.h1 **attr_code(header_class) do |h1|
52
- title.is_a?(String) ? h1 << title :
54
+ if title.is_a?(String)
55
+ h1 << title
56
+ else
53
57
  title&.children&.each { |c2| parse(c2, h1) }
58
+ end
54
59
  end
55
60
  div.parent.at(".//h1")
56
61
  end
@@ -66,8 +71,9 @@ module IsoDoc::Function
66
71
  end
67
72
  end
68
73
 
69
- def annex_name(annex, name, div)
74
+ def annex_name(_annex, name, div)
70
75
  return if name.nil?
76
+
71
77
  div.h1 **{ class: "Annex" } do |t|
72
78
  name.children.each { |c2| parse(c2, t) }
73
79
  end
@@ -144,7 +150,6 @@ module IsoDoc::Function
144
150
 
145
151
  def introduction(isoxml, out)
146
152
  f = isoxml.at(ns("//introduction")) || return
147
- title_attr = { class: "IntroTitle" }
148
153
  page_break(out)
149
154
  out.div **{ class: "Section3", id: f["id"] } do |div|
150
155
  clause_name(nil, f.at(ns("./title")), div, { class: "IntroTitle" })
@@ -160,7 +165,6 @@ module IsoDoc::Function
160
165
  out.div **attr_code(id: f["id"]) do |s|
161
166
  clause_name(nil, f.at(ns("./title")) || @i18n.foreword, s,
162
167
  { class: "ForewordTitle" })
163
- #s.h1(**{ class: "ForewordTitle" }) { |h1| h1 << @i18n.foreword }
164
168
  f.elements.each { |e| parse(e, s) unless e.name == "title" }
165
169
  end
166
170
  end
@@ -187,12 +191,11 @@ module IsoDoc::Function
187
191
  end
188
192
 
189
193
  def preface(isoxml, out)
190
- title_attr = { class: "IntroTitle" }
191
194
  isoxml.xpath(ns("//preface/clause | //preface/references | "\
192
195
  "//preface/definitions | //preface/terms")).each do |f|
193
196
  page_break(out)
194
197
  out.div **{ class: "Section3", id: f["id"] } do |div|
195
- clause_name(nil, f&.at(ns("./title")), div, title_attr)
198
+ clause_name(nil, f&.at(ns("./title")), div, { class: "IntroTitle" })
196
199
  f.elements.each do |e|
197
200
  parse(e, div) unless e.name == "title"
198
201
  end
@@ -202,37 +205,46 @@ module IsoDoc::Function
202
205
 
203
206
  def is_clause?(name)
204
207
  %w(clause references definitions terms foreword introduction abstract
205
- acknowledgements).include? name
208
+ acknowledgements).include? name
206
209
  end
207
210
 
208
211
  def preface_block(isoxml, out)
209
212
  p = isoxml.at(ns("//preface")) or return
210
213
  p.elements.each do |e|
211
214
  next if is_clause?(e.name)
215
+
212
216
  parse(e, out)
213
217
  end
214
218
  end
215
219
 
216
220
  def copyright_parse(node, out)
217
- out.div **{class: "boilerplate-copyright"} do |div|
221
+ return if @bare
222
+
223
+ out.div **{ class: "boilerplate-copyright" } do |div|
218
224
  node.children.each { |n| parse(n, div) }
219
225
  end
220
226
  end
221
227
 
222
228
  def license_parse(node, out)
223
- out.div **{class: "boilerplate-license"} do |div|
229
+ return if @bare
230
+
231
+ out.div **{ class: "boilerplate-license" } do |div|
224
232
  node.children.each { |n| parse(n, div) }
225
233
  end
226
234
  end
227
235
 
228
236
  def legal_parse(node, out)
229
- out.div **{class: "boilerplate-legal"} do |div|
237
+ return if @bare
238
+
239
+ out.div **{ class: "boilerplate-legal" } do |div|
230
240
  node.children.each { |n| parse(n, div) }
231
241
  end
232
242
  end
233
243
 
234
244
  def feedback_parse(node, out)
235
- out.div **{class: "boilerplate-feedback"} do |div|
245
+ return if @bare
246
+
247
+ out.div **{ class: "boilerplate-feedback" } do |div|
236
248
  node.children.each { |n| parse(n, div) }
237
249
  end
238
250
  end
@@ -1,17 +1,16 @@
1
1
  module IsoDoc::Function
2
2
  module Table
3
-
4
3
  def table_title_parse(node, out)
5
4
  name = node.at(ns("./name")) or return
6
5
  out.p **{ class: "TableTitle", style: "text-align:center;" } do |p|
7
- name and name.children.each { |n| parse(n, p) }
6
+ name&.children&.each { |n| parse(n, p) }
8
7
  end
9
8
  end
10
9
 
11
- def thead_parse(node, t)
10
+ def thead_parse(node, table)
12
11
  thead = node.at(ns("./thead"))
13
12
  if thead
14
- t.thead do |h|
13
+ table.thead do |h|
15
14
  thead.element_children.each_with_index do |n, i|
16
15
  tr_parse(n, h, i, thead.element_children.size, true)
17
16
  end
@@ -19,19 +18,19 @@ module IsoDoc::Function
19
18
  end
20
19
  end
21
20
 
22
- def tbody_parse(node, t)
21
+ def tbody_parse(node, table)
23
22
  tbody = node.at(ns("./tbody")) || return
24
- t.tbody do |h|
23
+ table.tbody do |h|
25
24
  tbody.element_children.each_with_index do |n, i|
26
25
  tr_parse(n, h, i, tbody.element_children.size, false)
27
26
  end
28
27
  end
29
28
  end
30
29
 
31
- def tfoot_parse(node, t)
30
+ def tfoot_parse(node, table)
32
31
  tfoot = node.at(ns("./tfoot"))
33
32
  if tfoot
34
- t.tfoot do |h|
33
+ table.tfoot do |h|
35
34
  tfoot.element_children.each_with_index do |n, i|
36
35
  tr_parse(n, h, i, tfoot.element_children.size, false)
37
36
  end
@@ -45,23 +44,23 @@ module IsoDoc::Function
45
44
  id: node["id"],
46
45
  class: "MsoISOTable",
47
46
  style: "border-width:1px;border-spacing:0;#{width}#{keep_style(node)}",
48
- title: node["alt"]
47
+ title: node["alt"],
49
48
  )
50
49
  end
51
50
 
52
- def tcaption(node, t)
51
+ def tcaption(node, table)
53
52
  return unless node["summary"]
54
53
 
55
- t.caption do |c|
54
+ table.caption do |c|
56
55
  c.span **{ style: "display:none" } do |s|
57
56
  s << node["summary"]
58
57
  end
59
58
  end
60
59
  end
61
60
 
62
- def colgroup(node, t)
61
+ def colgroup(node, table)
63
62
  colgroup = node.at(ns("./colgroup")) or return
64
- t.colgroup do |cg|
63
+ table.colgroup do |cg|
65
64
  colgroup.xpath(ns("./col")).each do |c|
66
65
  cg.col **{ style: "width: #{c['width']};" }
67
66
  end
@@ -90,19 +89,19 @@ module IsoDoc::Function
90
89
  # border-left:#{col.zero? ? "#{SW} 1.5pt;" : "none;"}
91
90
  # border-right:#{SW} #{col == totalcols && !header ? "1.5" : "1.0"}pt;
92
91
 
93
- def make_tr_attr(td, row, totalrows, header)
94
- style = td.name == "th" ? "font-weight:bold;" : ""
95
- td["align"] and style += "text-align:#{td['align']};"
96
- td["valign"] and style += "vertical-align:#{td['valign']};"
97
- rowmax = td["rowspan"] ? row + td["rowspan"].to_i - 1 : row
92
+ def make_tr_attr(cell, row, totalrows, header)
93
+ style = cell.name == "th" ? "font-weight:bold;" : ""
94
+ cell["align"] and style += "text-align:#{cell['align']};"
95
+ cell["valign"] and style += "vertical-align:#{cell['valign']};"
96
+ rowmax = cell["rowspan"] ? row + cell["rowspan"].to_i - 1 : row
98
97
  style += <<~STYLE
99
98
  border-top:#{row.zero? ? "#{SW} 1.5pt;" : 'none;'}
100
99
  border-bottom:#{SW} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
101
100
  STYLE
102
- header and scope = (td["colspan"] ? "colgroup" : "col")
103
- !header and td.name == "th" and scope =
104
- (td["rowspan"] ? "rowgroup" : "row")
105
- { rowspan: td["rowspan"], colspan: td["colspan"],
101
+ header and scope = (cell["colspan"] ? "colgroup" : "col")
102
+ !header and cell.name == "th" and scope =
103
+ (cell["rowspan"] ? "rowgroup" : "row")
104
+ { rowspan: cell["rowspan"], colspan: cell["colspan"],
106
105
  style: style.gsub(/\n/, ""), scope: scope }
107
106
  end
108
107
 
@@ -11,27 +11,27 @@ module IsoDoc::Function
11
11
  end
12
12
 
13
13
  def deprecated_term_parse(node, out)
14
- out.p **{ class: "DeprecatedTerms", style:"text-align:left;" } do |p|
14
+ out.p **{ class: "DeprecatedTerms", style: "text-align:left;" } do |p|
15
15
  p << l10n("#{@i18n.deprecated}: ")
16
16
  node.children.each { |c| parse(c, p) }
17
17
  end
18
18
  end
19
19
 
20
20
  def admitted_term_parse(node, out)
21
- out.p **{ class: "AltTerms", style:"text-align:left;" } do |p|
21
+ out.p **{ class: "AltTerms", style: "text-align:left;" } do |p|
22
22
  node.children.each { |c| parse(c, p) }
23
23
  end
24
24
  end
25
25
 
26
26
  def term_parse(node, out)
27
- out.p **{ class: "Terms", style:"text-align:left;" } do |p|
27
+ out.p **{ class: "Terms", style: "text-align:left;" } do |p|
28
28
  node.children.each { |c| parse(c, p) }
29
29
  end
30
30
  end
31
31
 
32
- def para_then_remainder(first, node, p, div)
32
+ def para_then_remainder(first, node, para, div)
33
33
  if first.name == "p"
34
- first.children.each { |n| parse(n, p) }
34
+ first.children.each { |n| parse(n, para) }
35
35
  node.elements.drop(1).each { |n| parse(n, div) }
36
36
  else
37
37
  node.elements.each { |n| parse(n, div) }
@@ -72,7 +72,6 @@ module IsoDoc::Function
72
72
  node.children.each { |n| parse(n, out) }
73
73
  end
74
74
 
75
- def termdocsource_parse(_node, _out)
76
- end
75
+ def termdocsource_parse(_node, _out); end
77
76
  end
78
77
  end
@@ -21,9 +21,10 @@ module IsoDoc::Function
21
21
  filename = filepath.sub_ext("").sub(/\.presentation$/, "").to_s
22
22
  dir = init_dir(filename, debug)
23
23
  @filename = filename
24
- @localdir = filepath.parent.to_s + "/"
24
+ @localdir = "#{filepath.parent}/"
25
25
  @sourcedir = @localdir
26
- @sourcefilename and @sourcedir = Pathname.new(@sourcefilename).parent.to_s + "/"
26
+ @sourcefilename and
27
+ @sourcedir = "#{Pathname.new(@sourcefilename).parent}/"
27
28
  [filename, dir]
28
29
  end
29
30
 
@@ -47,7 +48,7 @@ module IsoDoc::Function
47
48
 
48
49
  # isodoc.css overrides any CSS injected by Html2Doc, which
49
50
  # is inserted before this CSS.
50
- def define_head(head, filename, _dir)
51
+ def define_head(head, _filename, _dir)
51
52
  if @standardstylesheet
52
53
  head.style do |style|
53
54
  @standardstylesheet.open
@@ -128,6 +129,8 @@ module IsoDoc::Function
128
129
  end
129
130
 
130
131
  def boilerplate(node, out)
132
+ return if @bare
133
+
131
134
  boilerplate = node.at(ns("//boilerplate")) or return
132
135
  out.div **{ class: "authority" } do |s|
133
136
  boilerplate.children.each do |n|
@@ -1,193 +1,211 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module IsoDoc::Function
4
- module Utils
5
- def date_range(date)
6
- self.class.date_range(date)
7
- end
3
+ module IsoDoc
4
+ module Function
5
+ module Utils
6
+ def date_range(date)
7
+ self.class.date_range(date)
8
+ end
8
9
 
9
- def ns(xpath)
10
- self.class.ns(xpath)
11
- end
10
+ def ns(xpath)
11
+ self.class.ns(xpath)
12
+ end
12
13
 
13
- def insert_tab(out, n)
14
- tab = %w(Hans Hant).include?(@script) ? "&#x3000;" : "&nbsp; "
15
- [1..n].each { out << tab }
16
- end
14
+ def insert_tab(out, count)
15
+ tab = %w(Hans Hant).include?(@script) ? "&#x3000;" : "&nbsp; "
16
+ [1..count].each { out << tab }
17
+ end
17
18
 
18
- # add namespaces for Word fragments
19
- NOKOHEAD = <<~HERE
20
- <!DOCTYPE html SYSTEM
21
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
22
- <html xmlns="http://www.w3.org/1999/xhtml">
23
- <head> <title></title> <meta charset="UTF-8" /> </head>
24
- <body> </body> </html>
25
- HERE
26
-
27
- # block for processing XML document fragments as XHTML,
28
- # to allow for HTMLentities
29
- def noko(&block)
30
- doc = ::Nokogiri::XML.parse(NOKOHEAD)
31
- fragment = doc.fragment("")
32
- ::Nokogiri::XML::Builder.with fragment, &block
33
- fragment.to_xml(encoding: "US-ASCII").lines.map do |l|
34
- l.gsub(/\s*\n/, "")
19
+ # add namespaces for Word fragments
20
+ NOKOHEAD = <<~HERE
21
+ <!DOCTYPE html SYSTEM
22
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
23
+ <html xmlns="http://www.w3.org/1999/xhtml">
24
+ <head> <title></title> <meta charset="UTF-8" /> </head>
25
+ <body> </body> </html>
26
+ HERE
27
+
28
+ # block for processing XML document fragments as XHTML,
29
+ # to allow for HTMLentities
30
+ def noko(&block)
31
+ doc = ::Nokogiri::XML.parse(NOKOHEAD)
32
+ fragment = doc.fragment("")
33
+ ::Nokogiri::XML::Builder.with fragment, &block
34
+ fragment.to_xml(encoding: "US-ASCII").lines.map do |l|
35
+ l.gsub(/\s*\n/, "")
36
+ end
35
37
  end
36
- end
37
38
 
38
- def attr_code(attributes)
39
- attributes = attributes.reject { |_, val| val.nil? }.map
40
- attributes.map do |k, v|
41
- [k, v.is_a?(String) ? HTMLEntities.new.decode(v) : v]
42
- end.to_h
43
- end
39
+ def attr_code(attributes)
40
+ attributes = attributes.reject { |_, val| val.nil? }.map
41
+ attributes.map do |k, v|
42
+ [k, v.is_a?(String) ? HTMLEntities.new.decode(v) : v]
43
+ end.to_h
44
+ end
44
45
 
45
- DOCTYPE_HDR = '<!DOCTYPE html SYSTEM '\
46
- '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
47
-
48
- def to_xhtml(xml)
49
- xml.gsub!(/<\?xml[^>]*>/, "")
50
- /<!DOCTYPE /.match(xml) || (xml = DOCTYPE_HDR + xml)
51
- xml = xml.split(/(\&[^ \r\n\t#;]+;)/).map do |t|
52
- /^(\&[^ \t\r\n#;]+;)/.match?(t) ?
53
- HTMLEntities.new.encode(HTMLEntities.new.decode(t), :hexadecimal) : t
54
- end.join("")
55
- begin
56
- Nokogiri::XML.parse(xml, &:strict)
57
- rescue Nokogiri::XML::SyntaxError => e
58
- File.open("#{@filename}.#{@format}.err", "w:UTF-8") { |f| f.write xml }
59
- abort "Malformed Output XML for #{@format}: #{e} "\
60
- "(see #{@filename}.#{@format}.err)"
46
+ DOCTYPE_HDR = "<!DOCTYPE html SYSTEM "\
47
+ '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
48
+
49
+ def to_xhtml(xml)
50
+ xml = to_xhtml_prep(xml)
51
+ begin
52
+ Nokogiri::XML.parse(xml, &:strict)
53
+ rescue Nokogiri::XML::SyntaxError => e
54
+ File.open("#{@filename}.#{@format}.err", "w:UTF-8") do |f|
55
+ f.write xml
56
+ end
57
+ abort "Malformed Output XML for #{@format}: #{e} "\
58
+ "(see #{@filename}.#{@format}.err)"
59
+ end
61
60
  end
62
- end
63
61
 
64
- def to_xhtml_fragment(xml)
65
- doc = ::Nokogiri::XML.parse(NOKOHEAD)
66
- fragment = doc.fragment(xml)
67
- fragment
68
- end
62
+ def to_xhtml_prep(xml)
63
+ xml.gsub!(/<\?xml[^>]*>/, "")
64
+ /<!DOCTYPE /.match(xml) || (xml = DOCTYPE_HDR + xml)
65
+ xml.split(/(&[^ \r\n\t#;]+;)/).map do |t|
66
+ if /^(&[^ \t\r\n#;]+;)/.match?(t)
67
+ HTMLEntities.new.encode(HTMLEntities.new.decode(t), :hexadecimal)
68
+ else t
69
+ end
70
+ end.join("")
71
+ end
69
72
 
70
- def from_xhtml(xml)
71
- xml.to_xml.sub(%r{ xmlns="http://www.w3.org/1999/xhtml"}, "")
72
- end
73
+ def to_xhtml_fragment(xml)
74
+ doc = ::Nokogiri::XML.parse(NOKOHEAD)
75
+ doc.fragment(xml)
76
+ end
73
77
 
74
- CLAUSE_ANCESTOR =
75
- ".//ancestor::*[local-name() = 'annex' or "\
76
- "local-name() = 'definitions' or "\
77
- "local-name() = 'acknowledgements' or local-name() = 'term' or "\
78
- "local-name() = 'appendix' or local-name() = 'foreword' or "\
79
- "local-name() = 'introduction' or local-name() = 'terms' or "\
80
- "local-name() = 'clause' or local-name() = 'references']/@id"
81
-
82
- def get_clause_id(node)
83
- clause = node.xpath(CLAUSE_ANCESTOR)
84
- clause&.last&.text || nil
85
- end
78
+ def from_xhtml(xml)
79
+ xml.to_xml.sub(%r{ xmlns="http://www.w3.org/1999/xhtml"}, "")
80
+ end
86
81
 
87
- NOTE_CONTAINER_ANCESTOR =
88
- ".//ancestor::*[local-name() = 'annex' or "\
89
- "local-name() = 'foreword' or local-name() = 'appendix' or "\
90
- "local-name() = 'introduction' or local-name() = 'terms' or "\
91
- "local-name() = 'acknowledgements' or local-name() = 'term' or "\
92
- "local-name() = 'clause' or local-name() = 'references' or "\
93
- "local-name() = 'figure' or local-name() = 'formula' or "\
94
- "local-name() = 'table' or local-name() = 'example']/@id"
95
-
96
- def get_note_container_id(node)
97
- container = node.xpath(NOTE_CONTAINER_ANCESTOR)
98
- container&.last&.text || nil
99
- end
82
+ CLAUSE_ANCESTOR =
83
+ ".//ancestor::*[local-name() = 'annex' or "\
84
+ "local-name() = 'definitions' or "\
85
+ "local-name() = 'acknowledgements' or local-name() = 'term' or "\
86
+ "local-name() = 'appendix' or local-name() = 'foreword' or "\
87
+ "local-name() = 'introduction' or local-name() = 'terms' or "\
88
+ "local-name() = 'clause' or local-name() = 'references']/@id"
89
+
90
+ def get_clause_id(node)
91
+ clause = node.xpath(CLAUSE_ANCESTOR)
92
+ clause&.last&.text || nil
93
+ end
100
94
 
101
- def sentence_join(array)
102
- return '' if array.nil? || array.empty?
103
- if array.length == 1 then array[0]
104
- else
105
- @i18n.l10n("#{array[0..-2].join(', ')} "\
106
- "#{@i18n.and} #{array.last}",
107
- @lang, @script)
95
+ NOTE_CONTAINER_ANCESTOR =
96
+ ".//ancestor::*[local-name() = 'annex' or "\
97
+ "local-name() = 'foreword' or local-name() = 'appendix' or "\
98
+ "local-name() = 'introduction' or local-name() = 'terms' or "\
99
+ "local-name() = 'acknowledgements' or local-name() = 'term' or "\
100
+ "local-name() = 'clause' or local-name() = 'references' or "\
101
+ "local-name() = 'figure' or local-name() = 'formula' or "\
102
+ "local-name() = 'table' or local-name() = 'example']/@id"
103
+
104
+ def get_note_container_id(node)
105
+ container = node.xpath(NOTE_CONTAINER_ANCESTOR)
106
+ container&.last&.text || nil
108
107
  end
109
- end
110
108
 
111
- # avoid `; avoid {{ (Liquid Templates); avoid [[ (Javascript)
112
- def extract_delims(text)
113
- @openmathdelim = "(#("
114
- @closemathdelim = ")#)"
115
- while text.include?(@openmathdelim) || text.include?(@closemathdelim)
116
- @openmathdelim += "("
117
- @closemathdelim += ")"
109
+ def sentence_join(array)
110
+ return "" if array.nil? || array.empty?
111
+
112
+ if array.length == 1 then array[0]
113
+ else
114
+ @i18n.l10n("#{array[0..-2].join(', ')} "\
115
+ "#{@i18n.and} #{array.last}",
116
+ @lang, @script)
117
+ end
118
118
  end
119
- [@openmathdelim, @closemathdelim]
120
- end
121
119
 
122
- def header_strip(h)
123
- h = h.to_s.gsub(%r{<br\s*/>}, " ").gsub(/<\/?h[123456][^>]*>/, "")
124
- .gsub(/<\/?b[^>]*>/, "")
125
- h1 = to_xhtml_fragment(h.dup)
126
- h1.traverse do |x|
127
- x.replace(" ") if x.name == "span" && /mso-tab-count/.match(x["style"])
128
- x.remove if x.name == "img"
129
- x.remove if x.name == "span" && x["class"] == "MsoCommentReference"
130
- x.remove if x.name == "a" && x["class"] == "FootnoteRef"
131
- x.remove if x.name == "span" && /mso-bookmark/.match(x["style"])
132
- x.replace(x.children) if x.name == "a"
133
- end
134
- from_xhtml(h1)
135
- end
120
+ # avoid `; avoid {{ (Liquid Templates); avoid [[ (Javascript)
121
+ def extract_delims(text)
122
+ @openmathdelim = "(#("
123
+ @closemathdelim = ")#)"
124
+ while text.include?(@openmathdelim) || text.include?(@closemathdelim)
125
+ @openmathdelim += "("
126
+ @closemathdelim += ")"
127
+ end
128
+ [@openmathdelim, @closemathdelim]
129
+ end
136
130
 
137
- def liquid(doc)
138
- self.class.liquid(doc)
139
- end
131
+ def header_strip(hdr)
132
+ h1 = to_xhtml_fragment(hdr.to_s.gsub(%r{<br\s*/>}, " ")
133
+ .gsub(/<\/?h[123456][^>]*>/, "").gsub(/<\/?b[^>]*>/, "").dup)
134
+ h1.traverse do |x|
135
+ if x.name == "span" && /mso-tab-count/.match(x["style"])
136
+ x.replace(" ")
137
+ elsif header_strip_elem?(x) then x.remove
138
+ elsif x.name == "a" then x.replace(x.children)
139
+ end
140
+ end
141
+ from_xhtml(h1)
142
+ end
140
143
 
141
- def liquid(doc)
142
- # unescape HTML escapes in doc
143
- doc = doc.split(%r<(\{%|%\})>).each_slice(4).map do |a|
144
- a[2] = a[2].gsub(/\&lt;/, "<").gsub(/\&gt;/, ">") if a.size > 2
145
- a.join("")
146
- end.join("")
147
- Liquid::Template.parse(doc)
148
- end
144
+ def header_strip_elem?(elem)
145
+ elem.name == "img" ||
146
+ elem.name == "span" && elem["class"] == "MsoCommentReference" ||
147
+ elem.name == "a" && elem["class"] == "FootnoteRef" ||
148
+ elem.name == "span" && /mso-bookmark/.match(elem["style"])
149
+ end
149
150
 
150
- def empty2nil(v)
151
- return nil if !v.nil? && v.is_a?(String) && v.empty?
152
- v
153
- end
151
+ =begin
152
+ def liquid(doc)
153
+ self.class.liquid(doc)
154
+ end
155
+ =end
156
+
157
+ def liquid(doc)
158
+ # unescape HTML escapes in doc
159
+ doc = doc.split(%r<(\{%|%\})>).each_slice(4).map do |a|
160
+ a[2] = a[2].gsub(/&lt;/, "<").gsub(/&gt;/, ">") if a.size > 2
161
+ a.join("")
162
+ end.join("")
163
+ Liquid::Template.parse(doc)
164
+ end
154
165
 
155
- def populate_template(docxml, _format = nil)
156
- meta = @meta
157
- .get
158
- .merge(@labels ? {labels: @labels} : {})
159
- .merge(@meta.labels ? {labels: @meta.labels} : {})
160
- .merge(fonts_options || {})
161
- template = liquid(docxml)
162
- template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h)
163
- .gsub("&lt;", "&#x3c;").gsub("&gt;", "&#x3e;").gsub("&amp;", "&#x26;")
164
- end
166
+ def empty2nil(str)
167
+ return nil if !str.nil? && str.is_a?(String) && str.empty?
165
168
 
166
- def save_dataimage(uri, _relative_dir = true)
167
- %r{^data:(image|application)/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
168
- imgtype.sub!(/\+[a-z0-9]+$/, "") # svg+xml
169
- imgtype = "png" unless /^[a-z0-9]+$/.match imgtype
170
- Tempfile.open(["image", ".#{imgtype}"]) do |f|
171
- f.binmode
172
- f.write(Base64.strict_decode64(imgdata))
173
- @tempfile_cache << f # persist to the end
174
- f.path
169
+ str
175
170
  end
176
- end
177
171
 
178
- def image_localfile(i)
179
- if /^data:/.match? i["src"]
180
- save_dataimage(i["src"], false)
181
- elsif %r{^([A-Z]:)?/}.match? i["src"]
182
- i["src"]
183
- else
184
- File.join(@localdir, i["src"])
172
+ def populate_template(docxml, _format = nil)
173
+ meta = @meta
174
+ .get
175
+ .merge(@labels ? { labels: @labels } : {})
176
+ .merge(@meta.labels ? { labels: @meta.labels } : {})
177
+ .merge(fonts_options || {})
178
+ template = liquid(docxml)
179
+ template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h)
180
+ .gsub("&lt;", "&#x3c;").gsub("&gt;", "&#x3e;").gsub("&amp;", "&#x26;")
185
181
  end
186
- end
187
182
 
188
- def labelled_ancestor(node)
189
- !node.ancestors("example, requirement, recommendation, permission, "\
190
- "note, table, figure, sourcecode").empty?
183
+ def save_dataimage(uri, _relative_dir = true)
184
+ %r{^data:(image|application)/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
185
+ imgtype.sub!(/\+[a-z0-9]+$/, "") # svg+xml
186
+ imgtype = "png" unless /^[a-z0-9]+$/.match? imgtype
187
+ Tempfile.open(["image", ".#{imgtype}"]) do |f|
188
+ f.binmode
189
+ f.write(Base64.strict_decode64(imgdata))
190
+ @tempfile_cache << f # persist to the end
191
+ f.path
192
+ end
193
+ end
194
+
195
+ def image_localfile(img)
196
+ if /^data:/.match? img["src"]
197
+ save_dataimage(img["src"], false)
198
+ elsif %r{^([A-Z]:)?/}.match? img["src"]
199
+ img["src"]
200
+ else
201
+ File.join(@localdir, img["src"])
202
+ end
203
+ end
204
+
205
+ def labelled_ancestor(node)
206
+ !node.ancestors("example, requirement, recommendation, permission, "\
207
+ "note, table, figure, sourcecode").empty?
208
+ end
191
209
  end
192
210
  end
193
211
  end