isodoc 1.6.3 → 1.6.7.1

Sign up to get free protection for your applications and to get access to all the features.
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