Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

moved to puppetlabs

commit 1a97a4d896d58c3a3f2b5aedab82496646efa57a 1 parent 0e71227
@schacon authored
Showing with 6 additions and 8,574 deletions.
  1. +0 −18 CONTRIBUTING.md
  2. +0 −15 Gemfile
  3. +0 −9 JS_API.txt
  4. +0 −20 LICENSE
  5. +6 −0 README.md
  6. +0 −649 README.rdoc
  7. +0 −27 Rakefile
  8. +0 −34 TODO.txt
  9. +0 −189 bin/showoff
  10. +0 −5 example/four/01slide.md
  11. BIN  example/one/octocat.png
  12. +0 −34 example/one/slidesA.md
  13. +0 −50 example/one/slidesB.md
  14. +0 −15 example/showoff.json
  15. +0 −2  example/simple.tpl
  16. +0 −6 example/something.css
  17. +0 −30 example/three/js-events.md
  18. +0 −67 example/two/slidesA.md
  19. +0 −67 lib/commandline_parser.rb
  20. +0 −609 lib/showoff.rb
  21. +0 −3  lib/showoff/version.rb
  22. +0 −441 lib/showoff_utils.rb
  23. +0 −653 public/css/960.css
  24. +0 −114 public/css/fg.menu.css
  25. +0 −66 public/css/onepage.css
  26. +0 −78 public/css/presenter.css
  27. +0 −53 public/css/reset.css
  28. +0 −66 public/css/sh_style.css
  29. +0 −418 public/css/showoff.css
  30. BIN  public/css/spinner_bar.gif
  31. BIN  public/css/theme/images/ui-bg_diagonals-small_100_f0efea_40x40.png
  32. BIN  public/css/theme/images/ui-bg_flat_35_f0f0f0_40x100.png
  33. BIN  public/css/theme/images/ui-bg_glass_55_fcf0ba_1x400.png
  34. BIN  public/css/theme/images/ui-bg_glow-ball_25_2e2e28_600x600.png
  35. BIN  public/css/theme/images/ui-bg_highlight-soft_100_f0efea_1x100.png
  36. BIN  public/css/theme/images/ui-bg_highlight-soft_25_327E04_1x100.png
  37. BIN  public/css/theme/images/ui-bg_highlight-soft_25_5A9D1A_1x100.png
  38. BIN  public/css/theme/images/ui-bg_highlight-soft_95_ffedad_1x100.png
  39. BIN  public/css/theme/images/ui-bg_inset-soft_22_3b3b35_1x100.png
  40. BIN  public/css/theme/images/ui-icons_808080_256x240.png
  41. BIN  public/css/theme/images/ui-icons_8DC262_256x240.png
  42. BIN  public/css/theme/images/ui-icons_cd0a0a_256x240.png
  43. BIN  public/css/theme/images/ui-icons_e7e6e4_256x240.png
  44. BIN  public/css/theme/images/ui-icons_eeeeee_256x240.png
  45. BIN  public/css/theme/images/ui-icons_ffffff_256x240.png
  46. +0 −9 public/css/theme/ui.accordion.css
  47. +0 −2  public/css/theme/ui.all.css
  48. +0 −9 public/css/theme/ui.base.css
  49. +0 −37 public/css/theme/ui.core.css
  50. +0 −62 public/css/theme/ui.datepicker.css
  51. +0 −13 public/css/theme/ui.dialog.css
  52. +0 −4 public/css/theme/ui.progressbar.css
  53. +0 −13 public/css/theme/ui.resizable.css
  54. +0 −17 public/css/theme/ui.slider.css
  55. +0 −9 public/css/theme/ui.tabs.css
  56. +0 −245 public/css/theme/ui.theme.css
  57. BIN  public/favicon.ico
  58. +0 −8 public/js/coffee-script.js
  59. +0 −79 public/js/core.js
  60. +0 −645 public/js/fg.menu.js
  61. +0 −26 public/js/jTypeWriter.js
  62. +0 −4 public/js/jquery-1.7.2.min.js
  63. +0 −109 public/js/jquery-print.js
  64. +0 −56 public/js/jquery.batchImageLoad.js
  65. +0 −96 public/js/jquery.cookie.js
  66. +0 −1,284 public/js/jquery.cycle.all.js
  67. +0 −105 public/js/jquery.doubletap-0.1.js
  68. +0 −24 public/js/jquery.uuid.js
  69. +0 −201 public/js/jquery.ws-0.3pre.js
  70. +0 −4 public/js/onepage.js
  71. +0 −204 public/js/presenter.js
  72. +0 −1  public/js/sh_lang/sh_bison.min.js
  73. +0 −1  public/js/sh_lang/sh_c.min.js
  74. +0 −1  public/js/sh_lang/sh_caml.min.js
  75. +0 −1  public/js/sh_lang/sh_changelog.min.js
  76. +0 −1  public/js/sh_lang/sh_coffeescript.min.js
  77. +0 −1  public/js/sh_lang/sh_cpp.min.js
  78. +0 −1  public/js/sh_lang/sh_csharp.min.js
  79. +0 −1  public/js/sh_lang/sh_css.min.js
  80. +0 −2  public/js/sh_lang/sh_cucumber.min.js
  81. +0 −1  public/js/sh_lang/sh_desktop.min.js
  82. +0 −1  public/js/sh_lang/sh_diff.min.js
  83. +0 −1  public/js/sh_lang/sh_erlang.min.js
  84. +0 −1  public/js/sh_lang/sh_flex.min.js
  85. +0 −112 public/js/sh_lang/sh_gherkin.js
  86. +0 −1  public/js/sh_lang/sh_gherkin.min.js
  87. +0 −1  public/js/sh_lang/sh_glsl.min.js
  88. +0 −1  public/js/sh_lang/sh_haxe.min.js
  89. +0 −1  public/js/sh_lang/sh_html.min.js
  90. +0 −1  public/js/sh_lang/sh_java.min.js
  91. +0 −1  public/js/sh_lang/sh_javascript.min.js
  92. +0 −1  public/js/sh_lang/sh_javascript_dom.min.js
  93. +0 −1  public/js/sh_lang/sh_latex.min.js
  94. +0 −1  public/js/sh_lang/sh_ldap.min.js
  95. +0 −1  public/js/sh_lang/sh_log.min.js
  96. +0 −1  public/js/sh_lang/sh_lsm.min.js
  97. +0 −1  public/js/sh_lang/sh_m4.min.js
  98. +0 −1  public/js/sh_lang/sh_makefile.min.js
  99. +0 −1  public/js/sh_lang/sh_oracle.min.js
  100. +0 −1  public/js/sh_lang/sh_pascal.min.js
  101. +0 −1  public/js/sh_lang/sh_perl.min.js
  102. +0 −1  public/js/sh_lang/sh_php.min.js
  103. +0 −1  public/js/sh_lang/sh_prolog.min.js
  104. +0 −1  public/js/sh_lang/sh_properties.min.js
  105. +0 −1  public/js/sh_lang/sh_python.min.js
  106. +0 −1  public/js/sh_lang/sh_ruby.min.js
  107. +0 −1  public/js/sh_lang/sh_scala.min.js
  108. +0 −1  public/js/sh_lang/sh_sh.min.js
  109. +0 −1  public/js/sh_lang/sh_slang.min.js
  110. +0 −1  public/js/sh_lang/sh_sml.min.js
  111. +0 −1  public/js/sh_lang/sh_spec.min.js
  112. +0 −1  public/js/sh_lang/sh_sql.min.js
  113. +0 −1  public/js/sh_lang/sh_tcl.min.js
  114. +0 −1  public/js/sh_lang/sh_xml.min.js
  115. +0 −1  public/js/sh_lang/sh_xorg.min.js
  116. +0 −4 public/js/sh_main.min.js
  117. +0 −681 public/js/showoff.js
  118. +0 −13 public/js/showoffcore.js
  119. +0 −62 script/_showoff
  120. +0 −46 script/import_images.rb
  121. +0 −38 showoff.gemspec
  122. +0 −21 test/bare_test.rb
  123. +0 −62 test/basic_test.rb
  124. +0 −9 test/fixtures/bare/slides.md
  125. +0 −11 test/fixtures/image/one/01_slide.md
  126. BIN  test/fixtures/image/one/chacon.jpg
  127. +0 −1  test/fixtures/image/showoff.json
  128. +0 −16 test/fixtures/maruku/one/01_slide.md
  129. +0 −7 test/fixtures/maruku/showoff.json
  130. +0 −15 test/fixtures/simple/one/01_slide.md
  131. +0 −5 test/fixtures/simple/showoff.json
  132. +0 −43 test/markdown_test.rb
  133. +0 −73 test/test_helper.rb
  134. +0 −85 test/utils_test.rb
  135. +0 −46 views/header.erb
  136. +0 −50 views/index.erb
  137. +0 −57 views/onepage.erb
  138. +0 −70 views/presenter.erb
View
18 CONTRIBUTING.md
@@ -1,18 +0,0 @@
-Contributing
-======================
-
-To contribute to the ShowOff project:
-
-* Fork schacon/showoff
-
-* Use the ShowOff project in the 'example/' subdirectory to
- add an example of new features or make sure you haven't
- broken existin functionality. I basically use this preso
- as my unit tests.
-
-* Push your contribution to a branch named after your change
- ie: git push origin master:fixed-static-links
-
-* Send me a pull request through GitHub with a description of
- what you are contributing.
-
View
15 Gemfile
@@ -1,15 +0,0 @@
-source "https://rubygems.org"
-
-gemspec
-
-group :development do
- gem "mg"
- gem "turn"
- gem "rack-test"
- gem "pdf-inspector"
-end
-
-group :optional do
- gem "rmagick"
- gem "pdfkit"
-end
View
9 JS_API.txt
@@ -1,9 +0,0 @@
-getSlideProgress() - returns string '5/18'
-getCurrentNotes() - returns string of current notes
-gotoSlide(num)
-getSlidePercent() - returns int
-prevStep()
-nextStep()
-toggleFooter()
-togglePreshow()
-executeAnyCode()
View
20 LICENSE
@@ -1,20 +0,0 @@
-Copyright (c) 2009 Scott Chacon
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
6 README.md
@@ -0,0 +1,6 @@
+# Showoff Has Moved
+
+Puppetlabs is now maintaining [Showoff](https://github.com/puppetlabs/showoff). I keep this repo here only to preserve the issues and whatnot. Puppetlabs maintains the Gem and is now the parent of this network.
+
+Thanks!
+Scott
View
649 README.rdoc
@@ -1,649 +0,0 @@
-= ShowOff Presentation Software
-
-ShowOff is a Sinatra web app that reads simple configuration files for a
-presentation. It is sort of like a Keynote web app engine - think S5 +
-Slidedown. I am using it to do all my talks in 2010, because I have a deep
-hatred in my heart for Keynote and yet it is by far the best in the field.
-
-The idea is that you setup your markdown slide files in section subdirectories
-and then startup the showoff server in that directory. It will read in your
-<tt>showoff.json</tt> file for which sections go in which order and then will give
-you a URL to present from.
-
-It can:
-
-* show simple text
-* show images
-* show syntax highlighted code
-* bullets with incremental advancing
-* re-enact command line interactions
-* call up a menu of sections/slides at any time to jump around
-* execute Javascript, Coffeescript or Ruby live and display results
-* do simple transitions (instant, fade, slide in)
-* show a pre-show slideshow while you wait to start
-
-It might will can:
-
-* show a timer - elapsed / remaining
-* perform simple animations of images moving between keyframes
-* show synchronized, hidden notes on another browser (like an iphone)
-* show audience questions / comments (twitter or direct)
-* let audience members go back / catch up as you talk
-* let audience members vote on sections (?)
-* broadcast itself on Bonjour
-* let audience members download slides, code samples or other supplementary material
-* let you write on the slide with your mouse, madden-style via canvas
-* automatically resize text to fit screen [see Alex's shrink.js]
-
-Some of the nice things are that you can easily version control it, you
-can easily move sections between presentations, and you can rearrange or
-remove sections easily.
-
-= Usage
-
-ShowOff is meant to be run in a ShowOff formatted repository - that means that
-it has a <tt>showoff.json</tt> file and a number of sections (subdirectories) with
-markdown files for the slides you're presenting.
-
- $ gem install showoff
- $ git clone (showoff-repo)
- $ cd (showoff-repo)
- $ showoff serve
-
-If you run 'showoff' in the example subdirectory of ShowOff itself, it will
-show an example presentation, so you can see what it's like.
-
-You can also run 'showoff serve' inside a section subdirectory. If there is no
-<tt>showoff.json</tt> file then it will make its best guess, creating a presentation
-from all `.md` files in alphabetical order in the given (or current)
-directory.
-
-= Slide Format
-
-You can break your slides up into sections of however many subdirectories deep
-you need. ShowOff will recursively check all the directories mentioned in
-your <tt>showoff.json</tt> file for any markdown files (.md). Each markdown file can
-have any number of slides in it, separating each slide with the '!SLIDE'
-keyword and optional slide styles.
-
-For example, if you run 'showoff create my_new_pres' it will create a new
-starter presentation for you with one .md file at one/slide.md which will have
-the following contents:
-
- !SLIDE
-
- # My Presentation #
-
- !SLIDE bullets incremental transition=fade
-
- # Bullet Points #
-
- * first point
- * second point
- * third point
-
-That represents two slides, the first contains just a large title, and the
-second is faded into view showing the title and three bullets that are then
-incrementally shown. In order for ShowOff to see those slides, your
-<tt>showoff.json</tt> file needs to look something like this:
-
- {
- "name": "Something",
- "description": "Example Presentation",
- "sections": [
- {"section":"one"}
- ]
- }
-
-If you have multiple sections in your talk, you can make this json
-array include all the sections you want to show in which order you
-want to show them. Template configuration is done in
-<tt>showoff.json</tt> as well.
-
-Instead of a hash, you can use a plain string as an entry in the
-<tt>sections</tt> section of <tt>showoff.json</tt>. And if that plain string starts
-with '#' then it is interpreted not as a filename, but as
-markdown. This is used for inserting interstitial slides or notes --
-for instance, Alex Chaffee's {Ruby
-Notes}[http://github.com/alexch/ruby_notes] uses it to insert lab
-instructions between lecture slide sections, which may vary from venue
-to venue.
-
-If you want to keep the ability to emit an HTML document from your
-Markdown source file -- say, for a TextMate preview or a GitHub rendering
--- you can use angle brackets around the `!SLIDE` keyword and styles, e.g.
-
- <!SLIDE bullets incremental transition=fade>
-
-Some useful styles for each slide are:
-
-* center - centers images on a slide
-* full-page - allows an image to take up the whole slide
-* bullets - sizes and separates bullets properly (fits up to 5, generally)
-* smbullets - sizes and separates more bullets (smaller, closer together)
-* subsection - creates a different background for titles
-* command - monospaces h1 title slides
-* commandline - for pasted commandline sections (needs leading '$' for commands, then output on subsequent lines)
-* code - monospaces everything on the slide
-* incremental - can be used with 'bullets' and 'commandline' styles, will incrementally update elements on arrow key rather than switch slides
-* small - make all slide text 80%
-* smaller - make all slide text 70%
-* execute - on Javascript, Coffeescript and Ruby highlighted code slides, you can click on the code to execute it and display the results on the slide
-
-Check out the example directory included to see examples of most of these.
-
-Transitions can be supplied through the use of transition=tname on the !SLIDE
-definition, where tname is one of the following supported transitions:
-
-* blindX
-* blindY
-* blindZ
-* cover
-* curtainX
-* curtainY
-* fade
-* fadeZoom
-* growX
-* growY
-* none (this is the default)
-* scrollUp
-* scrollDown
-* scrollLeft
-* scrollRight
-* scrollHorz
-* scrollVert
-* shuffle
-* slideX
-* slideY
-* toss
-* turnUp
-* turnDown
-* turnLeft
-* turnRight
-* uncover
-* wipe
-* zoom
-
-The transitions are provided by jQuery Cycle plugin. See http://www.malsup.com/jquery/cycle/browser.html to view the effects and http://www.malsup.com/jquery/cycle/adv2.html for how to add custom effects.
-
-Here's a list of other available keywords:
-
-* skip - Skips slides marked with this keyword
-
-You can manage the presentation with the following keys:
-
-* space, cursor right: next slide
-* shift-space, cursor left: previous slide
-* d: debug mode
-* c, t: table of contents (vi)
-* f: toggle footer
-* z, ?: toggle help
-* p: toggle preshow
-
-= Showing plain old markdown
-
-If a markdown file has no !SLIDE keywords, then showoff will treat every line
-beginning with a single hash -- i.e. every H1 -- as a new slide in "bullets"
-style. Remember that you can't specify classes or transitions in this mode,
-and as soon as you add one !SLIDE you need them everywhere.
-
-= Preshow
-
-If you want to show a slideshow while you wait to speak, you can run a preshow. Add a +_preshow+ directory
-to your project (I use a symlink, so I don't have to add all the images into Git), put a bunch of images in the +_preshow+ directory and optionally add a +preshow+.+json+ file that provides descriptions for any of the images.
-If you then press 'p' at the beginning of your presentation, it will prompt you for a number of minutes until
-you start. Then it will count down the time until then, flipping through your pictures to entertain the
-audience in the meantime. Press 'p' again to stop, or wait until the timer runs out.
-
-= Custom JavaScript
-
-To insert custom JavaScript into your presentation you can either place it into
-a file (with extension .js) into the root directory of your presentation or you
-can embed a <+script+> element directly into your slides. This JavaScript will be
-executed—as usually—as soon as it is loaded.
-
-If you want to trigger some JavaScript as soon as a certain page is shown or
-when you switch to the next or previous slide, you can bind a callback to a
-custom event:
-
-* *showoff:show* will be triggered as soon as you enter a page
-* *showoff:next* will be triggered when you switch to the next page
-* *showoff:incr* will be triggered when you advance to the next increment on the page
-* *showoff:prev* will be triggered when you switch to the previous page
-
-These events are triggered on the "div.content" child of the slide, so you must
-add a custom and unique class to your SLIDE to identify it:
-
- !SLIDE custom_and_unique_class
- # 1st Example h1
- <script>
- // bind to custom event
- $(".custom_and_unique_class").bind("showoff:show", function (event) {
- // animate the h1
- var h1 = $(event.target).find("h1");
- h1.delay(500)
- .slideUp(300, function () { $(this).css({textDecoration: "line-through"}); })
- .slideDown(300);
- });
- </script>
-
-This will bind an event handler for *showoff:show* to your slide. The
-h1-element will be animated, as soon as this event is triggered on that slide.
-
-If you bind an event handler to the custom events *showoff:next* or
-*showoff:prev*, you can prevent the default action (that is switching to the
-appropriate slide) by calling *event.preventDefault()*:
-
- !SLIDE prevent_default
- # 2nd Example h1
- <script>
- $(".prevent_default").bind("showoff:next", function (event) {
- var h1 = $(event.target).find("h1");
- if (h1.css("text-decoration") === "none") {
- event.preventDefault();
- h1.css({textDecoration: "line-through"})
- }
- });
- </script>
-
-This will bind an event handler for *showoff:next* to your slide. When you press
-the right arrow key the first time, the h1-element will be decorated. When you
-press the right array key another time, you will switch to the next slide.
-
-The same applies to the *showoff:prev* event, of course.
-
-
-= Custom Stylesheets
-
-To insert custom Stylesheets into your presentation you can either place it into
-a file (with extension .css) into the root directory of your presentation or
-you can embed a <+link+> element directly into your slides. This stylesheet will
-be applied as soon as it is loaded.
-
-The content generated by the slide is wrapped with a +div+ with the class .+content+ like this.
-
- <div ref="intro/01_slide/1" class="content" style="margin-top: 210px;">
- <h1>jQuery &amp; Sinatra</h1>
- <h2>A Classy Combination</h2>
- </div>
-
-This makes the .+content+ tag a perfect place to add additional styling if that
-is your preference. An example of adding some styling is here.
-
- .content {
- color: black;
- font-family: helvetica, arial;
- }
- h1, h2 {
- color: rgb(79, 180, 226);
- font-family: Georgia;
- }
- .content::after {
- position: absolute;
- right: 120px;
- bottom: 120px;
- content: url(jay_small.png);
- }
-
-Note that the example above uses CSS3 styling with ::+after+ and the +content+
--attribute to add an image to the slides.
-
-= Templates
-
-Templates can come handy if you need more than what you can achieve
-via CSS. To configure templates you'll have to specify them in the
-<tt>showoff.json</tt> by adding an entry called "templates". This
-entry is an object where you can specify as many templates as you
-want. The default template is marked with the "default" key.
-
- {
- "name": "Something",
- "description": "Example Presentation",
- "templates" : {
- "default" : "tpl1.tpl",
- "special" : "tpl2.tpl"
- },
- "sections": [
- {"section":"one"}
- ]
- }
-
-If the "default" key is not given, no template will be used for the
-default slide. If you want to apply a certain layout to a slide you
-have to specify it in the slide header:
-
- !SLIDE[tpl=special]
- # Header
-
-== Template Commands
-
-You can place content anywhere in your template, but you have to
-explicitly mark the location using a special command:
-
-[~~~CONTENT~~~] is replaced by the slide content
-
-[~~~CURRENT_SLIDE~~~] is replaced by the current slide number
-
-[~~~NUM_SLIDES~~~] is replaced by the total number of slides
-
-[~~~CONFIG:*~~~] is replaced by any value (*) from the <tt>showoff.json</tt> configuration. This can be used to specify an author, venue, etc. A simple example would be <tt>~~~CONFIG:author~~~</tt>
-
-The usage of these replacements is not limited to templates, but
-anywhere in your slides.
-
-== Template Hints
-
-You can basically put everything you want into templates, but you
-should make sure that the CSS is applied fine. The best way to apply a
-custom layout is to create a container that uses absolute positioning
-and has width and height set to 100% which are then derived from the
-parent slide element.
-
-= Language highlighting
-
-Showoff uses {shjs}[http://shjs.sourceforge.net/] to highlight code blocks.
-If you begin a code block with three @-signs followed by a
-{programming language name}[http://shjs.sourceforge.net/doc/documentation.html],
-that line will be stripped and the rest of the block will become sparkly
-and colorful.
-
- @@@ ruby
- 10.times { puts "Whee!" }
-
-= Custom Ruby Files
-
-If you want to have executable Ruby code on your slides you must set the
-environment variable ENV['SHOWOFF_EVAL_RUBY']. This can be done with
-
- export SHOWOFF_EVAL_RUBY=1
-
-or
-
- # On Heroku
- heroku config:add SHOWOFF_EVAL_RUBY=1
-
-
-If you need supporting libraries when you evaluate the code. You can do this by
-putting Ruby files (*.rb) into the root directory of the presentation then they
-will be required when the presentation loads.
-
-= Presenter Notes
-
-Add a line that starts with .notes:
-
- .notes my notes here
-
-Toggle presenter notes with the n key while in the presentation.
-
-= Editor integration
-
-The "add slide" feature can allow you to add the necessary boilerplate from your editor. If you are using vim, you can
-
- !showoff add -t code Check This Code
-
-And your buffer will get
-
- !SLIDE
- # Check This Code #
- @@@ Ruby
- code_here()
-
-added where your cursor was. Binding this to a keybinding can allow you to add new slides quickly.
-
-= Command Line Interface
-
- showoff command_name [command-specific options] [--] arguments...
-
-* Use the command +help+ to get a summary of commands
-* Use the command <tt>help command_name</tt> to get a help for +command_name+
-* Use <tt>--</tt> to stop command line argument processing; useful if your arguments have dashes in them
-
-== Commands
-[<tt>add</tt>] Add a new slide at the end in a given dir
-[<tt>create</tt>] Create new showoff presentation
-[<tt>help</tt>] Shows list of commands or help for one command
-[<tt>heroku</tt>] Setup your presentation to serve on Heroku
-[<tt>github</tt>] Setup your presentation to serve on GitHub Pages
-[<tt>serve</tt>] Serves the showoff presentation in the current directory (or a given dir)
-[<tt>static</tt>] Generate static version of presentation
-
-
-== <tt>showoff add [title]</tt>
-
-Add a new slide at the end in a given dir
-
-*Aliases*
-* <tt><b>new</b></tt>
-
-Outputs or creates a new slide. With -d and -n, a new slide is created in the given dir, numbered to appear
-as the last slide in that dir (use -u to avoid numbering). Without those, outputs the slide markdown to
-stdout (useful for shelling out from your editor). You may also specify a source file to use for a code
-slide.
-
-=== options for add
-
-These options are specified *after* the command.
-
-[<tt>-d, --dir=dir</tt>] Slide dir (where to put a new slide file)
-[<tt>-n, --name=basename</tt>] Slide name (name of the new slide file)
-[<tt>-s, --source=path to file</tt>] Include code from the given file as the slide body
-[<tt>-t, --style, --type=valid showoff style/type</tt>] Slide Type/Style <i>( default: <tt>title</tt>)</i>
-[<tt>-u, --nonumber</tt>] Dont number the slide, use the given name verbatim
-
-
-== <tt>showoff create dir_name</tt>
-
-Create new showoff presentation
-
-*Aliases*
-* <tt><b>init</b></tt>
-
-This command helps start a new showoff presentation by setting up the proper directory structure for you. It takes the directory name you would like showoff to create for you.
-
-=== options for create
-
-These options are specified *after* the command.
-
-[<tt>-d, --slidedir=arg</tt>] sample slide directory name <i>( default: <tt>one</tt>)</i>
-[<tt>-n, --nosamples</tt>] Dont create sample slides
-
-
-== <tt>showoff help [command]</tt>
-
-Shows list of commands or help for one command
-
-
-== <tt>showoff heroku heroku_name</tt>
-
-Setup your presentation to serve on Heroku
-
-Creates the Gemfile and config.ru file needed to push a showoff pres to heroku. It will then run heroku create for you to register the new project on heroku and add the remote for you. Then all you need to do is commit the new created files and run git push heroku to deploy.
-
-
-== <tt>showoff github</tt>
-
-Generates a static version of your site and puts it in a gh-pages branch for static serving on GitHub.
-
-=== options for github
-These options are specified *after* the command.
-
-[<tt>-f, --force</tt>] force overwrite of existing Gemfile/.gems and config.ru files if they exist
-[<tt>-g, --dotgems</tt>] Use older-style .gems file instead of bundler-style Gemfile
-[<tt>-p, --password=arg</tt>] add password protection to your heroku site
-
-
-== <tt>showoff serve </tt>
-
-Serves the showoff presentation in the current directory
-
-==== options for serve
-These options are specified *after* the command.
-
-[<tt>-f, --pres_file=arg</tt>] Presentation file <i>(default: <tt>showoff.json</tt>)</i>
-[<tt>-h, --host=arg</tt>] Host or ip to run on <i>( default: <tt>localhost</tt>)</i>
-[<tt>-p, --port=arg</tt>] Port on which to run <i>( default: <tt>9090</tt>)</i>
-
-
-== <tt>showoff static name</tt>
-
-Generate static version of presentation
-
-= PDF Output
-
-Showoff can produce a PDF version of your presentation. To do this, you must install a few things first:
-
- gem install pdfkit
-
-You'll then need to install a version of wkhtmltopdf available at the {wkhtmltopdf repo}[http://code.google.com/p/wkhtmltopdf/wiki/compilation] (or brew install wkhtmltopdf on a mac) and make sure that +wkhtmltopdf+ is in your path:
-
- export $PATH="/location/to/my/wkhtmltopdf/0.9.9:$PATH"
-
-
-
-Then restart showoff, and navigate to <tt>/pdf</tt> (e.g. http://localhost/pdf) of your presentation and a PDF will be generated with the browser.
-
-= Misc
-
-== Markdown Engine
-
-It is possible to configure the markdown engine of your choice to use
-with showoff. The following engines are available:
-
-* redcarpet (default)
-* bluecloth
-* maruku
-* kramdown
-* rdiscount
-
-Configuring an engine (or overriding it's default configuration) allows you to access special features of that engine.
-
-=== Maruku
-
-When you prefer using Maruku as the markdown engine of choice for your
-presentation, you can use the LaTeX Math Mode features of
-maruku. First you need
-{BlahTex}[http://www.mediawiki.org/wiki/Extension:Blahtex] and then
-you need to configure your presentation as following:
-
- {
- /* other configuration options */,
- "markdown" : "maruku",
- "maruku" : {
- "use_tex" : true, /* required if you want to use LaTeX */
- "png_dir" : "images", /* optional */
- "html_png_url" : "/file/images/" /* optional */
- }
- }
-
-= Completion
-
-== ZSH completion
-You can complete commands and options in ZSH, by installing a script:
-
- mkdir -p $HOME/.zsh/Completion
- cp script/_showoff $HOME/.zsh/Completion
- echo 'fpath=(~/.zsh/Completion $fpath)' >> $HOME/.zshrc
-
-== <tt>bash</tt> completion
-
-You can complete commands for showoff by putting the following in your <tt>.bashrc</tt> (or whatever
-you use when starting <tt>bash</tt>):
-
- complete -F get_showoff_commands
- function get_showoff_commands()
- {
- if [ -z $2 ] ; then
- COMPREPLY=(`showoff help -c`)
- else
- COMPREPLY=(`showoff help -c $2`)
- fi
- }
-
-= Real World Usage
-
-So far, ShowOff has been used in the following presentations (and many others):
-
-* LinuxConf.au 2010 - Wrangling Git - Scott Chacon
- http://github.com/schacon/showoff-wrangling-git
-* SF Ruby Meetup - Resque! - Chris Wanstrath
- http://github.com/defunkt/sfruby-meetup-resque
-* RORO Sydney Talk, Feb 2010 - Beyond Actions - Dave Bolton
- http://github.com/lightningdb/roro-syd-beyond-actions
-* LRUG's February meeting - Showing Off with Ruby - Joel Chippindale
- http://github.com/mocoso/showing-off-with-ruby
-* PyCon 2010 - Hg and Git; Can't we all just get along? - Scott Chacon
- http://github.com/schacon/pycon-hg-git
-* PdxJs Tech Talk - Asynchronous Coding For My Tiny Ruby Brain - Rick Olson
- http://github.com/technoweenie/pdxjs-twitter-node
-* RORO Perth Talk - Rails 3; A Brief Introduction Darcy Laycock
- http://github.com/Sutto/roro-perth-rails-3
-* PDXRB Tech Talk - Here's Sinatra - Jesse Cooke
- http://github.com/jc00ke/pdxrb_sinatra
-* Red Dirt Ruby Conference May 2010 - Plain Old Tokyo Storage - Jeremy Hinegardner
- http://github.com/copiousfreetime/plain-old-tokyo-storage-presentation
- http://plain-old-tokyo-storage.heroku.com/
-* Lambda Lounge and StrangeLoop 2010 - JavaScript Functions : The Good Parts - Idioms for Encapsulation and Inheritance - Scott Bale
- http://github.com/scottbale/JavaScript-Function-Idioms
-* Open Source Bridge 2010 - Creating a low-cost clustered virtualization environment w/ Ganeti - Lance Albertson
- http://github.com/ramereth/presentation-ganeti
-* RailsConf 2010 - Domain-driven Test-assisted Production Rails Crisis Interventions - Rick Bradley
- http://railsconf2010.rickbradley.com/ http://github.com/rick/presentation_railsconf_2010
-* WebWorkersCamp - 25 promising projects in 50 minutes - Bruno Michel
- http://github.com/nono/Presentations/tree/master/20100703_25_promising_projects_in_50_minutes/
-* 11th Libre Software Meeting 2010 - Ruby 1.9, The future of Ruby? - Bruno Michel
- http://github.com/nono/Presentations/tree/master/20100708_RMLL_Ruby_1.9/
-* Lone Star PHP 2011 - Drupal - Chris Christensen
- https://github.com/christianchristensen/Presentations/tree/master/20110611-lonestarphp-drupal
-* Railsbridge Open Workshops - Sarah Allen, Sarah Mei, and Alex Chaffee
- http://github.com/alexch/workshop
-* SDRuby Lightning Talk - Readable Regexps - Ian Young
- https://github.com/iangreenleaf/sdruby-lightningtalk-tregexp
-* Disney HTML5 Summit 2011 - Polyfills: Shims and Shivs - Josh Dzielak
- https://github.com/dzello/shims_and_shivs
-
-
-If you use it for something, please let me know so I can add it.
-
-= Editor Support
-
-* TextMate Bundle - Showoff.tmdbundle - Dr Nic Williams
- http://github.com/drnic/Showoff.tmbundle
-
-* Emacs major-mode - showoff-mode - Nick Parker
- http://github.com/developernotes/showoff-mode
-
-= Future Plans
-
-I really want this to evolve into a dynamic presentation software server,
-that gives the audience a lot of interaction into the presentation -
-helping them decide dynamically what the content of the presentation is,
-ask questions without interupting the presenter, etc. I want the audience
-to be able to download a dynamically generated PDF of either the actual
-talk that was given, or all the available slides, plus supplementary
-material. And I want the presenter (me) to be able to push each
-presentation to Heroku or GitHub pages for archiving super easily.
-
-= Why Not S5 or Slidy or Slidedown?
-
-S5 and Slidy are really cool, and I was going to use them, but mainly I wanted
-something more dynamic. I wanted Slidy + Slidedown, where I could write my
-slideshows in a structured format in sections, where the sections could easily
-be moved around and between presentations and could be written in Markdown. I
-also like the idea of having interactive presentation system and didn't need
-half the features of S5/Slidy (style based print view, auto-scaling, themes,
-etc).
-
-= Requirements
-
-* Ruby (duh)
-* Sinatra (and thus Rack)
-* BlueCloth
-* Nokogiri
-* json
-* GLI gem
-* Firefox or Chrome to present
-* PDFKit (optional, for generating PDF of presentation) https://github.com/jdpace/PDFKit
-
-= Contributing
-
-See the CONTRIB.txt file for how to contribute to this project
View
27 Rakefile
@@ -1,27 +0,0 @@
-require 'rake/testtask'
-
-begin
- require 'mg'
-rescue LoadError
- abort "Please `gem install mg`"
-end
-
-MG.new("showoff.gemspec")
-
-#
-# Tests
-#
-
-task :default => :test
-
-desc "Run tests"
-task :turn do
- suffix = "-n #{ENV['TEST']}" if ENV['TEST']
- sh "turn test/*_test.rb #{suffix}"
-end
-
-Rake::TestTask.new do |t|
- t.libs << 'lib'
- t.pattern = 'test/**/*_test.rb'
- t.verbose = false
-end
View
34 TODO.txt
@@ -1,34 +0,0 @@
-TODO
-=================
-
-==
-
-- pdf with notes
-- presenter view
- - timer (time left, percent done, percent time done)
-- editing slides
-- webpage
-
---
-
-- clean up js
-- clean up ruby
-
-
-==
-
-- can have showoff.json in each subdir
-- showoff add
- - add slides of images directory (refactor script/import_images.rb)
-- simple highlighting (highlight region of slide / click to highlight)
-- presenter tools
- - preview column
- - preview
-- audience interface
- - slide download / git clone
- - static version download
- - questions / comments system
- - audience vote-based presentation builder, results live view
-- simple animations (image from A to B)
-- squeeze-to-fit style
-- extract Version into a separate file, so we can include it in gemspec without pulling in the universe
View
189 bin/showoff
@@ -1,189 +0,0 @@
-#! /usr/bin/env ruby
-
-$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
-require 'showoff'
-require 'showoff/version'
-require 'rubygems'
-require 'gli'
-
-include GLI::App
-
-version SHOWOFF_VERSION
-
-desc 'Create new showoff presentation'
-arg_name 'dir_name'
-long_desc 'This command helps start a new showoff presentation by setting up the proper directory structure for you. It takes the directory name you would like showoff to create for you.'
-command [:create,:init] do |c|
-
- c.desc 'Don''t create sample slides'
- c.switch [:n,:nosamples]
-
- c.desc 'sample slide directory name'
- c.default_value 'one'
- c.flag [:d,:slidedir]
-
- c.action do |global_options,options,args|
- raise "dir_name is required" if args.empty?
- ShowOffUtils.create(args[0],!options[:n],options[:d])
- if !options[:n]
- puts "done. run 'showoff serve' in #{options[:d]}/ dir to see slideshow"
- else
- puts "done. add slides, modify #{ShowOffUtils.presentation_config_file} and then run 'showoff serve' in #{dirname}/ dir to see slideshow"
- end
- end
-end
-
-desc 'Puts your showoff presentation into a gh-pages branch'
-long_desc 'Generates a static version of your presentation into your gh-pages branch for publishing to GitHub Pages'
-command :github do |c|
- c.action do |global_options,options,args|
- puts "Generating static content"
- ShowOffUtils.github
- puts "I've updated your 'gh-pages' branch with the static version of your presentation."
- puts "Push it to GitHub to publish it. Probably something like:"
- puts
- puts " git push origin gh-pages"
- puts
- end
-end
-
-desc 'Serves the showoff presentation in the current directory'
-desc 'Setup your presentation to serve on Heroku'
-arg_name 'heroku_name'
-long_desc 'Creates the Gemfile and config.ru file needed to push a showoff pres to heroku. It will then run ''heroku create'' for you to register the new project on heroku and add the remote for you. Then all you need to do is commit the new created files and run ''git push heroku'' to deploy.'
-command :heroku do |c|
-
- c.desc 'add password protection to your heroku site'
- c.flag [:p,:password]
-
- c.desc 'force overwrite of existing Gemfile/.gems and config.ru files if they exist'
- c.switch [:f,:force]
-
- c.desc 'Use older-style .gems file instead of bundler-style Gemfile'
- c.switch [:g,:dotgems]
-
- c.action do |global_options,options,args|
- raise "heroku_name is required" if args.empty?
- if ShowOffUtils.heroku(args[0],options[:f],options[:p],options[:g])
- puts "herokuized. run something like this to launch your heroku presentation:
-
- heroku create #{args[0]}"
-
- if options[:g]
- puts " git add .gems config.ru"
- else
- puts " bundle install"
- puts " git add Gemfile Gemfile.lock config.ru"
- end
- puts " git commit -m 'herokuized'
- git push heroku master
- "
-
- if options[:p]
- puts "CAREFUL: you are commiting your access password - anyone with read access to the repo can access the preso\n\n"
- end
- end
- end
-end
-
-desc 'Serves the showoff presentation in the specified (or current) directory'
-arg_name "[pres_dir]"
-default_value "."
-command :serve do |c|
-
- c.desc 'Show verbose messaging'
- c.switch :verbose
-
- c.desc 'Port on which to run'
- c.default_value "9090"
- c.flag [:p,:port]
-
- c.desc 'Host or ip to run on'
- c.default_value "localhost"
- c.flag [:h,:host]
-
- c.desc 'JSON file used to describe presentation'
- c.default_value "showoff.json"
- c.flag [:f, :pres_file]
-
- c.action do |global_options,options,args|
-
- url = "http://#{options[:h]}:#{options[:p].to_i}"
- puts "
--------------------------
-
-Your ShowOff presentation is now starting up.
-
-To view it plainly, visit [ #{url} ]
-
-To run it from presenter view, go to: [ #{url}/presenter ]
-
--------------------------
-
-"
- ShowOff.run! :host => options[:h], :port => options[:p].to_i, :pres_file => options[:f], :pres_dir => args[0], :verbose => options[:verbose]
- end
-end
-
-desc 'Add a new slide at the end in a given dir'
-arg_name '[title]'
-long_desc 'Outputs or creates a new slide. With -d and -n, a new slide is created in the given dir, numbered to appear as the last slide in that dir (use -u to avoid numbering). Without those, outputs the slide markdown to stdout (useful for shelling out from your editor). You may also specify a source file to use for a code slide'
-command [:add,:new] do |c|
- c.desc 'Don''t number the slide, use the given name verbatim'
- c.switch [:u,:nonumber]
-
- c.desc 'Include code from the given file as the slide body'
- c.arg_name 'path to file'
- c.flag [:s,:source]
-
- c.desc 'Slide Type/Style'
- c.arg_name 'valid showoff style/type'
- c.default_value 'title'
- c.flag [:t,:type,:style]
-
- c.desc 'Slide dir (where to put a new slide file)'
- c.arg_name 'dir'
- c.flag [:d,:dir]
-
- c.desc 'Slide name (name of the new slide file)'
- c.arg_name 'basename'
- c.flag [:n,:name]
-
- c.action do |global_options,options,args|
- title = args.join(" ")
- ShowOffUtils.add_slide(:dir => options[:d],
- :name => options[:n],
- :title => title,
- :number => !options[:u],
- :code => options[:s],
- :type => options[:t])
- end
-end
-
-desc 'Generate static version of presentation'
-arg_name 'name'
-long_desc 'Creates a static, one page version of the presentation as {name}.html'
-command [:static] do |c|
- c.action do |global_options,options,args|
- ShowOff.do_static(args[0])
- end
-end
-
-pre do |global,command,options,args|
- # Pre logic here
- # Return true to proceed; false to abourt and not call the
- # chosen command
- true
-end
-
-post do |global,command,options,args|
- # Post logic here
-end
-
-on_error do |exception|
- # Error logic here
- # return false to skip default error handling
- true
-end
-
-exit run(ARGV)
View
5 example/four/01slide.md
@@ -1,5 +0,0 @@
-!SLIDE[tpl=special]
-
-# A Template #
-
-Really? How many slides? -- ~~~NUM_SLIDES~~~
View
BIN  example/one/octocat.png
Deleted file not rendered
View
34 example/one/slidesA.md
@@ -1,34 +0,0 @@
-<!SLIDE title-slide>
-.notes first slide
-
-# First Slide #
-
-<!SLIDE bullets incremental transition=fade>
-.notes something something something something something something something something something something something something something something something dark side
-
-# Second Slide #
-
-* something
-* something else
-* a third thing
-* a fourth thing
-* a fifth thing
-
-<!SLIDE bullets>
-# Third Slide
-
-* Sometimes bullet items
- * Have sublists
- * And some sublist items
- * Have some of their own
- * And so on
-* But top-level "bullet items" have no bullets
- * isn't that odd?
-
-Also, sometimes you just want to have plain text sitting in the middle
-of the screen. The quick brown fox jumps over the lazy dog.
-
-!SLIDE center transition=scrollUp
-.notes another dark side
-
-![octocat](octocat.png)
View
50 example/one/slidesB.md
@@ -1,50 +0,0 @@
-!SLIDE
-.notes notes for my slide
-
- @@@ javascript
- function setupPreso() {
- if (preso_started)
- {
- alert("already started")
- return
- }
- preso_started = true
-
- loadSlides()
- doDebugStuff()
-
- document.onkeydown = keyDown
- }
-
-!SLIDE commandline incremental
-
- $ git commit -am 'incremental bullet points working'
- [master ac5fd8a] incremental bullet points working
- 2 files changed, 32 insertions(+), 5 deletions(-)
-
-!SLIDE commandline incremental
-
- $ git commit -am 'incremental bullet points working'
- [bmaster ac5fd8a] incremental bullet points working
- 2 files changed, 32 insertions(+), 5 deletions(-)
-
- $ git commit -am 'incremental bullet points working'
- [cmaster ac5fd8a] incremental bullet points working
- 2 files changed, 32 insertions(+), 5 deletions(-)
-
-!SLIDE commandline incremental
-
- # root command
- some output
-
- $ command over \
- several lines
- some more output
- over several lines
-
- $ no output command with \( backslashes \)
- $ command
- output with
- a
-
- blank line
View
15 example/showoff.json
@@ -1,15 +0,0 @@
-{
- "name": "Something",
- "description": "Example Presentation",
- "author": "Foo Bar John",
- "templates" : {
- "special" : "simple.tpl"
- },
- "pause_msg": "Paused !!!",
- "sections": [
- {"section":"one"},
- {"section":"two"},
- {"section":"three"},
- {"section":"four"}
- ]
-}
View
2  example/simple.tpl
@@ -1,2 +0,0 @@
-<div class="border">~~~CONFIG:author~~~@~~~CURRENT_SLIDE~~~</div>
-<div class="main">~~~CONTENT~~~<div>
View
6 example/something.css
@@ -1,6 +0,0 @@
-/* custom css and js files included at the top level of your presentation will
- * will be included in your presentation */
-
-.title-slide h1 {
- color: blue;
-}
View
30 example/three/js-events.md
@@ -1,30 +0,0 @@
-!SLIDE subsection
-# Custom events #
-
-!SLIDE custom_and_unique_class
-# 1st Example h1
-<script>
-// bind to custom event
-$(".custom_and_unique_class").bind("showoff:show", function (event) {
- // animate the h1
- var h1 = $(event.target).find("h1");
- h1.delay(500)
- .slideUp(300, function () { $(this).css({textDecoration: "line-through"}); })
- .slideDown(300);
-});
-</script>
-
-!SLIDE prevent_default
-# 2nd Example h1
-<script>
-$(".prevent_default").bind("showoff:next", function (event) {
- var h1 = $(event.target).find("h1");
- if (h1.css("text-decoration") === "none") {
- event.preventDefault();
- h1.css({textDecoration: "line-through"})
- }
-});
-</script>
-
-!SLIDE
-# Switched
View
67 example/two/slidesA.md
@@ -1,67 +0,0 @@
-!SLIDE subsection
-
-# Subsection Slide #
-
-!SLIDE
-
-# Code Slide #
-
- @@@ ruby
- require 'sinatra/base'
-
- class MyApp < Sinatra::Base
- set :sessions, true
- set :foo, 'bar'
-
- get '/' do
- 'Hello world!'
- end
- end
-
-!SLIDE
-
- @@@ erlang
- Output = process(Input, []).
-
- process([First|Rest], Output) ->
- NewFirst = do_stuff(First),
- process(Rest, [NewFirst|Output]);
-
- process([], Output) ->
- lists:reverse(Output).
-
-!SLIDE execute
-
-# Executable JavaScript #
-
- @@@ javascript
- result = 3 + 3;
-
-!SLIDE execute
-
-# Executable Ruby #
-
- @@@ ruby
- result = [1, 2, 3].map { |n| n*7 }
-
-!SLIDE execute
-# Executable Coffeescript #
-
- @@@coffeescript
- add = (a, b) ->
- "#{a}+#{b} is #{a+b}"
-
- result = add 2, 3
-
-
-!SLIDE
-
-# Write your own slides #
-
-## Using [markdown](http://daringfireball.net/projects/markdown/)
-
- !SLIDE
-
- # Title of the slide #
-
- How easy is this?
View
67 lib/commandline_parser.rb
@@ -1,67 +0,0 @@
-require 'parslet'
-
-# For parsing commandline slide content.
-class CommandlineParser < Parslet::Parser
-
- rule(:prompt) do
- str('$') | str('#') | str('>>')
- end
-
- rule(:text) do
- match['[:print:]'].repeat
- end
-
- rule(:singleline_input) do
- (str("\\\n").absent? >> match['[:print:]']).repeat
- end
-
- rule(:input) do
- multiline_input | singleline_input
- end
-
- rule(:multiline_input) do
-
- # some command \
- # continued \
- # \
- # and stop
- ( singleline_input >> str('\\') >> newline ).repeat(1) >> singleline_input
- end
-
- rule(:command) do
-
- # $ some command
- # some output
- ( prompt.as(:prompt) >> space? >> input.as(:input) >> output? ).as(:command)
- end
-
- rule(:output) do
-
- # output
- prompt.absent? >> text
- end
-
- rule(:output?) do
-
- #
- # some text
- # some text
- #
- # some text
- ( newline >> ( ( output >> newline ).repeat >> output.maybe ).as(:output) ).maybe
- end
-
- rule(:commands) do
- command.repeat
- end
-
- rule(:newline) do
- str("\n") | str("\r\n")
- end
-
- rule(:space?) do
- match['[:space:]'].repeat
- end
-
- root(:commands)
-end
View
609 lib/showoff.rb
@@ -1,609 +0,0 @@
-require 'rubygems'
-require 'sinatra/base'
-require 'json'
-require 'nokogiri'
-require 'fileutils'
-require 'logger'
-
-here = File.expand_path(File.dirname(__FILE__))
-require "#{here}/showoff_utils"
-require "#{here}/commandline_parser"
-
-begin
- require 'RMagick'
-rescue LoadError
- $stderr.puts 'WARN: image sizing disabled - install rmagick'
-end
-
-begin
- require 'pdfkit'
-rescue LoadError
- $stderr.puts 'WARN: pdf generation disabled - install pdfkit'
-end
-
-require 'tilt'
-
-class ShowOff < Sinatra::Application
-
- attr_reader :cached_image_size
-
- set :views, File.dirname(__FILE__) + '/../views'
- set :public_folder, File.dirname(__FILE__) + '/../public'
-
- set :verbose, false
- set :pres_dir, '.'
- set :pres_file, 'showoff.json'
- set :page_size, "Letter"
- set :pres_template, nil
- set :showoff_config, nil
- set :encoding, nil
-
- def initialize(app=nil)
- super(app)
- @logger = Logger.new(STDOUT)
- @logger.formatter = proc { |severity,datetime,progname,msg| "#{progname} #{msg}\n" }
- @logger.level = settings.verbose ? Logger::DEBUG : Logger::WARN
-
- dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
- @logger.debug(dir)
-
- showoff_dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
- settings.pres_dir ||= Dir.pwd
- @root_path = "."
-
- settings.pres_dir = File.expand_path(settings.pres_dir)
- if (settings.pres_file)
- ShowOffUtils.presentation_config_file = settings.pres_file
- end
-
- # Load configuration for page size and template from the
- # configuration JSON file
- if File.exists?(ShowOffUtils.presentation_config_file)
- showoff_json = JSON.parse(File.read(ShowOffUtils.presentation_config_file))
- settings.showoff_config = showoff_json
-
- # Set options for encoding, template and page size
- settings.encoding = showoff_json["encoding"]
- settings.page_size = showoff_json["page-size"] || "Letter"
- settings.pres_template = showoff_json["templates"]
- end
-
-
- @logger.debug settings.pres_template
-
- @cached_image_size = {}
- @logger.debug settings.pres_dir
- @pres_name = settings.pres_dir.split('/').pop
- require_ruby_files
-
- # Default asset path
- @asset_path = "./"
-
- # Initialize Markdown Configuration
- MarkdownConfig::setup(settings.pres_dir)
- end
-
- def self.pres_dir_current
- opt = {:pres_dir => Dir.pwd}
- ShowOff.set opt
- end
-
- def require_ruby_files
- Dir.glob("#{settings.pres_dir}/*.rb").map { |path| require path }
- end
-
- helpers do
- def load_section_files(section)
- section = File.join(settings.pres_dir, section)
- files = if File.directory? section
- Dir.glob("#{section}/**/*").sort
- else
- [section]
- end
- @logger.debug files
- files
- end
-
- def css_files
- Dir.glob("#{settings.pres_dir}/*.css").map { |path| File.basename(path) }
- end
-
- def js_files
- Dir.glob("#{settings.pres_dir}/*.js").map { |path| File.basename(path) }
- end
-
-
- def preshow_files
- Dir.glob("#{settings.pres_dir}/_preshow/*").map { |path| File.basename(path) }.to_json
- end
-
- # todo: move more behavior into this class
- class Slide
- attr_reader :classes, :text, :tpl
- def initialize( context = "")
-
- @tpl = "default"
- @classes = ["content"]
-
- # Parse the context string for options and content classes
- if context and context.match(/(\[(.*?)\])?(.*)/)
-
- options = ShowOffUtils.parse_options($2)
- @tpl = options["tpl"] if options["tpl"]
- @classes += $3.strip.chomp('>').split if $3
-
- end
-
- @text = ""
- end
- def <<(s)
- @text << s
- @text << "\n"
- end
- def empty?
- @text.strip == ""
- end
- def skip?
- @classes.include? 'skip'
- end
- end
-
-
- def process_markdown(name, content, static=false, pdf=false)
- if settings.encoding and content.respond_to?(:force_encoding)
- content.force_encoding(settings.encoding)
- end
- engine_options = ShowOffUtils.showoff_renderer_options(settings.pres_dir)
- @logger.debug "renderer: #{Tilt[:markdown].name}"
- @logger.debug "render options: #{engine_options.inspect}"
-
- # if there are no !SLIDE markers, then make every H1 define a new slide
- unless content =~ /^\<?!SLIDE/m
- content = content.gsub(/^# /m, "<!SLIDE>\n# ")
- end
-
- # todo: unit test
- lines = content.split("\n")
- @logger.debug "#{name}: #{lines.length} lines"
- slides = []
- slides << (slide = Slide.new)
- until lines.empty?
- line = lines.shift
- if line =~ /^<?!SLIDE(.*)>?/
- ctx = $1 ? $1.strip : $1
- slides << (slide = Slide.new(ctx))
- else
- slide << line
- end
- end
-
- slides.delete_if {|slide| slide.empty? || slide.skip? }
-
- final = ''
- if slides.size > 1
- seq = 1
- end
- slides.each do |slide|
- @slide_count += 1
- md = ''
- content_classes = slide.classes
-
- # extract transition, defaulting to none
- transition = 'none'
- content_classes.delete_if { |x| x =~ /^transition=(.+)/ && transition = $1 }
- # extract id, defaulting to none
- id = nil
- content_classes.delete_if { |x| x =~ /^#([\w-]+)/ && id = $1 }
- @logger.debug "id: #{id}" if id
- @logger.debug "classes: #{content_classes.inspect}"
- @logger.debug "transition: #{transition}"
- @logger.debug "tpl: #{slide.tpl} " if slide.tpl
- # create html
- md += "<div"
- md += " id=\"#{id}\"" if id
- md += " class=\"slide\" data-transition=\"#{transition}\">"
-
-
- template = "~~~CONTENT~~~"
- # Template handling
- if settings.pres_template
- # We allow specifying a new template even when default is
- # not given.
- if settings.pres_template.include?(slide.tpl) and
- File.exists?(settings.pres_template[slide.tpl])
- template = File.open(settings.pres_template[slide.tpl], "r").read()
- end
- end
-
- # Extract the content of the slide
- content = ""
- if seq
- content += "<div class=\"#{content_classes.join(' ')}\" ref=\"#{name}/#{seq.to_s}\">\n"
- else
- content += "<div class=\"#{content_classes.join(' ')}\" ref=\"#{name}\">\n"
- end
- sl = Tilt[:markdown].new(nil, nil, engine_options) { slide.text }.render
- sl = update_image_paths(name, sl, static, pdf)
- content += sl
- content += "</div>\n"
-
- # Apply the template to the slide and replace the key with
- # content of the slide
- md += process_content_for_replacements(template.gsub(/~~~CONTENT~~~/, content), @slide_count)
-
- # Apply other configuration
-
- md += "</div>\n"
- final += update_commandline_code(md)
- final = update_p_classes(final)
-
- if seq
- seq += 1
- end
- end
- final
- end
-
- # This method processes the content of the slide and replaces
- # content markers with their actual value information
- def process_content_for_replacements(content, seq)
- result = content.gsub("~~~CURRENT_SLIDE~~~", seq.to_s)
- # Now check for any kind of options
- content.scan(/(~~~CONFIG:(.*?)~~~)/).each do |match|
- result.gsub!(match[0], settings.showoff_config[match[1]]) if settings.showoff_config.key?(match[1])
- end
-
- result
- end
-
- def process_content_for_all_slides(content, num_slides)
- content.gsub("~~~NUM_SLIDES~~~", num_slides.to_s)
- end
-
-
- # find any lines that start with a <p>.(something) and turn them into <p class="something">
- def update_p_classes(markdown)
- markdown.gsub(/<p>\.(.*?) /, '<p class="\1">')
- end
-
- def update_image_paths(path, slide, static=false, pdf=false)
- paths = path.split('/')
- paths.pop
- path = paths.join('/')
- replacement_prefix = static ?
- ( pdf ? %(img src="file://#{settings.pres_dir}/#{path}) : %(img src="./file/#{path}) ) :
- %(img src="#{@asset_path}image/#{path})
- slide.gsub(/img src=[\"\'](?!https?:\/\/)([^\/].*?)[\"\']/) do |s|
- img_path = File.join(path, $1)
- w, h = get_image_size(img_path)
- src = %(#{replacement_prefix}/#{$1}")
- if w && h
- src << %( width="#{w}" height="#{h}")
- end
- src
- end
- end
-
- if defined?(Magick)
- def get_image_size(path)
- if !cached_image_size.key?(path)
- img = Magick::Image.ping(File.join(".", @asset_path, path)).first
- # don't set a size for svgs so they can expand to fit their container
- if img.mime_type == 'image/svg+xml'
- cached_image_size[path] = [nil, nil]
- else
- cached_image_size[path] = [img.columns, img.rows]
- end
- end
- cached_image_size[path]
- end
- else
- def get_image_size(path)
- end
- end
-
- def update_commandline_code(slide)
- html = Nokogiri::XML.parse(slide)
- parser = CommandlineParser.new
-
- html.css('pre').each do |pre|
- pre.css('code').each do |code|
- out = code.text
- lines = out.split("\n")
- if lines.first.strip[0, 3] == '@@@'
- lang = lines.shift.gsub('@@@', '').strip
- pre.set_attribute('class', 'sh_' + lang.downcase) if !lang.empty?
- code.content = lines.join("\n")
- end
- end
- end
-
- html.css('.commandline > pre > code').each do |code|
- out = code.text
- code.content = ''
- tree = parser.parse(out)
- transform = Parslet::Transform.new do
- rule(:prompt => simple(:prompt), :input => simple(:input), :output => simple(:output)) do
- command = Nokogiri::XML::Node.new('code', html)
- command.set_attribute('class', 'command')
- command.content = "#{prompt} #{input}"
- code << command
-
- # Add newline after the input so that users can
- # advance faster than the typewriter effect
- # and still keep inputs on separate lines.
- code << "\n"
-
- unless output.to_s.empty?
-
- result = Nokogiri::XML::Node.new('code', html)
- result.set_attribute('class', 'result')
- result.content = output
- code << result
- end
- end
- end
- transform.apply(tree)
- end
- html.root.to_s
- end
-
- def get_slides_html(static=false, pdf=false)
- @slide_count = 0
- sections = ShowOffUtils.showoff_sections(settings.pres_dir, @logger)
- files = []
- if sections
- data = ''
- sections.each do |section|
- if section =~ /^#/
- name = section.each_line.first.gsub(/^#*/,'').strip
- data << process_markdown(name, "<!SLIDE subsection>\n" + section, static, pdf)
- else
- files = []
- files << load_section_files(section)
- files = files.flatten
- files = files.select { |f| f =~ /.md$/ }
- files.each do |f|
- fname = f.gsub(settings.pres_dir + '/', '').gsub('.md', '')
- data << process_markdown(fname, File.read(f), static, pdf)
- end
- end
- end
- end
- process_content_for_all_slides(data, @slide_count)
- end
-
- def inline_css(csses, pre = nil)
- css_content = '<style type="text/css">'
- csses.each do |css_file|
- if pre
- css_file = File.join(File.dirname(__FILE__), '..', pre, css_file)
- else
- css_file = File.join(settings.pres_dir, css_file)
- end
- css_content += File.read(css_file)
- end
- css_content += '</style>'
- css_content
- end
-
- def inline_js(jses, pre = nil)
- js_content = '<script type="text/javascript">'
- jses.each do |js_file|
- if pre
- js_file = File.join(File.dirname(__FILE__), '..', pre, js_file)
- else
- js_file = File.join(settings.pres_dir, js_file)
- end
-
- begin
- js_content += File.read(js_file)
- rescue Errno::ENOENT
- $stderr.puts "WARN: Failed to inline JS. No such file: #{js_file}"
- next
- end
- end
- js_content += '</script>'
- js_content
- end
-
- def inline_all_js(jses_directory)
- inline_js(Dir.entries(File.join(File.dirname(__FILE__), '..', jses_directory)).find_all{|filename| filename.length > 2 }, jses_directory)
- end
-
- def index(static=false)
- if static
- @title = ShowOffUtils.showoff_title
- @slides = get_slides_html(static)
-
- @pause_msg = ShowOffUtils.pause_msg
-
- # Identify which languages to bundle for highlighting
- @languages = @slides.scan(/<pre class=".*(?!sh_sourceCode)(sh_[\w-]+).*"/).uniq.map{ |w| "sh_lang/#{w[0]}.min.js"}
-
- @asset_path = "./"
- end
- erb :index
- end
-
- def presenter
- erb :presenter
- end
-
- def clean_link(href)
- if href && href[0, 1] == '/'
- href = href[1, href.size]
- end
- href
- end
-
- def assets_needed
- assets = ["index", "slides"]
-
- index = erb :index
- html = Nokogiri::XML.parse(index)
- html.css('head link').each do |link|
- href = clean_link(link['href'])
- assets << href if href
- end
- html.css('head script').each do |link|
- href = clean_link(link['src'])
- assets << href if href
- end
-
- slides = get_slides_html
- html = Nokogiri::XML.parse("<slides>" + slides + "</slides>")
- html.css('img').each do |link|
- href = clean_link(link['src'])
- assets << href if href
- end
-
- css = Dir.glob("#{settings.public_folder}/**/*.css").map { |path| path.gsub(settings.public_folder + '/', '') }
- assets << css
-
- js = Dir.glob("#{settings.public_folder}/**/*.js").map { |path| path.gsub(settings.public_folder + '/', '') }
- assets << js
-
- assets.uniq.join("\n")
- end
-
- def slides(static=false)
- get_slides_html(static)
- end
-
- def onepage(static=false)
- @slides = get_slides_html(static)
- @languages = @slides.scan(/<pre class=".*(?!sh_sourceCode)(sh_[\w-]+).*"/).uniq.map{ |w| "/sh_lang/#{w[0]}.min.js"}
- erb :onepage
- end
-
- def pdf(static=true)
- @slides = get_slides_html(static, true)
- @inline = true
-
- # Identify which languages to bundle for highlighting
- @languages = @slides.scan(/<pre class=".*(?!sh_sourceCode)(sh_[\w-]+).*"/).uniq.map{ |w| "/sh_lang/#{w[0]}.min.js"}
-
- html = erb :onepage
- # TODO make a random filename
-
- # Process inline css and js for included images
- # The css uses relative paths for images and we prepend the file url
- html.gsub!(/url\([\"\']?(?!https?:\/\/)(.*?)[\"\']?\)/) do |s|
- "url(file://#{settings.pres_dir}/#{$1})"
- end
-
- # Todo fix javascript path
-
- # PDFKit.new takes the HTML and any options for wkhtmltopdf
- # run `wkhtmltopdf --extended-help` for a full list of options
- kit = PDFKit.new(html, ShowOffUtils.showoff_pdf_options(settings.pres_dir))
-
- # Save the PDF to a file
- file = kit.to_file('/tmp/preso.pdf')
- end
-
- end
-
-
- def self.do_static(what)
- what = "index" if !what
-
- showoff = ShowOff.new!
- name = showoff.instance_variable_get(:@pres_name)
- path = showoff.instance_variable_get(:@root_path)
- logger = showoff.instance_variable_get(:@logger)
- data = showoff.send(what, true)
-
- if data.is_a?(File)
- FileUtils.cp(data.path, "#{name}.pdf")
- else
- out = File.expand_path("#{path}/static")
- # First make a directory
- FileUtils.makedirs(out)
- # Then write the html
- file = File.new("#{out}/index.html", "w")
- file.puts(data)
- file.close
- # Now copy all the js and css
- my_path = File.join( File.dirname(__FILE__), '..', 'public')
- ["js", "css"].each { |dir|
- FileUtils.copy_entry("#{my_path}/#{dir}", "#{out}/#{dir}")
- }
- # And copy the directory
- Dir.glob("#{my_path}/#{name}/*").each { |subpath|
- base = File.basename(subpath)
- next if "static" == base
- next unless File.directory?(subpath) || base.match(/\.(css|js)$/)
- FileUtils.copy_entry(subpath, "#{out}/#{base}")
- }
-
- # Set up file dir
- file_dir = File.join(out, 'file')
- FileUtils.makedirs(file_dir)
- pres_dir = showoff.settings.pres_dir
-
- # ..., copy all user-defined styles and javascript files
- Dir.glob("#{pres_dir}/*.{css,js}").each { |path|
- FileUtils.copy(path, File.join(file_dir, File.basename(path)))
- }
-
- # ... and copy all needed image files
- data.scan(/img src=[\"\'].\/file\/(.*?)[\"\']/).flatten.each do |path|
- dir = File.dirname(path)
- FileUtils.makedirs(File.join(file_dir, dir))
- FileUtils.copy(File.join(pres_dir, path), File.join(file_dir, path))
- end
- # copy images from css too
- Dir.glob("#{pres_dir}/*.css").each do |css_path|
- File.open(css_path) do |file|
- data = file.read
- data.scan(/url\([\"\']?(?!https?:\/\/)(.*?)[\"\']?\)/).flatten.each do |path|
- path.gsub!(/(\#.*)$/, '') # get rid of the anchor
- path.gsub!(/(\?.*)$/, '') # get rid of the query
- logger.debug path
- dir = File.dirname(path)
- FileUtils.makedirs(File.join(file_dir, dir))
- FileUtils.copy(File.join(pres_dir, path), File.join(file_dir, path))
- end
- end
- end
- end
- end
-
- def eval_ruby code
- eval(code).to_s
- rescue => e
- e.message
- end
-
- get '/eval_ruby' do
- return eval_ruby(params[:code]) if ENV['SHOWOFF_EVAL_RUBY']
-
- return "Ruby Evaluation is off. To turn it on set ENV['SHOWOFF_EVAL_RUBY']"
- end
-
- get %r{(?:image|file)/(.*)} do
- path = params[:captures].first
- full_path = File.join(settings.pres_dir, path)
- send_file full_path
- end
-
- get %r{/(.*)} do
- @title = ShowOffUtils.showoff_title
- @pause_msg = ShowOffUtils.pause_msg
- what = params[:captures].first
- what = 'index' if "" == what
-
- @asset_path = (env['SCRIPT_NAME'] || '').gsub(/\/?$/, '/').gsub(/^\//, '')
-
- if (what != "favicon.ico")
- data = send(what)
- if data.is_a?(File)
- send_file data.path
- else
- data
- end
- end
- end
-end
View
3  lib/showoff/version.rb
@@ -1,3 +0,0 @@
-# No namespace here since ShowOff is a class and I'd have to inherit from
-# Sinatra::Application (which we don't want to load here)
-SHOWOFF_VERSION = '0.7.0'
View
441 lib/showoff_utils.rb
@@ -1,441 +0,0 @@
-class ShowOffUtils
-
- # Helper method to parse a comma separated options string and stores
- # the result in a dictionrary
- #
- # Example:
- #
- # "tpl=hpi,title=Over the rainbow"
- #
- # will be stored as
- #
- # { "tpl" => "hpi", "title" => "Over the rainbow" }
- def self.parse_options(option_string="")
- result = {}
-
- if option_string
- option_string.split(",").each do |element|
- pair = element.split("=")
- result[pair[0]] = pair.size > 1 ? pair[1] : nil
- end
- end
-
- result
- end
-
- def self.presentation_config_file
- @presentation_config_file ||= 'showoff.json'
- end
-
- def self.presentation_config_file=(filename)
- @presentation_config_file = filename
- end
-
- def self.create(dirname,create_samples,dir='one')
- Dir.mkdir(dirname) if !File.exists?(dirname)
- Dir.chdir(dirname) do
- if create_samples
- # create section
- Dir.mkdir(dir)
-
- # create markdown file
- File.open("#{dir}/01_slide.md", 'w+') do |f|
- f.puts make_slide("My Presentation")
- f.puts make_slide("Bullet Points","bullets incremental",["first point","second point","third point"])
- end
- end
-
- # create showoff.json
- File.open(ShowOffUtils.presentation_config_file, 'w+') do |f|
- f.puts "{ \"name\": \"My Preso\", \"sections\": [ {\"section\":\"#{dir}\"} ]}"
- end
- end
- end
-
- HEROKU_GEMS_FILE = '.gems'
- HEROKU_BUNDLER_GEMS_FILE = 'Gemfile'
- HEROKU_CONFIG_FILE = 'config.ru'
-
- # Setup presentation to run on Heroku
- #
- # name - String containing heroku name
- # force - boolean if .gems/Gemfile and config.ru should be overwritten if they don't exist
- # password - String containing password to protect your heroku site; nil means no password protection
- # use_dot_gems - boolean that, if true, indicates we should use the old, deprecated .gems file instead of Bundler
- def self.heroku(name, force = false, password = nil, use_dot_gems = false)
- modified_something = false
-
- if use_dot_gems
- modified_something = create_gems_file(HEROKU_GEMS_FILE,
- !password.nil?,
- force,
- lambda{ |gem| gem })
- else
- modified_something = create_gems_file(HEROKU_BUNDLER_GEMS_FILE,
- !password.nil?,
- force,
- lambda{ |gem| "gem '#{gem}'" },
- lambda{ "source :rubygems" })
- end
-
- create_file_if_needed(HEROKU_CONFIG_FILE,force) do |file|
- modified_something = true
- file.puts 'require "showoff"'
- if password.nil?
- file.puts 'run ShowOff.new'
- else
- file.puts 'require "rack"'
- file.puts 'showoff_app = ShowOff.new'
- file.puts 'protected_showoff = Rack::Auth::Basic.new(showoff_app) do |username, password|'
- file.puts "\tpassword == '#{password}'"
- file.puts 'end'
- file.puts 'run protected_showoff'
- end
- end
-
- modified_something
- end
-
- # generate a static version of the site into the gh-pages branch
- def self.github
- ShowOff.do_static(nil)
- `git add static`
- sha = `git write-tree`.chomp
- tree_sha = `git rev-parse #{sha}:static`.chomp
- `git read-tree HEAD` # reset staging to last-commit
- ghp_sha = `git rev-parse gh-pages 2>/dev/null`.chomp
- extra = ghp_sha != 'gh-pages' ? "-p #{ghp_sha}" : ''
- commit_sha = `echo 'static presentation' | git commit-tree #{tree_sha} #{extra}`.chomp
- `git update-ref refs/heads/gh-pages #{commit_sha}`
- end
-
- # Makes a slide as a string.
- # [title] title of the slide
- # [classes] any "classes" to include, such as 'smaller', 'transition', etc.
- # [content] slide content. Currently, if this is an array, it will make a bullet list. Otherwise
- # the string value of this will be put in the slide as-is
- def self.make_slide(title,classes="",content=nil)
- slide = "!SLIDE #{classes}\n"
- slide << "# #{title} #\n"
- slide << "\n"
- if content
- if content.kind_of? Array
- content.each { |x| slide << "* #{x.to_s}\n" }
- else
- slide << content.to_s
- end
- end
- slide
- end
-
- TYPES = {
- :default => lambda { |t,size,source,type| make_slide(t,"#{size} #{type}",source) },
- 'title' => lambda { |t,size,dontcare| make_slide(t,size) },
- 'bullets' => lambda { |t,size,dontcare| make_slide(t,"#{size} bullets incremental",["bullets","go","here"])},
- 'smbullets' => lambda { |t,size,dontcare| make_slide(t,"#{size} smbullets incremental",["bullets","go","here","and","here"])},
- 'code' => lambda { |t,size,src| make_slide(t,size,blank?(src) ? " @@@ Ruby\n code_here()" : src) },
- 'commandline' => lambda { |t,size,dontcare| make_slide(t,"#{size} commandline"," $ command here\n output here")},
- 'full-page' => lambda { |t,size,dontcare| make_slide(t,"#{size} full-page","![Image Description](image/ref.png)")},
- }
-
-
- # Adds a new slide to a given dir, giving it a number such that it falls after all slides
- # in that dir.
- # Options are:
- # [:dir] - dir where we put the slide (if omitted, slide is output to $stdout)
- # [:name] - name of the file, without the number prefix. (if omitted, a default is used)
- # [:title] - title in the slide. If not specified the source file name is
- # used. If THAT is not specified, uses the value of +:name+. If THAT is not
- # specified, a suitable default is used
- # [:code] - path to a source file to use as content (force :type to be 'code')
- # [:number] - true if numbering should be done, false if not
- # [:type] - the type of slide to create
- def self.add_slide(options)
-
- add_new_dir(options[:dir]) if options[:dir] && !File.exists?(options[:dir])
-
- options[:type] = 'code' if options[:code]
-
- title = determine_title(options[:title],options[:name],options[:code])
-
- options[:name] = 'new_slide' if !options[:name]
-
- size,source = determine_size_and_source(options[:code])
- type = options[:type] || :default
- slide = TYPES[type].call(title,size,source)
-
- if options[:dir]
- filename = determine_filename(options[:dir],options[:name],options[:number])
- write_file(filename,slide)
- else
- puts slide
- puts
- end
-
- end
-
- # Adds the given directory to this presentation, appending it to
- # the end of showoff.json as well
- def self.add_new_dir(dir)
- puts "Creating #{dir}..."
- Dir.mkdir dir
-
- showoff_json = JSON.parse(File.read(ShowOffUtils.presentation_config_file))
- showoff_json["section"] = dir
- File.open(ShowOffUtils.presentation_config_file,'w') do |file|
- file.puts JSON.generate(showoff_json)
- end
- puts "#{ShowOffUtils.presentation_config_file} updated"
- end
-
- def self.blank?(string)
- string.nil? || string.strip.length == 0
- end
-
- def self.determine_size_and_source(code)
- size = ""
- source = ""
- if code
- source,lines,width = read_code(code)
- size = adjust_size(lines,width)
- end
- [size,source]
- end
-
- def self.write_file(filename,slide)
- File.open(filename,'w') do |file|
- file.puts slide
- end
- puts "Wrote #{filename}"
- end
-
- def self.determine_filename(slide_dir,slide_name,number)
- filename = "#{slide_dir}/#{slide_name}.md"
- if number
- max = find_next_number(slide_dir)
- filename = "#{slide_dir}/#{max}_#{slide_name}.md"
- end
- filename
- end
-
- # Finds the next number in the given dir to
- # name a slide as the last slide in the dir.
- def self.find_next_number(slide_dir)
- max = 0
- Dir.open(slide_dir).each do |file|
- if file =~ /(\d+).*\.md/
- num = $1.to_i
- max = num if num > max
- end
- end
- max += 1
- max = "0#{max}" if max < 10
- max
- end
-
- def self.determine_title(title,slide_name,code)
- if blank?(title)
- title = slide_name
- title = File.basename(code) if code
- end
- title = "Title here" if blank?(title)
- title
- end
-
- # Determines a more optimal value for the size (e.g. small vs. smaller)
- # based upon the size of the code being formatted.
- def self.adjust_size(lines,width)
- size = ""
- # These values determined empircally
- size = "small" if width > 50
- size = "small" if lines > 15
- size = "smaller" if width > 57
- size = "smaller" if lines > 19
- puts "warning, some lines are too long and the code may be cut off" if width > 65
- puts "warning, your code is too long and the code may be cut off" if lines > 23
- size
- end
-
- # Reads the code from the source file, returning
- # the code, indented for markdown, as well as the number of lines
- # and the width of the largest line
- def self.read_code(source_file)
- code = " @@@ #{lang(source_file)}\n"
- lines = 0
- width = 0
- File.open(source_file) do |code_file|
- code_file.readlines.each do |line|
- code += " #{line}"
- lines += 1
- width = line.length if line.length > width
- end
- end
- [code,lines,width]
- end
-
- def self.showoff_sections(dir,logger)
- index = File.join(dir, ShowOffUtils.presentation_config_file)
- sections = nil
- if File.exists?(index)
- data = JSON.parse(File.read(index))
- logger.debug data
- if data.is_a?(Hash)
- sections = data['sections']
- else
- sections = data
- end
- sections = sections.map do |s|
- if s.is_a? Hash
- s['section']
- else
- s
- end
- end
- else
- sections = ["."] # if there's no showoff.json file, make a boring one
- end
- sections
- end
-
- def self.showoff_title(dir = '.')
- get_config_option(dir, 'name', "Presentation")
- end
-
- def self.pause_msg(dir = '.')
- get_config_option(dir, 'pause_msg', '')
- end
-
- def self.showoff_pdf_options(dir = '.')
- opts = get_config_option(dir, 'pdf_options', {:page_size => 'Letter', :orientation => 'Landscape'})
- Hash[opts.map {|k, v| [k.to_sym, v]}] # keys must be symbols
- end
-
- def self.showoff_markdown(dir = ".")
- get_config_option(dir, "markdown", "redcarpet")
- end
-
- def self.showoff_renderer_options(dir = '.', default_options = {})
- opts = get_config_option(dir, showoff_markdown(dir))
- Hash[opts.map {|k, v| [k.to_sym, v]}] if opts # keys must be symbols
- end
-
- def self.get_config_option(dir, option, default = nil)
- index = File.join(dir, ShowOffUtils.presentation_config_file)
- if File.exists?(index)
- data = JSON.parse(File.read(index))
- if data.is_a?(Hash)
- if default.is_a?(Hash)
- default.merge(data[option] || {})
- else
- data[option] || default
- end
- end
-