showoff 0.9.7.1 → 0.9.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 756658ffcc3440e126ed64c256a82ed7f188d1e0
4
- data.tar.gz: 6558c0816fe2ee1c4bfe1b18bf228b70f708a87e
3
+ metadata.gz: e0cff52fdf5f38360a5e10678acb81713da42532
4
+ data.tar.gz: 3dd12a4a362f8b0de756df4de1a34727533ee89c
5
5
  SHA512:
6
- metadata.gz: 2fe546cdf496d75232a11593820ef1070c66f4089598aaf9c9679d2f593446e0b47df3e6b08815180d21edac570e4f9e517ce28bb27277d26d8520d757eab551
7
- data.tar.gz: f6d1c58f94860d0f31982f91f3a64687fd80709a93f982a0c32a925a1189ecdf0ca6cfb773acb16495191d061e21f84762df78a0171efeb3769e13135a0cd6da
6
+ metadata.gz: fe5086466395d08f3667f90a76729d16d0546e5e57144ddf9a3dbcf69a1715f4cf57c6c658801f8a47d6ec4bb2e6090e707c69720eb7d4387d8670981d23b74b
7
+ data.tar.gz: 45a82534917bbdf68e3f792a381bac569a699184aa4bb3efe3b3013eda3b2367c89e3ef54f8b634d2ddaece0bd6b88fef46f7a171f9827ae23ac4e580028900b
data/bin/showoff CHANGED
@@ -99,6 +99,9 @@ command :serve do |c|
99
99
  c.desc 'Show verbose messaging'
100
100
  c.switch :verbose
101
101
 
102
+ c.desc 'Enable code review'
103
+ c.switch :review
104
+
102
105
  c.desc 'Port on which to run'
103
106
  c.default_value "9090"
104
107
  c.flag [:p,:port]
@@ -138,6 +141,7 @@ To run it from presenter view, go to: [ #{url}/presenter ]
138
141
  :pres_file => options[:f],
139
142
  :pres_dir => args[0],
140
143
  :verbose => options[:verbose],
144
+ :review => options[:review],
141
145
  :bind => options[:h]
142
146
  end
143
147
  end
data/lib/showoff.rb CHANGED
@@ -14,13 +14,15 @@ require "#{here}/commandline_parser"
14
14
  begin
15
15
  require 'RMagick'
16
16
  rescue LoadError
17
- $stderr.puts 'WARN: image sizing disabled - install rmagick'
17
+ $stderr.puts 'NOTICE: * automatic image sizing unavailable; install RMagick for this functionality.'
18
18
  end
19
19
 
20
20
  begin
21
21
  require 'pdfkit'
22
22
  rescue LoadError
23
- $stderr.puts 'WARN: pdf generation disabled - install pdfkit'
23
+ $stderr.puts 'NOTICE: * internal pdf generation disabled; install PDFKit for this functionality'
24
+ $stderr.puts 'NOTICE: the PDFKit integration will likely be deprecated. Instead, you should'
25
+ $stderr.puts 'NOTICE: simply use your browser to print from the /print endpoint.'
24
26
  end
25
27
 
26
28
  require 'tilt'
@@ -43,6 +45,8 @@ class ShowOff < Sinatra::Application
43
45
  set :presenters, []
44
46
 
45
47
  set :verbose, false
48
+ set :review, false
49
+
46
50
  set :pres_dir, '.'
47
51
  set :pres_file, 'showoff.json'
48
52
  set :page_size, "Letter"
@@ -69,6 +73,8 @@ class ShowOff < Sinatra::Application
69
73
  @logger.formatter = proc { |severity,datetime,progname,msg| "#{progname} #{msg}\n" }
70
74
  @logger.level = settings.verbose ? Logger::DEBUG : Logger::WARN
71
75
 
76
+ @review = settings.review
77
+
72
78
  dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
73
79
  @logger.debug(dir)
74
80
 
@@ -590,13 +596,21 @@ class ShowOff < Sinatra::Application
590
596
  @asset_path = "./"
591
597
  end
592
598
 
599
+ # Display favicon in the window if configured
600
+ @favicon = settings.showoff_config['favicon']
601
+
593
602
  # Check to see if the presentation has enabled feedback
594
- @feedback = settings.showoff_config['feedback']
603
+ @feedback = settings.showoff_config['feedback'] unless params[:feedback] == 'false'
604
+
605
+ # Provide a button in the sidebar for interactive editing if configured
606
+ @edit = settings.showoff_config['edit'] if @review
607
+
595
608
  erb :index
596
609
  end
597
610
 
598
611
  def presenter
599
612
  @issues = settings.showoff_config['issues']
613
+ @edit = settings.showoff_config['edit'] if @review
600
614
  @@cookie ||= guid()
601
615
  response.set_cookie('presenter', @@cookie)
602
616
  erb :presenter
@@ -645,17 +659,20 @@ class ShowOff < Sinatra::Application
645
659
 
646
660
  def onepage(static=false)
647
661
  @slides = get_slides_html(:static=>static, :toc=>true)
662
+ @favicon = settings.showoff_config['favicon']
648
663
  #@languages = @slides.scan(/<pre class=".*(?!sh_sourceCode)(sh_[\w-]+).*"/).uniq.map{ |w| "/sh_lang/#{w[0]}.min.js"}
649
664
  erb :onepage
650
665
  end
651
666
 
652
667
  def print(static=false)
653
668
  @slides = get_slides_html(:static=>static, :toc=>true, :print=>true)
669
+ @favicon = settings.showoff_config['favicon']
654
670
  erb :onepage
655
671
  end
656
672
 
657
673
  def supplemental(content, static=false)
658
674
  @slides = get_slides_html(:static=>static, :supplemental=>content)
675
+ @favicon = settings.showoff_config['favicon']
659
676
  @wrapper_classes = ['supplemental']
660
677
  erb :onepage
661
678
  end
@@ -665,6 +682,7 @@ class ShowOff < Sinatra::Application
665
682
  shared = Dir.glob("#{settings.pres_dir}/_files/share/*").map { |path| File.basename(path) }
666
683
  # We use the icky -999 magic index because it has to be comparable for the view sort
667
684
  @downloads = { -999 => [ true, 'Shared Files', shared ] }
685
+ @favicon = settings.showoff_config['favicon']
668
686
  rescue Errno::ENOENT => e
669
687
  # don't fail if the directory doesn't exist
670
688
  @downloads = {}
@@ -964,8 +982,7 @@ class ShowOff < Sinatra::Application
964
982
  protected! if settings.showoff_config['protected'].include? what
965
983
  end
966
984
 
967
- # this hasn't been set to anything remotely interesting for a long time now
968
- @asset_path = nil
985
+ @asset_path = env['SCRIPT_NAME'] == '' ? nil : env['SCRIPT_NAME'].gsub(/^\/?/, '/').gsub(/\/?$/, '/')
969
986
 
970
987
  begin
971
988
  if (what != "favicon.ico")
@@ -1,3 +1,3 @@
1
1
  # No namespace here since ShowOff is a class and I'd have to inherit from
2
2
  # Sinatra::Application (which we don't want to load here)
3
- SHOWOFF_VERSION = '0.9.7.1'
3
+ SHOWOFF_VERSION = '0.9.8'
@@ -38,6 +38,7 @@
38
38
  border-top-left-radius: 3px;
39
39
  border-top-right-radius: 3px;
40
40
  z-index: 2147483647; /* max, see http://www.puidokas.com/max-z-index/ */
41
+ display: none;
41
42
  }
42
43
  #followMode {
43
44
  display: none;
@@ -134,7 +135,8 @@
134
135
  }
135
136
 
136
137
  /* nested lists get their bullets back */
137
- .content ul ul {
138
+ .content ul ul,
139
+ .content ol ul {
138
140
  list-style: disc;
139
141
  margin: 10px 10px;
140
142
  padding-left: 40px;
@@ -299,6 +301,17 @@ img#disconnected {
299
301
  text-align: center;
300
302
  }
301
303
 
304
+ #feedbackSidebar div.row.tools {
305
+ position: absolute;
306
+ bottom: 30px;
307
+ width: 100%;
308
+ text-align: center;
309
+ }
310
+
311
+ #feedbackSidebar div.row.tools button#editSlide {
312
+ width: 90%%;
313
+ margin: auto 5%;
314
+ }
302
315
 
303
316
  .fg-menu-container {
304
317
  z-index: 2147483647; /* max, see http://www.puidokas.com/max-z-index/ */
@@ -487,10 +500,6 @@ ul#downloads li {
487
500
  margin: 0.5em;
488
501
  }
489
502
 
490
- span#issueUrl {
491
- display: none;
492
- }
493
-
494
503
  /**********************
495
504
  *** stats page ***
496
505
  **********************/
@@ -1,11 +1,12 @@
1
1
  // presenter js
2
2
  var slaveWindow = null;
3
+ var nextWindow = null;
3
4
 
4
5
  var paceData = [];
5
6
 
6
7
  $(document).ready(function(){
7
8
  // set up the presenter modes
8
- mode = { track: false, follow: true, update: true, slave: false };
9
+ mode = { track: false, follow: true, update: true, slave: false, next: false};
9
10
 
10
11
  // attempt to open another window for the presentation if the mode defaults
11
12
  // to enabling this. It does not by default, so this is likely a no-op.
@@ -103,9 +104,14 @@ function popupLoader(elem, page, id, event)
103
104
  }
104
105
 
105
106
  function reportIssue() {
106
- var slide = $("span#slideFile").text();
107
- var issues = $("span#issueUrl").text();
108
- var link = issues + encodeURIComponent('Issue with slide: ' + slide);
107
+ var slide = $("span#slideFile").text();
108
+ var link = issueUrl + encodeURIComponent('Issue with slide: ' + slide);
109
+ window.open(link);
110
+ }
111
+
112
+ function editSlide() {
113
+ var slide = $("span#slideFile").text();
114
+ var link = editUrl + slide + ".md";
109
115
  window.open(link);
110
116
  }
111
117
 
@@ -152,6 +158,58 @@ function openSlave()
152
158
  }
153
159
  }
154
160
 
161
+ function nextSlideNum(url) {
162
+ // Some fudging because the first slide is slide[0] but numbered 1 in the URL
163
+ console.log(typeof(url));
164
+ var snum;
165
+ if (typeof(url) == 'undefined') { snum = currentSlideFromParams()+1; }
166
+ else { snum = currentSlideFromParams()+2; }
167
+ return snum;
168
+ }
169
+
170
+ function toggleNext() {
171
+ mode.next = !mode.next;
172
+ openNext();
173
+ }
174
+
175
+ function openNext()
176
+ {
177
+ if (mode.next) {
178
+ try {
179
+ if(nextWindow == null || typeof(nextWindow) == 'undefined' || nextWindow.closed){
180
+ nextWindow = window.open('/?track=false&feedback=false&next=true#' + nextSlideNum(true),'','width=300,height=200');
181
+ }
182
+ else if(nextWindow.location.hash != '#' + nextSlideNum(true)) {
183
+ // maybe we need to reset content?
184
+ nextWindow.location.href = '/?track=false&feedback=false&next=true#' + nextSlideNum(true);
185
+ }
186
+
187
+ // maintain the pointer back to the parent.
188
+ nextWindow.presenterView = window;
189
+ nextWindow.mode = { track: false, next: true, follow: true };
190
+
191
+ $('#nextWindow').addClass('enabled');
192
+ }
193
+ catch(e) {
194
+ console.log('Failed to open or connect next window. Popup blocker?');
195
+ }
196
+
197
+ // Set up a maintenance loop to keep the connection between windows. I wish there were a cleaner way to do this.
198
+ //if (typeof maintainNext == 'undefined') {
199
+ // maintainNext = setInterval(openNext, 1000);
200
+ //}
201
+ }
202
+ else {
203
+ try {
204
+ nextWindow && nextWindow.close();
205
+ $('#nextWindow').removeClass('enabled');
206
+ }
207
+ catch (e) {
208
+ console.log('Next window failed to close properly.');
209
+ }
210
+ }
211
+ }
212
+
155
213
  function askQuestion(question) {
156
214
  $("#questions ul").prepend($('<li/>').text(question));
157
215
  }
@@ -264,11 +322,12 @@ function register() {
264
322
 
265
323
  function presPrevStep()
266
324
  {
267
- prevStep();
268
- try { slaveWindow.prevStep(false) } catch (e) {};
269
- postSlide();
325
+ prevStep();
326
+ try { slaveWindow.prevStep(false) } catch (e) {};
327
+ try { nextWindow.gotoSlide(nextSlideNum()) } catch (e) {};
328
+ postSlide();
270
329
 
271
- update();
330
+ update();
272
331
  }
273
332
 
274
333
  function presNextStep()
@@ -278,8 +337,9 @@ function presNextStep()
278
337
  incrCurr = slaveWindow.incrCurr
279
338
  incrSteps = slaveWindow.incrSteps
280
339
  */
281
- nextStep();
340
+ nextStep();
282
341
  try { slaveWindow.nextStep(false) } catch (e) {};
342
+ try { nextWindow.gotoSlide(nextSlideNum()) } catch (e) {};
283
343
  postSlide();
284
344
 
285
345
  update();
@@ -0,0 +1,137 @@
1
+ if (! this.sh_languages) {
2
+ this.sh_languages = {};
3
+ }
4
+ sh_languages['docker'] = [
5
+ [
6
+ [
7
+ /\b[+-]?(?:(?:0x[A-Fa-f0-9]+)|(?:(?:[\d]*\.)?[\d]+(?:[eE][+-]?[\d]+)?))u?(?:(?:int(?:8|16|32|64))|L)?\b/g,
8
+ 'sh_number',
9
+ -1
10
+ ],
11
+ [
12
+ /"/g,
13
+ 'sh_string',
14
+ 1
15
+ ],
16
+ [
17
+ /'/g,
18
+ 'sh_string',
19
+ 2
20
+ ],
21
+ [
22
+ /</g,
23
+ 'sh_string',
24
+ 3
25
+ ],
26
+ [
27
+ /\/[^\n]*\/\s/g, // anchor to \s to avoid matching directory names.
28
+ 'sh_regexp',
29
+ -1
30
+ ],
31
+ [
32
+ /(%r)(\{(?:\\\}|#\{[A-Za-z0-9]+\}|[^}])*\})/g,
33
+ ['sh_symbol', 'sh_regexp'],
34
+ -1
35
+ ],
36
+ [
37
+ /\b[A-Za-z0-9]+(?=\s*[=|\+]>)/g,
38
+ 'sh_attribute',
39
+ -1
40
+ ],
41
+ [
42
+ /\b(?:FROM|MAINTAINER|ENV|ADD|RUN|WORKDIR|VOLUME|ONBUILD|CMD|ENTRYPOINT|EXPOSE|USER)\b/g,
43
+ 'sh_keyword',
44
+ -1
45
+ ],
46
+ [
47
+ /(?:^\=begin)/g,
48
+ 'sh_comment',
49
+ 4
50
+ ],
51
+ [
52
+ /[A-Za-z0-9]+(?:\?|!)/g,
53
+ 'sh_normal',
54
+ -1
55
+ ],
56
+ [
57
+ /~|!|%|\^|\*|\(|\)|-|\+|=|\[|\]|\\|:|;|,|\.|\/|\?|&|<|>|\|/g,
58
+ 'sh_symbol',
59
+ -1
60
+ ],
61
+ [
62
+ /(#)(\{)/g,
63
+ ['sh_symbol', 'sh_cbracket'],
64
+ -1
65
+ ],
66
+ [
67
+ /#/g,
68
+ 'sh_comment',
69
+ 1
70
+ ],
71
+ [
72
+ /\{|\}/g,
73
+ 'sh_cbracket',
74
+ -1
75
+ ]
76
+ ],
77
+ [
78
+ [
79
+ /$/g,
80
+ null,
81
+ -2
82
+ ],
83
+ [
84
+ /\\(?:\\|")/g,
85
+ null,
86
+ -1
87
+ ],
88
+ [
89
+ /"/g,
90
+ 'sh_string',
91
+ -2
92
+ ]
93
+ ],
94
+ [
95
+ [
96
+ /$/g,
97
+ null,
98
+ -2
99
+ ],
100
+ [
101
+ /\\(?:\\|')/g,
102
+ null,
103
+ -1
104
+ ],
105
+ [
106
+ /'/g,
107
+ 'sh_string',
108
+ -2
109
+ ]
110
+ ],
111
+ [
112
+ [
113
+ /$/g,
114
+ null,
115
+ -2
116
+ ],
117
+ [
118
+ />/g,
119
+ 'sh_string',
120
+ -2
121
+ ]
122
+ ],
123
+ [
124
+ [
125
+ /^(?:\=end)/g,
126
+ 'sh_comment',
127
+ 5
128
+ ]
129
+ ],
130
+ [
131
+ [
132
+ /$/g,
133
+ null,
134
+ -2
135
+ ]
136
+ ]
137
+ ];
@@ -0,0 +1 @@
1
+ if(!this.sh_languages){this.sh_languages={}}sh_languages.docker=[[[/\b[+-]?(?:(?:0x[A-Fa-f0-9]+)|(?:(?:[\d]*\.)?[\d]+(?:[eE][+-]?[\d]+)?))u?(?:(?:int(?:8|16|32|64))|L)?\b/g,"sh_number",-1],[/"/g,"sh_string",1],[/'/g,"sh_string",2],[/</g,"sh_string",3],[/\/[^\n]*\/\s/g,"sh_regexp",-1],[/(%r)(\{(?:\\\}|#\{[A-Za-z0-9]+\}|[^}])*\})/g,["sh_symbol","sh_regexp"],-1],[/\b[A-Za-z0-9]+(?=\s*[=|\+]>)/g,"sh_attribute",-1],[/\b(?:FROM|MAINTAINER|ENV|ADD|RUN|WORKDIR|VOLUME|ONBUILD|CMD|ENTRYPOINT|EXPOSE|USER)\b/g,"sh_keyword",-1],[/(?:^\=begin)/g,"sh_comment",4],[/[A-Za-z0-9]+(?:\?|!)/g,"sh_normal",-1],[/~|!|%|\^|\*|\(|\)|-|\+|=|\[|\]|\\|:|;|,|\.|\/|\?|&|<|>|\|/g,"sh_symbol",-1],[/(#)(\{)/g,["sh_symbol","sh_cbracket"],-1],[/#/g,"sh_comment",1],[/\{|\}/g,"sh_cbracket",-1]],[[/$/g,null,-2],[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/$/g,null,-2],[/\\(?:\\|')/g,null,-1],[/'/g,"sh_string",-2]],[[/$/g,null,-2],[/>/g,"sh_string",-2]],[[/^(?:\=end)/g,"sh_comment",5]],[[/$/g,null,-2]]];
data/public/js/showoff.js CHANGED
@@ -60,6 +60,9 @@ function setupPreso(load_slides, prefix) {
60
60
  // give us the ability to disable tracking via url parameter
61
61
  if(query.track == 'false') mode.track = false;
62
62
 
63
+ // make sure that the next view doesn't bugger things on the first load
64
+ if(query.next == 'true') mode.next = true;
65
+
63
66
  // Make sure the slides always look right.
64
67
  // Better would be dynamic calculations, but this is enough for now.
65
68
  $(window).resize(function(){location.reload();});
@@ -83,6 +86,7 @@ function setupPreso(load_slides, prefix) {
83
86
  $("#sendFeedback").click(function() {
84
87
  sendFeedback($( "input:radio[name=rating]:checked" ).val(), $("textarea#feedback").val())
85
88
  });
89
+ $("#editSlide").click(function() { editSlide(); });
86
90
 
87
91
  $("textarea#question").val(questionPrompt);
88
92
  $("textarea#feedback").val(feedbackPrompt);
@@ -90,7 +94,9 @@ function setupPreso(load_slides, prefix) {
90
94
  $("textarea#feedback").focus(function() { clearIf($(this), feedbackPrompt) });
91
95
 
92
96
  // Open up our control socket
93
- connectControlChannel();
97
+ if(mode.track) {
98
+ connectControlChannel();
99
+ }
94
100
  /*
95
101
  ws = new WebSocket('ws://' + location.host + '/control');
96
102
  ws.onopen = function() { connected(); };
@@ -195,17 +201,33 @@ function checkSlideParameter() {
195
201
  }
196
202
  }
197
203
 
204
+ function currentSlideFromName(name) {
205
+ var count = 0;
206
+ slides.each(function(s, slide) {
207
+ if (name == $(slide).find(".content").attr("ref") ) {
208
+ found = count;
209
+ return false;
210
+ }
211
+ count++;
212
+ });
213
+ return count;
214
+ }
215
+
198
216
  function currentSlideFromParams() {
199
217
  var result;
200
218
  if (result = window.location.hash.match(/#([0-9]+)/)) {
201
219
  return result[result.length - 1] - 1;
202
220
  }
221
+ else {
222
+ var hash = window.location.hash
223
+ return currentSlideFromName(hash.substr(1, hash.length))
224
+ }
203
225
  }
204
226
 
205
227
  function setupSlideParamsCheck() {
206
228
  var check = function() {
207
229
  var currentSlide = currentSlideFromParams();
208
- if (slidenum != currentSlide) {
230
+ if (!isNaN(currentSlide) && slidenum != currentSlide) {
209
231
  slidenum = currentSlide;
210
232
  showSlide();
211
233
  }
@@ -283,7 +305,7 @@ function showSlide(back_step, updatepv) {
283
305
  $('#slideFilename').text(fileName);
284
306
 
285
307
  // Update presenter view, if we spawned one
286
- if (updatepv && 'presenterView' in window) {
308
+ if (updatepv && 'presenterView' in window && ! mode.next) {
287
309
  var pv = window.presenterView;
288
310
  pv.slidenum = slidenum;
289
311
  pv.incrCurr = incrCurr
@@ -448,6 +470,13 @@ function track() {
448
470
  }
449
471
  }
450
472
 
473
+ // Open a new tab with an online code editor, if so configured
474
+ function editSlide() {
475
+ var slide = $("span#slideFilename").text();
476
+ var link = editUrl + slide + ".md";
477
+ window.open(link);
478
+ }
479
+
451
480
  function follow(slide) {
452
481
  if (mode.follow) {
453
482
  console.log("New slide: " + slide);
data/views/header.erb CHANGED
@@ -5,6 +5,10 @@
5
5
 
6
6
  <link rel="stylesheet" href="<%= @asset_path %>/css/reset.css" type="text/css"/>
7
7
 
8
+ <% if @favicon %>
9
+ <link rel="icon" href="<%= @favicon %>"/>
10
+ <% end %>
11
+
8
12
  <link type="text/css" href="<%= @asset_path %>/css/fg.menu.css" media="screen" rel="stylesheet" />
9
13
  <link type="text/css" href="<%= @asset_path %>/css/theme/ui.all.css" media="screen" rel="stylesheet" />
10
14
  <link type="text/css" href="<%= @asset_path %>/css/sh_style.css" rel="stylesheet" />
@@ -44,7 +48,9 @@
44
48
  <% end %>
45
49
 
46
50
  <script type="text/javascript">
47
- $(function(){
51
+ $(function(){
48
52
  setupPreso(<%= @slides.nil? ? "true" : "false"%>, '<%= @asset_path %>');
49
- });
53
+ });
54
+
55
+ editUrl = "<%= @edit %>";
50
56
  </script>
@@ -3,6 +3,10 @@
3
3
 
4
4
  <meta name="viewport" content="width=device-width"/>
5
5
 
6
+ <% if @favicon %>
7
+ <link rel="icon" href="<%= @favicon %>"/>
8
+ <% end %>
9
+
6
10
  <link rel="stylesheet" href="<%= @asset_path %>/css/reset.css" type="text/css"/>
7
11
  <link rel="stylesheet" href="<%= @asset_path %>/css/showoff.css" type="text/css"/>
8
12
 
data/views/index.erb CHANGED
@@ -41,6 +41,11 @@
41
41
  <textarea id="feedback"></textarea>
42
42
  <button id="sendFeedback">Send Feedback</button>
43
43
  </div>
44
+ <% if @edit then %>
45
+ <div class="row tools">
46
+ <button id="editSlide">Edit Current Slide</button>
47
+ </div>
48
+ <% end %>
44
49
  <div id="disclaimer">All features are anonymous</div>
45
50
  </div>
46
51
  <div id="feedbackHandle"></div>
data/views/onepage.erb CHANGED
@@ -5,6 +5,10 @@
5
5
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
6
  <title><%= @title %></title>
7
7
 
8
+ <% if @favicon %>
9
+ <link rel="icon" href="<%= @favicon %>"/>
10
+ <% end %>
11
+
8
12
  <% if @inline %>
9
13
 
10
14
  <%= inline_css(['reset.css', 'showoff.css', 'theme/ui.all.css', 'sh_style.css', 'onepage.css'], 'public/css') %>
data/views/presenter.erb CHANGED
@@ -6,12 +6,14 @@
6
6
  <%= erb :header %>
7
7
  <link rel="stylesheet" href="<%= @asset_path %>/css/presenter.css" type="text/css"/>
8
8
  <script type="text/javascript" src="<%= @asset_path %>/js/presenter.js"></script>
9
+ <script type="text/javascript">
10
+ editUrl = "<%= @edit %>";
11
+ issueUrl = "<%= @issues %>";
12
+ </script>
9
13
  </head>
10
14
 
11
15
  <body>
12
16
 
13
- <span id="issueUrl"><%= @issues %></span>
14
-
15
17
  <div id="help">
16
18
  <table>
17
19
  <tr><td class="key">z, ?</td><td>toggle help (this)</td></tr>
@@ -33,12 +35,16 @@
33
35
  </div>
34
36
  <span id="links">
35
37
  <span class="desktop">
38
+ <% if @edit %>
39
+ <a id="edit" href="javascript:editSlide();" title="Edit current slide in new window.">Edit Slide</a>
40
+ <% end %>
36
41
  <% if @issues %>
37
42
  <a id="report" href="javascript:reportIssue();" title="Report an issue with the current slide.">Report Issue With Slide</a>
38
43
  <% end %>
39
44
  <a id="stats" href="/stats" target="_showoffchild">Viewing Statistics</a>
40
45
  <a id="downloads" href="/download" target="_showoffchild">Downloads</a>
41
- <a id="slaveWindow" href="javascript:toggleSlave();" title="Enable the slave window.">Enable Slave Window</a>
46
+ <a id="slaveWindow" href="javascript:toggleSlave();" title="Enable the slave window.">Slave Window</a>
47
+ <a id="nextWindow" href="javascript:toggleNext();" title="Enable the next window view.">Next Window</a>
42
48
  <a id="generatePDF" href="/pdf" title="Call out to wkhtmltopdf to generate a PDF.">Generate PDF</a>
43
49
  <a id="onePage" href="/onepage" title="Load the single page view. Useful for printing.">Single Page</a>
44
50
  </span>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: showoff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7.1
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Chacon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-20 00:00:00.000000000 Z
11
+ date: 2014-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -239,6 +239,8 @@ files:
239
239
  - public/js/sh_lang/sh_cucumber.min.js
240
240
  - public/js/sh_lang/sh_desktop.min.js
241
241
  - public/js/sh_lang/sh_diff.min.js
242
+ - public/js/sh_lang/sh_docker.js
243
+ - public/js/sh_lang/sh_docker.min.js
242
244
  - public/js/sh_lang/sh_erlang.min.js
243
245
  - public/js/sh_lang/sh_flex.min.js
244
246
  - public/js/sh_lang/sh_gherkin.js
@@ -301,7 +303,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
301
303
  version: '0'
302
304
  requirements: []
303
305
  rubyforge_project:
304
- rubygems_version: 2.0.3
306
+ rubygems_version: 2.0.14
305
307
  signing_key:
306
308
  specification_version: 4
307
309
  summary: The best damn presentation software a developer could ever love.