showoff 0.19.4 → 0.20.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Rakefile +24 -12
- data/bin/showoff +47 -24
- data/lib/keymap.rb +19 -5
- data/lib/showoff.rb +96 -44
- data/lib/showoff/compiler.rb +106 -0
- data/lib/showoff/compiler/downloads.rb +91 -0
- data/lib/showoff/compiler/fixups.rb +142 -0
- data/lib/showoff/compiler/form.rb +236 -0
- data/lib/showoff/compiler/glossary.rb +164 -0
- data/lib/showoff/compiler/i18n.rb +24 -0
- data/lib/showoff/compiler/notes.rb +73 -0
- data/lib/showoff/compiler/table_of_contents.rb +51 -0
- data/lib/showoff/compiler/variables.rb +71 -0
- data/lib/showoff/config.rb +218 -0
- data/lib/showoff/locale.rb +132 -0
- data/lib/showoff/logger.rb +15 -0
- data/lib/showoff/monkeypatches.rb +28 -0
- data/lib/showoff/presentation.rb +181 -0
- data/lib/showoff/presentation/section.rb +70 -0
- data/lib/showoff/presentation/slide.rb +113 -0
- data/lib/showoff/state.rb +89 -0
- data/lib/showoff/version.rb +2 -2
- data/lib/showoff_ng.rb +99 -0
- data/lib/showoff_utils.rb +27 -21
- data/public/css/font-awesome-5.6.1/css/all.min.css +5 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-brands-400.eot +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-brands-400.svg +1260 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-brands-400.ttf +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-brands-400.woff +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-brands-400.woff2 +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-regular-400.eot +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-regular-400.svg +471 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-regular-400.ttf +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-regular-400.woff +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-regular-400.woff2 +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-solid-900.eot +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-solid-900.svg +2760 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-solid-900.ttf +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-solid-900.woff +0 -0
- data/public/css/font-awesome-5.6.1/webfonts/fa-solid-900.woff2 +0 -0
- data/public/css/presenter.css +1 -0
- data/public/css/showoff.css +42 -10
- data/public/js/highlight.pack-9.15.10.js +22614 -0
- data/public/js/highlightjs-line-numbers.min.js +1 -0
- data/public/js/presenter.js +13 -11
- data/public/js/showoff.js +39 -31
- data/views/download.erb +2 -2
- data/views/header.erb +27 -26
- data/views/header_mini.erb +8 -8
- data/views/index.erb +56 -56
- data/views/onepage.erb +10 -16
- data/views/presenter.erb +124 -123
- data/views/slide.erb +29 -0
- data/views/stats.erb +1 -1
- metadata +113 -100
- data/locales/id.yml +0 -2
- data/public/css/font-awesome-4.4.0/css/font-awesome.min.css +0 -4
- data/public/css/font-awesome-4.4.0/fonts/FontAwesome.otf +0 -0
- data/public/css/font-awesome-4.4.0/fonts/fontawesome-webfont.eot +0 -0
- data/public/css/font-awesome-4.4.0/fonts/fontawesome-webfont.svg +0 -640
- data/public/css/font-awesome-4.4.0/fonts/fontawesome-webfont.ttf +0 -0
- data/public/css/font-awesome-4.4.0/fonts/fontawesome-webfont.woff +0 -0
- data/public/css/font-awesome-4.4.0/fonts/fontawesome-webfont.woff2 +0 -0
- data/public/js/highlight.pack-9.2.0.js +0 -15448
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4f74f67db7b91942fb6a135c5f66e7624653f5946ba59d4674773b2fdb386a95
|
4
|
+
data.tar.gz: c063015a1a32fd35ea7b10ee2033f725c35345fe57f2f8d6c902a98d4116884c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00dc6115962031eeb962d7fc46d7d5e7e443e9a2f033fc9b5994305364f143472cb651a5ba37802ee095318099e14a1ddf63357be37a51ba824c4dd2d10519cd
|
7
|
+
data.tar.gz: 676ddf144a82192920808f2caa8b352e630449dcbc0ee19abf147f73069e3e749d0d199225ca94b92c7ea32753328c312b9c3d274a42958019ce68d5771f41e8
|
data/Rakefile
CHANGED
@@ -67,21 +67,33 @@ task 'doc:website' => [:doc] do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
70
|
+
# These tests are currently unmaintained.
|
71
|
+
# @todo: port and delete
|
72
|
+
#
|
73
|
+
# desc "Run tests"
|
74
|
+
# task :test do
|
75
|
+
# require 'rake/testtask'
|
76
|
+
#
|
77
|
+
# Rake::TestTask.new do |t|
|
78
|
+
# t.libs << 'lib'
|
79
|
+
# t.pattern = 'test/**/*_test.rb'
|
80
|
+
# t.verbose = false
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# suffix = "-n #{ENV['TEST']}" if ENV['TEST']
|
84
|
+
# sh "turn test/*_test.rb #{suffix}"
|
85
|
+
# end
|
86
|
+
|
87
|
+
desc "Run RSpec unit tests"
|
88
|
+
task :spec do
|
89
|
+
ENV["LOG_SPEC_ORDER"] = "true"
|
90
|
+
if ENV['verbose'] == 'true'
|
91
|
+
sh %{rspec #{ENV['TEST'] || ENV['TESTS'] || 'spec'} -fd}
|
92
|
+
else
|
93
|
+
sh %{rspec #{ENV['TEST'] || ENV['TESTS'] || 'spec'}}
|
78
94
|
end
|
79
|
-
|
80
|
-
suffix = "-n #{ENV['TEST']}" if ENV['TEST']
|
81
|
-
sh "turn test/*_test.rb #{suffix}"
|
82
95
|
end
|
83
96
|
|
84
|
-
|
85
97
|
desc 'Validate translation files'
|
86
98
|
task 'lang:check' do
|
87
99
|
require 'yaml'
|
data/bin/showoff
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
|
3
3
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
4
|
-
require 'showoff'
|
4
|
+
#require 'showoff'
|
5
5
|
require 'showoff/version'
|
6
6
|
require 'rubygems'
|
7
7
|
require 'fidget'
|
@@ -16,7 +16,7 @@ module Wrapper
|
|
16
16
|
program_desc <<-desc
|
17
17
|
A web based presentation engine with awesome interaction features.
|
18
18
|
|
19
|
-
|
19
|
+
Showoff uses Markdown files with a few custom extensions to generate slides
|
20
20
|
that are served locally for presentation via web browser. Your audience can
|
21
21
|
view presentations directly as well, and interact with you in many ways.
|
22
22
|
|
@@ -28,7 +28,8 @@ module Wrapper
|
|
28
28
|
The simplest use case is to run `showoff serve` from the directory containing
|
29
29
|
the showoff.json file.
|
30
30
|
desc
|
31
|
-
|
31
|
+
switch :dev, :desc => "Use the next-gen development version of Showoff"
|
32
|
+
switch :debug, :desc => "Show application backtraces on crash"
|
32
33
|
|
33
34
|
desc 'Create new showoff presentation'
|
34
35
|
long_desc 'This command helps start a new showoff presentation by setting up the proper directory structure for you. It takes the directory name you would like showoff to create for you.'
|
@@ -43,9 +44,9 @@ module Wrapper
|
|
43
44
|
|
44
45
|
c.action do |global_options,options,args|
|
45
46
|
dir_name = args.first || '.'
|
46
|
-
|
47
|
+
ShowoffUtils.create(dir_name,!options[:n],options[:d])
|
47
48
|
if options[:n]
|
48
|
-
puts "Add slides and update #{dir_name}/#{
|
49
|
+
puts "Add slides and update #{dir_name}/#{ShowoffUtils.presentation_config_file}"
|
49
50
|
end
|
50
51
|
if args.empty?
|
51
52
|
puts "Run 'showoff serve' to see your new slideshow"
|
@@ -63,7 +64,7 @@ module Wrapper
|
|
63
64
|
c.flag [:f,:file]
|
64
65
|
|
65
66
|
c.action do |global_options,options,args|
|
66
|
-
|
67
|
+
ShowoffUtils.skeleton(options[:f])
|
67
68
|
puts "done. run 'showoff serve' to see your slideshow"
|
68
69
|
end
|
69
70
|
end
|
@@ -79,7 +80,7 @@ module Wrapper
|
|
79
80
|
c.switch [:j,:json]
|
80
81
|
|
81
82
|
c.action do |global_options,options,args|
|
82
|
-
|
83
|
+
ShowoffUtils.info(options[:f], options[:j])
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
@@ -91,7 +92,7 @@ module Wrapper
|
|
91
92
|
c.flag [:f,:file]
|
92
93
|
|
93
94
|
c.action do |global_options,options,args|
|
94
|
-
|
95
|
+
ShowoffUtils.validate(options[:f])
|
95
96
|
end
|
96
97
|
end
|
97
98
|
|
@@ -100,7 +101,7 @@ module Wrapper
|
|
100
101
|
command :github do |c|
|
101
102
|
c.action do |global_options,options,args|
|
102
103
|
puts "Generating static content"
|
103
|
-
|
104
|
+
ShowoffUtils.github
|
104
105
|
puts "I've updated your 'gh-pages' branch with the static version of your presentation."
|
105
106
|
puts "Push it to GitHub to publish it. Probably something like:"
|
106
107
|
puts
|
@@ -126,16 +127,16 @@ module Wrapper
|
|
126
127
|
raise "Name must start with a letter and can only contain lowercase letters, numbers, and dashes." unless args.first =~ /^[a-z][a-z1-9-]*$/
|
127
128
|
|
128
129
|
unless system('git remote get-url heroku')
|
129
|
-
|
130
|
+
ShowoffUtils.command("heroku create #{args[0]}", "Please ensure that the heroku gem is installed and you're logged in.")
|
130
131
|
end
|
131
132
|
|
132
|
-
if
|
133
|
-
|
133
|
+
if ShowoffUtils.heroku(args[0],options[:f],options[:p])
|
134
|
+
ShowoffUtils.command('bundle install', 'Please ensure that the bundler gem is installed.')
|
134
135
|
|
135
136
|
begin
|
136
|
-
|
137
|
-
|
138
|
-
|
137
|
+
ShowoffUtils.command('git add Procfile Gemfile Gemfile.lock config.ru')
|
138
|
+
ShowoffUtils.command('git commit -m "Herokuized by Showoff"')
|
139
|
+
ShowoffUtils.command('git push heroku master')
|
139
140
|
rescue => e
|
140
141
|
puts 'Git operations failed. Please correct issues, then manually commit the following files:'
|
141
142
|
puts ' * Procfile'
|
@@ -212,7 +213,7 @@ module Wrapper
|
|
212
213
|
|
213
214
|
# This is gross. A serious revamp in config file parsing is due.
|
214
215
|
config = JSON.parse(File.read(options[:f])) rescue {}
|
215
|
-
if Gem::Version.new(config['version']) > Gem::Version.new(SHOWOFF_VERSION) then
|
216
|
+
if Gem::Version.new(config['version'].to_s) > Gem::Version.new(SHOWOFF_VERSION) then
|
216
217
|
raise "This presentation requires Showoff version #{config['version']} or greater."
|
217
218
|
end
|
218
219
|
|
@@ -239,7 +240,7 @@ module Wrapper
|
|
239
240
|
puts "
|
240
241
|
-------------------------
|
241
242
|
|
242
|
-
Your
|
243
|
+
Your Showoff presentation is now starting up.
|
243
244
|
|
244
245
|
To view it plainly, visit [ #{url} ]
|
245
246
|
|
@@ -255,8 +256,8 @@ module Wrapper
|
|
255
256
|
end
|
256
257
|
|
257
258
|
if options[:url]
|
258
|
-
|
259
|
-
|
259
|
+
ShowoffUtils.clone(options[:git_url], options[:git_branch], options[:git_path]) do
|
260
|
+
Showoff.run!(options) do |server|
|
260
261
|
if options[:ssl]
|
261
262
|
server.ssl = true
|
262
263
|
server.ssl_options = ssl_options
|
@@ -265,7 +266,7 @@ module Wrapper
|
|
265
266
|
end
|
266
267
|
|
267
268
|
else
|
268
|
-
|
269
|
+
Showoff.run!(options) do |server|
|
269
270
|
if options[:ssl]
|
270
271
|
server.ssl = true
|
271
272
|
server.ssl_options = ssl_options
|
@@ -302,7 +303,7 @@ module Wrapper
|
|
302
303
|
|
303
304
|
c.action do |global_options,options,args|
|
304
305
|
title = args.join(" ")
|
305
|
-
|
306
|
+
ShowoffUtils.add_slide(:dir => options[:d],
|
306
307
|
:name => options[:n],
|
307
308
|
:title => title,
|
308
309
|
:number => !options[:u],
|
@@ -323,7 +324,7 @@ module Wrapper
|
|
323
324
|
c.flag [:l, :lang, :language, :locale]
|
324
325
|
|
325
326
|
c.action do |global_options,options,args|
|
326
|
-
|
327
|
+
Showoff.do_static(args, options)
|
327
328
|
end
|
328
329
|
end
|
329
330
|
|
@@ -331,15 +332,37 @@ module Wrapper
|
|
331
332
|
arg_name 'name'
|
332
333
|
long_desc 'Creates a PDF version of the presentation as {name}.pdf'
|
333
334
|
command [:pdf] do |c|
|
335
|
+
c.desc 'JSON file used to describe presentation'
|
336
|
+
c.default_value "showoff.json"
|
337
|
+
c.flag [:f, :file, :pres_file]
|
338
|
+
|
339
|
+
c.desc 'Language code to generate.'
|
340
|
+
c.flag [:l, :lang, :language, :locale]
|
341
|
+
|
334
342
|
c.action do |global_options,options,args|
|
335
|
-
|
343
|
+
Showoff.do_static(['pdf'].concat(args), options)
|
336
344
|
end
|
337
345
|
end
|
338
346
|
|
339
347
|
pre do |global,command,options,args|
|
340
348
|
# Pre logic here
|
341
|
-
# Return true to proceed; false to
|
349
|
+
# Return true to proceed; false to abort and not call the
|
342
350
|
# chosen command
|
351
|
+
|
352
|
+
if global[:debug]
|
353
|
+
ENV['GLI_DEBUG'] = 'true'
|
354
|
+
end
|
355
|
+
|
356
|
+
if global[:dev]
|
357
|
+
require 'showoff_ng'
|
358
|
+
|
359
|
+
if options[:file]
|
360
|
+
Showoff::Config.load(options[:file])
|
361
|
+
end
|
362
|
+
else
|
363
|
+
require 'showoff'
|
364
|
+
end
|
365
|
+
|
343
366
|
true
|
344
367
|
end
|
345
368
|
|
data/lib/keymap.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
module Keymap
|
2
2
|
def self.default()
|
3
3
|
{
|
4
|
-
'space' => 'NEXT',
|
5
4
|
'd' => 'DEBUG',
|
6
|
-
'
|
7
|
-
'left' => 'PREV',
|
8
|
-
'pageup' => 'PREVSEC',
|
5
|
+
'space' => 'NEXT',
|
9
6
|
'down' => 'NEXT',
|
10
7
|
'right' => 'NEXT',
|
11
|
-
'pagedown' => '
|
8
|
+
'pagedown' => 'NEXT',
|
9
|
+
'up' => 'PREV',
|
10
|
+
'left' => 'PREV',
|
11
|
+
'pageup' => 'PREV',
|
12
|
+
'SPACE' => 'NEXTSEC',
|
13
|
+
'DOWN' => 'NEXTSEC',
|
14
|
+
'RIGHT' => 'NEXTSEC',
|
15
|
+
'PAGEDOWN' => 'NEXTSEC',
|
16
|
+
'UP' => 'PREVSEC',
|
17
|
+
'LEFT' => 'PREVSEC',
|
18
|
+
'PAGEUP' => 'PREVSEC',
|
12
19
|
'R' => 'RELOAD',
|
13
20
|
'r' => 'REFRESH',
|
14
21
|
'c' => 'CONTENTS',
|
@@ -169,6 +176,13 @@ module Keymap
|
|
169
176
|
"`" => "~",
|
170
177
|
"=" => "+",
|
171
178
|
"-" => "_",
|
179
|
+
"space" => "SPACE",
|
180
|
+
"down" => "DOWN",
|
181
|
+
"right" => "RIGHT",
|
182
|
+
"pagedown" => "PAGEDOWN",
|
183
|
+
"up" => "UP",
|
184
|
+
"left" => "LEFT",
|
185
|
+
"pageup" => "PAGEUP",
|
172
186
|
}
|
173
187
|
end
|
174
188
|
|
data/lib/showoff.rb
CHANGED
@@ -28,7 +28,7 @@ end
|
|
28
28
|
|
29
29
|
require 'tilt'
|
30
30
|
|
31
|
-
class
|
31
|
+
class Showoff < Sinatra::Application
|
32
32
|
|
33
33
|
attr_reader :cached_image_size
|
34
34
|
|
@@ -92,13 +92,13 @@ class ShowOff < Sinatra::Application
|
|
92
92
|
|
93
93
|
settings.pres_dir = File.expand_path(settings.pres_dir)
|
94
94
|
if (settings.pres_file and settings.pres_file != 'showoff.json')
|
95
|
-
|
95
|
+
ShowoffUtils.presentation_config_file = settings.pres_file
|
96
96
|
end
|
97
97
|
|
98
98
|
# Load configuration for page size and template from the
|
99
99
|
# configuration JSON file
|
100
|
-
if File.exist?(
|
101
|
-
showoff_json = JSON.parse(File.read(
|
100
|
+
if File.exist?(ShowoffUtils.presentation_config_file)
|
101
|
+
showoff_json = JSON.parse(File.read(ShowoffUtils.presentation_config_file))
|
102
102
|
settings.showoff_config = showoff_json
|
103
103
|
|
104
104
|
# Set options for encoding, template and page size
|
@@ -164,9 +164,6 @@ class ShowOff < Sinatra::Application
|
|
164
164
|
@pres_name = settings.pres_dir.split('/').pop
|
165
165
|
require_ruby_files
|
166
166
|
|
167
|
-
# Default asset path
|
168
|
-
@asset_path = "./"
|
169
|
-
|
170
167
|
# invert the logic to maintain backwards compatibility of interactivity on by default
|
171
168
|
@interactive = ! settings.standalone rescue false
|
172
169
|
|
@@ -208,7 +205,7 @@ class ShowOff < Sinatra::Application
|
|
208
205
|
Thread.new do
|
209
206
|
loop do
|
210
207
|
sleep 30
|
211
|
-
|
208
|
+
Showoff.flush
|
212
209
|
end
|
213
210
|
end
|
214
211
|
end
|
@@ -217,7 +214,7 @@ class ShowOff < Sinatra::Application
|
|
217
214
|
MarkdownConfig::setup(settings.pres_dir)
|
218
215
|
|
219
216
|
# Process renderer config options
|
220
|
-
@engine_options =
|
217
|
+
@engine_options = ShowoffUtils.showoff_renderer_options(settings.pres_dir)
|
221
218
|
|
222
219
|
end
|
223
220
|
# save stats to disk
|
@@ -248,7 +245,7 @@ class ShowOff < Sinatra::Application
|
|
248
245
|
|
249
246
|
def self.pres_dir_current
|
250
247
|
opt = {:pres_dir => Dir.pwd}
|
251
|
-
|
248
|
+
Showoff.set opt
|
252
249
|
end
|
253
250
|
|
254
251
|
def require_ruby_files
|
@@ -257,11 +254,15 @@ class ShowOff < Sinatra::Application
|
|
257
254
|
|
258
255
|
helpers do
|
259
256
|
def css_files
|
260
|
-
Dir.glob("#{settings.pres_dir}/*.css").map { |path| File.basename(path) }
|
257
|
+
base = Dir.glob("#{settings.pres_dir}/*.css").map { |path| File.basename(path) }
|
258
|
+
extra = Array(settings.showoff_config['styles'])
|
259
|
+
base + extra
|
261
260
|
end
|
262
261
|
|
263
262
|
def js_files
|
264
|
-
Dir.glob("#{settings.pres_dir}/*.js").map { |path| File.basename(path) }
|
263
|
+
base = Dir.glob("#{settings.pres_dir}/*.js").map { |path| File.basename(path) }
|
264
|
+
extra = Array(settings.showoff_config['scripts'])
|
265
|
+
base + extra
|
265
266
|
end
|
266
267
|
|
267
268
|
def preshow_files
|
@@ -316,10 +317,12 @@ class ShowOff < Sinatra::Application
|
|
316
317
|
|
317
318
|
# return a hash of all language codes available and the long name description of each
|
318
319
|
def language_names
|
319
|
-
|
320
|
-
|
320
|
+
strings = JSON.parse(File.read('locales/strings.json')) rescue {}
|
321
|
+
locales = Dir.glob('locales/*')
|
322
|
+
.select {|f| File.directory?(f) }
|
323
|
+
.map {|f| File.basename(f) }
|
321
324
|
|
322
|
-
|
325
|
+
(strings.keys + locales).inject({}) do |memo, locale|
|
323
326
|
memo.update(locale => get_language_name(locale))
|
324
327
|
end
|
325
328
|
end
|
@@ -366,7 +369,7 @@ class ShowOff < Sinatra::Application
|
|
366
369
|
|
367
370
|
# Parse the context string for options and content classes
|
368
371
|
if context and context.match(/(\[(.*?)\])?(.*)/)
|
369
|
-
options =
|
372
|
+
options = ShowoffUtils.parse_options($2)
|
370
373
|
@tpl = options["tpl"] if options["tpl"]
|
371
374
|
@bg = options["bg"] if options["bg"]
|
372
375
|
@classes += $3.strip.chomp('>').split if $3
|
@@ -506,6 +509,7 @@ class ShowOff < Sinatra::Application
|
|
506
509
|
|
507
510
|
# Apply the template to the slide and replace the key to generate the content of the slide
|
508
511
|
sl = process_content_for_replacements(template.gsub(/~~~CONTENT~~~/, slide.text))
|
512
|
+
sl = process_content_for_language(sl, I18n.locale)
|
509
513
|
sl = Tilt[:markdown].new(nil, nil, @engine_options) { sl }.render
|
510
514
|
sl = build_forms(sl, content_classes)
|
511
515
|
sl = update_p_classes(sl)
|
@@ -535,6 +539,21 @@ class ShowOff < Sinatra::Application
|
|
535
539
|
final
|
536
540
|
end
|
537
541
|
|
542
|
+
def process_content_for_language(content, locale)
|
543
|
+
lang = locale.to_s.split('-').first
|
544
|
+
result = content
|
545
|
+
|
546
|
+
content.scan(/^((~~~LANG:([\w-]+)~~~\n)(.+?)(\n~~~ENDLANG~~~\n))/m).each do |match|
|
547
|
+
if match[2] == lang or match[2] == locale.to_s
|
548
|
+
result.sub!(match[0], match[3])
|
549
|
+
else
|
550
|
+
result.sub!(match[0], "\n")
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
result
|
555
|
+
end
|
556
|
+
|
538
557
|
# This method processes the content of the slide and replaces
|
539
558
|
# content markers with their actual value information
|
540
559
|
def process_content_for_replacements(content)
|
@@ -554,7 +573,21 @@ class ShowOff < Sinatra::Application
|
|
554
573
|
|
555
574
|
# Now check for any kind of options
|
556
575
|
content.scan(/(~~~CONFIG:(.*?)~~~)/).each do |match|
|
557
|
-
|
576
|
+
parts = match[1].split('.') # Use dots ('.') to separate Hash keys
|
577
|
+
if parts.size > 1
|
578
|
+
value = settings.showoff_config.dig(parts[0]).to_h.dig(*parts[1..-1])
|
579
|
+
else
|
580
|
+
value = settings.showoff_config.fetch(parts[0],nil)
|
581
|
+
end
|
582
|
+
|
583
|
+
unless value.is_a?(String)
|
584
|
+
msg = "#{match[0]} refers to a non-String data type (#{value.class})"
|
585
|
+
msg = "#{match[0]}: not found in settings data" if value.nil?
|
586
|
+
@logger.warn(msg)
|
587
|
+
next
|
588
|
+
end
|
589
|
+
|
590
|
+
result.gsub!(match[0], value)
|
558
591
|
end
|
559
592
|
|
560
593
|
# Load and replace any file tags
|
@@ -571,8 +604,11 @@ class ShowOff < Sinatra::Application
|
|
571
604
|
result.gsub!(match[0], "<pre class=\"highlight\"><code class=\"#{css}\">#{file}</code></pre>")
|
572
605
|
end
|
573
606
|
|
574
|
-
result.gsub!(/\[(fa
|
607
|
+
result.gsub!(/\[(fa\w?)-(\S*)\]/, '<i class="\1 fa-\2"></i>')
|
575
608
|
|
609
|
+
# For fenced code blocks, translate the space separated classes into one
|
610
|
+
# colon separated string so Commonmarker doesn't ignore the rest
|
611
|
+
result.gsub!(/^`{3} *(.+)$/) {|s| "``` #{$1.split.join(':')}"}
|
576
612
|
|
577
613
|
result
|
578
614
|
end
|
@@ -820,7 +856,7 @@ class ShowOff < Sinatra::Application
|
|
820
856
|
tools << "<input type=\"button\" class=\"display\" value=\"#{I18n.t('forms.display')}\">"
|
821
857
|
tools << "<input type=\"submit\" class=\"save\" value=\"#{I18n.t('forms.save')}\" disabled=\"disabled\">"
|
822
858
|
tools << '</div>'
|
823
|
-
form = "<form id='#{title}' action='
|
859
|
+
form = "<form id='#{title}' action='form/#{title}' method='POST'>#{content}#{tools}</form>"
|
824
860
|
doc = Nokogiri::HTML::DocumentFragment.parse(form)
|
825
861
|
doc.css('p').each do |p|
|
826
862
|
if p.text =~ /^(\w*) ?(?:->)? ?(.*)? (\*?)= ?(.*)?$/
|
@@ -1043,11 +1079,11 @@ class ShowOff < Sinatra::Application
|
|
1043
1079
|
|
1044
1080
|
case
|
1045
1081
|
when opts[:static] && opts[:pdf]
|
1046
|
-
replacement_prefix = "file://#{settings.pres_dir}
|
1082
|
+
replacement_prefix = "file://#{settings.pres_dir}"
|
1047
1083
|
when opts[:static]
|
1048
|
-
replacement_prefix =
|
1084
|
+
replacement_prefix = './file'
|
1049
1085
|
else
|
1050
|
-
replacement_prefix =
|
1086
|
+
replacement_prefix = 'image'
|
1051
1087
|
end
|
1052
1088
|
|
1053
1089
|
doc.css('img').each do |img|
|
@@ -1081,8 +1117,10 @@ class ShowOff < Sinatra::Application
|
|
1081
1117
|
# catch fenced code blocks from commonmarker
|
1082
1118
|
if (lang and lang.start_with? 'language-' )
|
1083
1119
|
pre.set_attribute('class', 'highlight')
|
1120
|
+
# turn the colon separated name back into classes
|
1121
|
+
code.set_attribute('class', lang.gsub(':', ' '))
|
1084
1122
|
|
1085
|
-
# or
|
1123
|
+
# or we've started a code block with a Showoff language tag
|
1086
1124
|
elsif out.strip[0, 3] == '@@@'
|
1087
1125
|
lines = out.split("\n")
|
1088
1126
|
lang = lines.shift.gsub('@@@', '').strip
|
@@ -1127,7 +1165,7 @@ class ShowOff < Sinatra::Application
|
|
1127
1165
|
def get_slides_html(opts={:static=>false, :pdf=>false, :toc=>false, :supplemental=>nil, :section=>nil})
|
1128
1166
|
sections = nil
|
1129
1167
|
Dir.chdir(get_locale_dir('locales', @locale)) do
|
1130
|
-
sections =
|
1168
|
+
sections = ShowoffUtils.showoff_sections(settings.pres_dir, settings.showoff_config, @logger)
|
1131
1169
|
end
|
1132
1170
|
|
1133
1171
|
if sections
|
@@ -1195,11 +1233,9 @@ class ShowOff < Sinatra::Application
|
|
1195
1233
|
|
1196
1234
|
def index(static=false)
|
1197
1235
|
if static
|
1198
|
-
@title =
|
1236
|
+
@title = ShowoffUtils.showoff_title(settings.pres_dir)
|
1199
1237
|
@slides = get_slides_html(:static=>static)
|
1200
|
-
@pause_msg =
|
1201
|
-
|
1202
|
-
@asset_path = "./"
|
1238
|
+
@pause_msg = ShowoffUtils.pause_msg
|
1203
1239
|
end
|
1204
1240
|
|
1205
1241
|
# Display favicon in the window if configured
|
@@ -1281,7 +1317,7 @@ class ShowOff < Sinatra::Application
|
|
1281
1317
|
@logger.info "Generating locale: #{@locale}"
|
1282
1318
|
|
1283
1319
|
# If we're displaying from a repository, let's update it
|
1284
|
-
|
1320
|
+
ShowoffUtils.update(settings.verbose) if settings.url
|
1285
1321
|
|
1286
1322
|
@@slide_titles = []
|
1287
1323
|
content = get_slides_html(:static=>static, :merged=>merged)
|
@@ -1291,9 +1327,14 @@ class ShowOff < Sinatra::Application
|
|
1291
1327
|
content
|
1292
1328
|
end
|
1293
1329
|
|
1294
|
-
def print(section=nil)
|
1330
|
+
def print(section=nil, munged=false)
|
1295
1331
|
@slides = get_slides_html(:static=>true, :toc=>true, :print=>true, :section=>section)
|
1296
1332
|
@favicon = settings.showoff_config['favicon']
|
1333
|
+
|
1334
|
+
unless munged
|
1335
|
+
@baseurl = '../' * section.split('/').count
|
1336
|
+
end
|
1337
|
+
|
1297
1338
|
erb :onepage
|
1298
1339
|
end
|
1299
1340
|
|
@@ -1423,7 +1464,7 @@ class ShowOff < Sinatra::Application
|
|
1423
1464
|
|
1424
1465
|
# PDFKit.new takes the HTML and any options for wkhtmltopdf
|
1425
1466
|
# run `wkhtmltopdf --extended-help` for a full list of options
|
1426
|
-
kit = PDFKit.new(html,
|
1467
|
+
kit = PDFKit.new(html, ShowoffUtils.showoff_pdf_options(settings.pres_dir))
|
1427
1468
|
|
1428
1469
|
# Save the PDF to a file
|
1429
1470
|
kit.to_file(name)
|
@@ -1437,11 +1478,11 @@ class ShowOff < Sinatra::Application
|
|
1437
1478
|
what = args[0] || "index"
|
1438
1479
|
opt = args[1]
|
1439
1480
|
|
1440
|
-
|
1481
|
+
ShowoffUtils.presentation_config_file = opts[:f]
|
1441
1482
|
|
1442
1483
|
# Sinatra now aliases new to new!
|
1443
1484
|
# https://github.com/sinatra/sinatra/blob/v1.3.3/lib/sinatra/base.rb#L1369
|
1444
|
-
showoff =
|
1485
|
+
showoff = Showoff.new!
|
1445
1486
|
|
1446
1487
|
name = showoff.instance_variable_get(:@pres_name)
|
1447
1488
|
path = showoff.instance_variable_get(:@root_path)
|
@@ -1457,7 +1498,7 @@ class ShowOff < Sinatra::Application
|
|
1457
1498
|
data = showoff.send(what, opt)
|
1458
1499
|
when 'print'
|
1459
1500
|
opt ||= 'handouts'
|
1460
|
-
data = showoff.send(what, opt)
|
1501
|
+
data = showoff.send(what, opt, true)
|
1461
1502
|
else
|
1462
1503
|
data = showoff.send(what, true)
|
1463
1504
|
end
|
@@ -1477,6 +1518,8 @@ class ShowOff < Sinatra::Application
|
|
1477
1518
|
["js", "css"].each { |dir|
|
1478
1519
|
FileUtils.copy_entry("#{my_path}/#{dir}", "#{out}/#{dir}", false, false, true)
|
1479
1520
|
}
|
1521
|
+
|
1522
|
+
# @todo: uh. I don't know how this ever worked. my_path is showoff and name is presentation.
|
1480
1523
|
# And copy the directory
|
1481
1524
|
Dir.glob("#{my_path}/#{name}/*").each { |subpath|
|
1482
1525
|
base = File.basename(subpath)
|
@@ -1491,8 +1534,15 @@ class ShowOff < Sinatra::Application
|
|
1491
1534
|
pres_dir = showoff.settings.pres_dir
|
1492
1535
|
|
1493
1536
|
# ..., copy all user-defined styles and javascript files
|
1494
|
-
|
1495
|
-
|
1537
|
+
showoff.css_files.each { |path|
|
1538
|
+
dest = File.join(out, path)
|
1539
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
1540
|
+
FileUtils.copy(path, dest)
|
1541
|
+
}
|
1542
|
+
showoff.js_files.each { |path|
|
1543
|
+
dest = File.join(out, path)
|
1544
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
1545
|
+
FileUtils.copy(path, dest)
|
1496
1546
|
}
|
1497
1547
|
|
1498
1548
|
# ... and copy all needed image files
|
@@ -1508,12 +1558,16 @@ class ShowOff < Sinatra::Application
|
|
1508
1558
|
end
|
1509
1559
|
end
|
1510
1560
|
# copy images from css too
|
1511
|
-
|
1561
|
+
showoff.css_files.each do |css_path|
|
1512
1562
|
File.open(css_path) do |file|
|
1513
1563
|
data = file.read
|
1514
1564
|
data.scan(/url\([\"\']?(?!https?:\/\/)(.*?)[\"\']?\)/).flatten.each do |path|
|
1515
1565
|
path.gsub!(/(\#.*)$/, '') # get rid of the anchor
|
1516
1566
|
path.gsub!(/(\?.*)$/, '') # get rid of the query
|
1567
|
+
|
1568
|
+
# resolve relative paths in the stylesheet
|
1569
|
+
path = "#{File.dirname(css_path)}/#{path}" unless path.start_with? '/'
|
1570
|
+
|
1517
1571
|
logger.debug path
|
1518
1572
|
dir = File.dirname(path)
|
1519
1573
|
FileUtils.makedirs(File.join(file_dir, dir))
|
@@ -1917,8 +1971,8 @@ class ShowOff < Sinatra::Application
|
|
1917
1971
|
# gawd, this whole routing scheme is bollocks
|
1918
1972
|
get %r{/([^/]*)/?([^/]*)} do
|
1919
1973
|
@locale = locale(request.cookies['locale'])
|
1920
|
-
@title =
|
1921
|
-
@pause_msg =
|
1974
|
+
@title = ShowoffUtils.showoff_title(settings.pres_dir)
|
1975
|
+
@pause_msg = ShowoffUtils.pause_msg
|
1922
1976
|
what = params[:captures].first
|
1923
1977
|
opt = params[:captures][1]
|
1924
1978
|
what = 'index' if "" == what
|
@@ -1929,12 +1983,12 @@ class ShowOff < Sinatra::Application
|
|
1929
1983
|
locked!
|
1930
1984
|
end
|
1931
1985
|
|
1932
|
-
@asset_path = env['SCRIPT_NAME'] == '' ? nil : env['SCRIPT_NAME'].gsub(/^\/?/, '/').gsub(/\/?$/, '/')
|
1933
|
-
|
1934
1986
|
begin
|
1935
1987
|
if (what != "favicon.ico")
|
1936
1988
|
if ['supplemental', 'print'].include? what
|
1937
1989
|
data = send(what, opt)
|
1990
|
+
elsif File.file? what
|
1991
|
+
data = File.open(what)
|
1938
1992
|
else
|
1939
1993
|
data = send(what)
|
1940
1994
|
end
|
@@ -1953,14 +2007,12 @@ class ShowOff < Sinatra::Application
|
|
1953
2007
|
end
|
1954
2008
|
|
1955
2009
|
not_found do
|
1956
|
-
# Why does the asset path start from cwd??
|
1957
|
-
@asset_path.slice!(/^./) rescue nil
|
1958
2010
|
@env = request.env
|
1959
2011
|
erb :'404'
|
1960
2012
|
end
|
1961
2013
|
|
1962
2014
|
at_exit do
|
1963
|
-
|
2015
|
+
Showoff.flush
|
1964
2016
|
end
|
1965
2017
|
|
1966
2018
|
end
|