wortsammler 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.
@@ -0,0 +1,747 @@
1
+ #
2
+ # This script converts the trace-References in a markdown file
3
+ # to hot references.
4
+ #
5
+ # usage prepareTracingInPandoc <infile> <format> <outfile>
6
+ #
7
+ # Traces are formatted according to [RS_DM_008].
8
+ #
9
+ # Trace itself becomes the target, uptraces are converted to references.
10
+ #
11
+ # Traces can also be referenced by
12
+ #
13
+ #
14
+ require 'rubygems'
15
+ require 'yaml'
16
+ require 'tmpdir'
17
+ require 'nokogiri'
18
+ require "rubyXL"
19
+
20
+
21
+ #require 'ruby-debug' #if not RUBY_PLATFORM=="i386-mingw32"
22
+
23
+ # TODO: make these patterns part of the configuration
24
+
25
+ ANY_ANCHOR_PATTERN = /<a\s+id=\"([^\"]+)\"\/>/
26
+ ANY_REF_PATTERN = /<a\s+href=\"#([^\"]+)\"\>([^<]*)<\/a>/
27
+
28
+ TRACE_ANCHOR_PATTERN = /\[(\w+_\w+_\w+)\](\s*\*\*)/
29
+ UPTRACE_REF_PATTERN = /\}\( ((\w+_\w+_\w+) (,\s*\w+_\w+_\w+)*)\)/x
30
+ TRACE_REF_PATTERN = /->\[(\w+_\w+_\w+)\]/
31
+
32
+ # filename
33
+ # heading
34
+ # level
35
+ # pages to include
36
+ # pageclearance
37
+ INCLUDE_PDF_PATTERN = /^\s+~~PDF\s+"(.+)" \s+ "(.+)" \s* (\d*) \s* (\d+-\d+)? \s* (clearpage|cleardoublepage)?~~/x
38
+
39
+ INCLUDE_MD_PATTERN = /^\s+~~MD\s+"(.+)" \s+ "(.+)" \s* (\d*) \s* (\d+-\d+)? \s* (clearpage|cleardoublepage)?~~/x
40
+
41
+ SNIPPET_PATTERN = /~~SN \s+ (\w+)~~/x
42
+
43
+
44
+ #
45
+ # This mixin convertes a file path to the os Path representation
46
+ # todo maybe replace this by a builtin ruby stuff such as "pathname"
47
+ #
48
+ class String
49
+ # convert the string to a path notation of the current operating system
50
+ def to_osPath
51
+ gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
52
+ end
53
+
54
+ # convert the string to a path notation of ruby.
55
+ def to_rubyPath
56
+ gsub(File::ALT_SEPARATOR || File::SEPARATOR, File::SEPARATOR)
57
+ end
58
+
59
+ # adding quotes around the string. Main purpose is to escape blanks
60
+ # in file paths.
61
+ def esc
62
+ "\"#{self}\""
63
+ end
64
+ end
65
+
66
+
67
+
68
+ #
69
+ # This class provides methods to tweak the reference according to the
70
+ # target document format
71
+ #
72
+ #
73
+ class ReferenceTweaker
74
+
75
+ #This attribute keeps the target format
76
+ attr_accessor :target, :log
77
+
78
+
79
+ private
80
+
81
+ # this prepares the reference in the target format
82
+ #
83
+ # :string: the Id of the referenced Traceable
84
+ def prepareTraceReferences(string)
85
+ result=string.gsub(/\s*/,"").split(",").map{|trace|
86
+ itrace = mkInternalTraceId(trace)
87
+ texTrace = mkTexTraceDisplay(trace)
88
+ if @target == "pdf" then
89
+ "\\hyperlink{#{itrace}}{#{texTrace}}"
90
+ else
91
+ "[#{trace}](\##{itrace})"
92
+ end
93
+ }
94
+ result.join(", ")
95
+ end
96
+
97
+
98
+ # this tweaks the reference-Id to be comaptible as TeX label
99
+ # private methd
100
+ def mkInternalTraceId(string)
101
+ string.gsub("_","-")
102
+ end
103
+
104
+ # this tweaks the reference-id to be displayed in TeX
105
+ # private method
106
+ def mkTexTraceDisplay(trace)
107
+ trace.gsub("_", "\\_")
108
+ end
109
+
110
+ public
111
+
112
+ # constructor
113
+ # :target: the target format
114
+ # in which the referneces shall be represented
115
+ #todo: improve logger approach
116
+ def initialize(target, logger=nil)
117
+ @target=target
118
+
119
+ @log=logger || $logger || nil
120
+
121
+ if @log == nil
122
+ @log = Logger.new(STDOUT)
123
+ @log.level = Logger::INFO
124
+ @log.datetime_format = "%Y-%m-%d %H:%M:%S"
125
+ @log.formatter = proc do |severity, datetime, progname, msg|
126
+ "#{datetime}: #{msg}\n"
127
+ end
128
+ end
129
+ end
130
+
131
+ # this does the postprocessing
132
+ # of the file
133
+ # in particluar handloe wortsammler's specific syntax.
134
+ def prepareFile(infile, outfile)
135
+
136
+ infileIo=File.new(infile)
137
+ text = infileIo.readlines.join
138
+ infileIo.close
139
+
140
+ #include pdf files
141
+
142
+ if @target == "pdf"
143
+ text.gsub!(INCLUDE_PDF_PATTERN){|m|
144
+
145
+ if $4
146
+ pages="[pages=#{$4}]"
147
+ else
148
+ pages=""
149
+ end
150
+
151
+ if $5
152
+ clearpage=$5
153
+ else
154
+ clearpage="cleardoublepage"
155
+ end
156
+
157
+ if $3.length > 0
158
+ level=$3
159
+ else
160
+ level=9
161
+ end
162
+
163
+ "\n\n\\#{clearpage}\n\\bookmark[level=#{level},page=\\thepage]{#{$2}}\n\\includepdf#{pages}{#{$1}}"
164
+ }
165
+ else #if not pdf then it gets a regular external link
166
+ text.gsub!(INCLUDE_PDF_PATTERN){|m|
167
+ "[#{$2}](#{$1})"
168
+ }
169
+ end
170
+
171
+ #inject the anchors for references to traces ->[traceid]
172
+ if @target == "pdf" then
173
+ text.gsub!(TRACE_ANCHOR_PATTERN){|m| "[#{$1}]#{$2}\\hypertarget{#{mkInternalTraceId($1)}}{}"}
174
+ else
175
+ text.gsub!(TRACE_ANCHOR_PATTERN){|m| "<a id=\"#{mkInternalTraceId($1)}\">[#{$1}]</a>#{$2}"}
176
+ end
177
+
178
+ #substitute arbitrary anchors for arbitrary targets <a id="">
179
+ if @target == "pdf" then
180
+ text.gsub!(ANY_ANCHOR_PATTERN){|m| "\\hypertarget{#{mkInternalTraceId($1)}}{}"}
181
+ else
182
+ # it is already html
183
+ end
184
+
185
+ #substitute arbitrary document internal references <a href=""></a>
186
+ if @target == "pdf" then
187
+ text.gsub!(ANY_REF_PATTERN){|m| "\\hyperlink{#{$1}}{#{mkTexTraceDisplay($2)}}"}
188
+ else
189
+ # it is already html
190
+ end
191
+
192
+ # substitute the uptrace references
193
+ text.gsub!(UPTRACE_REF_PATTERN){|m| "}(#{prepareTraceReferences($1)})"}
194
+
195
+ # substitute the informal trace references
196
+ text.gsub!(TRACE_REF_PATTERN){|m| "[#{prepareTraceReferences($1)}]"}
197
+
198
+ File.open(outfile, "w"){|f| f.puts(text)}
199
+ end
200
+ end
201
+
202
+
203
+
204
+ #
205
+ # This class handles the configuration of WortSammler framework
206
+ #
207
+
208
+ class ProoConfig
209
+ attr_reader :input, # An array with the input filenames
210
+ :outdir, # directory where to place the output files
211
+ :outname, # basis to determine the output files
212
+ :format, # array of output formats
213
+ :traceSortOrder, # Array of strings to determine the sort ord
214
+ :vars, # hash of variables for pandoc
215
+ :editions, # hash of editions for pandoc
216
+ :snippets, # Array of strings to determine snippet filenames
217
+ :upstream_tracefiles, # Array of strings to determine upstream tracefile names
218
+ :downstream_tracefile, # String to save downstram filename
219
+ :reqtracefile_base, # string to determine the requirements tracing results
220
+ :rootdir, # String directory of the configuration file
221
+ :stylefiles # Hash of stylefiles path to pandoc latex style file
222
+
223
+
224
+ # constructor
225
+ # @param [String] configFileName name of the configfile (without .yaml)
226
+ # @param [Symbol] configSelect Default configuration. If not specified
227
+ # the very first entry in the config file
228
+ # will apply.
229
+ # TODO: not yet implemented.
230
+ # @return [ProoConfig] instance
231
+ def initialize(configFileName, configSelect=nil)
232
+ begin
233
+ config = YAML.load(File.new(configFileName))
234
+ rescue Exception => e
235
+ unless File.exist?(configFileName) then
236
+ $log.error "config file not found '#{configFileName}'"
237
+ else
238
+ $log.error "config file could not be loaded '#{configFileName}'"
239
+ $log.error "reason '#{e.message}'"
240
+ end
241
+ exit(false)
242
+ end
243
+
244
+ basePath = File.dirname(configFileName)
245
+
246
+ # this makes an absolute path based on the absolute path
247
+ # of the configuration file
248
+ expand_path=lambda do |lf|
249
+ File.expand_path("#{basePath}/#{lf}")
250
+ end
251
+
252
+
253
+ #activeConfigs=config.select{|x| [x[:name]] & ConfigSelet}
254
+
255
+ selectedConfig=config.first
256
+ #TODO: check the config file
257
+ @input = selectedConfig[:input].map{|file| File.expand_path("#{basePath}/#{file}")}
258
+ @outdir = File.expand_path("#{basePath}/#{selectedConfig[:outdir]}")
259
+ @outname = selectedConfig[:outname]
260
+ @format = selectedConfig[:format]
261
+ @traceSortOrder = selectedConfig[:traceSortOrder]
262
+ @vars = selectedConfig[:vars] || {}
263
+ @editions = selectedConfig[:editions] || nil
264
+
265
+ @downstream_tracefile = selectedConfig[:downstream_tracefile] || nil
266
+
267
+ @reqtracefile_base = selectedConfig[:reqtracefile_base] #todo expand path
268
+
269
+ @upstream_tracefiles = selectedConfig[:upstream_tracefiles] || nil
270
+ @upstream_tracefiles = @upstream_tracefiles.map{|file| File.expand_path("#{basePath}/#{file}")} unless @upstream_tracefiles.nil?
271
+ @rootdir = basePath
272
+
273
+ stylefiles = selectedConfig[:stylefiles] || nil
274
+ if stylefiles.nil?
275
+ @stylefiles = {
276
+ :latex => expand_path.call("../ZSUPP_Styles/default.latex"),
277
+ :docx => expand_path.call("../ZSUPP_Styles/default.docx"),
278
+ :html => expand_path.call("../ZSUPP_Styles/default.css")
279
+ }
280
+ else
281
+ @stylefiles = stylefiles.map{ |key,value| {key => expand_path.call(value)} }.reduce(:merge)
282
+ end
283
+
284
+ snippets = selectedConfig[:snippets]
285
+ if snippets.nil?
286
+ @snippets = nil
287
+ else
288
+ @snippets = snippets.map{|file| File.expand_path("#{basePath}/#{file}")}
289
+ end
290
+ end
291
+
292
+
293
+ end
294
+
295
+
296
+
297
+ #
298
+ # This class provides the major functionalites
299
+ # Note that it is called PandocBeautifier for historical reasons
300
+ # provides methods to Process a pandoc file
301
+ #
302
+
303
+ class PandocBeautifier
304
+
305
+ attr_accessor :log
306
+
307
+ # the constructor
308
+ # @param [Logger] logger logger object to be applied.
309
+ # if none is specified, a default logger
310
+ # will be implemented
311
+
312
+ def initialize(logger=nil)
313
+
314
+ @view_pattern = /~~ED((\s*(\w+))*)~~/
315
+ # @view_pattern = /<\?ED((\s*(\w+))*)\?>/
316
+ @tempdir = Dir.mktmpdir
317
+
318
+ @log=logger || $logger || nil
319
+
320
+ if @log == nil
321
+ @log = Logger.new(STDOUT)
322
+ @log.level = Logger::INFO
323
+ @log.datetime_format = "%Y-%m-%d %H:%M:%S"
324
+ @log.formatter = proc do |severity, datetime, progname, msg|
325
+ "#{datetime}: #{msg}\n"
326
+ end
327
+
328
+ end
329
+ end
330
+
331
+ # perform the beautify
332
+ # * process the file with pandoc
333
+ # * revoke some quotes introduced by pandoc
334
+ # @param [String] file the name of the file to be beieautified
335
+ def beautify(file)
336
+
337
+ @log.debug(" Cleaning: \"#{file}\"")
338
+
339
+ docfile = File.new(file)
340
+ olddoc = docfile.readlines.join
341
+ docfile.close
342
+
343
+ # process the file in pandoc
344
+ cmd="pandoc -s #{file.esc} -f markdown -t markdown --atx-headers --reference-links "
345
+ newdoc = `#{cmd}`
346
+ @log.debug "beautify #{file.esc}: #{$?}"
347
+ @log.debug(" finished: \"#{file}\"")
348
+
349
+ # tweak the quoting
350
+ if $?.success? then
351
+ # do this twice since the replacement
352
+ # does not work on e.g. 2\_3\_4\_5.
353
+ #
354
+ newdoc.gsub!(/(\w)\\_(\w)/, '\1_\2')
355
+ newdoc.gsub!(/(\w)\\_(\w)/, '\1_\2')
356
+
357
+ # fix more quoting
358
+ newdoc.gsub!('-\\>[', '->[')
359
+
360
+ # (RS_Mdc)
361
+ # TODO: fix Table width toggles sometimes
362
+ if (not olddoc == newdoc) then ##only touch the file if it is really changed
363
+ File.open(file, "w"){|f| f.puts(newdoc)}
364
+ File.open(file+".bak", "w"){|f| f.puts(olddoc)} # (RS_Mdc_) # remove this if needed
365
+ @log.debug(" cleaned: \"#{file}\"")
366
+ else
367
+ @log.debug("was clean: \"#{file}\"")
368
+ end
369
+ #TODO: error handling here
370
+ else
371
+ @log.error("error calling pandoc - please watch the screen output")
372
+ end
373
+ end
374
+
375
+
376
+ # this replaces the text snippets in files
377
+ def replace_snippets_in_file(infile, snippets)
378
+ input_data = File.open(infile){|f| f.readlines.join}
379
+ output_data=input_data.clone
380
+
381
+ @log.debug("replacing snippets in #{infile}")
382
+
383
+ replace_snippets_in_text(output_data, snippets)
384
+
385
+ if (not input_data == output_data)
386
+ File.open(infile, "w"){|f| f.puts output_data}
387
+ end
388
+ end
389
+
390
+ # this replaces the snippets in a text
391
+ def replace_snippets_in_text(text, snippets)
392
+ changed=false
393
+ text.gsub!(SNIPPET_PATTERN){|m|
394
+ replacetext=snippets[$1.to_sym]
395
+ if replacetext
396
+ changed=true
397
+ @log.debug("replaced snippet #{$1} with #{replacetext}")
398
+ else
399
+ replacetext=m
400
+ @log.warn("Snippet not found: #{$1}")
401
+ end
402
+ replacetext
403
+ }
404
+ #recursively process nested snippets
405
+ #todo: this approach might rais undefined snippets twice if there are defined and undefined ones
406
+ replace_snippets_in_text(text, snippets) if changed==true
407
+ end
408
+
409
+
410
+ #
411
+ # Ths determines the view filter
412
+ #
413
+ # @param [String] line - the current input line
414
+ # @param [String] view - the currently selected view
415
+ #
416
+ # @return true/false if a view-command is found, else nil
417
+ def get_filter_command(line, view)
418
+ r = line.match(@view_pattern)
419
+
420
+ if not r.nil?
421
+ found = r[1].split(" ")
422
+ result = (found & [view, "all"].flatten).any?
423
+ else
424
+ result = nil
425
+ end
426
+
427
+ result
428
+ end
429
+
430
+ #
431
+ # This filters the document according to the target audience
432
+ #
433
+ # @param [String] inputfile name of inputfile
434
+ # @param [String] outputfile name of outputfile
435
+ # @param [String] view - name of intended view
436
+
437
+ def filter_document_variant(inputfile, outputfile, view)
438
+
439
+ input_data = File.open(inputfile){|f| f.readlines}
440
+
441
+ output_data = Array.new
442
+ is_active = true
443
+ input_data.each{|l|
444
+ switch=self.get_filter_command(l, view)
445
+ l.gsub!(@view_pattern, "")
446
+ is_active = switch unless switch.nil?
447
+ @log.debug "select edtiion #{view}: #{is_active}: #{l.strip}"
448
+
449
+ output_data << l if is_active
450
+ }
451
+
452
+ File.open(outputfile, "w"){|f| f.puts output_data.join }
453
+ end
454
+
455
+ #
456
+ # This filters the document according to the target audience
457
+ #
458
+ # @param [String] inputfile name of inputfile
459
+ # @param [String] outputfile name of outputfile
460
+ # @param [String] view - name of intended view
461
+
462
+ def process_debug_info(inputfile, outputfile, view)
463
+
464
+ input_data = File.open(inputfile){|f| f.readlines }
465
+
466
+ output_data = Array.new
467
+
468
+ input_data.each{|l|
469
+ l.gsub!(@view_pattern){|p|
470
+ if $1.strip == "all" then
471
+ color="black"
472
+ else
473
+ color="red"
474
+ end
475
+
476
+ "\\color{#{color}}\\rule{2cm}{0.5mm}\\marginpar{#{$1.strip}}"
477
+
478
+ }
479
+
480
+ l.gsub!(/todo:|TODO:/){|p| "#{p}\\marginpar{TODO}"}
481
+
482
+ output_data << l
483
+ }
484
+
485
+ File.open(outputfile, "w"){|f| f.puts output_data.join }
486
+ end
487
+
488
+
489
+ # This compiles the input documents to one single file
490
+ # it also beautifies the input files
491
+ #
492
+ # @param [Array of String] input - the input files to be processed in the given sequence
493
+ # @param [String] output - the the name of the output file
494
+ def collect_document(input, output)
495
+ inputs=input.map{|xx| xx.esc.to_osPath }.join(" ") # qoute cond combine the inputs
496
+
497
+ #now combine the input files
498
+ @log.info("combining the input files")
499
+ cmd="pandoc -s -S -o #{output} --ascii #{inputs}" # note that inputs is already quoted
500
+ system(cmd)
501
+ if $?.success? then
502
+ PandocBeautifier.new().beautify(output)
503
+ end
504
+ end
505
+
506
+ #
507
+ # This loads snippets from xlsx file
508
+ # @param file [String] Filename of the xlsx file
509
+ #
510
+ # @return [Hash] a hash with the snippets
511
+ def load_snippets_from_xlsx(file)
512
+ temp_filename = "#{@tempdir}/snippett.xlsx"
513
+ FileUtils::copy(file, temp_filename)
514
+ wb=RubyXL::Parser.parse(temp_filename)
515
+ result={}
516
+ wb.first.each{|row|
517
+ key, the_value = row
518
+ unless key.nil?
519
+ unless the_value.nil?
520
+ result[key.value.to_sym] = resolve_xml_entities(the_value.value) rescue ""
521
+ end
522
+ end
523
+ }
524
+ result
525
+ end
526
+
527
+ #
528
+ # this resolves xml entities in Text (lt, gt, amp)
529
+ # @param [String] text with entities
530
+ # @return [String] text with replaced entities
531
+ def resolve_xml_entities(text)
532
+ result=text
533
+ result.gsub!("&lt;", "<")
534
+ result.gsub!("&gt;", ">")
535
+ result.gsub!("&amp;", "&")
536
+ result
537
+ end
538
+
539
+ #
540
+ # This generates the final document
541
+ # @param [Array of String] input the input files to be processed in the given sequence
542
+ # @param [String] outdir the output directory
543
+ # @param [String] outname the base name of the output file. It is a basename in case the
544
+ # output format requires multiple files
545
+ # @param [Array of String] format list of formats which shall be generated.
546
+ # supported formats: "pdf", "latex", "html", "docx", "rtf", txt
547
+ # @param [Hash] vars - the variables passed to pandoc
548
+ # @param [Hash] editions - the editions to process; default nil - no edition processing
549
+ # @param [Array of String] snippetfiles the list of files containing snippets
550
+ def generateDocument(input, outdir, outname, format, vars, editions=nil, snippetfiles=nil, config=nil)
551
+
552
+
553
+ # combine the input files
554
+
555
+ temp_filename = "#{@tempdir}/x.md".to_osPath
556
+ collect_document(input, temp_filename)
557
+
558
+ # process the snippets
559
+
560
+ if not snippetfiles.nil?
561
+ snippets={}
562
+ snippetfiles.each{|f|
563
+ if File.exists?(f)
564
+ type=File.extname(f)
565
+ case type
566
+ when ".yaml"
567
+ x=YAML.load(File.new(f))
568
+ when ".xlsx"
569
+ x=load_snippets_from_xlsx(f)
570
+ else
571
+ @log.error("Unsupported File format for snipptets: #{type}")
572
+ x={}
573
+ end
574
+ snippets.merge!(x)
575
+ else
576
+ @log.error("Snippet file not found: #{f}")
577
+ end
578
+ }
579
+
580
+ replace_snippets_in_file(temp_filename, snippets)
581
+ end
582
+
583
+
584
+ if editions.nil?
585
+ # there are no editions
586
+ render_document(temp_filename, outdir, outname, format, vars, config)
587
+ else
588
+ # process the editions
589
+ editions.each{|edition_name, properties|
590
+ edition_out_filename = "#{outname}_#{properties[:filepart]}"
591
+ edition_temp_filename = "#{@tempdir}/#{edition_out_filename}.md"
592
+ vars[:title] = properties[:title]
593
+
594
+ if properties[:debug]
595
+ process_debug_info(temp_filename, edition_temp_filename, edition_name.to_s)
596
+ lvars=vars.clone
597
+ lvars[:linenumbers] = "true"
598
+ render_document(edition_temp_filename, outdir, edition_out_filename, ["pdf", "latex"], lvars, config)
599
+ else
600
+ filter_document_variant(temp_filename, edition_temp_filename, edition_name.to_s)
601
+ render_document(edition_temp_filename, outdir, edition_out_filename, format, vars, config)
602
+ end
603
+ }
604
+ end
605
+ end
606
+
607
+
608
+ #
609
+ # render a single file
610
+ # @param input [String] path to the inputfile
611
+ # @param outdir [String] path to the output directory
612
+ # @param format [Array of String] formats
613
+ #
614
+ # @return [nil] no useful return value
615
+ def render_single_document(input, outdir, format)
616
+ outname=File.basename(input, ".*")
617
+ render_document(input, outdir, outname, format, Hash.new)
618
+ end
619
+ #
620
+ # This renders the final document
621
+ # @param [String] input the input file
622
+ # @param [String] outdir the output directory
623
+ # @param [String] outname the base name of the output file. It is a basename in case the
624
+ # output format requires multiple files
625
+ # @param [Array of String] format list of formats which shall be generated.
626
+ # supported formats: "pdf", "latex", "html", "docx", "rtf", txt
627
+ # @param [Hash] vars - the variables passed to pandoc
628
+
629
+ # @param config [ProoConfig] the entire config object (for future extensions)
630
+ # @return nil
631
+
632
+ def render_document(input, outdir, outname, format, vars, config=nil)
633
+
634
+
635
+ #TODO: Clarify the following
636
+ # on Windows, Tempdir contains a drive letter. But drive letter
637
+ # seems not to work in pandoc -> pdf if the path separator ist forward
638
+ # slash. There are two options to overcome this
639
+ #
640
+ # 1. set tempdir such that it does not contain a drive letter
641
+ # 2. use Dir.mktempdir but ensure that all provided file names
642
+ # use the platform specific SEPARATOR
643
+ #
644
+ # for whatever Reason, I decided for 2.
645
+
646
+ tempfile = input
647
+ tempfilePdf = "#{@tempdir}/x.TeX.md".to_osPath
648
+ tempfileHtml = "#{@tempdir}/x.html.md".to_osPath
649
+ outfilePdf = "#{outdir}/#{outname}.pdf".to_osPath
650
+ outfileDocx = "#{outdir}/#{outname}.docx".to_osPath
651
+ outfileHtml = "#{outdir}/#{outname}.html".to_osPath
652
+ outfileRtf = "#{outdir}/#{outname}.rtf".to_osPath
653
+ outfileLatex = "#{outdir}/#{outname}.latex".to_osPath
654
+ outfileText = "#{outdir}/#{outname}.txt".to_osPath
655
+ outfileSlide = "#{outdir}/#{outname}.slide.html".to_osPath
656
+
657
+
658
+ localvars=vars.clone
659
+
660
+ #todo: make config required, so it can be reduced to the else part
661
+ if config.nil? then
662
+ latexStyleFile = File.dirname(File.expand_path(__FILE__))+"/../../resources/default.latex"
663
+ latexStyleFile = File.expand_path(latexStyleFile).to_osPath
664
+ else
665
+ latexStyleFile = config.stylefiles[:latex]
666
+ end
667
+
668
+
669
+
670
+ vars_string=localvars.map{|key, value| "-V #{key}=#{value.esc}"}.join(" ")
671
+
672
+ @log.info("rendering #{outname} as [#{format.join(', ')}]")
673
+
674
+ begin
675
+
676
+ if format.include?("pdf") then
677
+ ReferenceTweaker.new("pdf").prepareFile(tempfile, tempfilePdf)
678
+
679
+ cmd="pandoc -S #{tempfilePdf.esc} --toc --standalone --latex-engine xelatex --number-sections #{vars_string}" +
680
+ " --template #{latexStyleFile.esc} --ascii -o #{outfilePdf.esc}"
681
+ `#{cmd}`
682
+ end
683
+
684
+ if format.include?("latex") then
685
+
686
+ ReferenceTweaker.new("pdf").prepareFile(tempfile, tempfilePdf)
687
+
688
+ cmd="pandoc -S #{tempfilePdf.esc} --toc --standalone --latex-engine xelatex --number-sections #{vars_string}" +
689
+ " --template #{latexStyleFile.esc} --ascii -o #{outfileLatex.esc}"
690
+ `#{cmd}`
691
+ end
692
+
693
+ if format.include?("html") then
694
+ #todo: handle css
695
+ ReferenceTweaker.new("html").prepareFile(tempfile, tempfileHtml)
696
+
697
+ cmd="pandoc -S #{tempfileHtml.esc} --toc --standalone --self-contained --ascii --number-sections #{vars_string}" +
698
+ " -o #{outfileHtml.esc}"
699
+
700
+ `#{cmd}`
701
+ end
702
+
703
+ if format.include?("docx") then
704
+ #todo: handle style file
705
+ ReferenceTweaker.new("html").prepareFile(tempfile, tempfileHtml)
706
+
707
+ cmd="pandoc -S #{tempfileHtml.esc} --toc --standalone --self-contained --ascii --number-sections #{vars_string}" +
708
+ " -o #{outfileDocx.esc}"
709
+ `#{cmd}`
710
+ end
711
+
712
+ if format.include?("rtf") then
713
+
714
+ ReferenceTweaker.new("html").prepareFile(tempfile, tempfileHtml)
715
+
716
+ cmd="pandoc -S #{tempfileHtml.esc} --toc --standalone --self-contained --ascii --number-sections #{vars_string}" +
717
+ " -o #{outfileRtf.esc}"
718
+ `#{cmd}`
719
+ end
720
+
721
+ if format.include?("txt") then
722
+
723
+ ReferenceTweaker.new("pdf").prepareFile(tempfile, tempfileHtml)
724
+
725
+ cmd="pandoc -S #{tempfileHtml.esc} --toc --standalone --self-contained --ascii --number-sections #{vars_string}" +
726
+ " -t plain -o #{outfileText.esc}"
727
+ `#{cmd}`
728
+ end
729
+
730
+ if format.include?("slide") then
731
+
732
+ ReferenceTweaker.new("slide").prepareFile(tempfile, tempfilePdf)
733
+ #todo: hanlde stylefile
734
+ cmd="pandoc -S #{tempfileHtml.esc} --toc --standalone --number #{vars_string}" +
735
+ " --ascii -t dzslides --slide-level 2 -o #{outfileSlide.esc}"
736
+ `#{cmd}`
737
+ end
738
+ rescue
739
+
740
+ @log.error "failed to perform #{cmd}"
741
+ #TODO make a try catch block kere
742
+
743
+ end
744
+ nil
745
+ end
746
+
747
+ end