showoff 0.1.1 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt CHANGED
@@ -51,6 +51,19 @@ it has a showoff.json file and a number of sections (subdirectories) with markdo
51
51
  If you run 'showoff' in the ShowOff directory itself, it will show an example
52
52
  presentation from the 'example' subdirectory, so you can see what it's like.
53
53
 
54
+ Alternatively you can generate a static version of your presentation by either
55
+
56
+ $ showoff static
57
+
58
+ Which will generate a static directory with an index.html and all other necessary files.
59
+
60
+ Or
61
+
62
+ $ showoff static pdf
63
+
64
+ Which will generate a file called <name>.pdf where <name> is the name of the subdirectory.
65
+
66
+
54
67
  Slide Format
55
68
  ====================
56
69
 
@@ -92,6 +105,7 @@ them.
92
105
  Some useful styles for each slide are:
93
106
 
94
107
  * center - centers images on a slide
108
+ * full-page - allows an image to take up the whole slide
95
109
  * bullets - sizes and seperates bullets properly (fits up to 5, generally)
96
110
  * smbullets - sizes and seperates more bullets (smaller, closer together)
97
111
  * subsection - creates a different background for titles
data/bin/showoff CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
4
  require 'showoff'
5
- command = ARGV[0]
5
+ command = ARGV.shift
6
6
 
7
7
  case command
8
8
  when 'create'
@@ -13,6 +13,8 @@ when 'heroku'
13
13
  ShowOffUtils.heroku
14
14
  when 'serve'
15
15
  ShowOff.run! :host => 'localhost', :port => 9090
16
+ when 'static'
17
+ ShowOff.do_static(ARGV)
16
18
  else
17
19
  ShowOffUtils.help
18
- end
20
+ end
data/lib/showoff.rb CHANGED
@@ -4,6 +4,8 @@ require 'json'
4
4
  require 'nokogiri'
5
5
  require 'showoff_utils'
6
6
  require 'princely'
7
+ require 'ftools'
8
+
7
9
 
8
10
  begin
9
11
  require 'rdiscount'
@@ -18,16 +20,19 @@ class ShowOff < Sinatra::Application
18
20
  set :views, File.dirname(__FILE__) + '/../views'
19
21
  set :public, File.dirname(__FILE__) + '/../public'
20
22
  set :pres_dir, 'example'
21
-
23
+
22
24
  def initialize(app=nil)
23
25
  super(app)
24
26
  puts dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
25
27
  if Dir.pwd == dir
26
28
  options.pres_dir = dir + '/example'
29
+ @root_path = "."
27
30
  else
28
31
  options.pres_dir = Dir.pwd
32
+ @root_path = ".."
29
33
  end
30
34
  puts options.pres_dir
35
+ @pres_name = options.pres_dir.split('/').pop
31
36
  end
32
37
 
33
38
  helpers do
@@ -46,7 +51,7 @@ class ShowOff < Sinatra::Application
46
51
  Dir.glob("#{options.pres_dir}/*.js").map { |path| File.basename(path) }
47
52
  end
48
53
 
49
- def process_markdown(name, content)
54
+ def process_markdown(name, content, static=false)
50
55
  slides = content.split(/^!SLIDE/)
51
56
  slides.delete('')
52
57
  final = ''
@@ -75,7 +80,7 @@ class ShowOff < Sinatra::Application
75
80
  md += "<div class=\"#{content_classes.join(' ')}\" ref=\"#{name}\">\n"
76
81
  end
77
82
  sl = Markdown.new(slide).to_html
78
- sl = update_image_paths(name, sl)
83
+ sl = update_image_paths(name, sl, static)
79
84
  md += sl
80
85
  md += "</div>\n"
81
86
  md += "</div>\n"
@@ -84,11 +89,15 @@ class ShowOff < Sinatra::Application
84
89
  final
85
90
  end
86
91
 
87
- def update_image_paths(path, slide)
92
+ def update_image_paths(path, slide, static=false)
88
93
  paths = path.split('/')
89
94
  paths.pop
90
95
  path = paths.join('/')
91
- slide.gsub(/img src=\"(.*?)\"/, 'img src="/image/' + path + '/\1"')
96
+ if static
97
+ slide.gsub(/img src=\"(.*?)\"/, 'img src="file://'+options.pres_dir+'/static/' + path + '/\1"')
98
+ else
99
+ slide.gsub(/img src=\"(.*?)\"/, 'img src="/image/' + path + '/\1"')
100
+ end
92
101
  end
93
102
 
94
103
  def update_commandline_code(slide)
@@ -127,7 +136,7 @@ class ShowOff < Sinatra::Application
127
136
  html.root.to_s
128
137
  end
129
138
 
130
- def get_slides_html
139
+ def get_slides_html(static=false)
131
140
  index = File.join(options.pres_dir, 'showoff.json')
132
141
  files = []
133
142
  if File.exists?(index)
@@ -141,7 +150,7 @@ class ShowOff < Sinatra::Application
141
150
  data = ''
142
151
  files.each do |f|
143
152
  fname = f.gsub(options.pres_dir + '/', '').gsub('.md', '')
144
- data += process_markdown(fname, File.read(f))
153
+ data += process_markdown(fname, File.read(f),static)
145
154
  end
146
155
  end
147
156
  data
@@ -174,12 +183,73 @@ class ShowOff < Sinatra::Application
174
183
  js_content += '</script>'
175
184
  js_content
176
185
  end
186
+
187
+ def index(static=false)
188
+ if static
189
+ @slides = get_slides_html(static)
190
+ @asset_path = "."
191
+ end
192
+ erb :index
193
+ end
177
194
 
178
- end
195
+ def slides(static=false)
196
+ get_slides_html(static)
197
+ end
198
+
199
+ def onepage(static=false)
200
+ @slides = get_slides_html(static)
201
+ erb :onepage
202
+ end
203
+
204
+ def pdf(static=false)
205
+ @slides = get_slides_html(static)
206
+ @no_js = true
207
+ html = erb :onepage
208
+ p = Princely.new
209
+ # TODO make a random filename
210
+ p.pdf_from_string_to_file(html, '/tmp/preso.pdf')
211
+ File.new('/tmp/preso.pdf')
212
+ end
179
213
 
180
- get '/' do
181
- erb :index
182
214
  end
215
+
216
+
217
+ def self.do_static(args)
218
+ what = args.shift || "index"
219
+
220
+ # Nasty hack to get the actual ShowOff module
221
+ showoff = ShowOff.new
222
+ while !showoff.is_a?(ShowOff)
223
+ showoff = showoff.instance_variable_get(:@app)
224
+ end
225
+ name = showoff.instance_variable_get(:@pres_name)
226
+ path = showoff.instance_variable_get(:@root_path)
227
+ data = showoff.send(what, true)
228
+ if data.is_a?(File)
229
+ File.cp(data.path, "#{name}.pdf")
230
+ else
231
+ out = "#{path}/#{name}/static"
232
+ # First make a directory
233
+ File.makedirs("#{out}")
234
+ # Then write the html
235
+ file = File.new("#{out}/index.html", "w")
236
+ file.puts(data)
237
+ file.close
238
+ # Now copy all the js and css
239
+ ["js", "css"].each { |dir|
240
+ FileUtils.copy_entry("#{path}/public/#{dir}", "#{out}/#{dir}")
241
+ }
242
+ # And copy the directory
243
+ Dir.glob("#{path}/#{name}/*").each { |subpath|
244
+ base = File.basename(subpath)
245
+ next if "static" == base
246
+ next unless File.directory?(subpath) || base.match(/\.(css|js)$/)
247
+ FileUtils.copy_entry(subpath, "#{out}/#{base}")
248
+ }
249
+ end
250
+ end
251
+
252
+
183
253
 
184
254
  get %r{(?:image|file)/(.*)} do
185
255
  path = params[:captures].first
@@ -187,22 +257,17 @@ class ShowOff < Sinatra::Application
187
257
  send_file full_path
188
258
  end
189
259
 
190
- get '/slides' do
191
- get_slides_html
260
+ get %r{/(.*)} do
261
+ what = params[:captures].first
262
+ what = 'index' if "" == what
263
+ data = send(what)
264
+ if data.is_a?(File)
265
+ send_file data.path
266
+ else
267
+ data
268
+ end
192
269
  end
193
270
 
194
- get '/onepage' do
195
- @slides = get_slides_html
196
- erb :onepage
197
- end
198
-
199
- get '/pdf' do
200
- @slides = get_slides_html
201
- @no_js = true
202
- html = erb :onepage
203
- p = Princely.new
204
- p.pdf_from_string_to_file(html, '/tmp/preso.pdf')
205
- send_file '/tmp/preso.pdf'
206
- end
271
+
207
272
 
208
273
  end
@@ -191,9 +191,10 @@ a.fg-button { float:left; }
191
191
  padding:15px;
192
192
  margin:0px;
193
193
  font-family: monospace;
194
+ z-index: 2147483647; //max, see http://www.puidokas.com/max-z-index/
194
195
  }
195
196
 
196
197
  .executing {
197
198
  color:#0000FF !important;
198
199
  background-color: yellow;
199
- }
200
+ }
data/public/js/showoff.js CHANGED
@@ -12,8 +12,10 @@ var incrElem
12
12
  var incrCurr = 0
13
13
  var incrCode = false
14
14
  var debugMode = false
15
+ var gotoSlidenum = 0
15
16
 
16
- function setupPreso() {
17
+
18
+ function setupPreso(load_slides, prefix) {
17
19
  if (preso_started)
18
20
  {
19
21
  alert("already started")
@@ -21,7 +23,9 @@ function setupPreso() {
21
23
  }
22
24
  preso_started = true
23
25
 
24
- loadSlides()
26
+
27
+ loadSlides(load_slides, prefix)
28
+
25
29
  doDebugStuff()
26
30
 
27
31
  // bind event handlers
@@ -31,16 +35,22 @@ function setupPreso() {
31
35
  /* window.onunload = unloaded; */
32
36
  }
33
37
 
34
- function loadSlides() {
38
+ function loadSlides(load_slides, prefix) {
35
39
  //load slides offscreen, wait for images and then initialize
36
- $("#slides").load("/slides", false, function(){
37
- $("#slides img").batchImageLoad({
38
- loadingCompleteCallback: initializePresentation
40
+ if (load_slides) {
41
+ $("#slides").load("/slides", false, function(){
42
+ $("#slides img").batchImageLoad({
43
+ loadingCompleteCallback: initializePresentation(prefix)
39
44
  })
40
- })
45
+ })
46
+ } else {
47
+ $("#slides img").batchImageLoad({
48
+ loadingCompleteCallback: initializePresentation(prefix)
49
+ })
50
+ }
41
51
  }
42
52
 
43
- function initializePresentation() {
53
+ function initializePresentation(prefix) {
44
54
  //center slides offscreen
45
55
  centerSlides($('#slides > .slide'))
46
56
 
@@ -65,7 +75,7 @@ function initializePresentation() {
65
75
  showFirstSlide()
66
76
  slidesLoaded = true
67
77
  }
68
- sh_highlightDocument('/js/sh_lang/', '.min.js')
78
+ sh_highlightDocument(prefix+'/js/sh_lang/', '.min.js')
69
79
  }
70
80
 
71
81
  function centerSlides(slides) {
@@ -130,12 +140,23 @@ function showSlide(back_step) {
130
140
  }
131
141
 
132
142
  currentSlide = slides.eq(slidenum)
143
+
133
144
  var transition = currentSlide.attr('data-transition')
134
- if (back_step) {
145
+ var fullPage = currentSlide.find(".content").is('.full-page');
146
+
147
+ if (back_step || fullPage) {
135
148
  transition = 'none'
136
149
  }
150
+
137
151
  $('#preso').cycle(slidenum, transition)
138
152
 
153
+ if (fullPage) {
154
+ $('#preso').css({'width' : '100%', 'overflow' : 'visible'});
155
+ currentSlide.css({'width' : '100%', 'text-align' : 'center', 'overflow' : 'visible'});
156
+ } else {
157
+ $('#preso').css({'width' : '1020px', 'overflow' : 'hidden'});
158
+ }
159
+
139
160
  percent = getSlidePercent()
140
161
  $("#slideInfo").text((slidenum + 1) + '/' + slideTotal + ' - ' + percent + '%')
141
162
 
@@ -213,6 +234,19 @@ function keyDown(event)
213
234
 
214
235
  debug('key: ' + key)
215
236
 
237
+ if (key >= 48 && key <= 57) // 0 - 9
238
+ {
239
+ gotoSlidenum = gotoSlidenum * 10 + (key - 48);
240
+ return true;
241
+ }
242
+ if (key == 13 && gotoSlidenum > 0)
243
+ {
244
+ debug('go to ' + gotoSlidenum);
245
+ slidenum = gotoSlidenum - 1;
246
+ showSlide(true);
247
+ }
248
+ gotoSlidenum = 0;
249
+
216
250
  if (key == 32) // space bar
217
251
  {
218
252
  nextStep()
@@ -222,12 +256,12 @@ function keyDown(event)
222
256
  debugMode = !debugMode
223
257
  doDebugStuff()
224
258
  }
225
- else if (key == 37) // Left arrow
259
+ else if (key == 37 || key == 33) // Left arrow or page up
226
260
  {
227
261
  slidenum--
228
262
  showSlide(true) // We show the slide fully loaded
229
263
  }
230
- else if (key == 39) // Right arrow
264
+ else if (key == 39 || key == 34) // Right arrow or page down
231
265
  {
232
266
  nextStep()
233
267
  }
data/views/index.erb CHANGED
@@ -7,22 +7,22 @@
7
7
 
8
8
  <title>Presentation</title>
9
9
 
10
- <link rel="stylesheet" href="css/reset.css" type="text/css"/>
11
- <link rel="stylesheet" href="css/showoff.css" type="text/css"/>
10
+ <link rel="stylesheet" href="<%= @asset_path %>/css/reset.css" type="text/css"/>
11
+ <link rel="stylesheet" href="<%= @asset_path %>/css/showoff.css" type="text/css"/>
12
12
 
13
- <script type="text/javascript" src="/js/jquery-1.4.min.js"></script>
14
- <script type="text/javascript" src="/js/jquery.cycle.all.js"></script>
15
- <script type="text/javascript" src="/js/jquery.batchImageLoad.js"></script>
16
- <script type="text/javascript" src="/js/jquery-print.js"></script>
17
- <script type="text/javascript" src="/js/fg.menu.js"></script>
18
- <script type="text/javascript" src="/js/showoff.js"></script>
19
- <script type="text/javascript" src="/js/jTypeWriter.js"> </script>
13
+ <script type="text/javascript" src="<%= @asset_path %>/js/jquery-1.4.min.js"></script>
14
+ <script type="text/javascript" src="<%= @asset_path %>/js/jquery.cycle.all.js"></script>
15
+ <script type="text/javascript" src="<%= @asset_path %>/js/jquery.batchImageLoad.js"></script>
16
+ <script type="text/javascript" src="<%= @asset_path %>/js/jquery-print.js"></script>
17
+ <script type="text/javascript" src="<%= @asset_path %>/js/fg.menu.js"></script>
18
+ <script type="text/javascript" src="<%= @asset_path %>/js/showoff.js"></script>
19
+ <script type="text/javascript" src="<%= @asset_path %>/js/jTypeWriter.js"> </script>
20
20
 
21
- <script type="text/javascript" src="/js/sh_main.min.js"></script>
21
+ <script type="text/javascript" src="<%= @asset_path %>/js/sh_main.min.js"></script>
22
22
 
23
- <link type="text/css" href="/css/fg.menu.css" media="screen" rel="stylesheet" />
24
- <link type="text/css" href="/css/theme/ui.all.css" media="screen" rel="stylesheet" />
25
- <link type="text/css" href="/css/sh_style.css" rel="stylesheet" >
23
+ <link type="text/css" href="<%= @asset_path %>/css/fg.menu.css" media="screen" rel="stylesheet" />
24
+ <link type="text/css" href="<%= @asset_path %>/css/theme/ui.all.css" media="screen" rel="stylesheet" />
25
+ <link type="text/css" href="<%= @asset_path %>/css/sh_style.css" rel="stylesheet" >
26
26
 
27
27
  <% css_files.each do |css_file| %>
28
28
  <link rel="stylesheet" href="file/<%= css_file %>" type="text/css"/>
@@ -33,8 +33,9 @@
33
33
  <% end %>
34
34
 
35
35
  <script type="text/javascript">
36
+
36
37
  $(document).ready(function() {
37
- setupPreso();
38
+ setupPreso(<%= @slides.nil? ? "true" : "false"%>, '<%= @asset_path %>');
38
39
  });
39
40
  </script>
40
41
  </head>
@@ -50,8 +51,10 @@
50
51
  <tr><td class="key">space, &rarr;</td><td>next slide</td></tr>
51
52
  <tr><td class="key">&larr;</td><td>previous slide</td></tr>
52
53
  <tr><td class="key">d</td><td>debug mode</td></tr>
54
+ <tr><td class="key">## &lt;ret&gt;</td><td>go to slide #</td></tr>
53
55
  <tr><td class="key">c</td><td>table of contents (vi)</td></tr>
54
56
  <tr><td class="key">f</td><td>toggle footer</td></tr>
57
+ <tr><td class="key">r</td><td>reload slides</td></tr>
55
58
  <tr><td class="key">z</td><td>toggle help (this)</td></tr>
56
59
  </table>
57
60
  </div>
@@ -62,7 +65,9 @@
62
65
  <span id="debugInfo"></span>
63
66
  </div>
64
67
 
65
- <div id="slides" class="offscreen"></div>
68
+ <div id="slides" class="offscreen" <%= 'style="display:none;"' if @slides %>>
69
+ <%= @slides %>
70
+ </div>
66
71
 
67
72
  </body>
68
73
  </html>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: showoff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Chacon