rhet-butler 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rhet-butler +5 -0
- data/default-configuration/assets/apple-touch-icon-precomposed.png +0 -0
- data/default-configuration/assets/apple-touch-icon.png +0 -0
- data/default-configuration/assets/favicon.ico +0 -0
- data/default-configuration/assets/fonts/opensans/v6/MTP_ySUJH_bn48VBG8sNSonF5uFdDttMLvmWuJdhhgs.ttf +0 -0
- data/default-configuration/assets/fonts/opensans/v6/PRmiXeptR36kaC0GEAetxi8cqLH4MEiSE0ROcU-qHOA.ttf +0 -0
- data/default-configuration/assets/fonts/opensans/v6/cJZKeOuBrn4kERxqtaUH3aCWcynf_cDxXwCLxiixG1c.ttf +0 -0
- data/default-configuration/assets/fonts/opensans/v6/xjAJXh38I15wypJXxuGMBp0EAVxt0G0biEntp43Qt6E.ttf +0 -0
- data/default-configuration/assets/fonts/ptsans/v5/0XxGQsSc1g4rdRdjJKZrNC3USBnSvpkopQaUR-2r7iU.ttf +0 -0
- data/default-configuration/assets/fonts/ptsans/v5/FUDHvzEKSJww3kCxuiAo2A.ttf +0 -0
- data/default-configuration/assets/fonts/ptsans/v5/PIPMHY90P7jtyjpXuZ2cLKCWcynf_cDxXwCLxiixG1c.ttf +0 -0
- data/default-configuration/assets/fonts/ptsans/v5/lILlYDvubYemzYzN7GbLkInF5uFdDttMLvmWuJdhhgs.ttf +0 -0
- data/default-configuration/assets/fonts/ptserif/v5/03aPdn7fFF3H6ngCgAlQzC3USBnSvpkopQaUR-2r7iU.ttf +0 -0
- data/default-configuration/assets/fonts/ptserif/v5/EgBlzoNBIHxNPCMwXaAhYPesZW2xOQ-xsNqO47m55DA.ttf +0 -0
- data/default-configuration/assets/fonts/ptserif/v5/Foydq9xJp--nfYIx2TBz9fEr6Hm6RMS0v1dtXsGir4g.ttf +0 -0
- data/default-configuration/assets/fonts/ptserif/v5/QABk9IxT-LFTJ_dQzv7xpJ0EAVxt0G0biEntp43Qt6E.ttf +0 -0
- data/default-configuration/assets/javascript/highlight.js/LICENSE +24 -0
- data/default-configuration/assets/javascript/highlight.js/README.md +143 -0
- data/default-configuration/assets/javascript/highlight.js/README.ru.md +149 -0
- data/default-configuration/assets/javascript/highlight.js/classref.txt +568 -0
- data/default-configuration/assets/javascript/highlight.pack.js +1 -0
- data/default-configuration/assets/javascript/impress.js +800 -0
- data/default-configuration/assets/javascript/sockjs-0.2.1.js +2014 -0
- data/default-configuration/assets/javascript/sockjs-0.3.js +2314 -0
- data/default-configuration/assets/rhet-butler.jpg +0 -0
- data/default-configuration/assets/stylesheets/google-open-sans.css +72 -0
- data/default-configuration/assets/stylesheets/highlight/solarized_dark.css +88 -0
- data/default-configuration/assets/stylesheets/presentation.css +483 -0
- data/default-configuration/assets/stylesheets/presenter/presentation.css +477 -0
- data/default-configuration/assets/stylesheets/setup.css +0 -0
- data/default-configuration/common/config.yaml +4 -0
- data/default-configuration/common/templates/header-javascript.html +3 -0
- data/default-configuration/common/templates/presentation.html.erb +44 -0
- data/default-configuration/common/templates/presenter-qr.html.erb +77 -0
- data/default-configuration/common/templates/stylesheets.html.erb +3 -0
- data/default-configuration/presenter/config.yaml +7 -0
- data/default-configuration/presenter/templates/live-javascript.html.erb +26 -0
- data/default-configuration/presenter/templates/slide-notes.html.erb +3 -0
- data/default-configuration/presenter/templates/stylesheets.html.erb +3 -0
- data/default-configuration/viewer/config.yaml +7 -0
- data/default-configuration/viewer/templates/live-javascript.html.erb +16 -0
- data/default-configuration/viewer/templates/slide-notes.html.erb +0 -0
- data/lib/rhet-butler/arrangement.rb +78 -0
- data/lib/rhet-butler/command-line.rb +49 -0
- data/lib/rhet-butler/configuration.rb +76 -0
- data/lib/rhet-butler/file-manager.rb +126 -0
- data/lib/rhet-butler/html-generator.rb +29 -0
- data/lib/rhet-butler/layout-rule.rb +57 -0
- data/lib/rhet-butler/messaging.rb +58 -0
- data/lib/rhet-butler/slide-group.rb +56 -0
- data/lib/rhet-butler/slide-includer.rb +34 -0
- data/lib/rhet-butler/slide-loader.rb +361 -0
- data/lib/rhet-butler/slide.rb +164 -0
- data/lib/rhet-butler/static-generator.rb +44 -0
- data/lib/rhet-butler/web/assets-app.rb +40 -0
- data/lib/rhet-butler/web/main-app.rb +139 -0
- data/lib/rhet-butler/web/presentation-app.rb +50 -0
- data/lib/rhet-butler/web/qr-display-app.rb +37 -0
- data/lib/rhet-butler/yaml-schema.rb +9 -0
- data/lib/rhet-butler/yaml-type.rb +23 -0
- data/lib/rhet-butler.rb +2 -0
- data/spec/arrangements.rb +76 -0
- data/spec/html-generation.rb +48 -0
- data/spec/presentation-view.rb +72 -0
- data/spec/rhet-butler.rb +59 -0
- data/spec/slide-loader.rb +51 -0
- data/spec/slide-processing.rb +73 -0
- data/spec_support/gem_test_suite.rb +17 -0
- metadata +324 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
module RhetButler
|
2
|
+
class Arrangement
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
@slides = []
|
7
|
+
@slide_width = 1000
|
8
|
+
@slide_height = 1000
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :slides, :slide_width, :slide_height
|
12
|
+
|
13
|
+
def previous_slide
|
14
|
+
@slides.last
|
15
|
+
end
|
16
|
+
|
17
|
+
def each
|
18
|
+
if block_given?
|
19
|
+
@slides.each{|slide| yield slide}
|
20
|
+
else
|
21
|
+
@slides.each
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
def register(name)
|
27
|
+
Arrangement.registry[name] = self
|
28
|
+
end
|
29
|
+
|
30
|
+
def registry
|
31
|
+
@registry ||= {}
|
32
|
+
end
|
33
|
+
|
34
|
+
def [](name)
|
35
|
+
@registry[name]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Linear < Arrangement
|
41
|
+
register "linear"
|
42
|
+
|
43
|
+
def initialize(plus_x, plus_y)
|
44
|
+
super
|
45
|
+
@plus_x = plus_x
|
46
|
+
@plus_y = plus_y
|
47
|
+
end
|
48
|
+
|
49
|
+
def arrange(slideset)
|
50
|
+
slide = slideset.current_slide
|
51
|
+
slide.position.x = slideset.previous_slide.position.x + @plus_x
|
52
|
+
slide.position.y = slideset.previous_slide.position.y + @plus_y
|
53
|
+
return slide
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class LinearDigression < Linear
|
58
|
+
register "digress-linear"
|
59
|
+
register "linear-digress"
|
60
|
+
|
61
|
+
def previous_slide
|
62
|
+
@preceeding
|
63
|
+
end
|
64
|
+
|
65
|
+
def arrange(slideset)
|
66
|
+
@preceeding ||= slideset.previous_slide
|
67
|
+
super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Horizontal < Linear
|
72
|
+
register "horizontal"
|
73
|
+
|
74
|
+
def initialize
|
75
|
+
super(1000, 0)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'valise'
|
3
|
+
require 'rhet-butler/configuration'
|
4
|
+
require 'rhet-butler/file-manager'
|
5
|
+
|
6
|
+
module RhetButler
|
7
|
+
class CommandLine < ::Thor
|
8
|
+
def self.shared_options
|
9
|
+
method_option :sources, :type => :array
|
10
|
+
method_option :root_slide, :type => :string
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "static", "Builds a static version of the presentation"
|
14
|
+
method_option :target, :type => :string
|
15
|
+
shared_options
|
16
|
+
def static
|
17
|
+
require 'rhet-butler/static-generator'
|
18
|
+
|
19
|
+
file_manager = FileManager.new(options)
|
20
|
+
generator = StaticGenerator.new(file_manager)
|
21
|
+
|
22
|
+
generator.go!
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "check", "Load slide set to check syntax"
|
26
|
+
shared_options
|
27
|
+
def check
|
28
|
+
require 'rhet-butler/web/main-app'
|
29
|
+
|
30
|
+
file_manager = FileManager.new(options)
|
31
|
+
app = Web::MainApp.new(file_manager)
|
32
|
+
|
33
|
+
say "Slides loaded and parsed"
|
34
|
+
say " #{app.viewer_app.slides.length} slides loaded"
|
35
|
+
say " Serving slides and assets found in: #{app.slides}"
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "serve", "Run the presentation server"
|
39
|
+
shared_options
|
40
|
+
def serve
|
41
|
+
require 'rhet-butler/web/main-app'
|
42
|
+
|
43
|
+
file_manager = FileManager.new(options)
|
44
|
+
app = Web::MainApp.new(file_manager)
|
45
|
+
app.check
|
46
|
+
app.start
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module RhetButler
|
2
|
+
#This class is used to manage application config throughout. Basically it
|
3
|
+
#wraps a hash loaded from the base fileset. Since the file search path can be
|
4
|
+
#configured from there, it would be overly complex to allow config.yaml files
|
5
|
+
#in a configured source path.
|
6
|
+
#
|
7
|
+
#Also, n.b. all access to configuration is through methods on this class, so
|
8
|
+
#it's easy to see what values are allowed
|
9
|
+
class Configuration
|
10
|
+
def initialize(files, overrides=nil)
|
11
|
+
@base_hash =
|
12
|
+
begin
|
13
|
+
files.find("config.yaml").contents rescue {}
|
14
|
+
rescue Object
|
15
|
+
{}
|
16
|
+
end
|
17
|
+
@base_hash.merge!(overrides) unless overrides.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def root_slide_template
|
21
|
+
@base_hash['root_slide_template'] || 'presentation.html'
|
22
|
+
end
|
23
|
+
|
24
|
+
def username
|
25
|
+
@base_hash['username'] || 'judson'
|
26
|
+
end
|
27
|
+
|
28
|
+
def password
|
29
|
+
@base_hash['password'] || 'judsonr00tzme'
|
30
|
+
end
|
31
|
+
|
32
|
+
def author
|
33
|
+
@base_hash['author_name'] || "Judson Lester"
|
34
|
+
end
|
35
|
+
|
36
|
+
def title
|
37
|
+
@base_hash['presentation_title'] || 'Presentation'
|
38
|
+
end
|
39
|
+
|
40
|
+
def description
|
41
|
+
@base_hash['presentation_description'] || "A nifty presentation made with Rhet Butler"
|
42
|
+
end
|
43
|
+
|
44
|
+
def search_paths
|
45
|
+
@base_hash["sources"] || []
|
46
|
+
end
|
47
|
+
|
48
|
+
def static_target
|
49
|
+
@base_hash["static_target"] || "static"
|
50
|
+
end
|
51
|
+
|
52
|
+
def impress_config
|
53
|
+
@base_hash['impress-config'] || {}
|
54
|
+
end
|
55
|
+
|
56
|
+
def root_arrangement
|
57
|
+
@base_hash["arrangement"] || "horizontal"
|
58
|
+
end
|
59
|
+
|
60
|
+
def arrangement_blueprint
|
61
|
+
@base_hash["blueprint"] || {}
|
62
|
+
end
|
63
|
+
|
64
|
+
def serve_port
|
65
|
+
@base_hash["serve_port"] || 8081
|
66
|
+
end
|
67
|
+
|
68
|
+
def root_slide
|
69
|
+
@base_hash["root_slide"] || "slides.yaml"
|
70
|
+
end
|
71
|
+
|
72
|
+
def default_slide_type
|
73
|
+
@base_hash["default_slide_type"] || "textile"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'valise'
|
2
|
+
require 'rhet-butler/configuration'
|
3
|
+
|
4
|
+
module RhetButler
|
5
|
+
#All file handling is routed through this class.
|
6
|
+
#
|
7
|
+
#Basic configuration (including additional search paths for other configs and
|
8
|
+
#slides) can only come from the current directory or the "basic search path":
|
9
|
+
#* .rhet/
|
10
|
+
#* ~/.rhet/
|
11
|
+
#* /usr/share/rhet-butler/
|
12
|
+
#* /etc/rhet-butler/
|
13
|
+
#[the defaults provided by the gem]
|
14
|
+
#
|
15
|
+
#Other paths configured by --sources or sources: [] in base configs are added
|
16
|
+
#after the current directory and before that list.
|
17
|
+
#
|
18
|
+
#There are several subdirectories searched in these search paths, depending
|
19
|
+
#on context:
|
20
|
+
#
|
21
|
+
#* presenter/
|
22
|
+
#* viewer/
|
23
|
+
#* common/
|
24
|
+
#
|
25
|
+
#Presenter and viewer files are used for displaying the appropriate
|
26
|
+
#presentation, so that the presenter can have a different display (e.g. with
|
27
|
+
#notes and a timer) than the audience (e.g. nifty transitions etc.)
|
28
|
+
#
|
29
|
+
#Slide files are loaded without a sub-directory - they're always the same
|
30
|
+
#regardless of context.
|
31
|
+
#
|
32
|
+
#Presenter configs, templates, and assets are searched for in presenter, then
|
33
|
+
#common.
|
34
|
+
#
|
35
|
+
#Audience configs, templates and assets are searched for in viewer, then
|
36
|
+
#common.
|
37
|
+
#
|
38
|
+
class FileManager
|
39
|
+
def initialize(overrides = nil)
|
40
|
+
@overrides = overrides || {}
|
41
|
+
@cached_configs = {}
|
42
|
+
@cached_templates = {}
|
43
|
+
end
|
44
|
+
|
45
|
+
def base_config
|
46
|
+
@base_config ||= load_config(base_config_search_path)
|
47
|
+
end
|
48
|
+
|
49
|
+
def slide_files
|
50
|
+
all_files.sub_set("slides") + all_files
|
51
|
+
end
|
52
|
+
|
53
|
+
def base_assets
|
54
|
+
all_files.templates("assets")
|
55
|
+
end
|
56
|
+
|
57
|
+
def aspect_config(aspect_name)
|
58
|
+
@cached_configs[aspect_name] ||= load_config(aspect_search_path(aspect_name))
|
59
|
+
end
|
60
|
+
|
61
|
+
def aspect_templates(aspect)
|
62
|
+
@cached_templates[aspect] ||= aspect_search_path(aspect).templates
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def load_config(files)
|
67
|
+
Configuration.new(files, @overrides)
|
68
|
+
end
|
69
|
+
|
70
|
+
def current_directory
|
71
|
+
Valise::Set.define do
|
72
|
+
rw "."
|
73
|
+
handle "config.yaml", :yaml, :hash_merge
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def configured_search_path
|
78
|
+
base_config = self.base_config
|
79
|
+
Valise::Set.define do
|
80
|
+
base_config.search_paths.each do |path|
|
81
|
+
rw path
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def base_config_set
|
87
|
+
@base_config_set ||=
|
88
|
+
Valise::Set.define do
|
89
|
+
rw [".rhet"]
|
90
|
+
rw ["~", ".rhet"]
|
91
|
+
rw ["", "usr", "share", "rhet-butler"]
|
92
|
+
rw ["", "etc", "rhet-butler"]
|
93
|
+
ro from_here(["..", "..", "..", "default-configuration"])
|
94
|
+
|
95
|
+
handle "config.yaml", :yaml, :hash_merge
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def target_valise
|
100
|
+
@target_valise ||=
|
101
|
+
begin
|
102
|
+
target_directory = base_config.static_target
|
103
|
+
Valise::define do
|
104
|
+
rw target_directory
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def all_files
|
110
|
+
current_directory + configured_search_path + base_config_set
|
111
|
+
end
|
112
|
+
|
113
|
+
def base_config_search_path
|
114
|
+
set = current_directory + base_config_set
|
115
|
+
set + set.sub_set("common")
|
116
|
+
end
|
117
|
+
|
118
|
+
def aspect_search_path(aspect)
|
119
|
+
aspect = aspect.to_s
|
120
|
+
set = all_files.sub_set(aspect)
|
121
|
+
set += all_files.sub_set("common")
|
122
|
+
set += all_files
|
123
|
+
return set
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
require 'valise'
|
3
|
+
|
4
|
+
module RhetButler
|
5
|
+
class HTMLGenerator
|
6
|
+
class Presentation
|
7
|
+
def initialize(configuration)
|
8
|
+
@author_name = configuration.author
|
9
|
+
@title = configuration.title
|
10
|
+
@description = configuration.description
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :author_name, :title, :description
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(configuration, templates)
|
17
|
+
@impress_config = configuration.impress_config
|
18
|
+
@templates = templates
|
19
|
+
@slides = []
|
20
|
+
@presentation = Presentation.new(configuration)
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_accessor :slides, :presentation, :impress_config
|
24
|
+
|
25
|
+
def render(path, scope=nil, locals=nil)
|
26
|
+
@templates.find(path).contents.render(scope || self, locals || {})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rhet-butler/yaml-type'
|
2
|
+
|
3
|
+
module RhetButler
|
4
|
+
class LayoutRule
|
5
|
+
include YamlType
|
6
|
+
def initialize
|
7
|
+
@match = {}
|
8
|
+
@layout_args = nil
|
9
|
+
end
|
10
|
+
attr_accessor :match, :layout_type, :layout_args
|
11
|
+
|
12
|
+
def self.optional_config
|
13
|
+
%w[match]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.required_config
|
17
|
+
%w[layout]
|
18
|
+
end
|
19
|
+
|
20
|
+
def init_with(coder)
|
21
|
+
@config_hash =
|
22
|
+
case coder.type
|
23
|
+
when :seq
|
24
|
+
{ 'match' => coder.seq[0], 'layout' => coder.seq[1] }
|
25
|
+
when :map
|
26
|
+
coder.map
|
27
|
+
else
|
28
|
+
raise "Tried to configure a layout rule with non-sequence: #{coder.inspect}"
|
29
|
+
end
|
30
|
+
|
31
|
+
check_config_hash(@config_hash)
|
32
|
+
|
33
|
+
value_from_config("match") do |value|
|
34
|
+
if value == 'default'
|
35
|
+
@match = {}
|
36
|
+
else
|
37
|
+
@match = value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
@layout_type, @layout_args = *@config_hash['layout']
|
42
|
+
end
|
43
|
+
|
44
|
+
def layout
|
45
|
+
Arrangement[@layout_type].new(*(@layout_args||[]))
|
46
|
+
end
|
47
|
+
|
48
|
+
def match?(group)
|
49
|
+
@match.all? do |key, value|
|
50
|
+
target = group.metadata.fetch(key)
|
51
|
+
value === target
|
52
|
+
end
|
53
|
+
rescue KeyError
|
54
|
+
false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'thin'
|
2
|
+
require 'rack/sockjs'
|
3
|
+
|
4
|
+
module RhetButler
|
5
|
+
class FollowerSession < SockJS::Session
|
6
|
+
def initialize(connection)
|
7
|
+
super
|
8
|
+
@queue = connection.options[:queue]
|
9
|
+
end
|
10
|
+
|
11
|
+
def opened
|
12
|
+
@queue.subscribe(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def close(*args)
|
16
|
+
@queue.unsubscribe(self)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class LeaderSession < SockJS::Session
|
22
|
+
def initialize(connection)
|
23
|
+
super
|
24
|
+
@queue = connection.options[:queue]
|
25
|
+
end
|
26
|
+
|
27
|
+
def process_message(message)
|
28
|
+
@queue.current_slide = message
|
29
|
+
@queue.enqueue(message)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class SlideMessageQueue
|
34
|
+
attr_accessor :current_slide
|
35
|
+
def initialize
|
36
|
+
@listeners = {}
|
37
|
+
end
|
38
|
+
|
39
|
+
def inspect
|
40
|
+
"<<#{self.class.name} Listeners: #{@listeners.keys.length}>>"
|
41
|
+
end
|
42
|
+
|
43
|
+
def subscribe(session)
|
44
|
+
@listeners[session] = true
|
45
|
+
session.send(current_slide) unless current_slide.nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
def unsubscribe(session)
|
49
|
+
@listeners.delete_key(session)
|
50
|
+
end
|
51
|
+
|
52
|
+
def enqueue(message)
|
53
|
+
@listeners.keys.each do |session|
|
54
|
+
session.send(message)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rhet-butler/yaml-type'
|
2
|
+
|
3
|
+
module RhetButler
|
4
|
+
class SlideGroup
|
5
|
+
include YamlType
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
class <<self
|
9
|
+
def optional_config
|
10
|
+
%w[type slide_type]
|
11
|
+
end
|
12
|
+
|
13
|
+
def required_config
|
14
|
+
%w[slides]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def setup_defaults
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@slides = []
|
24
|
+
@metadata = {}
|
25
|
+
end
|
26
|
+
attr_accessor :slides
|
27
|
+
attr_reader :metadata
|
28
|
+
|
29
|
+
def each
|
30
|
+
if block_given?
|
31
|
+
@slides.each{|slide| yield(slide)}
|
32
|
+
else
|
33
|
+
@slides.each
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def init_with(coder)
|
38
|
+
setup_defaults
|
39
|
+
|
40
|
+
@config_hash =
|
41
|
+
case coder.type
|
42
|
+
when :map
|
43
|
+
coder.map
|
44
|
+
when :scalar
|
45
|
+
raise "A slide group needs to at least be a list of slides"
|
46
|
+
when :seq
|
47
|
+
{ 'slides' => coder.seq}
|
48
|
+
end
|
49
|
+
|
50
|
+
check_config_hash(@config_hash)
|
51
|
+
|
52
|
+
@slides = @config_hash.delete('slides')
|
53
|
+
@metadata = @config_hash
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module RhetButler
|
2
|
+
class Includer
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@slides = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def init_with(coder)
|
11
|
+
unless coder.type == :scalar
|
12
|
+
raise "!include with non-scalar - use a path string"
|
13
|
+
end
|
14
|
+
@path = coder.scalar
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_accessor :path
|
18
|
+
attr_reader :slides
|
19
|
+
|
20
|
+
def each
|
21
|
+
if block_given?
|
22
|
+
@slides.each{|slide| yield slide}
|
23
|
+
else
|
24
|
+
@slides.each
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def load(loader)
|
29
|
+
loader = loader.dup
|
30
|
+
@slides = loader.load_file(path)
|
31
|
+
loader
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|