parade 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -25,8 +25,8 @@ Parade has over presentational software:
25
25
 
26
26
  * Code Execution
27
27
 
28
- > Slides are able to provide execution and show results for javascript,
29
- Coffeescript, and Ruby live within the browser. Allowing for live
28
+ > Slides are able to provide execution and show results for JavaScript,
29
+ and Coffeescript live within the browser. Allowing for live
30
30
  demonstrations of code.
31
31
 
32
32
  * Web
@@ -301,7 +301,7 @@ Parade defines a number of special CSS classes:
301
301
  > make all slide text 70%
302
302
  >
303
303
  > ### execute
304
- > on Javascript, Coffeescript and Ruby highlighted code slides, you can
304
+ > on Javascript and Coffeescript highlighted code slides, you can
305
305
  > click on the code to execute it and display the results on the slide
306
306
 
307
307
 
@@ -513,6 +513,27 @@ Serves the parade presentation in the current directory
513
513
  >
514
514
  > parade serve
515
515
 
516
+ ## parade static html [path/to/parade/file]
517
+
518
+ Generates a static html representation of the presentation.
519
+
520
+ > ### Options
521
+ >
522
+ > These options are specified *after* the command.
523
+ >
524
+ > *-o, --output=file* Presentation output file
525
+
526
+ ## parade static pdf [path/to/parade/file]
527
+
528
+ Generates a pdf representation of the presentation.
529
+
530
+ > ### Options
531
+ >
532
+ > These options are specified *after* the command.
533
+ >
534
+ > *-o, --output=file* Presentation output file
535
+
536
+
516
537
  # Future Plans
517
538
 
518
539
  I really want this to evolve into a dynamic presentation software server,
data/bin/parade CHANGED
@@ -54,7 +54,7 @@ command [:s,:serve,:server] do |c|
54
54
  puts "
55
55
  -------------------------
56
56
 
57
- Your Parade presentation is now starting up.
57
+ yourr Parade presentation is now starting up.
58
58
 
59
59
  To view it plainly, visit [ #{url} ]
60
60
 
@@ -86,6 +86,9 @@ command [:static] do |c|
86
86
  c.desc "Force creation of the asset, even if one already exists with a similar name"
87
87
  c.switch [:f, :force]
88
88
 
89
+ c.desc 'Output file'
90
+ c.flag [:o,:output]
91
+
89
92
  c.action do |global,local,args|
90
93
 
91
94
  format_type = args.shift
@@ -5,9 +5,9 @@ module Parade
5
5
 
6
6
  #
7
7
  # Saves an html representation of the presentation to a single HTML file.
8
- #
8
+ #
9
9
  # @see HtmlOutput
10
- #
10
+ #
11
11
  class StaticHtml
12
12
  include RenderFromTemplate
13
13
 
@@ -5,7 +5,7 @@ module Parade
5
5
 
6
6
  #
7
7
  # Saves a PDF version of the presentation that is from the HtmlOutput
8
- #
8
+ #
9
9
  class StaticPdf
10
10
 
11
11
  def description
data/lib/parade/server.rb CHANGED
@@ -2,10 +2,6 @@ require_relative 'section'
2
2
  require_relative "parsers/dsl"
3
3
  require_relative 'renderers/update_image_paths'
4
4
 
5
- require_relative 'features/live_ruby'
6
- require_relative 'features/pdf_presentation'
7
- require_relative 'features/preshow'
8
-
9
5
  require_relative 'slide_post_renderers'
10
6
  require_relative 'slide_pre_renderers'
11
7
 
@@ -13,18 +9,17 @@ module Parade
13
9
 
14
10
  class Server < Sinatra::Application
15
11
 
16
- def initialize(app=nil)
17
- super(app)
18
- require_ruby_files
19
- end
20
12
 
21
- def require_ruby_files
22
- Dir.glob("#{settings.presentation_directory}/*.rb").map { |path| require path }
13
+ def self.views_path
14
+ File.dirname(__FILE__) + '/../views'
23
15
  end
24
16
 
25
- set :views, File.dirname(__FILE__) + '/../views'
26
- set :public_folder, File.dirname(__FILE__) + '/../public'
17
+ def self.public_path
18
+ File.dirname(__FILE__) + '/../public'
19
+ end
27
20
 
21
+ set :views, views_path
22
+ set :public_folder, public_path
28
23
  set :verbose, false
29
24
 
30
25
  set :presentation_directory do
@@ -32,9 +27,56 @@ module Parade
32
27
  end
33
28
 
34
29
  set :presentation_file, 'parade'
35
-
36
30
  set :default_presentation_files, [ 'parade', 'parade.json' ]
37
31
 
32
+
33
+ #
34
+ # Includes the specified module into the server to grant the server additional
35
+ # functionality.
36
+ #
37
+ def self.register(server_module)
38
+ include server_module
39
+ end
40
+
41
+ #
42
+ # Register a javascript file that will be loaded after the code javscript
43
+ #
44
+ def self.register_javascript(js_file)
45
+ plugin_javascript_files.push js_file
46
+ end
47
+
48
+ #
49
+ # @return the javascript files that have been registered by plugins
50
+ #
51
+ def self.plugin_javascript_files
52
+ @javscript_files ||= []
53
+ end
54
+
55
+ def self.register_stylesheet(css_file)
56
+ plugin_stylesheet_files.push css_file
57
+ end
58
+
59
+ def self.plugin_stylesheet_files
60
+ @css_files ||= []
61
+ end
62
+
63
+ def self.register_command(input,description)
64
+ plugin_commands.push OpenStruct.new(:input => input,:description => description)
65
+ end
66
+
67
+ def self.plugin_commands
68
+ @plugin_commands ||= []
69
+ end
70
+
71
+ def initialize(app=nil)
72
+ super(app)
73
+ require_ruby_files
74
+ end
75
+
76
+ def require_ruby_files
77
+ Dir.glob("#{settings.presentation_directory}/*.rb").map { |path| require path }
78
+ end
79
+
38
80
  def presentation_files
39
81
  (Array(settings.presentation_file) + settings.default_presentation_files).compact.uniq
40
82
  end
@@ -82,6 +124,18 @@ module Parade
82
124
  end
83
125
  end
84
126
 
127
+ def plugin_css_files
128
+ self.class.plugin_stylesheet_files.map do |path|
129
+ "<style>\n#{File.read(path)}\n</style>"
130
+ end.join("\n")
131
+ end
132
+
133
+ def plugin_js_files
134
+ self.class.plugin_javascript_files.map do |path|
135
+ "<script type='text/javascript'>#{File.read(path)}</script>"
136
+ end.join("\n")
137
+ end
138
+
85
139
  #
86
140
  # Create resources links to all the Javascript files found at the root of
87
141
  # presentation directory.
@@ -92,6 +146,10 @@ module Parade
92
146
  end
93
147
  end
94
148
 
149
+ def plugin_commands
150
+ self.class.plugin_commands
151
+ end
152
+
95
153
  def presentation
96
154
  load_presentation
97
155
  end
@@ -134,10 +192,6 @@ module Parade
134
192
  erb :onepage
135
193
  end
136
194
 
137
- include LiveRuby
138
- include PDFPresentation
139
- include Preshow
140
-
141
195
  end
142
196
 
143
- end
197
+ end
@@ -1,3 +1,3 @@
1
1
  module Parade
2
- VERSION = '0.9.0'
2
+ VERSION = '0.9.1'
3
3
  end
@@ -270,7 +270,6 @@ pre { margin: 1em 40px; padding: .25em; }
270
270
  .offscreen { position:absolute; top:0; left:-9999px; overflow:hidden; }
271
271
  #debugInfo { margin-left: 30px; }
272
272
  #notesInfo { margin-left: 30px; display: none }
273
- #preshow { display: none; }
274
273
 
275
274
  #help {
276
275
  background: #9f9;
@@ -389,7 +388,7 @@ a.fg-button { float:left; }
389
388
  cursor: pointer;
390
389
  }
391
390
 
392
- #tips, #preshow_timer {
391
+ #tips {
393
392
  display:inline;
394
393
  background-color:#000;
395
394
  color:#fff;
@@ -407,10 +406,6 @@ a.fg-button { float:left; }
407
406
  text-align:right;
408
407
  }
409
408
 
410
- #preshow_timer {
411
- bottom: 0px;
412
- }
413
-
414
409
  /** Print **/
415
410
  @media print {
416
411
  body {
@@ -1,5 +1,8 @@
1
1
  window.CodeExecutor = Spine.Class.create({
2
2
  init: function() {
3
+ this.visibleCodeBlocks = {};
4
+ this.executeCodeFor = {}
5
+
3
6
  $.subscribe("code:execute",$.proxy(function(e,code) {
4
7
  this.executeCode(code);
5
8
  },this));
@@ -7,10 +10,9 @@ window.CodeExecutor = Spine.Class.create({
7
10
  this.executeVisibleCode();
8
11
  },this));
9
12
  },
10
- visibleCodeBlocks: function() {
11
- return { ruby : $('.execute .ruby pre:visible'),
12
- js : $('.execute .javascript pre:visible'),
13
- coffee : $('.execute .coffeescript pre:visible') }
13
+ registerVisibleCodeBlock: function(language,elements,execution) {
14
+ this.visibleCodeBlocks[language] = elements;
15
+ this.executeCodeFor[language] = execution;
14
16
  },
15
17
  executeVisibleCode: function() {
16
18
 
@@ -32,35 +34,7 @@ window.CodeExecutor = Spine.Class.create({
32
34
  codeExecutor(code['code']);
33
35
  },
34
36
  executorForLanguage: function(language) {
35
- return this.supportedLanguages()[language];
36
- },
37
- supportedLanguages: function() {
38
- return { ruby : this.executeRuby,
39
- js : this.executeJavaScript,
40
- coffee : this.executeCoffee };
41
- },
42
- executeJavaScript: function(code) {
43
- var result = eval(code);
44
- setTimeout(function() { $.publish('code:execution:finished'); }, 250 );
45
- if (result != null) { $.publish('code:execution:results',result); }
46
- },
47
- executeRuby: function(code) {
48
- $.get('/eval_ruby', { code: code }, function(result) {
49
- if (result != null) { $.publish('code:execution:results',result); }
50
- $.publish('code:execution:finished');
51
- });
52
- },
53
- executeCoffee: function(code) {
54
- // When Coffeescript completes it's work the final result is encapsulated
55
- // within it. To get around it, the result of the last evaluation needs to
56
- // be assigned to the window, which we can then use for the purposes of
57
- // displaying the results.
58
-
59
- var codeWithAssignmentToResults = code + ';window.result=result;'
60
- eval(CoffeeScript.compile(codeWithAssignmentToResults));
61
-
62
- setTimeout(function() { $.publish('code:execution:finished'); }, 250 );
63
- if (result != null) { $.publish('code:execution:results',result); }
37
+ return this.executeCodeFor[language];
64
38
  }
65
39
  });
66
40
 
@@ -104,14 +78,28 @@ $(document).ready(function() {
104
78
  codeExecutor = new CodeExecutor;
105
79
  codeViewer = new CodeViewer;
106
80
 
81
+ codeExecutor.registerVisibleCodeBlock('js',$('.execute .javascript pre:visible'),function(code) {
82
+ var result = eval(code);
83
+ setTimeout(function() { $.publish('code:execution:finished'); }, 250 );
84
+ if (result != null) { $.publish('code:execution:results',result); }
85
+ });
86
+
107
87
  $('.execute pre.javascript').live("click", function() {
108
88
  var code = $(this).text();
109
89
  $.publish('code:execute',{ lang: 'js', code: code, elem: $(this) });
110
90
  });
111
91
 
112
- $('.execute pre.ruby').live("click", function() {
113
- var code = $(this).text();
114
- $.publish('code:execute',{ lang: 'ruby', code: code, elem: $(this) });
92
+ codeExecutor.registerVisibleCodeBlock('coffee',$('.execute .coffeescript pre:visible'), function(code) {
93
+ // When Coffeescript completes it's work the final result is encapsulated
94
+ // within it. To get around it, the result of the last evaluation needs to
95
+ // be assigned to the window, which we can then use for the purposes of
96
+ // displaying the results.
97
+
98
+ var codeWithAssignmentToResults = code + ';window.result=result;'
99
+ eval(CoffeeScript.compile(codeWithAssignmentToResults));
100
+
101
+ setTimeout(function() { $.publish('code:execution:finished'); }, 250 );
102
+ if (result != null) { $.publish('code:execution:results',result); }
115
103
  });
116
104
 
117
105
  $('.execute pre.coffeescript').live("click", function() {
@@ -42,10 +42,6 @@ $(document).ready(function() {
42
42
  $.publish("presentation:pause:toggle");
43
43
  });
44
44
 
45
- MainKeyboard.on('p', function(){
46
- $.publish("presentation:preshow:toggle");
47
- });
48
-
49
45
  MainKeyboard.on('enter', function(){
50
46
  $.publish("code:execute:visible")
51
47
  });
@@ -1,153 +1,5 @@
1
1
  $(document).ready(function() {
2
2
 
3
- window.Preshow = Spine.Class.create({
4
- init: function() {
5
- this.element = $(arguments[0]);
6
- this.secondsToRun = parseFloat(arguments[1] * 60);
7
-
8
- $.subscribe("presentation:preshow:toggle",$.proxy(function() {
9
- this.toggle();
10
- },this));
11
-
12
- },
13
- preshowRunning: false,
14
- start: function() {
15
-
16
- if (this.preshowIntervalReference) {
17
- return;
18
- }
19
-
20
- this.preservePresentationSpace();
21
-
22
- this.load();
23
-
24
- this.images = this.element.children("img");
25
-
26
- this.currentImageIndex = 0;
27
- this.totalImages = this.images.size();
28
-
29
-
30
- this.preshowRunning = true;
31
-
32
- $.publish("presentation:preshow:start");
33
-
34
- this.currentRunTime = 0;
35
- this.currentRemainingTime = this.secondsToRun;
36
-
37
- this.nextImage();
38
- this.preshowIntervalReference = setInterval($.proxy(this.perform,this),1000);
39
-
40
- },
41
- preservePresentationSpace: function() {
42
- this.storedPresentationSpace = this.element.html();
43
- },
44
- restorePresentationSpace: function() {
45
- this.element.empty();
46
- this.element.html(this.storedPresentationSpace);
47
- },
48
- displayImagesInterval: 5,
49
- perform: function() {
50
- this.currentRunTime ++;
51
- this.currentRemainingTime --;
52
-
53
- time = this.secondsToTime(this.currentRemainingTime);
54
-
55
- $('#preshow_timer').text(time + ' to go-time')
56
- var description = this.preshowDescription && this.preshowDescription[tmpImg.attr("ref")]
57
-
58
- if(description) {
59
- $('#tips').show();
60
- $('#tips').text(description);
61
- } else {
62
- $('#tips').hide();
63
- }
64
-
65
- if ((this.currentRunTime % this.displayImagesInterval) == 0) {
66
- this.nextImage();
67
- }
68
-
69
- this.preshowTip();
70
-
71
- if (this.currentRemainingTime <= 0) {
72
- this.stop();
73
- }
74
-
75
- },
76
- stop: function() {
77
-
78
- if (!this.preshowIntervalReference) {
79
- return;
80
- }
81
-
82
- this.preshowRunning = false;
83
- window.clearInterval(this.preshowIntervalReference);
84
- this.preshowIntervalReference = undefined;
85
-
86
- $('#preshow').remove();
87
- $('#tips').remove();
88
- $('#preshow_timer').remove();
89
-
90
- this.restorePresentationSpace();
91
-
92
- $.publish("presentation:preshow:stop");
93
-
94
- },
95
- toggle: function() {
96
-
97
- if (this.preshowIntervalReference) {
98
- this.stop();
99
- } else {
100
- this.start();
101
- }
102
-
103
- },
104
- preshowPath: "preshow",
105
- load: function() {
106
-
107
- $.getJSON(this.preshowPath, false, $.proxy(function(data) {
108
-
109
- this.element.after("<div id='preshow'></div><div id='tips'></div><div id='preshow_timer'></div>")
110
-
111
- $.each(data, $.proxy(function(i, n) {
112
- if(n == "preshow.json") {
113
- // has a descriptions file
114
- $.getJSON("/file/preshow/preshow.json", false, function(data) {
115
- this.preshowDescription = data;
116
- })
117
- } else {
118
- $('#preshow').append('<img ref="' + n + '" src="/file/preshow/' + n + '"/>');
119
- this.images = $("#preshow > img");
120
- this.totalImages = this.images.size();
121
- }
122
- },this));
123
-
124
- },this));
125
-
126
- },
127
- nextImage: function() {
128
- this.currentImageIndex ++;
129
- if((this.currentImageIndex + 1) > this.totalImages) {
130
- this.currentImageIndex = 0;
131
- }
132
-
133
- this.element.empty();
134
- tmpImg = this.images.eq(this.currentImageIndex).clone();
135
- $(tmpImg).attr('width', '1020');
136
- this.element.html(tmpImg);
137
- },
138
- preshowTip: function() {
139
-
140
- },
141
- secondsToTime: function(seconds) {
142
- minutes = Math.floor(seconds / 60)
143
- seconds = seconds - (minutes * 60)
144
- if(seconds < 10) {
145
- seconds = "0" + seconds
146
- }
147
- return minutes + ":" + seconds
148
- }
149
- });
150
-
151
3
  window.ToggleView = Spine.Class.create({
152
4
  init: function () {
153
5
 
@@ -513,23 +365,6 @@ $(document).ready(function() {
513
365
  this.showSlide()
514
366
  },this));
515
367
 
516
- $.subscribe("presentation:preshow:start",$.proxy(function() {
517
- this.footer.hide();
518
- },this));
519
-
520
- $.subscribe("presentation:preshow:stop",$.proxy(function() {
521
- this.footer.show();
522
-
523
- // Returning from a presentation requires the presentation frame to
524
- // be rebuilt.
525
-
526
- this.presentationFrame.cycle({
527
- timeout: 0
528
- });
529
- this.showSlide();
530
-
531
- },this));
532
-
533
368
  },
534
369
  centerSlides: function() {
535
370
  var presentation = this;
@@ -718,8 +553,6 @@ $(document).ready(function() {
718
553
  var locationWatcher = new LocationWatcher();
719
554
  locationWatcher.start();
720
555
 
721
- preshow = new Preshow("#preso",0.25);
722
-
723
556
  // bind event handlers
724
557
  /* window.onresize = resized; */
725
558
  /* window.onscroll = scrolled; */
data/lib/views/header.erb CHANGED
@@ -71,5 +71,8 @@
71
71
 
72
72
  <%= css 'default.css' %>
73
73
 
74
+ <%= plugin_css_files %>
74
75
  <%= custom_css_files %>
75
- <%= custom_js_files %>
76
+
77
+ <%= plugin_js_files %>
78
+ <%= custom_js_files %>
data/lib/views/index.erb CHANGED
@@ -23,7 +23,11 @@
23
23
  <tr><td class="key">f</td><td>toggle footer</td></tr>
24
24
  <tr><td class="key">r</td><td>reload slides</td></tr>
25
25
  <tr><td class="key">n</td><td>toggle notes</td></tr>
26
- <tr><td class="key">p</td><td>run preshow</td></tr>
26
+
27
+ <% plugin_commands.each do |command| %>
28
+ <tr><td class="key"><%= command.input %></td><td><%= command.description %></td></tr>
29
+ <% end %>
30
+
27
31
  </table>
28
32
  </div>
29
33
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parade
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -198,9 +198,6 @@ files:
198
198
  - lib/parade/commands/static_html.rb
199
199
  - lib/parade/commands/static_pdf.rb
200
200
  - lib/parade/commands/unknown.rb
201
- - lib/parade/features/live_ruby.rb
202
- - lib/parade/features/pdf_presentation.rb
203
- - lib/parade/features/preshow.rb
204
201
  - lib/parade/helpers/encode_image.rb
205
202
  - lib/parade/helpers/template_generator.rb
206
203
  - lib/parade/metadata/assignment.rb
@@ -231,7 +228,6 @@ files:
231
228
  - lib/parade/version.rb
232
229
  - lib/parade.rb
233
230
  - lib/public/css/960.css
234
- - lib/public/css/default.css
235
231
  - lib/public/css/fg.menu.css
236
232
  - lib/public/css/ghf_marked.css
237
233
  - lib/public/css/jquery-terminal.css
@@ -1,18 +0,0 @@
1
- module Parade
2
-
3
- module LiveRuby
4
-
5
- def self.included(server)
6
- server.get '/eval_ruby' do
7
- eval_ruby(params[:code])
8
- end
9
- end
10
-
11
- def eval_ruby(code)
12
- eval(code).to_s
13
- rescue => exception
14
- exception.message
15
- end
16
- end
17
-
18
- end
@@ -1,24 +0,0 @@
1
- module Parade
2
- module PDFPresentation
3
- def self.included(server)
4
-
5
- server.get '/pdf' do
6
-
7
- # TODO: Find the presentation file and/or regenerate it every time
8
-
9
- template_options = { 'erb_template_file' => File.join(File.dirname(__FILE__), "..", "..", "views", "pdf.erb"),
10
- 'custom_asset_path' => settings.presentation_directory,
11
- 'slides' => slides }
12
-
13
- html_content = TemplateGenerator.new(template_options).render
14
-
15
- # TODO the image references here are not full filepaths. creating issues
16
-
17
- kit = PDFKit.new(html_content,:page_size => 'Letter', :orientation => 'Landscape')
18
-
19
- send_file kit.to_file('presentation.pdf')
20
- end
21
-
22
- end
23
- end
24
- end
@@ -1,11 +0,0 @@
1
- module Parade
2
- module Preshow
3
- def self.included(server)
4
-
5
- server.get "/preshow" do
6
- Dir.glob("#{settings.presentation_directory}/preshow/*").map { |path| File.basename(path) }.to_json
7
- end
8
-
9
- end
10
- end
11
- end
@@ -1,3 +0,0 @@
1
- @media screen {
2
-
3
- }