guides 0.6.7 → 0.6.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +75 -3
- data/build/Distribution.erb +23 -0
- data/build/PackageInfo.erb +4 -0
- data/guides.gemspec +0 -1
- data/lib/guides.rb +1 -1
- data/lib/guides/cli.rb +7 -2
- data/lib/guides/generator.rb +13 -46
- data/lib/guides/helpers.rb +12 -2
- data/lib/guides/preview.rb +21 -8
- data/lib/guides/templates/assets/stylesheets/main.css +11 -0
- data/lib/guides/templates/source/index.html.erb +1 -1
- data/lib/guides/textile_transformer.rb +84 -0
- data/lib/guides/version.rb +1 -1
- data/spec/build_spec.rb +84 -31
- data/spec/fixtures/guides.yml +33 -0
- data/spec/fixtures/source/article_four.textile +10 -0
- data/spec/fixtures/source/article_one.textile +10 -0
- data/spec/fixtures/source/article_three.textile +10 -0
- data/spec/fixtures/source/article_two.md +10 -0
- data/spec/preview_spec.rb +61 -18
- data/spec/spec_helper.rb +4 -0
- data/spec/support/cli.rb +6 -0
- data/spec/support/rack.rb +7 -1
- data/spec/textile_transformer_spec.rb +86 -0
- metadata +18 -6
- data/lib/guides/textile_extensions.rb +0 -23
data/Rakefile
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "guides/version"
|
3
|
+
require "erb"
|
4
|
+
|
1
5
|
file "Guides/local/guides/bundle" => "Gemfile" do
|
2
6
|
require "rbconfig"
|
3
7
|
|
@@ -14,14 +18,16 @@ file "Guides/local/guides/bundle" => "Gemfile" do
|
|
14
18
|
puts "Regenerating the bundle."
|
15
19
|
|
16
20
|
sh "rm -rf bundle"
|
17
|
-
|
21
|
+
Bundler.with_clean_env do
|
22
|
+
sh "bundle --standalone --local --without development"
|
23
|
+
end
|
18
24
|
sh "mkdir -p Guides/local/guides"
|
19
25
|
sh "cp -R bundle Guides/local/guides/"
|
20
26
|
|
21
27
|
verbose(false) do
|
22
28
|
Dir.chdir("Guides/local/guides/bundle/ruby/1.9.1") do
|
23
29
|
Dir["{bin,cache,doc,specifications}"].each { |f| rm_rf f }
|
24
|
-
Dir["**/{ext,docs,test,spec}"].each { |f| rm_rf(f) if File.directory?(f) }
|
30
|
+
Dir["**/{ext,docs,test,spec}"].each { |f| rm_rf(f) if File.directory?(f) && f !~ /maruku/i }
|
25
31
|
Dir["**/erubis-*/doc-api"].each {|f| rm_rf(f) }
|
26
32
|
end
|
27
33
|
end
|
@@ -43,13 +49,79 @@ file "Guides/bin/guides" => "bin/guides" do
|
|
43
49
|
|
44
50
|
sh "mkdir -p Guides/bin"
|
45
51
|
File.open("Guides/bin/guides", "w") { |file| file.puts guides }
|
52
|
+
File.chmod 0755, "Guides/bin/guides"
|
46
53
|
end
|
47
54
|
|
48
55
|
desc "Prep the release for PackageMaker"
|
49
|
-
task :
|
56
|
+
task :make_pkg => ["Guides/local/guides/bundle", "Guides/local/guides/lib", "Guides/bin/guides"]
|
50
57
|
|
51
58
|
task :rm do
|
52
59
|
rm_rf "Guides"
|
53
60
|
end
|
54
61
|
|
62
|
+
directory "guides-pkg/Resources"
|
63
|
+
directory "guides-pkg/guides.pkg"
|
64
|
+
|
65
|
+
pkg_dependencies = [:make_pkg, "guides-pkg/Resources", "guides-pkg/guides.pkg",
|
66
|
+
"guides-pkg/Distribution", "guides-pkg/guides.pkg/Bom",
|
67
|
+
"guides-pkg/guides.pkg/PackageInfo", "guides-pkg/guides.pkg/Payload"]
|
68
|
+
|
69
|
+
def details
|
70
|
+
@details ||= begin
|
71
|
+
total_size, files = 0, 0
|
72
|
+
|
73
|
+
Dir["Guides/**/*"].each do |file|
|
74
|
+
files += 1
|
75
|
+
|
76
|
+
next if File.directory?(file)
|
77
|
+
|
78
|
+
total_size += File.size(file)
|
79
|
+
end
|
80
|
+
|
81
|
+
[total_size, files]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
file "guides-pkg/Distribution" do
|
86
|
+
src = File.read File.expand_path("../build/Distribution.erb", __FILE__)
|
87
|
+
erb = ERB.new(src)
|
88
|
+
|
89
|
+
total_size, files = details
|
90
|
+
|
91
|
+
kbytes = total_size / 1024
|
92
|
+
version = Guides::VERSION
|
93
|
+
|
94
|
+
File.open("guides-pkg/Distribution", "w") do |file|
|
95
|
+
file.puts erb.result(binding)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
file "guides-pkg/guides.pkg/PackageInfo" do
|
100
|
+
src = File.read File.expand_path("../build/PackageInfo.erb", __FILE__)
|
101
|
+
erb = ERB.new(src)
|
102
|
+
|
103
|
+
total_size, num_files = details
|
104
|
+
|
105
|
+
kbytes = total_size / 1024
|
106
|
+
version = Guides::VERSION
|
107
|
+
|
108
|
+
File.open("guides-pkg/guides.pkg/PackageInfo", "w") do |file|
|
109
|
+
file.puts erb.result(binding)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
file "guides-pkg/guides.pkg/Bom" do
|
114
|
+
sh "mkbom -s Guides guides-pkg/guides.pkg/Bom"
|
115
|
+
end
|
116
|
+
|
117
|
+
file "guides-pkg/guides.pkg/Payload" do
|
118
|
+
sh "cd Guides && pax -wz -x cpio . > ../guides-pkg/guides.pkg/Payload"
|
119
|
+
end
|
120
|
+
|
121
|
+
file "Guides.pkg" => pkg_dependencies do
|
122
|
+
sh "pkgutil --flatten guides-pkg Guides.pkg"
|
123
|
+
end
|
124
|
+
|
125
|
+
task :pkg => "Guides.pkg"
|
126
|
+
|
55
127
|
task :clean => [:rm, :pkg]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<installer-script minSpecVersion="1.000000" authoringTool="org.ruby-lang.rake" authoringToolVersion="0.8.7">
|
3
|
+
<title>Guides</title>
|
4
|
+
<options customize="never" allow-external-scripts="no"/>
|
5
|
+
<domains enable_localSystem="true"/>
|
6
|
+
<script>
|
7
|
+
function ruby19p136_installed() {
|
8
|
+
return !(system.files.fileExistsAtPath('/usr/local/ruby1.9') == true);
|
9
|
+
}
|
10
|
+
</script>
|
11
|
+
<choices-outline>
|
12
|
+
<line choice="ruby19p136"/>
|
13
|
+
<line choice="guides"/>
|
14
|
+
</choices-outline>
|
15
|
+
<choice id="ruby19p136" title="ruby" start_selected="false" start_enabled="false" selected="ruby19p136_installed()" enabled="ruby19p136_installed()">
|
16
|
+
<pkg-ref id="com.strobecorp.ruby19"/>
|
17
|
+
</choice>
|
18
|
+
<choice id="guides" title="Guides">
|
19
|
+
<pkg-ref id="com.strobecorp.guides"/>
|
20
|
+
</choice>
|
21
|
+
<pkg-ref id="com.strobecorp.ruby19" installKBytes="26156" archiveKBytes="7353" hash-sha256="7b9507f7a9178c0eaafd3ffcfd2e246400e82899e6f29df2f7c4fcec6ec04ac5" version="1.9.2p136" auth="Root">http://ruby-pkg.strobeapp.com/Ruby-1.9.2p136.pkg</pkg-ref>
|
22
|
+
<pkg-ref id="com.strobecorp.guides" installKBytes="<%= kbytes %>" version="<%= version %>" auth="Root">#guides.pkg</pkg-ref>
|
23
|
+
</installer-script>
|
data/guides.gemspec
CHANGED
data/lib/guides.rb
CHANGED
data/lib/guides/cli.rb
CHANGED
@@ -21,8 +21,12 @@ module Guides
|
|
21
21
|
desc "build", "build the guides output"
|
22
22
|
method_option "only", :type => :array
|
23
23
|
method_option "clean", :type => :boolean
|
24
|
+
method_option "production", :type => :boolean, :default => true, :banner => "use production mode", :aliases => "-p"
|
24
25
|
def build
|
25
|
-
|
26
|
+
if options[:clean]
|
27
|
+
FileUtils.rm_rf(File.join(Guides.root, options[:production] ? 'output' : 'staging'))
|
28
|
+
end
|
29
|
+
|
26
30
|
require "guides/generator"
|
27
31
|
|
28
32
|
opts = options.dup
|
@@ -42,8 +46,9 @@ module Guides
|
|
42
46
|
end
|
43
47
|
|
44
48
|
desc "preview", "preview the guides as you work"
|
49
|
+
method_option "production", :type => :boolean, :banner => "use production mode", :aliases => "-p"
|
45
50
|
def preview
|
46
|
-
Preview.start
|
51
|
+
Preview.start(options)
|
47
52
|
end
|
48
53
|
|
49
54
|
#desc "update", "when running from the pkg, updates the gem"
|
data/lib/guides/generator.rb
CHANGED
@@ -70,13 +70,14 @@ module Guides
|
|
70
70
|
|
71
71
|
@guides_dir = File.expand_path(Dir.pwd)
|
72
72
|
@source_dir = File.join(@guides_dir, "source")
|
73
|
-
@output_dir = File.join(@guides_dir, "output")
|
73
|
+
@output_dir = File.join(@guides_dir, options[:production] ? "output" : "staging")
|
74
74
|
|
75
75
|
FileUtils.mkdir_p(@output_dir)
|
76
76
|
|
77
77
|
@edge = options[:edge]
|
78
78
|
@warnings = options[:warnings]
|
79
79
|
@all = options[:all]
|
80
|
+
@production = options[:production]
|
80
81
|
|
81
82
|
@meta = Guides.meta
|
82
83
|
end
|
@@ -86,6 +87,13 @@ module Guides
|
|
86
87
|
copy_assets
|
87
88
|
end
|
88
89
|
|
90
|
+
def construction?(source_file)
|
91
|
+
# TODO: Clean this up a bit, it is messy
|
92
|
+
url = source_file.sub(/\.(#{EXTENSIONS.map{|e| Regexp.escape(e) }.join('|')})$/, '')
|
93
|
+
guide = @meta['index'].values.flatten.select{|g| g['url'] == url }.first rescue nil
|
94
|
+
guide && guide['construction']
|
95
|
+
end
|
96
|
+
|
89
97
|
private
|
90
98
|
def generate_guides
|
91
99
|
guides_to_generate.each do |guide|
|
@@ -116,6 +124,8 @@ module Guides
|
|
116
124
|
fin = File.join(source_dir, source_file)
|
117
125
|
fout = File.join(output_dir, output_file)
|
118
126
|
|
127
|
+
return false if @production && construction?(source_file)
|
128
|
+
|
119
129
|
if File.exists?(fout) && File.mtime(fout) < File.mtime(File.join(Guides.root, "guides.yml"))
|
120
130
|
Guides.meta(true)
|
121
131
|
return true
|
@@ -129,7 +139,7 @@ module Guides
|
|
129
139
|
|
130
140
|
puts "Generating #{output_file}"
|
131
141
|
File.open(File.join(output_dir, output_file), 'w') do |f|
|
132
|
-
view = ActionView::Base.new(source_dir, :edge => edge)
|
142
|
+
view = ActionView::Base.new(source_dir, :edge => edge, :production => @production)
|
133
143
|
view.extend(Helpers)
|
134
144
|
|
135
145
|
if guide =~ /\.html\.erb$/
|
@@ -222,56 +232,13 @@ module Guides
|
|
222
232
|
end
|
223
233
|
|
224
234
|
def textile(body, lite_mode=false)
|
225
|
-
|
226
|
-
with_workaround_for_notextile(body) do |new_body|
|
227
|
-
t = RedCloth.new(new_body)
|
228
|
-
t.hard_breaks = false
|
229
|
-
t.lite_mode = lite_mode
|
230
|
-
t.to_html(:notestuff, :plusplus)
|
231
|
-
end
|
235
|
+
TextileTransformer.new(@production).transform(body)
|
232
236
|
end
|
233
237
|
|
234
238
|
def markdown(body)
|
235
239
|
Maruku.new(body).to_html
|
236
240
|
end
|
237
241
|
|
238
|
-
# For some reason the notextile tag does not always turn off textile. See
|
239
|
-
# LH ticket of the security guide (#7). As a temporary workaround we deal
|
240
|
-
# with code blocks by hand.
|
241
|
-
def with_workaround_for_notextile(body)
|
242
|
-
code_blocks = []
|
243
|
-
|
244
|
-
body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain|javascript|css)>(.*?)</\1>}m) do |m|
|
245
|
-
brush = case $1
|
246
|
-
when 'ruby', 'sql', 'javascript', 'css', 'plain'
|
247
|
-
$1
|
248
|
-
when 'erb'
|
249
|
-
'ruby; html-script: true'
|
250
|
-
when 'html'
|
251
|
-
'xml' # html is understood, but there are .xml rules in the CSS
|
252
|
-
else
|
253
|
-
'plain'
|
254
|
-
end
|
255
|
-
|
256
|
-
code_blocks.push(<<HTML)
|
257
|
-
<notextile>
|
258
|
-
<div class="code_container">
|
259
|
-
<pre class="brush: #{brush}; gutter: false; toolbar: false">
|
260
|
-
#{ERB::Util.h($2).strip}
|
261
|
-
</pre>
|
262
|
-
</div>
|
263
|
-
</notextile>
|
264
|
-
HTML
|
265
|
-
"\ndirty_workaround_for_notextile_#{code_blocks.size - 1}\n"
|
266
|
-
end
|
267
|
-
|
268
|
-
body = yield body
|
269
|
-
|
270
|
-
body.gsub(%r{<p>dirty_workaround_for_notextile_(\d+)</p>}) do |_|
|
271
|
-
code_blocks[$1.to_i]
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
242
|
def warn_about_broken_links(html)
|
276
243
|
anchors = extract_anchors(html)
|
277
244
|
check_fragment_identifiers(html, anchors)
|
data/lib/guides/helpers.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Guides
|
2
2
|
module Helpers
|
3
3
|
def clickable_index
|
4
|
-
all_guides = Guides.meta["index"]
|
5
|
-
|
6
4
|
total_guides = all_guides.inject(0) do |sum, (name, guides)|
|
7
5
|
sum + guides.size
|
8
6
|
end
|
@@ -22,6 +20,18 @@ module Guides
|
|
22
20
|
render "clickable_index", :lgroup => lgroup, :rgroup => rgroup
|
23
21
|
end
|
24
22
|
|
23
|
+
def is_production?
|
24
|
+
assigns[:production]
|
25
|
+
end
|
26
|
+
|
27
|
+
def all_guides
|
28
|
+
Guides.meta["index"].inject({}) do |ret, (section, items)|
|
29
|
+
items = items.reject{|item| item['construction'] } if is_production?
|
30
|
+
ret[section] = items unless items.empty?
|
31
|
+
ret
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
25
35
|
def guide(name, url, options = {}, &block)
|
26
36
|
link = content_tag(:a, :href => url) { name }
|
27
37
|
result = content_tag(:dt, link)
|
data/lib/guides/preview.rb
CHANGED
@@ -2,10 +2,11 @@ require "rack"
|
|
2
2
|
|
3
3
|
module Guides
|
4
4
|
class App
|
5
|
-
def initialize
|
5
|
+
def initialize(options = {})
|
6
|
+
@production = !!options[:production]
|
6
7
|
@local = Rack::File.new(local_assets)
|
7
8
|
@source = Rack::File.new(source_assets)
|
8
|
-
@output = Rack::File.new(File.join(Guides.root, "output"))
|
9
|
+
@output = Rack::File.new(File.join(Guides.root, @production ? "output" : "staging"))
|
9
10
|
end
|
10
11
|
|
11
12
|
def local_assets
|
@@ -29,14 +30,21 @@ module Guides
|
|
29
30
|
return call(env)
|
30
31
|
when /\/(.*)\.html$/
|
31
32
|
name = $1
|
32
|
-
generator = Guides::Generator.new({})
|
33
|
-
|
33
|
+
generator = Guides::Generator.new({ :production => @production })
|
34
|
+
|
35
|
+
source_file = Dir["#{source_templates}/#{name}.{#{Guides::Generator::EXTENSIONS.join(",")}}"].first
|
34
36
|
|
35
37
|
unless source_file
|
36
38
|
return [404, {"Content-Type" => "text/html"}, ["#{name} not found in #{source_templates}: #{Guides.root}"]]
|
37
39
|
end
|
38
40
|
|
39
|
-
|
41
|
+
source_base = File.basename(source_file)
|
42
|
+
|
43
|
+
if generator.construction?(source_base) && @production
|
44
|
+
return [404, {"Content-Type" => "text/html"}, ["#{name} is under construction and not available in production"]]
|
45
|
+
end
|
46
|
+
|
47
|
+
generator.send(:generate_guide, source_base, "#{name}.html")
|
40
48
|
return @output.call(env)
|
41
49
|
else
|
42
50
|
source = @source.call(env)
|
@@ -47,12 +55,17 @@ module Guides
|
|
47
55
|
end
|
48
56
|
|
49
57
|
class Preview < Rack::Server
|
50
|
-
def self.start(
|
51
|
-
super :host => '0.0.0.0', :Port => 9292, :server => "thin"
|
58
|
+
def self.start(options = {})
|
59
|
+
super options.merge(:host => '0.0.0.0', :Port => 9292, :server => "thin")
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize(options = {})
|
63
|
+
@production = !!options[:production]
|
64
|
+
super(options)
|
52
65
|
end
|
53
66
|
|
54
67
|
def app
|
55
|
-
@app ||= App.new
|
68
|
+
@app ||= App.new(:production => @production)
|
56
69
|
end
|
57
70
|
end
|
58
71
|
end
|
@@ -370,6 +370,17 @@ div.code_container {
|
|
370
370
|
padding: 0.25em 1em 0.5em 48px;
|
371
371
|
}
|
372
372
|
|
373
|
+
div.code_container div.filename {
|
374
|
+
font-family: monospace;
|
375
|
+
color: #666;
|
376
|
+
border-bottom: 1px solid #ccc;
|
377
|
+
border-top: 1px solid #ccc;
|
378
|
+
margin: 4px -14px 0 -13px;
|
379
|
+
padding-bottom: 4px;
|
380
|
+
background-color: #ddd;
|
381
|
+
padding-left: 10px;
|
382
|
+
}
|
383
|
+
|
373
384
|
.note {
|
374
385
|
background: #fff9d8 url(../images/tab_note.gif) no-repeat left top;
|
375
386
|
border: none;
|
@@ -1 +1 @@
|
|
1
|
-
<%= render "full_index", :guides =>
|
1
|
+
<%= render "full_index", :guides => all_guides %>
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "strscan"
|
2
|
+
require "cgi"
|
3
|
+
|
4
|
+
module Guides
|
5
|
+
class TextileTransformer
|
6
|
+
LANGUAGES = { "ruby" => "ruby", "sql" => "sql", "javascript" => "javascript",
|
7
|
+
"css" => "css", "plain" => "plain", "erb" => "ruby; html-script: true",
|
8
|
+
"html" => "xml", "xml" => "xml", "shell" => "plain", "yaml" => "yaml" }
|
9
|
+
|
10
|
+
NOTES = { "CAUTION" => "warning", "IMPORTANT" => "warning", "WARNING" => "warning",
|
11
|
+
"INFO" => "info", "TIP" => "info", "NOTE" => "note" }
|
12
|
+
|
13
|
+
def initialize(production=false)
|
14
|
+
@production = production
|
15
|
+
end
|
16
|
+
|
17
|
+
def transform(string)
|
18
|
+
@string = string.dup
|
19
|
+
|
20
|
+
@output = ""
|
21
|
+
@pending_textile = ""
|
22
|
+
|
23
|
+
until @string.empty?
|
24
|
+
notes = NOTES.keys.map {|note| "#{note}" }.join("|")
|
25
|
+
languages = LANGUAGES.keys.join("|")
|
26
|
+
|
27
|
+
match = scan_until /(\+(\S.*?\S?)\+|<(#{languages})(?: filename=["']([^"']*)["'])?>|(#{notes}): |<(construction)>|\z)/m
|
28
|
+
|
29
|
+
@pending_textile << match.pre_match
|
30
|
+
|
31
|
+
if match[2] # +foo+
|
32
|
+
@pending_textile << "<notextile><tt>#{CGI.escapeHTML(match[2])}</tt></notextile>" if match[2]
|
33
|
+
elsif match[3] # <language>
|
34
|
+
flush_textile
|
35
|
+
generate_brushes match[3], LANGUAGES[match[3]], match[4]
|
36
|
+
elsif match[5] # NOTE:
|
37
|
+
flush_textile
|
38
|
+
consume_note NOTES[match[5]]
|
39
|
+
elsif match[6] # <construction>
|
40
|
+
consume_construction
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
flush_textile
|
45
|
+
|
46
|
+
@output
|
47
|
+
end
|
48
|
+
|
49
|
+
def generate_brushes(tag, replace, filename)
|
50
|
+
match = scan_until %r{</#{tag}>}
|
51
|
+
@output << %{<div class="code_container">\n}
|
52
|
+
@output << %{<div class="filename">#{filename}</div>\n} if filename
|
53
|
+
@output << %{<pre class="brush: #{replace}; gutter: false; toolbar: false">\n} <<
|
54
|
+
CGI.escapeHTML(match.pre_match) << %{</pre></div>}
|
55
|
+
end
|
56
|
+
|
57
|
+
def scan_until(regex)
|
58
|
+
match = @string.match(regex)
|
59
|
+
@string = match.post_match
|
60
|
+
match
|
61
|
+
end
|
62
|
+
|
63
|
+
def consume_note(css_class)
|
64
|
+
match = scan_until /(\r?\n){2}/
|
65
|
+
note = match.pre_match.gsub(/\n\s*/, " ")
|
66
|
+
note = RedCloth.new(note, [:lite_mode]).to_html
|
67
|
+
@output << %{<div class="#{css_class}"><p>#{note}</p></div>\n}
|
68
|
+
end
|
69
|
+
|
70
|
+
def consume_construction
|
71
|
+
if @production
|
72
|
+
@string.sub!(%r{^.*</construction>}, '')
|
73
|
+
else
|
74
|
+
@string.sub!(%r{</construction>}, '')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def flush_textile
|
79
|
+
@pending_textile.gsub!(/(?<!\n)\n(?!\n)/, ' ') # Don't convert single \n to line-breaks
|
80
|
+
@output << RedCloth.new(@pending_textile).to_html << "\n"
|
81
|
+
@pending_textile = ""
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/guides/version.rb
CHANGED
data/spec/build_spec.rb
CHANGED
@@ -1,45 +1,98 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
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
4
|
|
11
|
-
|
12
|
-
out.should =~ /Generating contribute.html.*Generating credits.html.*Generating index.html/m
|
13
|
-
end
|
5
|
+
describe "production" do
|
14
6
|
|
15
|
-
|
16
|
-
|
7
|
+
before(:all) do
|
8
|
+
reset_tmp
|
9
|
+
guides "new", "sample" and wait
|
10
|
+
copy_fixtures
|
11
|
+
Dir.chdir tmp.join("sample")
|
12
|
+
guides "build" and wait
|
13
|
+
end
|
17
14
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
File.file?("output/stylesheets/main.css").should be_true
|
23
|
-
File.file?("output/stylesheets/overrides.style.css").should be_true
|
24
|
-
end
|
15
|
+
it "generates the app" do
|
16
|
+
out.should == "Generating article_one.html\nGenerating article_three.html\n" +
|
17
|
+
"Generating article_two.html\nGenerating contribute.html\nGenerating credits.html\nGenerating index.html\n"
|
18
|
+
end
|
25
19
|
|
26
|
-
|
27
|
-
|
28
|
-
out.should be_blank
|
29
|
-
end
|
20
|
+
it "generates assets" do
|
21
|
+
files = Dir["output/*"]
|
30
22
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
23
|
+
File.directory?("output/images").should be_true
|
24
|
+
File.directory?("output/javascripts").should be_true
|
25
|
+
File.directory?("output/stylesheets").should be_true
|
26
|
+
File.file?("output/javascripts/guides.js").should be_true
|
27
|
+
File.file?("output/stylesheets/main.css").should be_true
|
28
|
+
File.file?("output/stylesheets/overrides.style.css").should be_true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "does nothing if run twice in a row" do
|
32
|
+
guides "build"
|
33
|
+
out.should be_blank
|
34
|
+
end
|
35
|
+
|
36
|
+
it "re-runs if run with --clean" do
|
37
|
+
guides "build", "--clean"
|
38
|
+
out.should == "Generating article_one.html\nGenerating article_three.html\n" +
|
39
|
+
"Generating article_two.html\nGenerating contribute.html\nGenerating credits.html\nGenerating index.html\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "creates index.html" do
|
43
|
+
File.read("output/index.html").should =~ /<a href="article_one.html">/
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should not show under-construction articles in index" do
|
47
|
+
File.read("output/index.html").should_not =~ /<a href="article_four.html">/
|
48
|
+
end
|
49
|
+
|
50
|
+
it "creates contribute.html" do
|
51
|
+
contribute = File.read("output/contribute.html")
|
52
|
+
contribute.should =~ /<h2>Contribute<\/h2>/
|
53
|
+
end
|
54
|
+
|
55
|
+
it "creates normal article" do
|
56
|
+
article_one = File.read("output/article_one.html")
|
57
|
+
article_one.should =~ /<h2>Article One<\/h2>/
|
58
|
+
end
|
59
|
+
|
60
|
+
it "creates markdown article" do
|
61
|
+
article_two = File.read("output/article_two.html")
|
62
|
+
article_two.should =~ /<h2[^>]*>Article Two<\/h2>/
|
63
|
+
end
|
64
|
+
|
65
|
+
it "does not create under-construction article" do
|
66
|
+
File.exist?("output/article_four.html").should be_false
|
67
|
+
end
|
35
68
|
|
36
|
-
it "creates index.html" do
|
37
|
-
File.read("output/index.html").should =~ /<a href="contribute.html">/
|
38
69
|
end
|
39
70
|
|
40
|
-
|
41
|
-
|
42
|
-
|
71
|
+
describe "development" do
|
72
|
+
|
73
|
+
before(:all) do
|
74
|
+
reset_tmp
|
75
|
+
guides "new", "sample" and wait
|
76
|
+
copy_fixtures
|
77
|
+
Dir.chdir tmp.join("sample")
|
78
|
+
guides "build", "--production=false" and wait
|
79
|
+
end
|
80
|
+
|
81
|
+
it "generates the app" do
|
82
|
+
out.should == "Generating article_four.html\nGenerating article_one.html\nGenerating article_three.html\n" +
|
83
|
+
"Generating article_two.html\nGenerating contribute.html\nGenerating credits.html\nGenerating index.html\n"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should show under-construction articles in index" do
|
87
|
+
File.read("staging/index.html").should =~ /<a href="article_four.html">/
|
88
|
+
end
|
89
|
+
|
90
|
+
it "creates under construction article" do
|
91
|
+
article_four = File.read("staging/article_four.html")
|
92
|
+
article_four.should =~ /<h2>Article Four<\/h2>/
|
93
|
+
end
|
94
|
+
|
43
95
|
end
|
96
|
+
|
44
97
|
end
|
45
98
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
title: Guides Test
|
2
|
+
description: Enter your description here.
|
3
|
+
It can take up several lines. This description
|
4
|
+
will appear immediately below the main title in
|
5
|
+
the outputted guides.
|
6
|
+
|
7
|
+
authors:
|
8
|
+
Documentation Team:
|
9
|
+
- name: Yehuda Katz
|
10
|
+
nick: wycats
|
11
|
+
description: Yehuda wrote the Rails guides gem.
|
12
|
+
Designers:
|
13
|
+
- name: Jason Zimdars
|
14
|
+
nick: jz
|
15
|
+
description: Jason Zimdars is an experienced creative director and web designer who has lead UI and UX design for numerous websites and web applications. You can see more of his design and writing at <a href="http://www.thinkcage.com/">Thinkcage.com</a> or follow him on <a href="http://twitter.com/JZ">Twitter</a>
|
16
|
+
|
17
|
+
index:
|
18
|
+
Section One:
|
19
|
+
- title: Article One
|
20
|
+
url: article_one
|
21
|
+
text: This is the first article
|
22
|
+
- title: Article Two
|
23
|
+
url: article_two
|
24
|
+
text: This is the second article
|
25
|
+
Section Two:
|
26
|
+
- title: Article Three
|
27
|
+
url: article_three
|
28
|
+
text: This is the third article
|
29
|
+
- title: Article Four
|
30
|
+
url: article_four
|
31
|
+
text: This is the fourth article
|
32
|
+
construction: true
|
33
|
+
|
data/spec/preview_spec.rb
CHANGED
@@ -4,35 +4,78 @@ describe "guides preview" do
|
|
4
4
|
before(:all) do
|
5
5
|
reset_tmp
|
6
6
|
guides "new", "sample" and wait
|
7
|
+
copy_fixtures
|
7
8
|
Dir.chdir tmp.join("sample")
|
8
|
-
guides "build" and wait
|
9
9
|
end
|
10
10
|
|
11
11
|
after(:all) do
|
12
12
|
Dir.chdir(tmp)
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
host! :preview
|
17
|
-
guides "preview"
|
18
|
-
end
|
15
|
+
describe "without arguments" do
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
before(:each) do
|
18
|
+
host! :preview
|
19
|
+
guides "preview"
|
20
|
+
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
after(:each) do
|
23
|
+
kill!
|
24
|
+
end
|
25
|
+
|
26
|
+
it "downloads the index at /" do
|
27
|
+
get "/"
|
28
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h3>Section One<\/h3>/m
|
29
|
+
end
|
30
|
+
|
31
|
+
it "downloads the index at /index.html" do
|
32
|
+
get "/"
|
33
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h3>Section One<\/h3>/m
|
34
|
+
end
|
35
|
+
|
36
|
+
it "downloads contribute at /contribute.html" do
|
37
|
+
get "/contribute.html"
|
38
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h2>Contribute<\/h2>/m
|
39
|
+
end
|
40
|
+
|
41
|
+
it "downloads a normal page" do
|
42
|
+
get "/article_one.html"
|
43
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h2>Article One<\/h2>/m
|
44
|
+
end
|
45
|
+
|
46
|
+
it "downloads a markdown page" do
|
47
|
+
get "/article_two.html"
|
48
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h2[^>]*>Article Two<\/h2>/m
|
49
|
+
end
|
50
|
+
|
51
|
+
it "downloads an under-construction page" do
|
52
|
+
get "/article_four.html"
|
53
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h2>Article Four<\/h2>/m
|
54
|
+
end
|
28
55
|
|
29
|
-
it "downloads the index at /index.html" do
|
30
|
-
get "/"
|
31
|
-
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h3>Start Here<\/h3>/m
|
32
56
|
end
|
33
57
|
|
34
|
-
|
35
|
-
|
36
|
-
|
58
|
+
describe "production" do
|
59
|
+
|
60
|
+
before(:each) do
|
61
|
+
host! :preview
|
62
|
+
guides "preview", "--production"
|
63
|
+
end
|
64
|
+
|
65
|
+
after(:each) do
|
66
|
+
kill!
|
67
|
+
end
|
68
|
+
|
69
|
+
it "downloads a normal page" do
|
70
|
+
get "/article_one.html"
|
71
|
+
should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h2>Article One<\/h2>/m
|
72
|
+
end
|
73
|
+
|
74
|
+
it "does not download an under-construction page" do
|
75
|
+
get "/article_four.html"
|
76
|
+
should_respond_with 404, "article_four is under construction and not available in production"
|
77
|
+
end
|
78
|
+
|
37
79
|
end
|
80
|
+
|
38
81
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/cli.rb
CHANGED
@@ -47,10 +47,16 @@ module SpecHelpers
|
|
47
47
|
@pid
|
48
48
|
end
|
49
49
|
|
50
|
+
def copy_fixtures
|
51
|
+
FileUtils.cp fixtures.join("guides.yml"), tmp.join("sample")
|
52
|
+
FileUtils.cp_r fixtures.join("source"), tmp.join("sample")
|
53
|
+
end
|
54
|
+
|
50
55
|
def wait_for_preview_server
|
51
56
|
s = TCPSocket.new('0.0.0.0', 9292)
|
52
57
|
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
|
53
58
|
sleep 0.2
|
59
|
+
raise "server not found" if (tries = (tries || 0) + 1) > 5
|
54
60
|
retry
|
55
61
|
rescue Exception => e
|
56
62
|
puts [e.class, e.message]
|
data/spec/support/rack.rb
CHANGED
@@ -78,7 +78,13 @@ module SpecHelpers
|
|
78
78
|
path = uri.path
|
79
79
|
path = "#{path}?#{uri.query}" if uri.query
|
80
80
|
|
81
|
-
|
81
|
+
begin
|
82
|
+
@response = conn.run_request(method, path, args.first, {})
|
83
|
+
rescue StandardError => e
|
84
|
+
sleep 0.5
|
85
|
+
raise e if (tries = (tries || 0) + 1) > 5
|
86
|
+
retry
|
87
|
+
end
|
82
88
|
end
|
83
89
|
|
84
90
|
def should_respond_with(status, body = nil, hdrs = {})
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Transformer" do
|
4
|
+
before do
|
5
|
+
@transformer = Guides::TextileTransformer.new(true)
|
6
|
+
@dev_transformer = Guides::TextileTransformer.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "handles regular textile" do
|
10
|
+
@transformer.transform("h1. foo\n\nbar").should == "<h1>foo</h1>\n<p>bar</p>\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "handles <code>" do
|
14
|
+
result = @transformer.transform("h1. foo\n\n+foo*bar*baz is <bat>+")
|
15
|
+
result.should == "<h1>foo</h1>\n<tt>foo*bar*baz is <bat></tt>\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "handles <javascript>" do
|
19
|
+
result = @transformer.transform("h1. foo\n\nHi there.\n\n<javascript>SC.Object.extend({\n foo: function() {\n return foo < bar && baz\n }\n})</javascript>")
|
20
|
+
result.should == %{<h1>foo</h1>\n<p>Hi there.</p>\n<div class="code_container">\n<pre class="brush: javascript; gutter: false; toolbar: false">\n} +
|
21
|
+
%{SC.Object.extend({\n foo: function() {\n return foo < bar && baz\n }\n})</pre></div>\n}
|
22
|
+
end
|
23
|
+
|
24
|
+
it "handles <javascript> with a filename" do
|
25
|
+
result = @transformer.transform("h1. foo\n\nHi there.\n\n<javascript filename='fake.js'>SC.Object.extend({\n foo: function() {\n return foo < bar && baz\n }\n})</javascript>")
|
26
|
+
result.should == %{<h1>foo</h1>\n<p>Hi there.</p>\n<div class="code_container">\n<div class="filename">fake.js</div>\n} +
|
27
|
+
%{<pre class="brush: javascript; gutter: false; toolbar: false">\n} +
|
28
|
+
%{SC.Object.extend({\n foo: function() {\n return foo < bar && baz\n }\n})</pre></div>\n}
|
29
|
+
end
|
30
|
+
|
31
|
+
it "handles <ruby>" do
|
32
|
+
result = @transformer.transform("h1. foo\n\nHi there.\n\n<ruby>class Foo < Bar\n def foo\n bar && baz\n end\nend</ruby>")
|
33
|
+
result.should == %{<h1>foo</h1>\n<p>Hi there.</p>\n<div class="code_container">\n<pre class="brush: ruby; gutter: false; toolbar: false">\n} +
|
34
|
+
%{class Foo < Bar\n def foo\n bar && baz\n end\nend</pre></div>\n}
|
35
|
+
end
|
36
|
+
|
37
|
+
it "handles <erb>" do
|
38
|
+
result = @transformer.transform("h1. foo\n\nHi there.\n\n<erb><div><%= ohai %></div></erb>")
|
39
|
+
result.should == %{<h1>foo</h1>\n<p>Hi there.</p>\n<div class="code_container">\n<pre class="brush: ruby; html-script: true; gutter: false; toolbar: false">\n} +
|
40
|
+
%{<div><%= ohai %></div></pre></div>\n}
|
41
|
+
end
|
42
|
+
|
43
|
+
it "handles <shell>" do
|
44
|
+
result = @transformer.transform("h1. foo\n\nHi there.\n\n<shell>$ foo && bar</shell>")
|
45
|
+
result.should == %{<h1>foo</h1>\n<p>Hi there.</p>\n<div class="code_container">\n<pre class="brush: plain; gutter: false; toolbar: false">\n} +
|
46
|
+
%{$ foo && bar</pre></div>\n}
|
47
|
+
end
|
48
|
+
|
49
|
+
it "handles <css>" do
|
50
|
+
result = @transformer.transform("h1. foo\n\nHi there.\n\n<css>body { color: red; };\na { color: blue; }</css>")
|
51
|
+
result.should == %{<h1>foo</h1>\n<p>Hi there.</p>\n<div class="code_container">\n} +
|
52
|
+
%{<pre class="brush: css; gutter: false; toolbar: false">\n} +
|
53
|
+
%{body { color: red; };\na { color: blue; }</pre></div>\n}
|
54
|
+
end
|
55
|
+
|
56
|
+
it "handles NOTE:" do
|
57
|
+
result = @transformer.transform("h1. foo\n\nHi there.\n\nNOTE: Some note\nmore of *the same* note\n\nAnother paragraph")
|
58
|
+
result.should == %{<h1>foo</h1>\n<p>Hi there.</p>\n<div class="note"><p>Some note more of <strong>the same</strong> note</p></div>\n} +
|
59
|
+
%{<p>Another paragraph</p>\n}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "does not convert single line breaks to <br>" do
|
63
|
+
@transformer.transform("This\nhas\nbreaks.").should == "<p>This has breaks.</p>\n"
|
64
|
+
@transformer.transform("This\nhas\nbreaks.\n\nAnd\nparagraphs.").should == "<p>This has breaks.</p>\n<p>And paragraphs.</p>\n"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "handles <construction>" do
|
68
|
+
str = "Testing this out. <construction>Write more here later.</construction> This is awesome.\n"
|
69
|
+
@transformer.transform(str).should == "<p>Testing this out. This is awesome.</p>\n"
|
70
|
+
@dev_transformer.transform(str).should == "<p>Testing this out. Write more here later. This is awesome.</p>\n"
|
71
|
+
|
72
|
+
str = "Before\n\n<construction>Blah</construction>\n\nAfter"
|
73
|
+
@transformer.transform(str).should == "<p>Before</p>\n<p>After</p>\n"
|
74
|
+
@dev_transformer.transform(str).should == "<p>Before</p>\n<p>Blah</p>\n<p>After</p>\n"
|
75
|
+
|
76
|
+
@dev_transformer.transform("<construction>+Test+</construction>").should == "<tt>Test</tt>\n"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "handles +" do
|
80
|
+
@transformer.transform("This +is a+ test.").should == "<p>This <tt>is a</tt> test.</p>\n"
|
81
|
+
@transformer.transform("This +is+ a +test+.").should == "<p>This <tt>is</tt> a <tt>test</tt>.</p>\n"
|
82
|
+
@transformer.transform("This +is a test.").should == "<p>This +is a test.</p>\n"
|
83
|
+
@transformer.transform("This + is + a + test.").should == "<p>This + is + a + test.</p>\n"
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: guides
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.6.
|
5
|
+
version: 0.6.8
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Yehuda Katz
|
@@ -10,8 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
14
|
-
default_executable: guides
|
13
|
+
date: 2011-04-27 00:00:00 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: actionpack
|
@@ -104,6 +103,8 @@ files:
|
|
104
103
|
- Gemfile
|
105
104
|
- Rakefile
|
106
105
|
- bin/guides
|
106
|
+
- build/Distribution.erb
|
107
|
+
- build/PackageInfo.erb
|
107
108
|
- guides.gemspec
|
108
109
|
- lib/guides.rb
|
109
110
|
- lib/guides/cli.rb
|
@@ -217,16 +218,21 @@ files:
|
|
217
218
|
- lib/guides/templates/source/credits.html.erb
|
218
219
|
- lib/guides/templates/source/index.html.erb
|
219
220
|
- lib/guides/templates/source/layout.html.erb
|
220
|
-
- lib/guides/
|
221
|
+
- lib/guides/textile_transformer.rb
|
221
222
|
- lib/guides/version.rb
|
222
223
|
- lib/guides/w3c_validator.rb
|
223
224
|
- spec/build_spec.rb
|
225
|
+
- spec/fixtures/guides.yml
|
226
|
+
- spec/fixtures/source/article_four.textile
|
227
|
+
- spec/fixtures/source/article_one.textile
|
228
|
+
- spec/fixtures/source/article_three.textile
|
229
|
+
- spec/fixtures/source/article_two.md
|
224
230
|
- spec/new_spec.rb
|
225
231
|
- spec/preview_spec.rb
|
226
232
|
- spec/spec_helper.rb
|
227
233
|
- spec/support/cli.rb
|
228
234
|
- spec/support/rack.rb
|
229
|
-
|
235
|
+
- spec/textile_transformer_spec.rb
|
230
236
|
homepage: http://yehudakatz.com
|
231
237
|
licenses: []
|
232
238
|
|
@@ -250,14 +256,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
250
256
|
requirements: []
|
251
257
|
|
252
258
|
rubyforge_project: guides
|
253
|
-
rubygems_version: 1.
|
259
|
+
rubygems_version: 1.7.1
|
254
260
|
signing_key:
|
255
261
|
specification_version: 3
|
256
262
|
summary: Extracting the Rails Guides framework for the rest of us
|
257
263
|
test_files:
|
258
264
|
- spec/build_spec.rb
|
265
|
+
- spec/fixtures/guides.yml
|
266
|
+
- spec/fixtures/source/article_four.textile
|
267
|
+
- spec/fixtures/source/article_one.textile
|
268
|
+
- spec/fixtures/source/article_three.textile
|
269
|
+
- spec/fixtures/source/article_two.md
|
259
270
|
- spec/new_spec.rb
|
260
271
|
- spec/preview_spec.rb
|
261
272
|
- spec/spec_helper.rb
|
262
273
|
- spec/support/cli.rb
|
263
274
|
- spec/support/rack.rb
|
275
|
+
- spec/textile_transformer_spec.rb
|
@@ -1,23 +0,0 @@
|
|
1
|
-
class RedCloth::TextileDoc
|
2
|
-
def notestuff(body)
|
3
|
-
body.gsub!(/^(IMPORTANT|CAUTION|WARNING|NOTE|INFO|TIP)[.:](.*?)(?=((\r?\n){2}|\z))/m) do |m|
|
4
|
-
css_class = $1.downcase
|
5
|
-
css_class = 'warning' if ['caution', 'important'].include?(css_class)
|
6
|
-
css_class = 'info' if css_class == 'tip'
|
7
|
-
|
8
|
-
result = "<div class='#{css_class}'><p>"
|
9
|
-
result << $2.strip
|
10
|
-
result << '</p></div>'
|
11
|
-
result
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def plusplus(body)
|
16
|
-
body.gsub!(/\+(.*?)\+/) do |m|
|
17
|
-
"<notextile><tt>#{$1}</tt></notextile>"
|
18
|
-
end
|
19
|
-
|
20
|
-
# The real plus sign
|
21
|
-
body.gsub!('<plus>', '+')
|
22
|
-
end
|
23
|
-
end
|