deckrb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/README.md +63 -0
  2. data/bin/deck +59 -0
  3. data/deck/GPL-license.txt +278 -0
  4. data/deck/MIT-license.txt +21 -0
  5. data/deck/README.md +57 -0
  6. data/deck/core/deck.core.css +404 -0
  7. data/deck/core/deck.core.html +39 -0
  8. data/deck/core/deck.core.js +498 -0
  9. data/deck/core/deck.core.scss +447 -0
  10. data/deck/extensions/goto/deck.goto.css +41 -0
  11. data/deck/extensions/goto/deck.goto.html +7 -0
  12. data/deck/extensions/goto/deck.goto.js +134 -0
  13. data/deck/extensions/goto/deck.goto.scss +46 -0
  14. data/deck/extensions/hash/deck.hash.css +13 -0
  15. data/deck/extensions/hash/deck.hash.html +2 -0
  16. data/deck/extensions/hash/deck.hash.js +129 -0
  17. data/deck/extensions/hash/deck.hash.scss +15 -0
  18. data/deck/extensions/menu/deck.menu.css +47 -0
  19. data/deck/extensions/menu/deck.menu.js +187 -0
  20. data/deck/extensions/menu/deck.menu.scss +58 -0
  21. data/deck/extensions/navigation/deck.navigation.css +43 -0
  22. data/deck/extensions/navigation/deck.navigation.html +3 -0
  23. data/deck/extensions/navigation/deck.navigation.js +91 -0
  24. data/deck/extensions/navigation/deck.navigation.scss +56 -0
  25. data/deck/extensions/scale/deck.scale.css +16 -0
  26. data/deck/extensions/scale/deck.scale.js +155 -0
  27. data/deck/extensions/scale/deck.scale.scss +17 -0
  28. data/deck/extensions/status/deck.status.css +18 -0
  29. data/deck/extensions/status/deck.status.html +6 -0
  30. data/deck/extensions/status/deck.status.js +95 -0
  31. data/deck/extensions/status/deck.status.scss +22 -0
  32. data/deck/extensions/theme-picker/deck.theme-picker.css +55 -0
  33. data/deck/extensions/theme-picker/deck.theme-picker.js +13 -0
  34. data/deck/introduction/index.html +221 -0
  35. data/deck/introduction/index.rb +101 -0
  36. data/deck/jquery-1.7.min.js +4 -0
  37. data/deck/modernizr.custom.js +4 -0
  38. data/deck/test/fixtures/complex.html +24 -0
  39. data/deck/test/fixtures/empty.html +19 -0
  40. data/deck/test/fixtures/iframe_simple.html +10 -0
  41. data/deck/test/fixtures/iframes.html +32 -0
  42. data/deck/test/fixtures/nesteds.html +36 -0
  43. data/deck/test/fixtures/standard.html +42 -0
  44. data/deck/test/index.html +39 -0
  45. data/deck/test/lib/jasmine-html.js +190 -0
  46. data/deck/test/lib/jasmine-jquery.js +288 -0
  47. data/deck/test/lib/jasmine.css +166 -0
  48. data/deck/test/lib/jasmine.js +2477 -0
  49. data/deck/test/settings.js +3 -0
  50. data/deck/test/spec.core.js +434 -0
  51. data/deck/test/spec.goto.js +119 -0
  52. data/deck/test/spec.hash.js +81 -0
  53. data/deck/test/spec.menu.js +66 -0
  54. data/deck/test/spec.navigation.js +51 -0
  55. data/deck/test/spec.scale.js +57 -0
  56. data/deck/test/spec.status.js +58 -0
  57. data/deck/themes/style/neon.css +114 -0
  58. data/deck/themes/style/neon.scss +139 -0
  59. data/deck/themes/style/swiss.css +75 -0
  60. data/deck/themes/style/swiss.scss +91 -0
  61. data/deck/themes/style/web-2.0.css +205 -0
  62. data/deck/themes/style/web-2.0.scss +236 -0
  63. data/deck/themes/transition/fade.css +44 -0
  64. data/deck/themes/transition/fade.scss +70 -0
  65. data/deck/themes/transition/horizontal-slide.css +79 -0
  66. data/deck/themes/transition/horizontal-slide.scss +94 -0
  67. data/deck/themes/transition/vertical-slide.css +97 -0
  68. data/deck/themes/transition/vertical-slide.scss +116 -0
  69. data/lib/deck.rb +7 -0
  70. data/lib/deck/app.rb +16 -0
  71. data/lib/deck/deck.rb +166 -0
  72. data/lib/deck/rack_static_patch.rb +13 -0
  73. data/lib/deck/slide.rb +120 -0
  74. data/lib/deck/version.rb +3 -0
  75. data/spec/deck_spec.rb +98 -0
  76. data/spec/javascripts/support/jasmine_config.rb +23 -0
  77. data/spec/javascripts/support/jasmine_runner.rb +32 -0
  78. data/spec/slide_spec.rb +285 -0
  79. data/spec/spec_helper.rb +7 -0
  80. metadata +172 -0
data/lib/deck.rb ADDED
@@ -0,0 +1,7 @@
1
+ here = File.expand_path(File.dirname(__FILE__))
2
+
3
+ module Deck
4
+ end
5
+
6
+ require "deck/deck"
7
+ require "deck/slide"
data/lib/deck/app.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Deck
2
+ class App
3
+ def initialize root, files
4
+ @root, @files = root, files
5
+ end
6
+
7
+ def call env
8
+ slides = []
9
+ @files.each do |file|
10
+ slides += Slide.from_file "#{@root}/#{file}"
11
+ end
12
+ deck = Deck.new :slides => slides
13
+ [200, {}, deck.to_pretty]
14
+ end
15
+ end
16
+ end
data/lib/deck/deck.rb ADDED
@@ -0,0 +1,166 @@
1
+ require 'erector'
2
+ require 'redcarpet'
3
+
4
+ require "deck/slide"
5
+
6
+ module Deck
7
+ class Deck < Erector::Widgets::Page
8
+ needs :title => "deck.rb presentation",
9
+ :description => nil,
10
+ :author => nil
11
+
12
+ needs :slides => nil
13
+
14
+ def page_title
15
+ @title
16
+ end
17
+
18
+ # todo: promote into Text
19
+ # todo: support numbers a la '&#1234;'
20
+ def entity entity_id
21
+ raw("&#{entity_id};")
22
+ end
23
+
24
+ # left over from deck.js' introduction/index.html
25
+
26
+ # <!DOCTYPE html>
27
+ # <!--[if lt IE 7]> <html class="no-js ie6" lang="en"> <![endif]-->
28
+ # <!--[if IE 7]> <html class="no-js ie7" lang="en"> <![endif]-->
29
+ # <!--[if IE 8]> <html class="no-js ie8" lang="en"> <![endif]-->
30
+ # <!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
31
+
32
+ # todo: promote into Page
33
+ def stylesheet src, attributes = {}
34
+ link({:rel => "stylesheet", :href => src}.merge(attributes))
35
+ end
36
+
37
+ def head_content
38
+ super
39
+ meta 'charset' => 'utf-8'
40
+ meta 'http-equiv'=>"X-UA-Compatible", 'content'=>"IE=edge,chrome=1"
41
+ meta :name=>"viewport", :content=>"width=1024, user-scalable=no"
42
+ meta :name => "description", :content=> @description if @description
43
+ meta :name => "author", :content=> @author if @author
44
+
45
+ # <!-- 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
+
57
+ # <!-- 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"
62
+ end
63
+
64
+ def scripts
65
+ # comment 'Grab CDN jQuery, with a protocol relative URL; fall back to local if offline'
66
+ # 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'
71
+
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'
78
+
79
+
80
+ # fire up deck.js
81
+ script "$(function(){$.deck('.slide');});"
82
+
83
+ script :type => "text/javascript", :src => 'deck/extensions/theme-picker/deck.theme-picker.js'
84
+
85
+ end
86
+
87
+ def body_attributes
88
+ {:class=>"deck-container"}
89
+ end
90
+
91
+ def body_content
92
+ slides
93
+ slide_navigation
94
+ deck_status
95
+ goto_slide
96
+ permalink
97
+ scripts
98
+ end
99
+
100
+ def slide slide_id
101
+ # todo: use Slide object, but without markdown
102
+ # slide = Slide.new(:slide_id => slide_id)
103
+ section.slide :id => slide_id do
104
+ yield
105
+ end
106
+ end
107
+
108
+ def slides
109
+ if @slides
110
+ @slides.each do |slide|
111
+ widget slide
112
+ end
113
+ else
114
+ default_slide
115
+ end
116
+ end
117
+
118
+ def default_slide
119
+ slide 'readme' do
120
+ h2 "deck.rb"
121
+ ul {
122
+ li "based on deck.js"
123
+ li "create a subclass of Deck (see introduction.rb)"
124
+ li "run erector to build it"
125
+ }
126
+ pre "erector --to-html ./deck.rb # generates deck.html"
127
+ end
128
+ end
129
+
130
+ def slide_navigation
131
+ a :href => '#', :class => 'deck-prev-link', :title => 'Previous' do
132
+ character 8592
133
+ end
134
+ a :href => '#', :class => 'deck-next-link', :title => 'Next' do
135
+ character 8594
136
+ end
137
+ end
138
+
139
+ def deck_status
140
+ p :class => 'deck-status' do
141
+ span :class => 'deck-status-current' do
142
+ end
143
+ text '/'
144
+ span :class => 'deck-status-total' do
145
+ end
146
+ end
147
+ end
148
+
149
+ def goto_slide
150
+ form :action => '.', :method => 'get', :class => 'goto-form' do
151
+ label :for => 'goto-slide' do
152
+ text 'Go to slide:'
153
+ end
154
+ input :type => 'text', :name => 'slidenum', :id => 'goto-slide', :list => 'goto-datalist'
155
+ datalist :id => 'goto-datalist' do
156
+ end
157
+ input :type => 'submit', :value => 'Go'
158
+ end
159
+ end
160
+
161
+ def permalink
162
+ a "#", :href => '.', :title => 'Permalink to this slide', :class => 'deck-permalink'
163
+ end
164
+
165
+ end
166
+ end
@@ -0,0 +1,13 @@
1
+ # Fix Rack bug https://github.com/rack/rack/issues/301
2
+ module Rack
3
+ class Static
4
+ def initialize(app, options={})
5
+ @app = app
6
+ @urls = options[:urls] || ["/favicon.ico"]
7
+ @index = options[:index]
8
+ root = options[:root] || Dir.pwd
9
+ cache_control = options[:cache_control]
10
+ @file_server = Rack::File.new(root, cache_control)
11
+ end
12
+ end
13
+ end
data/lib/deck/slide.rb ADDED
@@ -0,0 +1,120 @@
1
+ # based on work by Alex and others in Showoff
2
+ require 'redcarpet'
3
+
4
+
5
+ module Deck
6
+ class Slide < Erector::Widget
7
+
8
+ # todo: test this method
9
+ def self.from_file markdown_file
10
+ split File.read(markdown_file)
11
+ end
12
+
13
+ # given a chunk of Markdown text, splits it into an array of Slide objects
14
+ def self.split content
15
+ unless content =~ /^\<?!SLIDE/m
16
+ content = content.gsub(/^# /m, "<!SLIDE>\n# ")
17
+ end
18
+
19
+ lines = content.split("\n")
20
+ slides = []
21
+ slides << (slide = Slide.new)
22
+ until lines.empty?
23
+ line = lines.shift
24
+ if line =~ /^<?!SLIDE(.*)>?/
25
+ slides << (slide = Slide.new(:classes => $1))
26
+
27
+ elsif line =~ /^# / and !slide.empty?
28
+ # every H1 defines a new slide, unless there's a !SLIDE before it
29
+ slides << (slide = Slide.new)
30
+ slide << line
31
+
32
+ else
33
+ slide << line
34
+ end
35
+ end
36
+
37
+ slides.delete_if {|slide| slide.empty? }
38
+
39
+ slides
40
+ end
41
+
42
+ ####
43
+
44
+ attr_reader :classes, :markdown_text
45
+
46
+ needs :classes => nil, :markdown_text => nil, :slide_id => nil
47
+
48
+
49
+ def initialize options = {}
50
+ super options
51
+
52
+ @classes = process_classes
53
+ @markdown_text = ""
54
+ end
55
+
56
+ def process_classes
57
+ ["slide"] + case @classes
58
+ when NilClass
59
+ []
60
+ when String
61
+ @classes.strip.chomp('>').split
62
+ when Array
63
+ @classes
64
+ else
65
+ raise "can't deal with :classes => #{@classes.inspect}"
66
+ end
67
+ end
68
+
69
+ def markdown
70
+ @@markdown ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML,
71
+ :no_intra_emphasis => true,
72
+ :tables => true,
73
+ :fenced_code_blocks => true,
74
+ :no_intra_emphasis => true,
75
+ :autolink => true,
76
+ :strikethrough => true,
77
+ :lax_html_blocks => false,
78
+ :space_after_headers => true,
79
+ :superscript => false
80
+ )
81
+ end
82
+
83
+ def <<(s)
84
+ @markdown_text << s
85
+ @markdown_text << "\n"
86
+ end
87
+
88
+ def empty?
89
+ @markdown_text.strip == ""
90
+ end
91
+
92
+ def slide_id
93
+ @slide_id ||= begin
94
+ lines = @markdown_text.split("\n")
95
+ 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
109
+ end
110
+ end
111
+
112
+ def content
113
+ section :class => @classes, :id => slide_id do
114
+ text "\n" # markdown HTML should be left-aligned, in case of PRE blocks and other quirks
115
+ html = markdown.render(massaged_markdown_text)
116
+ rawtext html
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,3 @@
1
+ module Deck
2
+ VERSION = "0.1.0"
3
+ end
data/spec/deck_spec.rb ADDED
@@ -0,0 +1,98 @@
1
+ here = File.expand_path File.dirname(__FILE__)
2
+ require "#{here}/spec_helper"
3
+
4
+ require "deck/deck"
5
+
6
+ module Deck
7
+ describe Deck do
8
+ def temp_dir options = {:remove => true}
9
+ @temp_dir ||= begin
10
+ require 'tmpdir'
11
+ require 'fileutils'
12
+ called_from = File.basename caller.first.split(':').first, ".rb"
13
+ path = File.join(Dir::tmpdir, "#{called_from}_#{Time.now.to_i}_#{rand(1000)}")
14
+ Dir.mkdir(path)
15
+ at_exit {FileUtils.rm_rf(path) if File.exists?(path)} if options[:remove]
16
+ path
17
+ end
18
+ end
19
+
20
+ def to_html nokogiri_node
21
+ nokogiri_node.serialize(:save_with => 0).chomp
22
+ end
23
+
24
+ def as_html_page snippet
25
+ snippet =~ /<html/ ? snippet : "<html>#{snippet}</html>"
26
+ end
27
+
28
+ def deck_widget options = {}
29
+ @deck_widget ||= Deck.new options
30
+ end
31
+
32
+ def doc
33
+ @doc ||= begin
34
+ @html = deck_widget.to_html
35
+ Nokogiri.parse(as_html_page(@html))
36
+ end
37
+ end
38
+
39
+ def write name, contents = "contents of #{name}"
40
+ path = "#{temp_dir}/#{name}"
41
+ File.open(path, "w") do |f|
42
+ f.write contents
43
+ end
44
+ File.new path
45
+ end
46
+
47
+ describe "#write" do
48
+ before do
49
+ @hello = write "hello.txt"
50
+ @goodbye = write "goodbye.txt", "farewell"
51
+ end
52
+
53
+ it "uses temp_dir" do
54
+ File.dirname(@hello).should == temp_dir
55
+ File.dirname(@goodbye).should == temp_dir
56
+ end
57
+
58
+ it "writes a default value" do
59
+ File.read(@hello).should == "contents of hello.txt"
60
+ end
61
+
62
+ it "writes a given value" do
63
+ # since write returns a File instance, we can call read on it
64
+ @goodbye.read.should == "farewell"
65
+ end
66
+
67
+ it "writes a file" do
68
+ file = write("hello.md", "# hello")
69
+ assert { File.read(file) == "# hello" }
70
+ end
71
+
72
+ end
73
+
74
+
75
+ it "renders a basic deck.js HTML page" do
76
+ assert { doc }
77
+ assert { @html.include? '<link href="deck/core/deck.core.css" rel="stylesheet" />' }
78
+ end
79
+
80
+ it "contains a single dummy slide" do
81
+ assert { doc.css('section.slide').size == 1 }
82
+ end
83
+
84
+ it "renders a markdown file with one slide" do
85
+ file = write("hello.md", "# hello")
86
+
87
+ deck_widget :slides => Slide.split(File.read file)
88
+ assert { doc.css('section.slide').size == 1 }
89
+ slide = doc.css('section.slide').first
90
+ assert { slide["id"] == "hello" }
91
+ assert { to_html(slide) == "<section class=\"slide\" id=\"hello\">" +
92
+ "<h1>hello</h1>\n" +
93
+ "</section>"
94
+ }
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,23 @@
1
+ module Jasmine
2
+ class Config
3
+
4
+ # Add your overrides or custom config code here
5
+
6
+ end
7
+ end
8
+
9
+
10
+ # Note - this is necessary for rspec2, which has removed the backtrace
11
+ module Jasmine
12
+ class SpecBuilder
13
+ def declare_spec(parent, spec)
14
+ me = self
15
+ example_name = spec["name"]
16
+ @spec_ids << spec["id"]
17
+ backtrace = @example_locations[parent.description + " " + example_name]
18
+ parent.it example_name, {} do
19
+ me.report_spec(spec["id"])
20
+ end
21
+ end
22
+ end
23
+ end