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 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
- sh "bundle --standalone --local --without development"
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 :pkg => ["Guides/local/guides/bundle", "Guides/local/guides/lib", "Guides/bin/guides"]
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>
@@ -0,0 +1,4 @@
1
+ <pkg-info format-version="2" identifier="com.strobecorp.guides" version="<%= version %>" install-location="/usr" auth="root">
2
+ <payload installKBytes="<%= kbytes %>" numberOfFiles="<%= num_files %>"/>
3
+ </pkg-info>
4
+
data/guides.gemspec CHANGED
@@ -28,7 +28,6 @@ Gem::Specification.new do |s|
28
28
  s.files = `git ls-files`.split("\n")
29
29
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
30
30
  s.executables = %w(guides)
31
- s.default_executable = "guides"
32
31
  s.require_paths = ["lib"]
33
32
  end
34
33
 
data/lib/guides.rb CHANGED
@@ -2,7 +2,7 @@ require "action_pack"
2
2
  require "redcloth"
3
3
  require "maruku"
4
4
 
5
- require "guides/textile_extensions"
5
+ require "guides/textile_transformer"
6
6
  require "guides/markdown_extensions"
7
7
  require "guides/generator"
8
8
 
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
- FileUtils.rm_rf("#{Guides.root}/output") if options[:clean]
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"
@@ -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
- # If the issue with notextile is fixed just remove the wrapper.
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)
@@ -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)
@@ -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
- source_file = Dir["#{source_templates}/#{name}.{html.erb,textile}"].first
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
- generator.send(:generate_guide, File.basename(source_file), "#{name}.html")
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 => Guides.meta["index"] %>
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
@@ -1,3 +1,3 @@
1
1
  module Guides
2
- VERSION = "0.6.7"
2
+ VERSION = "0.6.8"
3
3
  end
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
- it "generates the app" do
12
- out.should =~ /Generating contribute.html.*Generating credits.html.*Generating index.html/m
13
- end
5
+ describe "production" do
14
6
 
15
- it "generates assets" do
16
- files = Dir["output/*"]
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
- 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
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
- it "does nothing if run twice in a row" do
27
- guides "build"
28
- out.should be_blank
29
- end
20
+ it "generates assets" do
21
+ files = Dir["output/*"]
30
22
 
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
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
- it "creates contribute.html" do
41
- contribute = File.read("output/contribute.html")
42
- contribute.should =~ /<h2>Contribute<\/h2>/
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
+
@@ -0,0 +1,10 @@
1
+ h2. Article Four
2
+
3
+ This is where we have the stuff for the fourth article.
4
+
5
+ endprologue.
6
+
7
+
8
+ h3. What is Article Four?
9
+
10
+ Article Four is the fourth article.
@@ -0,0 +1,10 @@
1
+ h2. Article One
2
+
3
+ This is where we have the stuff for the first article.
4
+
5
+ endprologue.
6
+
7
+
8
+ h3. What is Article One?
9
+
10
+ Article One is the first article.
@@ -0,0 +1,10 @@
1
+ h2. Article Three
2
+
3
+ This is where we have the stuff for the third article.
4
+
5
+ endprologue.
6
+
7
+
8
+ h3. What is Article Three?
9
+
10
+ Article Three is the third article.
@@ -0,0 +1,10 @@
1
+ ## Article Two
2
+
3
+ This is where we have the stuff for the second article.
4
+
5
+ endprologue.
6
+
7
+
8
+ ### What is Article Two?
9
+
10
+ Article Two is the second article.
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
- before(:each) do
16
- host! :preview
17
- guides "preview"
18
- end
15
+ describe "without arguments" do
19
16
 
20
- after(:each) do
21
- kill!
22
- end
17
+ before(:each) do
18
+ host! :preview
19
+ guides "preview"
20
+ end
23
21
 
24
- it "downloads the index at /" do
25
- get "/"
26
- should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h3>Start Here<\/h3>/m
27
- end
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
- it "downloads contribute at /contribute.html" do
35
- get "/contribute.html"
36
- should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h2>Contribute<\/h2>/m
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
@@ -16,6 +16,10 @@ RSpec.configure do |config|
16
16
  Dir.chdir(tmp)
17
17
  end
18
18
 
19
+ def fixtures
20
+ @fixtures ||= Pathname.new(File.expand_path("../fixtures", __FILE__))
21
+ end
22
+
19
23
  config.before(:suite) do
20
24
  reset_tmp
21
25
  end
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
- @response = conn.run_request(method, path, args.first, {})
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 &lt;bat&gt;</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 &lt; bar &amp;&amp; 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 &lt; bar &amp;&amp; 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 &lt; Bar\n def foo\n bar &amp;&amp; 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
+ %{&lt;div&gt;&lt;%= ohai %&gt;&lt;/div&gt;</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 &amp;&amp; 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.7
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-02-25 00:00:00 -08:00
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/textile_extensions.rb
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
- has_rdoc: true
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.5.2
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