showoff 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/showoff.rb +54 -25
- data/lib/showoff_utils.rb +25 -9
- data/views/index.erb +1 -1
- metadata +43 -25
- data/public/js/showoff.client.js +0 -80
data/lib/showoff.rb
CHANGED
@@ -13,13 +13,12 @@ rescue LoadError
|
|
13
13
|
end
|
14
14
|
|
15
15
|
begin
|
16
|
-
require 'prawn'
|
17
16
|
require 'princely'
|
18
17
|
rescue LoadError
|
19
|
-
puts 'pdf generation disabled - install
|
18
|
+
puts 'pdf generation disabled - install princely'
|
20
19
|
end
|
21
20
|
|
22
|
-
begin
|
21
|
+
begin
|
23
22
|
require 'rdiscount'
|
24
23
|
rescue LoadError
|
25
24
|
require 'bluecloth'
|
@@ -34,7 +33,7 @@ class ShowOff < Sinatra::Application
|
|
34
33
|
set :views, File.dirname(__FILE__) + '/../views'
|
35
34
|
set :public, File.dirname(__FILE__) + '/../public'
|
36
35
|
set :pres_dir, 'example'
|
37
|
-
|
36
|
+
|
38
37
|
def initialize(app=nil)
|
39
38
|
super(app)
|
40
39
|
puts dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
@@ -77,7 +76,7 @@ class ShowOff < Sinatra::Application
|
|
77
76
|
md = ''
|
78
77
|
# extract content classes
|
79
78
|
lines = slide.split("\n")
|
80
|
-
content_classes = lines.shift.split
|
79
|
+
content_classes = lines.shift.split rescue []
|
81
80
|
slide = lines.join("\n")
|
82
81
|
# add content class too
|
83
82
|
content_classes.unshift "content"
|
@@ -94,7 +93,7 @@ class ShowOff < Sinatra::Application
|
|
94
93
|
else
|
95
94
|
md += "<div class=\"#{content_classes.join(' ')}\" ref=\"#{name}\">\n"
|
96
95
|
end
|
97
|
-
sl = Markdown.new(slide).to_html
|
96
|
+
sl = Markdown.new(slide).to_html
|
98
97
|
sl = update_image_paths(name, sl, static)
|
99
98
|
md += sl
|
100
99
|
md += "</div>\n"
|
@@ -143,7 +142,7 @@ class ShowOff < Sinatra::Application
|
|
143
142
|
|
144
143
|
def update_commandline_code(slide)
|
145
144
|
html = Nokogiri::XML.parse(slide)
|
146
|
-
|
145
|
+
|
147
146
|
html.css('pre').each do |pre|
|
148
147
|
pre.css('code').each do |code|
|
149
148
|
out = code.text
|
@@ -176,14 +175,12 @@ class ShowOff < Sinatra::Application
|
|
176
175
|
end
|
177
176
|
html.root.to_s
|
178
177
|
end
|
179
|
-
|
178
|
+
|
180
179
|
def get_slides_html(static=false)
|
181
|
-
|
180
|
+
sections = ShowOffUtils.showoff_sections(options.pres_dir)
|
182
181
|
files = []
|
183
|
-
if
|
184
|
-
|
185
|
-
order = order.map { |s| s['section'] }
|
186
|
-
order.each do |section|
|
182
|
+
if sections
|
183
|
+
sections.each do |section|
|
187
184
|
files << load_section_files(section)
|
188
185
|
end
|
189
186
|
files = files.flatten
|
@@ -201,9 +198,9 @@ class ShowOff < Sinatra::Application
|
|
201
198
|
css_content = '<style type="text/css">'
|
202
199
|
csses.each do |css_file|
|
203
200
|
if pre
|
204
|
-
css_file = File.join(File.dirname(__FILE__), '..', pre, css_file)
|
201
|
+
css_file = File.join(File.dirname(__FILE__), '..', pre, css_file)
|
205
202
|
else
|
206
|
-
css_file = File.join(options.pres_dir, css_file)
|
203
|
+
css_file = File.join(options.pres_dir, css_file)
|
207
204
|
end
|
208
205
|
css_content += File.read(css_file)
|
209
206
|
end
|
@@ -215,16 +212,16 @@ class ShowOff < Sinatra::Application
|
|
215
212
|
js_content = '<script type="text/javascript">'
|
216
213
|
jses.each do |js_file|
|
217
214
|
if pre
|
218
|
-
js_file = File.join(File.dirname(__FILE__), '..', pre, js_file)
|
215
|
+
js_file = File.join(File.dirname(__FILE__), '..', pre, js_file)
|
219
216
|
else
|
220
|
-
js_file = File.join(options.pres_dir, js_file)
|
217
|
+
js_file = File.join(options.pres_dir, js_file)
|
221
218
|
end
|
222
219
|
js_content += File.read(js_file)
|
223
220
|
end
|
224
221
|
js_content += '</script>'
|
225
222
|
js_content
|
226
223
|
end
|
227
|
-
|
224
|
+
|
228
225
|
def index(static=false)
|
229
226
|
if static
|
230
227
|
@slides = get_slides_html(static)
|
@@ -233,6 +230,37 @@ class ShowOff < Sinatra::Application
|
|
233
230
|
erb :index
|
234
231
|
end
|
235
232
|
|
233
|
+
def clean_link(href)
|
234
|
+
if href && href[0, 1] == '/'
|
235
|
+
href = href[1, href.size]
|
236
|
+
end
|
237
|
+
href
|
238
|
+
end
|
239
|
+
|
240
|
+
def assets_needed
|
241
|
+
assets = ["index", "slides"]
|
242
|
+
|
243
|
+
index = erb :index
|
244
|
+
html = Nokogiri::XML.parse(index)
|
245
|
+
html.css('head link').each do |link|
|
246
|
+
href = clean_link(link['href'])
|
247
|
+
assets << href if href
|
248
|
+
end
|
249
|
+
html.css('head script').each do |link|
|
250
|
+
href = clean_link(link['src'])
|
251
|
+
assets << href if href
|
252
|
+
end
|
253
|
+
|
254
|
+
slides = get_slides_html
|
255
|
+
html = Nokogiri::XML.parse("<slides>" + slides + "</slides>")
|
256
|
+
html.css('img').each do |link|
|
257
|
+
href = clean_link(link['src'])
|
258
|
+
assets << href if href
|
259
|
+
end
|
260
|
+
|
261
|
+
assets.join("\n")
|
262
|
+
end
|
263
|
+
|
236
264
|
def slides(static=false)
|
237
265
|
get_slides_html(static)
|
238
266
|
end
|
@@ -253,11 +281,11 @@ class ShowOff < Sinatra::Application
|
|
253
281
|
end
|
254
282
|
|
255
283
|
end
|
256
|
-
|
257
|
-
|
284
|
+
|
285
|
+
|
258
286
|
def self.do_static(what)
|
259
287
|
what = "index" if !what
|
260
|
-
|
288
|
+
|
261
289
|
# Nasty hack to get the actual ShowOff module
|
262
290
|
showoff = ShowOff.new
|
263
291
|
while !showoff.is_a?(ShowOff)
|
@@ -282,7 +310,7 @@ class ShowOff < Sinatra::Application
|
|
282
310
|
FileUtils.copy_entry("#{my_path}/#{dir}", "#{out}/#{dir}")
|
283
311
|
}
|
284
312
|
# And copy the directory
|
285
|
-
Dir.glob("#{my_path}/#{name}/*").each { |subpath|
|
313
|
+
Dir.glob("#{my_path}/#{name}/*").each { |subpath|
|
286
314
|
base = File.basename(subpath)
|
287
315
|
next if "static" == base
|
288
316
|
next unless File.directory?(subpath) || base.match(/\.(css|js)$/)
|
@@ -290,7 +318,7 @@ class ShowOff < Sinatra::Application
|
|
290
318
|
}
|
291
319
|
end
|
292
320
|
end
|
293
|
-
|
321
|
+
|
294
322
|
|
295
323
|
|
296
324
|
get %r{(?:image|file)/(.*)} do
|
@@ -300,8 +328,9 @@ class ShowOff < Sinatra::Application
|
|
300
328
|
end
|
301
329
|
|
302
330
|
get %r{/(.*)} do
|
331
|
+
@title = 'testing'
|
303
332
|
what = params[:captures].first
|
304
|
-
what = 'index' if "" == what
|
333
|
+
what = 'index' if "" == what
|
305
334
|
if (what != "favicon.ico")
|
306
335
|
data = send(what)
|
307
336
|
if data.is_a?(File)
|
@@ -312,6 +341,6 @@ class ShowOff < Sinatra::Application
|
|
312
341
|
end
|
313
342
|
end
|
314
343
|
|
315
|
-
|
344
|
+
|
316
345
|
|
317
346
|
end
|
data/lib/showoff_utils.rb
CHANGED
@@ -17,7 +17,7 @@ class ShowOffUtils
|
|
17
17
|
|
18
18
|
# create showoff.json
|
19
19
|
File.open(SHOWOFF_JSON_FILE, 'w+') do |f|
|
20
|
-
f.puts "[ {\"section\":\"#{dir}\"} ]"
|
20
|
+
f.puts "{ \"name\": \"My Preso\", \"sections\": [ {\"section\":\"#{dir}\"} ]}"
|
21
21
|
end
|
22
22
|
|
23
23
|
if create_samples
|
@@ -87,7 +87,7 @@ class ShowOffUtils
|
|
87
87
|
|
88
88
|
|
89
89
|
# Adds a new slide to a given dir, giving it a number such that it falls after all slides
|
90
|
-
# in that dir.
|
90
|
+
# in that dir.
|
91
91
|
# Options are:
|
92
92
|
# [:dir] - dir where we put the slide (if omitted, slide is output to $stdout)
|
93
93
|
# [:name] - name of the file, without the number prefix. (if omitted, a default is used)
|
@@ -125,7 +125,7 @@ class ShowOffUtils
|
|
125
125
|
# the end of showoff.json as well
|
126
126
|
def self.add_new_dir(dir)
|
127
127
|
puts "Creating #{dir}..."
|
128
|
-
Dir.mkdir dir
|
128
|
+
Dir.mkdir dir
|
129
129
|
|
130
130
|
showoff_json = JSON.parse(File.read(SHOWOFF_JSON_FILE))
|
131
131
|
showoff_json << { "section" => dir }
|
@@ -135,7 +135,7 @@ class ShowOffUtils
|
|
135
135
|
puts "#{SHOWOFF_JSON_FILE} updated"
|
136
136
|
end
|
137
137
|
|
138
|
-
def self.blank?(string)
|
138
|
+
def self.blank?(string)
|
139
139
|
string.nil? || string.strip.length == 0
|
140
140
|
end
|
141
141
|
|
@@ -182,7 +182,7 @@ class ShowOffUtils
|
|
182
182
|
|
183
183
|
def self.determine_title(title,slide_name,code)
|
184
184
|
if blank?(title)
|
185
|
-
title = slide_name
|
185
|
+
title = slide_name
|
186
186
|
title = File.basename(code) if code
|
187
187
|
end
|
188
188
|
title = "Title here" if blank?(title)
|
@@ -198,12 +198,12 @@ class ShowOffUtils
|
|
198
198
|
size = "small" if lines > 15
|
199
199
|
size = "smaller" if width > 57
|
200
200
|
size = "smaller" if lines > 19
|
201
|
-
puts "warning, some lines are too long and the code may be cut off" if width > 65
|
201
|
+
puts "warning, some lines are too long and the code may be cut off" if width > 65
|
202
202
|
puts "warning, your code is too long and the code may be cut off" if lines > 23
|
203
203
|
size
|
204
204
|
end
|
205
205
|
|
206
|
-
# Reads the code from the source file, returning
|
206
|
+
# Reads the code from the source file, returning
|
207
207
|
# the code, indented for markdown, as well as the number of lines
|
208
208
|
# and the width of the largest line
|
209
209
|
def self.read_code(source_file)
|
@@ -211,7 +211,7 @@ class ShowOffUtils
|
|
211
211
|
lines = 0
|
212
212
|
width = 0
|
213
213
|
File.open(source_file) do |code_file|
|
214
|
-
code_file.readlines.each do |line|
|
214
|
+
code_file.readlines.each do |line|
|
215
215
|
code += " #{line}"
|
216
216
|
lines += 1
|
217
217
|
width = line.length if line.length > width
|
@@ -220,7 +220,23 @@ class ShowOffUtils
|
|
220
220
|
[code,lines,width]
|
221
221
|
end
|
222
222
|
|
223
|
-
|
223
|
+
def self.showoff_sections(dir = '.')
|
224
|
+
index = File.join(dir, ShowOffUtils::SHOWOFF_JSON_FILE )
|
225
|
+
order = nil
|
226
|
+
if File.exists?(index)
|
227
|
+
data = JSON.parse(File.read(index))
|
228
|
+
pp data
|
229
|
+
if data.is_a?(Hash)
|
230
|
+
order = data['sections']
|
231
|
+
else
|
232
|
+
order = data
|
233
|
+
end
|
234
|
+
order = order.map { |s| s['section'] }
|
235
|
+
end
|
236
|
+
order
|
237
|
+
end
|
238
|
+
|
239
|
+
EXTENSIONS = {
|
224
240
|
'pl' => 'perl',
|
225
241
|
'rb' => 'ruby',
|
226
242
|
'erl' => 'erlang',
|
data/views/index.erb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
5
|
<head>
|
6
6
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
7
|
-
<title
|
7
|
+
<title><%= @title %></title>
|
8
8
|
|
9
9
|
<link rel="stylesheet" href="<%= @asset_path %>/css/reset.css" type="text/css"/>
|
10
10
|
<link rel="stylesheet" href="<%= @asset_path %>/css/showoff.css" type="text/css"/>
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: showoff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 3
|
9
|
+
version: 0.2.3
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Scott Chacon
|
@@ -14,54 +19,66 @@ default_executable:
|
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: sinatra
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
23
29
|
version: "0"
|
24
|
-
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
25
32
|
- !ruby/object:Gem::Dependency
|
26
33
|
name: bluecloth
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
37
|
- - ">="
|
32
38
|
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
33
41
|
version: "0"
|
34
|
-
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id002
|
35
44
|
- !ruby/object:Gem::Dependency
|
36
45
|
name: nokogiri
|
37
|
-
|
38
|
-
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
48
|
requirements:
|
41
49
|
- - ">="
|
42
50
|
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
43
53
|
version: "0"
|
44
|
-
|
54
|
+
type: :runtime
|
55
|
+
version_requirements: *id003
|
45
56
|
- !ruby/object:Gem::Dependency
|
46
57
|
name: json
|
47
|
-
|
48
|
-
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
60
|
requirements:
|
51
61
|
- - ">="
|
52
62
|
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
53
65
|
version: "0"
|
54
|
-
|
66
|
+
type: :runtime
|
67
|
+
version_requirements: *id004
|
55
68
|
- !ruby/object:Gem::Dependency
|
56
69
|
name: gli
|
57
|
-
|
58
|
-
|
59
|
-
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
60
72
|
requirements:
|
61
73
|
- - ">="
|
62
74
|
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 1
|
77
|
+
- 1
|
78
|
+
- 0
|
63
79
|
version: 1.1.0
|
64
|
-
|
80
|
+
type: :runtime
|
81
|
+
version_requirements: *id005
|
65
82
|
description: " ShowOff is a Sinatra web app that reads simple configuration files for a\n presentation. It is sort of like a Keynote web app engine. I am using it\n to do all my talks in 2010, because I have a deep hatred in my heart for\n Keynote and yet it is by far the best in the field.\n\n The idea is that you setup your slide files in section subdirectories and\n then startup the showoff server in that directory. It will read in your\n showoff.json file for which sections go in which order and then will give \n you a URL to present from.\n"
|
66
83
|
email: schacon@gmail.com
|
67
84
|
executables:
|
@@ -165,7 +182,6 @@ files:
|
|
165
182
|
- public/js/sh_lang/sh_xml.min.js
|
166
183
|
- public/js/sh_lang/sh_xorg.min.js
|
167
184
|
- public/js/sh_main.min.js
|
168
|
-
- public/js/showoff.client.js
|
169
185
|
- public/js/showoff.js
|
170
186
|
has_rdoc: true
|
171
187
|
homepage: http://github.com/schacon/showoff
|
@@ -180,18 +196,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
196
|
requirements:
|
181
197
|
- - ">="
|
182
198
|
- !ruby/object:Gem::Version
|
199
|
+
segments:
|
200
|
+
- 0
|
183
201
|
version: "0"
|
184
|
-
version:
|
185
202
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
203
|
requirements:
|
187
204
|
- - ">="
|
188
205
|
- !ruby/object:Gem::Version
|
206
|
+
segments:
|
207
|
+
- 0
|
189
208
|
version: "0"
|
190
|
-
version:
|
191
209
|
requirements: []
|
192
210
|
|
193
211
|
rubyforge_project:
|
194
|
-
rubygems_version: 1.3.
|
212
|
+
rubygems_version: 1.3.6
|
195
213
|
signing_key:
|
196
214
|
specification_version: 3
|
197
215
|
summary: The best damn presentation software a developer could ever love.
|
data/public/js/showoff.client.js
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
//alert($.uuid('c-'))
|
2
|
-
//alert($.uuid('p-'))
|
3
|
-
//$.ws.conn({
|
4
|
-
// url : 'ws://localhost:3840/connect?to=master&id=client',
|
5
|
-
// onopen : function () {
|
6
|
-
// console.log('connected');
|
7
|
-
// },
|
8
|
-
// onmessage : function (data) {
|
9
|
-
// console.log("received: " + data)
|
10
|
-
// if(data == 'next') {
|
11
|
-
// nextStep()
|
12
|
-
// } else if(data == 'prev') {
|
13
|
-
// prevStep()
|
14
|
-
// } else if(data.match(/^\d+$/)) {
|
15
|
-
// gotoSlide(data)
|
16
|
-
// }
|
17
|
-
// },
|
18
|
-
// onclose : function (event) {
|
19
|
-
// console.log('disconnected');
|
20
|
-
// }
|
21
|
-
//})
|
22
|
-
|
23
|
-
(function($) {
|
24
|
-
var client = ShowOff.Client = function() {
|
25
|
-
this.id = $.cookie('showoff-client-id')
|
26
|
-
if(!this.id) {
|
27
|
-
this.id = $.uuid('c-')
|
28
|
-
$.cookie('showoff-client-id', this.id)
|
29
|
-
}
|
30
|
-
this.master = false;
|
31
|
-
}
|
32
|
-
|
33
|
-
// a no-op until the client is connected
|
34
|
-
client.send = client.sendToClients = function() {}
|
35
|
-
|
36
|
-
client.create = function() {
|
37
|
-
ShowOff.Client = new ShowOff.Client();
|
38
|
-
return ShowOff.Client;
|
39
|
-
}
|
40
|
-
|
41
|
-
client.prototype.watchPresentation = function(host, port, presentationId) {
|
42
|
-
var url = 'ws://' + host + ':' + port + '/connect?to=' + presentationId + '&id=' + this.id;
|
43
|
-
var cli = this;
|
44
|
-
this.socket = $.ws.conn({
|
45
|
-
url : url,
|
46
|
-
onmessage : this.onMessage,
|
47
|
-
onopen : function () {
|
48
|
-
console.log('connected to ' + url);
|
49
|
-
},
|
50
|
-
onclose : function () {
|
51
|
-
console.log('disconnected');
|
52
|
-
}
|
53
|
-
})
|
54
|
-
}
|
55
|
-
|
56
|
-
client.prototype.onMessage = function(data) {
|
57
|
-
var cli = ShowOff.Client;
|
58
|
-
console.log("recd: " + data)
|
59
|
-
switch(data) {
|
60
|
-
case 'master':
|
61
|
-
cli.master = true;
|
62
|
-
break;
|
63
|
-
case 'next':
|
64
|
-
nextStep();
|
65
|
-
break;
|
66
|
-
default:
|
67
|
-
if(data.match(/^\d+$/))
|
68
|
-
gotoSlide(data);
|
69
|
-
}
|
70
|
-
}
|
71
|
-
|
72
|
-
client.prototype.sendToClients = function(data) {
|
73
|
-
if(!this.master) return
|
74
|
-
this.send(data)
|
75
|
-
}
|
76
|
-
|
77
|
-
client.prototype.send = function(data) {
|
78
|
-
this.socket.send(data);
|
79
|
-
}
|
80
|
-
})(jQuery)
|