rhet-butler 0.11.1 → 0.12.1

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.
Files changed (31) hide show
  1. checksums.yaml +8 -8
  2. data/default-configuration/assets/javascript/sockjs-0.3.4.js +2379 -0
  3. data/default-configuration/assets/stylesheets/rhet.css.sass +4 -3
  4. data/default-configuration/common/templates/header-javascript.html +1 -1
  5. data/default-configuration/common/templates/presentation.html.erb +1 -1
  6. data/default-configuration/common/templates/presenter-qr.html.erb +1 -1
  7. data/default-configuration/presenter/templates/stylesheets.html.erb +1 -0
  8. data/lib/rhet-butler/command-line.rb +2 -0
  9. data/lib/rhet-butler/filter-resolver.rb +10 -1
  10. data/lib/rhet-butler/messaging.rb +24 -7
  11. data/lib/rhet-butler/resource-localizer.rb +1 -1
  12. data/lib/rhet-butler/slide-contents/embed.rb +39 -0
  13. data/lib/rhet-butler/slide-contents.rb +40 -0
  14. data/lib/rhet-butler/slide-loader.rb +8 -7
  15. data/lib/rhet-butler/slide-rendering.rb +17 -6
  16. data/lib/rhet-butler/slide.rb +9 -78
  17. data/lib/rhet-butler/stasis/rack-loader.rb +3 -1
  18. data/lib/rhet-butler/stasis/transform-queue.rb +23 -13
  19. data/lib/rhet-butler/static-generator.rb +1 -1
  20. data/lib/rhet-butler/web/main-app.rb +12 -12
  21. data/lib/rhet-butler/web/presentation-app.rb +5 -1
  22. data/lib/rhet-butler/yaml-schema.rb +1 -1
  23. data/spec/slide-loader.rb +11 -1
  24. metadata +8 -12
  25. data/lib/rhet-butler/arrangement-finder.rb +0 -71
  26. data/lib/rhet-butler/arrangement.rb +0 -78
  27. data/lib/rhet-butler/layout-rule.rb +0 -61
  28. data/lib/rhet-butler/slide-arranger.rb +0 -39
  29. data/lib/rhet-butler/slide-processor.rb +0 -27
  30. data/spec/arrangements.rb +0 -76
  31. data/spec/slide-processing.rb +0 -76
@@ -134,19 +134,20 @@ body
134
134
  vertical-align: middle
135
135
 
136
136
  @for $i from 1 through 10
137
- li.cue-#{$i}
137
+ li.cue-#{$i}, svg .cue-#{$i}
138
138
  opacity: 0
139
139
 
140
+
140
141
  &.current-cue-#{$i}
141
142
  code span.cue-#{$i}
142
143
  border-radius: 5px
143
144
  +box-shadow(-1px -1px 0px 1px rgba(140,140,140,0.5) inset, 1px 1px 0px 1px rgba(40, 40, 40, 0.5) inset)
144
145
  background-color: rgba(255,255,255,0.1)
145
146
 
146
- li.cue-#{$i}
147
+ li.cue-#{$i}, svg .cue-#{$i}
147
148
  +animation(fadeIn .6s ease both)
148
149
  @for $j from 1 through $i
149
- li.cue-#{$j}
150
+ li.cue-#{$j}, svg .cue-#{$j}
150
151
  opacity: 1
151
152
 
152
153
  p
@@ -1,3 +1,3 @@
1
- <script type="text/javascript" src="assets/javascript/sockjs-0.2.1.js"></script>
1
+ <script type="text/javascript" src="assets/javascript/sockjs-0.3.4.js"></script>
2
2
  <script src="assets/javascript/highlight.pack.js"></script>
3
3
  <script>hljs.initHighlightingOnLoad();</script>
@@ -2,7 +2,7 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
- <meta name="viewport" content="width=1024" />
5
+ <meta name="viewport" content="width=100%" />
6
6
  <meta name="apple-mobile-web-app-capable" content="yes" />
7
7
  <title><%= presentation.title %></title>
8
8
 
@@ -19,7 +19,7 @@
19
19
  }
20
20
  </style>
21
21
 
22
- <script type="text/javascript" src="/assets/javascript/sockjs-0.2.1.js"></script>
22
+ <script type="text/javascript" src="/assets/javascript/sockjs-0.3.4.js"></script>
23
23
  <script type="text/javascript">
24
24
  var sock = new SockJS("/live/follower");
25
25
 
@@ -1,3 +1,4 @@
1
1
  <link href="/stylesheets/google-open-sans.css" rel="stylesheet" />
2
2
  <link href="/stylesheets/presenter/rhet.css" rel="stylesheet" />
3
+ <link href="/stylesheets/prez-local.css" rel="stylesheet" />
3
4
  <link href="/stylesheets/highlight/solarized_dark.css" rel="stylesheet" />
@@ -10,6 +10,7 @@ module RhetButler
10
10
  method_option :root_slide, :type => :string
11
11
  end
12
12
 
13
+ #:nocov:
13
14
  desc "init", "Create example skeleton files to get started with"
14
15
  def init
15
16
  require 'fileutils'
@@ -113,5 +114,6 @@ module RhetButler
113
114
  app.check
114
115
  app.start
115
116
  end
117
+ #:nocov:
116
118
  end
117
119
  end
@@ -36,11 +36,20 @@ module RhetButler
36
36
  slide.html_classes += slide.content_filters.map do |filter|
37
37
  filter.html_class
38
38
  end
39
+
39
40
  slide.note_filters = get_filters(slide.note_filters || default_note_filters)
40
41
  slide.html_classes += slide.content_filters.map do |filter|
41
42
  "note-" + filter.html_class unless filter.html_class.nil?
42
43
  end
43
- rescue => ex
44
+
45
+ [ *slide.raw_content ].each do |content| #XXX This is how all content filtering should work
46
+ case content
47
+ when SlideContents
48
+ content.filters = get_filters(content.filters || default_content_filters)
49
+ end
50
+ end
51
+
52
+ rescue
44
53
  puts "While processing #{slide}:"
45
54
  raise
46
55
  end
@@ -2,35 +2,47 @@ require 'thin'
2
2
  require 'rack/sockjs'
3
3
 
4
4
  module RhetButler
5
- class FollowerSession < SockJS::Session
5
+ class QueueSession < SockJS::Session
6
+ include Thin::Logging
7
+
6
8
  def initialize(connection)
7
9
  super
8
10
  @queue = connection.options[:queue]
9
11
  end
12
+ end
10
13
 
14
+ class FollowerSession < QueueSession
11
15
  def opened
16
+ log_info("Follower opened socket")
12
17
  @queue.subscribe(self)
13
18
  end
14
19
 
15
20
  def close(*args)
21
+ log_info("Follower closed socket")
16
22
  @queue.unsubscribe(self)
17
23
  super
18
24
  end
19
25
  end
20
26
 
21
- class LeaderSession < SockJS::Session
22
- def initialize(connection)
23
- super
24
- @queue = connection.options[:queue]
27
+ class LeaderSession < QueueSession
28
+ def opened
29
+ log_info("Leader opened socket")
30
+ end
31
+
32
+ def close(*args)
33
+ log_info("Leader closed socket")
25
34
  end
26
35
 
27
36
  def process_message(message)
37
+ log_info("Leader moved to slide #{message}")
28
38
  @queue.current_slide = message
29
39
  @queue.enqueue(message)
30
40
  end
31
41
  end
32
42
 
33
43
  class SlideMessageQueue
44
+ include Thin::Logging
45
+
34
46
  attr_accessor :current_slide
35
47
  def initialize
36
48
  @listeners = {}
@@ -46,12 +58,17 @@ module RhetButler
46
58
  end
47
59
 
48
60
  def unsubscribe(session)
49
- @listeners.delete_key(session)
61
+ @listeners.delete(session)
50
62
  end
51
63
 
52
64
  def enqueue(message)
53
65
  @listeners.keys.each do |session|
54
- session.send(message)
66
+ begin
67
+ session.send(message)
68
+ rescue MetaState::WrongStateError => wse
69
+ log_info("Follower in wrong state: #{wse.inspect}")
70
+ @listeners.delete(session)
71
+ end
55
72
  end
56
73
  end
57
74
  end
@@ -15,7 +15,7 @@ module RhetButler
15
15
  transform_queue.writer.store_log = store_log
16
16
 
17
17
  target_uri = transform_queue.mapping.target_link_for(source_uri)
18
- transform_queue.add_mapping(source_uri, target_uri, target_path)
18
+ transform_queue.add_mapping(nil, source_uri, target_uri, target_path)
19
19
  transform_queue.go
20
20
  end
21
21
  end
@@ -0,0 +1,39 @@
1
+ require 'nokogiri'
2
+
3
+ module RhetButler
4
+ class SlideContents
5
+ class Embed < SlideContents
6
+ register "embed"
7
+ register "embedded"
8
+
9
+ def self.required_config
10
+ %w{source}
11
+ end
12
+
13
+ def self.optional_config
14
+ %w{filters}
15
+ end
16
+
17
+ def positional_options
18
+ %w{source}
19
+ end
20
+
21
+ attr_reader :source
22
+ attr_accessor :filters
23
+
24
+ def configure
25
+ value_from_config("source") do |source|
26
+ @source = source
27
+ end
28
+
29
+ value_from_config("filters") do |value|
30
+ @filters = value
31
+ end
32
+ end
33
+
34
+ def content(file_set)
35
+ "\n" + file_set.contents(source) + "\n"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,40 @@
1
+ require 'rhet-butler/yaml-type'
2
+
3
+ module RhetButler
4
+ class SlideContents < 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-contents/embed'
@@ -1,13 +1,14 @@
1
1
  require 'rhet-butler/yaml-schema'
2
2
  require 'rhet-butler/file-loading'
3
3
  require 'rhet-butler/include-processor'
4
- require 'rhet-butler/slide-processor'
4
+ require 'rhet-butler/slide-rendering'
5
5
  require 'rhet-butler/filter-resolver'
6
6
 
7
7
  module RhetButler
8
8
  class SlideLoader
9
- def initialize(slide_files, configuration)
9
+ def initialize(slide_files, asset_files, configuration)
10
10
  @file_set = slide_files
11
+ @asset_set = asset_files
11
12
  @named_filter_lists = configuration.named_filter_lists
12
13
  @default_content_filters = configuration.default_content_filters
13
14
  @default_note_filters = configuration.default_note_filters
@@ -21,8 +22,8 @@ module RhetButler
21
22
  includer = Includer.new
22
23
  includer.path = @root_slide
23
24
  root_group.slides = [includer]
24
-
25
25
  loading = FileLoading.new(@file_set)
26
+
26
27
  including = IncludeProcessor.new(loading)
27
28
  including.root_group = root_group
28
29
  including.traverse
@@ -34,10 +35,10 @@ module RhetButler
34
35
  filter_resolver.default_note_filters = @default_note_filters
35
36
  filter_resolver.traverse
36
37
 
37
- processor = SlideProcessor.new
38
- processor.root_group = root_group
39
- processor.blueprint = @blueprint
40
- processor.process
38
+ renderer = SlideRendering.new
39
+ renderer.root_group = root_group
40
+ renderer.file_set = @asset_set
41
+ renderer.traverse
41
42
 
42
43
  return root_group
43
44
  end
@@ -2,20 +2,31 @@ require 'rhet-butler/slide-renderer'
2
2
  require 'rhet-butler/slide-traverser'
3
3
  module RhetButler
4
4
  class SlideRendering < SlideTraverser
5
- attr_accessor :root_group
5
+ attr_accessor :root_group, :file_set
6
6
 
7
7
  def setup
8
8
  descend(@root_group, @root_group)
9
9
  end
10
10
 
11
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)
12
+ slide.content = filter_text(slide.raw_content, slide.content_filters)
13
+ slide.notes = filter_text(slide.raw_notes, slide.note_filters)
14
+ raise "Slide content needs to be a string, was: #{slide.content.inspect}" unless String === slide.content
15
+ raise "Slide notes needs to be a string, was: #{slide.notes.inspect}" unless String === slide.notes
14
16
  end
15
17
 
16
- def filter_text(text, filters)
17
- filters.inject(text) do |text, filter|
18
- filter.process(text)
18
+ def filter_text(content, filters)
19
+ case content
20
+ when String
21
+ filters.inject(content) do |text, filter|
22
+ filter.process(text)
23
+ end
24
+ when Array
25
+ content.map{|item| filter_text(item, filters)}.join("")
26
+ when SlideContents
27
+ filter_text(content.content(file_set), content.filters)
28
+ else
29
+ raise "Don't know how to filter slide content like #{content.inspect}"
19
30
  end
20
31
  end
21
32
  end
@@ -8,7 +8,6 @@ module RhetButler
8
8
  def optional_config
9
9
  %w[
10
10
  title html_id html_classes html_class
11
- pos_x pos_y pos_z rot_x rot_y rot_z scale
12
11
  notes filters note_filters
13
12
  ]
14
13
  end
@@ -18,42 +17,11 @@ module RhetButler
18
17
  end
19
18
  end
20
19
 
21
- class Position
22
- def initialize
23
- @x = 0
24
- @y = 0
25
- @z = 0
26
- end
27
-
28
- attr_accessor :x, :y, :z
29
-
30
- def to_attrs
31
- "data-x='#@x' data-y='#@y' data-z='#@z'"
32
- end
33
- end
34
-
35
- class Rotation
36
- def initialize
37
- @x = 0
38
- @y = 0
39
- @z = 0
40
- end
41
-
42
- attr_accessor :x, :y, :z
43
-
44
- def to_attrs
45
- "data-rotate-x='#@x' data-rotate-y='#@y' data-rotate-z='#@z'"
46
- end
47
- end
48
-
49
20
  def setup_defaults
50
21
  @template_name = "slide.html"
51
22
  @html_classes = ["slide"]
52
23
  @html_id = nil
53
- @position = Position.new
54
- @rotation = Rotation.new
55
- @scale = 1.0
56
- @notes = ""
24
+ @raw_notes = ""
57
25
  @type = nil
58
26
  end
59
27
 
@@ -63,8 +31,6 @@ module RhetButler
63
31
  @content = source.content.dup unless source.content.nil?
64
32
  @notes = source.notes.dup unless source.notes.nil?
65
33
  @html_id = source.html_id.dup unless source.html_id.nil?
66
- @position = source.position.dup unless source.position.nil?
67
- @rotation = source.rotation.dup unless source.rotation.nil?
68
34
  @html_classes = source.html_classes.dup unless source.html_classes.nil?
69
35
  end
70
36
 
@@ -76,7 +42,7 @@ module RhetButler
76
42
  when :scalar
77
43
  { 'content' => coder.scalar.to_s }
78
44
  when :seq
79
- warn "Got a sequence for a slide - not sure how to parse that. Skipping"
45
+ { 'content' => coder.seq.to_a }
80
46
  end
81
47
  end
82
48
 
@@ -86,13 +52,11 @@ module RhetButler
86
52
  end
87
53
 
88
54
  value_from_config("content") do |content|
89
- raise "Slide content needs to be a string, was: #{content.inspect}" unless String === content
90
- @content = content
55
+ @raw_content = content
91
56
  end
92
57
 
93
58
  value_from_config("notes") do |notes|
94
- raise "Slide notes needs to be a string, was: #{notes.inspect}" unless String === notes
95
- @notes = notes
59
+ @raw_notes = notes
96
60
  end
97
61
 
98
62
  value_from_config("html_id") do |value|
@@ -107,30 +71,6 @@ module RhetButler
107
71
  @html_classes << value
108
72
  end
109
73
 
110
- value_from_config("pos_x") do |value|
111
- @position.x = value
112
- end
113
- value_from_config("pos_y") do |value|
114
- @position.y = value
115
- end
116
- value_from_config("pos_z") do |value|
117
- @position.z = value
118
- end
119
-
120
- value_from_config("rot_x") do |value|
121
- @rotation.x = value
122
- end
123
- value_from_config("rot_y") do |value|
124
- @rotation.y = value
125
- end
126
- value_from_config("rot_z") do |value|
127
- @rotation.z = value
128
- end
129
-
130
- value_from_config("scale") do |value|
131
- @scale = value
132
- end
133
-
134
74
  value_from_config("filters") do |value|
135
75
  @content_filters = value
136
76
  @html_classes += [*value].map do |filter|
@@ -147,13 +87,14 @@ module RhetButler
147
87
  end
148
88
 
149
89
  attr_reader :config_hash
150
- attr_accessor :content, :html_classes, :html_id, :notes
151
- attr_accessor :position, :rotation, :content_filters, :note_filters
152
- attr_accessor :scale
90
+ attr_accessor :raw_content, :raw_notes
91
+ attr_accessor :content, :notes
92
+ attr_accessor :html_classes, :html_id
93
+ attr_accessor :content_filters, :note_filters
153
94
  attr_reader :template_name
154
95
 
155
96
  def to_s
156
- "Slide: #{content[0..20]}"
97
+ "Slide: #{content.nil? ? "R:#{raw_content[0..20]}" : content[0..20]}"
157
98
  end
158
99
 
159
100
  def id_attr
@@ -167,15 +108,5 @@ module RhetButler
167
108
  def classes
168
109
  @html_classes.join(" ")
169
110
  end
170
-
171
- def impress_attrs
172
- attrs = []
173
-
174
- attrs << @position.to_attrs
175
- attrs << @rotation.to_attrs
176
- attrs << "data-scale='#{"%0.2f" % scale}'"
177
-
178
- attrs.join(" ")
179
- end
180
111
  end
181
112
  end