deckrb 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/README.md +55 -20
  2. data/bin/deck +5 -10
  3. data/lib/deck.rb +1 -1
  4. data/lib/deck/noko.rb +15 -0
  5. data/lib/deck/rack_app.rb +61 -0
  6. data/lib/deck/slide.rb +50 -28
  7. data/lib/deck/{deck.rb → slide_deck.rb} +42 -41
  8. data/lib/deck/version.rb +1 -1
  9. data/spec/rack_app_spec.rb +177 -0
  10. data/spec/slide_deck_spec.rb +46 -0
  11. data/spec/slide_spec.rb +24 -21
  12. data/spec/spec_helper.rb +5 -0
  13. metadata +51 -81
  14. data/deck/GPL-license.txt +0 -278
  15. data/deck/MIT-license.txt +0 -21
  16. data/deck/README.md +0 -57
  17. data/deck/core/deck.core.css +0 -404
  18. data/deck/core/deck.core.html +0 -39
  19. data/deck/core/deck.core.js +0 -498
  20. data/deck/core/deck.core.scss +0 -447
  21. data/deck/extensions/goto/deck.goto.css +0 -41
  22. data/deck/extensions/goto/deck.goto.html +0 -7
  23. data/deck/extensions/goto/deck.goto.js +0 -134
  24. data/deck/extensions/goto/deck.goto.scss +0 -46
  25. data/deck/extensions/hash/deck.hash.css +0 -13
  26. data/deck/extensions/hash/deck.hash.html +0 -2
  27. data/deck/extensions/hash/deck.hash.js +0 -129
  28. data/deck/extensions/hash/deck.hash.scss +0 -15
  29. data/deck/extensions/menu/deck.menu.css +0 -47
  30. data/deck/extensions/menu/deck.menu.js +0 -187
  31. data/deck/extensions/menu/deck.menu.scss +0 -58
  32. data/deck/extensions/navigation/deck.navigation.css +0 -43
  33. data/deck/extensions/navigation/deck.navigation.html +0 -3
  34. data/deck/extensions/navigation/deck.navigation.js +0 -91
  35. data/deck/extensions/navigation/deck.navigation.scss +0 -56
  36. data/deck/extensions/scale/deck.scale.css +0 -16
  37. data/deck/extensions/scale/deck.scale.js +0 -155
  38. data/deck/extensions/scale/deck.scale.scss +0 -17
  39. data/deck/extensions/status/deck.status.css +0 -18
  40. data/deck/extensions/status/deck.status.html +0 -6
  41. data/deck/extensions/status/deck.status.js +0 -95
  42. data/deck/extensions/status/deck.status.scss +0 -22
  43. data/deck/extensions/theme-picker/deck.theme-picker.css +0 -55
  44. data/deck/extensions/theme-picker/deck.theme-picker.js +0 -13
  45. data/deck/introduction/index.html +0 -221
  46. data/deck/introduction/index.rb +0 -101
  47. data/deck/jquery-1.7.min.js +0 -4
  48. data/deck/modernizr.custom.js +0 -4
  49. data/deck/test/fixtures/complex.html +0 -24
  50. data/deck/test/fixtures/empty.html +0 -19
  51. data/deck/test/fixtures/iframe_simple.html +0 -10
  52. data/deck/test/fixtures/iframes.html +0 -32
  53. data/deck/test/fixtures/nesteds.html +0 -36
  54. data/deck/test/fixtures/standard.html +0 -42
  55. data/deck/test/index.html +0 -39
  56. data/deck/test/lib/jasmine-html.js +0 -190
  57. data/deck/test/lib/jasmine-jquery.js +0 -288
  58. data/deck/test/lib/jasmine.css +0 -166
  59. data/deck/test/lib/jasmine.js +0 -2477
  60. data/deck/test/settings.js +0 -3
  61. data/deck/test/spec.core.js +0 -434
  62. data/deck/test/spec.goto.js +0 -119
  63. data/deck/test/spec.hash.js +0 -81
  64. data/deck/test/spec.menu.js +0 -66
  65. data/deck/test/spec.navigation.js +0 -51
  66. data/deck/test/spec.scale.js +0 -57
  67. data/deck/test/spec.status.js +0 -58
  68. data/deck/themes/style/neon.css +0 -114
  69. data/deck/themes/style/neon.scss +0 -139
  70. data/deck/themes/style/swiss.css +0 -75
  71. data/deck/themes/style/swiss.scss +0 -91
  72. data/deck/themes/style/web-2.0.css +0 -205
  73. data/deck/themes/style/web-2.0.scss +0 -236
  74. data/deck/themes/transition/fade.css +0 -44
  75. data/deck/themes/transition/fade.scss +0 -70
  76. data/deck/themes/transition/horizontal-slide.css +0 -79
  77. data/deck/themes/transition/horizontal-slide.scss +0 -94
  78. data/deck/themes/transition/vertical-slide.css +0 -97
  79. data/deck/themes/transition/vertical-slide.scss +0 -116
  80. data/lib/deck/app.rb +0 -16
  81. data/spec/deck_spec.rb +0 -98
data/README.md CHANGED
@@ -11,6 +11,13 @@
11
11
  * Erector
12
12
  * Markdown
13
13
  * presentations can comprise several source files
14
+ * source files look good as source, built HTML, preview HTML, or as a deck doc
15
+ * slide directives look like comments when rendered into HTML (e.g. as <!SLIDE>)
16
+ * links to auxiliary files (e.g. `img src`) are resolved relative to the source file
17
+ * generated HTML is pretty-printed
18
+ * uses RedCarpet markdown extensions, including
19
+ * tables <http://michelf.com/projects/php-markdown/extra/#table>
20
+ * fenced code blocks <http://michelf.com/projects/php-markdown/extra/#fenced-code-blocks>
14
21
 
15
22
  ## Command-Line API (proposed)
16
23
 
@@ -18,7 +25,7 @@
18
25
 
19
26
  * start a local Rack server (probably Sinatra) on port 4333
20
27
  * http://localhost:4333/ serves the presentation in foo.md
21
- * can also specify multiple source files in a row
28
+ * can specify multiple source files in a row
22
29
 
23
30
  `deck build foo.md`
24
31
 
@@ -29,35 +36,63 @@
29
36
 
30
37
  `deck deploy` ???
31
38
 
32
- * some way to build/rebuild a project that is deployable to heroky
33
-
39
+ * some way to build/rebuild a project that is deployable to heroku
34
40
 
35
41
  ### Options
36
42
 
37
- * --output dir
38
- * --config deck.json
39
- * --port portnum
40
- * --theme themename
43
+ * none yet :-)
41
44
 
42
45
  ## Credits
43
46
 
44
- * deck.js by Caleb at http://imakewebthings.com
45
- * deck.rb by Alex Chaffee http://alexchaffee.com, with help from
46
- * Steven! Ragnarök @nuclearsandwich
47
+ * deck.js by Caleb at <http://imakewebthings.com>
48
+ * deck.rb by Alex Chaffee <http://alexchaffee.com>, with help from
49
+ * Steven! Ragnarök <http://nuclearsandwich.com>
50
+
51
+ ### See Also
52
+
47
53
  * showoff by Scott Chacon
54
+ * keydown by Davis Frank
55
+
56
+ ## Bugs and Limitations
57
+
58
+ * auxiliary files are interleaved in URL path space, so overlapping file names might not resolve to the right file
59
+ * H1s are converted to H2s for compatibility with deck.js's CSS
60
+ * unless they're the only item on the slide, in which case they remain H1s
48
61
 
49
62
  ## TODO
50
63
 
51
- * markdown
52
- * multiple files
53
- * rack app
64
+ * config file
54
65
  * config:
55
- * show theme selector
56
- * show page number/nav
66
+ * show/hide theme selector
67
+ * show/hide page number/nav
57
68
  * choose deck extensions
58
- * slim
59
- * haml
69
+ * command-line tool can take a directory
70
+ * first pass: globs all *.md files in it
71
+ * command-line options:
72
+ * --output dir
73
+ * --config deck.json
74
+ * --port portnum
75
+ * --theme themename
76
+ * more slide file types
77
+ * html
78
+ * slim http://slim-lang.com/index.html
79
+ * haml
80
+ * tilt
60
81
  * specify Redcarpet Markdown extensions
61
- * syntax highlighting (using sh (js) or coderay (rack)?)
62
- * option to render all JS and CSS inline, for a self-contained HTML doc (and maybe images too)
63
-
82
+ * option to render all JS and CSS inline, for a self-contained HTML doc
83
+ * and maybe images too, base64-encoded
84
+ * image scaling
85
+ * build and push into a gh-pages branch
86
+ * build and push into a heroku app
87
+ * find any lines that start with a <p>.(something) and turn them into <p class="something">
88
+ * see showoff.rb:189
89
+ * fix title tag (base it off of presentation name or something)
90
+
91
+ ## TODO (community)
92
+
93
+ * submit theme-picker extension to deck.js
94
+ * add to deck.js wiki https://github.com/imakewebthings/deck.js/wiki
95
+ * announce on https://groups.google.com/forum/#!forum/webslideshow
96
+ * mix with keydown https://github.com/infews/keydown
97
+ * gh-pages documentation site
98
+ * integrate with slideshow https://github.com/geraldb/slideshow-deck.js
data/bin/deck CHANGED
@@ -1,12 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  here = File.expand_path(File.dirname(__FILE__))
4
- root = File.join(here, '..')
5
4
  $: << File.join(here, '..', 'lib')
6
5
 
7
6
  require "rack"
8
7
  require "deck"
9
- require "deck/app"
8
+ require "deck/rack_app"
10
9
 
11
10
  command = ARGV.shift
12
11
 
@@ -26,7 +25,7 @@ when 'build'
26
25
  end
27
26
 
28
27
  File.open(output_path, "w") do |file|
29
- deck = Deck.new :slides => slides
28
+ deck = SlideDeck.new :slides => slides
30
29
  # deck.to_pretty(:output => file) # todo: figure out why this doesn't work
31
30
  file.write deck.to_pretty
32
31
  end
@@ -36,14 +35,10 @@ when 'run'
36
35
  # Fix Rack bug https://github.com/rack/rack/issues/301
37
36
  require 'deck/rack_static_patch'
38
37
 
38
+
39
39
  port = 4333 # todo: option
40
- app = Rack::Builder.app do
41
- use Rack::ShowExceptions
42
- use Rack::ShowStatus
43
- use Rack::Static, :urls => ["/deck"], :root => root
44
- run Deck::App.new(Dir.pwd, ARGV)
45
- end
46
- Rack::Handler.default.run app, :Port => port
40
+ slide_files = ARGV
41
+ Rack::Handler.default.run Deck::RackApp.build(slide_files), :Port => port
47
42
 
48
43
  else
49
44
  puts "Unknown command '#{command}'"
@@ -3,5 +3,5 @@ here = File.expand_path(File.dirname(__FILE__))
3
3
  module Deck
4
4
  end
5
5
 
6
- require "deck/deck"
6
+ require "deck/slide_deck"
7
7
  require "deck/slide"
@@ -0,0 +1,15 @@
1
+ require 'nokogiri'
2
+
3
+ module Deck
4
+ # Wrappers around Nokogiri's occasionally inscrutable API
5
+ module Noko
6
+ def noko_html nokogiri_node
7
+ nokogiri_node.serialize(:save_with => 0).chomp
8
+ end
9
+
10
+ def noko_doc html_snippet
11
+ html_doc = html_snippet =~ /<html/ ? html_snippet : "<html>#{html_snippet}</html>"
12
+ Nokogiri.parse(html_doc)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,61 @@
1
+ here = File.expand_path File.dirname(__FILE__)
2
+
3
+ require 'coderay'
4
+ require 'rack/codehighlighter'
5
+
6
+ module Deck
7
+ class RackApp
8
+ def self.app_root
9
+ here = File.dirname(__FILE__)
10
+ app_root = File.expand_path "#{here}/../.."
11
+ end
12
+
13
+ def self.build slide_files
14
+
15
+ if const_defined?(:Thin)
16
+ if require "thin/logging"
17
+ Thin::Logging.debug = true
18
+ end
19
+ end
20
+
21
+ Rack::Builder.app do
22
+ use Rack::ShowExceptions
23
+ use Rack::ShowStatus
24
+ use Rack::Codehighlighter, :coderay,
25
+ :element => "pre>code",
26
+ :markdown => true,
27
+ :pattern => /\A[:@]{3}\s?(\w+)\s*(\n|&#x000A;)/i
28
+ run ::Deck::RackApp.new(slide_files)
29
+ end
30
+ end
31
+
32
+ def initialize slide_files
33
+ @slide_files = [slide_files].flatten
34
+
35
+ @file_servers =
36
+ [Rack::File.new("#{::Deck::RackApp.app_root}/public")] +
37
+ @slide_files.map do |slide_file|
38
+ Rack::File.new(File.dirname slide_file)
39
+ end
40
+ end
41
+
42
+ def call env
43
+ request = Rack::Request.new(env)
44
+ if request.path == "/"
45
+ slides = []
46
+ @slide_files.each do |file|
47
+ slides += Slide.from_file file
48
+ end
49
+ deck = SlideDeck.new :slides => slides
50
+ [200, {'Content-Type' => 'text/html'}, [deck.to_pretty]]
51
+ else
52
+ result = [404, {}, []]
53
+ @file_servers.each do |file_server|
54
+ result = file_server.call(env)
55
+ return result if result.first < 400
56
+ end
57
+ result
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,10 +1,12 @@
1
1
  # based on work by Alex and others in Showoff
2
2
  require 'redcarpet'
3
-
3
+ require 'deck/noko'
4
4
 
5
5
  module Deck
6
6
  class Slide < Erector::Widget
7
7
 
8
+ include Deck::Noko
9
+
8
10
  # todo: test this method
9
11
  def self.from_file markdown_file
10
12
  split File.read(markdown_file)
@@ -12,8 +14,10 @@ module Deck
12
14
 
13
15
  # given a chunk of Markdown text, splits it into an array of Slide objects
14
16
  def self.split content
15
- unless content =~ /^\<?!SLIDE/m
16
- content = content.gsub(/^# /m, "<!SLIDE>\n# ")
17
+ unless content =~ /^\<?!SLIDE/m # this only applies to files with no !SLIDEs at all, which is odd
18
+ content = content.
19
+ gsub(/^# /m, "<!SLIDE>\n# ").
20
+ gsub(/^(.*)\n(===+)/, "<!SLIDE>\n\\1\n\\2")
17
21
  end
18
22
 
19
23
  lines = content.split("\n")
@@ -24,7 +28,7 @@ module Deck
24
28
  if line =~ /^<?!SLIDE(.*)>?/
25
29
  slides << (slide = Slide.new(:classes => $1))
26
30
 
27
- elsif line =~ /^# / and !slide.empty?
31
+ elsif (line =~ /^# / or lines.first =~ /^(===+)/) and !slide.empty?
28
32
  # every H1 defines a new slide, unless there's a !SLIDE before it
29
33
  slides << (slide = Slide.new)
30
34
  slide << line
@@ -44,15 +48,15 @@ module Deck
44
48
  attr_reader :classes, :markdown_text
45
49
 
46
50
  needs :classes => nil, :markdown_text => nil, :slide_id => nil
47
-
48
-
51
+
52
+
49
53
  def initialize options = {}
50
54
  super options
51
-
55
+
52
56
  @classes = process_classes
53
57
  @markdown_text = ""
54
58
  end
55
-
59
+
56
60
  def process_classes
57
61
  ["slide"] + case @classes
58
62
  when NilClass
@@ -64,7 +68,7 @@ module Deck
64
68
  else
65
69
  raise "can't deal with :classes => #{@classes.inspect}"
66
70
  end
67
- end
71
+ end
68
72
 
69
73
  def markdown
70
74
  @@markdown ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML,
@@ -79,42 +83,60 @@ module Deck
79
83
  :superscript => false
80
84
  )
81
85
  end
82
-
86
+
83
87
  def <<(s)
84
88
  @markdown_text << s
85
89
  @markdown_text << "\n"
86
90
  end
87
-
91
+
88
92
  def empty?
89
93
  @markdown_text.strip == ""
90
94
  end
91
-
95
+
92
96
  def slide_id
93
97
  @slide_id ||= begin
94
98
  lines = @markdown_text.split("\n")
95
99
  raise "an empty slide has no id" if lines.empty?
96
- lines.first.gsub(/^#*/, '').strip.downcase.gsub(/[^\w\s]/, '').gsub(/\s/, '_')
97
- end
98
- end
99
-
100
- def header_only?
101
- markdown_text.strip =~ /^# / and markdown_text.strip.split("\n").size == 1
102
- end
103
-
104
- def massaged_markdown_text
105
- unless header_only?
106
- "##{markdown_text.strip}"
107
- else
108
- markdown_text
100
+ lines.first.downcase.gsub(/[^\w\s]/, '').strip.gsub(/\s/, '_')
109
101
  end
110
102
  end
111
-
103
+
112
104
  def content
113
105
  section :class => @classes, :id => slide_id do
114
106
  text "\n" # markdown HTML should be left-aligned, in case of PRE blocks and other quirks
115
- html = markdown.render(massaged_markdown_text)
107
+ html = markdown.render(markdown_text)
108
+ html = munge(html)
116
109
  rawtext html
117
- end
110
+ end
118
111
  end
112
+
113
+ private
114
+
115
+ # if there is an H1, change it to an H2, unless it's the only thing there
116
+ # TODO: or unless the slide class is whatever
117
+ def mutate_h1? doc
118
+ h1s = doc.css('h1') || []
119
+ if h1s.size == 0
120
+ false
121
+ else
122
+ stuff = doc.css('body>*')
123
+ if stuff.size == 1
124
+ false
125
+ else
126
+ true
127
+ end
128
+ end
129
+ end
130
+
131
+ def munge html
132
+ doc = noko_doc(html)
133
+ if mutate_h1? doc
134
+ doc.css('h1').each {|node| node.node_name = "h2"}
135
+ doc.css('body').inner_html + "\n"
136
+ else
137
+ html
138
+ end
139
+ end
140
+
119
141
  end
120
142
  end
@@ -4,23 +4,23 @@ require 'redcarpet'
4
4
  require "deck/slide"
5
5
 
6
6
  module Deck
7
- class Deck < Erector::Widgets::Page
7
+ class SlideDeck < Erector::Widgets::Page
8
8
  needs :title => "deck.rb presentation",
9
9
  :description => nil,
10
10
  :author => nil
11
-
11
+
12
12
  needs :slides => nil
13
-
13
+
14
14
  def page_title
15
15
  @title
16
16
  end
17
-
17
+
18
18
  # todo: promote into Text
19
19
  # todo: support numbers a la '&#1234;'
20
20
  def entity entity_id
21
21
  raw("&#{entity_id};")
22
22
  end
23
-
23
+
24
24
  # left over from deck.js' introduction/index.html
25
25
 
26
26
  # <!DOCTYPE html>
@@ -34,54 +34,55 @@ module Deck
34
34
  link({:rel => "stylesheet", :href => src}.merge(attributes))
35
35
  end
36
36
 
37
+ def extensions
38
+ @extensions || [
39
+ 'goto',
40
+ 'menu',
41
+ 'navigation',
42
+ 'status',
43
+ 'hash',
44
+ 'scale',
45
+ # 'theme-picker',
46
+ ]
47
+ end
48
+
37
49
  def head_content
38
50
  super
39
51
  meta 'charset' => 'utf-8'
40
52
  meta 'http-equiv'=>"X-UA-Compatible", 'content'=>"IE=edge,chrome=1"
41
- meta :name=>"viewport", :content=>"width=1024, user-scalable=no"
53
+ meta :name => "viewport", :content=> "width=1024, user-scalable=no"
42
54
  meta :name => "description", :content=> @description if @description
43
55
  meta :name => "author", :content=> @author if @author
44
56
 
57
+ stylesheet "coderay.css"
58
+
45
59
  # <!-- Core and extension CSS files -->
46
- stylesheet "deck/core/deck.core.css"
47
-
48
- stylesheet "deck/extensions/goto/deck.goto.css"
49
- stylesheet "deck/extensions/menu/deck.menu.css"
50
- stylesheet "deck/extensions/navigation/deck.navigation.css"
51
- stylesheet "deck/extensions/status/deck.status.css"
52
- stylesheet "deck/extensions/hash/deck.hash.css"
53
- stylesheet "deck/extensions/scale/deck.scale.css"
54
-
55
- stylesheet "deck/extensions/theme-picker/deck.theme-picker.css"
56
-
60
+ stylesheet "deck.js/core/deck.core.css"
61
+ extensions.each do |extension|
62
+ stylesheet "deck.js/extensions/#{extension}/deck.#{extension}.css"
63
+ end
64
+
57
65
  # <!-- Theme CSS files (menu swaps these out) -->
58
- stylesheet "deck/themes/style/web-2.0.css", :id=>"style-theme-link"
59
- stylesheet "deck/themes/transition/horizontal-slide.css", :id => "transition-theme-link"
60
-
61
- script :src=>"deck/modernizr.custom.js"
66
+ stylesheet "deck.js/themes/style/swiss.css", :id=>"style-theme-link"
62
67
  end
63
68
 
64
69
  def scripts
70
+ script :src => "deck.js/modernizr.custom.js"
71
+
65
72
  # comment 'Grab CDN jQuery, with a protocol relative URL; fall back to local if offline'
66
73
  # script :src => '//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.min.js'
67
- script :src => './deck/jquery-1.7.min.js'
68
-
69
- comment 'Deck Core and extensions'
70
- script :type => "text/javascript", :src => 'deck/core/deck.core.js'
74
+ script :src => 'deck.js/jquery-1.7.min.js'
71
75
 
72
- script :type => "text/javascript", :src => 'deck/extensions/hash/deck.hash.js'
73
- script :type => "text/javascript", :src => 'deck/extensions/menu/deck.menu.js'
74
- script :type => "text/javascript", :src => 'deck/extensions/goto/deck.goto.js'
75
- script :type => "text/javascript", :src => 'deck/extensions/status/deck.status.js'
76
- script :type => "text/javascript", :src => 'deck/extensions/navigation/deck.navigation.js'
77
- script :type => "text/javascript", :src => 'deck/extensions/scale/deck.scale.js'
76
+ comment 'Deck Core and extensions'
77
+ script :type => "text/javascript", :src => 'deck.js/core/deck.core.js'
78
78
 
79
+ extensions.each do |extension|
80
+ script :type => "text/javascript", :src => "deck.js/extensions/#{extension}/deck.#{extension}.js"
81
+ end
79
82
 
80
83
  # fire up deck.js
81
84
  script "$(function(){$.deck('.slide');});"
82
-
83
- script :type => "text/javascript", :src => 'deck/extensions/theme-picker/deck.theme-picker.js'
84
-
85
+
85
86
  end
86
87
 
87
88
  def body_attributes
@@ -96,7 +97,7 @@ module Deck
96
97
  permalink
97
98
  scripts
98
99
  end
99
-
100
+
100
101
  def slide slide_id
101
102
  # todo: use Slide object, but without markdown
102
103
  # slide = Slide.new(:slide_id => slide_id)
@@ -104,7 +105,7 @@ module Deck
104
105
  yield
105
106
  end
106
107
  end
107
-
108
+
108
109
  def slides
109
110
  if @slides
110
111
  @slides.each do |slide|
@@ -114,14 +115,14 @@ module Deck
114
115
  default_slide
115
116
  end
116
117
  end
117
-
118
+
118
119
  def default_slide
119
120
  slide 'readme' do
120
121
  h2 "deck.rb"
121
122
  ul {
122
123
  li "based on deck.js"
123
124
  li "create a subclass of Deck (see introduction.rb)"
124
- li "run erector to build it"
125
+ li "run erector to build it"
125
126
  }
126
127
  pre "erector --to-html ./deck.rb # generates deck.html"
127
128
  end
@@ -145,7 +146,7 @@ module Deck
145
146
  end
146
147
  end
147
148
  end
148
-
149
+
149
150
  def goto_slide
150
151
  form :action => '.', :method => 'get', :class => 'goto-form' do
151
152
  label :for => 'goto-slide' do
@@ -161,6 +162,6 @@ module Deck
161
162
  def permalink
162
163
  a "#", :href => '.', :title => 'Permalink to this slide', :class => 'deck-permalink'
163
164
  end
164
-
165
+
165
166
  end
166
- end
167
+ end