metanorma-mpfd 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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +17 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +25 -0
  7. data/README.adoc +1 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/rspec +18 -0
  11. data/bin/setup +8 -0
  12. data/lib/asciidoctor/mpfd/biblio.rng +836 -0
  13. data/lib/asciidoctor/mpfd/converter.rb +204 -0
  14. data/lib/asciidoctor/mpfd/isodoc.rng +1041 -0
  15. data/lib/asciidoctor/mpfd/isostandard.rng +1001 -0
  16. data/lib/asciidoctor/mpfd/pdf.js +31 -0
  17. data/lib/asciidoctor/mpfd/rsd.rng +212 -0
  18. data/lib/asciidoctor/mpfd/section.rb +94 -0
  19. data/lib/asciidoctor/mpfd/version.rb +5 -0
  20. data/lib/asciidoctor/mpfd.rb +9 -0
  21. data/lib/isodoc/mpfd/html/header.html +184 -0
  22. data/lib/isodoc/mpfd/html/html_rsd_intro.html +8 -0
  23. data/lib/isodoc/mpfd/html/html_rsd_titlepage.html +58 -0
  24. data/lib/isodoc/mpfd/html/htmlstyle.scss +1094 -0
  25. data/lib/isodoc/mpfd/html/logo.jpg +0 -0
  26. data/lib/isodoc/mpfd/html/logo.svg +1 -0
  27. data/lib/isodoc/mpfd/html/mpfa-logo-no-text@4x.png +0 -0
  28. data/lib/isodoc/mpfd/html/mpfa-logo@4x.png +0 -0
  29. data/lib/isodoc/mpfd/html/rsd.scss +564 -0
  30. data/lib/isodoc/mpfd/html/scripts.html +82 -0
  31. data/lib/isodoc/mpfd/html/word_rsd_intro.html +3 -0
  32. data/lib/isodoc/mpfd/html/word_rsd_titlepage.html +42 -0
  33. data/lib/isodoc/mpfd/html/wordstyle.scss +1096 -0
  34. data/lib/isodoc/mpfd/html_convert.rb +370 -0
  35. data/lib/isodoc/mpfd/i18n-en.yaml +1 -0
  36. data/lib/isodoc/mpfd/metadata.rb +98 -0
  37. data/lib/isodoc/mpfd/pdf_convert.rb +367 -0
  38. data/lib/isodoc/mpfd/word_convert.rb +347 -0
  39. data/lib/metanorma/mpfd/processor.rb +43 -0
  40. data/lib/metanorma/mpfd.rb +7 -0
  41. data/lib/metanorma-mpfd.rb +11 -0
  42. data/metanorma-mpfd.gemspec +46 -0
  43. metadata +326 -0
@@ -0,0 +1,367 @@
1
+ require "isodoc"
2
+ require_relative "metadata"
3
+
4
+ module IsoDoc
5
+ module Mpfd
6
+ # A {Converter} implementation that generates PDF HTML output, and a
7
+ # document schema encapsulation of the document for validation
8
+ class PdfConvert < IsoDoc::PdfConvert
9
+ def rsd_html_path(file)
10
+ File.join(File.dirname(__FILE__), File.join("html", file))
11
+ end
12
+
13
+ def initialize(options)
14
+ super
15
+ @htmlstylesheet = generate_css(rsd_html_path("htmlstyle.scss"), true, default_fonts(options))
16
+ @htmlcoverpage = rsd_html_path("html_rsd_titlepage.html")
17
+ @htmlintropage = rsd_html_path("html_rsd_intro.html")
18
+ @scripts = rsd_html_path("scripts.html")
19
+ system "cp #{rsd_html_path('logo.jpg')} logo.jpg"
20
+ system "cp #{rsd_html_path('mpfa-logo-no-text@4x.png')} mpfa-logo-no-text@4x.png"
21
+ @files_to_delete << "logo.jpg"
22
+ @files_to_delete << "mpfa-logo-no-text@4x.png"
23
+ end
24
+
25
+ def default_fonts(options)
26
+ b = options[:bodyfont] ||
27
+ (options[:script] == "Hans" ? '"SimSun",serif' :
28
+ '"Overpass",sans-serif')
29
+ h = options[:headerfont] ||
30
+ (options[:script] == "Hans" ? '"SimHei",sans-serif' :
31
+ '"Overpass",sans-serif')
32
+ m = options[:monospacefont] || '"Space Mono",monospace'
33
+ "$bodyfont: #{b};\n$headerfont: #{h};\n$monospacefont: #{m};\n"
34
+ end
35
+
36
+ def metadata_init(lang, script, labels)
37
+ @meta = Metadata.new(lang, script, labels)
38
+ end
39
+
40
+ def html_head()
41
+ <<~HEAD.freeze
42
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
43
+
44
+ <!--TOC script import-->
45
+ <script type="text/javascript" src="https://cdn.rawgit.com/jgallen23/toc/0.3.2/dist/toc.min.js"></script>
46
+
47
+ <!--Google fonts-->
48
+ <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i|Space+Mono:400,700" rel="stylesheet">
49
+ <link href="https://fonts.googleapis.com/css?family=Overpass:300,300i,600,900" rel="stylesheet">
50
+ <link href="https://fonts.googleapis.com/css?family=Titillium+Web:400,400i,700,700i" rel="stylesheet">
51
+ <!--Font awesome import for the link icon-->
52
+ <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/solid.css" integrity="sha384-v2Tw72dyUXeU3y4aM2Y0tBJQkGfplr39mxZqlTBDUZAb9BGoC40+rdFCG0m10lXk" crossorigin="anonymous">
53
+ <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/fontawesome.css" integrity="sha384-q3jl8XQu1OpdLgGFvNRnPdj5VIlCvgsDQTQB6owSOHWlAurxul7f+JpUOVdAiJ5P" crossorigin="anonymous">
54
+ <style class="anchorjs"></style>
55
+ HEAD
56
+ end
57
+
58
+ def make_body(xml, docxml)
59
+ body_attr = { lang: "EN-US", link: "blue", vlink: "#954F72", "xml:lang": "EN-US", class: "container" }
60
+ xml.body **body_attr do |body|
61
+ make_body1(body, docxml)
62
+ make_body2(body, docxml)
63
+ make_body3(body, docxml)
64
+ end
65
+ end
66
+
67
+ def html_toc(docxml)
68
+ docxml
69
+ end
70
+
71
+ def annex_name(annex, name, div)
72
+ div.h1 **{ class: "Annex" } do |t|
73
+ t << "#{get_anchors[annex['id']][:label]} "
74
+ t << "<b>#{name.text}</b>"
75
+ end
76
+ end
77
+
78
+ def annex_name_lbl(clause, num)
79
+ obl = l10n("(#{@inform_annex_lbl})")
80
+ obl = l10n("(#{@norm_annex_lbl})") if clause["obligation"] == "normative"
81
+ l10n("<b>#{@annex_lbl} #{num}</b> #{obl}")
82
+ end
83
+
84
+ def pre_parse(node, out)
85
+ out.pre node.text # content.gsub(/</, "&lt;").gsub(/>/, "&gt;")
86
+ end
87
+
88
+ def term_defs_boilerplate(div, source, term, preface)
89
+ if source.empty? && term.nil?
90
+ div << @no_terms_boilerplate
91
+ else
92
+ div << term_defs_boilerplate_cont(source, term)
93
+ end
94
+ end
95
+
96
+ def i18n_init(lang, script)
97
+ super
98
+ @annex_lbl = "Appendix"
99
+ end
100
+
101
+ def error_parse(node, out)
102
+ # catch elements not defined in ISO
103
+ case node.name
104
+ when "pre"
105
+ pre_parse(node, out)
106
+ when "keyword"
107
+ out.span node.text, **{ class: "keyword" }
108
+ else
109
+ super
110
+ end
111
+ end
112
+
113
+ def fileloc(loc)
114
+ File.join(File.dirname(__FILE__), loc)
115
+ end
116
+
117
+ def info(isoxml, out)
118
+ @meta.security isoxml, out
119
+ super
120
+ end
121
+
122
+ def annex_name(annex, name, div)
123
+ div.h1 **{ class: "Annex" } do |t|
124
+ t << "#{get_anchors[annex['id']][:label]} "
125
+ t << "<b>#{name.text}</b>"
126
+ end
127
+ end
128
+
129
+ def annex_name_lbl(clause, num)
130
+ obl = l10n("(#{@inform_annex_lbl})")
131
+ obl = l10n("(#{@norm_annex_lbl})") if clause["obligation"] == "normative"
132
+ l10n("<b>#{@annex_lbl} #{num}</b> #{obl}")
133
+ end
134
+
135
+ def pre_parse(node, out)
136
+ out.pre node.text # content.gsub(/</, "&lt;").gsub(/>/, "&gt;")
137
+ end
138
+
139
+ def term_defs_boilerplate(div, source, term, preface)
140
+ if source.empty? && term.nil?
141
+ div << @no_terms_boilerplate
142
+ else
143
+ div << term_defs_boilerplate_cont(source, term)
144
+ end
145
+ end
146
+
147
+ def i18n_init(lang, script)
148
+ super
149
+ @annex_lbl = "Appendix"
150
+ end
151
+
152
+ def error_parse(node, out)
153
+ # catch elements not defined in ISO
154
+ case node.name
155
+ when "pre"
156
+ pre_parse(node, out)
157
+ when "keyword"
158
+ out.span node.text, **{ class: "keyword" }
159
+ else
160
+ super
161
+ end
162
+ end
163
+
164
+ def fileloc(loc)
165
+ File.join(File.dirname(__FILE__), loc)
166
+ end
167
+
168
+ def i18n_init(lang, script)
169
+ super
170
+ y = if lang == "en"
171
+ YAML.load_file(File.join(File.dirname(__FILE__), "i18n-en.yaml"))
172
+ elsif lang == "zh" && script == "Hans"
173
+ YAML.load_file(File.join(File.dirname(__FILE__),
174
+ "i18n-zh-Hans.yaml"))
175
+ else
176
+ YAML.load_file(File.join(File.dirname(__FILE__), "i18n-zh-Hans.yaml"))
177
+ end
178
+ @labels = @labels.merge(y)
179
+ @clause_lbl = y["clause"]
180
+ end
181
+
182
+ def terms_defs_title(f)
183
+ return f&.at(ns("./title"))&.content
184
+ end
185
+
186
+ TERM_CLAUSE = "//preface/terms | "\
187
+ "//preface/clause[descendant::terms]".freeze
188
+
189
+
190
+ def terms_defs(isoxml, out, num)
191
+ f = isoxml.at(ns(TERM_CLAUSE)) or return num
192
+ out.div **attr_code(id: f["id"]) do |div|
193
+ clause_name(nil, terms_defs_title(f), div, nil)
194
+ f.elements.each do |e|
195
+ parse(e, div) unless %w{title source}.include? e.name
196
+ end
197
+ end
198
+ num
199
+ end
200
+
201
+ FRONT_CLAUSE = "//*[parent::preface]".freeze
202
+ #FRONT_CLAUSE = "//clause[parent::preface] | //terms[parent::preface]".freeze
203
+
204
+ def preface(isoxml, out)
205
+ isoxml.xpath(ns(FRONT_CLAUSE)).each do |c|
206
+ if c.name == "terms" then terms_defs isoxml, out, 0
207
+ else
208
+ out.div **attr_code(id: c["id"]) do |s|
209
+ clause_name(get_anchors[c['id']][:label],
210
+ c&.at(ns("./title"))&.content, s, nil)
211
+ c.elements.reject { |c1| c1.name == "title" }.each do |c1|
212
+ parse(c1, s)
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ def make_body3(body, docxml)
220
+ body.div **{ class: "main-section" } do |div3|
221
+ preface docxml, div3
222
+ middle docxml, div3
223
+ footnotes div3
224
+ comments div3
225
+ end
226
+ end
227
+
228
+ def middle(isoxml, out)
229
+ middle_title(out)
230
+ clause isoxml, out
231
+ annex isoxml, out
232
+ bibliography isoxml, out
233
+ end
234
+
235
+ def termdef_parse(node, out)
236
+ set_termdomain("")
237
+ node.children.each { |n| parse(n, out) }
238
+ end
239
+
240
+ def initial_anchor_names(d)
241
+ #preface_names(d.at(ns("//foreword")))
242
+ #preface_names(d.at(ns("//introduction")))
243
+ #preface_names(d.at(ns("//preface/terms | "\
244
+ #"//preface/clause[descendant::terms]")))
245
+ d.xpath(ns(FRONT_CLAUSE)).each do |c|
246
+ preface_names(c)
247
+ sequential_asset_names(c)
248
+ end
249
+ middle_section_asset_names(d)
250
+ clause_names(d, 0)
251
+ termnote_anchor_names(d)
252
+ termexample_anchor_names(d)
253
+ end
254
+
255
+ def annex_name_lbl(clause, num)
256
+ l10n("<b>#{@annex_lbl} #{num}</b>")
257
+ end
258
+
259
+ def clause_names(docxml, sect_num)
260
+ q = "//clause[parent::sections]"
261
+ @topnum = nil
262
+ lvl = 0
263
+ docxml.xpath(ns(q)).each do |c|
264
+ container_names(c, 0)
265
+ sect_num, lvl = sect_names(c, nil, sect_num, 0, lvl)
266
+ end
267
+ end
268
+
269
+ def container_names(clause, lvl)
270
+ if clause["container"]
271
+ @anchors[clause["id"]] =
272
+ { label: nil, xref: clause.at(ns("./title"))&.text, level: lvl+1 }
273
+ end
274
+ clause.xpath(ns("./clause | ./term | ./terms | "\
275
+ "./definitions")).each do |c|
276
+ container_names(c, clause["container"] ? lvl+1 : lvl)
277
+ end
278
+ end
279
+
280
+ def sect_names(clause, num, i, lvl, prev_lvl)
281
+ return i if clause.nil?
282
+ curr = i
283
+ if clause["container"]
284
+ retlvl = lvl+1
285
+ else
286
+ retlvl = lvl
287
+ i+=1
288
+ curr = i
289
+ name = num.nil? ? i.to_s : "#{num}.#{i}"
290
+ @anchors[clause["id"]] = { label: name, xref: l10n("#{@clause_lbl} #{name}"), level: lvl+1 }
291
+ end
292
+ prev = lvl
293
+ j = 0
294
+ clause.xpath(ns("./clause | ./term | ./terms | "\
295
+ "./definitions")).each do |c|
296
+ if clause["container"]
297
+ i, lvl = sect_names(c, num, i, lvl, lvl)
298
+ else
299
+ j, prev = sect_names(c, name, j, lvl+1, prev)
300
+ end
301
+ end
302
+ i = j if j >0
303
+ i = curr if lvl < prev
304
+ [i, prev]
305
+ end
306
+
307
+ def annex_naming(c, num, lvl, i)
308
+ if c["guidance"] then annex_names1(c, "#{num}E", lvl + 1)
309
+ else
310
+ i+= 1
311
+ annex_names1(c, "#{num}.#{i}", lvl + 1)
312
+ end
313
+ i
314
+ end
315
+
316
+ def annex_names(clause, num)
317
+ @anchors[clause["id"]] = { label: annex_name_lbl(clause, num),
318
+ xref: "#{@annex_lbl} #{num}", level: 1 }
319
+ i = 0
320
+ clause.xpath(ns("./clause")).each do |c|
321
+ i = annex_naming(c, num, 1, i)
322
+ end
323
+ hierarchical_asset_names(clause, num)
324
+ end
325
+
326
+ def annex_names1(clause, num, level)
327
+ @anchors[clause["id"]] = { label: num, xref: "#{@annex_lbl} #{num}",
328
+ level: level }
329
+ i = 0
330
+ clause.xpath(ns("./clause")).each do |c|
331
+ i = annex_naming(c, num, level, i)
332
+ end
333
+ end
334
+
335
+ def clause(isoxml, out)
336
+ isoxml.xpath(ns(MIDDLE_CLAUSE)).each do |c|
337
+ out.div **attr_code(id: c["id"]) do |s|
338
+ clause_name(get_anchors[c['id']][:label],
339
+ c&.at(ns("./title"))&.content, s, class: c["container"] ? "containerhdr" : nil )
340
+ c.elements.reject { |c1| c1.name == "title" }.each do |c1|
341
+ parse(c1, s)
342
+ end
343
+ end
344
+ end
345
+ end
346
+
347
+ def clause_parse_title(node, div, c1, out)
348
+ if node["inline-header"] == "true"
349
+ inline_header_title(out, node, c1)
350
+ else
351
+ attrs = { class: node["container"] ? "containerhdr" : nil }
352
+ div.send "h#{get_anchors[node['id']][:level]}", **attr_code(attrs) do |h|
353
+ lbl = get_anchors[node['id']][:label]
354
+ h << "#{lbl}. " if lbl
355
+ c1&.children&.each { |c2| parse(c2, h) }
356
+ end
357
+ end
358
+ end
359
+
360
+ def ol_depth(node)
361
+ ol_style(node["type"])
362
+ end
363
+
364
+ end
365
+ end
366
+ end
367
+