magic_reveal 2.4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|