showoff 0.19.4 → 0.20.3
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 +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
|