parade 0.8.0

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 (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,35 @@
1
+ module Parade
2
+ class Metadata
3
+
4
+ #
5
+ # Specify the HTML id of the slide through this metadata parser. This allows
6
+ # the id to be defined like one would reference with jQuery.
7
+ #
8
+ # @example Setting the Metadata id
9
+ #
10
+ # metadata = Metadata.parse "transition=fade one two #id three tpl=template_name"
11
+ # metadata.id # => id
12
+ #
13
+ # @see Metadata
14
+ #
15
+ class HTMLId
16
+
17
+ def match?(term)
18
+ term =~ /#.+/
19
+ end
20
+
21
+ def apply(term,hash)
22
+ hash[:id] = parse(term)
23
+ hash
24
+ end
25
+
26
+ private
27
+
28
+ def parse(term)
29
+ term[1..-1]
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ module Parade
2
+ class Metadata
3
+
4
+ #
5
+ # The Template metadata allows the specification of a template to use for
6
+ # the slide. This is extremely similar to the {Assignment} parser, except
7
+ # it allows for the previously supported abbreviation *tpl* for representing
8
+ # template.
9
+ #
10
+ class Template
11
+
12
+ def match?(term)
13
+ term =~ /^(?:tpl|template)=(.+)$/
14
+ end
15
+
16
+ def apply(term,hash)
17
+ hash[:template] = parse(term)
18
+ hash
19
+ end
20
+
21
+ private
22
+
23
+ def parse(term)
24
+ term =~ /^(?:tpl|template)=(.+)$/
25
+ template_name = Regexp.last_match(1)
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,138 @@
1
+ require_relative '../section'
2
+ require_relative 'presentation_filepath_parser'
3
+
4
+ module Parade
5
+ module Parsers
6
+
7
+ class Dsl
8
+
9
+ #
10
+ # The parade DSL parse method is used to convert the parade file contents
11
+ # into executable ruby code. This method is also called recursively when
12
+ # a section contains sub-sections to properly parse that data as well.
13
+ #
14
+ # @param [String,Section] contents the string representation of the parade
15
+ # dsl contents to be parsed or the current section to be used as the
16
+ # current context.
17
+ # @param [Hash] options additional options to provide additional
18
+ # configuration to the parsing process.
19
+ #
20
+ # def self.parse(contents,options = {})
21
+ # builder = new
22
+ # builder.options = options
23
+ #
24
+ # config = Proc.new { eval(contents) }
25
+ # builder.instance_eval(&config)
26
+ #
27
+ # builder.current_section
28
+ # end
29
+
30
+ def self.parse(contents,options = {},&config)
31
+ builder = new
32
+ builder.options = options
33
+
34
+ if contents.is_a? Section
35
+ builder.current_section = contents
36
+ else
37
+ config = Proc.new { eval(contents) }
38
+ end
39
+
40
+ builder.instance_eval(&config)
41
+
42
+ builder.current_section
43
+ end
44
+
45
+ #
46
+ # This is used within the DSL to set the title of the current section.
47
+ #
48
+ # @param [String] new_title the title for the setion.
49
+ #
50
+ def title(new_title)
51
+ current_section.title = new_title
52
+ end
53
+
54
+ #
55
+ # This is used within the DSL to set the description of the current section.
56
+ #
57
+ # @param [String] new_description the description for the setion.
58
+ #
59
+ def description(new_description)
60
+ current_section.description = new_description
61
+ end
62
+
63
+ #
64
+ # This is used by the DSL to add additional sections. Adds the specified
65
+ # slides or sub-sections, defined by their filepaths, as a subsection of
66
+ # this section.
67
+ #
68
+ def section(*filepaths,&block)
69
+
70
+ if block
71
+ sub_section = Section.new :title => filepaths.flatten.compact.join(" ")
72
+ section_content = self.class.parse sub_section, options, &block
73
+ else
74
+ section_content = Array(filepaths).flatten.compact.map do |filepath|
75
+ filepath = File.join(current_path,filepath)
76
+ PresentationFilepathParser.parse(filepath,options)
77
+ end
78
+ end
79
+
80
+ current_section.add_section section_content
81
+ section_content
82
+ end
83
+
84
+ alias_method :slides, :section
85
+
86
+ def template(template_name,template_file)
87
+ current_section.add_template template_name, File.join(options[:current_path], template_file)
88
+ end
89
+
90
+ #
91
+ # This is used by the DSL to specify the resources used by the presentation
92
+ #
93
+ def resources(resource_filepath)
94
+ current_section.add_resource File.join(options[:current_path], resource_filepath)
95
+ end
96
+
97
+ def pause_message(message)
98
+ current_section.pause_message = message
99
+ end
100
+
101
+ # @return [Hash] configuration options that the DSL class will use
102
+ # and pass to other file and directory parsers to ensure the
103
+ # path information is presevered correctly.
104
+ attr_accessor :options
105
+
106
+ # @return [String] the root path where the presentation is being served
107
+ # from. This path is necessary to ensure that images have the correct
108
+ # image path built for it.
109
+ def root_path
110
+ File.directory?(options[:root_path]) ? options[:root_path] : File.dirname(options[:root_path])
111
+ end
112
+
113
+ # @return [String] the current path is the path for the current section
114
+ # this usually differs from the root_path when parsing sections defined
115
+ # within a section (a sub-section).
116
+ def current_path
117
+ if options[:current_path]
118
+ File.directory?(options[:current_path]) ? options[:current_path] : File.dirname(options[:current_path])
119
+ else
120
+ root_path
121
+ end
122
+ end
123
+
124
+ attr_writer :current_section
125
+
126
+ # @return [Section] the current section being built.
127
+ def current_section
128
+ @current_section ||= begin
129
+ new_section = Section.new
130
+ new_section.add_resource current_path
131
+ new_section
132
+ end
133
+ end
134
+
135
+ end
136
+
137
+ end
138
+ end
@@ -0,0 +1,17 @@
1
+ module Parade
2
+ module Parsers
3
+
4
+ #
5
+ # Given a DSL defined file, load the contents and then parse the contents
6
+ # with the DSL parser.
7
+ #
8
+ class DslFileParser
9
+
10
+ def self.parse(filepath,options = {})
11
+ Dsl.parse File.read(filepath), options
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,67 @@
1
+ module Parade
2
+ module Parsers
3
+
4
+ #
5
+ # Load the JSON format of a presentation, convert it to the DSL format,
6
+ # and then send it to the DSL parser. This parser is to provide backwards
7
+ # compatabiliy to the previously defined JSON format of a Parade presentation.
8
+ #
9
+ # @example parade.json format
10
+ #
11
+ # {
12
+ # "name": "Something",
13
+ # "description": "Example Presentation",
14
+ # "templates" : { "default" : "custom.tpl" },
15
+ # "sections": [
16
+ # {"section":"one"},
17
+ # {"section":"two"},
18
+ # {"section":"three"}
19
+ # ]
20
+ # }
21
+ #
22
+ class JsonFileParser
23
+
24
+ def self.parse(filepath,options = {})
25
+ parade_json = JSON.parse File.read(filepath)
26
+
27
+ dsl_content = convert_to_parade_dsl parade_json
28
+ Dsl.parse dsl_content, options
29
+ end
30
+
31
+ private
32
+
33
+ def self.convert_to_parade_dsl(content)
34
+
35
+ dsl_content = ""
36
+
37
+ dsl_content << "title '#{content['name']}'\n" if content['name']
38
+ dsl_content << "description %{#{content['description']}}\n" if content['description']
39
+ dsl_content << "pause_message %{#{content['pause_msg']}}" if content['pause_msg']
40
+
41
+ templates = content['templates'] || {}
42
+
43
+ templates.each do |template_name,template_file|
44
+ dsl_content << "template '#{template_name}', '#{template_file}'\n"
45
+ end
46
+
47
+ Array(content['sections']).each do |section|
48
+
49
+ if section.is_a?(Hash)
50
+ filename_or_folder = section['section']
51
+ else
52
+ filename_or_folder = section
53
+ end
54
+
55
+ Array(filename_or_folder).each do |file_or_folder|
56
+ dsl_content << "slides '#{file_or_folder}'\n"
57
+ end
58
+ end
59
+
60
+ dsl_content
61
+
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,44 @@
1
+ module Parade
2
+ module Parsers
3
+
4
+ #
5
+ # Within the markdown file the image paths are relative to the markdown
6
+ # file. This parser will convert any image paths specified within the
7
+ # markdown and convert them to relative to the presentation root.
8
+ #
9
+ # This parsing functionality ensures that the image path when this is
10
+ # later rendered to HTML will have the correct path.
11
+ #
12
+ # @example ![octocat](octocat.png)
13
+ #
14
+ # "![octocat](octocat.png)" # => "![octocat](section/octocat.png)"
15
+ #
16
+ class MarkdownImagePaths
17
+
18
+ #
19
+ # Convert all the image paths within the markdown content with the
20
+ # specified path parameter.
21
+ #
22
+ # @example Update all image paths to be prefixed with 'section'
23
+ #
24
+ # MarkdownImagePaths.parse(markdown_content, :path => 'section')
25
+ #
26
+ #
27
+ # @param [String] content markdown content that may or may not contain
28
+ # image tags.
29
+ # @param [Hash] options that contains parameters to help to properly
30
+ # convert the image path.
31
+ #
32
+ def self.parse(content,options = {})
33
+ return content unless options[:path]
34
+
35
+ content.gsub(/!\[([^\]]*)\]\((?!https?:\/\/)(.+)\)/) do |match|
36
+ updated_image_path = File.join(options[:path],$2)
37
+ %{![#{$1}](#{updated_image_path})}
38
+ end
39
+
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,63 @@
1
+ require_relative '../slide'
2
+
3
+ module Parade
4
+ module Parsers
5
+
6
+ #
7
+ # As multiple slides are contained within a markdown file, this parser
8
+ # will split the markdown along the specified slide marker.
9
+ #
10
+ # @todo this currently does too much at the moment. It should simply split
11
+ # the markdown file along the slide markers and allow another parser
12
+ # perform the work of creating the actual slide objects.
13
+ #
14
+ class MarkdownSlideSplitter
15
+
16
+ #
17
+ # Splits the markdown content into separate slide files based on the
18
+ # separator defined by this class.
19
+ #
20
+ # @param [String] content content that is markdown format
21
+ # @return [Array] slides parsed from the markdown content
22
+ def self.parse(content,options = {})
23
+
24
+ # if there are no !SLIDE markers, then make every H1 define a new slide
25
+ unless content =~ /^\<?!SLIDE/m
26
+ content = content.gsub(/^# /m, "<!SLIDE>\n# ")
27
+ end
28
+
29
+ lines = content.split("\n")
30
+
31
+ # Break the markdown apart into separate markdown files based on the
32
+ # separator
33
+
34
+ slides = []
35
+ current_slide = Slide.new
36
+ slides << current_slide
37
+
38
+ until lines.empty?
39
+ line = lines.shift
40
+
41
+ if line =~ /^<?!SLIDE(.*)>?/
42
+
43
+ # Remove the trailing > from the metadata
44
+ metadata_string = Regexp.last_match(1).gsub(/>$/,'')
45
+
46
+ metadata = Metadata.parse metadata_string
47
+
48
+ current_slide = Slide.new(:metadata => metadata)
49
+ slides << current_slide
50
+ else
51
+ current_slide << line
52
+ end
53
+
54
+ end
55
+
56
+ slides.delete_if {|slide| slide.empty? }
57
+ slides.each_with_index {|slide,index| slide.sequence = (index + 1) }
58
+
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,36 @@
1
+ require_relative 'presentation_file_parser'
2
+ require_relative 'slides_file_content_parser'
3
+
4
+ module Parade
5
+ module Parsers
6
+
7
+ module PresentationDirectoryParser
8
+
9
+ SLIDE_SEARCH_PATTERN = File.join('**','*.md')
10
+
11
+ def self.parse(filepath,options = {})
12
+
13
+ parade_file = Array(options[:parade_file]).find do |relative_filepath|
14
+ parade_file = File.join(filepath,relative_filepath)
15
+ File.exists? parade_file
16
+ end
17
+
18
+ if parade_file
19
+ PresentationFileParser.parse File.join(filepath,parade_file), options
20
+ else
21
+
22
+ slides = Dir[File.join(filepath,SLIDE_SEARCH_PATTERN)].map do |slide_filepath|
23
+ SlidesFileContentParser.parse slide_filepath, options
24
+ end
25
+
26
+ section = Section.new
27
+ section.add_section slides
28
+ section
29
+
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ require_relative 'dsl_file_parser'
2
+ require_relative 'json_file_parser'
3
+
4
+ module Parade
5
+ module Parsers
6
+
7
+ #
8
+ # The Presentation File Parser allows for the JSON formatted file or the
9
+ # DSL formatted files. The determination of which to use is solely based
10
+ # on the file extension.
11
+ #
12
+ class PresentationFileParser
13
+
14
+ def self.parse(filepath,options = {})
15
+ 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
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end