showoff 0.1.0 → 0.1.1
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 +66 -17
- data/lib/showoff.rb +20 -17
- data/public/css/onepage.css +1 -1
- data/public/css/pdf.css +1 -1
- data/public/css/reset.css +53 -0
- data/public/css/showoff.css +17 -27
- data/public/js/jquery.batchImageLoad.js +56 -0
- data/public/js/jquery.cycle.all.js +1284 -0
- data/public/js/onepage.js +1 -6
- data/public/js/showoff.js +66 -29
- data/views/index.erb +6 -3
- data/views/onepage.erb +2 -2
- metadata +6 -3
data/README.txt
CHANGED
@@ -2,13 +2,13 @@ ShowOff Presentation Software
|
|
2
2
|
=============================
|
3
3
|
|
4
4
|
ShowOff is a Sinatra web app that reads simple configuration files for a
|
5
|
-
presentation. It is sort of like a Keynote web app engine - think S5 +
|
6
|
-
Slidedown. I am using it to do all my talks in 2010, because I have a deep
|
5
|
+
presentation. It is sort of like a Keynote web app engine - think S5 +
|
6
|
+
Slidedown. I am using it to do all my talks in 2010, because I have a deep
|
7
7
|
hatred in my heart for Keynote and yet it is by far the best in the field.
|
8
8
|
|
9
9
|
The idea is that you setup your markdown slide files in section subdirectories
|
10
10
|
and then startup the showoff server in that directory. It will read in your
|
11
|
-
showoff.json file for which sections go in which order and then will give
|
11
|
+
showoff.json file for which sections go in which order and then will give
|
12
12
|
you a URL to present from.
|
13
13
|
|
14
14
|
It can:
|
@@ -20,10 +20,10 @@ It can:
|
|
20
20
|
* re-enact command line interactions
|
21
21
|
* call up a menu of sections/slides at any time to jump around
|
22
22
|
* execute javascript or ruby live and display results
|
23
|
+
* do simple transitions (instant, fade, slide in)
|
23
24
|
|
24
25
|
It might will can:
|
25
26
|
|
26
|
-
* do simple transitions (instant, fade, slide in)
|
27
27
|
* show a timer - elapsed / remaining
|
28
28
|
* perform simple animations of images moving between keyframes
|
29
29
|
* show syncronized, hidden notes on another browser (like an iphone)
|
@@ -48,7 +48,7 @@ it has a showoff.json file and a number of sections (subdirectories) with markdo
|
|
48
48
|
$ cd (showoff-repo)
|
49
49
|
$ showoff serve
|
50
50
|
|
51
|
-
If you run 'showoff' in the ShowOff directory itself, it will show an example
|
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
54
|
Slide Format
|
@@ -60,7 +60,7 @@ your showoff.json file for any markdown files (.md). Each markdown file can
|
|
60
60
|
have any number of slides in it, seperating each slide with the '!SLIDE'
|
61
61
|
keyword and optional slide styles.
|
62
62
|
|
63
|
-
For example, if you run 'showoff create my_new_pres' it will create a new
|
63
|
+
For example, if you run 'showoff create my_new_pres' it will create a new
|
64
64
|
starter presentation for you with one .md file at one/slide.md which will have
|
65
65
|
the following contents:
|
66
66
|
|
@@ -68,7 +68,7 @@ the following contents:
|
|
68
68
|
|
69
69
|
# My Presentation #
|
70
70
|
|
71
|
-
!SLIDE bullets incremental
|
71
|
+
!SLIDE bullets incremental transition=fade
|
72
72
|
|
73
73
|
# Bullet Points #
|
74
74
|
|
@@ -76,17 +76,17 @@ the following contents:
|
|
76
76
|
* second point
|
77
77
|
* third point
|
78
78
|
|
79
|
-
That represents two slides,
|
80
|
-
|
81
|
-
ShowOff to see those slides, your
|
82
|
-
like this:
|
79
|
+
That represents two slides, the first contains just a large title, and the
|
80
|
+
second is faded into view showing the title and three bullets that are then
|
81
|
+
incrementally shown. In order for ShowOff to see those slides, your
|
82
|
+
showoff.json file needs to look something like this:
|
83
83
|
|
84
|
-
[
|
85
|
-
{"section":"one"}
|
84
|
+
[
|
85
|
+
{"section":"one"}
|
86
86
|
]
|
87
87
|
|
88
|
-
If you have multiple sections in your talk, you can make this json array
|
89
|
-
include all the sections you want to show in which order you want to show
|
88
|
+
If you have multiple sections in your talk, you can make this json array
|
89
|
+
include all the sections you want to show in which order you want to show
|
90
90
|
them.
|
91
91
|
|
92
92
|
Some useful styles for each slide are:
|
@@ -96,7 +96,7 @@ Some useful styles for each slide are:
|
|
96
96
|
* smbullets - sizes and seperates more bullets (smaller, closer together)
|
97
97
|
* subsection - creates a different background for titles
|
98
98
|
* command - monospaces h1 title slides
|
99
|
-
* commandline - for pasted commandline sections
|
99
|
+
* commandline - for pasted commandline sections
|
100
100
|
(needs leading '$' for commands, then output on subsequent lines)
|
101
101
|
* code - monospaces everything on the slide
|
102
102
|
* incremental - can be used with 'bullets' and 'commandline' styles,
|
@@ -108,6 +108,43 @@ Some useful styles for each slide are:
|
|
108
108
|
|
109
109
|
Check out the example directory included to see examples of most of these.
|
110
110
|
|
111
|
+
Transitions can be supplied through the use of transition=tname on the !SLIDE
|
112
|
+
definition, where tname is one of the following supported transitions:
|
113
|
+
|
114
|
+
* blindX
|
115
|
+
* blindY
|
116
|
+
* blindZ
|
117
|
+
* cover
|
118
|
+
* curtainX
|
119
|
+
* curtainY
|
120
|
+
* fade
|
121
|
+
* fadeZoom
|
122
|
+
* growX
|
123
|
+
* growY
|
124
|
+
* none (this is the default)
|
125
|
+
* scrollUp
|
126
|
+
* scrollDown
|
127
|
+
* scrollLeft
|
128
|
+
* scrollRight
|
129
|
+
* scrollHorz
|
130
|
+
* scrollVert
|
131
|
+
* shuffle
|
132
|
+
* slideX
|
133
|
+
* slideY
|
134
|
+
* toss
|
135
|
+
* turnUp
|
136
|
+
* turnDown
|
137
|
+
* turnLeft
|
138
|
+
* turnRight
|
139
|
+
* uncover
|
140
|
+
* wipe
|
141
|
+
* zoom
|
142
|
+
|
143
|
+
The transitions are provided by jQuery Cycle plugin. See
|
144
|
+
http://www.malsup.com/jquery/cycle/browser.html to view the effects and
|
145
|
+
http://www.malsup.com/jquery/cycle/adv2.html for how to add
|
146
|
+
custom effects.
|
147
|
+
|
111
148
|
You can manage the presentation with the following keys:
|
112
149
|
|
113
150
|
* space, cursor right: next slide
|
@@ -115,7 +152,7 @@ You can manage the presentation with the following keys:
|
|
115
152
|
* d: debug mode
|
116
153
|
* c: table of contents (vi)
|
117
154
|
* f: toggle footer
|
118
|
-
* z: toggle help
|
155
|
+
* z: toggle help
|
119
156
|
|
120
157
|
Real World Usage
|
121
158
|
====================
|
@@ -134,6 +171,18 @@ So far, ShowOff has been used in the following presentations:
|
|
134
171
|
* LRUG's February meeting - Showing Off with Ruby - Joel Chippindale
|
135
172
|
http://github.com/mocoso/showing-off-with-ruby
|
136
173
|
|
174
|
+
* PyCon 2010 - Hg and Git; Can't we all just get along? - Scott Chacon
|
175
|
+
http://github.com/schacon/pycon-hg-git
|
176
|
+
|
177
|
+
* PdxJs Tech Talk - Asynchronous Coding For My Tiny Ruby Brain - Rick Olson
|
178
|
+
http://github.com/technoweenie/pdxjs-twitter-node
|
179
|
+
|
180
|
+
* RORO Perth Talk - Rails 3; A Brief Introduction — Darcy Laycock
|
181
|
+
http://github.com/Sutto/roro-perth-rails-3
|
182
|
+
|
183
|
+
* PDXRB Tech Talk - Here's Sinatra - Jesse Cooke
|
184
|
+
http://github.com/jc00ke/pdxrb_sinatra
|
185
|
+
|
137
186
|
If you use it for something, please let me know so I can add it.
|
138
187
|
|
139
188
|
Future Plans
|
data/lib/showoff.rb
CHANGED
@@ -3,13 +3,7 @@ require 'sinatra/base'
|
|
3
3
|
require 'json'
|
4
4
|
require 'nokogiri'
|
5
5
|
require 'showoff_utils'
|
6
|
-
|
7
|
-
begin
|
8
|
-
require 'prawn'
|
9
|
-
require 'princely'
|
10
|
-
rescue LoadError
|
11
|
-
puts 'pdf generation disabled - install prawn'
|
12
|
-
end
|
6
|
+
require 'princely'
|
13
7
|
|
14
8
|
begin
|
15
9
|
require 'rdiscount'
|
@@ -52,7 +46,7 @@ class ShowOff < Sinatra::Application
|
|
52
46
|
Dir.glob("#{options.pres_dir}/*.js").map { |path| File.basename(path) }
|
53
47
|
end
|
54
48
|
|
55
|
-
def process_markdown(name, content
|
49
|
+
def process_markdown(name, content)
|
56
50
|
slides = content.split(/^!SLIDE/)
|
57
51
|
slides.delete('')
|
58
52
|
final = ''
|
@@ -61,21 +55,30 @@ class ShowOff < Sinatra::Application
|
|
61
55
|
end
|
62
56
|
slides.each do |slide|
|
63
57
|
md = ''
|
58
|
+
# extract content classes
|
64
59
|
lines = slide.split("\n")
|
65
|
-
|
60
|
+
content_classes = lines.shift.split
|
66
61
|
slide = lines.join("\n")
|
67
|
-
|
62
|
+
# add content class too
|
63
|
+
content_classes.unshift "content"
|
64
|
+
# extract transition, defaulting to none
|
65
|
+
transition = 'none'
|
66
|
+
content_classes.delete_if { |x| x =~ /^transition=(.+)/ && transition = $1 }
|
67
|
+
puts "classes: #{content_classes.inspect}"
|
68
|
+
puts "transition: #{transition}"
|
69
|
+
# create html
|
70
|
+
md += "<div class=\"slide\" data-transition=\"#{transition}\">"
|
68
71
|
if seq
|
69
|
-
md += "<div class=\"
|
72
|
+
md += "<div class=\"#{content_classes.join(' ')}\" ref=\"#{name}/#{seq.to_s}\">\n"
|
70
73
|
seq += 1
|
71
74
|
else
|
72
|
-
md += "<div class=\"
|
75
|
+
md += "<div class=\"#{content_classes.join(' ')}\" ref=\"#{name}\">\n"
|
73
76
|
end
|
74
77
|
sl = Markdown.new(slide).to_html
|
75
78
|
sl = update_image_paths(name, sl)
|
76
79
|
md += sl
|
77
80
|
md += "</div>\n"
|
78
|
-
md += "</div>\n"
|
81
|
+
md += "</div>\n"
|
79
82
|
final += update_commandline_code(md)
|
80
83
|
end
|
81
84
|
final
|
@@ -124,7 +127,7 @@ class ShowOff < Sinatra::Application
|
|
124
127
|
html.root.to_s
|
125
128
|
end
|
126
129
|
|
127
|
-
def get_slides_html
|
130
|
+
def get_slides_html
|
128
131
|
index = File.join(options.pres_dir, 'showoff.json')
|
129
132
|
files = []
|
130
133
|
if File.exists?(index)
|
@@ -138,7 +141,7 @@ class ShowOff < Sinatra::Application
|
|
138
141
|
data = ''
|
139
142
|
files.each do |f|
|
140
143
|
fname = f.gsub(options.pres_dir + '/', '').gsub('.md', '')
|
141
|
-
data += process_markdown(fname, File.read(f)
|
144
|
+
data += process_markdown(fname, File.read(f))
|
142
145
|
end
|
143
146
|
end
|
144
147
|
data
|
@@ -189,12 +192,12 @@ class ShowOff < Sinatra::Application
|
|
189
192
|
end
|
190
193
|
|
191
194
|
get '/onepage' do
|
192
|
-
@slides = get_slides_html
|
195
|
+
@slides = get_slides_html
|
193
196
|
erb :onepage
|
194
197
|
end
|
195
198
|
|
196
199
|
get '/pdf' do
|
197
|
-
@slides = get_slides_html
|
200
|
+
@slides = get_slides_html
|
198
201
|
@no_js = true
|
199
202
|
html = erb :onepage
|
200
203
|
p = Princely.new
|
data/public/css/onepage.css
CHANGED
data/public/css/pdf.css
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
/* http://meyerweb.com/eric/tools/css/reset/ */
|
2
|
+
/* v1.0 | 20080212 */
|
3
|
+
|
4
|
+
html, body, div, span, applet, object, iframe,
|
5
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
6
|
+
a, abbr, acronym, address, big, cite, code,
|
7
|
+
del, dfn, em, font, img, ins, kbd, q, s, samp,
|
8
|
+
small, strike, strong, sub, sup, tt, var,
|
9
|
+
b, u, i, center,
|
10
|
+
dl, dt, dd, ol, ul, li,
|
11
|
+
fieldset, form, label, legend,
|
12
|
+
table, caption, tbody, tfoot, thead, tr, th, td {
|
13
|
+
margin: 0;
|
14
|
+
padding: 0;
|
15
|
+
border: 0;
|
16
|
+
outline: 0;
|
17
|
+
font-size: 100%;
|
18
|
+
vertical-align: baseline;
|
19
|
+
background: transparent;
|
20
|
+
}
|
21
|
+
body {
|
22
|
+
line-height: 1;
|
23
|
+
}
|
24
|
+
ol, ul {
|
25
|
+
list-style: none;
|
26
|
+
}
|
27
|
+
blockquote, q {
|
28
|
+
quotes: none;
|
29
|
+
}
|
30
|
+
blockquote:before, blockquote:after,
|
31
|
+
q:before, q:after {
|
32
|
+
content: '';
|
33
|
+
content: none;
|
34
|
+
}
|
35
|
+
|
36
|
+
/* remember to define focus styles! */
|
37
|
+
:focus {
|
38
|
+
outline: 0;
|
39
|
+
}
|
40
|
+
|
41
|
+
/* remember to highlight inserts somehow! */
|
42
|
+
ins {
|
43
|
+
text-decoration: none;
|
44
|
+
}
|
45
|
+
del {
|
46
|
+
text-decoration: line-through;
|
47
|
+
}
|
48
|
+
|
49
|
+
/* tables still need 'cellspacing="0"' in the markup */
|
50
|
+
table {
|
51
|
+
border-collapse: collapse;
|
52
|
+
border-spacing: 0;
|
53
|
+
}
|
data/public/css/showoff.css
CHANGED
@@ -1,33 +1,25 @@
|
|
1
1
|
body {
|
2
2
|
font-family: "Gill Sans", Helvetica, Arial, sans-serif;
|
3
|
-
padding: 0;
|
4
|
-
margin: 0;
|
5
|
-
border: 0;
|
6
3
|
}
|
7
4
|
|
8
|
-
#preso {
|
9
|
-
|
10
|
-
padding: 0;
|
5
|
+
#preso, .slide {
|
6
|
+
background: #fff;
|
11
7
|
width: 1020px;
|
12
8
|
height: 740px;
|
13
|
-
margin-left:auto;
|
9
|
+
margin-left:auto;
|
14
10
|
margin-right:auto;
|
15
11
|
overflow:hidden;
|
16
12
|
}
|
17
|
-
|
13
|
+
|
14
|
+
#footer {
|
18
15
|
background: #eee;
|
19
|
-
margin: 0;
|
20
16
|
padding: 2px;
|
21
17
|
width: 1010px;
|
22
18
|
height: 20px;
|
23
|
-
margin-left:auto;
|
19
|
+
margin-left:auto;
|
24
20
|
margin-right:auto;
|
25
21
|
}
|
26
22
|
|
27
|
-
.slide {
|
28
|
-
border: 1px solid #fff;
|
29
|
-
}
|
30
|
-
|
31
23
|
.center img {
|
32
24
|
display:block;
|
33
25
|
margin-left:auto;
|
@@ -35,13 +27,7 @@ body {
|
|
35
27
|
}
|
36
28
|
|
37
29
|
.bullets ul {
|
38
|
-
display: block;
|
39
|
-
height: 600px;
|
40
30
|
font-size: 3em;
|
41
|
-
list-style: none;
|
42
|
-
margin-left: 0;
|
43
|
-
padding-left: 1em;
|
44
|
-
text-indent: -1em;
|
45
31
|
}
|
46
32
|
.bullets ul li {
|
47
33
|
text-align: center;
|
@@ -49,13 +35,7 @@ body {
|
|
49
35
|
}
|
50
36
|
|
51
37
|
.smbullets ul {
|
52
|
-
display: block;
|
53
|
-
height: 600px;
|
54
38
|
font-size: 2em;
|
55
|
-
list-style: none;
|
56
|
-
margin-left: 0;
|
57
|
-
padding-left: 1em;
|
58
|
-
text-indent: -1em;
|
59
39
|
}
|
60
40
|
.smbullets ul li {
|
61
41
|
text-align: center;
|
@@ -102,9 +82,14 @@ h1 { font-size: 5em; font-weight: normal; text-align: center;}
|
|
102
82
|
h2 { font-size: 3em; font-weight: normal; text-align: center; }
|
103
83
|
h3 { font-size: 2em; font-weight: normal; text-align: center; }
|
104
84
|
|
85
|
+
h1, h2, h3 {
|
86
|
+
margin: 0.5em 0;
|
87
|
+
}
|
88
|
+
|
105
89
|
pre { margin-left: 40px; font-size: 2.8em; }
|
106
90
|
|
107
91
|
.hidden { position:absolute; top:0; left:-9999px; width:1px; height:1px; overflow:hidden; }
|
92
|
+
.offscreen { position:absolute; top:0; left:-9999px; overflow:hidden; }
|
108
93
|
#debugInfo { margin-left: 30px; }
|
109
94
|
|
110
95
|
#help {
|
@@ -112,6 +97,7 @@ pre { margin-left: 40px; font-size: 2.8em; }
|
|
112
97
|
position: absolute;
|
113
98
|
right: 80px;
|
114
99
|
display: none;
|
100
|
+
z-index: 2147483647; //max, see http://www.puidokas.com/max-z-index/
|
115
101
|
}
|
116
102
|
#help table tr td.key {
|
117
103
|
text-align: right;
|
@@ -120,6 +106,10 @@ pre { margin-left: 40px; font-size: 2.8em; }
|
|
120
106
|
font-weight: bold;
|
121
107
|
}
|
122
108
|
|
109
|
+
.fg-menu-container {
|
110
|
+
z-index: 2147483647; //max, see http://www.puidokas.com/max-z-index/
|
111
|
+
}
|
112
|
+
|
123
113
|
.fg-button { clear:left; margin:0 4px 40px 20px; padding: .4em 1em; text-decoration:none !important; cursor:pointer; position: relative; text-align: center; zoom: 1; }
|
124
114
|
.fg-button .ui-icon { position: absolute; top: 50%; margin-top: -8px; left: 50%; margin-left: -8px; }
|
125
115
|
a.fg-button { float:left; }
|
@@ -190,7 +180,7 @@ a.fg-button { float:left; }
|
|
190
180
|
.code .vi { color: #008080 } /* Name.Variable.Instance */
|
191
181
|
.code .il { color: #009999 } /* Literal.Number.Integer.Long */
|
192
182
|
|
193
|
-
.results {
|
183
|
+
.results {
|
194
184
|
background-color:#002200;
|
195
185
|
color:#00AA00;
|
196
186
|
font-size:2em;
|
@@ -0,0 +1,56 @@
|
|
1
|
+
/**
|
2
|
+
* Plugin which is applied on a list of img objects and calls
|
3
|
+
* the specified callback function, only when all of them are loaded (or errored).
|
4
|
+
* @author: H. Yankov (hristo.yankov at gmail dot com)
|
5
|
+
* @version: 1.0.0 (Feb/22/2010)
|
6
|
+
* http://yankov.us
|
7
|
+
*/
|
8
|
+
|
9
|
+
(function($) {
|
10
|
+
$.fn.batchImageLoad = function(options) {
|
11
|
+
var images = $(this);
|
12
|
+
var originalTotalImagesCount = images.size();
|
13
|
+
var totalImagesCount = originalTotalImagesCount;
|
14
|
+
var elementsLoaded = 0;
|
15
|
+
|
16
|
+
// Init
|
17
|
+
$.fn.batchImageLoad.defaults = {
|
18
|
+
loadingCompleteCallback: null,
|
19
|
+
imageLoadedCallback: null
|
20
|
+
}
|
21
|
+
var opts = $.extend({}, $.fn.batchImageLoad.defaults, options);
|
22
|
+
|
23
|
+
// Start
|
24
|
+
images.each(function() {
|
25
|
+
// The image has already been loaded (cached)
|
26
|
+
if ($(this)[0].complete) {
|
27
|
+
totalImagesCount--;
|
28
|
+
if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
|
29
|
+
// The image is loading, so attach the listener
|
30
|
+
} else {
|
31
|
+
$(this).load(function() {
|
32
|
+
elementsLoaded++;
|
33
|
+
|
34
|
+
if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
|
35
|
+
|
36
|
+
// An image has been loaded
|
37
|
+
if (elementsLoaded >= totalImagesCount)
|
38
|
+
if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
|
39
|
+
});
|
40
|
+
$(this).error(function() {
|
41
|
+
elementsLoaded++;
|
42
|
+
|
43
|
+
if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
|
44
|
+
|
45
|
+
// The image has errored
|
46
|
+
if (elementsLoaded >= totalImagesCount)
|
47
|
+
if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
|
48
|
+
});
|
49
|
+
}
|
50
|
+
});
|
51
|
+
|
52
|
+
// There are no unloaded images
|
53
|
+
if (totalImagesCount <= 0)
|
54
|
+
if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
|
55
|
+
};
|
56
|
+
})(jQuery);
|