rhet-butler 0.5.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +15 -0
  2. data/default-configuration/assets/javascript/keyboard-nav.js +91 -0
  3. data/default-configuration/assets/javascript/rhet-present.js +855 -0
  4. data/default-configuration/assets/javascript/rhet-present.min.js +55 -0
  5. data/default-configuration/assets/stylesheets/_animate-helpers.scss +41 -0
  6. data/default-configuration/assets/stylesheets/animate/_attention.scss +36 -0
  7. data/default-configuration/assets/stylesheets/animate/_bounce.scss +71 -0
  8. data/default-configuration/assets/stylesheets/animate/_fade.scss +56 -0
  9. data/default-configuration/assets/stylesheets/animate/_flip.scss +98 -0
  10. data/default-configuration/assets/stylesheets/animate/_lightSpeed.scss +20 -0
  11. data/default-configuration/assets/stylesheets/animate/_roll.scss +20 -0
  12. data/default-configuration/assets/stylesheets/animate/_rotate.scss +40 -0
  13. data/default-configuration/assets/stylesheets/animate/_special.scss +17 -0
  14. data/default-configuration/assets/stylesheets/animate/_windblown.sass +17 -0
  15. data/default-configuration/assets/stylesheets/animate/attention/._pulse.scss.swp +0 -0
  16. data/default-configuration/assets/stylesheets/animate/attention/_flash.scss +34 -0
  17. data/default-configuration/assets/stylesheets/animate/attention/_pulse.scss +28 -0
  18. data/default-configuration/assets/stylesheets/animate/attention/_shake.scss +53 -0
  19. data/default-configuration/assets/stylesheets/animate/attention/_swing.scss +40 -0
  20. data/default-configuration/assets/stylesheets/animate/attention/_tada.scss +51 -0
  21. data/default-configuration/assets/stylesheets/animate/attention/_wiggle.scss +52 -0
  22. data/default-configuration/assets/stylesheets/animate/attention/_wobble.scss +41 -0
  23. data/default-configuration/assets/stylesheets/animate/bounce/_bounceIn.scss +151 -0
  24. data/default-configuration/assets/stylesheets/animate/bounce/_bounceOut.scss +139 -0
  25. data/default-configuration/assets/stylesheets/animate/fade/_fadeIn.sass +139 -0
  26. data/default-configuration/assets/stylesheets/animate/fade/_fadeOut.sass +139 -0
  27. data/default-configuration/assets/stylesheets/animate/flip/_flipIn.scss +78 -0
  28. data/default-configuration/assets/stylesheets/animate/flip/_flipOut.scss +66 -0
  29. data/default-configuration/assets/stylesheets/animate/lightSpeed/_lightSpeedIn.scss +37 -0
  30. data/default-configuration/assets/stylesheets/animate/lightSpeed/_lightSpeedOut.scss +29 -0
  31. data/default-configuration/assets/stylesheets/animate/roll/_rollIn.scss +29 -0
  32. data/default-configuration/assets/stylesheets/animate/roll/_rollOut.scss +28 -0
  33. data/default-configuration/assets/stylesheets/animate/rotate/_rotateIn.scss +208 -0
  34. data/default-configuration/assets/stylesheets/animate/rotate/_rotateOut.scss +208 -0
  35. data/default-configuration/assets/stylesheets/animate/special/_hinge.scss +49 -0
  36. data/default-configuration/assets/stylesheets/animate/windblown/_windblownIn.sass +28 -0
  37. data/default-configuration/assets/stylesheets/animate/windblown/_windblownOut.sass +24 -0
  38. data/default-configuration/assets/stylesheets/font.css +30 -0
  39. data/default-configuration/assets/stylesheets/highlight/arta.css +158 -0
  40. data/default-configuration/assets/stylesheets/highlight/ascetic.css +50 -0
  41. data/default-configuration/assets/stylesheets/highlight/brown_paper.css +104 -0
  42. data/default-configuration/assets/stylesheets/highlight/brown_papersq.png +0 -0
  43. data/default-configuration/assets/stylesheets/highlight/dark.css +103 -0
  44. data/default-configuration/assets/stylesheets/highlight/default.css +135 -0
  45. data/default-configuration/assets/stylesheets/highlight/far.css +111 -0
  46. data/default-configuration/assets/stylesheets/highlight/github.css +127 -0
  47. data/default-configuration/assets/stylesheets/highlight/googlecode.css +144 -0
  48. data/default-configuration/assets/stylesheets/highlight/idea.css +121 -0
  49. data/default-configuration/assets/stylesheets/highlight/ir_black.css +104 -0
  50. data/default-configuration/assets/stylesheets/highlight/magula.css +120 -0
  51. data/default-configuration/assets/stylesheets/highlight/monokai.css +114 -0
  52. data/default-configuration/assets/stylesheets/highlight/pojoaque.css +104 -0
  53. data/default-configuration/assets/stylesheets/highlight/pojoaque.jpg +0 -0
  54. data/default-configuration/assets/stylesheets/highlight/rainbow.css +114 -0
  55. data/default-configuration/assets/stylesheets/highlight/school_book.css +111 -0
  56. data/default-configuration/assets/stylesheets/highlight/school_book.png +0 -0
  57. data/default-configuration/assets/stylesheets/highlight/solarized_light.css +88 -0
  58. data/default-configuration/assets/stylesheets/highlight/sunburst.css +158 -0
  59. data/default-configuration/assets/stylesheets/highlight/tomorrow-night-blue.css +52 -0
  60. data/default-configuration/assets/stylesheets/highlight/tomorrow-night-bright.css +51 -0
  61. data/default-configuration/assets/stylesheets/highlight/tomorrow-night-eighties.css +51 -0
  62. data/default-configuration/assets/stylesheets/highlight/tomorrow-night.css +52 -0
  63. data/default-configuration/assets/stylesheets/highlight/tomorrow.css +49 -0
  64. data/default-configuration/assets/stylesheets/highlight/vs.css +86 -0
  65. data/default-configuration/assets/stylesheets/highlight/xcode.css +154 -0
  66. data/default-configuration/assets/stylesheets/highlight/zenburn.css +114 -0
  67. data/default-configuration/assets/stylesheets/presenter/rhet.css.sass +160 -0
  68. data/default-configuration/assets/stylesheets/rhet.css.sass +142 -0
  69. data/default-configuration/assets/themes.googleusercontent.com/static/fonts/arimo/v5/K-bXE71xZHgbUS_UdQjugvesZW2xOQ-xsNqO47m55DA.ttf +0 -0
  70. data/default-configuration/assets/themes.googleusercontent.com/static/fonts/cinzeldecorative/v1/pXhIVnhFtL_B9Vb1wq2F9wIh9oxuYcmvOvyh_107lQs.ttf +0 -0
  71. data/default-configuration/assets/themes.googleusercontent.com/static/fonts/cinzeldecorative/v1/pXhIVnhFtL_B9Vb1wq2F9zCUrkmwPfdnoTjOU_kXqBI.ttf +0 -0
  72. data/default-configuration/assets/themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJYW_AySPyikQrZReizgrnuw.ttf +0 -0
  73. data/default-configuration/assets/themes.googleusercontent.com/static/fonts/slackey/v3/bJZDrYrGx8atJRHR9DVdqg.ttf +0 -0
  74. data/default-configuration/common/config.yaml +17 -0
  75. data/default-configuration/common/templates/group.html.erb +5 -0
  76. data/default-configuration/common/templates/presentation.html.erb +11 -17
  77. data/default-configuration/common/templates/presenter-qr.html.erb +3 -3
  78. data/default-configuration/common/templates/slide.html.erb +3 -0
  79. data/default-configuration/common/templates/stylesheets.html.erb +1 -1
  80. data/default-configuration/presenter/templates/live-javascript.html.erb +4 -3
  81. data/default-configuration/presenter/templates/slide.html.erb +6 -0
  82. data/default-configuration/presenter/templates/stylesheets.html.erb +1 -1
  83. data/default-configuration/skels/config.yaml +15 -0
  84. data/default-configuration/skels/slides.yaml +6 -0
  85. data/default-configuration/viewer/templates/live-javascript.html.erb +1 -1
  86. data/lib/rhet-butler/arrangement-finder.rb +71 -0
  87. data/lib/rhet-butler/command-line.rb +69 -1
  88. data/lib/rhet-butler/configuration.rb +20 -5
  89. data/lib/rhet-butler/file-loading.rb +28 -0
  90. data/lib/rhet-butler/file-manager.rb +42 -22
  91. data/lib/rhet-butler/filter-resolver.rb +45 -0
  92. data/lib/rhet-butler/html-generator.rb +24 -4
  93. data/lib/rhet-butler/include-processor.rb +55 -0
  94. data/lib/rhet-butler/layout-rule.rb +17 -13
  95. data/lib/rhet-butler/resource-localizer.rb +22 -0
  96. data/lib/rhet-butler/sass-functions.rb +40 -0
  97. data/lib/rhet-butler/slide-arranger.rb +39 -0
  98. data/lib/rhet-butler/slide-group.rb +56 -21
  99. data/lib/rhet-butler/slide-includer.rb +5 -2
  100. data/lib/rhet-butler/slide-loader.rb +16 -332
  101. data/lib/rhet-butler/slide-processor.rb +27 -0
  102. data/lib/rhet-butler/slide-renderer.rb +42 -0
  103. data/lib/rhet-butler/slide-renderers/code.rb +19 -0
  104. data/lib/rhet-butler/slide-renderers/cues.rb +27 -0
  105. data/lib/rhet-butler/slide-renderers/textile.rb +14 -0
  106. data/lib/rhet-butler/slide-rendering.rb +22 -0
  107. data/lib/rhet-butler/slide-traverser.rb +45 -0
  108. data/lib/rhet-butler/slide.rb +40 -30
  109. data/lib/rhet-butler/stasis/css-transform.rb +55 -0
  110. data/lib/rhet-butler/stasis/document-transform.rb +32 -0
  111. data/lib/rhet-butler/stasis/html-transform.rb +51 -0
  112. data/lib/rhet-butler/stasis/http-loader.rb +19 -0
  113. data/lib/rhet-butler/stasis/identity-transform.rb +18 -0
  114. data/lib/rhet-butler/stasis/rack-loader.rb +57 -0
  115. data/lib/rhet-butler/stasis/resource-mapping.rb +55 -0
  116. data/lib/rhet-butler/stasis/transform-queue.rb +87 -0
  117. data/lib/rhet-butler/stasis/writer.rb +35 -0
  118. data/lib/rhet-butler/stasis.rb +18 -0
  119. data/lib/rhet-butler/static-generator.rb +21 -29
  120. data/lib/rhet-butler/web/assets-app.rb +24 -8
  121. data/lib/rhet-butler/web/main-app.rb +17 -8
  122. data/lib/rhet-butler/web/presentation-app.rb +22 -14
  123. data/lib/rhet-butler/web/qr-display-app.rb +4 -1
  124. data/lib/rhet-butler/yaml-schema.rb +5 -4
  125. data/lib/rhet-butler/yaml-type.rb +24 -1
  126. data/spec/html-generation.rb +7 -1
  127. data/spec/presentation-view.rb +33 -8
  128. data/spec/rhet-butler.rb +0 -13
  129. data/spec/slide-loader.rb +3 -3
  130. data/spec/slide-processing.rb +6 -3
  131. metadata +209 -119
  132. data/default-configuration/assets/javascript/impress.js +0 -800
  133. data/default-configuration/assets/stylesheets/presenter/presentation.css +0 -477
  134. data/lib/rhet-butler.rb +0 -2
@@ -1,10 +1,11 @@
1
1
  require 'rhet-butler/yaml-type'
2
2
 
3
3
  module RhetButler
4
- class SlideGroup
5
- include YamlType
4
+ class SlideGroup < YamlType
6
5
  include Enumerable
7
6
 
7
+ register "group"
8
+
8
9
  class <<self
9
10
  def optional_config
10
11
  %w[type slide_type]
@@ -15,16 +16,43 @@ module RhetButler
15
16
  end
16
17
  end
17
18
 
18
-
19
19
  def setup_defaults
20
- end
21
-
22
- def initialize
20
+ @html_id = nil
21
+ @classes = ["group"]
23
22
  @slides = []
24
23
  @metadata = {}
25
24
  end
25
+
26
+ def normalize_config(coder)
27
+ case coder.type
28
+ when :map
29
+ coder.map
30
+ when :scalar
31
+ raise "A slide group needs to at least be a list of slides"
32
+ when :seq
33
+ { 'slides' => coder.seq}
34
+ end
35
+ end
36
+
37
+ def configure
38
+ value_from_config("html_id") do |value|
39
+ @html_id = value
40
+ end
41
+
42
+ value_from_config("html_classes") do |value|
43
+ @html_classes += [*value]
44
+ end
45
+
46
+ value_from_config("html_class") do |value|
47
+ @html_classes << value
48
+ end
49
+
50
+ @slides = @config_hash.delete('slides')
51
+ @metadata = @config_hash
52
+ end
53
+
26
54
  attr_accessor :slides
27
- attr_reader :metadata
55
+ attr_reader :metadata, :classes
28
56
 
29
57
  def each
30
58
  if block_given?
@@ -34,23 +62,30 @@ module RhetButler
34
62
  end
35
63
  end
36
64
 
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}
65
+ def each_slide
66
+ if block_given?
67
+ @slides.each do |slide|
68
+ if slide.is_a? SlideGroup
69
+ slide.each_slide{|sl| yield sl}
70
+ else
71
+ yield slide
72
+ end
48
73
  end
74
+ else
75
+ enum_for :each_slide
76
+ end
77
+ end
49
78
 
50
- check_config_hash(@config_hash)
79
+ def template_name
80
+ "group.html"
81
+ end
51
82
 
52
- @slides = @config_hash.delete('slides')
53
- @metadata = @config_hash
83
+ def id_attr
84
+ if @html_id.nil?
85
+ return ""
86
+ else
87
+ "id='#@html_id'"
88
+ end
54
89
  end
55
90
  end
56
91
  end
@@ -1,7 +1,10 @@
1
+ require 'rhet-butler/yaml-type'
2
+
1
3
  module RhetButler
2
- class Includer
3
- include Enumerable
4
+ class Includer < YamlType
5
+ register 'include'
4
6
 
7
+ include Enumerable
5
8
 
6
9
  def initialize
7
10
  @slides = []
@@ -1,13 +1,16 @@
1
- require 'rhet-butler/slide-group'
2
- require 'rhet-butler/slide'
3
- require 'rhet-butler/slide-includer'
4
- require 'rhet-butler/arrangement'
1
+ require 'rhet-butler/yaml-schema'
2
+ require 'rhet-butler/file-loading'
3
+ require 'rhet-butler/include-processor'
4
+ require 'rhet-butler/slide-processor'
5
+ require 'rhet-butler/filter-resolver'
5
6
 
6
7
  module RhetButler
7
8
  class SlideLoader
8
9
  def initialize(slide_files, configuration)
9
10
  @file_set = slide_files
10
- @default_slide_type = configuration.default_slide_type
11
+ @named_filter_lists = configuration.named_filter_lists
12
+ @default_content_filters = configuration.default_content_filters
13
+ @default_note_filters = configuration.default_note_filters
11
14
  @root_slide = configuration.root_slide
12
15
  @root_group = SlideGroup.new
13
16
  @blueprint = configuration.arrangement_blueprint
@@ -24,338 +27,19 @@ module RhetButler
24
27
  including.root_group = root_group
25
28
  including.traverse
26
29
 
30
+ filter_resolver = FilterResolver.new
31
+ filter_resolver.root_group = root_group
32
+ filter_resolver.named_filter_lists = @named_filter_lists
33
+ filter_resolver.default_content_filters = @default_content_filters
34
+ filter_resolver.default_note_filters = @default_note_filters
35
+ filter_resolver.traverse
36
+
27
37
  processor = SlideProcessor.new
28
38
  processor.root_group = root_group
29
- processor.default_slide_type = @default_slide_type
30
39
  processor.blueprint = @blueprint
31
40
  processor.process
32
- return processor.slides
33
- end
34
- end
35
-
36
- require 'rhet-butler/yaml-schema'
37
- class FileLoading
38
- def initialize(file_set)
39
- @file_set = file_set
40
- @loaded_paths = {}
41
- end
42
- attr_reader :loaded_paths, :file_set
43
-
44
- def initialize_copy(other)
45
- @file_set = other.file_set
46
- @loaded_paths = other.loaded_paths.dup
47
- end
48
-
49
- def load_file(rel_path)
50
- file = @file_set.find(rel_path)
51
-
52
- if @loaded_paths.has_key?(file.full_path)
53
- raise "Circular inclusion of slides: >> #{file.full_path} << #{@loaded_paths.keys.inspect}"
54
- else
55
- @loaded_paths[file.full_path] = true
56
- end
57
-
58
- return YAML.load_stream(file.contents).flatten
59
- end
60
- end
61
-
62
- class SlideProcessor
63
- attr_accessor :root_group, :blueprint, :default_slide_type
64
- attr_reader :slides
65
-
66
- def process
67
- rendering = SlideRendering.new
68
- rendering.root_group = @root_group
69
- rendering.default_type = @default_slide_type
70
- rendering.traverse
71
-
72
- finder = ArrangementFinder.new
73
- finder.root_group = @root_group
74
- finder.blueprint = @blueprint
75
- finder.traverse
76
-
77
- arranger = SlideArranger.new
78
- arranger.root_arrangement = finder.root_arrangement
79
- arranger.traverse
80
-
81
- @slides = arranger.slides
82
- end
83
- end
84
-
85
- class SlideTraverser
86
- def initialize
87
- @iter_stack = []
88
- @target_stack = []
89
- end
90
-
91
- attr_reader :iter_stack, :target_stack
92
-
93
- def on_group(group)
94
- descend(group, group)
95
- end
96
-
97
- def ascend
98
- target_stack.pop
99
- iter_stack.pop
100
- end
101
-
102
- def descend(source, dest)
103
- iter_stack.push source.each
104
- target_stack.push dest
105
- end
106
-
107
- def traverse
108
- setup
109
- until iter_stack.empty?
110
- begin
111
- item = iter_stack.last.next
112
- case item
113
- when Slide
114
- on_slide(item)
115
- when Includer
116
- on_include(item)
117
- else
118
- on_group(item)
119
- end
120
- rescue StopIteration
121
- ascend
122
- end
123
- end
124
- end
125
- end
126
-
127
- class ClassRegistry
128
- def initialize
129
- @classes = {}
130
- end
131
-
132
- def register(name, klass)
133
- @classes[name.to_s] = klass
134
- end
135
-
136
- def fetch(name)
137
- @classes.fetch(name.to_s)
138
- end
139
- alias [] fetch
140
- end
141
-
142
- class SlideRenderer
143
- class << self
144
- def registry
145
- @registry ||= ClassRegistry.new
146
- end
147
-
148
- def register(name)
149
- SlideRenderer.registry.register(name, self)
150
- end
151
-
152
- def for_type(type)
153
- SlideRenderer.registry.fetch(type)
154
- end
155
-
156
- def process(type, options, slide)
157
- for_type(type).new(options, slide).to_s
158
- end
159
- end
160
-
161
- def initialize(options, slide)
162
- @options = options
163
- @slide_content = slide
164
- end
165
-
166
- def to_s
167
- process(@slide_content)
168
- end
169
- end
170
-
171
- class CodeRenderer < SlideRenderer
172
- register :code
173
-
174
- def process(string)
175
- "<pre><code#{@options ? " class='#{@options}'" : ""}>#{string}</code></pre>"
176
- end
177
- end
178
-
179
- require 'redcloth'
180
- class TextileRenderer < SlideRenderer
181
- register :textile
182
- register :texttile
183
-
184
- def process(string)
185
- RedCloth.new(string).to_html
186
- end
187
- end
188
-
189
- class SlideRendering < SlideTraverser
190
- attr_accessor :root_group, :default_type
191
-
192
- def setup
193
- descend(@root_group, @root_group)
194
- end
195
-
196
- def on_slide(slide)
197
- slide_type = slide.type || default_type
198
- base_type,options = *(slide_type.split(":"))
199
- slide.content = SlideRenderer.process(base_type, options, slide.content)
200
- slide.notes = SlideRenderer.process("textile", nil, slide.notes) unless slide.notes.nil?
201
- end
202
- end
203
-
204
- class IncludeProcessor < SlideTraverser
205
- Collector = Struct.new(:group, :slides, :loader)
206
- attr_accessor :root_group
207
-
208
- def initialize(loader)
209
- @loader = loader
210
- super()
211
- end
212
-
213
- def current_loader
214
- if target_stack.empty?
215
- return @loader
216
- else
217
- return target_stack.last.loader
218
- end
219
- end
220
-
221
- def setup
222
- descend(@root_group, @root_group)
223
- end
224
-
225
- def descend(source, dest)
226
- unless Collector === dest
227
- dest = Collector.new(dest, [], current_loader)
228
- end
229
- super(source, dest)
230
- end
231
-
232
- def ascend
233
- target = target_stack.pop
234
- unless target == target_stack.last
235
- target.group.slides = target.slides
236
- end
237
- iter_stack.pop
238
- end
239
-
240
- def on_include(includer)
241
- loader = includer.load(current_loader)
242
- collector = target_stack.last.dup
243
- collector.loader = loader
244
- descend(includer, collector)
245
- end
246
-
247
- def on_slide(slide)
248
- target_stack.last.slides << slide
249
- end
250
-
251
- def on_group(group)
252
- target_stack.last.slides << group
253
- super
254
- end
255
- end
256
-
257
- class ArrangementFinder < SlideTraverser
258
- attr_accessor :root_arrangement, :root_group, :blueprint
259
-
260
- def initialize
261
- super
262
- end
263
-
264
- def setup
265
- if @blueprint.empty?
266
- raise "Empty blueprint - can't layout slides"
267
- end
268
-
269
- @blueprint.combination(2) do |first, second|
270
- if first.match == second.match
271
- if first.match == {}
272
- raise "Two default rules (default or match: {}) - please fix"
273
- end
274
- warn "Blueprint rules with duplicate rules: will ignore the later one:"
275
- warn second.inspect
276
- end
277
- end
278
-
279
- unless @blueprint.last.match == {}
280
- warn "Last blueprint rule not a default - fixing..."
281
- defaults, rules = @blueprint.partition{|rule| rule.match == {}}
282
- raise "Multiple default blueprint rules" unless defaults.length < 2
283
- raise "No default blueprint rule" unless defaults.length > 0
284
- @blueprint = rules + defaults
285
- end
286
-
287
- default_rule = @blueprint.last
288
- @active_match = default_rule
289
- @root_arrangement = default_rule.layout
290
- descend(@root_group, @root_arrangement)
291
- end
292
-
293
- def on_slide(slide)
294
- target_stack.last.slides << slide
295
- end
296
-
297
- def on_group(group)
298
- arrangement = find_arrangement(group)
299
- if arrangement != target_stack.last
300
- target_stack.last.slides << arrangement
301
- end
302
- descend(group, arrangement)
303
- end
304
-
305
- def match?(filter, value)
306
- return filter === value
307
- end
308
-
309
- def find_arrangement(group)
310
- match = {}
311
- template = nil
312
- match = blueprint.find do |rule|
313
- rule.match?(group)
314
- end
315
-
316
- if !match.nil? and match != @active_match
317
- @active_match = match
318
- return match.layout
319
- else
320
- return target_stack.last
321
- end
322
- end
323
- end
324
-
325
- class SlideArranger < SlideTraverser
326
- attr_reader :slides, :current_slide
327
- attr_accessor :root_arrangement
328
-
329
- def setup
330
- @slides = []
331
- on_group(@root_arrangement)
332
- end
333
-
334
- def null_slide
335
- @null_slide ||= Slide.new
336
- end
337
-
338
- def previous_slide
339
- case @previous_slide
340
- when Slide
341
- @previous_slide
342
- when nil
343
- null_slide
344
- else
345
- @previous_slide.previous_slide
346
- end
347
- end
348
-
349
- def on_slide(slide)
350
- @current_slide = slide.dup
351
- target_stack.last.arrange(self)
352
- @slides.push @current_slide
353
- @previous_slide = @current_slide
354
- end
355
41
 
356
- def ascend
357
- @previous_slide = target_stack.last
358
- super
42
+ return root_group
359
43
  end
360
44
  end
361
45
  end
@@ -0,0 +1,27 @@
1
+ require 'rhet-butler/slide-rendering'
2
+ require 'rhet-butler/arrangement-finder'
3
+ require 'rhet-butler/slide-arranger'
4
+
5
+ module RhetButler
6
+ class SlideProcessor
7
+ attr_accessor :root_group, :blueprint, :default_content_filters, :default_note_filters
8
+ attr_reader :slides
9
+
10
+ def process
11
+ rendering = SlideRendering.new
12
+ rendering.root_group = @root_group
13
+ rendering.traverse
14
+
15
+ finder = ArrangementFinder.new
16
+ finder.root_group = @root_group
17
+ finder.blueprint = @blueprint
18
+ finder.traverse
19
+
20
+ arranger = SlideArranger.new
21
+ arranger.root_arrangement = finder.root_arrangement
22
+ arranger.traverse
23
+
24
+ @slides = arranger.slides
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ require 'rhet-butler/yaml-type'
2
+
3
+ module RhetButler
4
+ class SlideRenderer < YamlType
5
+ def self.required_config
6
+ []
7
+ end
8
+
9
+ def self.optional_config
10
+ []
11
+ end
12
+
13
+ def setup_defaults
14
+ end
15
+
16
+ def positional_options
17
+ []
18
+ end
19
+
20
+ def normalize_config(coder)
21
+ case coder.type
22
+ when :seq
23
+ Hash[positional_options.zip(coder.seq)]
24
+ when :map
25
+ coder.map
26
+ else
27
+ Hash[positional_options.zip([coder.scalar])]
28
+ end
29
+ end
30
+
31
+ def configure
32
+ end
33
+
34
+ def html_class
35
+ nil
36
+ end
37
+ end
38
+ end
39
+
40
+ require 'rhet-butler/slide-renderers/code'
41
+ require 'rhet-butler/slide-renderers/textile'
42
+ require 'rhet-butler/slide-renderers/cues'
@@ -0,0 +1,19 @@
1
+ module RhetButler
2
+ module SlideRenderers
3
+ class Code < SlideRenderer
4
+ register :code
5
+
6
+ def self.optional_config
7
+ %w{class}
8
+ end
9
+
10
+ def positional_options
11
+ %w{class}
12
+ end
13
+
14
+ def process(string)
15
+ "<pre><code#{@config_hash ? " class='#{@config_hash['class']}'" : ""}>#{string}</code></pre>"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ require 'nokogiri'
2
+
3
+ module RhetButler
4
+ module SlideRenderers
5
+ class Cues < SlideRenderer
6
+ register "cues"
7
+
8
+ class XPathExtensions
9
+ def self.regex(node_set, pattern)
10
+ re = Regexp.new(pattern)
11
+ node_set.find_all do |node|
12
+ node.value =~ re
13
+ end
14
+ end
15
+ end
16
+
17
+ def process(string)
18
+ doc = Nokogiri::HTML::DocumentFragment.parse(string) #may need DocumentFragment::parse
19
+ doc.xpath('.//*/@class[regex(.,"\b\d+\b")]', XPathExtensions).each do |attr|
20
+ attr.value = "rhet-butler item " + attr.value
21
+ attr.value = attr.value.gsub(/\b\d+\b/){|m| "cue-#{m[0]}"}
22
+ end
23
+ doc.to_s
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ require 'redcloth'
2
+
3
+ module RhetButler
4
+ module SlideRenderers
5
+ class Textile < SlideRenderer
6
+ register "textile"
7
+ register "texttile"
8
+
9
+ def process(string)
10
+ RedCloth.new(string).to_html
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ require 'rhet-butler/slide-renderer'
2
+ require 'rhet-butler/slide-traverser'
3
+ module RhetButler
4
+ class SlideRendering < SlideTraverser
5
+ attr_accessor :root_group
6
+
7
+ def setup
8
+ descend(@root_group, @root_group)
9
+ end
10
+
11
+ def on_slide(slide)
12
+ slide.content = filter_text(slide.content, slide.content_filters)
13
+ slide.notes = filter_text(slide.notes, slide.note_filters)
14
+ end
15
+
16
+ def filter_text(text, filters)
17
+ filters.inject(text) do |text, filter|
18
+ filter.process(text)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,45 @@
1
+ require 'rhet-butler/yaml-schema'
2
+
3
+ module RhetButler
4
+ class SlideTraverser
5
+ def initialize
6
+ @iter_stack = []
7
+ @target_stack = []
8
+ end
9
+
10
+ attr_reader :iter_stack, :target_stack
11
+
12
+ def on_group(group)
13
+ descend(group, group)
14
+ end
15
+
16
+ def ascend
17
+ target_stack.pop
18
+ iter_stack.pop
19
+ end
20
+
21
+ def descend(source, dest)
22
+ iter_stack.push source.each
23
+ target_stack.push dest
24
+ end
25
+
26
+ def traverse
27
+ setup
28
+ until iter_stack.empty?
29
+ begin
30
+ item = iter_stack.last.next
31
+ case item
32
+ when Slide
33
+ on_slide(item)
34
+ when Includer
35
+ on_include(item)
36
+ else
37
+ on_group(item)
38
+ end
39
+ rescue StopIteration
40
+ ascend
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end