showoff 0.18.1 → 0.18.2
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 +4 -4
- data/bin/showoff +15 -0
- data/lib/showoff.rb +11 -4
- data/lib/showoff/version.rb +1 -1
- data/lib/showoff_utils.rb +48 -0
- data/locales/de.yml +1 -0
- data/locales/en.yml +1 -0
- data/locales/es.yml +1 -0
- data/locales/fr.yml +1 -0
- data/locales/ja.yml +1 -0
- data/locales/nl.yml +1 -0
- data/locales/pt.yml +1 -0
- data/public/css/presenter.css +1 -1
- data/public/css/showoff.css +8 -0
- data/public/js/presenter.js +7 -1
- data/public/js/showoff.js +29 -6
- data/views/index.erb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5049af41567ade99af8a0949da8f756bdbe4eaad
|
4
|
+
data.tar.gz: 09b6a2ba7fadc69530ac3465a1a5497576fc5319
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4332919c9668a1549a91512a74b0b91ec86b8f930a29779dc10c5b0858e4d418cf3a9efe7dddf6977b890e8a16ed13a0e4a8a5ce2a1293040ee59501d954c410
|
7
|
+
data.tar.gz: 720a04998515eba5fa39ff989e18b6a351d69bbcd56a2e55bb435f5b596987e5ffb930d07fa7f4c337060de5f5c7624a02aa5a6f899e9ca1aea1c648c66ade89
|
data/bin/showoff
CHANGED
@@ -68,6 +68,21 @@ module Wrapper
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
desc 'Display information about a Showoff presentation'
|
72
|
+
long_desc 'This command compiles the presentation, then lists out all Markdown files, images, stylesheets, and javascripts included.'
|
73
|
+
command [:info] do |c|
|
74
|
+
|
75
|
+
c.desc 'alternate json filename'
|
76
|
+
c.flag [:f,:file]
|
77
|
+
|
78
|
+
c.desc 'render output as json'
|
79
|
+
c.switch [:j,:json]
|
80
|
+
|
81
|
+
c.action do |global_options,options,args|
|
82
|
+
ShowOffUtils.info(options[:f], options[:j])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
71
86
|
desc 'Validate the consistency of your presentation.'
|
72
87
|
long_desc 'This ensures that each file listed in showoff.json exists and validates code blocks on each slide.'
|
73
88
|
command [:validate] do |c|
|
data/lib/showoff.rb
CHANGED
@@ -1036,10 +1036,17 @@ class ShowOff < Sinatra::Application
|
|
1036
1036
|
end
|
1037
1037
|
|
1038
1038
|
doc.css('img').each do |img|
|
1039
|
-
|
1040
|
-
|
1039
|
+
|
1040
|
+
# does the image path start from the preso root?
|
1041
|
+
if img[:src].start_with? '/'
|
1042
|
+
img_path = img[:src]
|
1043
|
+
else
|
1044
|
+
# clean up the path and remove some of the relative nonsense
|
1045
|
+
img_path = Pathname.new(File.join(slide_dir, img[:src])).cleanpath.to_path
|
1046
|
+
end
|
1041
1047
|
src = "#{replacement_prefix}/#{img_path}"
|
1042
1048
|
img[:src] = src
|
1049
|
+
|
1043
1050
|
end
|
1044
1051
|
doc.to_html
|
1045
1052
|
end
|
@@ -1251,12 +1258,12 @@ class ShowOff < Sinatra::Application
|
|
1251
1258
|
end
|
1252
1259
|
|
1253
1260
|
def slides(static=false)
|
1254
|
-
@logger.
|
1261
|
+
@logger.info "Cached presentations: #{@@cache.keys}"
|
1255
1262
|
|
1256
1263
|
# if we have a cache and we're not asking to invalidate it
|
1257
1264
|
return @@cache[@locale] if (@@cache[@locale] and params['cache'] != 'clear')
|
1258
1265
|
|
1259
|
-
@logger.
|
1266
|
+
@logger.info "Generating locale: #{@locale}"
|
1260
1267
|
|
1261
1268
|
# If we're displaying from a repository, let's update it
|
1262
1269
|
ShowOffUtils.update(settings.verbose) if settings.url
|
data/lib/showoff/version.rb
CHANGED
data/lib/showoff_utils.rb
CHANGED
@@ -97,6 +97,37 @@ class ShowOffUtils
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
+
def self.info(config, json = false)
|
101
|
+
ShowOffUtils.presentation_config_file = config
|
102
|
+
showoff = ShowOff.new!
|
103
|
+
content = showoff.slides
|
104
|
+
dom = Nokogiri::HTML(content)
|
105
|
+
|
106
|
+
data = {}
|
107
|
+
data['files'] = self.showoff_slide_files('.')
|
108
|
+
data['images'] = dom.css('img').map {|img| img[:src].sub(/.\/image\/+/,'') }
|
109
|
+
data['styles'] = Dir.glob('*.css')
|
110
|
+
data['scripts'] = Dir.glob('*.js')
|
111
|
+
|
112
|
+
# now grep through the styles and identify referenced images
|
113
|
+
data['styles'].each do |style|
|
114
|
+
File.readlines(style).each do |line|
|
115
|
+
next unless line =~ /url\(\'(\S+)\'\)/
|
116
|
+
data['images'] << $1
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
if json
|
121
|
+
puts JSON.pretty_generate(data)
|
122
|
+
else
|
123
|
+
data.each do |key, list|
|
124
|
+
puts "#{key.capitalize}:"
|
125
|
+
list.each {|file| puts " * #{file}" }
|
126
|
+
puts
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
100
131
|
def self.validate(config)
|
101
132
|
showoff = ShowOff.new!(:pres_file => config)
|
102
133
|
validators = showoff.settings.showoff_config['validators'] || {}
|
@@ -449,6 +480,9 @@ class ShowOffUtils
|
|
449
480
|
# - { "section": [ "array.md, "of.md, "files.md"] }
|
450
481
|
# - { "include": "sections.json" }
|
451
482
|
sections = {}
|
483
|
+
counters = {}
|
484
|
+
lastpath = nil
|
485
|
+
|
452
486
|
data.map do |entry|
|
453
487
|
next entry if entry.is_a? String
|
454
488
|
next nil unless entry.is_a? Hash
|
@@ -489,6 +523,20 @@ class ShowOffUtils
|
|
489
523
|
end
|
490
524
|
else
|
491
525
|
path = File.dirname(entry)
|
526
|
+
|
527
|
+
# this lastpath business allows us to reference files in a directory that aren't
|
528
|
+
# necessarily contiguous.
|
529
|
+
if path != lastpath
|
530
|
+
counters[path] ||= 0
|
531
|
+
counters[path] += 1
|
532
|
+
end
|
533
|
+
|
534
|
+
# now record the last path we've seen
|
535
|
+
lastpath = path
|
536
|
+
|
537
|
+
# and if there are more than one disparate occurences of path, add a counter to this string
|
538
|
+
path = "#{path} (#{counters[path]})" unless counters[path] == 1
|
539
|
+
|
492
540
|
sections[path] ||= []
|
493
541
|
sections[path] << filename
|
494
542
|
end
|
data/locales/de.yml
CHANGED
data/locales/en.yml
CHANGED
data/locales/es.yml
CHANGED
data/locales/fr.yml
CHANGED
data/locales/ja.yml
CHANGED
data/locales/nl.yml
CHANGED
data/locales/pt.yml
CHANGED
data/public/css/presenter.css
CHANGED
data/public/css/showoff.css
CHANGED
@@ -1199,6 +1199,14 @@ a.term:after {
|
|
1199
1199
|
right: 1em;
|
1200
1200
|
}
|
1201
1201
|
|
1202
|
+
#synchronize {
|
1203
|
+
display: none;
|
1204
|
+
position: absolute;
|
1205
|
+
bottom: 1em;
|
1206
|
+
left: 1em;
|
1207
|
+
font-size: 0.8em;
|
1208
|
+
}
|
1209
|
+
|
1202
1210
|
/* Render hidden headlines so that when we print with wkhtmltopdf, we can use section
|
1203
1211
|
titles for page headers. it would make sense to put this in the print section, but
|
1204
1212
|
then you get a weird double headline when previewing a print in the browser. */
|
data/public/js/presenter.js
CHANGED
@@ -293,6 +293,10 @@ function openSlave()
|
|
293
293
|
// Add a class to differentiate from the audience view
|
294
294
|
slaveWindow.document.getElementById("preso").className = 'display';
|
295
295
|
|
296
|
+
// remove some display view chrome
|
297
|
+
$('.slide.activity', slaveWindow.document).removeClass('activity').children('.activityToggle').remove();
|
298
|
+
$('#synchronize', slaveWindow.document).remove();
|
299
|
+
|
296
300
|
// call back and update the parent presenter if the window is closed
|
297
301
|
slaveWindow.onunload = function(e) {
|
298
302
|
slaveWindow.opener.closeSlave(true);
|
@@ -630,7 +634,9 @@ reconnectControlChannel = function() {
|
|
630
634
|
},
|
631
635
|
error: function() {
|
632
636
|
console.log("Showoff server unavailable");
|
633
|
-
setTimeout(
|
637
|
+
setTimeout( function() {
|
638
|
+
reconnectControlChannel();
|
639
|
+
}, 5000);
|
634
640
|
},
|
635
641
|
});
|
636
642
|
}
|
data/public/js/showoff.js
CHANGED
@@ -4,6 +4,7 @@ var ShowOff = {};
|
|
4
4
|
|
5
5
|
var preso_started = false
|
6
6
|
var slidenum = 0
|
7
|
+
var presenterSlideNum = 0
|
7
8
|
var slideTotal = 0
|
8
9
|
var slides
|
9
10
|
var currentSlide
|
@@ -117,6 +118,11 @@ function setupPreso(load_slides, prefix) {
|
|
117
118
|
buttons: buttons
|
118
119
|
});
|
119
120
|
|
121
|
+
$("#synchronize").button();
|
122
|
+
$("#synchronize").click(function() {
|
123
|
+
synchronize();
|
124
|
+
});
|
125
|
+
|
120
126
|
// wait until the presentation is loaded to hook up the previews.
|
121
127
|
$("body").bind("showoff:loaded", function (event) {
|
122
128
|
var target = $('#navigationHover');
|
@@ -249,10 +255,6 @@ function initializePresentation(prefix) {
|
|
249
255
|
}
|
250
256
|
});
|
251
257
|
|
252
|
-
// The display window doesn't need the extra chrome
|
253
|
-
if(typeof(presenterView) != 'undefined') {
|
254
|
-
$('.slide.activity').removeClass('activity').children('.activityToggle').remove();
|
255
|
-
}
|
256
258
|
$('.slide.activity .activityToggle input.activity').checkboxradio();
|
257
259
|
$('.slide.activity .activityToggle input.activity').change(toggleComplete);
|
258
260
|
|
@@ -772,6 +774,9 @@ function showSlide(back_step, updatepv) {
|
|
772
774
|
activityIncomplete = false;
|
773
775
|
}
|
774
776
|
|
777
|
+
// show the sync button if we're not on the same slide as the presenter
|
778
|
+
checkSyncState();
|
779
|
+
|
775
780
|
// make all bigly text tremendous
|
776
781
|
currentSlide.children('.content.bigtext').bigtext();
|
777
782
|
|
@@ -1278,8 +1283,10 @@ function editSlide() {
|
|
1278
1283
|
window.open(link);
|
1279
1284
|
}
|
1280
1285
|
|
1281
|
-
function follow(slide, newIncrement) {
|
1282
|
-
|
1286
|
+
function follow(slide, newIncrement, force) {
|
1287
|
+
presenterSlideNum = slide;
|
1288
|
+
|
1289
|
+
if ((mode.follow && ! activityIncomplete) || force) {
|
1283
1290
|
var lastSlide = slidenum;
|
1284
1291
|
console.log("New slide: " + slide);
|
1285
1292
|
gotoSlide(slide);
|
@@ -1302,6 +1309,22 @@ function follow(slide, newIncrement) {
|
|
1302
1309
|
|
1303
1310
|
}
|
1304
1311
|
}
|
1312
|
+
|
1313
|
+
// show the sync button if we're not on the same slide as the presenter
|
1314
|
+
checkSyncState();
|
1315
|
+
}
|
1316
|
+
|
1317
|
+
function checkSyncState() {
|
1318
|
+
if (presenterSlideNum != slidenum && presenterSlideNum != null) {
|
1319
|
+
$("#synchronize").show();
|
1320
|
+
}
|
1321
|
+
else {
|
1322
|
+
$("#synchronize").hide();
|
1323
|
+
}
|
1324
|
+
}
|
1325
|
+
|
1326
|
+
function synchronize() {
|
1327
|
+
follow(presenterSlideNum, 0, true);
|
1305
1328
|
}
|
1306
1329
|
|
1307
1330
|
function getPosition() {
|
data/views/index.erb
CHANGED
@@ -95,7 +95,7 @@
|
|
95
95
|
<%= erb :help %>
|
96
96
|
|
97
97
|
<div id="preso"><center><%= I18n.t('loading') %></center></div>
|
98
|
-
|
98
|
+
<a id="synchronize"><i class="fa fa-link" aria-hidden="true" href="#"></i> <%= I18n.t('navigation.sync') %></a>
|
99
99
|
<div id="notes"></div>
|
100
100
|
|
101
101
|
<footer id="footer">
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: showoff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.
|
4
|
+
version: 0.18.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Chacon
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-06-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|