Class: Hyla::Commands::Generate

Inherits:
Hyla::Command show all
Defined in:
lib/hyla/commands/generate.rb

Class Method Summary collapse

Class Method Details

.add_tag_to_index_file(index_file) ⇒ Object

Add snippet tag index file



567
568
569
570
571
# File 'lib/hyla/commands/generate.rb', line 567

def self.add_tag_to_index_file(index_file)
  text = File.read(index_file)
  replace = text.gsub!('[]','[tag=' + Configuration::SNIPPET_TAG + ']')
  File.open(index_file, "w") { |file| file.puts replace }
end

.asciidoc_to_html(source, destination, extensions, options) ⇒ Object

Call Asciidoctor.render function



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/hyla/commands/generate.rb', line 147

def self.asciidoc_to_html(source, destination, extensions, options)

  # Move to Source directory & Retrieve Asciidoctor files to be processed
  source = File.expand_path source
  @destination = File.expand_path destination

  Hyla.logger.info ">>       Source dir: #{source}"
  Hyla.logger.info ">>  Destination dir: #{@destination}"

  # Exit if source directory does not exist
  if !Dir.exist? source
    Hyla.logger.error ">> Source directory does not exist"
    exit(1)
  end

  # Move to source directory
  Dir.chdir(source)
  current_dir = Dir.pwd
  Hyla.logger.info ">>       Current dir: #{current_dir}"

  #
  # Backup Asciidoctor attributes
  # Strange issue discovered
  #
  @attributes_bk = options[:attributes]

  # Delete destination directory (generated_content, ...)
  # FileUtils.rm_rf(Dir.glob(@destination))

  # Search for files using extensions parameter and do the rendering
  adoc_file_paths = []
  Find.find(current_dir) do |f|
    if f =~ /.*\.(?:#{extensions})$/

      path_to_source = Pathname.new(source)
      path_to_adoc_file = Pathname.new(f)
      relative_path = path_to_adoc_file.relative_path_from(path_to_source).to_s
      Hyla.logger.debug ">>       Relative path: #{relative_path}"
      adoc_file_paths << relative_path

      # Get asciidoc file name
      file_name_processed = path_to_adoc_file.basename

      #
      # Create destination dir relative to the path calculated
      #
      html_dir = @destination + '/' + File.dirname(relative_path)
      Hyla.logger.info ">>        Dir of html: #{html_dir}"
      FileUtils.mkdir_p html_dir

      # Copy Fonts
      # TODO : Verify if we still need to do that as the FONTS liberation have been moved
      # TODO : under local lib directory of revealjs
      # self.cp_resources_to_dir(File.dirname(html_dir), 'fonts')

      # Copy Resources for Slideshow
      case options[:backend]
        when 'deckjs'
          # Copy css, js files to destination directory
          self.cp_resources_to_dir(File.dirname(html_dir), 'deck.js')
        when 'revealjs'
          self.cp_resources_to_dir(File.dirname(html_dir), 'revealjs')
      end

      #
      # Check if companion parameter is defined
      # as we have to generate a new AllSlides.txt file
      # containing as tag name this value [snippet]
      #
      if options[:snippet_content] == true
        Hyla.logger.info "Snippet content has been selected. Index file will be modified and modifications will be reverted after asciidoctor processing"
        add_tag_to_index_file(f)
      end

      #
      # Render asciidoc to HTML
      #
      Hyla.logger.info ">> File to be rendered : #{file_name_processed}"

      #
      # Convert asciidoc file name to html file name
      #
      html_file_name = file_name_processed.to_s.gsub(/.adoc$|.ad$|.asciidoc$|.index$|.txt$/, '.html')
      options[:to_dir] = html_dir
      options[:to_file] = html_file_name
      options[:attributes] = @attributes_bk
      Asciidoctor.render_file(f, options)

      #
      # Check if companion parameter is defined
      # as we have to generate a new AllSlides.txt file
      # containing as tag name this value [companion]
      #
      if options[:snippet_content] == true
        remove_tag_from_index_file(f)
      end

    end
  end

  # No asciidoc files retrieved
  if adoc_file_paths.empty?
    Hyla.logger.info "     >>   No asciidoc files retrieved."
    exit(1)
  end

end

.backend_dir(backend) ⇒ Object

Return backend directory containing templates (haml, slim)



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/hyla/commands/generate.rb', line 131

def self.backend_dir(backend)
  case backend
    when 'deckjs'
      return [Configuration::backends, 'haml', 'deckjs'] * '/'
    when 'revealjs'
      return [Configuration::backends, 'slim', 'revealjs'] * '/'
    when 'html5'
      return [Configuration::backends, 'slim', 'html5'] * '/'
    else
      return [Configuration::backends, 'slim', 'html5'] * '/'
  end
end

.check_mandatory_option?(key, value) ⇒ Boolean

Check mandatory options

Returns:

  • (Boolean)


585
586
587
588
589
590
591
592
# File 'lib/hyla/commands/generate.rb', line 585

def self.check_mandatory_option?(key, value)
  if value.nil? or value.empty?
    Hyla.logger.warn "Mandatory option missing: #{key}"
    exit(1)
  else
    true
  end
end

.check_slash_end(out_dir) ⇒ Object

Add ‘/’ at the end of the target path if the target path provided doesn’t contain it



535
536
537
538
539
540
541
542
543
# File 'lib/hyla/commands/generate.rb', line 535

def self.check_slash_end(out_dir)
  last_char = out_dir.to_s[-1, 1]
  Hyla.logger.info '>> Last char : ' + last_char
  if !last_char.equal? '/\//'
    temp_dir = out_dir.to_s
    out_dir = temp_dir + '/'
  end
  out_dir
end

.check_style(style) ⇒ Object

CSS Style to be used Default is : asciidoctor.css



259
260
261
262
263
264
265
# File 'lib/hyla/commands/generate.rb', line 259

def self.check_style(style)
  if !style.nil?
    css_file = [style, '.css'].join()
  else
    css_file = 'asciidoctor.css'
  end
end

.cp_resources_to_dir(path, resource) ⇒ Object

Copy resources to target dir



269
270
271
272
273
# File 'lib/hyla/commands/generate.rb', line 269

def self.cp_resources_to_dir(path, resource)
  source = [Configuration::resources, resource] * '/'
  destination = [path, resource] * '/'
  FileUtils.cp_r source, destination
end

.create_asset_directory(assets = []) ⇒ Object

Create Asset Directory



516
517
518
519
520
# File 'lib/hyla/commands/generate.rb', line 516

def self.create_asset_directory(assets = [])
  assets.each do |asset|
    Dir.mkdir(asset) if !Dir.exist? asset
  end
end

.create_index_file(file_name, level) ⇒ Object

Create ascidoc index file containing references to asciidoc files part of a module



549
550
551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/hyla/commands/generate.rb', line 549

def self.create_index_file(file_name, level)
  n_file_name = file_name + Configuration::INDEX_SUFFIX
  index_file = File.new(n_file_name, 'w')

  index_file.puts Configuration::HEADER_INDEX
  index_file.puts "\n"
  # TODO - until now we cannot use level 0 for parent/children files
  # even if doctype: book
  # This is why the level for each index file title is '=='
  index_file.puts '== ' + file_name
  index_file.puts "\n"

  index_file
end

.extract_file_names(file_name, destination) ⇒ Object

Extract files names from a file containing include

directive



597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
# File 'lib/hyla/commands/generate.rb', line 597

def self.extract_file_names(file_name, destination)

  result = []
  f = File.open(file_name, 'r')
  matches = f.grep(Configuration::IncludeDirectiveRx)

  if matches

    matches.each do |record|
      # Extract string after include::
      matchdata = record.match(/^include::(.+)/)

      if matchdata

        data = matchdata[1]
        # Remove []
        name = data.to_s.gsub(/[\[\]]/, '').strip

        # Rename file to .html
        name = name.gsub(/ad$/, 'html')
        file_name = [destination, name] * '/'
        file_path = File.expand_path file_name
        result << file_path
      end
    end
  end
  f.close
  return result
end

.html_to_pdf(file_name, source, destination, footer_text, header_html_path, cover_path) ⇒ Object

#

# Generate PDF
#
def self.html_to_pdf(source, destination, html_file_name)
  file_path = [source, html_file_name] * '/'
  html_file = File.new(file_path)
  kit = PDFKit.new(html_file,
                   :page_size => 'A4',
                   :toc => true,
                   :page_offset => 1,
                   :footer_center => 'Page [page]')

  # Create destination directory if it does not exist
  unless File.directory?(destination)
    FileUtils.mkdir_p(destination)
  end

  # Save PDF to a file
  pdf_file_name = [destination, html_file_name.sub(/html|htm/, 'pdf')] * '/'
  kit.to_file(pdf_file_name)
  Hyla.logger.info ">> PDF file generated and saved : #{pdf_file_name} "
end


447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
# File 'lib/hyla/commands/generate.rb', line 447

def self.html_to_pdf(file_name, source, destination, footer_text, header_html_path, cover_path)

  @cover_path = cover_path
  destination= File.expand_path destination
  pdf_file = [destination, "result.pdf"] * '/'
  wkhtml_cmd = "wkhtmltopdf"
  size = 'A4'

  # pdf_file_name = [destination, html_file_name.sub(/html|htm/, 'pdf')] * '/'

  list_of_files = ""

  unless File.directory?(destination)
    FileUtils.mkdir_p(destination)
  end

  if file_name.nil? || file_name.empty?
    filter = [source] * '/' + "*.html"
    files = Dir[filter]

    files.each do |file|
      file_name = File.basename file
      next if file_name.downcase.include?('assessments')
      next if file_name.downcase.include?('labinstructions')
      next if file_name.downcase.include?('title')
      next if file_name.downcase.include?('cover')
      file = File.expand_path file
      list_of_files = list_of_files + " " + file
    end
  else
    #
    # If the file passed as parameter has extension name equal to txt, then we will extract the file names
    # whenever we have a include:: directive in the file
    #
    extension_name = File.extname file_name

    case extension_name
      when '.txt'
        file_to_processed = [File.expand_path(Dir.getwd), file_name] * '/'
        result = self.extract_file_names(file_to_processed, source)

        result.each do | file_path |
          if file_path.downcase.include?('title') || file_path.downcase.include?('cover')
            @cover_path = file_path
            next
          end
          list_of_files = list_of_files + " " + file_path
        end

      else
        list_of_files = [File.expand_path(source), file_name] * '/'
    end
  end

  wkhtml_cmd.concat " #{list_of_files} #{pdf_file}"
  wkhtml_cmd.concat " --margin-top '18mm' --header-html '#{header_html_path}'" if header_html_path
  wkhtml_cmd.concat " --margin-bottom '10mm'  --footer-center '#{footer_text}'" if footer_text
  wkhtml_cmd.concat " --cover '#@cover_path'" if @cover_path
  wkhtml_cmd.concat " --page-size #{size}"
  Hyla.logger.debug "c #{wkhtml_cmd}"

  Dir.chdir(source) do
    system "#{wkhtml_cmd}"
  end
end

.process(args, options = {}) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/hyla/commands/generate.rb', line 6

def self.process(args, options = {})

  rendering = options[:rendering] if self.check_mandatory_option?('-r / --rendering', options[:rendering])

  case rendering

    when 'toc2adoc'

      Hyla.logger.info "Rendering : Table of Content to Asciidoc"
      self.check_mandatory_option?('-t / --toc', options[:toc])
      self.check_mandatory_option?('-d / --destination', options[:destination])

      @toc_file = options[:toc]
      @out_dir = options[:destination]
      @project_name = options[:project_name] if options[:project_name]
      @project_name = 'My Project' if !options[:project_name]

      self.table_of_content_to_asciidoc(@toc_file, @out_dir, @project_name)

    when 'adoc2html'

      Hyla.logger.info "Rendering : Asciidoc to HTML"
      self.check_mandatory_option?('-s / --source', options[:source])
      self.check_mandatory_option?('-d / --destination', options[:destination])

      @destination = options[:destination]
      @source = options[:source]

      # Check Style to be used
      new_asciidoctor_option = {
          :template_dirs => [self.backend_dir(options[:backend])],
          :attributes => {
              'stylesheet' => self.check_style(options[:style])
          }
      }

      merged_options = Configuration[options].deep_merge(new_asciidoctor_option)

      extensions = 'adoc|ad|asciidoc'

      self.asciidoc_to_html(@source, @destination, extensions, merged_options)

    when 'index2html'
      Hyla.logger.info "Rendering : Asciidoctor Indexed Files to HTML"
      self.check_mandatory_option?('-s / --source', options[:source])
      self.check_mandatory_option?('-d / --destination', options[:destination])

      @destination = options[:destination]
      @source = options[:source]

      new_asciidoctor_option = {
          :template_dirs => [self.backend_dir(options[:backend])],
          :attributes => {
              'stylesheet' => self.check_style(options[:style])
          }
      }

      merged_options = Configuration[options].deep_merge(new_asciidoctor_option)

      # Extension(s) of the files containing include directives
      extensions = 'txt'

      self.asciidoc_to_html(@source, @destination, extensions, merged_options)

    when 'html2pdf'

      Hyla.logger.info "Rendering : Generate PDF from HTML file"

      source_dir = options[:source] if self.check_mandatory_option?('-s / --source', options[:source])
      out_dir = options[:destination] if self.check_mandatory_option?('-d / --destination', options[:destination])

      file_name = options[:file]
      cover_path ||= options[:cover_path]
      header_html_path = options[:header_html_path]
      footer_text = options[:footer_text]

      self.html_to_pdf(file_name, source_dir, out_dir, footer_text, header_html_path, cover_path)

    when 'cover2png'

      Hyla.logger.info "Rendering : Generate Cover HTML page & picture - format png"

      out_dir = options[:destination] if self.check_mandatory_option?('-d / --destination', options[:destination])
      file_name = options[:cover_file]
      image_name = options[:cover_image]

      # Configure Slim engine
      slim_file = Configuration::cover_template
      slim_tmpl = File.read(slim_file)
      template = Slim::Template.new(:pretty => true) { slim_tmpl }

      # Do the Rendering HTML
      parameters = {:course_name => options[:course_name],
                    :module_name => options[:module_name],
                    :image_path => options[:image_path]}
      res = template.render(Object.new, parameters)

      unless Dir.exist? out_dir
        FileUtils.mkdir_p out_dir
      end

      Dir.chdir(out_dir) do
        out_file = File.new(file_name, 'w')
        out_file.puts res
        out_file.puts "\n"

        # Do the Rendering Image
        kit = IMGKit.new(res, quality: 90, width: 950, height: 750)
        kit.to_img(:png)
        kit.to_file(image_name)

        # Convert HTML to Image
        # system ("wkhtmltoimage -f 'png' #{file_name} #{image_name}")
      end

    else
      Hyla.logger.error ">> Unknow rendering"
      exit(1)
  end
end

.remove_special_chars(pos, text) ⇒ Object

Remove space, dot from a String



525
526
527
528
529
# File 'lib/hyla/commands/generate.rb', line 525

def self.remove_special_chars(pos, text)
  return text[pos, text.length].strip.gsub(/\s/, '_')
  .gsub('.', '')
  .gsub('&', '')
end

.remove_tag_from_index_file(index_file) ⇒ Object

Remove snippet tag from index file



576
577
578
579
580
# File 'lib/hyla/commands/generate.rb', line 576

def self.remove_tag_from_index_file(index_file)
  text = File.read(index_file)
  replace = text.gsub!('[tag=' + Configuration::SNIPPET_TAG + ']', '[]')
  File.open(index_file, "w") { |file| file.puts replace }
end

.table_of_content_to_asciidoc(toc_file, out_dir, project_name) ⇒ Object

Method parsing TOC File to generate directories and files Each Level 1 entry will become a directory and each Level 2 a file created under the directory

Parameters:

  • toc_file (File Containing the Table of Content)
  • out_dir (Directory where asciidoc files will be generated)
  • project_name (Project name used to create parent of index files)


284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# File 'lib/hyla/commands/generate.rb', line 284

def self.table_of_content_to_asciidoc(toc_file, out_dir, project_name)

  Hyla.logger.info '>> Project Name : ' + project_name + ' <<'

  # Open file & parse it
  f = File.open(toc_file, 'r')

  # Expand File Path
  @out_dir = File.expand_path out_dir

  #
  # Create destination directory if it does not exist
  unless Dir.exist? @out_dir
    FileUtils.mkdir_p @out_dir
  end

  # Copy YAML Config file
  FileUtils.cp_r [Configuration::templates, Configuration::YAML_CONFIG_FILE_NAME] * '/', @out_dir

  # Copy styles
  FileUtils.cp_r Configuration::styles, @out_dir

  #
  # Move to 'generated' directory as we will
  # create content relative to this directory
  #
  Dir.chdir @out_dir
  @out_dir = Pathname.pwd

  # Create index file of all index files
  @project_index_file = self.create_index_file(project_name, Configuration::LEVEL_1)


  # File iteration
  f.each do |line|

    #
    # Check level 1
    # Create a directory where its name corresponds to 'Title Level 1' &
    # where we have removed the leading '=' symbol and '.' and
    # replaced ' ' by '_'
    #
    if line[/^=\s/]

      #
      # Create Directory of the module and next the File
      #
      dir_name = remove_special_chars(2, line)
      new_dir = [@out_dir, dir_name].join('/')
      FileUtils.rm_rf new_dir
      FileUtils.mkdir new_dir
      Hyla.logger.info '>> Directory created : ' + new_dir + ' <<'

      Dir.chdir(new_dir)

      # Add image, audio, video directory
      self.create_asset_directory(['image', 'audio', 'video'])

      #
      # Create an index file
      # It is used to include files belonging to a module and will be used for SlideShows
      # The file created contains a title (= Dir Name) and header with attributes
      #
      @index_file = create_index_file(dir_name, Configuration::LEVEL_1)

      # Include index file created to parent index file
      @project_index_file.puts Configuration::INCLUDE_PREFIX + dir_name + '/' + dir_name + Configuration::INDEX_SUFFIX + Configuration::INCLUDE_SUFFIX
      @project_index_file.puts "\n"

      #
      # Generate a Module key value
      # 01, 02, ...
      # that we will use as key to create the asciidoc file
      #
      dir_name = File.basename(Dir.getwd)
      @module_key = dir_name.initial.rjust(2, '0')
      Hyla.logger.info ">> Module key : #@module_key <<"

      #
      # Reset counter value used to generate file number
      # for the file 01, 00
      #
      @index = 0

      # Move to next line record
      next
    end

    #
    # Check Level 2
    # Create a file for each Title Level 2 where name corresponds to title (without '==' symbol) &
    # where we have removed the leading '==' symbol  and '.' and replace ' ' by '_'
    #
    if line[/^==\s/]

      # Close File created previously if it exists
      if !@previous_f.nil?
        @previous_f.close
      end

      #
      # Replace special characters form the file and
      # add the module key followed by the index value for the file
      # Example : m01p01_MyTitle.ad, m01p02_Another_Title.ad
      #
      f_name = remove_special_chars(3, line)
      @index += 1
      #file_index = @index.to_s.initial.rjust(2, '0')
      file_index = sprintf('%02d', @index)
      f_name = 'm' + @module_key + 'p' + file_index + '_' + f_name + '.ad'

      Hyla.logger.info '   # File created : ' + f_name.to_s

      #
      # Create File and add configuration HEADER
      #
      @new_f = File.new(f_name, 'w')
      @new_f.puts Configuration::HEADER
      @new_f.puts "\n"

      @previous_f = @new_f

      # Include file to index
      @index_file.puts Configuration::INCLUDE_PREFIX + f_name + Configuration::INCLUDE_SUFFIX
      @index_file.puts "\n"
    end

    #
    # Add Content to file if it exists and line does not start with characters to be skipped
    #
    if !@new_f.nil? and !line.start_with?(Configuration::SKIP_CHARACTERS)
      @new_f.puts line
    end

  end

end