parade 0.10.1 → 0.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/README.md +187 -120
- data/lib/parade/commands/html_output.rb +1 -1
- data/lib/parade/parsers/dsl.rb +29 -0
- data/lib/parade/parsers/presentation_file_parser.rb +3 -9
- data/lib/parade/renderers/columns_renderer.rb +29 -11
- data/lib/parade/renderers/content_with_caption_renderer.rb +87 -0
- data/lib/parade/section.rb +9 -0
- data/lib/parade/server.rb +5 -1
- data/lib/parade/slide.rb +6 -1
- data/lib/parade/slide_post_renderers.rb +3 -0
- data/lib/parade/version.rb +1 -1
- data/lib/public/css/themes/default.css +0 -1
- data/lib/public/css/themes/hayfield.css +58 -0
- data/lib/public/css/themes/minimal.css +144 -0
- data/lib/public/js/parade-command-input.js +3 -0
- data/lib/public/js/parade-keyboard-input.js +0 -4
- data/lib/public/js/parade.js +0 -12
- data/lib/views/footer.erb +0 -1
- data/lib/views/help.erb +0 -1
- data/lib/views/not_found.erb +21 -0
- data/lib/views/print.erb +5 -0
- metadata +51 -50
- data/lib/parade/parsers/json_file_parser.rb +0 -67
- data/lib/public/css/jquery-ui/images/ui-bg_diagonals-small_100_f0efea_40x40.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-bg_flat_35_f0f0f0_40x100.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-bg_glass_55_fcf0ba_1x400.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-bg_glow-ball_25_2e2e28_600x600.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-bg_highlight-soft_100_f0efea_1x100.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-bg_highlight-soft_25_327E04_1x100.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-bg_highlight-soft_25_5A9D1A_1x100.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-bg_highlight-soft_95_ffedad_1x100.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-bg_inset-soft_22_3b3b35_1x100.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-icons_808080_256x240.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-icons_8DC262_256x240.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-icons_e7e6e4_256x240.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-icons_eeeeee_256x240.png +0 -0
- data/lib/public/css/jquery-ui/images/ui-icons_ffffff_256x240.png +0 -0
- data/lib/public/css/spinner_bar.gif +0 -0
@@ -26,7 +26,7 @@ module Parade
|
|
26
26
|
if File.directory? filepath
|
27
27
|
root_path = filepath
|
28
28
|
root_node = Parsers::PresentationDirectoryParser.parse filepath, :root_path => ".",
|
29
|
-
:parade_file => (Array(options['parade_file']) + [ "parade"
|
29
|
+
:parade_file => (Array(options['parade_file']) + [ "parade" ]).compact.uniq
|
30
30
|
else
|
31
31
|
root_path = File.dirname filepath
|
32
32
|
root_node = Parsers::PresentationFileParser.parse filepath, :root_path => root_path
|
data/lib/parade/parsers/dsl.rb
CHANGED
@@ -86,6 +86,34 @@ module Parade
|
|
86
86
|
current_section.add_template template_name, File.join(options[:current_path], template_file)
|
87
87
|
end
|
88
88
|
|
89
|
+
#
|
90
|
+
# This is used by the DSL to specify any additional CSS Classes specific
|
91
|
+
# to the section. All slides within the section will receive these
|
92
|
+
# additional CSS Classes when the slide is rendered
|
93
|
+
#
|
94
|
+
# @example Specifying the css classes in multiple different ways
|
95
|
+
#
|
96
|
+
# section "Iteration 0" do
|
97
|
+
# css_classes "blue-background"
|
98
|
+
# slides "iteration-zero.md"
|
99
|
+
# end
|
100
|
+
# section "Iteration 1" do
|
101
|
+
# css_classes [ "blue-background" ]
|
102
|
+
# slides "iteration-zero.md"
|
103
|
+
# end
|
104
|
+
# section "Iteration WonderWoman" do
|
105
|
+
# css_classes "blue-background", "red-font", "white-borders"
|
106
|
+
# slides "iteration-zero.md"
|
107
|
+
# end
|
108
|
+
# section "Iteration Spiderman" do
|
109
|
+
# css_classes "blue-background red-spandex web-spitters"
|
110
|
+
# slides "iteration-zero.md"
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
def css_classes(*css_classes)
|
114
|
+
current_section.css_classes = css_classes.flatten.map { |css_class| css_class.split(" ") }.flatten
|
115
|
+
end
|
116
|
+
|
89
117
|
#
|
90
118
|
# This is used by the DSL to specify the resources used by the presentation
|
91
119
|
#
|
@@ -93,6 +121,7 @@ module Parade
|
|
93
121
|
current_section.add_resource File.join(options[:current_path], resource_filepath)
|
94
122
|
end
|
95
123
|
|
124
|
+
|
96
125
|
#
|
97
126
|
# Sets the current sections theme to the specified theme
|
98
127
|
# @note this will only work at the top level section of the presentation
|
@@ -1,24 +1,18 @@
|
|
1
1
|
require_relative 'dsl_file_parser'
|
2
|
-
require_relative 'json_file_parser'
|
3
2
|
|
4
3
|
module Parade
|
5
4
|
module Parsers
|
6
|
-
|
5
|
+
|
7
6
|
#
|
8
7
|
# The Presentation File Parser allows for the JSON formatted file or the
|
9
8
|
# DSL formatted files. The determination of which to use is solely based
|
10
9
|
# on the file extension.
|
11
|
-
#
|
10
|
+
#
|
12
11
|
class PresentationFileParser
|
13
12
|
|
14
13
|
def self.parse(filepath,options = {})
|
15
14
|
options = options.merge(:current_path => File.dirname(filepath))
|
16
|
-
|
17
|
-
if File.extname(filepath) == ".json"
|
18
|
-
JsonFileParser.parse(filepath,options)
|
19
|
-
else
|
20
|
-
DslFileParser.parse(filepath,options)
|
21
|
-
end
|
15
|
+
DslFileParser.parse(filepath,options)
|
22
16
|
end
|
23
17
|
|
24
18
|
end
|
@@ -26,40 +26,58 @@ module Parade
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def render(content)
|
29
|
-
|
30
29
|
html = Nokogiri::XML.fragment(content)
|
31
|
-
html.css(".content.#{css_class}").each do |slide|
|
32
30
|
|
33
|
-
|
34
|
-
|
31
|
+
#for each element with the class 'content.css_class'
|
32
|
+
html.css(".content.#{css_class}").each do |slide|
|
35
33
|
|
36
|
-
|
34
|
+
#chunk and mark nods that are html_element as columns
|
35
|
+
chunks = chunk_children_by_element(slide, html_element)
|
37
36
|
|
37
|
+
#remove the current children
|
38
38
|
slide.children = ""
|
39
39
|
|
40
|
+
#append the container grid count..size.. thing
|
40
41
|
slide['class'] += " container_#{segments}"
|
41
42
|
current_column = slide
|
42
43
|
|
43
|
-
|
44
|
+
#get the number of elements that are html_element
|
45
|
+
column_count = chunks.find_all {|is_column, contents| is_column }.count
|
44
46
|
|
45
47
|
chunks.each do |is_column,contents|
|
46
48
|
|
47
49
|
if is_column
|
48
|
-
|
49
|
-
current_column = Nokogiri::XML::Node.new('div',html)
|
50
|
-
current_column['class'] = "grid_#{ segments / column_count }"
|
50
|
+
current_column = new_column_div(html, column_count)
|
51
51
|
end
|
52
52
|
|
53
53
|
contents.each {|content| current_column.add_child content }
|
54
|
-
|
54
|
+
slide.add_child current_column unless current_column == slide
|
55
55
|
|
56
|
-
|
56
|
+
end
|
57
57
|
|
58
58
|
end
|
59
59
|
|
60
60
|
html.to_s
|
61
61
|
|
62
62
|
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def chunk_children_by_element slide, html_element
|
67
|
+
chunks = slide.children.chunk {|child| child.name == html_element }
|
68
|
+
end
|
69
|
+
|
70
|
+
def new_column_div(html, column_count)
|
71
|
+
column = Nokogiri::XML::Node.new('div',html)
|
72
|
+
column['class'] = grid_class(column_count)
|
73
|
+
|
74
|
+
column
|
75
|
+
end
|
76
|
+
|
77
|
+
def grid_class column_count
|
78
|
+
"grid_#{ segments / column_count }"
|
79
|
+
end
|
80
|
+
|
63
81
|
end
|
64
82
|
|
65
83
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Parade
|
2
|
+
module Renderers
|
3
|
+
|
4
|
+
#
|
5
|
+
# With the given HTML content, search for the CSS class for the HTML element
|
6
|
+
# and when found the first of the elements will be contained in a smaller
|
7
|
+
# column on the left and the remaining elements will be contained in
|
8
|
+
# a larger container on the right.
|
9
|
+
#
|
10
|
+
class ContentWithCaptionRenderer
|
11
|
+
|
12
|
+
attr_accessor :css_class
|
13
|
+
attr_accessor :html_element
|
14
|
+
#attr_accessor :segments
|
15
|
+
|
16
|
+
#
|
17
|
+
# @example Creating a ContentWithCaptionRenderer
|
18
|
+
#
|
19
|
+
# Creation of a column renderer that will look for slides with the class
|
20
|
+
# 'content-with-caption', and create a smaller column with the first of
|
21
|
+
# the h2 elements on the left and a larger column on the right that
|
22
|
+
# contains all remaining h2 elements
|
23
|
+
#
|
24
|
+
# ContentWithCaptionElement.new(:css_class => 'content-with-caption',:html_element => "h2",:segments => 12)
|
25
|
+
#
|
26
|
+
def initialize(params={})
|
27
|
+
params.each {|k,v| send("#{k}=",v) if respond_to? "#{k}=" }
|
28
|
+
end
|
29
|
+
|
30
|
+
def render(content)
|
31
|
+
html = Nokogiri::XML.fragment(content)
|
32
|
+
|
33
|
+
html.css(".content.#{css_class}").each do |slide|
|
34
|
+
|
35
|
+
chunks = chunk_children_by_element(slide, html_element)
|
36
|
+
|
37
|
+
slide.children = ""
|
38
|
+
|
39
|
+
slide['class'] += " columns container_12"
|
40
|
+
current_column = slide
|
41
|
+
is_first_h2 = true
|
42
|
+
is_second_h2 = true
|
43
|
+
|
44
|
+
column_count = chunks.find_all {|is_column, contents| is_column }.count
|
45
|
+
|
46
|
+
chunks.each do |is_column,contents|
|
47
|
+
|
48
|
+
if is_column && is_first_h2
|
49
|
+
current_column = new_column_div(html, 4)
|
50
|
+
is_first_h2 = false
|
51
|
+
elsif is_column && is_second_h2
|
52
|
+
current_column = new_column_div(html, 8)
|
53
|
+
is_second_h2 = false
|
54
|
+
end
|
55
|
+
|
56
|
+
contents.each {|content| current_column.add_child content }
|
57
|
+
slide.add_child current_column unless current_column == slide
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
html.to_s
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def chunk_children_by_element slide, html_element
|
70
|
+
chunks = slide.children.chunk {|child| child.name == html_element }
|
71
|
+
end
|
72
|
+
|
73
|
+
def new_column_div(html, column_span)
|
74
|
+
column = Nokogiri::XML::Node.new('div',html)
|
75
|
+
column['class'] = grid_class(column_span)
|
76
|
+
|
77
|
+
column
|
78
|
+
end
|
79
|
+
|
80
|
+
def grid_class column_span
|
81
|
+
"grid_#{ column_span}"
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
data/lib/parade/section.rb
CHANGED
@@ -44,6 +44,15 @@ module Parade
|
|
44
44
|
# root section.
|
45
45
|
attr_accessor :section
|
46
46
|
|
47
|
+
# Set the additional css classes that will be applied to all the slides
|
48
|
+
# within the section.
|
49
|
+
attr_writer :css_classes
|
50
|
+
|
51
|
+
# @return [Array<String>] returns an array of css classes names
|
52
|
+
def css_classes
|
53
|
+
@css_classes || []
|
54
|
+
end
|
55
|
+
|
47
56
|
#
|
48
57
|
# Append sections to this section.
|
49
58
|
#
|
data/lib/parade/server.rb
CHANGED
@@ -27,7 +27,7 @@ module Parade
|
|
27
27
|
end
|
28
28
|
|
29
29
|
set :presentation_file, 'parade'
|
30
|
-
set :default_presentation_files, [ 'parade'
|
30
|
+
set :default_presentation_files, [ 'parade' ]
|
31
31
|
|
32
32
|
|
33
33
|
#
|
@@ -220,6 +220,10 @@ module Parade
|
|
220
220
|
erb :print
|
221
221
|
end
|
222
222
|
|
223
|
+
not_found do
|
224
|
+
erb :not_found
|
225
|
+
end
|
226
|
+
|
223
227
|
end
|
224
228
|
|
225
229
|
end
|
data/lib/parade/slide.rb
CHANGED
@@ -70,7 +70,7 @@ module Parade
|
|
70
70
|
|
71
71
|
# @return [String] the CSS classes for the slide
|
72
72
|
def slide_classes
|
73
|
-
[ title.downcase.gsub(' ','-') ] + content_classes
|
73
|
+
[ title.downcase.gsub(' ','-') ] + section_classes + content_classes
|
74
74
|
end
|
75
75
|
|
76
76
|
# @return [String] the CSS classes for the content section of the slide
|
@@ -78,6 +78,11 @@ module Parade
|
|
78
78
|
metadata.classes
|
79
79
|
end
|
80
80
|
|
81
|
+
# @return [String] the CSS classes specifed at the section level
|
82
|
+
def section_classes
|
83
|
+
section.css_classes
|
84
|
+
end
|
85
|
+
|
81
86
|
# @return [String] the transition style for the slide
|
82
87
|
def transition
|
83
88
|
metadata.transition || "none"
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require_relative 'renderers/command_line_renderer'
|
2
2
|
require_relative 'renderers/special_paragraph_renderer'
|
3
3
|
require_relative 'renderers/columns_renderer'
|
4
|
+
require_relative 'renderers/content_with_caption_renderer'
|
4
5
|
|
5
6
|
module Parade
|
6
7
|
|
@@ -22,5 +23,7 @@ module Parade
|
|
22
23
|
html_element: "h2", segments: 12)
|
23
24
|
SlidePostRenderers.register Renderers::ColumnsRenderer.new(css_class: 'comparison',
|
24
25
|
html_element: "h2", segments: 12)
|
26
|
+
SlidePostRenderers.register Renderers::ContentWithCaptionRenderer.new(css_class: 'content-with-caption',
|
27
|
+
html_element: "h2")
|
25
28
|
|
26
29
|
end
|
data/lib/parade/version.rb
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
/* customr css and js files included at the top level of your presentation will
|
2
|
+
* will be included in your presentation */
|
3
|
+
|
4
|
+
body {
|
5
|
+
box-sizing: border-box;
|
6
|
+
color: #2f5d2f;
|
7
|
+
background: #489060;
|
8
|
+
font-size: 16px;
|
9
|
+
font-family: Helvetica, Arial, sans-serif;
|
10
|
+
line-height: 1.5;
|
11
|
+
-webkit-font-smoothing: antialiased;
|
12
|
+
}
|
13
|
+
|
14
|
+
|
15
|
+
h1{
|
16
|
+
color: #183018;
|
17
|
+
font-family: 'Lucida Console', Tahoma, fantasy;
|
18
|
+
font-weight: bold;
|
19
|
+
background: #A8C060;
|
20
|
+
}
|
21
|
+
|
22
|
+
h2{
|
23
|
+
color: #183018;
|
24
|
+
font-family: 'Lucida Console', Tahoma, fantasy;
|
25
|
+
border-bottom: 1px dotted #183018;
|
26
|
+
}
|
27
|
+
|
28
|
+
a{
|
29
|
+
color: #F5582F;
|
30
|
+
}
|
31
|
+
|
32
|
+
a:hover {
|
33
|
+
color: #FF0033;
|
34
|
+
}
|
35
|
+
|
36
|
+
.slide {
|
37
|
+
background-color: #F7F794;
|
38
|
+
}
|
39
|
+
|
40
|
+
#footer {
|
41
|
+
background: #183018;
|
42
|
+
color: #b5e853;
|
43
|
+
}
|
44
|
+
|
45
|
+
blockquote {
|
46
|
+
background-color: #D8D878;
|
47
|
+
color: #376e49;
|
48
|
+
border-left: 4px solid #489060;
|
49
|
+
}
|
50
|
+
|
51
|
+
.highlight.text,
|
52
|
+
.highlight.ruby,
|
53
|
+
.highlight.javascript,
|
54
|
+
.highlight.shell,
|
55
|
+
.highlight.shell pre.command,
|
56
|
+
.highlight.shell pre.result {
|
57
|
+
background-color: #fdfde3;
|
58
|
+
}
|
@@ -0,0 +1,144 @@
|
|
1
|
+
body {
|
2
|
+
font-size: 100%;
|
3
|
+
font-family: Helvetica, Arial, sans-serif;
|
4
|
+
background: #333;
|
5
|
+
overflow:hidden;
|
6
|
+
margin:0;
|
7
|
+
padding:0;
|
8
|
+
}
|
9
|
+
|
10
|
+
h1,h2,h3 { font-weight: bold; letter-spacing: -0.05em; text-align: center; }
|
11
|
+
h1 { font-size: 5em; }
|
12
|
+
h2 { font-size: 2.5em; }
|
13
|
+
h3 { font-size: 2em; }
|
14
|
+
|
15
|
+
pre {
|
16
|
+
margin: 1em 40px;
|
17
|
+
padding: .25em;
|
18
|
+
}
|
19
|
+
|
20
|
+
pre, pre.highlight, pre.highlight pre {
|
21
|
+
background-color: #eee;
|
22
|
+
font-size: 20px;
|
23
|
+
line-height: 26px;
|
24
|
+
overflow: auto;
|
25
|
+
border-radius: 3px;
|
26
|
+
-moz-border-radius: 3px;
|
27
|
+
-webkit-border-radius: 3px;
|
28
|
+
padding: 6px 10px;
|
29
|
+
}
|
30
|
+
|
31
|
+
|
32
|
+
a, a code {
|
33
|
+
color: #4183C4;
|
34
|
+
text-decoration: none;
|
35
|
+
}
|
36
|
+
|
37
|
+
blockquote {
|
38
|
+
border-left: 4px solid #ddd;
|
39
|
+
color: black;
|
40
|
+
font-style: oblique;
|
41
|
+
padding-left: 11px;
|
42
|
+
margin: 14px 0;
|
43
|
+
}
|
44
|
+
|
45
|
+
.content > blockquote {
|
46
|
+
font-size: 200%;
|
47
|
+
margin: 2em;
|
48
|
+
}
|
49
|
+
|
50
|
+
.content > p {
|
51
|
+
font-size: 2em;
|
52
|
+
line-height: 1.25em;
|
53
|
+
}
|
54
|
+
|
55
|
+
.bullets > ul > li {
|
56
|
+
font-size: .75em;
|
57
|
+
padding: .25em;
|
58
|
+
text-align: left;
|
59
|
+
margin-left: 10%;
|
60
|
+
list-style-type: disc;
|
61
|
+
}
|
62
|
+
|
63
|
+
.smbullets > ul > li {
|
64
|
+
font-size: .70em;
|
65
|
+
padding: .10em;
|
66
|
+
text-align: left;
|
67
|
+
margin-left: 10%;
|
68
|
+
list-style-type: disc;
|
69
|
+
}
|
70
|
+
|
71
|
+
#preso, .slide {
|
72
|
+
background: #fff;
|
73
|
+
width: 1024px;
|
74
|
+
height: 768px;
|
75
|
+
margin-left:auto;
|
76
|
+
margin-right:auto;
|
77
|
+
overflow:hidden;
|
78
|
+
-webkit-box-shadow:0 0 25px rgba(0,0,0,0.35);
|
79
|
+
-moz-box-shadow:0 0 25px rgba(0,0,0,0.35);
|
80
|
+
box-shadow:0 0 25px rgba(0,0,0,0.35);
|
81
|
+
}
|
82
|
+
|
83
|
+
#footer {
|
84
|
+
background: rgba(221,221,221,0.75);
|
85
|
+
color:#333;
|
86
|
+
padding: 2px 5px;
|
87
|
+
width: 1014px;
|
88
|
+
height: 20px;
|
89
|
+
line-height:20px;
|
90
|
+
font-size:14px;
|
91
|
+
position:relative;
|
92
|
+
top:-24px;
|
93
|
+
margin:0 auto;
|
94
|
+
-webkit-border-top-left-radius: 3px;
|
95
|
+
-webkit-border-top-right-radius: 3px;
|
96
|
+
-moz-border-radius-topleft: 3px;
|
97
|
+
-moz-border-radius-topright: 3px;
|
98
|
+
border-top-left-radius: 3px;
|
99
|
+
border-top-right-radius: 3px;
|
100
|
+
z-index: 2147483647;
|
101
|
+
}
|
102
|
+
|
103
|
+
#pauseScreen {
|
104
|
+
background: rgba(0, 0, 0, 0.85);
|
105
|
+
width: 100%;
|
106
|
+
height: 100%;
|
107
|
+
position: absolute;
|
108
|
+
top: 0px;
|
109
|
+
left: 0px;
|
110
|
+
display: none;
|
111
|
+
margin: auto;
|
112
|
+
color: white;
|
113
|
+
font-size: 2em;
|
114
|
+
padding: 1em;
|
115
|
+
z-index: 2147483647;
|
116
|
+
text-align: center;
|
117
|
+
}
|
118
|
+
|
119
|
+
#debugInfo { margin-left: 30px; }
|
120
|
+
|
121
|
+
#help {
|
122
|
+
background: #9f9;
|
123
|
+
position: absolute;
|
124
|
+
right: 80px;
|
125
|
+
display: none;
|
126
|
+
z-index: 2147483647;
|
127
|
+
}
|
128
|
+
|
129
|
+
#help table tr td.key {
|
130
|
+
text-align: right;
|
131
|
+
border-right: 2px solid #8b8;
|
132
|
+
padding-right: 4px;
|
133
|
+
font-weight: bold;
|
134
|
+
}
|
135
|
+
|
136
|
+
.content.columns h2, .content.comparison h2 {
|
137
|
+
padding-bottom: 10px;
|
138
|
+
border-bottom: 2px solid black;
|
139
|
+
}
|
140
|
+
|
141
|
+
.notes { display: none }
|
142
|
+
.hidden { position:absolute; top:0; left:-9999px; width:1px; height:1px; overflow:hidden; }
|
143
|
+
.offscreen { position:absolute; top:0; left:-9999px; overflow:hidden; }
|
144
|
+
.buttonNav { display: none }
|