pandocomatic 0.1.4.9 → 0.1.4.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b790fdc99211b28030f3e6c2fb83ec9a68dcbf2c
4
- data.tar.gz: b3bce488828fd3f610b922d012022b9fa2c880ff
3
+ metadata.gz: 11bf26bcbf6d79b0583eca48c30e1b685314f514
4
+ data.tar.gz: c26dd9a4433581a6154df33096d993fe56208338
5
5
  SHA512:
6
- metadata.gz: daa6fea415f430f87d4806e15d405a8b2bd469005eec21530c1799ccde8dc19736ff8af34559a0d91e1ef6f9814531193301697c8f209bbb75dcd1f655672ac3
7
- data.tar.gz: cd9553189cb5f60350073d79192980e5ed4d205df5f79cf87a582f1bf6177b91fa875e535e6d05a722e80de93aa2ab6bca704c5e705773214bf693d4c9553a58
6
+ metadata.gz: 5b1d7bcd5051193689a09812c45a7e4155d06e47ca9d6906b5d02ba0dbb628cdaa952ae613206b1eb59d3dfc3f21a81c102006743cc53895cc0b51500a078d9a
7
+ data.tar.gz: cc8a459844153351c30749c2d0ff215ec8ff64655661b74f893acffcd7ecf1fba447d7d063a399dbf43a89b94862cd964b6e2c52c3ebc50c6872b672472ea8b1
@@ -18,271 +18,415 @@
18
18
  #++
19
19
  module Pandocomatic
20
20
 
21
- require 'yaml'
22
- require 'paru/pandoc'
21
+ require 'yaml'
22
+ require 'paru/pandoc'
23
+
24
+ # The default configuration for pandocomatic is read from
25
+ # default_configuration.yaml.
26
+ DEFAULT_CONFIG = YAML.load_file File.join(__dir__, 'default_configuration.yaml')
27
+
28
+ # Maps pandoc output formats to an extension.
29
+ FORMAT_TO_EXT = {
30
+ 'native' => 'hs',
31
+ 'markdown' => 'md',
32
+ 'markdown_strict' => 'md',
33
+ 'markdown_phpextra' => 'md',
34
+ 'markdown_github' => 'md',
35
+ 'html5' => 'html',
36
+ 'docx' => 'docx',
37
+ 'latex' => 'tex'
38
+ }
39
+
40
+ # A Configuration object models a pandocomatic configuration.
41
+ class Configuration
42
+
43
+ # Create a new Configuration instance based on the command-line
44
+ # options, a data_dir, and a configuration file.
45
+ def initialize options, data_dir, configuration_file
46
+ @data_dir = data_dir
23
47
 
24
- DEFAULT_CONFIG = YAML.load_file File.join(__dir__, 'default_configuration.yaml')
48
+ load configuration_file
49
+ end
25
50
 
26
- FORMAT_TO_EXT = {
27
- 'native' => 'hs',
28
- 'markdown' => 'md',
29
- 'markdown_strict' => 'md',
30
- 'markdown_phpextra' => 'md',
31
- 'markdown_github' => 'md',
32
- 'html5' => 'html',
33
- 'docx' => 'docx',
34
- 'latex' => 'tex'
35
- }
51
+ # Read a configuration file and create a pandocomatic configuration object
52
+ #
53
+ # @param [String] filename Path to the configuration yaml file
54
+ # @return [Configuration] a pandocomatic configuration object
55
+ def load(filename)
56
+ begin
57
+ path = File.absolute_path filename
58
+ settings = YAML.load_file path
59
+ if settings['settings'] and settings['settings']['data-dir'] then
60
+ data_dir = settings['settings']['data-dir']
61
+ src_dir = File.dirname filename
62
+ if data_dir.start_with? '.' then
63
+ @data_dir = File.absolute_path data_dir, src_dir
64
+ else
65
+ @data_dir = data_dir
66
+ end
67
+ end
68
+ rescue StandardError => e
69
+ raise ConfigurationError.new(:unable_to_load_config_file, e, filename)
70
+ end
36
71
 
37
- # Configuration describes a pandocomatic configuration.
38
- class Configuration
72
+ # hidden files will always be skipped, as will pandocomatic
73
+ # configuration files, unless explicitly set to not skip via the
74
+ # "unskip" option
39
75
 
40
- def initialize options, data_dir, configuration_file
41
- @data_dir = data_dir
76
+ @settings = {'skip' => ['.*', 'pandocomatic.yaml']}
42
77
 
43
- load configuration_file
44
- end
78
+ @templates = {}
79
+ @convert_patterns = {}
45
80
 
46
- # Read a configuration file and create a pandocomatic configuration object
47
- #
48
- # @param [String] filename Path to the configuration yaml file
49
- # @return [Configuration] a pandocomatic configuration object
50
- def load(filename)
51
- begin
52
- path = File.absolute_path filename
53
- settings = YAML.load_file path
54
- if settings['settings'] and settings['settings']['data-dir'] then
55
- data_dir = settings['settings']['data-dir']
56
- src_dir = File.dirname filename
57
- if data_dir.start_with? '.' then
58
- @data_dir = File.absolute_path data_dir, src_dir
59
- else
60
- @data_dir = data_dir
61
- end
81
+ configure settings
62
82
  end
63
- rescue StandardError => e
64
- raise ConfigurationError.new(:unable_to_load_config_file, e, filename)
65
- end
66
83
 
67
- # hidden files will always be skipped, as will pandocomatic
68
- # configuration files, unless explicitly set to not skip via the
69
- # "unskip" option
84
+ # Update this configuration with a configuration file
85
+ #
86
+ # @param [String] filename path to the configuration file
87
+ #
88
+ # @return [Configuration] a new configuration
89
+ def reconfigure(filename)
90
+ begin
91
+ settings = YAML.load_file filename
92
+ new_config = Marshal.load(Marshal.dump(self))
93
+ new_config.configure settings
94
+ new_config
95
+ rescue StandardError => e
96
+ raise ConfigurationError.new(:unable_to_load_config_file, e, filename)
97
+ end
98
+ end
70
99
 
71
- @settings = {'skip' => ['.*', 'pandocomatic.yaml']}
100
+ # Configure pandocomatic based on a settings Hash
101
+ #
102
+ # @param settings [Hash] a settings Hash to mixin in this
103
+ # Configuration.
104
+ def configure(settings)
105
+ reset_settings settings['settings'] if settings.has_key? 'settings'
106
+ if settings.has_key? 'templates' then
107
+ settings['templates'].each do |name, template|
108
+ full_template = {
109
+ 'extends' => [],
110
+ 'glob' => [],
111
+ 'setup' => [],
112
+ 'preprocessors' => [],
113
+ 'metadata' => {},
114
+ 'pandoc' => {},
115
+ 'postprocessors' => [],
116
+ 'cleanup' => []
117
+ }
118
+
119
+ reset_template name, full_template.merge(template)
120
+ end
121
+ end
122
+ end
72
123
 
73
- @templates = {}
74
- @convert_patterns = {}
124
+ # Convert this Configuration to a String
125
+ #
126
+ # @return [String]
127
+ def to_s()
128
+ marshal_dump
129
+ end
75
130
 
76
- configure settings
77
- end
131
+ # Should the source file be skipped given this Configuration?
132
+ #
133
+ # @param src [String] path to a source file
134
+ # @return [Boolean] True if this source file matches the pattern in
135
+ # the 'skip' setting, false otherwise.
136
+ def skip?(src)
137
+ if @settings.has_key? 'skip' then
138
+ @settings['skip'].any? {|glob| File.fnmatch glob, File.basename(src)}
139
+ else
140
+ false
141
+ end
142
+ end
78
143
 
79
- # Update this configuration with a configuration file
80
- #
81
- # @param [String] filename path to the configuration file
82
- #
83
- # @return [Configuration] a new configuration
84
- def reconfigure(filename)
85
- begin
86
- settings = YAML.load_file filename
87
- new_config = Marshal.load(Marshal.dump(self))
88
- new_config.configure settings
89
- new_config
90
- rescue StandardError => e
91
- raise ConfigurationError.new(:unable_to_load_config_file, e, filename)
92
- end
93
- end
144
+ # Should the source file be converted given this Configuration?
145
+ #
146
+ # @param src [String] True if this source file matches the 'glob'
147
+ # patterns in a template, false otherwise.
148
+ def convert?(src)
149
+ @convert_patterns.values.flatten.any? {|glob| File.fnmatch glob, File.basename(src)}
150
+ end
94
151
 
95
- def configure(settings)
96
- reset_settings settings['settings'] if settings.has_key? 'settings'
97
- if settings.has_key? 'templates' then
98
- settings['templates'].each do |name, template|
99
- full_template = {
100
- 'glob' => [],
101
- 'setup' => [],
102
- 'preprocessors' => [],
103
- 'metadata' => {},
104
- 'pandoc' => {},
105
- 'postprocessors' => [],
106
- 'cleanup' => []
107
- }
108
-
109
- reset_template name, full_template.merge(template)
152
+ # Should pandocomatic be run recursively given this Configuration?
153
+ #
154
+ # @return [Boolean] True if the setting 'recursive' is true, false
155
+ # otherwise
156
+ def recursive?()
157
+ @settings['recursive']
110
158
  end
111
- end
112
- end
113
159
 
114
- def marshal_dump()
115
- [@data_dir, @settings, @templates, @convert_patterns]
116
- end
160
+ # Should pandocomatic follow symbolic links given this Configuration?
161
+ #
162
+ # @return [Boolean] True if the setting 'follow_links' is true, false
163
+ # otherwise
164
+ def follow_links?()
165
+ @settings['follow_links']
166
+ end
117
167
 
118
- def marshal_load(array)
119
- @data_dir, @settings, @templates, @convert_patterns = array
120
- end
168
+ # Set the extension of the destination file given this Confguration,
169
+ # template, and metadata
170
+ #
171
+ # @param dst [String] path to a destination file
172
+ # @param template_name [String] the name of the template used to
173
+ # convert to destination
174
+ # @param metadata [PandocMetadata] the metadata in the source file
175
+ def set_extension(dst, template_name, metadata)
176
+ dir = File.dirname dst
177
+ ext = File.extname dst
178
+ basename = File.basename dst, ext
179
+ File.join dir, "#{basename}.#{find_extension(dst, template_name, metadata)}"
180
+ end
121
181
 
122
- def to_s()
123
- marshal_dump
124
- end
182
+ # Find the extension of the destination file given this Confguration,
183
+ # template, and metadata
184
+ #
185
+ # @param dst [String] path to a destination file
186
+ # @param template_name [String] the name of the template used to
187
+ # convert to destination
188
+ # @param metadata [PandocMetadata] the metadata in the source file
189
+ #
190
+ # @return [String] the extension to use for the destination file
191
+ def find_extension(dst, template_name, metadata)
192
+ extension = "html"
193
+ if template_name.nil? or template_name.empty? then
194
+ if metadata.has_pandocomatic?
195
+ pandocomatic = metadata.pandocomatic
196
+ if pandocomatic.has_key? "pandoc"
197
+ pandoc = pandocomatic["pandoc"]
198
+
199
+ if pandoc.has_key? "to"
200
+ extension = pandoc["to"]
201
+ end
202
+ end
203
+ end
204
+ else
205
+ # TODO: what if there is no pandoc.to?
206
+ if @templates[template_name].has_key? "pandoc"
207
+ pandoc = @templates[template_name]["pandoc"]
208
+ if pandoc.has_key? "to"
209
+ extension = pandoc["to"]
210
+ end
211
+ end
212
+ end
125
213
 
126
- def skip?(src)
127
- if @settings.has_key? 'skip' then
128
- @settings['skip'].any? {|glob| File.fnmatch glob, File.basename(src)}
129
- else
130
- false
131
- end
132
- end
214
+ extension = FORMAT_TO_EXT[extension] || extension
215
+ return extension
216
+ end
133
217
 
134
- def convert?(src)
135
- @convert_patterns.values.flatten.any? {|glob| File.fnmatch glob, File.basename(src)}
136
- end
218
+ # Is there a template with template_name in this Configuration?
219
+ #
220
+ # @param template_name [String] a template's name
221
+ #
222
+ # @return [Boolean] True if there is a template with name equal to
223
+ # template_name in this Configuration
224
+ def has_template?(template_name)
225
+ @templates.has_key? template_name
226
+ end
137
227
 
138
- def recursive?()
139
- @settings['recursive']
140
- end
228
+ # Get the template with template_name from this Configuration
229
+ #
230
+ # @param template_name [String] a template's name
231
+ #
232
+ # @return [Hash] The template with template_name.
233
+ def get_template(template_name)
234
+ @templates[template_name]
235
+ end
141
236
 
142
- def follow_links?()
143
- @settings['follow_links']
144
- end
237
+ # Determine the template to use with this source document given this
238
+ # Configuration.
239
+ #
240
+ # @param src [String] path to the source document
241
+ # @return [String] the template's name to use
242
+ def determine_template(src)
243
+ @convert_patterns.select do |template_name, globs|
244
+ globs.any? {|glob| File.fnmatch glob, File.basename(src)}
245
+ end.keys.first
246
+ end
145
247
 
146
- def set_extension(dst, template_name, metadata)
147
- dir = File.dirname dst
148
- ext = File.extname dst
149
- basename = File.basename dst, ext
150
- File.join dir, "#{basename}.#{find_extension(dst, template_name, metadata)}"
151
- end
248
+ # Update the path to an executable processor or executor given this
249
+ # Configuration
250
+ #
251
+ # @param path [String] path to the executable
252
+ # @param src_dir [String] the source directory from which pandocomatic
253
+ # conversion process has been started
254
+ # @param check_executable [Booelan = false] Should the executable be
255
+ # verified to be executable? Defaults to false.
256
+ #
257
+ # @return [String] the updated path.
258
+ def update_path(path, src_dir, check_executable = false)
259
+ updated_path = path
260
+ if path.start_with? './'
261
+ # refers to a local (to file) dir
262
+ updated_path = File.join src_dir, path
263
+ else
264
+ if path.start_with? '/'
265
+ updated_path = path
266
+ else
267
+ if check_executable
268
+ updated_path = Configuration.which path
269
+ end
270
+
271
+ if updated_path.nil? or not updated_path.start_with? '/' then
272
+ # refers to data-dir
273
+ updated_path = File.join @data_dir, path
274
+ end
275
+ end
276
+ end
152
277
 
153
- def find_extension(dst, template_name, metadata)
154
- extension = "html"
155
- if template_name.nil? or template_name.empty? then
156
- if metadata.has_pandocomatic?
157
- pandocomatic = metadata.pandocomatic
158
- if pandocomatic.has_key? "pandoc"
159
- pandoc = pandocomatic["pandoc"]
278
+ updated_path
279
+ end
160
280
 
161
- if pandoc.has_key? "to"
162
- extension = pandoc["to"]
281
+ private
282
+
283
+ # Reset the settings for pandocomatic based on a new settings Hash
284
+ #
285
+ # @settings [Hash] the new settings to use to reset the settings in
286
+ # this Configuration with.
287
+ def reset_settings(settings)
288
+ settings.each do |setting, value|
289
+ case setting
290
+ when 'skip'
291
+ @settings['skip'] = @settings['skip'].concat(value).uniq
292
+ when 'data-dir'
293
+ next # skip data-dir setting; is set once in initialization
294
+ else
295
+ @settings[setting] = value
163
296
  end
164
297
  end
165
- end
166
- else
167
- # TODO: what if there is no pandoc.to?
168
- if @templates[template_name].has_key? "pandoc"
169
- pandoc = @templates[template_name]["pandoc"]
170
- if pandoc.has_key? "to"
171
- extension = pandoc["to"]
172
- end
173
298
  end
174
- end
175
-
176
- extension = FORMAT_TO_EXT[extension] || extension
177
- return extension
178
- end
179
-
180
- def has_template?(template_name)
181
- @templates.has_key? template_name
182
- end
183
299
 
184
- def get_template(template_name)
185
- @templates[template_name]
186
- end
300
+ # Merge two templates
301
+ #
302
+ # @param base_template [Hash] the base template
303
+ # @param mixin_template [Hash] the template to mixin into the base template
304
+ # @return [Hash] the merged templates
305
+ def merge(base_template, mixin_template)
306
+ fields = [
307
+ 'extends',
308
+ 'glob',
309
+ 'metadata',
310
+ 'setup',
311
+ 'preprocessors',
312
+ 'pandoc',
313
+ 'postprocessors',
314
+ 'cleanup'
315
+ ]
316
+
317
+ fields.each do |field|
318
+ case field
319
+ when 'extends'
320
+ if mixin_template[field] and mixin_template[field].is_a? String
321
+ mixin_template[field] = [mixin_template[field]]
322
+ end
323
+ when
324
+ 'cleanup',
325
+ 'setup',
326
+ 'preprocessors',
327
+ 'postprocessors',
328
+ 'glob'
329
+
330
+ if base_template[field] then
331
+ # If both templates have this field, concat the arrays
332
+ # and remove duplicates
333
+ if mixin_template[field] then
334
+ base_template[field].concat(mixin_template[field]).uniq!
335
+ end
336
+ else
337
+ # If the base does not have this fiel yet, assign it
338
+ # the mixin's
339
+ if mixin_template[field] then
340
+ base_template[field] = mixin_template[field]
341
+ end
342
+ end
343
+ when 'pandoc', 'metadata'
344
+ # Merge Hashes
345
+ if base_template[field] then
346
+ if mixin_template[field] then
347
+ base_template[field].merge! mixin_template[field]
348
+ end
349
+ else
350
+ if mixin_template[field] then
351
+ base_template[field] = mixin_template[field]
352
+ end
353
+ end
354
+ end
355
+ end
187
356
 
188
- def determine_template(src)
189
- @convert_patterns.select do |template_name, globs|
190
- globs.any? {|glob| File.fnmatch glob, File.basename(src)}
191
- end.keys.first
192
- end
357
+ base_template
358
+ end
193
359
 
194
- def update_path(path, src_dir, check_executable = false)
195
- updated_path = path
196
- if path.start_with? './'
197
- # refers to a local (to file) dir
198
- updated_path = File.join src_dir, path
199
- else
200
- if path.start_with? '/'
201
- updated_path = path
202
- else
203
- if check_executable
204
- updated_path = Configuration.which path
360
+ # Resolve the templates the templates extends and mixes them in, in
361
+ # order of occurrence.
362
+ #
363
+ # @param template [Hash] the template to extend
364
+ # @return [Hash] the resolved template
365
+ def extend_template(template)
366
+ resolved_template = {};
367
+ if template.has_key? 'extends' and not template['extends'].empty?
368
+ to_extend = template['extends']
369
+ to_extend = [to_extend] if to_extend.is_a? String
370
+
371
+ to_extend.each do |name|
372
+ if @templates.has_key? name
373
+ resolved_template = merge resolved_template, @templates[name]
374
+ else
375
+ warn "Cannot find template with name '#{parent_template_name}'. Skipping this template while extending: '#{template.to_s}'."
376
+ end
205
377
  end
206
378
 
207
- if updated_path.nil? or not updated_path.start_with? '/' then
208
- # refers to data-dir
209
- updated_path = File.join @data_dir, path
210
- end
379
+ resolved_template
211
380
  end
212
- end
213
381
 
214
- updated_path
215
- end
216
-
217
- private
218
-
219
- def reset_settings(settings)
220
- settings.each do |setting, value|
221
- case setting
222
- when 'skip'
223
- @settings['skip'] = @settings['skip'].concat(value).uniq
224
- when 'data-dir'
225
- next # skip data-dir setting; is set once in initialization
226
- else
227
- @settings[setting] = value
382
+ merge resolved_template, template
228
383
  end
229
- end
230
- end
231
384
 
232
- def reset_template(name, template)
233
- if @templates.has_key? name then
234
- fields = ['glob', 'cleanup', 'setup', 'preprocessors', 'pandoc', 'postprocessors']
235
- fields.each do |field|
236
- case field
237
- when 'cleanup', 'setup', 'preprocessors', 'postprocessors', 'glob'
238
- if @templates[name][field] then
239
- if template[field] then
240
- @templates[name][field].concat(template[field]).uniq!
241
- end
385
+ # Reset the template with name in this Configuration based on a new
386
+ # template
387
+ #
388
+ # @param name [String] the name of the template in this Configuration
389
+ # @param template [Hash] the template to use to update the template in
390
+ # this Configuarion with
391
+ def reset_template(name, template)
392
+ extended_template = extend_template template
393
+
394
+ if @templates.has_key? name then
395
+ @templates[name] = merge @templates[name], extended_template
242
396
  else
243
- if template[field] then
244
- @templates[name][field] = template[field]
245
- end
397
+ @templates[name] = extended_template
246
398
  end
247
- when 'pandoc', 'metadata'
248
- if @templates[name][field] then
249
- if template[field] then
250
- @templates[name][field].merge! template[field]
251
- end
252
- else
253
- if template[field] then
254
- @templates[name][field] = template[field]
255
- end
399
+
400
+ if extended_template.has_key? 'glob' then
401
+ @convert_patterns[name] = extended_template['glob']
256
402
  end
257
- end
258
403
  end
259
- else
260
- @templates[name] = template
261
- end
262
-
263
- if template.has_key? 'glob' then
264
- @convert_patterns[name] = template['glob']
265
- end
266
- end
267
404
 
268
- # Cross-platform way of finding an executable in the $PATH.
269
- #
270
- # which('ruby') #=> /usr/bin/ruby
271
- #
272
- # Taken from:
273
- # http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby#5471032
274
- def self.which(cmd)
275
- exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
276
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
277
- exts.each { |ext|
278
- exe = File.join(path, "#{cmd}#{ext}")
279
- return exe if File.executable?(exe) &&
280
- !File.directory?(exe)
281
- }
405
+ # Cross-platform way of finding an executable in the $PATH.
406
+ #
407
+ # which('ruby') #=> /usr/bin/ruby
408
+ #
409
+ # Taken from:
410
+ # http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby#5471032
411
+ def self.which(cmd)
412
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
413
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
414
+ exts.each { |ext|
415
+ exe = File.join(path, "#{cmd}#{ext}")
416
+ return exe if File.executable?(exe) &&
417
+ !File.directory?(exe)
418
+ }
419
+ end
420
+ return nil
421
+ end
422
+
423
+ def marshal_dump()
424
+ [@data_dir, @settings, @templates, @convert_patterns]
282
425
  end
283
- return nil
284
- end
285
426
 
286
- end
427
+ def marshal_load(array)
428
+ @data_dir, @settings, @templates, @convert_patterns = array
429
+ end
287
430
 
431
+ end
288
432
  end
@@ -18,93 +18,149 @@
18
18
  #++
19
19
  module Pandocomatic
20
20
 
21
- require 'json'
22
- require 'yaml'
23
- require 'paru'
24
- require 'paru/pandoc2yaml'
25
-
26
- require_relative './error/pandoc_error.rb'
27
- require_relative './error/io_error.rb'
28
-
29
- class PandocMetadata < Hash
30
-
31
- def self.extract_metadata input_document
32
- begin
33
- Paru::Pandoc2Yaml.extract_metadata(input_document)
34
- rescue StandardError => e
35
- raise IOError.new(:error_opening_file, e, input_document)
36
- end
37
- end
21
+ require 'json'
22
+ require 'yaml'
23
+ require 'paru'
24
+
25
+ require_relative './error/pandoc_error.rb'
26
+ require_relative './error/io_error.rb'
27
+
28
+ # PandocMetadata represents the metadata with pandoc options set in
29
+ # templates and input files.
30
+ class PandocMetadata < Hash
31
+
32
+ # Extract the metadata from an input file
33
+ #
34
+ # @param input_document [String] a path to an input file
35
+ # @return [String] the input document's metadata in the YAML format.
36
+ def self.extract_metadata input_document
37
+ begin
38
+ pandoc2yaml File.read(input_document)
39
+ rescue StandardError => e
40
+ raise IOError.new(:error_opening_file, e, input_document)
41
+ end
42
+ end
38
43
 
39
- # Collect the metadata embedded in the src file
40
- def self.load_file src
41
- yaml_metadata = extract_metadata src
44
+ # Extract the YAML metadata from an input string
45
+ #
46
+ # @param input [String] the input string
47
+ # @return [String] the YAML data embedded in the input string
48
+ def self.pandoc2yaml(input)
49
+ input
50
+ .scan(/^---[ \t]*\n(.+?)^(?:---|\.\.\.)[ \t]*\n/m)
51
+ .flatten
52
+ .map{|yaml| yaml.strip}
53
+ .join("\n")
54
+ end
42
55
 
43
- if yaml_metadata.empty? then
44
- return PandocMetadata.new
45
- else
46
- return PandocMetadata.new YAML.load(yaml_metadata)
47
- end
48
- end
49
-
50
- def initialize hash = {}
51
- super
52
- merge! hash
53
- end
56
+ # Collect the metadata embedded in the src file and create a new
57
+ # PandocMetadata instance
58
+ #
59
+ # @param src [String] the path to the file to load metadata from
60
+ # @return [PandocMetadata] the metadata in the source file, or an empty
61
+ # one if no such metadata is contained in the source file.
62
+ def self.load_file src
63
+ yaml_metadata = extract_metadata src
64
+
65
+ if yaml_metadata.empty? then
66
+ return PandocMetadata.new
67
+ else
68
+ return PandocMetadata.new YAML.load(yaml_metadata)
69
+ end
70
+ end
54
71
 
55
- def has_template?()
56
- has_pandocomatic? and pandocomatic.has_key? 'use-template' and not pandocomatic['use-template'].empty?
57
- end
72
+ # Creat e new PandocMetadata object based on the properties contained
73
+ # in a Hash
74
+ #
75
+ # @param hash [Hash] initial properties for this new PandocMetadata
76
+ # object
77
+ # @return [PandocMetadata]
78
+ def initialize hash = {}
79
+ super
80
+ merge! hash
81
+ end
58
82
 
59
- def templates()
60
- if has_template?
61
- if pandocomatic['use-template'].is_a? Array
62
- pandocomatic['use-template']
83
+ # Does this PandocMetadata object use a template?
84
+ #
85
+ # @return [Boolean] true if it has a key 'use-template' among the
86
+ # pandocomatic template properties.
87
+ def has_template?()
88
+ has_pandocomatic? and pandocomatic.has_key? 'use-template' and not pandocomatic['use-template'].empty?
89
+ end
90
+
91
+ # Get all the templates of this PandocMetadata oject
92
+ #
93
+ # @return [Array] an array of templates used in this PandocMetadata
94
+ # object
95
+ def templates()
96
+ if has_template?
97
+ if pandocomatic['use-template'].is_a? Array
98
+ pandocomatic['use-template']
99
+ else
100
+ [pandocomatic['use-template']]
101
+ end
63
102
  else
64
- [pandocomatic['use-template']]
103
+ [""]
65
104
  end
66
- else
67
- [""]
68
105
  end
69
- end
70
-
71
- def template_name()
72
- if has_template? then
73
- pandocomatic['use-template']
74
- else
75
- ''
76
- end
77
- end
78
106
 
79
- # TODO: allow a pandoc block outside a pandocomatic block to make
80
- # pandocomatic work like paru's do-pandoc.rb.
107
+ # Get the used template's name
108
+ #
109
+ # @return [String] the name of the template used, if any, "" otherwise.
110
+ def template_name()
111
+ if has_template? then
112
+ pandocomatic['use-template']
113
+ else
114
+ ''
115
+ end
116
+ end
117
+
118
+ # Does this PandocMetadata object have a pandocomatic property?
119
+ #
120
+ # @return [Boolean] True if this PandocMetadata object has a Hash
121
+ # property named "pandocomatic_". False otherwise.
122
+ #
123
+ # Note. For backward compatibility with older versions of
124
+ # pandocomatic, properties named "pandocomatic" (without the trailing
125
+ # underscore) are also accepted.
126
+ def has_pandocomatic?()
127
+ config = nil
128
+ if has_key? 'pandocomatic' or has_key? 'pandocomatic_'
129
+ config = self['pandocomatic'] if has_key? 'pandocomatic'
130
+ config = self['pandocomatic_'] if has_key? 'pandocomatic_'
131
+ end
132
+ config.is_a? Hash
133
+ end
81
134
 
82
- def has_pandoc_options?()
83
- has_pandocomatic? and pandocomatic.has_key? 'pandoc'
84
- end
135
+ # Get the pandoc options for this PandocMetadata object
136
+ #
137
+ # @return [Hash] the pandoc options if there are any, an empty Hash
138
+ # otherwise.
139
+ def pandoc_options()
140
+ if has_pandoc_options? then
141
+ pandocomatic['pandoc']
142
+ else
143
+ {}
144
+ end
145
+ end
85
146
 
86
- def pandoc_options()
87
- if has_pandoc_options? then
88
- pandocomatic['pandoc']
89
- else
90
- {}
91
- end
92
- end
147
+ # Get the pandocomatic property of this PandocMetadata object
148
+ #
149
+ # @return [Hash] the pandocomatic property as a Hash, if any, an empty
150
+ # Hash otherwise.
151
+ def pandocomatic()
152
+ return self['pandocomatic'] if has_key? 'pandocomatic'
153
+ return self['pandocomatic_'] if has_key? 'pandocomatic_'
154
+ end
93
155
 
94
- def has_pandocomatic?()
95
- config = nil
96
- if has_key? 'pandocomatic' or has_key? 'pandocomatic_'
97
- config = self['pandocomatic'] if has_key? 'pandocomatic'
98
- config = self['pandocomatic_'] if has_key? 'pandocomatic_'
99
- end
100
- config.is_a? Hash
101
- end
156
+ # Does this PandocMetadata object has a pandoc options property?
157
+ #
158
+ # @return [Boolean] True if there is a pandoc options property in this
159
+ # PandocMetadata object. False otherwise.
160
+ def has_pandoc_options?()
161
+ has_pandocomatic? and pandocomatic.has_key? 'pandoc'
162
+ end
102
163
 
103
- def pandocomatic()
104
- return self['pandocomatic'] if has_key? 'pandocomatic'
105
- return self['pandocomatic_'] if has_key? 'pandocomatic_'
106
164
  end
107
165
 
108
- end
109
-
110
166
  end
@@ -44,7 +44,7 @@ module Pandocomatic
44
44
  require_relative './command/convert_file_multiple_command.rb'
45
45
 
46
46
  class Pandocomatic
47
- VERSION = [0, 1, 4, 9]
47
+ VERSION = [0, 1, 4, 10]
48
48
  CONFIG_FILE = 'pandocomatic.yaml'
49
49
 
50
50
  def self.run(args)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pandocomatic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4.9
4
+ version: 0.1.4.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Huub de Beer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-12 00:00:00.000000000 Z
11
+ date: 2017-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: paru