showoff 0.1.1 → 0.1.4
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.
- data/README.txt +14 -0
- data/bin/showoff +4 -2
- data/lib/showoff.rb +90 -25
- data/public/css/showoff.css +2 -1
- data/public/js/showoff.js +46 -12
- data/views/index.erb +20 -15
- metadata +1 -1
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
|
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
|
-
|
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
|
-
|
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
|
191
|
-
|
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
|
-
|
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
|
data/public/css/showoff.css
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
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="
|
14
|
-
<script type="text/javascript" src="
|
15
|
-
<script type="text/javascript" src="
|
16
|
-
<script type="text/javascript" src="
|
17
|
-
|
18
|
-
<script type="text/javascript" src="
|
19
|
-
|
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="
|
21
|
+
<script type="text/javascript" src="<%= @asset_path %>/js/sh_main.min.js"></script>
|
22
22
|
|
23
|
-
<link type="text/css" href="
|
24
|
-
<link type="text/css" href="
|
25
|
-
<link type="text/css" href="
|
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, →</td><td>next slide</td></tr>
|
51
52
|
<tr><td class="key">←</td><td>previous slide</td></tr>
|
52
53
|
<tr><td class="key">d</td><td>debug mode</td></tr>
|
54
|
+
<tr><td class="key">## <ret></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"
|
68
|
+
<div id="slides" class="offscreen" <%= 'style="display:none;"' if @slides %>>
|
69
|
+
<%= @slides %>
|
70
|
+
</div>
|
66
71
|
|
67
72
|
</body>
|
68
73
|
</html>
|