guides 0.5.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +3 -0
- data/RELEASES.yml +6 -0
- data/Rakefile +33 -0
- data/guides.gemspec +1 -0
- data/lib/guides.rb +11 -1
- data/lib/guides/cli.rb +30 -2
- data/lib/guides/generator.rb +44 -4
- data/lib/guides/helpers.rb +5 -8
- data/lib/guides/preview.rb +50 -0
- data/lib/guides/templates/assets/stylesheets/main.css +2 -2
- data/lib/guides/templates/source/layout.html.erb +4 -0
- data/lib/guides/textile_extensions.rb +1 -1
- data/lib/guides/version.rb +1 -1
- data/spec/build_spec.rb +45 -0
- data/spec/new_spec.rb +18 -0
- data/spec/preview_spec.rb +35 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/cli.rb +113 -0
- data/spec/support/rack.rb +112 -0
- metadata +35 -6
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/RELEASES.yml
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
desc "Prep the release for PackageMaker"
|
2
|
+
task :pkg do
|
3
|
+
system "rm -rf Guides"
|
4
|
+
system "mkdir -p Guides/local/guides/lib"
|
5
|
+
|
6
|
+
`git ls-files -- lib`.split("\n").each do |file|
|
7
|
+
system "mkdir -p #{File.dirname("Guides/local/guides/#{file}")}"
|
8
|
+
system "cp #{file} Guides/local/guides/#{file}"
|
9
|
+
end
|
10
|
+
|
11
|
+
require "rbconfig"
|
12
|
+
|
13
|
+
unless Config::CONFIG["target_cpu"] == "universal"
|
14
|
+
puts "Please use a universal binary copy of ruby"
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
|
18
|
+
unless RUBY_VERSION == "1.9.2"
|
19
|
+
puts "Please use Ruby 1.9.2"
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
|
23
|
+
puts "Regenerating the bundle."
|
24
|
+
|
25
|
+
system "rm -rf bundle"
|
26
|
+
system "bundle --standalone"
|
27
|
+
system "cp -R bundle Guides/local/guides/bundle"
|
28
|
+
|
29
|
+
guides = File.read("bin/guides").sub(/\A#.*/, "#!/usr/local/ruby1.9test/bin/ruby -I /usr/local/guides/bundle -r bundler/setup")
|
30
|
+
|
31
|
+
system "mkdir -p Guides/bin"
|
32
|
+
File.open("Guides/bin/guides", "w") { |file| file.puts guides }
|
33
|
+
end
|
data/guides.gemspec
CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_dependency "rack", "~> 1.2.1"
|
23
23
|
s.add_dependency "RedCloth", "~> 4.1.1"
|
24
24
|
s.add_dependency "thor", "~> 0.14.6"
|
25
|
+
s.add_dependency "thin", "~> 1.2.7"
|
25
26
|
|
26
27
|
s.files = `git ls-files`.split("\n")
|
27
28
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/lib/guides.rb
CHANGED
@@ -5,13 +5,23 @@ require "guides/textile_extensions"
|
|
5
5
|
require "guides/generator"
|
6
6
|
|
7
7
|
module Guides
|
8
|
+
class Error < StandardError
|
9
|
+
def self.status_code(code = nil)
|
10
|
+
define_method(:status_code) { code }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class FormatError < Error; status_code(2) ; end
|
15
|
+
|
8
16
|
class << self
|
9
17
|
def root
|
10
18
|
# TODO: Search for guides.yml
|
11
19
|
File.expand_path(Dir.pwd)
|
12
20
|
end
|
13
21
|
|
14
|
-
def meta
|
22
|
+
def meta(reload = false)
|
23
|
+
@meta = nil if reload
|
24
|
+
|
15
25
|
@meta ||= begin
|
16
26
|
if File.exist?("#{root}/guides.yml")
|
17
27
|
YAML.load_file("#{root}/guides.yml")
|
data/lib/guides/cli.rb
CHANGED
@@ -1,21 +1,27 @@
|
|
1
1
|
require "thor"
|
2
2
|
require "guides/new"
|
3
|
+
require "guides/preview"
|
4
|
+
require "guides/version"
|
3
5
|
|
4
6
|
module Guides
|
5
7
|
class CLI < Thor
|
6
8
|
ASSETS_ROOT = File.expand_path("../assets", __FILE__)
|
7
9
|
SOURCE_ROOT = File.expand_path("../source", __FILE__)
|
8
10
|
|
11
|
+
def self.basename
|
12
|
+
"guides"
|
13
|
+
end
|
14
|
+
|
9
15
|
desc "new NAME", "create a new directory of guides"
|
10
16
|
method_option "name", :type => :string
|
11
17
|
def new(name)
|
12
18
|
invoke "guides:new:copy", [name, options[:name] || name]
|
13
19
|
end
|
14
20
|
|
15
|
-
desc "
|
21
|
+
desc "build", "build the guides output"
|
16
22
|
method_option "only", :type => :array
|
17
23
|
method_option "clean", :type => :boolean
|
18
|
-
def
|
24
|
+
def build
|
19
25
|
FileUtils.rm_rf("#{Guides.root}/output") if options[:clean]
|
20
26
|
require "guides/generator"
|
21
27
|
|
@@ -27,9 +33,31 @@ module Guides
|
|
27
33
|
generator.generate
|
28
34
|
end
|
29
35
|
|
36
|
+
map "-v" => "version"
|
37
|
+
map "--version" => "version"
|
38
|
+
|
39
|
+
desc "version", "print the current version"
|
40
|
+
def version
|
41
|
+
shell.say "Guides #{Guides::VERSION}", :green
|
42
|
+
end
|
43
|
+
|
30
44
|
desc "preview", "preview the guides as you work"
|
31
45
|
def preview
|
46
|
+
Preview.start
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "update", "when running from the pkg, updates the gem"
|
50
|
+
def update
|
51
|
+
Update.start
|
52
|
+
end
|
32
53
|
|
54
|
+
no_tasks do
|
55
|
+
def invoke_task(*)
|
56
|
+
super
|
57
|
+
rescue Guides::Error => e
|
58
|
+
shell.say e.message, :red
|
59
|
+
exit e.status_code
|
60
|
+
end
|
33
61
|
end
|
34
62
|
end
|
35
63
|
end
|
data/lib/guides/generator.rb
CHANGED
@@ -85,6 +85,33 @@ module Guides
|
|
85
85
|
copy_assets
|
86
86
|
end
|
87
87
|
|
88
|
+
def generate_guide(guide, output_file)
|
89
|
+
return unless generate?(guide, output_file)
|
90
|
+
|
91
|
+
puts "Generating #{output_file}"
|
92
|
+
File.open(File.join(output_dir, output_file), 'w') do |f|
|
93
|
+
view = ActionView::Base.new(source_dir, :edge => edge)
|
94
|
+
view.extend(Helpers)
|
95
|
+
|
96
|
+
if guide =~ /\.html\.erb$/
|
97
|
+
# Generate the special pages like the home.
|
98
|
+
view.render("sections")
|
99
|
+
type = @edge ? "edge" : "normal"
|
100
|
+
result = view.render(:layout => 'layout', :file => guide, :locals => {:guide_type => type})
|
101
|
+
else
|
102
|
+
body = File.read(File.join(source_dir, guide))
|
103
|
+
body = set_header_section(body, view)
|
104
|
+
body = set_index(body, view)
|
105
|
+
|
106
|
+
result = view.render(:layout => 'layout', :text => textile(body))
|
107
|
+
|
108
|
+
warn_about_broken_links(result) if @warnings
|
109
|
+
end
|
110
|
+
|
111
|
+
f.write result
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
88
115
|
private
|
89
116
|
def generate_guides
|
90
117
|
guides_to_generate.each do |guide|
|
@@ -114,6 +141,12 @@ module Guides
|
|
114
141
|
def generate?(source_file, output_file)
|
115
142
|
fin = File.join(source_dir, source_file)
|
116
143
|
fout = File.join(output_dir, output_file)
|
144
|
+
|
145
|
+
if File.exists?(fout) && File.mtime(fout) < File.mtime(File.join(Guides.root, "guides.yml"))
|
146
|
+
Guides.meta(true)
|
147
|
+
return true
|
148
|
+
end
|
149
|
+
|
117
150
|
all || !File.exists?(fout) || File.mtime(fout) < File.mtime(fin)
|
118
151
|
end
|
119
152
|
|
@@ -148,8 +181,15 @@ module Guides
|
|
148
181
|
new_body = body.gsub(/(.*?)endprologue\./m, '').strip
|
149
182
|
header = $1
|
150
183
|
|
151
|
-
header
|
152
|
-
|
184
|
+
unless header
|
185
|
+
raise FormatError, "A prologue is required. Use 'endprologue.' to separate the prologue from the main body."
|
186
|
+
end
|
187
|
+
|
188
|
+
if header =~ /h2\.(.*)/
|
189
|
+
page_title = "#{@meta["title"]}: #{$1.strip}"
|
190
|
+
else
|
191
|
+
raise FormatError, "A title is required. Use the 'h2.' declaration to denote the title."
|
192
|
+
end
|
153
193
|
|
154
194
|
header = textile(header)
|
155
195
|
|
@@ -192,8 +232,8 @@ module Guides
|
|
192
232
|
|
193
233
|
def textile(body, lite_mode=false)
|
194
234
|
# If the issue with notextile is fixed just remove the wrapper.
|
195
|
-
with_workaround_for_notextile(body) do |
|
196
|
-
t = RedCloth.new(
|
235
|
+
with_workaround_for_notextile(body) do |new_body|
|
236
|
+
t = RedCloth.new(new_body)
|
197
237
|
t.hard_breaks = false
|
198
238
|
t.lite_mode = lite_mode
|
199
239
|
t.to_html(:notestuff, :plusplus, :code, :tip)
|
data/lib/guides/helpers.rb
CHANGED
@@ -1,19 +1,15 @@
|
|
1
1
|
module Guides
|
2
2
|
module Helpers
|
3
|
-
def full_index
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
3
|
def clickable_index
|
8
|
-
|
4
|
+
all_guides = Guides.meta["index"]
|
9
5
|
|
10
|
-
total_guides =
|
6
|
+
total_guides = all_guides.inject(0) do |sum, (name, guides)|
|
11
7
|
sum + guides.size
|
12
8
|
end
|
13
9
|
|
14
10
|
lgroup, rgroup, counted_guides = {}, {}, 0
|
15
11
|
|
16
|
-
|
12
|
+
all_guides.each do |name, guides|
|
17
13
|
if counted_guides > (total_guides / 2.0)
|
18
14
|
rgroup[name] = guides
|
19
15
|
else
|
@@ -39,7 +35,7 @@ module Guides
|
|
39
35
|
end
|
40
36
|
|
41
37
|
def author(name, nick, image = 'credits_pic_blank.gif', &block)
|
42
|
-
image = "images/#{image}"
|
38
|
+
image = "images/#{image}" unless image =~ /^http/
|
43
39
|
|
44
40
|
result = content_tag(:img, nil, :src => image, :class => 'left pic', :alt => name)
|
45
41
|
result << content_tag(:h3, name)
|
@@ -53,3 +49,4 @@ module Guides
|
|
53
49
|
end
|
54
50
|
end
|
55
51
|
end
|
52
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "rack"
|
2
|
+
|
3
|
+
module Guides
|
4
|
+
class App
|
5
|
+
LOCAL_ASSETS = File.expand_path("../templates/assets", __FILE__)
|
6
|
+
SOURCE_ASSETS = File.join(Guides.root, "assets")
|
7
|
+
SOURCE_TEMPLATES = File.join(Guides.root, "source")
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@local = Rack::File.new(LOCAL_ASSETS)
|
11
|
+
@source = Rack::File.new(SOURCE_ASSETS)
|
12
|
+
@output = Rack::File.new(File.join(Guides.root, "output"))
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
path = env["PATH_INFO"]
|
17
|
+
|
18
|
+
case path
|
19
|
+
when "/"
|
20
|
+
env["PATH_INFO"] = "/index.html"
|
21
|
+
return call(env)
|
22
|
+
when /(.*).html/
|
23
|
+
name = $1
|
24
|
+
generator = Guides::Generator.new({})
|
25
|
+
source_file = Dir["#{SOURCE_TEMPLATES}/#{name}.{html.erb,textile}"].first
|
26
|
+
|
27
|
+
unless source_file
|
28
|
+
return [404, {"Content-Type" => "text/html"}, ["#{name} not found"]]
|
29
|
+
end
|
30
|
+
|
31
|
+
generator.send(:generate_guide, File.basename(source_file), "#{name}.html")
|
32
|
+
return @output.call(env)
|
33
|
+
else
|
34
|
+
source = @source.call(env)
|
35
|
+
return source if source.first == 200
|
36
|
+
return @local.call(env)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Preview < Rack::Server
|
42
|
+
def self.start(*)
|
43
|
+
super :host => '0.0.0.0', :Port => 9292, :server => "thin"
|
44
|
+
end
|
45
|
+
|
46
|
+
def app
|
47
|
+
@app ||= App.new
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -24,7 +24,7 @@ dl dt { font-weight: bold; }
|
|
24
24
|
dd { margin-left: 1.5em;}
|
25
25
|
|
26
26
|
pre,code { margin: 1.5em 0; overflow: auto; color: #222;}
|
27
|
-
pre,code,tt {
|
27
|
+
pre,code,tt,ins {
|
28
28
|
font-size: 1em;
|
29
29
|
font-family: "Anonymous Pro", "Inconsolata", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
|
30
30
|
line-height: 1.5;
|
@@ -384,7 +384,7 @@ div.code_container {
|
|
384
384
|
margin: 0.25em 0 1.5em 0;
|
385
385
|
}
|
386
386
|
|
387
|
-
.note tt, .info tt {border:none; background: none; padding: 0;}
|
387
|
+
.note tt, .note ins, .info tt, .note ins {border:none; background: none; padding: 0;}
|
388
388
|
|
389
389
|
#mainCol ul li {
|
390
390
|
list-style:none;
|
@@ -48,8 +48,12 @@
|
|
48
48
|
|
49
49
|
<div id="feature">
|
50
50
|
<div class="wrapper">
|
51
|
+
<% if header_section = yield(:header_section).presence %>
|
52
|
+
<%= header_section %>
|
53
|
+
<% else %>
|
51
54
|
<h2><%= Guides.meta["title"] %></h2>
|
52
55
|
<p><%= Guides.meta["description"] %></p>
|
56
|
+
<% end %>
|
53
57
|
</div>
|
54
58
|
</div>
|
55
59
|
|
data/lib/guides/version.rb
CHANGED
data/spec/build_spec.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "guides build" do
|
4
|
+
before(:all) do
|
5
|
+
reset_tmp
|
6
|
+
guides "new", "sample" and wait
|
7
|
+
Dir.chdir tmp.join("sample")
|
8
|
+
guides "build" and wait
|
9
|
+
end
|
10
|
+
|
11
|
+
it "generates the app" do
|
12
|
+
out.should =~ /Generating contribute.html.*Generating credits.html.*Generating index.html/m
|
13
|
+
end
|
14
|
+
|
15
|
+
it "generates assets" do
|
16
|
+
files = Dir["output/*"]
|
17
|
+
|
18
|
+
File.directory?("output/images").should be_true
|
19
|
+
File.directory?("output/javascripts").should be_true
|
20
|
+
File.directory?("output/stylesheets").should be_true
|
21
|
+
File.file?("output/javascripts/guides.js").should be_true
|
22
|
+
File.file?("output/stylesheets/main.css").should be_true
|
23
|
+
File.file?("output/stylesheets/overrides.style.css").should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "does nothing if run twice in a row" do
|
27
|
+
guides "build"
|
28
|
+
out.should be_blank
|
29
|
+
end
|
30
|
+
|
31
|
+
it "re-runs if run with --clean" do
|
32
|
+
guides "build", "--clean"
|
33
|
+
out.should =~ /Generating contribute.html.*Generating credits.html.*Generating index.html/m
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates index.html" do
|
37
|
+
File.read("output/index.html").should =~ /<a href="contribute.html">/
|
38
|
+
end
|
39
|
+
|
40
|
+
it "creates contribute.html" do
|
41
|
+
contribute = File.read("output/contribute.html")
|
42
|
+
contribute.should =~ /<h2>Contribute<\/h2>/
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
data/spec/new_spec.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "guides new" do
|
4
|
+
before(:each) do
|
5
|
+
reset_tmp
|
6
|
+
end
|
7
|
+
|
8
|
+
it "prints an error if new is called with no name" do
|
9
|
+
guides "new", :track_stderr => true
|
10
|
+
err.should =~ /"new" was called incorrectly/
|
11
|
+
end
|
12
|
+
|
13
|
+
it "generates an app if a name is given" do
|
14
|
+
guides "new", "sample"
|
15
|
+
out.should =~ /create.*guides\.yml/
|
16
|
+
tmp.join("sample", "guides.yml").read.should =~ /\Atitle: sample/
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "guides generate" do
|
4
|
+
before(:all) do
|
5
|
+
reset_tmp
|
6
|
+
guides "new", "sample" and wait
|
7
|
+
Dir.chdir tmp.join("sample")
|
8
|
+
guides "build" and wait
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:all) do
|
12
|
+
Dir.chdir(tmp)
|
13
|
+
end
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
host! :preview
|
17
|
+
launch_test_server
|
18
|
+
guides "preview"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "downloads the index at /" do
|
22
|
+
get "/"
|
23
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h3>Start Here<\/h3>/m
|
24
|
+
end
|
25
|
+
|
26
|
+
it "downloads the index at /index.html" do
|
27
|
+
get "/"
|
28
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h3>Start Here<\/h3>/m
|
29
|
+
end
|
30
|
+
|
31
|
+
it "downloads contribute at /contribute.html" do
|
32
|
+
get "/contribute.html"
|
33
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h2>Contribute<\/h2>/m
|
34
|
+
end
|
35
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "pathname"
|
3
|
+
require "support/cli"
|
4
|
+
require "support/rack"
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
include SpecHelpers
|
8
|
+
|
9
|
+
def tmp
|
10
|
+
@tmp ||= Pathname.new(File.expand_path("../../tmp", __FILE__))
|
11
|
+
end
|
12
|
+
|
13
|
+
def reset_tmp
|
14
|
+
FileUtils.rm_rf(tmp)
|
15
|
+
FileUtils.mkdir_p(tmp)
|
16
|
+
Dir.chdir(tmp)
|
17
|
+
end
|
18
|
+
|
19
|
+
config.before(:suite) do
|
20
|
+
reset_tmp
|
21
|
+
end
|
22
|
+
end
|
data/spec/support/cli.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require "guides"
|
2
|
+
require "guides/cli"
|
3
|
+
|
4
|
+
module SpecHelpers
|
5
|
+
attr_reader :stdin, :stdout, :stderr
|
6
|
+
|
7
|
+
def env
|
8
|
+
@env ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def guides(*argv)
|
12
|
+
opts = Hash === argv.last ? argv.pop : {}
|
13
|
+
|
14
|
+
kill!
|
15
|
+
create_pipes
|
16
|
+
|
17
|
+
@pid = Process.fork do
|
18
|
+
Dir.chdir opts[:chdir] if opts[:chdir]
|
19
|
+
|
20
|
+
@stdout.close
|
21
|
+
@stdin.close
|
22
|
+
@stderr.close
|
23
|
+
|
24
|
+
STDOUT.reopen @stdout_child
|
25
|
+
STDIN.reopen @stdin_child
|
26
|
+
|
27
|
+
if opts[:track_stderr] || argv.first == 'preview'
|
28
|
+
STDERR.reopen @stderr_child
|
29
|
+
end
|
30
|
+
|
31
|
+
env.each do |key, val|
|
32
|
+
ENV[key] = val
|
33
|
+
end
|
34
|
+
|
35
|
+
Guides::CLI.start(argv)
|
36
|
+
end
|
37
|
+
|
38
|
+
if argv.first == 'preview'
|
39
|
+
wait_for_preview_server
|
40
|
+
end
|
41
|
+
|
42
|
+
@stdout_child.close
|
43
|
+
@stdin_child.close
|
44
|
+
@stderr_child.close
|
45
|
+
@pid
|
46
|
+
end
|
47
|
+
|
48
|
+
def wait_for_preview_server
|
49
|
+
s = TCPSocket.new('0.0.0.0', 9292)
|
50
|
+
rescue Errno::ECONNREFUSED
|
51
|
+
sleep 0.2
|
52
|
+
retry
|
53
|
+
ensure
|
54
|
+
s.close
|
55
|
+
end
|
56
|
+
|
57
|
+
def out_until_block(io = stdout)
|
58
|
+
# read 1 first so we wait until the process is done processing the last write
|
59
|
+
chars = nil
|
60
|
+
|
61
|
+
IO.select( [ io ] )
|
62
|
+
|
63
|
+
chars = io.read(1)
|
64
|
+
sleep 0.05
|
65
|
+
|
66
|
+
loop do
|
67
|
+
chars << io.read_nonblock(1000)
|
68
|
+
sleep 0.05
|
69
|
+
end
|
70
|
+
rescue Errno::EAGAIN, EOFError => e
|
71
|
+
chars || ""
|
72
|
+
end
|
73
|
+
|
74
|
+
def input(line, opts = {})
|
75
|
+
if on = opts[:on]
|
76
|
+
should_block_on on
|
77
|
+
end
|
78
|
+
stdin << "#{line}\n"
|
79
|
+
end
|
80
|
+
|
81
|
+
def wait
|
82
|
+
return unless @pid
|
83
|
+
|
84
|
+
pid, status = Process.wait2(@pid, 0)
|
85
|
+
|
86
|
+
@exit_status = status
|
87
|
+
@pid = nil
|
88
|
+
end
|
89
|
+
|
90
|
+
def exit_status
|
91
|
+
wait
|
92
|
+
@exit_status
|
93
|
+
end
|
94
|
+
|
95
|
+
def kill!
|
96
|
+
Process.kill(9, @pid) if @pid
|
97
|
+
end
|
98
|
+
|
99
|
+
def out
|
100
|
+
stdout.read
|
101
|
+
end
|
102
|
+
|
103
|
+
def err
|
104
|
+
stderr.read
|
105
|
+
end
|
106
|
+
|
107
|
+
def create_pipes
|
108
|
+
@stdout, @stdout_child = IO.pipe
|
109
|
+
@stdin_child, @stdin = IO.pipe
|
110
|
+
@stderr, @stderr_child = IO.pipe
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'faraday'
|
3
|
+
require 'rack'
|
4
|
+
require 'webrick'
|
5
|
+
require 'socket'
|
6
|
+
|
7
|
+
Thread.abort_on_exception = true
|
8
|
+
|
9
|
+
module SpecHelpers
|
10
|
+
RACK_ENV_KEYS = [ 'PATH_INFO', 'REQUEST_METHOD', 'QUERY_STRING', 'rack.input',
|
11
|
+
'HTTP_X_ZOMG' ]
|
12
|
+
|
13
|
+
def self.launch_test_server
|
14
|
+
@test_server ||= begin
|
15
|
+
app = lambda do |env|
|
16
|
+
ret = env.slice(*RACK_ENV_KEYS)
|
17
|
+
ret['rack.input'] = ret['rack.input'].read if ret['rack.input']
|
18
|
+
[ 200, { 'Content-Type' => 'text/plain' }, ret.inspect ]
|
19
|
+
end
|
20
|
+
|
21
|
+
t = Thread.new do
|
22
|
+
logger = WEBrick::Log.new(nil, WEBrick::BasicLog::WARN)
|
23
|
+
Rack::Handler::WEBrick.run(app, :Host => '0.0.0.0', :Port => 9293,
|
24
|
+
:Logger => logger, :AccessLog => [])
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
s = TCPSocket.new('0.0.0.0', 9293)
|
29
|
+
rescue Errno::ECONNREFUSED
|
30
|
+
sleep 0.2
|
31
|
+
retry
|
32
|
+
end
|
33
|
+
|
34
|
+
s.close
|
35
|
+
t
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def launch_test_server
|
40
|
+
SpecHelpers.launch_test_server
|
41
|
+
end
|
42
|
+
|
43
|
+
%w( get post put delete head ).each do |method|
|
44
|
+
class_eval <<-RUBY
|
45
|
+
def #{method}(uri, *args)
|
46
|
+
request(:#{method}, uri, *args)
|
47
|
+
end
|
48
|
+
RUBY
|
49
|
+
end
|
50
|
+
|
51
|
+
attr_reader :response
|
52
|
+
attr_reader :host
|
53
|
+
|
54
|
+
def host!(host)
|
55
|
+
@host = host
|
56
|
+
end
|
57
|
+
|
58
|
+
def request(method, uri, *args)
|
59
|
+
uri = URI(uri)
|
60
|
+
host = uri.host || @host
|
61
|
+
scheme = uri.scheme || 'http'
|
62
|
+
headers = Hash === args.last ? args.pop : {}
|
63
|
+
|
64
|
+
if host == :preview
|
65
|
+
ip = host = 'http://localhost:9292'
|
66
|
+
else
|
67
|
+
ip = ENV['STROBEAPP_URL']
|
68
|
+
end
|
69
|
+
|
70
|
+
headers['Host'] = host
|
71
|
+
headers['Authorization'] = 'basic x:x' # hac to bypass varnish
|
72
|
+
|
73
|
+
conn = Faraday::Connection.new(:url => ip) do |c|
|
74
|
+
c.use Faraday::Adapter::NetHttp
|
75
|
+
c.headers.merge! headers
|
76
|
+
end
|
77
|
+
|
78
|
+
path = uri.path
|
79
|
+
path = "#{path}?#{uri.query}" if uri.query
|
80
|
+
|
81
|
+
@response = conn.run_request(method, path, args.first, {})
|
82
|
+
end
|
83
|
+
|
84
|
+
def should_respond_with(status, body = nil, hdrs = {})
|
85
|
+
@response.status.should == status
|
86
|
+
|
87
|
+
if body.is_a?(Regexp)
|
88
|
+
@response.body.should =~ body
|
89
|
+
elsif body
|
90
|
+
@response.body.should == body
|
91
|
+
end
|
92
|
+
|
93
|
+
hdrs.each do |hdr, val|
|
94
|
+
@response.headers[hdr].should == val
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def should_have_env(env)
|
99
|
+
@response.status.should == 200
|
100
|
+
empty = RACK_ENV_KEYS - env.keys
|
101
|
+
actual = eval(@response.body)
|
102
|
+
|
103
|
+
env.each do |key, val|
|
104
|
+
actual[key].should == val
|
105
|
+
end
|
106
|
+
|
107
|
+
empty.each do |key|
|
108
|
+
actual[key].should be_blank
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 6
|
8
|
+
- 1
|
9
|
+
version: 0.6.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Yehuda Katz
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-13 00:00:00 -08:00
|
18
18
|
default_executable: guides
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -92,6 +92,21 @@ dependencies:
|
|
92
92
|
version: 0.14.6
|
93
93
|
type: :runtime
|
94
94
|
version_requirements: *id005
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: thin
|
97
|
+
prerelease: false
|
98
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 1
|
105
|
+
- 2
|
106
|
+
- 7
|
107
|
+
version: 1.2.7
|
108
|
+
type: :runtime
|
109
|
+
version_requirements: *id006
|
95
110
|
description: A tool for creating version controlled guides for open source projects, based on the Rails Guides framework
|
96
111
|
email:
|
97
112
|
- wycats@gmail.com
|
@@ -104,6 +119,8 @@ extra_rdoc_files: []
|
|
104
119
|
files:
|
105
120
|
- .gitignore
|
106
121
|
- Gemfile
|
122
|
+
- RELEASES.yml
|
123
|
+
- Rakefile
|
107
124
|
- bin/guides
|
108
125
|
- guides.gemspec
|
109
126
|
- lib/guides.rb
|
@@ -113,6 +130,7 @@ files:
|
|
113
130
|
- lib/guides/indexer.rb
|
114
131
|
- lib/guides/levenshtein.rb
|
115
132
|
- lib/guides/new.rb
|
133
|
+
- lib/guides/preview.rb
|
116
134
|
- lib/guides/templates/assets/images/book_icon.gif
|
117
135
|
- lib/guides/templates/assets/images/bullet.gif
|
118
136
|
- lib/guides/templates/assets/images/chapters_icon.gif
|
@@ -219,6 +237,12 @@ files:
|
|
219
237
|
- lib/guides/textile_extensions.rb
|
220
238
|
- lib/guides/version.rb
|
221
239
|
- lib/guides/w3c_validator.rb
|
240
|
+
- spec/build_spec.rb
|
241
|
+
- spec/new_spec.rb
|
242
|
+
- spec/preview_spec.rb
|
243
|
+
- spec/spec_helper.rb
|
244
|
+
- spec/support/cli.rb
|
245
|
+
- spec/support/rack.rb
|
222
246
|
has_rdoc: true
|
223
247
|
homepage: http://yehudakatz.com
|
224
248
|
licenses: []
|
@@ -253,5 +277,10 @@ rubygems_version: 1.3.7
|
|
253
277
|
signing_key:
|
254
278
|
specification_version: 3
|
255
279
|
summary: Extracting the Rails Guides framework for the rest of us
|
256
|
-
test_files:
|
257
|
-
|
280
|
+
test_files:
|
281
|
+
- spec/build_spec.rb
|
282
|
+
- spec/new_spec.rb
|
283
|
+
- spec/preview_spec.rb
|
284
|
+
- spec/spec_helper.rb
|
285
|
+
- spec/support/cli.rb
|
286
|
+
- spec/support/rack.rb
|