slideshow 0.7.7 → 0.7.8

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.
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