slideshow 0.7.7 → 0.7.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/History.txt +93 -0
  2. data/Manifest.txt +58 -0
  3. data/README.txt +51 -0
  4. data/Rakefile +18 -0
  5. data/lib/slideshow.rb +23 -613
  6. data/lib/slideshow/gen.rb +483 -0
  7. data/lib/{helpers → slideshow/helpers}/capture_helper.rb +0 -0
  8. data/lib/{helpers → slideshow/helpers}/coderay_helper.rb +0 -0
  9. data/lib/{helpers → slideshow/helpers}/text_helper.rb +0 -0
  10. data/lib/{helpers → slideshow/helpers}/uv_helper.rb +0 -0
  11. data/lib/slideshow/opts.rb +136 -0
  12. data/templates/fullerscreen.txt +5 -0
  13. data/templates/fullerscreen.txt.gen +7 -0
  14. data/{lib/templates → templates}/fullerscreen.txt.sample +0 -0
  15. data/{lib/templates → templates/fullerscreen}/footer.html.erb +0 -0
  16. data/{lib/templates → templates/fullerscreen}/header.html.erb +0 -0
  17. data/{lib/templates → templates/fullerscreen}/style.css.erb +0 -0
  18. data/{lib/templates → templates}/gradient.svg.erb +0 -0
  19. data/{lib/templates → templates}/s5.txt +1 -1
  20. data/{lib/templates → templates}/s5.txt.gen +0 -0
  21. data/{lib/templates → templates}/s5.txt.sample +0 -0
  22. data/{lib/templates → templates}/s5/footer.html.erb +0 -0
  23. data/{lib/templates → templates}/s5/header.html.erb +0 -0
  24. data/{lib/templates → templates}/s5/opera.css +0 -0
  25. data/{lib/templates → templates}/s5/outline.css +0 -0
  26. data/{lib/templates → templates}/s5/print.css +0 -0
  27. data/{lib/templates → templates}/s5/s5-core.css +0 -0
  28. data/{lib/templates → templates}/s5/slides.js +0 -0
  29. data/{lib/templates → templates}/s5/style.css.erb +0 -0
  30. data/{lib/templates → templates}/s5blank.txt.gen +0 -0
  31. data/{lib/templates → templates}/s5blank.txt.sample +0 -0
  32. data/{lib/templates → templates}/s5blank/blank.textile +0 -0
  33. data/{lib/templates → templates}/s5blank/footer.html.erb +0 -0
  34. data/{lib/templates → templates}/s5blank/header.html.erb +0 -0
  35. data/{lib/templates → templates}/s5blank/ui/default/blank.gif +0 -0
  36. data/{lib/templates → templates}/s5blank/ui/default/bodybg.gif +0 -0
  37. data/{lib/templates → templates}/s5blank/ui/default/framing.css +0 -0
  38. data/{lib/templates → templates}/s5blank/ui/default/iepngfix.htc +0 -0
  39. data/{lib/templates → templates}/s5blank/ui/default/opera.css +0 -0
  40. data/{lib/templates → templates}/s5blank/ui/default/outline.css +0 -0
  41. data/{lib/templates → templates}/s5blank/ui/default/pretty.css +0 -0
  42. data/{lib/templates → templates}/s5blank/ui/default/print.css +0 -0
  43. data/{lib/templates → templates}/s5blank/ui/default/s5-core.css +0 -0
  44. data/{lib/templates → templates}/s5blank/ui/default/slides.css +0 -0
  45. data/{lib/templates → templates}/s5blank/ui/default/slides.js +0 -0
  46. data/{lib/templates → templates}/s6.txt +0 -0
  47. data/{lib/templates → templates}/s6.txt.gen +0 -0
  48. data/{lib/templates → templates}/s6.txt.sample +0 -0
  49. data/{lib/templates → templates}/s6/footer.html.erb +0 -0
  50. data/{lib/templates → templates}/s6/header.html.erb +0 -0
  51. data/{lib/templates → templates}/s6/jquery.js +0 -0
  52. data/{lib/templates → templates}/s6/outline.css +0 -0
  53. data/{lib/templates → templates}/s6/print.css +0 -0
  54. data/{lib/templates → templates}/s6/slides.core.js +0 -0
  55. data/{lib/templates → templates}/s6/slides.css +0 -0
  56. data/{lib/templates → templates}/s6/slides.js +0 -0
  57. data/{lib/templates → templates}/s6/style.css.erb +0 -0
  58. metadata +81 -66
  59. data/lib/templates/fullerscreen.txt +0 -5
  60. data/lib/templates/fullerscreen.txt.gen +0 -7
@@ -0,0 +1,483 @@
1
+
2
+
3
+
4
+ module Slideshow
5
+
6
+ class Gen
7
+
8
+ KNOWN_TEXTILE_EXTNAMES = [ '.textile', '.t' ]
9
+ KNOWN_MARKDOWN_EXTNAMES = [ '.markdown', '.m', '.mark', '.mkdn', '.md', '.txt', '.text' ]
10
+ KNOWN_EXTNAMES = KNOWN_TEXTILE_EXTNAMES + KNOWN_MARKDOWN_EXTNAMES
11
+
12
+ # note: only bluecloth is listed as a dependency in gem specs (because it's Ruby only and, thus, easy to install)
13
+ # if you want to use other markdown libs install the required/desired lib e.g.
14
+ # use gem install rdiscount for rdiscount and so on
15
+ #
16
+ # also note for now the first present markdown library gets used
17
+ # the search order is first come, first serve, that is: rdiscount, rpeg-markdown, maruku, bluecloth (fallback, always present)
18
+ KNOWN_MARKDOWN_LIBS = [
19
+ [ 'rdiscount', lambda { |content| RDiscount.new( content ).to_html } ],
20
+ [ 'rpeg-markdown', lambda { |content| PEGMarkdown.new( content ).to_html } ],
21
+ [ 'maruku', lambda { |content| Maruku.new( content, {:on_error => :raise} ).to_html } ],
22
+ [ 'bluecloth', lambda { |content| BlueCloth.new( content ).to_html } ]
23
+ ]
24
+
25
+ BUILTIN_MANIFESTS = [ 'fullerscreen.txt', 'fullerscreen.txt.gen',
26
+ 's5.txt', 's5.txt.gen',
27
+ 's6.txt', 's6.txt.gen',
28
+ 's5blank.txt.gen' ]
29
+
30
+ def initialize
31
+ @logger = Logger.new(STDOUT)
32
+ @logger.level = Logger::INFO
33
+ @opts = Opts.new
34
+ end
35
+
36
+ # replace w/ attr_reader :logger, :opts ??
37
+
38
+ def logger
39
+ @logger
40
+ end
41
+
42
+ def opts
43
+ @opts
44
+ end
45
+
46
+ def headers
47
+ # give access to helpers to opts with a different name
48
+ @opts
49
+ end
50
+
51
+ def session
52
+ # give helpers/plugins a session-like hash
53
+ @session
54
+ end
55
+
56
+ def markup_type
57
+ @markup_type # :textile, :markdown
58
+ end
59
+
60
+ def load_markdown_libs
61
+ # check for available markdown libs/gems
62
+ # try to require each lib and remove any not installed
63
+ @markdown_libs = []
64
+
65
+ KNOWN_MARKDOWN_LIBS.each do |lib|
66
+ begin
67
+ require lib[0]
68
+ @markdown_libs << lib
69
+ rescue LoadError => ex
70
+ logger.debug "Markdown library #{lib[0]} not found. Use gem install #{lib[0]} to install."
71
+ end
72
+ end
73
+
74
+ logger.debug "Installed Markdown libraries: #{@markdown_libs.map{ |lib| lib[0] }.join(', ')}"
75
+ logger.debug "Using Markdown library #{@markdown_libs.first[0]}."
76
+ end
77
+
78
+ # todo: move to filter (for easier reuse)
79
+ def markdown_to_html( content )
80
+ @markdown_libs.first[1].call( content )
81
+ end
82
+
83
+ # todo: move to filter (for easier reuse)
84
+ def textile_to_html( content )
85
+ # turn off hard line breaks
86
+ # turn off span caps (see http://rubybook.ca/2008/08/16/redcloth)
87
+ red = RedCloth.new( content, [:no_span_caps] )
88
+ red.hard_breaks = false
89
+ content = red.to_html
90
+ end
91
+
92
+ def wrap_markup( text )
93
+ if markup_type == :textile
94
+ # saveguard with notextile wrapper etc./no further processing needed
95
+ "<notextile>\n#{text}\n</notextile>"
96
+ else
97
+ text
98
+ end
99
+ end
100
+
101
+ def cache_dir
102
+ PLATFORM =~ /win32/ ? win32_cache_dir : File.join(File.expand_path("~"), ".slideshow")
103
+ end
104
+
105
+ def win32_cache_dir
106
+ unless File.exists?(home = ENV['HOMEDRIVE'] + ENV['HOMEPATH'])
107
+ puts "No HOMEDRIVE or HOMEPATH environment variable. Set one to save a" +
108
+ "local cache of stylesheets for syntax highlighting and more."
109
+ return false
110
+ else
111
+ return File.join(home, 'slideshow')
112
+ end
113
+ end
114
+
115
+ def load_manifest( path )
116
+
117
+ # check if file exists (if yes use custom template package!) - allows you to override builtin package with same name
118
+ if BUILTIN_MANIFESTS.include?( path ) && !File.exists?( path )
119
+ templatesdir = "#{File.dirname( LIB_PATH )}/templates"
120
+ logger.debug "use builtin template package"
121
+ logger.debug "templatesdir=#{templatesdir}"
122
+ filename = "#{templatesdir}/#{path}"
123
+ else
124
+ templatesdir = File.dirname( path )
125
+ logger.debug "use custom template package"
126
+ logger.debug "templatesdir=#{templatesdir}"
127
+ filename = path
128
+ end
129
+
130
+ manifest = []
131
+ puts " Loading template manifest #{filename}..."
132
+
133
+ File.open( filename ).readlines.each_with_index do |line,i|
134
+ case line
135
+ when /^\s*$/
136
+ # skip empty lines
137
+ when /^\s*#.*$/
138
+ # skip comment lines
139
+ else
140
+ logger.debug "line #{i+1}: #{line.strip}"
141
+ values = line.strip.split( /[ <,+]+/ )
142
+
143
+ # add source for shortcuts (assumes relative path; if not issue warning/error)
144
+ values << values[0] if values.size == 1
145
+
146
+ # normalize all source paths (1..-1) /make full path/add template dir
147
+ (1..values.size-1).each do |i|
148
+ values[i] = "#{templatesdir}/#{values[i]}"
149
+ logger.debug " path[#{i}]=>#{values[i]}<"
150
+ end
151
+
152
+ manifest << values
153
+ end
154
+ end
155
+
156
+ manifest
157
+ end
158
+
159
+ def load_template( path )
160
+ puts " Loading template #{path}..."
161
+ return File.read( path )
162
+ end
163
+
164
+ def render_template( content, the_binding )
165
+ ERB.new( content ).result( the_binding )
166
+ end
167
+
168
+ def load_template_old_delete( name, builtin )
169
+
170
+ if opts.has_includes?
171
+ opts.includes.each do |path|
172
+ logger.debug "File.exists? #{path}/#{name}"
173
+
174
+ if File.exists?( "#{path}/#{name}" ) then
175
+ puts "Loading custom template #{path}/#{name}..."
176
+ return File.read( "#{path}/#{name}" )
177
+ end
178
+ end
179
+ end
180
+
181
+ # fallback load builtin template packaged with gem
182
+ load_builtin_template( builtin )
183
+ end
184
+
185
+ def with_output_path( dest, output_path )
186
+ dest_full = File.expand_path( dest, output_path )
187
+ logger.debug "dest_full=#{dest_full}"
188
+
189
+ # make sure dest path exists
190
+ dest_path = File.dirname( dest_full )
191
+ logger.debug "dest_path=#{dest_path}"
192
+ File.makedirs( dest_path ) unless File.directory? dest_path
193
+ dest_full
194
+ end
195
+
196
+ def create_slideshow_templates
197
+ logger.debug "manifest=#{opts.manifest}.gen"
198
+ manifest = load_manifest( opts.manifest+".gen" )
199
+
200
+ # expand output path in current dir and make sure output path exists
201
+ outpath = File.expand_path( opts.output_path )
202
+ logger.debug "outpath=#{outpath}"
203
+ File.makedirs( outpath ) unless File.directory? outpath
204
+
205
+ manifest.each do |entry|
206
+ dest = entry[0]
207
+ source = entry[1]
208
+
209
+ puts "Copying to #{dest} from #{source}..."
210
+ File.copy( source, with_output_path( dest, outpath ) )
211
+ end
212
+
213
+ puts "Done."
214
+ end
215
+
216
+ def create_slideshow( fn )
217
+
218
+ logger.debug "manifest=#{opts.manifest}"
219
+ manifest = load_manifest( opts.manifest )
220
+ # pp manifest
221
+
222
+ # expand output path in current dir and make sure output path exists
223
+ outpath = File.expand_path( opts.output_path )
224
+ logger.debug "outpath=#{outpath}"
225
+ File.makedirs( outpath ) unless File.directory? outpath
226
+
227
+ dirname = File.dirname( fn )
228
+ basename = File.basename( fn, '.*' )
229
+ extname = File.extname( fn )
230
+ logger.debug "dirname=#{dirname}, basename=#{basename}, extname=#{extname}"
231
+
232
+ # change working dir to sourcefile dir
233
+ # todo: add a -c option to commandline? to let you set cwd?
234
+
235
+ newcwd = File.expand_path( dirname )
236
+ oldcwd = File.expand_path( Dir.pwd )
237
+
238
+ unless newcwd == oldcwd then
239
+ logger.debug "oldcwd=#{oldcwd}"
240
+ logger.debug "newcwd=#{newcwd}"
241
+ Dir.chdir newcwd
242
+ end
243
+
244
+ puts "Preparing slideshow '#{basename}'..."
245
+
246
+ if extname.empty? then
247
+ extname = ".textile" # default to .textile
248
+
249
+ KNOWN_EXTNAMES.each do |e|
250
+ logger.debug "File.exists? #{dirname}/#{basename}#{e}"
251
+ if File.exists?( "#{dirname}/#{basename}#{e}" ) then
252
+ extname = e
253
+ logger.debug "extname=#{extname}"
254
+ break
255
+ end
256
+ end
257
+ end
258
+
259
+ if KNOWN_MARKDOWN_EXTNAMES.include?( extname )
260
+ @markup_type = :markdown
261
+ else
262
+ @markup_type = :textile
263
+ end
264
+
265
+ # shared variables for templates (binding)
266
+ @content_for = {} # reset content_for hash
267
+ @name = basename
268
+ @headers = @opts # deprecate/remove: use headers method in template
269
+
270
+ @session = {} # reset session hash for plugins/helpers
271
+
272
+ inname = "#{dirname}/#{basename}#{extname}"
273
+
274
+ logger.debug "inname=#{inname}"
275
+
276
+ content_with_headers = File.read( inname )
277
+
278
+ # todo: read headers before command line options (lets you override options using commandline switch)?
279
+
280
+ # read source document; split off optional header from source
281
+ # strip leading optional headers (key/value pairs) including optional empty lines
282
+
283
+ read_headers = true
284
+ content = ""
285
+
286
+ # fix: allow comments in header too (#)
287
+
288
+ content_with_headers.each do |line|
289
+ if read_headers && line =~ /^\s*(\w[\w-]*)[ \t]*:[ \t]*(.*)/
290
+ key = $1.downcase
291
+ value = $2.strip
292
+
293
+ logger.debug " adding option: key=>#{key}< value=>#{value}<"
294
+ opts.put( key, value )
295
+ elsif line =~ /^\s*$/
296
+ content << line unless read_headers
297
+ else
298
+ read_headers = false
299
+ content << line
300
+ end
301
+ end
302
+
303
+ opts.set_defaults
304
+
305
+ # ruby note: .*? is non-greedy (shortest-possible) regex match
306
+ content.gsub!(/__SKIP__.*?__END__/m, '')
307
+ content.sub!(/__END__.*/m, '')
308
+
309
+ # allow plugins/helpers; process source (including header) using erb
310
+
311
+ # note: include is a ruby keyword; rename to __include__ so we can use it
312
+ content.gsub!( /<%=[ \t]*include/, '<%= __include__' )
313
+
314
+ content = ERB.new( content ).result( binding )
315
+
316
+ # run pre-filters (built-in macros)
317
+ # o replace {{{ w/ <pre class='code'>
318
+ # o replace }}} w/ </pre>
319
+ content.gsub!( "{{{{{{", "<pre class='code'>_S9BEGIN_" )
320
+ content.gsub!( "}}}}}}", "_S9END_</pre>" )
321
+ content.gsub!( "{{{", "<pre class='code'>" )
322
+ content.gsub!( "}}}", "</pre>" )
323
+ # restore escaped {{{}}} I'm sure there's a better way! Rubyize this! Anyone?
324
+ content.gsub!( "_S9BEGIN_", "{{{" )
325
+ content.gsub!( "_S9END_", "}}}" )
326
+
327
+ # convert light-weight markup to hypertext
328
+
329
+ content = case @markup_type
330
+ when :markdown
331
+ markdown_to_html( content )
332
+ when :textile
333
+ textile_to_html( content )
334
+ end
335
+
336
+ # post-processing
337
+
338
+ slide_counter = 0
339
+ content2 = ''
340
+
341
+ ## todo: move this to a filter (for easier reuse)
342
+
343
+ # wrap h1's in slide divs; note use just <h1 since some processors add ids e.g. <h1 id='x'>
344
+ content.each_line do |line|
345
+ if line.include?( '<h1' ) then
346
+ content2 << "\n\n</div>" if slide_counter > 0
347
+ content2 << "<div class='slide'>\n\n"
348
+ slide_counter += 1
349
+ end
350
+ content2 << line
351
+ end
352
+ content2 << "\n\n</div>" if slide_counter > 0
353
+
354
+ manifest.each do |entry|
355
+ outname = entry[0]
356
+ if outname.include? '__file__' # process
357
+ outname = outname.gsub( '__file__', basename )
358
+ puts "Preparing #{outname}..."
359
+
360
+ out = File.new( with_output_path( outname, outpath ), "w+" )
361
+
362
+ out << render_template( load_template( entry[1] ), binding )
363
+
364
+ if entry.size > 2 # more than one source file? assume header and footer with content added inbetween
365
+ out << content2
366
+ out << render_template( load_template( entry[2] ), binding )
367
+ end
368
+
369
+ out.flush
370
+ out.close
371
+
372
+ else # just copy verbatim if target/dest has no __file__ in name
373
+ dest = entry[0]
374
+ source = entry[1]
375
+
376
+ puts "Copying to #{dest} from #{source}..."
377
+ File.copy( source, with_output_path( dest, outpath ) )
378
+ end
379
+ end
380
+
381
+ puts "Done."
382
+ end
383
+
384
+ def load_plugins
385
+
386
+ # use lib folder unless we're in our very own folder
387
+ # (that already uses lib for its core functionality), thus, use plugins instead
388
+ if( LIB_PATH == File.expand_path( 'lib' ) )
389
+ pattern = 'plugins/**/*.rb'
390
+ else
391
+ pattern = 'lib/**/*.rb'
392
+ end
393
+
394
+ logger.debug "pattern=#{pattern}"
395
+
396
+ Dir.glob( pattern ) do |plugin|
397
+ begin
398
+ puts "Loading plugins in '#{plugin}'..."
399
+ require( plugin )
400
+ rescue Exception => e
401
+ puts "** error: failed loading plugins in '#{plugin}': #{e}"
402
+ end
403
+ end
404
+ end
405
+
406
+ def run( args )
407
+
408
+ opt=OptionParser.new do |cmd|
409
+
410
+ cmd.banner = "Usage: slideshow [options] name"
411
+
412
+ cmd.on( '-o', '--output PATH', 'Output Path' ) { |s| opts.put( 'output', s ) }
413
+
414
+ cmd.on( '-g', '--generate', 'Generate Slide Show Templates' ) { opts.put( 'generate', true ) }
415
+
416
+ cmd.on( "-t", "--template TEMPLATE", "Template Manifest" ) do |t|
417
+ # todo: do some checks on passed in template argument
418
+ opts.put( 'manifest', t )
419
+ end
420
+
421
+ # shortcut: same as -t s5.txt
422
+ cmd.on( '--s5', 'S5-Compatible Slide Show (same as -t s5.txt)' ) { opts.put( 's5', true ); opts.put( 'manifest', 's5.txt' ) }
423
+
424
+ # shortcut: same as -t fullerscreen.txt
425
+ cmd.on( '--fullerscreen', 'FullerScreen-Compatible Slide Show (same as -t fullerscreen.txt)' ) { opts.put( 'fuller', true ); opts.put( 'manifest', 'fullerscreen.txt' ) }
426
+
427
+ # ?? opts.on( "-s", "--style STYLE", "Select Stylesheet" ) { |s| $options[:style]=s }
428
+ # ?? opts.on( "--version", "Show version" ) {}
429
+
430
+ # ?? cmd.on( '-i', '--include PATH', 'Load Path' ) { |s| opts.put( 'include', s ) }
431
+
432
+ # todo: find different letter for debug trace switch (use v for version?)
433
+ cmd.on( "-v", "--verbose", "Show debug trace" ) do
434
+ logger.datetime_format = "%H:%H:%S"
435
+ logger.level = Logger::DEBUG
436
+ end
437
+
438
+ cmd.on_tail( "-h", "--help", "Show this message" ) do
439
+ puts
440
+ puts "Slide Show (S9) is a free web alternative to PowerPoint or KeyNote in Ruby"
441
+ puts
442
+ puts cmd.help
443
+ puts
444
+ puts "Examples:"
445
+ puts " slideshow microformats"
446
+ puts " slideshow microformats.textile"
447
+ puts " slideshow -o slides microformats # Output slideshow to slides folder"
448
+ puts " slideshow --s5 microformats # Use S5-compatible slide show templates"
449
+ puts " slideshow --fullerscreen microformats # Use FullerScreen-compatible slide show templates"
450
+ puts
451
+ puts "More examles:"
452
+ puts " slideshow -g # Generate slide show templates"
453
+ puts " slideshow -g --s5 # Generate S5 compatible slide show templates"
454
+ puts " slideshow -g --fullerscreen # Generate FullerScreen compatible slide show templates"
455
+ puts " slideshow -g -t s5blank.txt # Generate S5 blank starter templates"
456
+ puts
457
+ puts " slideshow -t s3.txt microformats # Use your own slide show templates (e.g. s3.txt)"
458
+ puts
459
+ puts
460
+ puts "Further information:"
461
+ puts " http://slideshow.rubyforge.org"
462
+ exit
463
+ end
464
+ end
465
+
466
+ opt.parse!( args )
467
+
468
+ puts "Slide Show (S9) Version: #{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
469
+
470
+ if opts.generate?
471
+ create_slideshow_templates
472
+ else
473
+ load_markdown_libs
474
+ load_plugins # check for optional plugins/extension in ./lib folder
475
+
476
+ args.each { |fn| create_slideshow( fn ) }
477
+ end
478
+ end
479
+
480
+ end # class Gen
481
+
482
+
483
+ end # module Slideshow