metanorma-ogc 0.0.2

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 (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.hound.yml +3 -0
  4. data/.rubocop.yml +10 -0
  5. data/.travis.yml +16 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +25 -0
  9. data/README.adoc +323 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/rspec +17 -0
  13. data/bin/setup +8 -0
  14. data/lib/asciidoctor/ogc.rb +7 -0
  15. data/lib/asciidoctor/ogc/biblio.rng +890 -0
  16. data/lib/asciidoctor/ogc/converter.rb +253 -0
  17. data/lib/asciidoctor/ogc/front.rb +163 -0
  18. data/lib/asciidoctor/ogc/isodoc.rng +1091 -0
  19. data/lib/asciidoctor/ogc/isostandard.rng +1068 -0
  20. data/lib/asciidoctor/ogc/ogc.rng +210 -0
  21. data/lib/isodoc/ogc.rb +10 -0
  22. data/lib/isodoc/ogc/html/header.html +181 -0
  23. data/lib/isodoc/ogc/html/html_ogc_intro.html +85 -0
  24. data/lib/isodoc/ogc/html/html_ogc_titlepage.html +172 -0
  25. data/lib/isodoc/ogc/html/htmlstyle.scss +1054 -0
  26. data/lib/isodoc/ogc/html/ogc.scss +644 -0
  27. data/lib/isodoc/ogc/html/scripts.html +82 -0
  28. data/lib/isodoc/ogc/html/scripts.pdf.html +70 -0
  29. data/lib/isodoc/ogc/html/word_ogc_intro.html +92 -0
  30. data/lib/isodoc/ogc/html/word_ogc_titlepage.html +194 -0
  31. data/lib/isodoc/ogc/html/wordstyle.scss +1104 -0
  32. data/lib/isodoc/ogc/html_convert.rb +355 -0
  33. data/lib/isodoc/ogc/i18n-en.yaml +1 -0
  34. data/lib/isodoc/ogc/metadata.rb +102 -0
  35. data/lib/isodoc/ogc/pdf_convert.rb +357 -0
  36. data/lib/isodoc/ogc/word_convert.rb +345 -0
  37. data/lib/metanorma-ogc.rb +8 -0
  38. data/lib/metanorma/ogc.rb +11 -0
  39. data/lib/metanorma/ogc/processor.rb +43 -0
  40. data/lib/metanorma/ogc/version.rb +5 -0
  41. data/metanorma-ogc.gemspec +45 -0
  42. metadata +338 -0
@@ -0,0 +1,357 @@
1
+ require "isodoc"
2
+ require_relative "metadata"
3
+ require "fileutils"
4
+
5
+ module IsoDoc
6
+ module Ogc
7
+ # A {Converter} implementation that generates PDF HTML output, and a
8
+ # document schema encapsulation of the document for validation
9
+ class PdfConvert < IsoDoc::PdfConvert
10
+ def initialize(options)
11
+ @libdir = File.dirname(__FILE__)
12
+ super
13
+ #FileUtils.cp html_doc_path('logo.jpg'), "logo.jpg"
14
+ #@files_to_delete << "logo.jpg"
15
+ end
16
+
17
+ def default_fonts(options)
18
+ {
19
+ bodyfont: (options[:script] == "Hans" ? '"SimSun",serif' : '"Overpass",sans-serif'),
20
+ headerfont: (options[:script] == "Hans" ? '"SimHei",sans-serif' : '"Overpass",sans-serif'),
21
+ monospacefont: '"Space Mono",monospace'
22
+ }
23
+ end
24
+
25
+ def default_file_locations(_options)
26
+ {
27
+ htmlstylesheet: html_doc_path("htmlstyle.scss"),
28
+ htmlcoverpage: html_doc_path("html_ogc_titlepage.html"),
29
+ htmlintropage: html_doc_path("html_ogc_intro.html"),
30
+ scripts_pdf: html_doc_path("scripts.pdf.html"),
31
+ }
32
+ end
33
+
34
+ def metadata_init(lang, script, labels)
35
+ @meta = Metadata.new(lang, script, labels)
36
+ end
37
+
38
+ def html_head()
39
+ <<~HEAD.freeze
40
+ <title>{{ doctitle }}</title>
41
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
42
+
43
+ <!--TOC script import-->
44
+ <script type="text/javascript" src="https://cdn.rawgit.com/jgallen23/toc/0.3.2/dist/toc.min.js"></script>
45
+
46
+ <!--Google fonts-->
47
+ <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i|Space+Mono:400,700" rel="stylesheet">
48
+ <link href="https://fonts.googleapis.com/css?family=Overpass:300,300i,600,900" rel="stylesheet">
49
+ <!--Font awesome import for the link icon-->
50
+ <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/solid.css" integrity="sha384-rdyFrfAIC05c5ph7BKz3l5NG5yEottvO/DQ0dCrwD8gzeQDjYBHNr1ucUpQuljos" crossorigin="anonymous">
51
+ <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/fontawesome.css" integrity="sha384-u5J7JghGz0qUrmEsWzBQkfvc8nK3fUT7DCaQzNQ+q4oEXhGSx+P2OqjWsfIRB8QT" crossorigin="anonymous">
52
+ <style class="anchorjs"></style>
53
+ HEAD
54
+ end
55
+
56
+ def make_body(xml, docxml)
57
+ body_attr = { lang: "EN-US", link: "blue", vlink: "#954F72", "xml:lang": "EN-US", class: "container" }
58
+ xml.body **body_attr do |body|
59
+ make_body1(body, docxml)
60
+ make_body2(body, docxml)
61
+ make_body3(body, docxml)
62
+ end
63
+ end
64
+
65
+ def html_toc(docxml)
66
+ docxml
67
+ end
68
+
69
+ def annex_name(annex, name, div)
70
+ div.h1 **{ class: "Annex" } do |t|
71
+ t << "#{get_anchors[annex['id']][:label]} "
72
+ t.br
73
+ t.b do |b|
74
+ name&.children&.each { |c2| parse(c2, b) }
75
+ end
76
+ end
77
+ end
78
+
79
+ def term_defs_boilerplate(div, source, term, preface)
80
+ if source.empty? && term.nil?
81
+ div << @no_terms_boilerplate
82
+ else
83
+ div << term_defs_boilerplate_cont(source, term)
84
+ end
85
+ end
86
+
87
+ def fileloc(loc)
88
+ File.join(File.dirname(__FILE__), loc)
89
+ end
90
+
91
+ def cleanup(docxml)
92
+ super
93
+ term_cleanup(docxml)
94
+ end
95
+
96
+ def term_cleanup(docxml)
97
+ docxml.xpath("//p[@class = 'Terms']").each do |d|
98
+ h2 = d.at("./preceding-sibling::*[@class = 'TermNum'][1]")
99
+ h2.add_child("&nbsp;")
100
+ h2.add_child(d.remove)
101
+ end
102
+ docxml
103
+ end
104
+
105
+ def info(isoxml, out)
106
+ @meta.keywords isoxml, out
107
+ super
108
+ end
109
+
110
+ def load_yaml(lang, script)
111
+ y = if @i18nyaml then YAML.load_file(@i18nyaml)
112
+ elsif lang == "en"
113
+ YAML.load_file(File.join(File.dirname(__FILE__), "i18n-en.yaml"))
114
+ else
115
+ YAML.load_file(File.join(File.dirname(__FILE__), "i18n-en.yaml"))
116
+ end
117
+ super.merge(y)
118
+ end
119
+
120
+
121
+ def keywords(_docxml, out)
122
+ kw = @meta.get[:keywords]
123
+ kw.empty? and return
124
+ @prefacenum += 1
125
+ out.div **{ class: "Section3" } do |div|
126
+ clause_name(RomanNumerals.to_roman(@prefacenum).downcase, "Keywords", div, class: "IntroTitle")
127
+ div.p "The following are keywords to be used by search engines and document catalogues."
128
+ div.p kw.join(", ")
129
+ end
130
+ end
131
+
132
+ SUBMITTINGORGS =
133
+ "//bibdata/contributor[role/@type = 'author']/organization/name".freeze
134
+
135
+ def submittingorgs(docxml, out)
136
+ orgs = []
137
+ docxml.xpath(ns(SUBMITTINGORGS)).each { |org| orgs << org.text }
138
+ return if orgs.empty?
139
+ @prefacenum += 1
140
+ out.div **{ class: "Section3" } do |div|
141
+ clause_name(RomanNumerals.to_roman(@prefacenum).downcase, "Submitting Organizations", div, class: "IntroTitle")
142
+ div.p "The following organizations submitted this Document to the Open Geospatial Consortium (OGC):"
143
+ div.ul do |ul|
144
+ orgs.each do |org|
145
+ ul.li org
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ def submitters(docxml, out)
152
+ f = docxml.at(ns("//submitters")) || return
153
+ out.div **{ class: "Section3" } do |div|
154
+ clause_name(get_anchors[f['id']][:label], "Submitters", div, class: "IntroTitle")
155
+ f.elements.each { |e| parse(e, div) unless e.name == "title" }
156
+ end
157
+ end
158
+
159
+ def make_body3(body, docxml)
160
+ body.div **{ class: "main-section" } do |div3|
161
+ @prefacenum = 0
162
+ abstract docxml, div3
163
+ keywords docxml, div3
164
+ foreword docxml, div3
165
+ submittingorgs docxml, div3
166
+ submitters docxml, div3
167
+ middle docxml, div3
168
+ footnotes div3
169
+ comments div3
170
+ end
171
+ end
172
+
173
+ def preface_names(clause)
174
+ return if clause.nil?
175
+ @prefacenum += 1
176
+ @anchors[clause["id"]] =
177
+ { label: RomanNumerals.to_roman(@prefacenum).downcase,
178
+ level: 1, xref: preface_clause_name(clause), type: "clause" }
179
+ clause.xpath(ns("./clause | ./terms | ./term | ./definitions")).each_with_index do |c, i|
180
+ section_names1(c, "#{@prefacenum}.#{i + 1}", 2)
181
+ end
182
+ end
183
+
184
+ def abstract(isoxml, out)
185
+ f = isoxml.at(ns("//preface/abstract")) || return
186
+ @prefacenum += 1
187
+ page_break(out)
188
+ out.div **attr_code(id: f["id"]) do |s|
189
+ clause_name(get_anchors[f["id"]][:label], @abstract_lbl, s, class: "AbstractTitle")
190
+ f.elements.each { |e| parse(e, s) unless e.name == "title" }
191
+ end
192
+ end
193
+
194
+ def foreword(isoxml, out)
195
+ f = isoxml.at(ns("//foreword")) || return
196
+ @prefacenum += 1
197
+ page_break(out)
198
+ out.div **attr_code(id: f["id"]) do |s|
199
+ clause_name(get_anchors[f["id"]][:label], @foreword_lbl, s, class: "ForewordTitle")
200
+ f.elements.each { |e| parse(e, s) unless e.name == "title" }
201
+ end
202
+ end
203
+
204
+ def example_parse(node, out)
205
+ name = node.at(ns("./name"))
206
+ sourcecode_name_parse(node, out, name) if name
207
+ out.table **example_table_attr(node) do |t|
208
+ t.tr do |tr|
209
+ tr.td **EXAMPLE_TBL_ATTR do |td|
210
+ td << example_label(node)
211
+ end
212
+ tr.td **{ valign: "top", class: "example" } do |td|
213
+ node.children.each { |n| parse(n, td) unless n.name == "name" }
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ def error_parse(node, out)
220
+ case node.name
221
+ when "recommendation" then recommendation_parse(node, out)
222
+ when "requirement" then requirement_parse(node, out)
223
+ when "permission" then permission_parse(node, out)
224
+ else
225
+ super
226
+ end
227
+ end
228
+
229
+ def anchor_names(docxml)
230
+ super
231
+ recommendation_anchor_names(docxml)
232
+ requirement_anchor_names(docxml)
233
+ permission_anchor_names(docxml)
234
+ end
235
+
236
+ def recommendation_anchor_names(docxml)
237
+ docxml.xpath(ns("//recommendation")).each_with_index do |x, i|
238
+ @anchors[x["id"]] = anchor_struct(i+1, nil, "Recommendation", "recommendation")
239
+ end
240
+ end
241
+
242
+ def requirement_anchor_names(docxml)
243
+ docxml.xpath(ns("//requirement")).each_with_index do |x, i|
244
+ @anchors[x["id"]] = anchor_struct(i+1, nil, "Requirement", "requirement")
245
+ end
246
+ end
247
+
248
+ def permission_anchor_names(docxml)
249
+ docxml.xpath(ns("//permission")).each_with_index do |x, i|
250
+ @anchors[x["id"]] = anchor_struct(i+1, nil, "Permission", "permission")
251
+ end
252
+ end
253
+
254
+ def recommend_table_attr(node)
255
+ attr_code(id: node["id"], class: "recommend",
256
+ cellspacing: 0, cellpadding: 0,
257
+ style: "border-collapse:collapse" )
258
+ end
259
+
260
+ REQ_TBL_ATTR =
261
+ { valign: "top", class: "example_label",
262
+ style: "width:100.0pt;padding:0 0 0 1em;margin-left:0pt" }.freeze
263
+
264
+ def recommend_name_parse(node, div)
265
+ name = node&.at(ns("./name"))&.text or return
266
+ div.p do |p|
267
+ p.b name
268
+ end
269
+ end
270
+
271
+ def recommendation_parse(node, out)
272
+ out.table **recommend_table_attr(node) do |t|
273
+ t.tr do |tr|
274
+ tr.td **REQ_TBL_ATTR do |td|
275
+ td << recommendation_label(node)
276
+ end
277
+ tr.td **{ valign: "top", class: "recommend" } do |td|
278
+ recommend_name_parse(node, td)
279
+ node.children.each { |n| parse(n, td) unless n.name == "name" }
280
+ end
281
+ end
282
+ end
283
+ end
284
+
285
+ def recommendation_label(node)
286
+ n = get_anchors[node["id"]]
287
+ return "Recommendation" if n.nil? || n[:label].empty?
288
+ l10n("#{"Recommendation"} #{n[:label]}")
289
+ end
290
+
291
+ def requirement_parse(node, out)
292
+ out.table **recommend_table_attr(node) do |t|
293
+ t.tr do |tr|
294
+ tr.td **REQ_TBL_ATTR do |td|
295
+ td << requirement_label(node)
296
+ end
297
+ tr.td **{ valign: "top", class: "recommend" } do |td|
298
+ recommend_name_parse(node, td)
299
+ node.children.each { |n| parse(n, td) unless n.name == "name" }
300
+ end
301
+ end
302
+ end
303
+ end
304
+
305
+ def requirement_label(node)
306
+ n = get_anchors[node["id"]]
307
+ return "Requirement" if n.nil? || n[:label].empty?
308
+ l10n("#{"Requirement"} #{n[:label]}")
309
+ end
310
+
311
+ def permission_parse(node, out)
312
+ out.table **recommend_table_attr(node) do |t|
313
+ t.tr do |tr|
314
+ tr.td **REQ_TBL_ATTR do |td|
315
+ td << permission_label(node)
316
+ end
317
+ tr.td **{ valign: "top", class: "recommend" } do |td|
318
+ recommend_name_parse(node, td)
319
+ node.children.each { |n| parse(n, td) unless n.name == "name" }
320
+ end
321
+ end
322
+ end
323
+ end
324
+
325
+ def permission_label(node)
326
+ n = get_anchors[node["id"]]
327
+ return "Permission" if n.nil? || n[:label].empty?
328
+ l10n("#{"Permission"} #{n[:label]}")
329
+ end
330
+
331
+
332
+ def initial_anchor_names(d)
333
+ @prefacenum = 0
334
+ preface_names(d.at(ns("//preface/abstract")))
335
+ @prefacenum += 1 if d.at(ns("//keyword"))
336
+ preface_names(d.at(ns("//foreword")))
337
+ #preface_names(d.at(ns("//introduction")))
338
+ @prefacenum += 1 if d.at(ns(SUBMITTINGORGS))
339
+ preface_names(d.at(ns("//submitters")))
340
+ sequential_asset_names(d.xpath(ns("//preface/abstract | //foreword | //introduction | //submitters")))
341
+ n = section_names(d.at(ns("//clause[title = 'Scope']")), 0, 1)
342
+ n = section_names(d.at(ns("//clause[title = 'Conformance']")), n, 1)
343
+ n = section_names(d.at(ns(
344
+ "//references[title = 'Normative References' or title = 'Normative references']")), n, 1)
345
+ n = section_names(d.at(ns("//sections/terms | "\
346
+ "//sections/clause[descendant::terms]")), n, 1)
347
+ n = section_names(d.at(ns("//sections/definitions")), n, 1)
348
+ middle_section_asset_names(d)
349
+ clause_names(d, n)
350
+ termnote_anchor_names(d)
351
+ termexample_anchor_names(d)
352
+ end
353
+
354
+ end
355
+ end
356
+ end
357
+
@@ -0,0 +1,345 @@
1
+ require "isodoc"
2
+ require_relative "metadata"
3
+ require "fileutils"
4
+
5
+ module IsoDoc
6
+ module Ogc
7
+ # A {Converter} implementation that generates Word output, and a document
8
+ # schema encapsulation of the document for validation
9
+
10
+ class WordConvert < IsoDoc::WordConvert
11
+ def initialize(options)
12
+ @libdir = File.dirname(__FILE__)
13
+ super
14
+ #FileUtils.cp html_doc_path('logo.jpg'), "logo.jpg"
15
+ end
16
+
17
+ def default_fonts(options)
18
+ {
19
+ bodyfont: (options[:script] == "Hans" ? '"SimSun",serif' : '"Times New Roman",serif'),
20
+ headerfont: (options[:script] == "Hans" ? '"SimHei",sans-serif' : '"Times New Roman",serif'),
21
+ monospacefont: '"Courier New",monospace'
22
+ }
23
+ end
24
+
25
+ def default_file_locations(options)
26
+ {
27
+ wordstylesheet: html_doc_path("wordstyle.scss"),
28
+ standardstylesheet: html_doc_path("ogc.scss"),
29
+ header: html_doc_path("header.html"),
30
+ wordcoverpage: html_doc_path("word_ogc_titlepage.html"),
31
+ wordintropage: html_doc_path("word_ogc_intro.html"),
32
+ ulstyle: "l3",
33
+ olstyle: "l2",
34
+ }
35
+ end
36
+
37
+
38
+ def metadata_init(lang, script, labels)
39
+ @meta = Metadata.new(lang, script, labels)
40
+ end
41
+
42
+ def make_body(xml, docxml)
43
+ body_attr = { lang: "EN-US", link: "blue", vlink: "#954F72" }
44
+ xml.body **body_attr do |body|
45
+ make_body1(body, docxml)
46
+ make_body2(body, docxml)
47
+ make_body3(body, docxml)
48
+ end
49
+ end
50
+
51
+ =begin
52
+ def make_body2(body, docxml)
53
+ body.div **{ class: "WordSection2" } do |div2|
54
+ info docxml, div2
55
+ div2.p { |p| p << "&nbsp;" } # placeholder
56
+ end
57
+ section_break(body)
58
+ end
59
+ =end
60
+
61
+ def annex_name(annex, name, div)
62
+ div.h1 **{ class: "Annex" } do |t|
63
+ t << "#{get_anchors[annex['id']][:label]} "
64
+ t.br
65
+ t.b do |b|
66
+ name&.children&.each { |c2| parse(c2, b) }
67
+ end
68
+ end
69
+ end
70
+
71
+ def term_defs_boilerplate(div, source, term, preface)
72
+ if source.empty? && term.nil?
73
+ div << @no_terms_boilerplate
74
+ else
75
+ div << term_defs_boilerplate_cont(source, term)
76
+ end
77
+ end
78
+
79
+ def fileloc(loc)
80
+ File.join(File.dirname(__FILE__), loc)
81
+ end
82
+
83
+ def cleanup(docxml)
84
+ super
85
+ term_cleanup(docxml)
86
+ end
87
+
88
+ def term_cleanup(docxml)
89
+ docxml.xpath("//p[@class = 'Terms']").each do |d|
90
+ h2 = d.at("./preceding-sibling::*[@class = 'TermNum'][1]")
91
+ h2.add_child("&nbsp;")
92
+ h2.add_child(d.remove)
93
+ end
94
+ docxml
95
+ end
96
+
97
+ def info(isoxml, out)
98
+ @meta.keywords isoxml, out
99
+ super
100
+ end
101
+
102
+ def load_yaml(lang, script)
103
+ y = if @i18nyaml then YAML.load_file(@i18nyaml)
104
+ elsif lang == "en"
105
+ YAML.load_file(File.join(File.dirname(__FILE__), "i18n-en.yaml"))
106
+ else
107
+ YAML.load_file(File.join(File.dirname(__FILE__), "i18n-en.yaml"))
108
+ end
109
+ super.merge(y)
110
+ end
111
+
112
+ def keywords(_docxml, out)
113
+ kw = @meta.get[:keywords]
114
+ kw.empty? and return
115
+ @prefacenum += 1
116
+ out.div **{ class: "Section3" } do |div|
117
+ clause_name(RomanNumerals.to_roman(@prefacenum).downcase, "Keywords", div, class: "IntroTitle")
118
+ div.p "The following are keywords to be used by search engines and document catalogues."
119
+ div.p kw.join(", ")
120
+ end
121
+ end
122
+
123
+ SUBMITTINGORGS =
124
+ "//bibdata/contributor[role/@type = 'author']/organization/name".freeze
125
+
126
+ def submittingorgs(docxml, out)
127
+ orgs = []
128
+ docxml.xpath(ns(SUBMITTINGORGS)).each { |org| orgs << org.text }
129
+ return if orgs.empty?
130
+ @prefacenum += 1
131
+ out.div **{ class: "Section3" } do |div|
132
+ clause_name(RomanNumerals.to_roman(@prefacenum).downcase, "Submitting Organizations", div, class: "IntroTitle")
133
+ div.p "The following organizations submitted this Document to the Open Geospatial Consortium (OGC):"
134
+ div.ul do |ul|
135
+ orgs.each do |org|
136
+ ul.li org
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ def submitters(docxml, out)
143
+ f = docxml.at(ns("//submitters")) || return
144
+ out.div **{ class: "Section3" } do |div|
145
+ clause_name(get_anchors[f['id']][:label], "Submitters", div, class: "IntroTitle")
146
+ f.elements.each { |e| parse(e, div) unless e.name == "title" }
147
+ end
148
+ end
149
+
150
+ def make_body2(body, docxml)
151
+ body.div **{ class: "WordSection2" } do |div2|
152
+ @prefacenum = 0
153
+ info docxml, div2
154
+ abstract docxml, div2
155
+ keywords docxml, div2
156
+ foreword docxml, div2
157
+ submittingorgs docxml, div2
158
+ submitters docxml, div2
159
+ div2.p { |p| p << "&nbsp;" } # placeholder
160
+ end
161
+ section_break(body)
162
+ end
163
+
164
+ def preface_names(clause)
165
+ return if clause.nil?
166
+ @prefacenum += 1
167
+ @anchors[clause["id"]] =
168
+ { label: RomanNumerals.to_roman(@prefacenum).downcase,
169
+ level: 1, xref: preface_clause_name(clause), type: "clause" }
170
+ clause.xpath(ns("./clause | ./terms | ./term | ./definitions")).each_with_index do |c, i|
171
+ section_names1(c, "#{@prefacenum}.#{i + 1}", 2)
172
+ end
173
+ end
174
+
175
+ def abstract(isoxml, out)
176
+ f = isoxml.at(ns("//preface/abstract")) || return
177
+ @prefacenum += 1
178
+ page_break(out)
179
+ out.div **attr_code(id: f["id"]) do |s|
180
+ clause_name(get_anchors[f["id"]][:label], @abstract_lbl, s, class: "AbstractTitle")
181
+ f.elements.each { |e| parse(e, s) unless e.name == "title" }
182
+ end
183
+ end
184
+
185
+ def foreword(isoxml, out)
186
+ f = isoxml.at(ns("//foreword")) || return
187
+ @prefacenum += 1
188
+ page_break(out)
189
+ out.div **attr_code(id: f["id"]) do |s|
190
+ clause_name(get_anchors[f["id"]][:label], @foreword_lbl, s, class: "ForewordTitle")
191
+ f.elements.each { |e| parse(e, s) unless e.name == "title" }
192
+ end
193
+ end
194
+
195
+ def example_parse(node, out)
196
+ name = node.at(ns("./name"))
197
+ sourcecode_name_parse(node, out, name) if name
198
+ out.table **example_table_attr(node) do |t|
199
+ t.tr do |tr|
200
+ tr.td **EXAMPLE_TBL_ATTR do |td|
201
+ td << example_label(node)
202
+ end
203
+ tr.td **{ valign: "top", class: "example" } do |td|
204
+ node.children.each { |n| parse(n, td) unless n.name == "name" }
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ def error_parse(node, out)
211
+ case node.name
212
+ when "recommendation" then recommendation_parse(node, out)
213
+ when "requirement" then requirement_parse(node, out)
214
+ when "permission" then permission_parse(node, out)
215
+ else
216
+ super
217
+ end
218
+ end
219
+
220
+ def anchor_names(docxml)
221
+ super
222
+ recommendation_anchor_names(docxml)
223
+ requirement_anchor_names(docxml)
224
+ permission_anchor_names(docxml)
225
+ end
226
+
227
+ def recommendation_anchor_names(docxml)
228
+ docxml.xpath(ns("//recommendation")).each_with_index do |x, i|
229
+ @anchors[x["id"]] = anchor_struct(i+1, nil, "Recommendation", "recommendation")
230
+ end
231
+ end
232
+
233
+ def requirement_anchor_names(docxml)
234
+ docxml.xpath(ns("//requirement")).each_with_index do |x, i|
235
+ @anchors[x["id"]] = anchor_struct(i+1, nil, "Requirement", "requirement")
236
+ end
237
+ end
238
+
239
+ def permission_anchor_names(docxml)
240
+ docxml.xpath(ns("//permission")).each_with_index do |x, i|
241
+ @anchors[x["id"]] = anchor_struct(i+1, nil, "Permission", "permission")
242
+ end
243
+ end
244
+
245
+ def recommend_table_attr(node)
246
+ attr_code(id: node["id"], class: "recommend",
247
+ cellspacing: 0, cellpadding: 0,
248
+ style: "border-collapse:collapse" )
249
+ end
250
+
251
+ REQ_TBL_ATTR =
252
+ { valign: "top", class: "example_label",
253
+ style: "width:100.0pt;padding:0 0 0 1em;margin-left:0pt" }.freeze
254
+
255
+ def recommend_name_parse(node, div)
256
+ name = node&.at(ns("./name"))&.text or return
257
+ div.p do |p|
258
+ p.b name
259
+ end
260
+ end
261
+
262
+ def recommendation_parse(node, out)
263
+ out.table **recommend_table_attr(node) do |t|
264
+ t.tr do |tr|
265
+ tr.td **REQ_TBL_ATTR do |td|
266
+ td << recommendation_label(node)
267
+ end
268
+ tr.td **{ valign: "top", class: "recommend" } do |td|
269
+ recommend_name_parse(node, td)
270
+ node.children.each { |n| parse(n, td) unless n.name == "name" }
271
+ end
272
+ end
273
+ end
274
+ end
275
+
276
+ def recommendation_label(node)
277
+ n = get_anchors[node["id"]]
278
+ return "Recommendation" if n.nil? || n[:label].empty?
279
+ l10n("#{"Recommendation"} #{n[:label]}")
280
+ end
281
+
282
+ def requirement_parse(node, out)
283
+ out.table **recommend_table_attr(node) do |t|
284
+ t.tr do |tr|
285
+ tr.td **REQ_TBL_ATTR do |td|
286
+ td << requirement_label(node)
287
+ end
288
+ tr.td **{ valign: "top", class: "recommend" } do |td|
289
+ recommend_name_parse(node, td)
290
+ node.children.each { |n| parse(n, td) unless n.name == "name" }
291
+ end
292
+ end
293
+ end
294
+ end
295
+
296
+ def requirement_label(node)
297
+ n = get_anchors[node["id"]]
298
+ return "Requirement" if n.nil? || n[:label].empty?
299
+ l10n("#{"Requirement"} #{n[:label]}")
300
+ end
301
+
302
+ def permission_parse(node, out)
303
+ out.table **recommend_table_attr(node) do |t|
304
+ t.tr do |tr|
305
+ tr.td **REQ_TBL_ATTR do |td|
306
+ td << permission_label(node)
307
+ end
308
+ tr.td **{ valign: "top", class: "recommend" } do |td|
309
+ recommend_name_parse(node, td)
310
+ node.children.each { |n| parse(n, td) unless n.name == "name" }
311
+ end
312
+ end
313
+ end
314
+ end
315
+
316
+ def permission_label(node)
317
+ n = get_anchors[node["id"]]
318
+ return "Permission" if n.nil? || n[:label].empty?
319
+ l10n("#{"Permission"} #{n[:label]}")
320
+ end
321
+
322
+ def initial_anchor_names(d)
323
+ @prefacenum = 0
324
+ preface_names(d.at(ns("//preface/abstract")))
325
+ @prefacenum += 1 if d.at(ns("//keyword"))
326
+ preface_names(d.at(ns("//foreword")))
327
+ #preface_names(d.at(ns("//introduction")))
328
+ @prefacenum += 1 if d.at(ns(SUBMITTINGORGS))
329
+ preface_names(d.at(ns("//submitters")))
330
+ sequential_asset_names(d.xpath(ns("//preface/abstract | //foreword | //introduction | //submitters")))
331
+ n = section_names(d.at(ns("//clause[title = 'Scope']")), 0, 1)
332
+ n = section_names(d.at(ns("//clause[title = 'Conformance']")), n, 1)
333
+ n = section_names(d.at(ns(
334
+ "//references[title = 'Normative References' or title = 'Normative references']")), n, 1)
335
+ n = section_names(d.at(ns("//sections/terms | "\
336
+ "//sections/clause[descendant::terms]")), n, 1)
337
+ n = section_names(d.at(ns("//sections/definitions")), n, 1)
338
+ middle_section_asset_names(d)
339
+ clause_names(d, n)
340
+ termnote_anchor_names(d)
341
+ termexample_anchor_names(d)
342
+ end
343
+ end
344
+ end
345
+ end