magic_reveal 2.4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +88 -0
- data/Rakefile +10 -0
- data/bin/magic-reveal +7 -0
- data/lib/magic_reveal/app.rb +50 -0
- data/lib/magic_reveal/cli/options.rb +30 -0
- data/lib/magic_reveal/cli.rb +43 -0
- data/lib/magic_reveal/conductor.rb +51 -0
- data/lib/magic_reveal/creator.rb +49 -0
- data/lib/magic_reveal/identifier.rb +30 -0
- data/lib/magic_reveal/index_libber.rb +37 -0
- data/lib/magic_reveal/reveal_js_fetcher.rb +31 -0
- data/lib/magic_reveal/slide_renderer.rb +59 -0
- data/lib/magic_reveal/template-config.ru +2 -0
- data/lib/magic_reveal/version.rb +4 -0
- data/lib/magic_reveal.rb +7 -0
- data/magic-reveal.gemspec +45 -0
- data/spec/data/wrapped.zip +0 -0
- data/spec/magic_reveal/app_spec.rb +6 -0
- data/spec/magic_reveal/cli/options_spec.rb +34 -0
- data/spec/magic_reveal/cli_spec.rb +58 -0
- data/spec/magic_reveal/conductor_spec.rb +44 -0
- data/spec/magic_reveal/creator_spec.rb +56 -0
- data/spec/magic_reveal/identifier_spec.rb +98 -0
- data/spec/magic_reveal/index_libber_spec.rb +43 -0
- data/spec/magic_reveal/reveal_js_fetcher_spec.rb +45 -0
- data/spec/magic_reveal/slide_renderer_spec.rb +124 -0
- data/spec/magic_reveal_spec.rb +8 -0
- data/spec/spec_helper.rb +23 -0
- metadata +329 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'magic_reveal/cli'
|
3
|
+
|
4
|
+
|
5
|
+
describe MagicReveal::Cli do
|
6
|
+
describe ".run" do
|
7
|
+
context "with a null options" do
|
8
|
+
let(:options) { double(MagicReveal::Cli::Options).as_null_object }
|
9
|
+
let(:args) { double("ARGV") }
|
10
|
+
before { subject.stub(:options).and_return(options) }
|
11
|
+
|
12
|
+
context "command=nil" do
|
13
|
+
before { subject.run args }
|
14
|
+
|
15
|
+
it "parses the args" do
|
16
|
+
expect(options).to have_received(:parse).with(args)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "fetches the command" do
|
20
|
+
expect(options).to have_received(:command)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "command=new" do
|
25
|
+
let(:creator) { double(MagicReveal::Creator).as_null_object }
|
26
|
+
before do
|
27
|
+
subject.creator = creator
|
28
|
+
options.stub(:command).and_return(:new)
|
29
|
+
subject.run args
|
30
|
+
end
|
31
|
+
|
32
|
+
it "fetches the project" do
|
33
|
+
expect(options).to have_received(:project)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates the project" do
|
37
|
+
expect(creator).
|
38
|
+
to have_received(:create_project).
|
39
|
+
with(options.project)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe ".creator" do
|
46
|
+
it "narf" do
|
47
|
+
MagicReveal::Creator.should_receive(:new).with(Dir.getwd)
|
48
|
+
subject.creator
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe ".options" do
|
53
|
+
it "responds to 'parse'" do
|
54
|
+
subject.options.should respond_to(:parse)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'magic_reveal/conductor'
|
3
|
+
|
4
|
+
describe MagicReveal::Conductor do
|
5
|
+
subject { described_class.new 'http://localhost/conductor_test/' }
|
6
|
+
|
7
|
+
around do |example|
|
8
|
+
Dir.mktmpdir('conductor') do |tmpdir|
|
9
|
+
@tmpdir = Pathname.new tmpdir
|
10
|
+
example.run
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
its(:url) { should be_kind_of(URI) }
|
15
|
+
|
16
|
+
describe ".fetch" do
|
17
|
+
it "should save a file" do
|
18
|
+
subject.url = "http://google.com/"
|
19
|
+
save_file = @tmpdir + 'index.html'
|
20
|
+
subject.fetch save_file
|
21
|
+
save_file.should exist
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".unpack" do
|
26
|
+
let(:unpack_dir) { @tmpdir + "unpack-#{rand 200}" }
|
27
|
+
context "given a zipfile" do
|
28
|
+
let(:zipfile) { EXAMPLE_DATA + 'wrapped.zip' }
|
29
|
+
|
30
|
+
it "unpacks and unwraps the zipfile" do
|
31
|
+
subject.unpack zipfile, unpack_dir
|
32
|
+
(unpack_dir + 'testfile.md').should exist
|
33
|
+
end
|
34
|
+
|
35
|
+
context "and the unpack directory exists already" do
|
36
|
+
before { unpack_dir.mkdir }
|
37
|
+
|
38
|
+
it "should raise an error" do
|
39
|
+
expect { subject.unpack zipfile, unpack_dir }.to raise_error(MagicReveal::Error)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'magic_reveal/creator'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
describe MagicReveal::Creator do
|
6
|
+
before { subject.reveal_js_fetcher = fetcher }
|
7
|
+
let(:fetcher) { double(MagicReveal::RevealJsFetcher).as_null_object }
|
8
|
+
|
9
|
+
context "with a temporary directory" do
|
10
|
+
subject { described_class.new @tmpdir }
|
11
|
+
around { |example| Dir.mktmpdir { |dir| @tmpdir = Pathname.new dir; example.run } }
|
12
|
+
|
13
|
+
its(:directory) { should eq(@tmpdir) }
|
14
|
+
|
15
|
+
describe "create_project" do
|
16
|
+
let(:project) { "project#{rand 99}" }
|
17
|
+
before { FileUtils.stub(:copy_file) }
|
18
|
+
|
19
|
+
it "makes the project directory" do
|
20
|
+
subject.create_project(project)
|
21
|
+
expect(@tmpdir + project).to be_directory
|
22
|
+
end
|
23
|
+
|
24
|
+
it "fetches and saves reveal.js" do
|
25
|
+
subject.create_project(project)
|
26
|
+
expect(fetcher).
|
27
|
+
to have_received(:save_to).
|
28
|
+
with(@tmpdir + project + 'reveal.js')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "copies the template_slides" do
|
32
|
+
src = subject.template_slides
|
33
|
+
dst = @tmpdir + project + 'slides.md'
|
34
|
+
FileUtils.should_receive(:copy_file).with(src.to_s, dst.to_s)
|
35
|
+
subject.create_project(project)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "copies the template_config_ru" do
|
39
|
+
src = subject.template_config_ru
|
40
|
+
dst = @tmpdir + project + 'config.ru'
|
41
|
+
FileUtils.should_receive(:copy_file).with(src.to_s, dst.to_s)
|
42
|
+
subject.create_project(project)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe ".template_slides" do
|
47
|
+
its(:template_slides) { should be_kind_of(Pathname) }
|
48
|
+
its(:template_slides) { should be_file }
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".template_config_ru" do
|
52
|
+
its(:template_config_ru) { should be_kind_of(Pathname) }
|
53
|
+
its(:template_config_ru) { should be_file }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'magic_reveal/identifier'
|
3
|
+
|
4
|
+
describe MagicReveal::Identifier do
|
5
|
+
subject { described_class.new sys_admin }
|
6
|
+
let(:sys_admin) { double(Sys::Admin).as_null_object }
|
7
|
+
|
8
|
+
describe ".name" do
|
9
|
+
before do
|
10
|
+
sys_admin.stub(:respond_to?)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "gets the login" do
|
14
|
+
subject.name
|
15
|
+
expect(sys_admin).to have_received(:get_login)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "passes the login to get_user" do
|
19
|
+
subject.name
|
20
|
+
expect(sys_admin).to have_received(:get_user).with(sys_admin.get_login)
|
21
|
+
end
|
22
|
+
|
23
|
+
context "the user has a full_name" do
|
24
|
+
let(:user) { double(Sys::Admin::User) }
|
25
|
+
before do
|
26
|
+
sys_admin.stub(:get_user).with(sys_admin.get_login).and_return(user)
|
27
|
+
sys_admin.stub(:respond_to?).with(:full_name).and_return(true)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns the full_name" do
|
31
|
+
name = double("full_name")
|
32
|
+
user.should receive(:full_name).and_return(name)
|
33
|
+
expect(subject.name).to eq(name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "the user has a simple gecos" do
|
38
|
+
let(:user) { double(Sys::Admin::User) }
|
39
|
+
before do
|
40
|
+
sys_admin.stub(:get_user).with(sys_admin.get_login).and_return(user)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns the gecos" do
|
44
|
+
gecos = "Joe Cool #{rand 99}"
|
45
|
+
user.should receive(:gecos).and_return(gecos)
|
46
|
+
expect(subject.name).to eq(gecos)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "the user has a comma-delimited gecos" do
|
51
|
+
let(:user) { double(Sys::Admin::User) }
|
52
|
+
before do
|
53
|
+
sys_admin.stub(:get_user).with(sys_admin.get_login).and_return(user)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns the gecos" do
|
57
|
+
name = "Joe Cool #{rand 99}"
|
58
|
+
gecos = "#{name},White House,412 555-1212,"
|
59
|
+
user.should receive(:gecos).and_return(gecos)
|
60
|
+
expect(subject.name).to eq(name)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "the user has an empty comma-delimited gecos" do
|
65
|
+
it "returns the gecos" do
|
66
|
+
login = "joecool#{rand 99}"
|
67
|
+
user = double(Sys::Admin::User)
|
68
|
+
|
69
|
+
sys_admin.stub(:get_login).and_return(login)
|
70
|
+
sys_admin.stub(:get_user).with(login).and_return(user)
|
71
|
+
|
72
|
+
user.should receive(:gecos).and_return(",,,")
|
73
|
+
expect(subject.name).to eq(login)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "the user has an empty gecos" do
|
78
|
+
it "returns the gecos" do
|
79
|
+
login = "joecool#{rand 99}"
|
80
|
+
user = double(Sys::Admin::User)
|
81
|
+
|
82
|
+
sys_admin.stub(:get_login).and_return(login)
|
83
|
+
sys_admin.stub(:get_user).with(login).and_return(user)
|
84
|
+
|
85
|
+
user.should receive(:gecos).and_return("")
|
86
|
+
expect(subject.name).to eq(login)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#name (an alias)" do
|
92
|
+
it "calls .name on an instance" do
|
93
|
+
instance = double(described_class).as_null_object
|
94
|
+
described_class.stub(:new).and_return(instance)
|
95
|
+
expect(described_class.name).to be(instance.name)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'magic_reveal/index_libber'
|
3
|
+
|
4
|
+
describe MagicReveal::IndexLibber do
|
5
|
+
subject { described_class.new html_text }
|
6
|
+
|
7
|
+
describe ".update_author" do
|
8
|
+
let(:html_text) { '<meta name="author" content="Hakim El Hattab">' }
|
9
|
+
|
10
|
+
it "replaces the author" do
|
11
|
+
author = "Joe Cool #{rand 99}"
|
12
|
+
subject.update_author author
|
13
|
+
expect(subject.to_s).to match %r{content=.#{Regexp.quote author}.}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe ".update_description" do
|
18
|
+
let(:html_text) { '<meta name="description" content="A framework for easily creating beautiful presentations using HTML">' }
|
19
|
+
|
20
|
+
it "replaces the description" do
|
21
|
+
description = "#{rand 99} luft balloons"
|
22
|
+
subject.update_description description
|
23
|
+
expect(subject.html.at('meta').get_attribute('content')).to eq(description)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ".update_slides" do
|
28
|
+
let(:slides) { '<section><h2>life with Joe</h2><p>…is good</section>' * 2 }
|
29
|
+
let(:html_text) { '<!DOCTYPE html><div class="reveal"><div class="slides"><section>text</section></div></div>' }
|
30
|
+
|
31
|
+
it "does stuff" do
|
32
|
+
subject.update_slides slides
|
33
|
+
puts subject
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "with random html" do
|
38
|
+
let(:html_text) { "<!DOCTYPE html>\n<body>\n<p>text here\n</body>" }
|
39
|
+
|
40
|
+
its(:to_s) { should match %r{<body>\s*<p>text here\s*</p>\s*</body>} }
|
41
|
+
its(:to_s) { should be_kind_of(String) }
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'magic_reveal/reveal_js_fetcher'
|
3
|
+
|
4
|
+
describe MagicReveal::RevealJsFetcher do
|
5
|
+
subject { described_class.new version }
|
6
|
+
let(:version) { "#{rand 9}.#{rand 9}.#{rand 9}" }
|
7
|
+
|
8
|
+
describe "#new" do
|
9
|
+
its(:version) { should be(version) }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".zip_url" do
|
13
|
+
its(:zip_url) { should match(/#{Regexp.escape version}\.zip\Z/) }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".conductor" do
|
17
|
+
it "uses the zip_url" do
|
18
|
+
MagicReveal::Conductor.should_receive(:new).with(subject.zip_url)
|
19
|
+
subject.conductor
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the conductor" do
|
23
|
+
expect(subject.conductor).to be_kind_of(MagicReveal::Conductor)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ".save_to" do
|
28
|
+
let(:conductor) { double(MagicReveal::Conductor).as_null_object }
|
29
|
+
let(:reveal_dir) { Pathname.new(Dir.tmpdir) + "save_to_test#{rand 99}" }
|
30
|
+
before do
|
31
|
+
subject.conductor = conductor
|
32
|
+
conductor.stub(:fetch) { |zipfile| @zipfile = zipfile }
|
33
|
+
subject.save_to reveal_dir
|
34
|
+
end
|
35
|
+
|
36
|
+
it "uses conductor to fetch the zipfile" do
|
37
|
+
expect(conductor).to have_received(:fetch).with(anything)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "uses conductor to fetch the zipfile" do
|
41
|
+
expect(conductor).to have_received(:unpack).
|
42
|
+
with(@zipfile, reveal_dir)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'magic_reveal/slide_renderer'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
describe MagicReveal::SlideRenderer do
|
6
|
+
describe ".header" do
|
7
|
+
context "when no slides have been shown" do
|
8
|
+
before { subject.has_shown_slides = false }
|
9
|
+
it "starts with <section>" do
|
10
|
+
expect(subject.header("text", 1)).to match(/\A<section>/)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when slides have been shown" do
|
15
|
+
before { subject.has_shown_slides = true }
|
16
|
+
|
17
|
+
it "starts with </section><section>" do
|
18
|
+
expect(subject.header("text", 1)).to match(%r{\A</section>\s*<section>})
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "ends with <h?>text</h?>" do
|
23
|
+
txt = "text#{rand 99}"
|
24
|
+
lvl = rand(6)
|
25
|
+
expect(subject.header(txt, lvl)).to match(%r{<h#{lvl}>#{txt}</h#{lvl}>\Z})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe ".doc_header" do
|
30
|
+
it "should generate an HTML comment" do
|
31
|
+
expect(subject.doc_header).to match %r{\A<!--\s.*\s-->\Z}
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should set has_shown_slides to false" do
|
35
|
+
subject.has_shown_slides = true
|
36
|
+
subject.doc_header
|
37
|
+
expect(subject.has_shown_slides).to be_false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".doc_footer" do
|
42
|
+
context "when slides have been shown" do
|
43
|
+
before { subject.has_shown_slides = true }
|
44
|
+
|
45
|
+
it "emits a </section>" do
|
46
|
+
expect(subject.doc_footer).to eq('</section>')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when no slides have been shown" do
|
51
|
+
before { subject.has_shown_slides = false }
|
52
|
+
|
53
|
+
it "emits an empty string" do
|
54
|
+
expect(subject.doc_footer).to eq('')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe ".block_code" do
|
60
|
+
let(:code) { "code = #{rand 99};" }
|
61
|
+
context "with language" do
|
62
|
+
let(:language) { "lang#{rand 99}" }
|
63
|
+
|
64
|
+
it "has the pre class set to the language" do
|
65
|
+
expect(subject.block_code(code, language)).
|
66
|
+
to match(%r{\A\s*<pre class="#{language}">})
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "without language" do
|
71
|
+
it "has pre without class" do
|
72
|
+
expect(subject.block_code(code, nil)).
|
73
|
+
to match(%r{\A\s*<pre>})
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "wraps the text in a <code> tag" do
|
78
|
+
text = "#{rand 99} text #{rand 99}"
|
79
|
+
expect(subject.block_code(text, nil)).
|
80
|
+
to match(%r{<code>#{Regexp.quote text}</code>})
|
81
|
+
end
|
82
|
+
|
83
|
+
it "escapes the code text" do
|
84
|
+
CGI.should_receive(:escapeHTML).and_return('text')
|
85
|
+
subject.block_code('whatever', nil)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "ends with </pre>" do
|
89
|
+
expect(subject.block_code('whatever', nil)).
|
90
|
+
to match(%r{</pre>\s*\Z})
|
91
|
+
end
|
92
|
+
|
93
|
+
it "has no space between <pre> and <code>" do
|
94
|
+
expect(subject.block_code('whatever', nil)).
|
95
|
+
to match(%r{<pre[^>]*><code>})
|
96
|
+
end
|
97
|
+
|
98
|
+
it "has no space between </pre> and </code>" do
|
99
|
+
expect(subject.block_code('whatever', nil)).
|
100
|
+
to match(%r{</code></pre>})
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "prepare_code" do
|
105
|
+
context "with @@source = filename" do
|
106
|
+
around { |example| Dir.mktmpdir { |dir| @tmpdir = Pathname.new dir; example.run } }
|
107
|
+
let(:filename) { @tmpdir + "file#{rand 99}" }
|
108
|
+
|
109
|
+
it "loads the contents from filename" do
|
110
|
+
text = "#{rand 99} bottles of beer"
|
111
|
+
filename.open('w') { |f| f.write text }
|
112
|
+
|
113
|
+
expect(subject.prepare_code "@@source = #{filename}").to eq(text)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "without @@source" do
|
118
|
+
it "returns the text" do
|
119
|
+
text = "#{rand 99} luft balloons."
|
120
|
+
expect(subject.prepare_code text).to eq(text)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
EXAMPLE_DATA = Pathname.new(__FILE__).dirname + 'data'
|
5
|
+
|
6
|
+
if ENV['TRAVIS'] == 'true'
|
7
|
+
require 'coveralls'
|
8
|
+
Coveralls.wear!
|
9
|
+
else
|
10
|
+
begin
|
11
|
+
require 'simplecov'
|
12
|
+
SimpleCov.start
|
13
|
+
rescue LoadError
|
14
|
+
warn "Unable to load simplecov; skipping coverage report"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec.configure do |c|
|
19
|
+
c.run_all_when_everything_filtered = true
|
20
|
+
c.treat_symbols_as_metadata_keys_with_true_values = true
|
21
|
+
|
22
|
+
c.filter_run :focus => true
|
23
|
+
end
|