parade 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/LICENSE +21 -0
  2. data/README.md +542 -0
  3. data/Rakefile +15 -0
  4. data/bin/parade +138 -0
  5. data/lib/parade.rb +43 -0
  6. data/lib/parade/commands/commands.rb +84 -0
  7. data/lib/parade/commands/generate_outline.rb +34 -0
  8. data/lib/parade/commands/generate_presentation.rb +34 -0
  9. data/lib/parade/commands/generate_rackup.rb +32 -0
  10. data/lib/parade/commands/html_output.rb +47 -0
  11. data/lib/parade/commands/render_from_template.rb +50 -0
  12. data/lib/parade/commands/static_html.rb +38 -0
  13. data/lib/parade/commands/static_pdf.rb +39 -0
  14. data/lib/parade/commands/unknown.rb +23 -0
  15. data/lib/parade/features/live_ruby.rb +18 -0
  16. data/lib/parade/features/pdf_presentation.rb +24 -0
  17. data/lib/parade/features/preshow.rb +11 -0
  18. data/lib/parade/helpers/encode_image.rb +24 -0
  19. data/lib/parade/helpers/template_generator.rb +130 -0
  20. data/lib/parade/metadata.rb +73 -0
  21. data/lib/parade/metadata/assignment.rb +38 -0
  22. data/lib/parade/metadata/css_classes.rb +22 -0
  23. data/lib/parade/metadata/html_id.rb +35 -0
  24. data/lib/parade/metadata/template.rb +31 -0
  25. data/lib/parade/parsers/dsl.rb +138 -0
  26. data/lib/parade/parsers/dsl_file_parser.rb +17 -0
  27. data/lib/parade/parsers/json_file_parser.rb +67 -0
  28. data/lib/parade/parsers/markdown_image_paths.rb +44 -0
  29. data/lib/parade/parsers/markdown_slide_splitter.rb +63 -0
  30. data/lib/parade/parsers/presentation_directory_parser.rb +36 -0
  31. data/lib/parade/parsers/presentation_file_parser.rb +27 -0
  32. data/lib/parade/parsers/presentation_filepath_parser.rb +35 -0
  33. data/lib/parade/parsers/slides_file_content_parser.rb +27 -0
  34. data/lib/parade/renderers/columns_renderer.rb +68 -0
  35. data/lib/parade/renderers/command_line_renderer.rb +142 -0
  36. data/lib/parade/renderers/html_with_pygments.rb +42 -0
  37. data/lib/parade/renderers/inline_images.rb +31 -0
  38. data/lib/parade/renderers/special_paragraph_renderer.rb +23 -0
  39. data/lib/parade/renderers/update_image_paths.rb +75 -0
  40. data/lib/parade/section.rb +183 -0
  41. data/lib/parade/server.rb +139 -0
  42. data/lib/parade/slide.rb +128 -0
  43. data/lib/parade/version.rb +3 -0
  44. data/lib/public/css/960.css +653 -0
  45. data/lib/public/css/fg.menu.css +114 -0
  46. data/lib/public/css/ghf_marked.css +180 -0
  47. data/lib/public/css/jquery-terminal.css +73 -0
  48. data/lib/public/css/onepage.css +62 -0
  49. data/lib/public/css/parade.css +450 -0
  50. data/lib/public/css/pdf.css +13 -0
  51. data/lib/public/css/reset.css +53 -0
  52. data/lib/public/css/spinner_bar.gif +0 -0
  53. data/lib/public/css/theme/images/ui-bg_diagonals-small_100_f0efea_40x40.png +0 -0
  54. data/lib/public/css/theme/images/ui-bg_flat_35_f0f0f0_40x100.png +0 -0
  55. data/lib/public/css/theme/images/ui-bg_glass_55_fcf0ba_1x400.png +0 -0
  56. data/lib/public/css/theme/images/ui-bg_glow-ball_25_2e2e28_600x600.png +0 -0
  57. data/lib/public/css/theme/images/ui-bg_highlight-soft_100_f0efea_1x100.png +0 -0
  58. data/lib/public/css/theme/images/ui-bg_highlight-soft_25_327E04_1x100.png +0 -0
  59. data/lib/public/css/theme/images/ui-bg_highlight-soft_25_5A9D1A_1x100.png +0 -0
  60. data/lib/public/css/theme/images/ui-bg_highlight-soft_95_ffedad_1x100.png +0 -0
  61. data/lib/public/css/theme/images/ui-bg_inset-soft_22_3b3b35_1x100.png +0 -0
  62. data/lib/public/css/theme/images/ui-icons_808080_256x240.png +0 -0
  63. data/lib/public/css/theme/images/ui-icons_8DC262_256x240.png +0 -0
  64. data/lib/public/css/theme/images/ui-icons_cd0a0a_256x240.png +0 -0
  65. data/lib/public/css/theme/images/ui-icons_e7e6e4_256x240.png +0 -0
  66. data/lib/public/css/theme/images/ui-icons_eeeeee_256x240.png +0 -0
  67. data/lib/public/css/theme/images/ui-icons_ffffff_256x240.png +0 -0
  68. data/lib/public/css/theme/ui.accordion.css +9 -0
  69. data/lib/public/css/theme/ui.all.css +2 -0
  70. data/lib/public/css/theme/ui.base.css +9 -0
  71. data/lib/public/css/theme/ui.core.css +37 -0
  72. data/lib/public/css/theme/ui.datepicker.css +62 -0
  73. data/lib/public/css/theme/ui.dialog.css +13 -0
  74. data/lib/public/css/theme/ui.progressbar.css +4 -0
  75. data/lib/public/css/theme/ui.resizable.css +13 -0
  76. data/lib/public/css/theme/ui.slider.css +17 -0
  77. data/lib/public/css/theme/ui.tabs.css +9 -0
  78. data/lib/public/css/theme/ui.theme.css +245 -0
  79. data/lib/public/favicon.ico +0 -0
  80. data/lib/public/js/coffee-script.js +8 -0
  81. data/lib/public/js/fg.menu.js +645 -0
  82. data/lib/public/js/jTypeWriter.js +26 -0
  83. data/lib/public/js/jquery-1.4.2.js +6240 -0
  84. data/lib/public/js/jquery-print.js +109 -0
  85. data/lib/public/js/jquery-pubsub.js +27 -0
  86. data/lib/public/js/jquery-terminal.js +2712 -0
  87. data/lib/public/js/jquery.batchImageLoad.js +56 -0
  88. data/lib/public/js/jquery.cycle.all.js +1284 -0
  89. data/lib/public/js/keyboard.js +733 -0
  90. data/lib/public/js/parade-code-execution.js +122 -0
  91. data/lib/public/js/parade-command-input.js +16 -0
  92. data/lib/public/js/parade-command-visor.js +92 -0
  93. data/lib/public/js/parade-keyboard-input.js +54 -0
  94. data/lib/public/js/parade.js +675 -0
  95. data/lib/public/js/spine.js +904 -0
  96. data/lib/templates/config.ru.erb +4 -0
  97. data/lib/templates/showoff.erb +27 -0
  98. data/lib/templates/slides.md.erb +25 -0
  99. data/lib/views/header.erb +73 -0
  100. data/lib/views/index.erb +53 -0
  101. data/lib/views/inline_css.erb +3 -0
  102. data/lib/views/inline_js.erb +3 -0
  103. data/lib/views/onepage.erb +17 -0
  104. data/lib/views/pdf.erb +17 -0
  105. data/lib/views/slide.erb +5 -0
  106. metadata +317 -0
@@ -0,0 +1,38 @@
1
+ require_relative 'html_output'
2
+
3
+ module Parade
4
+ module Commands
5
+
6
+ #
7
+ # Saves an html representation of the presentation to a single HTML file.
8
+ #
9
+ # @see HtmlOutput
10
+ #
11
+ class StaticHtml
12
+ include RenderFromTemplate
13
+
14
+ def description
15
+ "Output into a single HTML file"
16
+ end
17
+
18
+ def generate(options)
19
+ options.merge!('template' => 'onepage')
20
+
21
+ html_generator = HtmlOutput.new
22
+ html_content = html_generator.generate(options)
23
+
24
+ output_file = options[:output] || default_html_output
25
+
26
+ if create_file_with_contents output_file, html_content, options
27
+ puts "Saved HTML to #{output_file}"
28
+ end
29
+ end
30
+
31
+ def default_html_output
32
+ "presentation.html"
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,39 @@
1
+ require_relative 'html_output'
2
+
3
+ module Parade
4
+ module Commands
5
+
6
+ #
7
+ # Saves a PDF version of the presentation that is from the HtmlOutput
8
+ #
9
+ class StaticPdf
10
+
11
+ def description
12
+ "Output into a PDF format"
13
+ end
14
+
15
+ def generate(options)
16
+ options.merge!('template' => 'pdf')
17
+
18
+ html_generator = HtmlOutput.new
19
+ html_content = html_generator.generate(options)
20
+
21
+ kit = PDFKit.new(html_content,:page_size => 'Letter', :orientation => 'Landscape')
22
+
23
+ output_file = options[:output] || default_pdf_output
24
+
25
+ return if (File.exists?(output_file) and not options.key?(:force))
26
+
27
+ kit.to_file(output_file)
28
+
29
+ puts "Saved PDF to #{output_file}"
30
+ end
31
+
32
+ def default_pdf_output
33
+ "presentation.pdf"
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module Parade
3
+ module Commands
4
+
5
+ #
6
+ # The Unknown Command is provided as the default for the command lists
7
+ # as a default to ensure that a nil is not returned, allowing a for
8
+ # an object that adheres to the generate method.
9
+ #
10
+ class Unknown
11
+
12
+ def description
13
+ "Could not find the command specified"
14
+ end
15
+
16
+ def generate(options)
17
+ puts description
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ module Parade
2
+
3
+ module LiveRuby
4
+
5
+ def self.included(server)
6
+ server.get '/eval_ruby' do
7
+ eval_ruby(params[:code])
8
+ end
9
+ end
10
+
11
+ def eval_ruby(code)
12
+ eval(code).to_s
13
+ rescue => exception
14
+ exception.message
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,24 @@
1
+ module Parade
2
+ module PDFPresentation
3
+ def self.included(server)
4
+
5
+ server.get '/pdf' do
6
+
7
+ # TODO: Find the presentation file and/or regenerate it every time
8
+
9
+ template_options = { 'erb_template_file' => File.join(File.dirname(__FILE__), "..", "..", "views", "pdf.erb"),
10
+ 'custom_asset_path' => settings.presentation_directory,
11
+ 'slides' => slides }
12
+
13
+ html_content = TemplateGenerator.new(template_options).render
14
+
15
+ # TODO the image references here are not full filepaths. creating issues
16
+
17
+ kit = PDFKit.new(html_content,:page_size => 'Letter', :orientation => 'Landscape')
18
+
19
+ send_file kit.to_file('presentation.pdf')
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ module Parade
2
+ module Preshow
3
+ def self.included(server)
4
+
5
+ server.get "/preshow" do
6
+ Dir.glob("#{settings.presentation_directory}/preshow/*").map { |path| File.basename(path) }.to_json
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ require 'base64'
2
+
3
+ module Parade
4
+ module Helpers
5
+
6
+ module EncodeImage
7
+
8
+ def image_path_to_base64
9
+ $stderr.puts "Please install `rmagick` to allow images to be included in content"
10
+ ''
11
+ end
12
+
13
+ if defined?(Magick)
14
+ def image_path_to_base64(path)
15
+ magick_image = Magick::Image.read(path).first
16
+ data = Base64.encode64(magick_image.to_blob).gsub("\n",'').strip
17
+ "data:image/#{magick_image.format};base64,#{data}"
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,130 @@
1
+ require 'ostruct'
2
+
3
+ module Parade
4
+
5
+ #
6
+ # TemplateGenator uses ERB to generate a template and uses itself as the
7
+ # reference as the binding. This template generator is being used primarily
8
+ # as a way to generate static versions of the content in HTML.
9
+ #
10
+ # When created an :erb_template_file needs to be specified in the Hash, all
11
+ # other fields are dependent on what is contained within the template itself
12
+ #
13
+ class TemplateGenerator < OpenStruct
14
+
15
+ #
16
+ # @param [String] filepath the filepath to load
17
+ #
18
+ def css_template(filepath)
19
+ CSSTemplateGenerator.new :filepath => filepath
20
+ end
21
+
22
+ def js_template(filepath)
23
+ JSTemplateGenerator.new :filepath => filepath
24
+ end
25
+
26
+ #
27
+ # Return javascript to be inlined in a template
28
+ #
29
+ # @param [String] filepath the filepath to the javascript file
30
+ # @return [String] HTML content that is inlined javascript data
31
+ def js(filepath)
32
+ js_template(filepath).render
33
+ end
34
+
35
+ #
36
+ # Return stylesheet to be inlined in a template
37
+ #
38
+ # @param [String] filepath the filepath to the stylesheet file
39
+ # @return [String] HTML content that is inlined stylesheet data
40
+ #
41
+ def css(filepath)
42
+ css_template(filepath).render
43
+ end
44
+
45
+ def custom_css_files
46
+ if custom_asset_path
47
+ Dir.glob("#{custom_asset_path}**/*.css").map do |path|
48
+ css_template(path).render
49
+ end.join("\n")
50
+ end
51
+ end
52
+
53
+ def custom_js_files
54
+ if custom_asset_path
55
+ Dir.glob("#{custom_asset_path}**/*.js").map do |path|
56
+ js_template(path).render
57
+ end.join("\n")
58
+ end
59
+ end
60
+
61
+ #
62
+ # To provide support of having references to other templates, this will
63
+ # handle erb method calls and in-line that template's content
64
+ #
65
+ # @param [Strign] filepath the filepath to another template
66
+ # @return [String] HTML content of the specfied template at the filepath
67
+ #
68
+ def erb(filepath)
69
+ template_filepath = File.join File.dirname(erb_template_file), "#{filepath}.erb"
70
+ template_file = ERB.new File.read(template_filepath)
71
+ template_file.result(binding)
72
+ end
73
+
74
+ #
75
+ # @return [Types] the HTML content of the template specified
76
+ #
77
+ def render
78
+ template_file = ERB.new File.read(erb_template_file)
79
+ template_file.result(binding)
80
+ end
81
+ end
82
+
83
+ #
84
+ # Generate inline CSS assets. Using CssParser it is able to traverse imports
85
+ # to ensure all CSS is inlined within the document.
86
+ #
87
+ # Also embeds all images contained within the CSS into the inlined CSS.
88
+ #
89
+ class CSSTemplateGenerator < TemplateGenerator
90
+ include Helpers::EncodeImage
91
+
92
+ def content
93
+ content_filepath = File.exists?(filepath) ? filepath : File.join(File.dirname(__FILE__), "..", "..", "public", "css", filepath)
94
+ parser = CssParser::Parser.new
95
+ parser.load_file!(content_filepath)
96
+
97
+ css_contents = parser.to_s
98
+
99
+ css_contents.gsub(/url\([\s"']*([^\)"'\s]*)[\s"']*\)/m) do |image_uri|
100
+ image_name = Regexp.last_match(1)
101
+ image_path = File.join File.dirname(content_filepath), image_name
102
+ base64_data = image_path_to_base64(image_path)
103
+ "url(#{base64_data})"
104
+ end
105
+
106
+ end
107
+
108
+ def erb_template_file
109
+ File.join File.dirname(__FILE__), "..", "..", "views", "inline_css.erb"
110
+ end
111
+
112
+ end
113
+
114
+ #
115
+ # Inline the specified javascript
116
+ #
117
+ class JSTemplateGenerator < TemplateGenerator
118
+
119
+ def content
120
+ content_filepath = File.exists?(filepath) ? filepath : File.join(File.dirname(__FILE__), "..", "..", "public", "js", filepath)
121
+ File.read content_filepath
122
+ end
123
+
124
+ def erb_template_file
125
+ File.join File.dirname(__FILE__), "..", "..", "views", "inline_js.erb"
126
+ end
127
+
128
+ end
129
+
130
+ end
@@ -0,0 +1,73 @@
1
+ require_relative 'metadata/assignment'
2
+ require_relative 'metadata/css_classes'
3
+ require_relative 'metadata/html_id'
4
+ require_relative 'metadata/template'
5
+
6
+ module Parade
7
+
8
+ #
9
+ # Slides within Parade contain metadata. This metadata allows you to set
10
+ # CSS classes and IDs. You are also able, as well to assigna unique
11
+ # transitions between each slide.
12
+ #
13
+ class Metadata
14
+
15
+ #
16
+ # @example Raw Metadata that contains CSS Class, ID, transitions, and template data
17
+ #
18
+ # metadata = Metadata.parse "transition=fade one two #id three tpl=template_name"
19
+ # metadata.classes # => [ 'one', 'two', 'three' ]
20
+ # metadata.transition # => 'fade'
21
+ # metadata.id # => 'id'
22
+ # metadata.template # => 'template_name'
23
+ #
24
+ # @param [String] metadata a single string that contains all the raw metadata.
25
+ #
26
+ def self.parse(metadata)
27
+
28
+ metadata_hash = {}
29
+
30
+ metadata.to_s.split(' ').each do |term|
31
+ metadata_type = parsers.find {|parser| parser.match? term }
32
+ metadata_type.apply(term,metadata_hash)
33
+ end
34
+
35
+ self.new metadata_hash
36
+ end
37
+
38
+ #
39
+ # The list of the parsers that are used to parse the metadata string.
40
+ #
41
+ def self.parsers
42
+ [ Template.new,
43
+ Assignment.new,
44
+ HTMLId.new,
45
+ CSSClasses.new ]
46
+ end
47
+
48
+ #
49
+ # The initialize method is generally not called directly and instead is
50
+ # used through the `Metadata.parse` method.
51
+ #
52
+ # @param [Hash] params this hash contains the key-value pairs that map
53
+ # directly to accessor methods within the Metadata class.
54
+ #
55
+ # @see Metadata.parse
56
+ #
57
+ def initialize(params = {})
58
+ params.each {|k,v| send("#{k}=",v) if respond_to? "#{k}=" }
59
+ end
60
+
61
+ attr_writer :classes
62
+
63
+ def classes
64
+ @classes || []
65
+ end
66
+
67
+ attr_accessor :id
68
+ attr_accessor :transition
69
+ attr_accessor :template
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,38 @@
1
+ module Parade
2
+ class Metadata
3
+
4
+ #
5
+ # The Assignment metadata parser is a general parser that allows the ability
6
+ # to assign a value to the specified field of the metadata. This is
7
+ # usually used for assigning the *transition* field but could be used to set
8
+ # the *id* in the metadata.
9
+ #
10
+ # @example Settings the Metadata id
11
+ #
12
+ # metadata = Metadata.parse "id=unique-slide-id"
13
+ # metadata.id # => "unique-slide-id"
14
+ #
15
+ # @see Metadata
16
+ #
17
+ class Assignment
18
+
19
+ def match?(term)
20
+ term =~ /.+=.+/
21
+ end
22
+
23
+ def apply(term,hash)
24
+ key, value = parse(term)
25
+ hash[key] = value
26
+ hash
27
+ end
28
+
29
+ private
30
+
31
+ def parse(term)
32
+ term.split('=')
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ module Parade
2
+ class Metadata
3
+
4
+ #
5
+ # By default the CSS Class metadata parser is a catch all parser that will
6
+ # use all the terms and create CSS classes.
7
+ #
8
+ class CSSClasses
9
+
10
+ def match?(term)
11
+ true
12
+ end
13
+
14
+ def apply(term,hash)
15
+ (hash[:classes] ||= []) << term
16
+ hash
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end