metanorma 1.2.6 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -45,6 +45,7 @@ module Metanorma
45
45
  mnf.xpath("xmlns:docref").map do |dr|
46
46
  h = { "identifier" => dr.at("identifier").text }
47
47
  h["fileref"] = dr[:fileref] if dr[:fileref]
48
+ h["attachment"] = dr[:attachment] if dr[:attachment]
48
49
  h
49
50
  end
50
51
  end
@@ -62,12 +63,13 @@ module Metanorma
62
63
  docs = @docref.each_with_object({}) do |dr, m|
63
64
  next m unless dr["fileref"]
64
65
 
65
- m[dr["identifier"]] = Document.parse_file File.join(dir, dr["fileref"])
66
+ m[dr["identifier"]] = Document.parse_file(
67
+ File.join(dir, dr["fileref"]),
68
+ dr["attachment"], dr["identifier"]
69
+ )
66
70
  m
67
71
  end
68
- @manifest.reduce(docs) do |mem, mnf|
69
- mem.merge mnf.documents(dir)
70
- end
72
+ @manifest.reduce(docs) { |mem, mnf| mem.merge mnf.documents(dir) }
71
73
  end
72
74
 
73
75
  # @param builder [Nokogiri::XML::Builder]
@@ -101,6 +103,7 @@ module Metanorma
101
103
  @docref.each do |dr|
102
104
  drf = builder.docref { |b| b.identifier dr["identifier"] }
103
105
  drf[:fileref] = dr["fileref"]
106
+ drf[:attachment] = dr["attachment"] if dr["attachment"]
104
107
  if collection.directives.include?("documents-inline")
105
108
  id = collection.documents.find_index { |k, _| k == dr["identifier"] }
106
109
  drf[:id] = format("doc%<index>09d", index: id)
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "isodoc"
4
- require_relative "./collection_fileprocess"
4
+ require_relative "collection_fileprocess"
5
+ require_relative "fontist_utils"
5
6
 
6
7
  module Metanorma
7
8
  # XML collection renderer
@@ -64,6 +65,7 @@ module Metanorma
64
65
  out = col.clone
65
66
  out.directives << "documents-inline"
66
67
  out.documents.keys.each do |id|
68
+ next if @files[id][:attachment]
67
69
  filename = @files[id][:outputs][e]
68
70
  out.documents[id] = Metanorma::Document.raw_file(filename)
69
71
  end
@@ -74,13 +76,27 @@ module Metanorma
74
76
  end
75
77
 
76
78
  def pdfconv
77
- x = Asciidoctor.load nil, backend: @doctype.to_sym
78
- x.converter.pdf_converter(Dummy.new)
79
+ doctype = @doctype.to_sym
80
+ x = Asciidoctor.load nil, backend: doctype
81
+ x.converter.pdf_converter(PdfOptionsNode.new(doctype, @compile_options))
82
+ end
83
+
84
+ class PdfOptionsNode
85
+ def initialize(doctype, options)
86
+ doc_proc = Metanorma::Registry.instance.find_processor(doctype)
87
+ @font_locations = FontistUtils.fontist_font_locations(doc_proc, options)
88
+ end
89
+
90
+ def attr(key)
91
+ if key == "mn2pdf-font-manifest-file" && @font_locations
92
+ @font_locations.path
93
+ end
94
+ end
79
95
  end
80
96
 
81
97
  # Dummy class
82
98
  class Dummy
83
- def attr(_xyz); end
99
+ def attr(_key); end
84
100
  end
85
101
 
86
102
  # The isodoc class for the metanorma flavour we are using
@@ -1,9 +1,11 @@
1
1
  require "fileutils"
2
2
  require "nokogiri"
3
3
  require "htmlentities"
4
-
4
+ require "yaml"
5
5
  require "fontist"
6
6
  require "fontist/manifest/install"
7
+ require_relative "compile_validate"
8
+ require_relative "fontist_utils"
7
9
 
8
10
  module Metanorma
9
11
  class Compile
@@ -24,23 +26,19 @@ module Metanorma
24
26
  (file, isodoc = process_input(filename, options)) or return nil
25
27
  relaton_export(isodoc, options)
26
28
  extract(isodoc, options[:extract], options[:extract_type])
27
- install_fonts(options)
29
+ FontistUtils.install_fonts(@processor, options)
28
30
  process_extensions(extensions, file, isodoc, options)
29
31
  end
30
32
 
31
33
  def require_libraries(options)
32
- if options[:require]
33
- options[:require].each do |r|
34
- require r
35
- end
36
- end
34
+ options&.dig(:require)&.each { |r| require r }
37
35
  end
38
36
 
39
37
  def xml_options_extract(file)
40
38
  xml = Nokogiri::XML(file)
41
39
  if xml.root
42
40
  @registry.root_tags.each do |k, v|
43
- return { type: k } if v == xml.root.name
41
+ return { type: k } if v == xml.root.name
44
42
  end
45
43
  end
46
44
  {}
@@ -62,48 +60,6 @@ module Metanorma
62
60
  options
63
61
  end
64
62
 
65
- def validate_type(options)
66
- unless options[:type]
67
- Util.log("[metanorma] Error: Please specify a standard type: #{@registry.supported_backends}.", :error)
68
- return nil
69
- end
70
-
71
- stdtype = options[:type].to_sym
72
- metanorma_flavor = "metanorma-#{stdtype}"
73
-
74
- unless @registry.supported_backends.include? stdtype
75
- Util.log("[metanorma] Info: Loading `#{metanorma_flavor}` gem for standard type `#{stdtype}`.", :info)
76
- end
77
-
78
- begin
79
- require "metanorma-#{stdtype}"
80
- Util.log("[metanorma] Info: gem `#{metanorma_flavor}` loaded.", :info)
81
-
82
- rescue Gem::ConflictError
83
- Util.log("[metanorma] Error: Couldn't resolve dependencies for `metanorma-#{stdtype}`, Please add it to your Gemfile and run bundle install first", :error)
84
- return false
85
-
86
- rescue LoadError
87
- Util.log("[metanorma] Error: loading gem `#{metanorma_flavor}` failed. Exiting.", :error)
88
- return false
89
- end
90
-
91
- unless @registry.supported_backends.include? stdtype
92
- Util.log("[metanorma] Error: The `#{metanorma_flavor}` gem still doesn't support `#{stdtype}`. Exiting.", :error)
93
- return false
94
- end
95
-
96
- true
97
- end
98
-
99
- def validate_format(options)
100
- unless options[:format] == :asciidoc
101
- Util.log("[metanorma] Error: Only source file format currently supported is 'asciidoc'.", :error)
102
- return false
103
- end
104
- true
105
- end
106
-
107
63
  def get_extensions(options)
108
64
  options[:extension_keys] ||= @processor.output_formats.reduce([]) do |memo, (k, _)|
109
65
  memo << k
@@ -120,7 +76,7 @@ module Metanorma
120
76
  end
121
77
  if !extensions.include?(:presentation) and extensions.any? { |e| @processor.use_presentation_xml(e) }
122
78
  extensions << :presentation
123
- end
79
+ end
124
80
  extensions
125
81
  end
126
82
 
@@ -186,7 +142,7 @@ module Metanorma
186
142
  xml.xpath("//sourcecode | //xmlns:sourcecode").each_with_index do |s, i|
187
143
  filename = s["filename"] || sprintf("sourcecode-%04d.txt", i)
188
144
  File.open("#{dirname}/sourcecode/#{filename}", "w:UTF-8") do |f|
189
- f.write clean_sourcecode(s.dup)
145
+ f.write clean_sourcecode(s.dup)
190
146
  end
191
147
  end
192
148
  end
@@ -196,6 +152,7 @@ module Metanorma
196
152
  FileUtils.mkdir_p "#{dirname}/image"
197
153
  xml.xpath("//image | //xmlns:image").each_with_index do |s, i|
198
154
  next unless /^data:image/.match s["src"]
155
+
199
156
  %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ s["src"]
200
157
  filename = s["filename"] || sprintf("image-%04d.%s", i, imgtype)
201
158
  File.open("#{dirname}/image/#{filename}", "wb") do |f|
@@ -221,22 +178,22 @@ module Metanorma
221
178
 
222
179
  # dependency ordering
223
180
  def sort_extensions_execution(ext)
224
- case ext
225
- when :xml then 0
226
- when :rxl then 1
227
- when :presentation then 2
228
- else
229
- 99
230
- end
181
+ case ext
182
+ when :xml then 0
183
+ when :rxl then 1
184
+ when :presentation then 2
185
+ else
186
+ 99
187
+ end
231
188
  end
232
189
 
233
190
  def wrap_html(options, file_extension, outfilename)
234
- if options[:wrapper] and /html$/.match file_extension
235
- outfilename = outfilename.sub(/\.html$/, "")
236
- FileUtils.mkdir_p outfilename
237
- FileUtils.mv "#{outfilename}.html", outfilename
238
- FileUtils.mv "#{outfilename}_images", outfilename, force: true
239
- end
191
+ if options[:wrapper] && /html$/.match(file_extension)
192
+ outfilename = outfilename.sub(/\.html$/, "")
193
+ FileUtils.mkdir_p outfilename
194
+ FileUtils.mv "#{outfilename}.html", outfilename
195
+ FileUtils.mv "#{outfilename}_images", outfilename, force: true
196
+ end
240
197
  end
241
198
 
242
199
  # isodoc is Raw Metanorma XML
@@ -249,8 +206,14 @@ module Metanorma
249
206
  end.each do |ext|
250
207
  isodoc_options = @processor.extract_options(file)
251
208
  isodoc_options[:datauriimage] = true if options[:datauriimage]
209
+ isodoc_options[:sourcefilename] = options[:filename]
252
210
  file_extension = @processor.output_formats[ext]
253
211
  outfilename = f.sub(/\.[^.]+$/, ".#{file_extension}")
212
+ if ext == :pdf
213
+ font_locations = FontistUtils.fontist_font_locations(@processor, options)
214
+ font_locations and
215
+ isodoc_options[:mn2pdf] = { font_manifest_file: font_locations.path }
216
+ end
254
217
  if ext == :rxl
255
218
  options[:relaton] = outfilename
256
219
  relaton_export(isodoc, options)
@@ -260,66 +223,20 @@ module Metanorma
260
223
  @processor.output(nil, presentationxml_name, outfilename, ext, isodoc_options) :
261
224
  @processor.output(isodoc, xml_name, outfilename, ext, isodoc_options)
262
225
  rescue StandardError => e
263
- puts e.message
264
- puts e.backtrace.join("\n")
226
+ if e.message.include? "Fatal:"
227
+ @errors << e.message
228
+ else
229
+ puts e.message
230
+ puts e.backtrace.join("\n")
231
+ end
265
232
  end
266
233
  end
267
234
  wrap_html(options, file_extension, outfilename)
268
235
  end
269
236
  end
270
237
 
271
- def install_fonts(options)
272
- if options[:no_install_fonts]
273
- Util.log("[fontist] Skip font installation because" \
274
- " --no-install-fonts argument passed", :debug)
275
- return
276
- end
277
-
278
- if !@processor.respond_to?(:fonts_manifest) || @processor.fonts_manifest.nil?
279
- Util.log("[fontist] Skip font installation because font_manifest is missing", :debug)
280
- return
281
- end
282
-
283
- @updated_formulas_repo = false
284
-
285
- manifest = @processor.fonts_manifest
286
- agree_to_terms = options[:agree_to_terms] || false
287
- continue_without_fonts = options[:continue_without_fonts] || false
288
-
289
- install_fonts_safe(manifest, agree_to_terms, continue_without_fonts)
290
- end
291
-
292
238
  private
293
239
 
294
- def install_fonts_safe(manifest, agree, continue)
295
- fontist_install(manifest, agree)
296
- rescue Fontist::Errors::LicensingError
297
- if continue
298
- Util.log("[fontist] Processing will continue without fonts installed", :debug)
299
- else
300
- Util.log("[fontist] Aborting without proper fonts installed," \
301
- " make sure that you have set option --agree-to-terms", :fatal)
302
- end
303
- rescue Fontist::Errors::FontError => e
304
- log_level = continue ? :warning : :fatal
305
- Util.log("[fontist] '#{e.font}' font is not supported. " \
306
- "Please report this issue at github.com/metanorma/metanorma-#{@processor.short}/issues" \
307
- " to report this issue.", log_level)
308
- rescue Fontist::Errors::FormulaIndexNotFoundError
309
- Util.log("[fontist] Bug: formula index not found after 'fontist update'", :fatal) if @updated_formulas_repo
310
- Util.log("[fontist] Missing formula index. Fetching it...", :debug)
311
- Fontist::Formula.update_formulas_repo
312
- @updated_formulas_repo = true
313
- install_fonts_safe(manifest, agree, continue)
314
- end
315
-
316
- def fontist_install(manifest, agree)
317
- Fontist::Manifest::Install.from_hash(
318
- manifest,
319
- confirmation: agree ? "yes" : "no"
320
- )
321
- end
322
-
323
240
  # @param options [Hash]
324
241
  # @return [String]
325
242
  def change_output_dir(options)
@@ -0,0 +1,45 @@
1
+ module Metanorma
2
+ class Compile
3
+ def validate_type(options)
4
+ unless options[:type]
5
+ Util.log("[metanorma] Error: Please specify a standard type: "\
6
+ "#{@registry.supported_backends}.", :error)
7
+ return nil
8
+ end
9
+ stdtype = options[:type].to_sym
10
+ metanorma_flavor = "metanorma-#{stdtype}"
11
+ unless @registry.supported_backends.include? stdtype
12
+ Util.log("[metanorma] Info: Loading `#{metanorma_flavor}` gem "\
13
+ "for standard type `#{stdtype}`.", :info)
14
+ end
15
+ begin
16
+ require "metanorma-#{stdtype}"
17
+ Util.log("[metanorma] Info: gem `#{metanorma_flavor}` loaded.", :info)
18
+ rescue Gem::ConflictError
19
+ Util.log("[metanorma] Error: Couldn't resolve dependencies for "\
20
+ "`metanorma-#{stdtype}`, Please add it to your Gemfile "\
21
+ "and run bundle install first", :error)
22
+ return false
23
+ rescue LoadError
24
+ Util.log("[metanorma] Error: loading gem `#{metanorma_flavor}` "\
25
+ "failed. Exiting.", :error)
26
+ return false
27
+ end
28
+ unless @registry.supported_backends.include? stdtype
29
+ Util.log("[metanorma] Error: The `#{metanorma_flavor}` gem "\
30
+ "still doesn't support `#{stdtype}`. Exiting.", :error)
31
+ return false
32
+ end
33
+ true
34
+ end
35
+
36
+ def validate_format(options)
37
+ unless options[:format] == :asciidoc
38
+ Util.log("[metanorma] Error: Only source file format currently "\
39
+ "supported is 'asciidoc'.", :error)
40
+ return false
41
+ end
42
+ true
43
+ end
44
+ end
45
+ end
@@ -15,7 +15,7 @@ module Metanorma
15
15
  attr_accessor :logs
16
16
 
17
17
  def initialize
18
- @logs ||= [:warning, :error, :fatal]
18
+ @logs ||= %i[warning error fatal]
19
19
  end
20
20
  end
21
21
 
@@ -1,20 +1,25 @@
1
1
  module Metanorma
2
2
  class Document
3
3
  # @return [Strin]
4
- attr_reader :file
4
+ attr_reader :file, :attachment, :bibitem
5
5
 
6
6
  # @param bibitem [RelatonBib::BibliographicItem]
7
7
  def initialize(bibitem, file, options = {})
8
8
  @bibitem = bibitem
9
9
  @file = file
10
+ @attachment = options[:attachment]
10
11
  @raw = options[:raw]
11
12
  end
12
13
 
13
14
  class << self
14
15
  # @param file [String] file path
16
+ # @param attachment [Bool] is an attachment
17
+ # @param identifier [String] is the identifier assigned the file
18
+ # in the collection file
15
19
  # @return [Metanorma::Document]
16
- def parse_file(file)
17
- new bibitem(file), file
20
+ def parse_file(file, attachment, identifier = nil)
21
+ new(bibitem(file, attachment, identifier), file,
22
+ { attachment: attachment })
18
23
  end
19
24
 
20
25
  # #param xml [Nokogiri::XML::Document, Nokogiri::XML::Element]
@@ -29,6 +34,12 @@ module Metanorma
29
34
  new(doc, filename, raw: true)
30
35
  end
31
36
 
37
+ def attachment_bibitem(identifier)
38
+ Nokogiri::XML(
39
+ "<bibdata><docidentifier>#{identifier}</docidentifier></bibdata>",
40
+ )
41
+ end
42
+
32
43
  private
33
44
 
34
45
  # #param xml [Nokogiri::XML::Document, Nokogiri::XML::Element]
@@ -49,13 +60,16 @@ module Metanorma
49
60
  # @param file [String]
50
61
  # @return [RelatonBib::BibliographicItem,
51
62
  # RelatonIso::IsoBibliographicItem]
52
- def bibitem(file)
53
- case format(file)
54
- when :xml
55
- from_xml Nokogiri::XML(File.read(file, encoding: "UTF-8"))
56
- when :yaml
57
- yaml = File.read(file, encoding: "UTF-8")
58
- Relaton::Cli::YAMLConvertor.convert_single_file(yaml)
63
+ def bibitem(file, attachment, identifier)
64
+ if attachment then attachment_bibitem(identifier)
65
+ else
66
+ case format(file)
67
+ when :xml
68
+ from_xml Nokogiri::XML(File.read(file, encoding: "UTF-8"))
69
+ when :yaml
70
+ yaml = File.read(file, encoding: "UTF-8")
71
+ Relaton::Cli::YAMLConvertor.convert_single_file(yaml)
72
+ end
59
73
  end
60
74
  end
61
75
  end
@@ -0,0 +1,108 @@
1
+ module Metanorma
2
+ class FontistUtils
3
+ class << self
4
+ private
5
+
6
+ def validate_options(options)
7
+ agree_to_terms = options[:agree_to_terms] || false
8
+ continue_without_fonts = options[:continue_without_fonts] || false
9
+ no_progress = options[:no_progress] || false
10
+
11
+ [agree_to_terms, continue_without_fonts, no_progress]
12
+ end
13
+
14
+ def validate_install_fonts(processor, options)
15
+ if options[:no_install_fonts]
16
+ Util.log("[fontist] Skip font installation because" \
17
+ " --no-install-fonts argument passed", :debug)
18
+ return false
19
+ elsif missing_fontist_manifest?(processor)
20
+ Util.log("[fontist] Skip font installation because "\
21
+ "font_manifest is missing", :debug)
22
+ return false
23
+ end
24
+ true
25
+ end
26
+
27
+ def install_fonts_safe(manifest, agree, continue, no_progress)
28
+ fontist_install(manifest, agree, no_progress)
29
+ rescue Fontist::Errors::LicensingError
30
+ if continue
31
+ Util.log(
32
+ "[fontist] Processing will continue without fonts installed",
33
+ :debug
34
+ )
35
+ else
36
+ Util.log("[fontist] Aborting without proper fonts installed," \
37
+ " make sure that you have set option --agree-to-terms",
38
+ :fatal)
39
+ end
40
+ rescue Fontist::Errors::FontError => e
41
+ log_level = continue ? :warning : :fatal
42
+ Util.log("[fontist] '#{e.font}' font is not supported. " \
43
+ "Please report this issue at github.com/metanorma/metanorma" \
44
+ "/issues to report this issue.", log_level)
45
+ rescue Fontist::Errors::FormulaIndexNotFoundError
46
+ if @@updated_formulas_repo
47
+ Util.log(
48
+ "[fontist] Bug: formula index not found after 'fontist update'",
49
+ :fatal
50
+ )
51
+ end
52
+ Util.log("[fontist] Missing formula index. Fetching it...", :debug)
53
+ Fontist::Formula.update_formulas_repo
54
+ @@updated_formulas_repo = true
55
+ install_fonts_safe(manifest, agree, continue, no_progress)
56
+ end
57
+
58
+ def fontist_install(manifest, agree, no_progress)
59
+ Fontist::Manifest::Install.from_hash(
60
+ manifest,
61
+ confirmation: agree ? "yes" : "no",
62
+ no_progress: no_progress
63
+ )
64
+ end
65
+
66
+ def dump_fontist_manifest_locations(manifest)
67
+ location_manifest = Fontist::Manifest::Locations.from_hash(
68
+ manifest
69
+ )
70
+ location_manifest_file = Tempfile.new(["fontist_locations", ".yml"])
71
+ location_manifest_file.write location_manifest.to_yaml
72
+ location_manifest_file.flush
73
+ location_manifest_file
74
+ end
75
+
76
+ def missing_fontist_manifest?(processor)
77
+ !processor.respond_to?(:fonts_manifest) || processor.fonts_manifest.nil?
78
+ end
79
+ end
80
+
81
+ def self.install_fonts(processor, options)
82
+ return unless validate_install_fonts(processor, options)
83
+
84
+ @@updated_formulas_repo = false
85
+ manifest = processor.fonts_manifest
86
+ agree_to_terms, can_without_fonts, no_progress = validate_options(options)
87
+
88
+ install_fonts_safe(
89
+ manifest,
90
+ agree_to_terms,
91
+ can_without_fonts,
92
+ no_progress
93
+ )
94
+ end
95
+
96
+ def self.fontist_font_locations(processor, options)
97
+ if missing_fontist_manifest?(processor) || options[:no_install_fonts]
98
+ return nil
99
+ end
100
+
101
+ dump_fontist_manifest_locations(processor.fonts_manifest)
102
+ rescue Fontist::Errors::FormulaIndexNotFoundError
103
+ raise unless options[:continue_without_fonts]
104
+
105
+ nil
106
+ end
107
+ end
108
+ end