Class: Slideshow::Gen

Inherits:
Object
  • Object
show all
Includes:
AnalyticsHelper, BackgroundHelper, DebugFilter, DirectiveHelper, Fetch, HeadersFilter, Manifest, MarkdownEngines, MarkdownHelper, RestEngines, SlideFilter, SourceHelper, StepHelper, Syntax::CodeRayHelper, Syntax::ShHelper, Syntax::UvHelper, TableHelper, TextFilter, TextileEngines
Defined in:
lib/slideshow/fetch.rb,
lib/slideshow/gen.rb,
lib/slideshow/manifest.rb,
lib/slideshow/markup/rest.rb,
lib/slideshow/markup/textile.rb,
lib/slideshow/markup/markdown.rb,
lib/slideshow/filters/text_filter.rb,
lib/slideshow/helpers/step_helper.rb,
lib/slideshow/helpers/table_helper.rb,
lib/slideshow/filters/debug_filter.rb,
lib/slideshow/filters/slide_filter.rb,
lib/slideshow/helpers/source_helper.rb,
lib/slideshow/filters/headers_filter.rb,
lib/slideshow/helpers/markdown_helper.rb,
lib/slideshow/helpers/syntax/sh_helper.rb,
lib/slideshow/helpers/analytics_helper.rb,
lib/slideshow/helpers/syntax/uv_helper.rb,
lib/slideshow/helpers/directive_helper.rb,
lib/slideshow/helpers/background_helper.rb,
lib/slideshow/helpers/syntax/coderay_helper.rb

Overview

module CodeRayHelper module Syntax module Slideshow

Constant Summary

Constant Summary

Constants included from Syntax::CodeRayHelper

Syntax::CodeRayHelper::CR_LANG, Syntax::CodeRayHelper::CR_LINE_NUMBERS

Constants included from Syntax::UvHelper

Syntax::UvHelper::UV_LANG, Syntax::UvHelper::UV_LINE_NUMBERS, Syntax::UvHelper::UV_THEME

Constants included from Syntax::ShHelper

Syntax::ShHelper::SH_LANG, Syntax::ShHelper::SH_LINE_NUMBERS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Syntax::CodeRayHelper

#coderay, #coderay_worker

Methods included from BackgroundHelper

#background, #gradient

Methods included from DirectiveHelper

#css, #slide, #style

Methods included from Syntax::UvHelper

#uv, #uv_worker

Methods included from AnalyticsHelper

#google_analytics

Methods included from Syntax::ShHelper

#sh_worker, #sv

Methods included from MarkdownHelper

#clear, #s9_class

Methods included from HeadersFilter

#leading_headers

Methods included from SourceHelper

#source

Methods included from SlideFilter

#add_slide_directive_before_div_h1, #add_slide_directive_before_h1

Methods included from DebugFilter

#dump_content_to_file_debug_html, #dump_content_to_file_debug_text, #dump_content_to_file_debug_text_erb

Methods included from TableHelper

#left, #right

Methods included from StepHelper

#step

Methods included from TextFilter

#code_block_curly_style, #comments_percent_style, #directives_bang_style_to_percent_style, #directives_percent_style, #erb, #erb_django_simple_params, #erb_django_style, #erb_rename_helper_hack, #erb_simple_params, #skip_end_directive

Methods included from MarkdownEngines

#bluecloth_to_html, #kramdown_to_html, #load_markdown_libs, #markdown_to_html, #maruku_to_html, #pandoc_ruby_to_html, #pandoc_ruby_to_html_incremental, #pandoc_ruby_to_s5, #pandoc_ruby_to_s5_incremental, #rdiscount_to_html, #rpeg_markdown_to_html

Methods included from TextileEngines

#redcloth_java_fix_escape_nonascii, #redcloth_java_fix_escape_nonascii_exclude_pre, #textile_to_html

Methods included from RestEngines

#rest_to_html

Methods included from Manifest

#find_manifests, #installed_generator_manifests, #installed_template_manifests, #load_manifest, #load_manifest_core

Methods included from Fetch

#fetch_file, #fetch_slideshow_templates

Constructor Details

#initializeGen

Returns a new instance of Gen



5
6
7
8
9
10
# File 'lib/slideshow/gen.rb', line 5

def initialize
  @logger = Logger.new(STDOUT)
  @logger.level = Logger::INFO
  @opts   = Opts.new
  @config = Config.new
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config



12
13
14
# File 'lib/slideshow/gen.rb', line 12

def config
  @config
end

#loggerObject (readonly)

Returns the value of attribute logger



12
13
14
# File 'lib/slideshow/gen.rb', line 12

def logger
  @logger
end

#markup_typeObject (readonly)

:textile, :markdown, :rest



20
21
22
# File 'lib/slideshow/gen.rb', line 20

def markup_type
  @markup_type
end

#optsObject (readonly)

Returns the value of attribute opts



12
13
14
# File 'lib/slideshow/gen.rb', line 12

def opts
  @opts
end

#sessionObject (readonly)

give helpers/plugins a session-like hash



13
14
15
# File 'lib/slideshow/gen.rb', line 13

def session
  @session
end

Instance Method Details

#cache_dirObject

todo/fix: move to Config class



69
70
71
# File 'lib/slideshow/gen.rb', line 69

def cache_dir
  RUBY_PLATFORM =~ /win32/ ? win32_cache_dir : File.join(File.expand_path("~"), ".slideshow")
end

#config_dirObject

todo/fix: move to Config class



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/slideshow/gen.rb', line 85

def config_dir
  unless @config_dir  # first time? calculate config_dir value to "cache"
    
    if opts.config_path
      @config_dir = opts.config_path
    else
      @config_dir = cache_dir
    end
  
    # make sure path exists
    FileUtils.makedirs( @config_dir ) unless File.directory? @config_dir
  end
  
  @config_dir
end

#create_slideshow(fn) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
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
# File 'lib/slideshow/gen.rb', line 257

def create_slideshow( fn )

    manifest_path_or_name = opts.manifest
    
    # add .txt file extension if missing (for convenience)
    manifest_path_or_name << ".txt"   if File.extname( manifest_path_or_name ).empty?

  
    logger.debug "manifest=#{manifest_path_or_name}"
    
    # check if file exists (if yes use custom template package!) - allows you to override builtin package with same name 
    if File.exists?( manifest_path_or_name )
      manifest = load_manifest( manifest_path_or_name )
    else
      # check for builtin manifests
      manifests = installed_template_manifests
      matches = manifests.select { |m| m[0] == manifest_path_or_name } 

      if matches.empty?
        puts "*** error: unknown template manifest '#{manifest_path_or_name}'"  
        # todo: list installed manifests
        exit 2
      end
        
      manifest = load_manifest( matches[0][1] )
    end
  
    # expand output path in current dir and make sure output path exists
    outpath = File.expand_path( opts.output_path ) 
    logger.debug "outpath=#{outpath}"
    FileUtils.makedirs( outpath ) unless File.directory? outpath 

    dirname  = File.dirname( fn )    
    basename = File.basename( fn, '.*' )
    extname  = File.extname( fn )
    logger.debug "dirname=#{dirname}, basename=#{basename}, extname=#{extname}"

    # change working dir to sourcefile dir
    # todo: add a -c option to commandline? to let you set cwd?
    
    newcwd  = File.expand_path( dirname )
    oldcwd  = File.expand_path( Dir.pwd )
    
    unless newcwd == oldcwd then
      logger.debug "oldcwd=#{oldcwd}"
      logger.debug "newcwd=#{newcwd}"
      Dir.chdir newcwd
    end  

    puts "Preparing slideshow '#{basename}'..."
                
  if extname.empty? then
    extname  = ".textile"   # default to .textile 
    
    config.known_extnames.each do |e|
       logger.debug "File.exists? #{dirname}/#{basename}#{e}"
       if File.exists?( "#{dirname}/#{basename}#{e}" ) then         
          extname = e
          logger.debug "extname=#{extname}"
          break
       end
    end     
  end

  if config.known_markdown_extnames.include?( extname )
    @markup_type = :markdown
  elsif config.known_rest_extnames.include?( extname )
    @markup_type = :rest
  else
    @markup_type = :textile
  end
  
  # shared variables for templates (binding)
  @content_for = {}  # reset content_for hash

  @name        = basename
  @extname     = extname

  @headers     = @opts  # deprecate/remove: use headers method in template

  @session     = {}  # reset session hash for plugins/helpers

  inname  =  "#{dirname}/#{basename}#{extname}"

  logger.debug "inname=#{inname}"
    
  content = File.read( inname )

  # run text filters
  
  config.text_filters.each do |filter|
    mn = filter.tr( '-', '_' ).to_sym  # construct method name (mn)
    content = send( mn, content )   # call filter e.g.  include_helper_hack( content )  
  end

  # convert light-weight markup to hypertext

  content = text_to_html( content )

  # post-processing

  # make content2 and slide2 available to erb template
    # -- todo: cleanup variable names and use attr_readers for content and slide
  
  if @markup_type == :markdown && config.markdown_post_processing?( @markdown_libs.first ) == false
    puts "  Skipping post-processing (passing content through as is)..."
    @content = content  # content all-in-one - make it available in erb templates
  else
    # sets @content (all-in-one string) and @slides (structured content; split into slides)
    post_processing_slides( content )
  end


  manifest.each do |entry|
    outname = entry[0]
    if outname.include? '__file__' # process
      outname = outname.gsub( '__file__', basename )
      puts "Preparing #{outname}..."

      out = File.new( with_output_path( outname, outpath ), "w+" )

      out << render_template( load_template( entry[1] ), binding )
      
      if entry.size > 2 # more than one source file? assume header and footer with content added inbetween
        out << content2 
        out << render_template( load_template( entry[2] ), binding )
      end

      out.flush
      out.close

    else # just copy verbatim if target/dest has no __file__ in name
      dest   = entry[0]      
      source = entry[1]
            
      puts "Copying to #{dest} from #{source}..."     
      FileUtils.copy( source, with_output_path( dest, outpath ) )
    end
  end

  puts "Done."
end

#create_slideshow_templatesObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/slideshow/gen.rb', line 124

def create_slideshow_templates
  
  manifest_name = opts.manifest 
  logger.debug "manifest=#{manifest_name}"
  
  manifests = installed_generator_manifests
  
  # check for builtin generator manifests
  matches = manifests.select { |m| m[0] == manifest_name+".gen" }
  
  if matches.empty?
    puts "*** error: unknown template manifest '#{manifest_name}'"  
    # todo: list installed manifests
    exit 2
  end
      
  manifest = load_manifest( matches[0][1] )

  # expand output path in current dir and make sure output path exists
  outpath = File.expand_path( opts.output_path ) 
  logger.debug "outpath=#{outpath}"
  FileUtils.makedirs( outpath ) unless File.directory? outpath 

  manifest.each do |entry|
    dest   = entry[0]      
    source = entry[1]
                
    puts "Copying to #{dest} from #{source}..."     
    FileUtils.copy( source, with_output_path( dest, outpath ) )
  end
  
  puts "Done."   
end

#guard_block(text) ⇒ Object



44
45
46
47
48
49
50
51
52
# File 'lib/slideshow/gen.rb', line 44

def guard_block( text )
  if markup_type == :textile
    # saveguard with notextile wrapper etc./no further processing needed
    # note: add leading newlines to avoid block-runons
    "\n\n<notextile>\n#{text}\n</notextile>\n"
  else
    text
  end    
end

#guard_inline(text) ⇒ Object



54
55
56
# File 'lib/slideshow/gen.rb', line 54

def guard_inline( text )
  wrap_markup( text )
end

#guard_text(text) ⇒ Object



35
36
37
38
39
40
41
42
# File 'lib/slideshow/gen.rb', line 35

def guard_text( text )
  # todo/fix 2: note for Textile we need to differentiate between blocks and inline
  #   thus, to avoid runs - use guard_block (add a leading newline to avoid getting include in block that goes before)
  
  # todo/fix: remove wrap_markup; replace w/ guard_text
  #   why: text might be css, js, not just html      
  wrap_markup( text )
end

#headersObject



15
16
17
18
# File 'lib/slideshow/gen.rb', line 15

def headers
  # give access to helpers to opts with a different name
  @opts
end

#list_slideshow_templatesObject



158
159
160
161
162
163
164
165
166
167
# File 'lib/slideshow/gen.rb', line 158

def list_slideshow_templates
  manifests = installed_template_manifests
  
  puts ''
  puts 'Installed templates include:'
  
  manifests.each do |manifest|
    puts "  #{manifest[0]} (#{manifest[1]})"
  end
end

#load_pluginsObject



400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/slideshow/gen.rb', line 400

def load_plugins
    
  patterns = []
  patterns << "#{config_dir}/lib/**/*.rb"
  patterns << 'lib/**/*.rb' unless LIB_PATH == File.expand_path( 'lib' )  # don't include lib if we are in repo (don't include slideshow/lib)
  
  patterns.each do |pattern|
    pattern.gsub!( '\\', '/')  # normalize path; make sure all path use / only
    Dir.glob( pattern ) do |plugin|
      begin
        puts "Loading plugins in '#{plugin}'..."
        require( plugin )
      rescue Exception => e
        puts "** error: failed loading plugins in '#{plugin}': #{e}"
      end
    end
  end
end

#load_template(path) ⇒ Object



102
103
104
105
# File 'lib/slideshow/gen.rb', line 102

def load_template( path ) 
  puts "  Loading template #{path}..."
  return File.read( path )
end

#post_processing_slides(content) ⇒ Object

move into a filter??



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
254
# File 'lib/slideshow/gen.rb', line 170

def post_processing_slides( content )
  
  # 1) add slide break  

  if (@markup_type == :markdown && @markdown_libs.first == 'pandoc-ruby') || @markup_type == :rest
    content = add_slide_directive_before_div_h1( content )
  else
    content = add_slide_directive_before_h1( content )
  end

  dump_content_to_file_debug_html( content )

  # 2) use generic slide break processing instruction to
  #   split content into slides

  slide_counter = 0

  slides       = []
  slide_source = ""
   
  content.each_line do |line|
     if line.include?( '<!-- _S9SLIDE_' )  then
        if slide_counter > 0 then   # found start of new slide (and, thus, end of last slide)
          slides   << slide_source  # add slide to slide stack
          slide_source = ""         # reset slide source buffer
        end
        slide_counter += 1
     end
     slide_source  << line
  end

  if slide_counter > 0 then
    slides   << slide_source     # add slide to slide stack
    slide_source = ""            # reset slide source buffer 
  end

  ## split slide source into header (optional) and content/body
  ## plus check for (css style) classes

  slides2 = []
  slides.each do |slide_source|
    slide = Slide.new

    ## check for css style classes    
    from = 0
    while (pos = slide_source.index( /<!-- _S9(SLIDE|STYLE)_(.*?)-->/m, from ))
      logger.debug "  adding css classes from pi #{$1.downcase}: #{$2.strip}"

      if slide.classes.nil?
        slide.classes = $2.strip
      else
        slide.classes << " #{$2.strip}"
      end
    
      from = Regexp.last_match.end(0)
    end
     
     # try to cut off header using non-greedy .+? pattern; tip test regex online at rubular.com
     #  note/fix: needs to get improved to also handle case for h1 wrapped into div
     #    (e.g. extract h1 - do not assume it starts slide source)
    if slide_source =~ /^\s*(<h1.*?>.*?<\/h\d>)\s*(.*)/m 
      slide.header  = $1
      slide.content = ($2 ? $2 : "")
      logger.debug "  adding slide with header:\n#{slide.header}"
    else
      slide.content = slide_source
      logger.debug "  adding slide with *no* header:\n#{slide.content}"
    end
    slides2 << slide
  end

   # for convenience create a string w/ all in-one-html
   #  no need to wrap slides in divs etc.
 
   content2 = ""
   slides2.each do |slide|         
      content2 << slide.to_classic_html
   end
 
  # make content2 and slide2 available to erb template
  # -- todo: cleanup variable names and use attr_readers for content and slide

  @slides   = slides2     # strutured content 
  @content  = content2   # content all-in-one    
end

#render_template(content, the_binding) ⇒ Object



107
108
109
# File 'lib/slideshow/gen.rb', line 107

def render_template( content, the_binding )
  ERB.new( content ).result( the_binding )
end

#run(args) ⇒ Object



419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
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
# File 'lib/slideshow/gen.rb', line 419

def run( args )

  opt=OptionParser.new do |cmd|
    
    cmd.banner = "Usage: slideshow [options] name"
    
    cmd.on( '-o', '--output PATH', 'Output Path' ) { |s| opts.put( 'output', s ) }

    cmd.on( '-g', '--generate',  'Generate Slide Show Templates (Using Built-In S6 Pack)' ) { opts.put( 'generate', true ) }
    
    cmd.on( "-t", "--template MANIFEST", "Template Manifest" ) do |t|
      # todo: do some checks on passed in template argument
      opts.put( 'manifest', t )
    end

    # ?? opts.on( "-s", "--style STYLE", "Select Stylesheet" ) { |s| $options[:style]=s }
    # ?? opts.on( "--version", "Show version" )  {}
        
    # ?? cmd.on( '-i', '--include PATH', 'Load Path' ) { |s| opts.put( 'include', s ) }

    cmd.on( '-f', '--fetch URI', 'Fetch Templates' ) do |u|
      opts.put( 'fetch_uri', u )
    end
    
    cmd.on( '-c', '--config PATH', 'Configuration Path (default is ~/.slideshow)' ) do |p|
      opts.put( 'config_path', p )
    end
    
    cmd.on( '-l', '--list', 'List Installed Templates' ) { opts.put( 'list', true ) }

    # todo: find different letter for debug trace switch (use v for version?)
    cmd.on( "-v", "--verbose", "Show debug trace" )  do
       logger.datetime_format = "%H:%H:%S"
       logger.level = Logger::DEBUG      
    end
 
    cmd.on_tail( "-h", "--help", "Show this message" ) do
         puts 
         puts "Slide Show (S9) is a free web alternative to PowerPoint or KeyNote in Ruby"
         puts
         puts cmd.help
         puts
         puts "Examples:"
         puts "  slideshow microformats"
         puts "  slideshow microformats.textile         # Process slides using Textile"
         puts "  slideshow microformats.text            # Process slides using Markdown"
         puts "  slideshow microformats.rst             # Process slides using reStructuredText"
         puts "  slideshow -o slides microformats       # Output slideshow to slides folder"
         puts
         puts "More examles:"
         puts "  slideshow -g                           # Generate slide show templates using built-in S6 pack"
         puts
         puts "  slideshow -l                           # List installed slide show templates"
         puts "  slideshow -f s5blank                   # Fetch (install) S5 blank starter template from internet"
         puts "  slideshow -t s5blank microformats      # Use your own slide show templates (e.g. s5blank)"
         puts
         puts "Further information:"
         puts "  http://slideshow.rubyforge.org" 
         exit
    end
  end

  opt.parse!( args )
  
  config.load

  puts "Slide Show (S9) Version: #{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"

  if opts.list?
    list_slideshow_templates
  elsif opts.generate?
    create_slideshow_templates
  elsif opts.fetch?
    fetch_slideshow_templates
  else
    load_markdown_libs
    load_plugins  # check for optional plugins/extension in ./lib folder
    
    args.each { |fn| create_slideshow( fn ) }
  end
end

#text_to_html(content) ⇒ Object

uses configured markup processor (textile,markdown,rest) to generate html



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/slideshow/gen.rb', line 23

def text_to_html( content )
  content = case @markup_type
    when :markdown
      markdown_to_html( content )
    when :textile
      textile_to_html( content )
    when :rest
      rest_to_html( content )
  end
  content
end

#win32_cache_dirObject

todo/fix: move to Config class



74
75
76
77
78
79
80
81
82
# File 'lib/slideshow/gen.rb', line 74

def win32_cache_dir
  unless ENV['HOMEDRIVE'] && ENV['HOMEPATH'] && File.exists?(home = ENV['HOMEDRIVE'] + ENV['HOMEPATH'])
    puts "No HOMEDRIVE or HOMEPATH environment variable.  Set one to save a" +
         "local cache of stylesheets for syntax highlighting and more."
    return false
  else
    return File.join(home, '.slideshow')
  end
end

#with_output_path(dest, output_path) ⇒ Object



112
113
114
115
116
117
118
119
120
121
# File 'lib/slideshow/gen.rb', line 112

def with_output_path( dest, output_path )
  dest_full = File.expand_path( dest, output_path )
  logger.debug "dest_full=#{dest_full}"
    
  # make sure dest path exists
  dest_path = File.dirname( dest_full )
  logger.debug "dest_path=#{dest_path}"
  FileUtils.makedirs( dest_path ) unless File.directory? dest_path
  dest_full
end

#wrap_markup(text) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/slideshow/gen.rb', line 59

def wrap_markup( text )    
  if markup_type == :textile
    # saveguard with notextile wrapper etc./no further processing needed
    "<notextile>\n#{text}\n</notextile>"
  else
    text
  end
end