isodoc 1.0.24 → 1.0.29

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +14 -4
  3. data/.github/workflows/ubuntu.yml +19 -5
  4. data/.github/workflows/windows.yml +14 -4
  5. data/isodoc.gemspec +1 -1
  6. data/lib/isodoc-yaml/i18n-en.yaml +3 -1
  7. data/lib/isodoc-yaml/i18n-fr.yaml +3 -1
  8. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +3 -1
  9. data/lib/isodoc/convert.rb +1 -0
  10. data/lib/isodoc/function/blocks.rb +43 -49
  11. data/lib/isodoc/function/{blocks_example.rb → blocks_example_note.rb} +57 -2
  12. data/lib/isodoc/function/cleanup.rb +16 -2
  13. data/lib/isodoc/function/i18n.rb +1 -0
  14. data/lib/isodoc/function/inline.rb +79 -77
  15. data/lib/isodoc/function/inline_simple.rb +72 -0
  16. data/lib/isodoc/function/lists.rb +12 -6
  17. data/lib/isodoc/function/references.rb +51 -39
  18. data/lib/isodoc/function/reqt.rb +13 -4
  19. data/lib/isodoc/function/section.rb +19 -8
  20. data/lib/isodoc/function/table.rb +3 -4
  21. data/lib/isodoc/function/terms.rb +1 -1
  22. data/lib/isodoc/function/to_word_html.rb +23 -13
  23. data/lib/isodoc/function/utils.rb +13 -6
  24. data/lib/isodoc/function/xref_counter.rb +43 -9
  25. data/lib/isodoc/function/xref_gen.rb +2 -1
  26. data/lib/isodoc/function/xref_gen_seq.rb +11 -10
  27. data/lib/isodoc/function/xref_sect_gen.rb +24 -24
  28. data/lib/isodoc/headlesshtml_convert.rb +5 -0
  29. data/lib/isodoc/html_convert.rb +5 -0
  30. data/lib/isodoc/html_function/footnotes.rb +3 -3
  31. data/lib/isodoc/html_function/html.rb +16 -1
  32. data/lib/isodoc/html_function/postprocess.rb +6 -5
  33. data/lib/isodoc/metadata.rb +10 -3
  34. data/lib/isodoc/metadata_date.rb +19 -7
  35. data/lib/isodoc/pdf_convert.rb +5 -0
  36. data/lib/isodoc/version.rb +1 -1
  37. data/lib/isodoc/word_convert.rb +5 -0
  38. data/lib/isodoc/word_function/body.rb +13 -51
  39. data/lib/isodoc/word_function/footnotes.rb +3 -3
  40. data/lib/isodoc/word_function/inline.rb +75 -0
  41. data/lib/isodoc/word_function/postprocess.rb +13 -2
  42. data/lib/isodoc/word_function/table.rb +3 -3
  43. data/lib/isodoc/xslfo_convert.rb +5 -0
  44. data/spec/assets/i18n.yaml +4 -1
  45. data/spec/assets/odf.emf +0 -0
  46. data/spec/assets/odf.svg +4 -0
  47. data/spec/assets/odf1.svg +4 -0
  48. data/spec/isodoc/blocks_spec.rb +274 -51
  49. data/spec/isodoc/cleanup_spec.rb +317 -25
  50. data/spec/isodoc/footnotes_spec.rb +20 -5
  51. data/spec/isodoc/i18n_spec.rb +12 -12
  52. data/spec/isodoc/inline_spec.rb +299 -4
  53. data/spec/isodoc/lists_spec.rb +8 -8
  54. data/spec/isodoc/metadata_spec.rb +112 -3
  55. data/spec/isodoc/postproc_spec.rb +39 -21
  56. data/spec/isodoc/ref_spec.rb +121 -52
  57. data/spec/isodoc/section_spec.rb +236 -207
  58. data/spec/isodoc/table_spec.rb +28 -28
  59. data/spec/isodoc/terms_spec.rb +57 -13
  60. data/spec/isodoc/xref_spec.rb +218 -71
  61. metadata +10 -5
@@ -60,8 +60,12 @@ module IsoDoc::Function
60
60
  %w(label title subject classification tag value inherit).include? n.name
61
61
  end
62
62
 
63
+ def reqt_attrs(node, klass)
64
+ attr_code(class: klass, id: node["id"], style: keep_style(node))
65
+ end
66
+
63
67
  def recommendation_parse(node, out)
64
- out.div **{ class: "recommend" } do |t|
68
+ out.div **reqt_attrs(node, "recommend") do |t|
65
69
  recommendation_name(node, t, @recommendation_lbl)
66
70
  recommendation_attributes(node, out)
67
71
  node.children.each do |n|
@@ -71,7 +75,7 @@ module IsoDoc::Function
71
75
  end
72
76
 
73
77
  def requirement_parse(node, out)
74
- out.div **{ class: "require" } do |t|
78
+ out.div **reqt_attrs(node, "require") do |t|
75
79
  recommendation_name(node, t, @requirement_lbl)
76
80
  recommendation_attributes(node, out)
77
81
  node.children.each do |n|
@@ -81,7 +85,7 @@ module IsoDoc::Function
81
85
  end
82
86
 
83
87
  def permission_parse(node, out)
84
- out.div **{ class: "permission" } do |t|
88
+ out.div **reqt_attrs(node, "permission") do |t|
85
89
  recommendation_name(node, t, @permission_lbl)
86
90
  recommendation_attributes(node, out)
87
91
  node.children.each do |n|
@@ -90,9 +94,14 @@ module IsoDoc::Function
90
94
  end
91
95
  end
92
96
 
97
+ def reqt_component_attrs(node)
98
+ attr_code(class: "requirement-" + node.name,
99
+ style: keep_style(node))
100
+ end
101
+
93
102
  def requirement_component_parse(node, out)
94
103
  return if node["exclude"] == "true"
95
- out.div **{ class: "requirement-" + node.name } do |div|
104
+ out.div **reqt_component_attrs(node) do |div|
96
105
  node.children.each do |n|
97
106
  parse(n, div)
98
107
  end
@@ -16,6 +16,7 @@ module IsoDoc::Function
16
16
  clausedelimspace(out)
17
17
  end
18
18
  c1&.children&.each { |c2| parse(c2, b) }
19
+ clausedelimspace(out) if /\S/.match(c1&.text)
19
20
  end
20
21
  end
21
22
  end
@@ -109,20 +110,29 @@ module IsoDoc::Function
109
110
  num
110
111
  end
111
112
 
112
- def terms_defs_title(f)
113
- symbols = f.at(ns(".//definitions"))
114
- return @termsdefsymbols_lbl if symbols
115
- @termsdef_lbl
116
- end
117
-
118
113
  TERM_CLAUSE = "//sections/terms | "\
119
114
  "//sections/clause[descendant::terms]".freeze
120
115
 
116
+ def term_def_title(title)
117
+ case title&.text
118
+ when "Terms, definitions, symbols and abbreviated terms"
119
+ @labels["termsdefsymbolsabbrev"]
120
+ when "Terms, definitions and symbols"
121
+ @labels["termsdefsymbols"]
122
+ when "Terms, definitions and abbreviated terms"
123
+ @labels["termsdefabbrev"]
124
+ when "Terms and definitions"
125
+ @labels["termsdef"]
126
+ else
127
+ title
128
+ end
129
+ end
130
+
121
131
  def terms_defs(isoxml, out, num)
122
132
  f = isoxml.at(ns(TERM_CLAUSE)) or return num
123
133
  out.div **attr_code(id: f["id"]) do |div|
124
134
  num = num + 1
125
- clause_name(num, terms_defs_title(f), div, nil)
135
+ clause_name(num, term_def_title(f&.at(ns("./title"))), div, nil)
126
136
  f.elements.each do |e|
127
137
  parse(e, div) unless %w{title source}.include? e.name
128
138
  end
@@ -198,7 +208,8 @@ module IsoDoc::Function
198
208
 
199
209
  def preface(isoxml, out)
200
210
  title_attr = { class: "IntroTitle" }
201
- isoxml.xpath(ns("//preface/clause")).each do |f|
211
+ isoxml.xpath(ns("//preface/clause | //preface/terms | //preface/definitions | "\
212
+ "//preface/references")).each do |f|
202
213
  page_break(out)
203
214
  out.div **{ class: "Section3", id: f["id"] } do |div|
204
215
  clause_name(nil, f&.at(ns("./title")), div, title_attr)
@@ -44,12 +44,12 @@ module IsoDoc::Function
44
44
  end
45
45
  end
46
46
 
47
- def make_table_attr(node)
47
+ def table_attrs(node)
48
48
  width = node["width"] ? "width:#{node['width']};" : nil
49
49
  attr_code(
50
50
  id: node["id"],
51
51
  class: "MsoISOTable",
52
- style: "border-width:1px;border-spacing:0;#{width}",
52
+ style: "border-width:1px;border-spacing:0;#{width}#{keep_style(node)}",
53
53
  title: node["alt"]
54
54
  )
55
55
  end
@@ -66,7 +66,7 @@ module IsoDoc::Function
66
66
  def table_parse(node, out)
67
67
  @in_table = true
68
68
  table_title_parse(node, out)
69
- out.table **make_table_attr(node) do |t|
69
+ out.table **table_attrs(node) do |t|
70
70
  tcaption(node, t)
71
71
  thead_parse(node, t)
72
72
  tbody_parse(node, t)
@@ -91,7 +91,6 @@ module IsoDoc::Function
91
91
  style += <<~STYLE
92
92
  border-top:#{row.zero? ? "#{SW} 1.5pt;" : 'none;'}
93
93
  border-bottom:#{SW} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
94
- padding:0;
95
94
  STYLE
96
95
  header and scope = (td["colspan"] ? "colgroup" : "col")
97
96
  !header and td.name == "th" and scope =
@@ -40,7 +40,7 @@ module IsoDoc::Function
40
40
  end
41
41
 
42
42
  def termnote_parse(node, out)
43
- out.div **{ class: "Note" } do |div|
43
+ out.div **note_attrs(node) do |div|
44
44
  first = node.first_element_child
45
45
  div.p do |p|
46
46
  p << "#{anchor(node['id'], :label) || '???'}: "
@@ -21,7 +21,7 @@ module IsoDoc::Function
21
21
  filename = filepath.sub_ext('').to_s
22
22
  dir = "#{filename}_files"
23
23
  unless debug
24
- Dir.mkdir(dir) unless File.exists?(dir)
24
+ Dir.mkdir(dir, 0777) unless File.exists?(dir)
25
25
  FileUtils.rm_rf "#{dir}/*"
26
26
  end
27
27
  @filename = filename
@@ -79,7 +79,7 @@ module IsoDoc::Function
79
79
 
80
80
  def make_body3(body, docxml)
81
81
  body.div **{ class: "main-section" } do |div3|
82
- boilerplate docxml, div3
82
+ boilerplate docxml, div3
83
83
  abstract docxml, div3
84
84
  foreword docxml, div3
85
85
  introduction docxml, div3
@@ -102,6 +102,7 @@ module IsoDoc::Function
102
102
  @meta.relations isoxml, out
103
103
  @meta.version isoxml, out
104
104
  @meta.url isoxml, out
105
+ @meta.keywords isoxml, out
105
106
  @meta.get
106
107
  end
107
108
 
@@ -109,8 +110,15 @@ module IsoDoc::Function
109
110
  out.p(**{ class: "zzSTDTitle1" }) { |p| p << @meta.get[:doctitle] }
110
111
  end
111
112
 
113
+ def middle_admonitions(isoxml, out)
114
+ isoxml.xpath(ns("//sections/note | //sections/admonition")).each do |x|
115
+ parse(x, out)
116
+ end
117
+ end
118
+
112
119
  def middle(isoxml, out)
113
120
  middle_title(out)
121
+ middle_admonitions(isoxml, out)
114
122
  i = scope isoxml, out, 0
115
123
  i = norm_ref isoxml, out, i
116
124
  i = terms_defs isoxml, out, i
@@ -120,20 +128,20 @@ module IsoDoc::Function
120
128
  bibliography isoxml, out
121
129
  end
122
130
 
123
- def boilerplate(node, out)
124
- boilerplate = node.at(ns("//boilerplate")) or return
125
- out.div **{class: "authority"} do |s|
126
- boilerplate.children.each do |n|
127
- if n.name == "title"
128
- s.h1 do |h|
129
- n.children.each { |nn| parse(nn, h) }
130
- end
131
- else
132
- parse(n, s)
131
+ def boilerplate(node, out)
132
+ boilerplate = node.at(ns("//boilerplate")) or return
133
+ out.div **{class: "authority"} do |s|
134
+ boilerplate.children.each do |n|
135
+ if n.name == "title"
136
+ s.h1 do |h|
137
+ n.children.each { |nn| parse(nn, h) }
133
138
  end
139
+ else
140
+ parse(n, s)
134
141
  end
135
142
  end
136
143
  end
144
+ end
137
145
 
138
146
  def parse(node, out)
139
147
  if node.text?
@@ -157,7 +165,7 @@ module IsoDoc::Function
157
165
  when "clause" then clause_parse(node, out)
158
166
  when "xref" then xref_parse(node, out)
159
167
  when "eref" then eref_parse(node, out)
160
- when "origin" then eref_parse(node, out)
168
+ when "origin" then origin_parse(node, out)
161
169
  when "link" then link_parse(node, out)
162
170
  when "ul" then ul_parse(node, out)
163
171
  when "ol" then ol_parse(node, out)
@@ -210,6 +218,8 @@ module IsoDoc::Function
210
218
  when "license-statement" then license_parse(node, out)
211
219
  when "legal-statement" then legal_parse(node, out)
212
220
  when "feedback-statement" then feedback_parse(node, out)
221
+ when "passthrough" then passthrough_parse(node, out)
222
+ when "variant" then variant_parse(node, out)
213
223
  else
214
224
  error_parse(node, out)
215
225
  end
@@ -49,7 +49,12 @@ module IsoDoc::Function
49
49
  /^(\&[^ \t\r\n#;]+;)/.match(t) ?
50
50
  HTMLEntities.new.encode(HTMLEntities.new.decode(t), :hexadecimal) : t
51
51
  end.join("")
52
- Nokogiri::XML.parse(xml)
52
+ begin
53
+ Nokogiri::XML.parse(xml) { |config| config.strict }
54
+ rescue Nokogiri::XML::SyntaxError => e
55
+ File.open("#{@filename}.#{@format}.err", "w:UTF-8") { |f| f.write xml }
56
+ abort "Malformed Output XML for #{@format}: #{e} (see #{@filename}.#{@format}.err)"
57
+ end
53
58
  end
54
59
 
55
60
  def to_xhtml_fragment(xml)
@@ -64,7 +69,7 @@ module IsoDoc::Function
64
69
 
65
70
  CLAUSE_ANCESTOR =
66
71
  ".//ancestor::*[local-name() = 'annex' or "\
67
- "local-name() = 'acknowledgements' or "\
72
+ "local-name() = 'acknowledgements' or local-name() = 'term' or "\
68
73
  "local-name() = 'appendix' or local-name() = 'foreword' or "\
69
74
  "local-name() = 'introduction' or local-name() = 'terms' or "\
70
75
  "local-name() = 'clause' or local-name() = 'references']/@id".freeze
@@ -78,7 +83,7 @@ module IsoDoc::Function
78
83
  ".//ancestor::*[local-name() = 'annex' or "\
79
84
  "local-name() = 'foreword' or local-name() = 'appendix' or "\
80
85
  "local-name() = 'introduction' or local-name() = 'terms' or "\
81
- "local-name() = 'acknowledgements' or "\
86
+ "local-name() = 'acknowledgements' or local-name() = 'term' or "\
82
87
  "local-name() = 'clause' or local-name() = 'references' or "\
83
88
  "local-name() = 'figure' or local-name() = 'formula' or "\
84
89
  "local-name() = 'table' or local-name() = 'example']/@id".freeze
@@ -110,12 +115,13 @@ module IsoDoc::Function
110
115
  end
111
116
 
112
117
  def header_strip(h)
113
- h = h.to_s.gsub(%r{<br/>}, " ").sub(/<\/?h[123456][^>]*>/, "")
118
+ h = h.to_s.gsub(%r{<br\s*/>}, " ").gsub(/<\/?h[123456][^>]*>/, "").
119
+ gsub(/<\/?b[^>]*>/, "")
114
120
  h1 = to_xhtml_fragment(h.dup)
115
121
  h1.traverse do |x|
116
122
  x.replace(" ") if x.name == "span" && /mso-tab-count/.match(x["style"])
117
123
  x.remove if x.name == "span" && x["class"] == "MsoCommentReference"
118
- x.remove if x.name == "a" && x["epub:type"] == "footnote"
124
+ x.remove if x.name == "a" && x["class"] == "FootnoteRef"
119
125
  x.remove if x.name == "span" && /mso-bookmark/.match(x["style"])
120
126
  x.replace(x.children) if x.name == "a"
121
127
  end
@@ -141,7 +147,7 @@ module IsoDoc::Function
141
147
  end
142
148
 
143
149
  def populate_template(docxml, _format = nil)
144
- meta = @meta.get.merge(@labels || {})
150
+ meta = @meta.get.merge(@labels || {}).merge(@meta.labels || {})
145
151
  template = liquid(docxml)
146
152
  template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h).
147
153
  gsub('&lt;', '&#x3c;').gsub('&gt;', '&#x3e;').gsub('&amp;', '&#x26;')
@@ -149,6 +155,7 @@ module IsoDoc::Function
149
155
 
150
156
  def save_dataimage(uri, relative_dir = true)
151
157
  %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
158
+ imgtype.sub!(/\+[a-z0-9]+$/, "") # svg+xml
152
159
  imgtype = "png" unless /^[a-z0-9]+$/.match imgtype
153
160
  Tempfile.open(["image", ".#{imgtype}"]) do |f|
154
161
  f.binmode
@@ -15,26 +15,60 @@ module IsoDoc::Function
15
15
  @num = 0
16
16
  @letter = ""
17
17
  @subseq = ""
18
+ @letter_override = nil
19
+ @number_override = nil
20
+ end
21
+
22
+ def new_subseq_increment(node)
23
+ @subseq = node["subsequence"]
24
+ @num += 1
25
+ @letter = node["subsequence"] ? "a" : ""
26
+ if node["number"]
27
+ /^(?<n>\d*)(?<a>[a-z]*)$/ =~ node["number"]
28
+ if n || a
29
+ @letter_override = @letter = a if a
30
+ @number_override = @num = n.to_i if n
31
+ else
32
+ @letter_override = node["number"]
33
+ @letter = @letter_override if /^[a-z]$/.match(@letter_override)
34
+ end
35
+ end
36
+ end
37
+
38
+ def sequence_increment(node)
39
+ if node["number"]
40
+ @number_override = node["number"]
41
+ @num = @number_override.to_i if /^\d+$/.match(@number_override)
42
+ else
43
+ @num += 1
44
+ end
45
+ end
46
+
47
+ def subsequence_increment(node)
48
+ if node["number"]
49
+ @letter_override = node["number"]
50
+ @letter = @letter_override if /^[a-z]$/.match(@letter_override)
51
+ else
52
+ @letter = (@letter.ord + 1).chr.to_s
53
+ end
18
54
  end
19
55
 
20
56
  def increment(node)
21
57
  return self if node["unnumbered"]
58
+ @letter_override = nil
59
+ @number_override = nil
22
60
  if node["subsequence"] != @subseq
23
- @subseq = node["subsequence"]
24
- @num += 1
25
- @letter = node["subsequence"] ? "a" : ""
61
+ new_subseq_increment(node)
62
+ elsif @letter.empty?
63
+ sequence_increment(node)
26
64
  else
27
- if @letter.empty?
28
- @num += 1
29
- else
30
- @letter = (@letter.ord + 1).chr.to_s
31
- end
65
+ subsequence_increment(node)
32
66
  end
33
67
  self
34
68
  end
35
69
 
36
70
  def print
37
- "#{@num}#{@letter}"
71
+ "#{@number_override || @num}#{@letter_override || @letter}"
38
72
  end
39
73
 
40
74
  def listlabel(depth)
@@ -40,6 +40,7 @@ module IsoDoc::Function
40
40
 
41
41
  SECTIONS_XPATH =
42
42
  "//foreword | //introduction | //acknowledgements | //preface/clause | "\
43
+ "//preface/terms | preface/definitions | preface/references | "\
43
44
  "//sections/terms | //annex | "\
44
45
  "//sections/clause | //sections/definitions | "\
45
46
  "//bibliography/references | //bibliography/clause".freeze
@@ -68,7 +69,7 @@ module IsoDoc::Function
68
69
  "not(self::xmlns:terms) and not(self::xmlns:definitions)]//"\
69
70
  "xmlns:example | ./xmlns:example".freeze
70
71
 
71
- CHILD_SECTIONS = "./clause | ./appendix | ./terms | ./definitions"
72
+ CHILD_SECTIONS = "./clause | ./appendix | ./terms | ./definitions | ./references"
72
73
 
73
74
  def example_anchor_names(sections)
74
75
  sections.each do |s|
@@ -1,15 +1,20 @@
1
1
  module IsoDoc::Function
2
2
  module XrefGen
3
+ def subfigure_increment(j, c, t)
4
+ if t.parent.name == "figure" then j += 1
5
+ else
6
+ j = 0
7
+ c.increment(t)
8
+ end
9
+ j
10
+ end
11
+
3
12
  def sequential_figure_names(clause)
4
13
  c = Counter.new
5
14
  j = 0
6
15
  clause.xpath(ns(".//figure | .//sourcecode[not(ancestor::example)]")).
7
16
  each do |t|
8
- if t.parent.name == "figure" then j += 1
9
- else
10
- j = 0
11
- c.increment(t)
12
- end
17
+ j = subfigure_increment(j, c, t)
13
18
  label = c.print + (j.zero? ? "" : "-#{j}")
14
19
  next if t["id"].nil? || t["id"].empty?
15
20
  @anchors[t["id"]] =
@@ -80,11 +85,7 @@ module IsoDoc::Function
80
85
  j = 0
81
86
  clause.xpath(ns(".//figure | .//sourcecode[not(ancestor::example)]")).
82
87
  each do |t|
83
- if t.parent.name == "figure" then j += 1
84
- else
85
- j = 0
86
- c.increment(t)
87
- end
88
+ j = subfigure_increment(j, c, t)
88
89
  label = "#{num}#{hiersep}#{c.print}" +
89
90
  (j.zero? ? "" : "#{hierfigsep}#{j}")
90
91
  next if t["id"].nil? || t["id"].empty?
@@ -5,10 +5,9 @@ module IsoDoc::Function
5
5
  annex_names(c, (65 + i).chr.to_s)
6
6
  end
7
7
  docxml.xpath(
8
- ns("//bibliography/clause[not(xmlns:title = 'Normative References' or "\
9
- "xmlns:title = 'Normative references')] |"\
10
- "//bibliography/references[not(xmlns:title = 'Normative References'"\
11
- " or xmlns:title = 'Normative references')]")).each do |b|
8
+ ns("//bibliography/clause[.//references[@normative = 'false']] | "\
9
+ "//bibliography/references[@normative = 'false']"
10
+ )).each do |b|
12
11
  preface_names(b)
13
12
  end
14
13
  docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |ref|
@@ -17,23 +16,13 @@ module IsoDoc::Function
17
16
  end
18
17
 
19
18
  def initial_anchor_names(d)
20
- preface_names(d.at(ns("//preface/abstract")))
21
- preface_names(d.at(ns("//foreword")))
22
- preface_names(d.at(ns("//introduction")))
23
- d.xpath(ns("//preface/clause")).each do |c|
24
- preface_names(c)
25
- end
26
- preface_names(d.at(ns("//acknowledgements")))
19
+ d.xpath(ns("//preface/*")).each { |c| c.element? and preface_names(c) }
27
20
  # potentially overridden in middle_section_asset_names()
28
- sequential_asset_names(
29
- d.xpath(ns("//preface/abstract | //foreword | //introduction | "\
30
- "//preface/clause | //acknowledgements")))
21
+ sequential_asset_names(d.xpath(ns("//preface/*")))
31
22
  n = section_names(d.at(ns("//clause[title = 'Scope']")), 0, 1)
32
23
  n = section_names(d.at(ns(
33
- "//bibliography/clause[title = 'Normative References' or "\
34
- "title = 'Normative references'] |"\
35
- "//bibliography/references[title = 'Normative References' or "\
36
- "title = 'Normative references']")), n, 1)
24
+ "//bibliography/clause[.//references[@normative = 'true']] | "\
25
+ "//bibliography/references[@normative = 'true']")), n, 1)
37
26
  n = section_names(d.at(ns("//sections/terms | "\
38
27
  "//sections/clause[descendant::terms]")), n, 1)
39
28
  n = section_names(d.at(ns("//sections/definitions")), n, 1)
@@ -76,10 +65,8 @@ module IsoDoc::Function
76
65
 
77
66
  def middle_section_asset_names(d)
78
67
  middle_sections = "//clause[title = 'Scope'] | "\
79
- "//references[title = 'Normative References' or title = "\
80
- "'Normative references'] | "\
81
- "//sections/terms | //preface/abstract | //foreword | "\
82
- "//introduction | //preface/clause | //acknowledgements "\
68
+ "//references[@normative = 'true'] | "\
69
+ "//sections/terms | //preface/* | "\
83
70
  "//sections/definitions | //clause[parent::sections]"
84
71
  sequential_asset_names(d.xpath(ns(middle_sections)))
85
72
  end
@@ -120,12 +107,25 @@ module IsoDoc::Function
120
107
  l10n("<b>#{@annex_lbl} #{num}</b><br/>#{obl}")
121
108
  end
122
109
 
110
+ def single_annex_special_section(clause)
111
+ a = clause.xpath(ns("./references | ./terms | ./definitions"))
112
+ a.size == 1 or return nil
113
+ clause.xpath(ns("./clause | ./p | ./table | ./ol | ./ul | ./dl | "\
114
+ "./note | ./admonition | ./figure")).size == 0 or
115
+ return nil
116
+ a[0]
117
+ end
118
+
123
119
  def annex_names(clause, num)
124
120
  @anchors[clause["id"]] = { label: annex_name_lbl(clause, num),
125
121
  type: "clause",
126
122
  xref: "#{@annex_lbl} #{num}", level: 1 }
127
- clause.xpath(ns(SUBCLAUSES)).each_with_index do |c, i|
128
- annex_names1(c, "#{num}.#{i + 1}", 2)
123
+ if a = single_annex_special_section(clause)
124
+ annex_names1(a, "#{num}", 1)
125
+ else
126
+ clause.xpath(ns(SUBCLAUSES)).each_with_index do |c, i|
127
+ annex_names1(c, "#{num}.#{i + 1}", 2)
128
+ end
129
129
  end
130
130
  hierarchical_asset_names(clause, num)
131
131
  end