showoffer 0.0.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 (206) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +559 -0
  3. data/Rakefile +27 -0
  4. data/bin/showoffer +189 -0
  5. data/lib/commandline_parser.rb +67 -0
  6. data/lib/showoff.rb +515 -0
  7. data/lib/showoff/version.rb +3 -0
  8. data/lib/showoff_utils.rb +360 -0
  9. data/public/css/960.css +653 -0
  10. data/public/css/fg.menu.css +114 -0
  11. data/public/css/onepage.css +60 -0
  12. data/public/css/pdf.css +12 -0
  13. data/public/css/presenter.css +76 -0
  14. data/public/css/reset.css +53 -0
  15. data/public/css/sh_style.css +66 -0
  16. data/public/css/showoff.css +403 -0
  17. data/public/css/spinner_bar.gif +0 -0
  18. data/public/css/theme/images/ui-bg_diagonals-small_100_f0efea_40x40.png +0 -0
  19. data/public/css/theme/images/ui-bg_flat_35_f0f0f0_40x100.png +0 -0
  20. data/public/css/theme/images/ui-bg_glass_55_fcf0ba_1x400.png +0 -0
  21. data/public/css/theme/images/ui-bg_glow-ball_25_2e2e28_600x600.png +0 -0
  22. data/public/css/theme/images/ui-bg_highlight-soft_100_f0efea_1x100.png +0 -0
  23. data/public/css/theme/images/ui-bg_highlight-soft_25_327E04_1x100.png +0 -0
  24. data/public/css/theme/images/ui-bg_highlight-soft_25_5A9D1A_1x100.png +0 -0
  25. data/public/css/theme/images/ui-bg_highlight-soft_95_ffedad_1x100.png +0 -0
  26. data/public/css/theme/images/ui-bg_inset-soft_22_3b3b35_1x100.png +0 -0
  27. data/public/css/theme/images/ui-icons_808080_256x240.png +0 -0
  28. data/public/css/theme/images/ui-icons_8DC262_256x240.png +0 -0
  29. data/public/css/theme/images/ui-icons_cd0a0a_256x240.png +0 -0
  30. data/public/css/theme/images/ui-icons_e7e6e4_256x240.png +0 -0
  31. data/public/css/theme/images/ui-icons_eeeeee_256x240.png +0 -0
  32. data/public/css/theme/images/ui-icons_ffffff_256x240.png +0 -0
  33. data/public/css/theme/ui.accordion.css +9 -0
  34. data/public/css/theme/ui.all.css +2 -0
  35. data/public/css/theme/ui.base.css +9 -0
  36. data/public/css/theme/ui.core.css +37 -0
  37. data/public/css/theme/ui.datepicker.css +62 -0
  38. data/public/css/theme/ui.dialog.css +13 -0
  39. data/public/css/theme/ui.progressbar.css +4 -0
  40. data/public/css/theme/ui.resizable.css +13 -0
  41. data/public/css/theme/ui.slider.css +17 -0
  42. data/public/css/theme/ui.tabs.css +9 -0
  43. data/public/css/theme/ui.theme.css +245 -0
  44. data/public/favicon.ico +0 -0
  45. data/public/highlight/AUTHORS.en.txt +46 -0
  46. data/public/highlight/AUTHORS.ru.txt +46 -0
  47. data/public/highlight/LICENSE +24 -0
  48. data/public/highlight/README.md +136 -0
  49. data/public/highlight/README.ru.md +140 -0
  50. data/public/highlight/classref.txt +437 -0
  51. data/public/highlight/export.html +87 -0
  52. data/public/highlight/highlight.js +630 -0
  53. data/public/highlight/highlight.pack.js +1 -0
  54. data/public/highlight/languages/1c.js +68 -0
  55. data/public/highlight/languages/apache.js +432 -0
  56. data/public/highlight/languages/avrasm.js +75 -0
  57. data/public/highlight/languages/axapta.js +43 -0
  58. data/public/highlight/languages/bash.js +56 -0
  59. data/public/highlight/languages/cmake.js +24 -0
  60. data/public/highlight/languages/cpp.js +62 -0
  61. data/public/highlight/languages/cs.js +41 -0
  62. data/public/highlight/languages/css.js +101 -0
  63. data/public/highlight/languages/delphi.js +70 -0
  64. data/public/highlight/languages/diff.js +64 -0
  65. data/public/highlight/languages/django.js +72 -0
  66. data/public/highlight/languages/dos.js +29 -0
  67. data/public/highlight/languages/erlang-repl.js +81 -0
  68. data/public/highlight/languages/erlang.js +201 -0
  69. data/public/highlight/languages/go.js +58 -0
  70. data/public/highlight/languages/haskell.js +77 -0
  71. data/public/highlight/languages/ini.js +32 -0
  72. data/public/highlight/languages/java.js +45 -0
  73. data/public/highlight/languages/javascript.js +53 -0
  74. data/public/highlight/languages/lisp.js +87 -0
  75. data/public/highlight/languages/lua.js +75 -0
  76. data/public/highlight/languages/mel.js +40 -0
  77. data/public/highlight/languages/nginx.js +224 -0
  78. data/public/highlight/languages/objectivec.js +94 -0
  79. data/public/highlight/languages/parser3.js +52 -0
  80. data/public/highlight/languages/perl.js +143 -0
  81. data/public/highlight/languages/php.js +55 -0
  82. data/public/highlight/languages/profile.js +49 -0
  83. data/public/highlight/languages/python.js +71 -0
  84. data/public/highlight/languages/renderman.js +230 -0
  85. data/public/highlight/languages/ruby.js +203 -0
  86. data/public/highlight/languages/scala.js +60 -0
  87. data/public/highlight/languages/smalltalk.js +55 -0
  88. data/public/highlight/languages/sql.js +90 -0
  89. data/public/highlight/languages/tex.js +62 -0
  90. data/public/highlight/languages/vala.js +75 -0
  91. data/public/highlight/languages/vbscript.js +30 -0
  92. data/public/highlight/languages/vhdl.js +30 -0
  93. data/public/highlight/languages/xml.js +103 -0
  94. data/public/highlight/styles/arta.css +151 -0
  95. data/public/highlight/styles/ascetic.css +45 -0
  96. data/public/highlight/styles/brown_paper.css +105 -0
  97. data/public/highlight/styles/brown_papersq.png +0 -0
  98. data/public/highlight/styles/dark.css +103 -0
  99. data/public/highlight/styles/default.css +121 -0
  100. data/public/highlight/styles/far.css +118 -0
  101. data/public/highlight/styles/github.css +129 -0
  102. data/public/highlight/styles/idea.css +118 -0
  103. data/public/highlight/styles/ir_black.css +103 -0
  104. data/public/highlight/styles/magula.css +118 -0
  105. data/public/highlight/styles/school_book.css +111 -0
  106. data/public/highlight/styles/school_book.png +0 -0
  107. data/public/highlight/styles/solarized_dark.css +96 -0
  108. data/public/highlight/styles/solarized_light.css +96 -0
  109. data/public/highlight/styles/sunburst.css +147 -0
  110. data/public/highlight/styles/vs.css +84 -0
  111. data/public/highlight/styles/zenburn.css +115 -0
  112. data/public/highlight/test.html +1609 -0
  113. data/public/js/coffee-script.js +8 -0
  114. data/public/js/core.js +79 -0
  115. data/public/js/fg.menu.js +645 -0
  116. data/public/js/jTypeWriter.js +26 -0
  117. data/public/js/jquery-1.4.2.min.js +154 -0
  118. data/public/js/jquery-print.js +109 -0
  119. data/public/js/jquery.batchImageLoad.js +56 -0
  120. data/public/js/jquery.cookie.js +96 -0
  121. data/public/js/jquery.cycle.all.js +1284 -0
  122. data/public/js/jquery.doubletap-0.1.js +105 -0
  123. data/public/js/jquery.uuid.js +24 -0
  124. data/public/js/jquery.ws-0.3pre.js +201 -0
  125. data/public/js/onepage.js +5 -0
  126. data/public/js/presenter.js +193 -0
  127. data/public/js/sh_lang/sh_bison.min.js +1 -0
  128. data/public/js/sh_lang/sh_c.min.js +1 -0
  129. data/public/js/sh_lang/sh_caml.min.js +1 -0
  130. data/public/js/sh_lang/sh_changelog.min.js +1 -0
  131. data/public/js/sh_lang/sh_coffeescript.min.js +1 -0
  132. data/public/js/sh_lang/sh_cpp.min.js +1 -0
  133. data/public/js/sh_lang/sh_csharp.min.js +1 -0
  134. data/public/js/sh_lang/sh_css.min.js +1 -0
  135. data/public/js/sh_lang/sh_cucumber.min.js +2 -0
  136. data/public/js/sh_lang/sh_desktop.min.js +1 -0
  137. data/public/js/sh_lang/sh_diff.min.js +1 -0
  138. data/public/js/sh_lang/sh_erlang.min.js +1 -0
  139. data/public/js/sh_lang/sh_flex.min.js +1 -0
  140. data/public/js/sh_lang/sh_glsl.min.js +1 -0
  141. data/public/js/sh_lang/sh_haxe.min.js +1 -0
  142. data/public/js/sh_lang/sh_html.min.js +1 -0
  143. data/public/js/sh_lang/sh_java.min.js +1 -0
  144. data/public/js/sh_lang/sh_javascript.min.js +1 -0
  145. data/public/js/sh_lang/sh_javascript_dom.min.js +1 -0
  146. data/public/js/sh_lang/sh_latex.min.js +1 -0
  147. data/public/js/sh_lang/sh_ldap.min.js +1 -0
  148. data/public/js/sh_lang/sh_log.min.js +1 -0
  149. data/public/js/sh_lang/sh_lsm.min.js +1 -0
  150. data/public/js/sh_lang/sh_m4.min.js +1 -0
  151. data/public/js/sh_lang/sh_makefile.min.js +1 -0
  152. data/public/js/sh_lang/sh_oracle.min.js +1 -0
  153. data/public/js/sh_lang/sh_pascal.min.js +1 -0
  154. data/public/js/sh_lang/sh_perl.min.js +1 -0
  155. data/public/js/sh_lang/sh_php.min.js +1 -0
  156. data/public/js/sh_lang/sh_prolog.min.js +1 -0
  157. data/public/js/sh_lang/sh_properties.min.js +1 -0
  158. data/public/js/sh_lang/sh_python.min.js +1 -0
  159. data/public/js/sh_lang/sh_ruby.min.js +1 -0
  160. data/public/js/sh_lang/sh_scala.min.js +1 -0
  161. data/public/js/sh_lang/sh_sh.min.js +1 -0
  162. data/public/js/sh_lang/sh_slang.min.js +1 -0
  163. data/public/js/sh_lang/sh_sml.min.js +1 -0
  164. data/public/js/sh_lang/sh_spec.min.js +1 -0
  165. data/public/js/sh_lang/sh_sql.min.js +1 -0
  166. data/public/js/sh_lang/sh_tcl.min.js +1 -0
  167. data/public/js/sh_lang/sh_xml.min.js +1 -0
  168. data/public/js/sh_lang/sh_xorg.min.js +1 -0
  169. data/public/js/sh_main.min.js +4 -0
  170. data/public/js/showoff.js +652 -0
  171. data/public/js/showoffcore.js +13 -0
  172. data/public/scripts/script.js +280 -0
  173. data/public/themes/ribbon/fonts/DroidSansMono.svg +626 -0
  174. data/public/themes/ribbon/fonts/DroidSansMono.ttf +0 -0
  175. data/public/themes/ribbon/fonts/PTSans.Bold.Italic.svg +728 -0
  176. data/public/themes/ribbon/fonts/PTSans.Bold.Italic.ttf +0 -0
  177. data/public/themes/ribbon/fonts/PTSans.Bold.Italic.woff +0 -0
  178. data/public/themes/ribbon/fonts/PTSans.Bold.svg +728 -0
  179. data/public/themes/ribbon/fonts/PTSans.Bold.ttf +0 -0
  180. data/public/themes/ribbon/fonts/PTSans.Bold.woff +0 -0
  181. data/public/themes/ribbon/fonts/PTSans.Italic.svg +728 -0
  182. data/public/themes/ribbon/fonts/PTSans.Italic.ttf +0 -0
  183. data/public/themes/ribbon/fonts/PTSans.Italic.woff +0 -0
  184. data/public/themes/ribbon/fonts/PTSans.Narrow.Bold.svg +728 -0
  185. data/public/themes/ribbon/fonts/PTSans.Narrow.Bold.ttf +0 -0
  186. data/public/themes/ribbon/fonts/PTSans.Narrow.Bold.woff +0 -0
  187. data/public/themes/ribbon/fonts/PTSans.Narrow.svg +728 -0
  188. data/public/themes/ribbon/fonts/PTSans.Narrow.ttf +0 -0
  189. data/public/themes/ribbon/fonts/PTSans.Narrow.woff +0 -0
  190. data/public/themes/ribbon/fonts/PTSans.svg +728 -0
  191. data/public/themes/ribbon/fonts/PTSans.ttf +0 -0
  192. data/public/themes/ribbon/fonts/PTSans.woff +0 -0
  193. data/public/themes/ribbon/fonts/TargetBlank.otf +0 -0
  194. data/public/themes/ribbon/fonts/TargetBlank.svg +14 -0
  195. data/public/themes/ribbon/images/grid.png +0 -0
  196. data/public/themes/ribbon/images/linen.png +0 -0
  197. data/public/themes/ribbon/images/ribbon.svg +4 -0
  198. data/public/themes/ribbon/styles/fonts.css +63 -0
  199. data/public/themes/ribbon/styles/print.css +68 -0
  200. data/public/themes/ribbon/styles/reset.css +42 -0
  201. data/public/themes/ribbon/styles/style.css +408 -0
  202. data/views/header.erb +11 -0
  203. data/views/index.erb +13 -0
  204. data/views/onepage.erb +39 -0
  205. data/views/presenter.erb +70 -0
  206. metadata +328 -0
@@ -0,0 +1,3 @@
1
+ # No namespace here since ShowOff is a class and I'd have to inherit from
2
+ # Sinatra::Application (which we don't want to load here)
3
+ SHOWOFF_VERSION = '0.0.1'
@@ -0,0 +1,360 @@
1
+ class ShowOffUtils
2
+ def self.presentation_config_file
3
+ @presentation_config_file ||= 'showoff.json'
4
+ end
5
+
6
+ def self.presentation_config_file=(filename)
7
+ @presentation_config_file = filename
8
+ end
9
+
10
+ def self.create(dirname,create_samples,dir='one')
11
+ Dir.mkdir(dirname) if !File.exists?(dirname)
12
+ Dir.chdir(dirname) do
13
+ if create_samples
14
+ # create section
15
+ Dir.mkdir(dir)
16
+
17
+ # create markdown file
18
+ File.open("#{dir}/01_slide.md", 'w+') do |f|
19
+ f.puts make_slide("My Presentation")
20
+ f.puts make_slide("Bullet Points","bullets incremental",["first point","second point","third point"])
21
+ end
22
+ end
23
+
24
+ # create showoff.json
25
+ File.open(ShowOffUtils.presentation_config_file, 'w+') do |f|
26
+ f.puts "{ \"name\": \"My Preso\", \"sections\": [ {\"section\":\"#{dir}\"} ]}"
27
+ end
28
+ end
29
+ end
30
+
31
+ HEROKU_GEMS_FILE = '.gems'
32
+ HEROKU_BUNDLER_GEMS_FILE = 'Gemfile'
33
+ HEROKU_CONFIG_FILE = 'config.ru'
34
+
35
+ # Setup presentation to run on Heroku
36
+ #
37
+ # name - String containing heroku name
38
+ # force - boolean if .gems/Gemfile and config.ru should be overwritten if they don't exist
39
+ # password - String containing password to protect your heroku site; nil means no password protection
40
+ # use_dot_gems - boolean that, if true, indicates we should use the old, deprecated .gems file instead of Bundler
41
+ def self.heroku(name, force = false, password = nil, use_dot_gems = false)
42
+ modified_something = false
43
+
44
+ if use_dot_gems
45
+ modified_something = create_gems_file(HEROKU_GEMS_FILE,
46
+ !password.nil?,
47
+ force,
48
+ lambda{ |gem| gem })
49
+ else
50
+ modified_something = create_gems_file(HEROKU_BUNDLER_GEMS_FILE,
51
+ !password.nil?,
52
+ force,
53
+ lambda{ |gem| "gem '#{gem}'" },
54
+ lambda{ "source :rubygems" })
55
+ end
56
+
57
+ create_file_if_needed(HEROKU_CONFIG_FILE,force) do |file|
58
+ modified_something = true
59
+ file.puts 'require "showoff"'
60
+ if password.nil?
61
+ file.puts 'run ShowOff.new'
62
+ else
63
+ file.puts 'require "rack"'
64
+ file.puts 'showoff_app = ShowOff.new'
65
+ file.puts 'protected_showoff = Rack::Auth::Basic.new(showoff_app) do |username, password|'
66
+ file.puts "\tpassword == '#{password}'"
67
+ file.puts 'end'
68
+ file.puts 'run protected_showoff'
69
+ end
70
+ end
71
+
72
+ modified_something
73
+ end
74
+
75
+ # generate a static version of the site into the gh-pages branch
76
+ def self.github
77
+ ShowOff.do_static(nil)
78
+ `git add static`
79
+ sha = `git write-tree`.chomp
80
+ tree_sha = `git rev-parse #{sha}:static`.chomp
81
+ `git read-tree HEAD` # reset staging to last-commit
82
+ ghp_sha = `git rev-parse gh-pages 2>/dev/null`.chomp
83
+ extra = ghp_sha != 'gh-pages' ? "-p #{ghp_sha}" : ''
84
+ commit_sha = `echo 'static presentation' | git commit-tree #{tree_sha} #{extra}`.chomp
85
+ `git update-ref refs/heads/gh-pages #{commit_sha}`
86
+ end
87
+
88
+ # Makes a slide as a string.
89
+ # [title] title of the slide
90
+ # [classes] any "classes" to include, such as 'smaller', 'transition', etc.
91
+ # [content] slide content. Currently, if this is an array, it will make a bullet list. Otherwise
92
+ # the string value of this will be put in the slide as-is
93
+ def self.make_slide(title,classes="",content=nil)
94
+ slide = "!SLIDE #{classes}\n"
95
+ slide << "# #{title} #\n"
96
+ slide << "\n"
97
+ if content
98
+ if content.kind_of? Array
99
+ content.each { |x| slide << "* #{x.to_s}\n" }
100
+ else
101
+ slide << content.to_s
102
+ end
103
+ end
104
+ slide
105
+ end
106
+
107
+ TYPES = {
108
+ :default => lambda { |t,size,source,type| make_slide(t,"#{size} #{type}",source) },
109
+ 'title' => lambda { |t,size,dontcare| make_slide(t,size) },
110
+ 'bullets' => lambda { |t,size,dontcare| make_slide(t,"#{size} bullets incremental",["bullets","go","here"])},
111
+ 'smbullets' => lambda { |t,size,dontcare| make_slide(t,"#{size} smbullets incremental",["bullets","go","here","and","here"])},
112
+ 'code' => lambda { |t,size,src| make_slide(t,size,blank?(src) ? " @@@ Ruby\n code_here()" : src) },
113
+ 'commandline' => lambda { |t,size,dontcare| make_slide(t,"#{size} commandline"," $ command here\n output here")},
114
+ 'full-page' => lambda { |t,size,dontcare| make_slide(t,"#{size} full-page","![Image Description](image/ref.png)")},
115
+ }
116
+
117
+
118
+ # Adds a new slide to a given dir, giving it a number such that it falls after all slides
119
+ # in that dir.
120
+ # Options are:
121
+ # [:dir] - dir where we put the slide (if omitted, slide is output to $stdout)
122
+ # [:name] - name of the file, without the number prefix. (if omitted, a default is used)
123
+ # [:title] - title in the slide. If not specified the source file name is
124
+ # used. If THAT is not specified, uses the value of +:name+. If THAT is not
125
+ # specified, a suitable default is used
126
+ # [:code] - path to a source file to use as content (force :type to be 'code')
127
+ # [:number] - true if numbering should be done, false if not
128
+ # [:type] - the type of slide to create
129
+ def self.add_slide(options)
130
+
131
+ add_new_dir(options[:dir]) if options[:dir] && !File.exists?(options[:dir])
132
+
133
+ options[:type] = 'code' if options[:code]
134
+
135
+ title = determine_title(options[:title],options[:name],options[:code])
136
+
137
+ options[:name] = 'new_slide' if !options[:name]
138
+
139
+ size,source = determine_size_and_source(options[:code])
140
+ type = options[:type] || :default
141
+ slide = TYPES[type].call(title,size,source)
142
+
143
+ if options[:dir]
144
+ filename = determine_filename(options[:dir],options[:name],options[:number])
145
+ write_file(filename,slide)
146
+ else
147
+ puts slide
148
+ puts
149
+ end
150
+
151
+ end
152
+
153
+ # Adds the given directory to this presentation, appending it to
154
+ # the end of showoff.json as well
155
+ def self.add_new_dir(dir)
156
+ puts "Creating #{dir}..."
157
+ Dir.mkdir dir
158
+
159
+ showoff_json = JSON.parse(File.read(ShowOffUtils.presentation_config_file))
160
+ showoff_json["section"] = dir
161
+ File.open(ShowOffUtils.presentation_config_file,'w') do |file|
162
+ file.puts JSON.generate(showoff_json)
163
+ end
164
+ puts "#{ShowOffUtils.presentation_config_file} updated"
165
+ end
166
+
167
+ def self.blank?(string)
168
+ string.nil? || string.strip.length == 0
169
+ end
170
+
171
+ def self.determine_size_and_source(code)
172
+ size = ""
173
+ source = ""
174
+ if code
175
+ source,lines,width = read_code(code)
176
+ size = adjust_size(lines,width)
177
+ end
178
+ [size,source]
179
+ end
180
+
181
+ def self.write_file(filename,slide)
182
+ File.open(filename,'w') do |file|
183
+ file.puts slide
184
+ end
185
+ puts "Wrote #{filename}"
186
+ end
187
+
188
+ def self.determine_filename(slide_dir,slide_name,number)
189
+ filename = "#{slide_dir}/#{slide_name}.md"
190
+ if number
191
+ max = find_next_number(slide_dir)
192
+ filename = "#{slide_dir}/#{max}_#{slide_name}.md"
193
+ end
194
+ filename
195
+ end
196
+
197
+ # Finds the next number in the given dir to
198
+ # name a slide as the last slide in the dir.
199
+ def self.find_next_number(slide_dir)
200
+ max = 0
201
+ Dir.open(slide_dir).each do |file|
202
+ if file =~ /(\d+).*\.md/
203
+ num = $1.to_i
204
+ max = num if num > max
205
+ end
206
+ end
207
+ max += 1
208
+ max = "0#{max}" if max < 10
209
+ max
210
+ end
211
+
212
+ def self.determine_title(title,slide_name,code)
213
+ if blank?(title)
214
+ title = slide_name
215
+ title = File.basename(code) if code
216
+ end
217
+ title = "Title here" if blank?(title)
218
+ title
219
+ end
220
+
221
+ # Determines a more optimal value for the size (e.g. small vs. smaller)
222
+ # based upon the size of the code being formatted.
223
+ def self.adjust_size(lines,width)
224
+ size = ""
225
+ # These values determined empircally
226
+ size = "small" if width > 50
227
+ size = "small" if lines > 15
228
+ size = "smaller" if width > 57
229
+ size = "smaller" if lines > 19
230
+ puts "warning, some lines are too long and the code may be cut off" if width > 65
231
+ puts "warning, your code is too long and the code may be cut off" if lines > 23
232
+ size
233
+ end
234
+
235
+ # Reads the code from the source file, returning
236
+ # the code, indented for markdown, as well as the number of lines
237
+ # and the width of the largest line
238
+ def self.read_code(source_file)
239
+ code = " @@@ #{lang(source_file)}\n"
240
+ lines = 0
241
+ width = 0
242
+ File.open(source_file) do |code_file|
243
+ code_file.readlines.each do |line|
244
+ code += " #{line}"
245
+ lines += 1
246
+ width = line.length if line.length > width
247
+ end
248
+ end
249
+ [code,lines,width]
250
+ end
251
+
252
+ def self.showoff_sections(dir,logger)
253
+ index = File.join(dir, ShowOffUtils.presentation_config_file)
254
+ sections = nil
255
+ if File.exists?(index)
256
+ data = JSON.parse(File.read(index))
257
+ logger.debug data
258
+ if data.is_a?(Hash)
259
+ sections = data['sections']
260
+ else
261
+ sections = data
262
+ end
263
+ sections = sections.map do |s|
264
+ if s.is_a? Hash
265
+ s['section']
266
+ else
267
+ s
268
+ end
269
+ end
270
+ else
271
+ sections = ["."] # if there's no showoff.json file, make a boring one
272
+ end
273
+ sections
274
+ end
275
+
276
+ def self.showoff_title(dir = '.')
277
+ get_config_option(dir, 'name', "Presentation")
278
+ end
279
+
280
+ def self.showoff_pdf_options(dir = '.')
281
+ opts = get_config_option(dir, 'pdf_options', {:page_size => 'Letter', :orientation => 'Landscape'})
282
+ Hash[opts.map {|k, v| [k.to_sym, v]}] # keys must be symbols
283
+ end
284
+
285
+ def self.get_config_option(dir, option, default = nil)
286
+ index = File.join(dir, ShowOffUtils.presentation_config_file)
287
+ if File.exists?(index)
288
+ data = JSON.parse(File.read(index))
289
+ if data.is_a?(Hash)
290
+ if default.is_a?(Hash)
291
+ default.merge(data[option] || default)
292
+ else
293
+ data[option] || default
294
+ end
295
+ end
296
+ else
297
+ default
298
+ end
299
+ end
300
+
301
+ EXTENSIONS = {
302
+ 'pl' => 'perl',
303
+ 'rb' => 'ruby',
304
+ 'erl' => 'erlang',
305
+ # so not exhaustive, but probably good enough for now
306
+ }
307
+
308
+ def self.lang(source_file)
309
+ ext = File.extname(source_file).gsub(/^\./,'')
310
+ EXTENSIONS[ext] || ext
311
+ end
312
+
313
+ REQUIRED_GEMS = %w(redcarpet showoff heroku)
314
+
315
+ # Creates the file that lists the gems for heroku
316
+ #
317
+ # filename - String name of the file
318
+ # password - Boolean to indicate if we are setting a password
319
+ # force - Boolean to indicate if we should overwrite the existing file
320
+ # formatter - Proc/lambda that takes 1 argument, the gem name, and formats it for the file
321
+ # This is so we can support both the old .gems and the new bundler Gemfile
322
+ # header - Proc/lambda that creates any header information in the file
323
+ #
324
+ # Returns a boolean indicating that we had to create the file or not.
325
+ def self.create_gems_file(filename,password,force,formatter,header=nil)
326
+ create_file_if_needed(filename,force) do |file|
327
+ file.puts header.call unless header.nil?
328
+ REQUIRED_GEMS.each { |gem| file.puts formatter.call(gem) }
329
+ file.puts formatter.call("rack") if password
330
+ end
331
+ end
332
+
333
+ # Creates the given filename if it doesn't exist or if force is true
334
+ #
335
+ # filename - String name of the file to create
336
+ # force - if true, the file will always be created, if false, only create
337
+ # if it's not there
338
+ # block - takes a block that will be given the file handle to write
339
+ # data into the file IF it's being created
340
+ #
341
+ # Examples
342
+ #
343
+ # create_file_if_needed("config.ru",false) do |file|
344
+ # file.puts "require 'showoff'"
345
+ # file.puts "run ShowOff.new"
346
+ # end
347
+ #
348
+ # Returns true if the file was created
349
+ def self.create_file_if_needed(filename,force)
350
+ if !File.exists?(filename) || force
351
+ File.open(filename, 'w+') do |f|
352
+ yield f
353
+ end
354
+ true
355
+ else
356
+ puts "#{filename} exists; not overwriting (see showoff help heroku)"
357
+ false
358
+ end
359
+ end
360
+ end
@@ -0,0 +1,653 @@
1
+ /*
2
+ 960 Grid System ~ Core CSS.
3
+ Learn more ~ http://960.gs/
4
+
5
+ Licensed under GPL and MIT.
6
+ */
7
+
8
+ /*
9
+ Forces backgrounds to span full width,
10
+ even if there is horizontal scrolling.
11
+ Increase this if your layout is wider.
12
+
13
+ Note: IE6 works fine without this fix.
14
+ */
15
+
16
+ body {
17
+ min-width: 960px;
18
+ }
19
+
20
+ /* `Container
21
+ ----------------------------------------------------------------------------------------------------*/
22
+
23
+ .container_12,
24
+ .container_16 {
25
+ margin-left: auto;
26
+ margin-right: auto;
27
+ width: 960px;
28
+ }
29
+
30
+ /* `Grid >> Global
31
+ ----------------------------------------------------------------------------------------------------*/
32
+
33
+ .grid_1,
34
+ .grid_2,
35
+ .grid_3,
36
+ .grid_4,
37
+ .grid_5,
38
+ .grid_6,
39
+ .grid_7,
40
+ .grid_8,
41
+ .grid_9,
42
+ .grid_10,
43
+ .grid_11,
44
+ .grid_12,
45
+ .grid_13,
46
+ .grid_14,
47
+ .grid_15,
48
+ .grid_16 {
49
+ display: inline;
50
+ float: left;
51
+ margin-left: 10px;
52
+ margin-right: 10px;
53
+ }
54
+
55
+ .push_1, .pull_1,
56
+ .push_2, .pull_2,
57
+ .push_3, .pull_3,
58
+ .push_4, .pull_4,
59
+ .push_5, .pull_5,
60
+ .push_6, .pull_6,
61
+ .push_7, .pull_7,
62
+ .push_8, .pull_8,
63
+ .push_9, .pull_9,
64
+ .push_10, .pull_10,
65
+ .push_11, .pull_11,
66
+ .push_12, .pull_12,
67
+ .push_13, .pull_13,
68
+ .push_14, .pull_14,
69
+ .push_15, .pull_15 {
70
+ position: relative;
71
+ }
72
+
73
+ .container_12 .grid_3,
74
+ .container_16 .grid_4 {
75
+ width: 220px;
76
+ }
77
+
78
+ .container_12 .grid_6,
79
+ .container_16 .grid_8 {
80
+ width: 460px;
81
+ }
82
+
83
+ .container_12 .grid_9,
84
+ .container_16 .grid_12 {
85
+ width: 700px;
86
+ }
87
+
88
+ .container_12 .grid_12,
89
+ .container_16 .grid_16 {
90
+ width: 940px;
91
+ }
92
+
93
+ /* `Grid >> Children (Alpha ~ First, Omega ~ Last)
94
+ ----------------------------------------------------------------------------------------------------*/
95
+
96
+ .alpha {
97
+ margin-left: 0;
98
+ }
99
+
100
+ .omega {
101
+ margin-right: 0;
102
+ }
103
+
104
+ /* `Grid >> 12 Columns
105
+ ----------------------------------------------------------------------------------------------------*/
106
+
107
+ .container_12 .grid_1 {
108
+ width: 60px;
109
+ }
110
+
111
+ .container_12 .grid_2 {
112
+ width: 140px;
113
+ }
114
+
115
+ .container_12 .grid_4 {
116
+ width: 300px;
117
+ }
118
+
119
+ .container_12 .grid_5 {
120
+ width: 380px;
121
+ }
122
+
123
+ .container_12 .grid_7 {
124
+ width: 540px;
125
+ }
126
+
127
+ .container_12 .grid_8 {
128
+ width: 620px;
129
+ }
130
+
131
+ .container_12 .grid_10 {
132
+ width: 780px;
133
+ }
134
+
135
+ .container_12 .grid_11 {
136
+ width: 860px;
137
+ }
138
+
139
+ /* `Grid >> 16 Columns
140
+ ----------------------------------------------------------------------------------------------------*/
141
+
142
+ .container_16 .grid_1 {
143
+ width: 40px;
144
+ }
145
+
146
+ .container_16 .grid_2 {
147
+ width: 100px;
148
+ }
149
+
150
+ .container_16 .grid_3 {
151
+ width: 160px;
152
+ }
153
+
154
+ .container_16 .grid_5 {
155
+ width: 280px;
156
+ }
157
+
158
+ .container_16 .grid_6 {
159
+ width: 340px;
160
+ }
161
+
162
+ .container_16 .grid_7 {
163
+ width: 400px;
164
+ }
165
+
166
+ .container_16 .grid_9 {
167
+ width: 520px;
168
+ }
169
+
170
+ .container_16 .grid_10 {
171
+ width: 580px;
172
+ }
173
+
174
+ .container_16 .grid_11 {
175
+ width: 640px;
176
+ }
177
+
178
+ .container_16 .grid_13 {
179
+ width: 760px;
180
+ }
181
+
182
+ .container_16 .grid_14 {
183
+ width: 820px;
184
+ }
185
+
186
+ .container_16 .grid_15 {
187
+ width: 880px;
188
+ }
189
+
190
+ /* `Prefix Extra Space >> Global
191
+ ----------------------------------------------------------------------------------------------------*/
192
+
193
+ .container_12 .prefix_3,
194
+ .container_16 .prefix_4 {
195
+ padding-left: 240px;
196
+ }
197
+
198
+ .container_12 .prefix_6,
199
+ .container_16 .prefix_8 {
200
+ padding-left: 480px;
201
+ }
202
+
203
+ .container_12 .prefix_9,
204
+ .container_16 .prefix_12 {
205
+ padding-left: 720px;
206
+ }
207
+
208
+ /* `Prefix Extra Space >> 12 Columns
209
+ ----------------------------------------------------------------------------------------------------*/
210
+
211
+ .container_12 .prefix_1 {
212
+ padding-left: 80px;
213
+ }
214
+
215
+ .container_12 .prefix_2 {
216
+ padding-left: 160px;
217
+ }
218
+
219
+ .container_12 .prefix_4 {
220
+ padding-left: 320px;
221
+ }
222
+
223
+ .container_12 .prefix_5 {
224
+ padding-left: 400px;
225
+ }
226
+
227
+ .container_12 .prefix_7 {
228
+ padding-left: 560px;
229
+ }
230
+
231
+ .container_12 .prefix_8 {
232
+ padding-left: 640px;
233
+ }
234
+
235
+ .container_12 .prefix_10 {
236
+ padding-left: 800px;
237
+ }
238
+
239
+ .container_12 .prefix_11 {
240
+ padding-left: 880px;
241
+ }
242
+
243
+ /* `Prefix Extra Space >> 16 Columns
244
+ ----------------------------------------------------------------------------------------------------*/
245
+
246
+ .container_16 .prefix_1 {
247
+ padding-left: 60px;
248
+ }
249
+
250
+ .container_16 .prefix_2 {
251
+ padding-left: 120px;
252
+ }
253
+
254
+ .container_16 .prefix_3 {
255
+ padding-left: 180px;
256
+ }
257
+
258
+ .container_16 .prefix_5 {
259
+ padding-left: 300px;
260
+ }
261
+
262
+ .container_16 .prefix_6 {
263
+ padding-left: 360px;
264
+ }
265
+
266
+ .container_16 .prefix_7 {
267
+ padding-left: 420px;
268
+ }
269
+
270
+ .container_16 .prefix_9 {
271
+ padding-left: 540px;
272
+ }
273
+
274
+ .container_16 .prefix_10 {
275
+ padding-left: 600px;
276
+ }
277
+
278
+ .container_16 .prefix_11 {
279
+ padding-left: 660px;
280
+ }
281
+
282
+ .container_16 .prefix_13 {
283
+ padding-left: 780px;
284
+ }
285
+
286
+ .container_16 .prefix_14 {
287
+ padding-left: 840px;
288
+ }
289
+
290
+ .container_16 .prefix_15 {
291
+ padding-left: 900px;
292
+ }
293
+
294
+ /* `Suffix Extra Space >> Global
295
+ ----------------------------------------------------------------------------------------------------*/
296
+
297
+ .container_12 .suffix_3,
298
+ .container_16 .suffix_4 {
299
+ padding-right: 240px;
300
+ }
301
+
302
+ .container_12 .suffix_6,
303
+ .container_16 .suffix_8 {
304
+ padding-right: 480px;
305
+ }
306
+
307
+ .container_12 .suffix_9,
308
+ .container_16 .suffix_12 {
309
+ padding-right: 720px;
310
+ }
311
+
312
+ /* `Suffix Extra Space >> 12 Columns
313
+ ----------------------------------------------------------------------------------------------------*/
314
+
315
+ .container_12 .suffix_1 {
316
+ padding-right: 80px;
317
+ }
318
+
319
+ .container_12 .suffix_2 {
320
+ padding-right: 160px;
321
+ }
322
+
323
+ .container_12 .suffix_4 {
324
+ padding-right: 320px;
325
+ }
326
+
327
+ .container_12 .suffix_5 {
328
+ padding-right: 400px;
329
+ }
330
+
331
+ .container_12 .suffix_7 {
332
+ padding-right: 560px;
333
+ }
334
+
335
+ .container_12 .suffix_8 {
336
+ padding-right: 640px;
337
+ }
338
+
339
+ .container_12 .suffix_10 {
340
+ padding-right: 800px;
341
+ }
342
+
343
+ .container_12 .suffix_11 {
344
+ padding-right: 880px;
345
+ }
346
+
347
+ /* `Suffix Extra Space >> 16 Columns
348
+ ----------------------------------------------------------------------------------------------------*/
349
+
350
+ .container_16 .suffix_1 {
351
+ padding-right: 60px;
352
+ }
353
+
354
+ .container_16 .suffix_2 {
355
+ padding-right: 120px;
356
+ }
357
+
358
+ .container_16 .suffix_3 {
359
+ padding-right: 180px;
360
+ }
361
+
362
+ .container_16 .suffix_5 {
363
+ padding-right: 300px;
364
+ }
365
+
366
+ .container_16 .suffix_6 {
367
+ padding-right: 360px;
368
+ }
369
+
370
+ .container_16 .suffix_7 {
371
+ padding-right: 420px;
372
+ }
373
+
374
+ .container_16 .suffix_9 {
375
+ padding-right: 540px;
376
+ }
377
+
378
+ .container_16 .suffix_10 {
379
+ padding-right: 600px;
380
+ }
381
+
382
+ .container_16 .suffix_11 {
383
+ padding-right: 660px;
384
+ }
385
+
386
+ .container_16 .suffix_13 {
387
+ padding-right: 780px;
388
+ }
389
+
390
+ .container_16 .suffix_14 {
391
+ padding-right: 840px;
392
+ }
393
+
394
+ .container_16 .suffix_15 {
395
+ padding-right: 900px;
396
+ }
397
+
398
+ /* `Push Space >> Global
399
+ ----------------------------------------------------------------------------------------------------*/
400
+
401
+ .container_12 .push_3,
402
+ .container_16 .push_4 {
403
+ left: 240px;
404
+ }
405
+
406
+ .container_12 .push_6,
407
+ .container_16 .push_8 {
408
+ left: 480px;
409
+ }
410
+
411
+ .container_12 .push_9,
412
+ .container_16 .push_12 {
413
+ left: 720px;
414
+ }
415
+
416
+ /* `Push Space >> 12 Columns
417
+ ----------------------------------------------------------------------------------------------------*/
418
+
419
+ .container_12 .push_1 {
420
+ left: 80px;
421
+ }
422
+
423
+ .container_12 .push_2 {
424
+ left: 160px;
425
+ }
426
+
427
+ .container_12 .push_4 {
428
+ left: 320px;
429
+ }
430
+
431
+ .container_12 .push_5 {
432
+ left: 400px;
433
+ }
434
+
435
+ .container_12 .push_7 {
436
+ left: 560px;
437
+ }
438
+
439
+ .container_12 .push_8 {
440
+ left: 640px;
441
+ }
442
+
443
+ .container_12 .push_10 {
444
+ left: 800px;
445
+ }
446
+
447
+ .container_12 .push_11 {
448
+ left: 880px;
449
+ }
450
+
451
+ /* `Push Space >> 16 Columns
452
+ ----------------------------------------------------------------------------------------------------*/
453
+
454
+ .container_16 .push_1 {
455
+ left: 60px;
456
+ }
457
+
458
+ .container_16 .push_2 {
459
+ left: 120px;
460
+ }
461
+
462
+ .container_16 .push_3 {
463
+ left: 180px;
464
+ }
465
+
466
+ .container_16 .push_5 {
467
+ left: 300px;
468
+ }
469
+
470
+ .container_16 .push_6 {
471
+ left: 360px;
472
+ }
473
+
474
+ .container_16 .push_7 {
475
+ left: 420px;
476
+ }
477
+
478
+ .container_16 .push_9 {
479
+ left: 540px;
480
+ }
481
+
482
+ .container_16 .push_10 {
483
+ left: 600px;
484
+ }
485
+
486
+ .container_16 .push_11 {
487
+ left: 660px;
488
+ }
489
+
490
+ .container_16 .push_13 {
491
+ left: 780px;
492
+ }
493
+
494
+ .container_16 .push_14 {
495
+ left: 840px;
496
+ }
497
+
498
+ .container_16 .push_15 {
499
+ left: 900px;
500
+ }
501
+
502
+ /* `Pull Space >> Global
503
+ ----------------------------------------------------------------------------------------------------*/
504
+
505
+ .container_12 .pull_3,
506
+ .container_16 .pull_4 {
507
+ left: -240px;
508
+ }
509
+
510
+ .container_12 .pull_6,
511
+ .container_16 .pull_8 {
512
+ left: -480px;
513
+ }
514
+
515
+ .container_12 .pull_9,
516
+ .container_16 .pull_12 {
517
+ left: -720px;
518
+ }
519
+
520
+ /* `Pull Space >> 12 Columns
521
+ ----------------------------------------------------------------------------------------------------*/
522
+
523
+ .container_12 .pull_1 {
524
+ left: -80px;
525
+ }
526
+
527
+ .container_12 .pull_2 {
528
+ left: -160px;
529
+ }
530
+
531
+ .container_12 .pull_4 {
532
+ left: -320px;
533
+ }
534
+
535
+ .container_12 .pull_5 {
536
+ left: -400px;
537
+ }
538
+
539
+ .container_12 .pull_7 {
540
+ left: -560px;
541
+ }
542
+
543
+ .container_12 .pull_8 {
544
+ left: -640px;
545
+ }
546
+
547
+ .container_12 .pull_10 {
548
+ left: -800px;
549
+ }
550
+
551
+ .container_12 .pull_11 {
552
+ left: -880px;
553
+ }
554
+
555
+ /* `Pull Space >> 16 Columns
556
+ ----------------------------------------------------------------------------------------------------*/
557
+
558
+ .container_16 .pull_1 {
559
+ left: -60px;
560
+ }
561
+
562
+ .container_16 .pull_2 {
563
+ left: -120px;
564
+ }
565
+
566
+ .container_16 .pull_3 {
567
+ left: -180px;
568
+ }
569
+
570
+ .container_16 .pull_5 {
571
+ left: -300px;
572
+ }
573
+
574
+ .container_16 .pull_6 {
575
+ left: -360px;
576
+ }
577
+
578
+ .container_16 .pull_7 {
579
+ left: -420px;
580
+ }
581
+
582
+ .container_16 .pull_9 {
583
+ left: -540px;
584
+ }
585
+
586
+ .container_16 .pull_10 {
587
+ left: -600px;
588
+ }
589
+
590
+ .container_16 .pull_11 {
591
+ left: -660px;
592
+ }
593
+
594
+ .container_16 .pull_13 {
595
+ left: -780px;
596
+ }
597
+
598
+ .container_16 .pull_14 {
599
+ left: -840px;
600
+ }
601
+
602
+ .container_16 .pull_15 {
603
+ left: -900px;
604
+ }
605
+
606
+ /* `Clear Floated Elements
607
+ ----------------------------------------------------------------------------------------------------*/
608
+
609
+ /* http://sonspring.com/journal/clearing-floats */
610
+
611
+ .clear {
612
+ clear: both;
613
+ display: block;
614
+ overflow: hidden;
615
+ visibility: hidden;
616
+ width: 0;
617
+ height: 0;
618
+ }
619
+
620
+ /* http://www.yuiblog.com/blog/2010/09/27/clearfix-reloaded-overflowhidden-demystified */
621
+
622
+ .clearfix:before,
623
+ .clearfix:after,
624
+ .container_12:before,
625
+ .container_12:after,
626
+ .container_16:before,
627
+ .container_16:after {
628
+ content: '.';
629
+ display: block;
630
+ overflow: hidden;
631
+ visibility: hidden;
632
+ font-size: 0;
633
+ line-height: 0;
634
+ width: 0;
635
+ height: 0;
636
+ }
637
+
638
+ .clearfix:after,
639
+ .container_12:after,
640
+ .container_16:after {
641
+ clear: both;
642
+ }
643
+
644
+ /*
645
+ The following zoom:1 rule is specifically for IE6 + IE7.
646
+ Move to separate stylesheet if invalid CSS is a problem.
647
+ */
648
+
649
+ .clearfix,
650
+ .container_12,
651
+ .container_16 {
652
+ zoom: 1;
653
+ }