vanilla 1.17 → 1.17.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/Rakefile +21 -7
  2. data/bin/vanilla +2 -2
  3. data/lib/vanilla.rb +10 -7
  4. data/lib/vanilla/app.rb +57 -97
  5. data/lib/vanilla/config.rb +46 -0
  6. data/lib/vanilla/console.rb +1 -1
  7. data/lib/vanilla/renderers/base.rb +12 -2
  8. data/lib/vanilla/request.rb +9 -34
  9. data/lib/vanilla/routing.rb +34 -0
  10. data/lib/vanilla/test_helper.rb +10 -7
  11. data/pristine_app/Gemfile.lock +35 -0
  12. data/pristine_app/application.rb +2 -4
  13. data/pristine_app/public/vanilla.css +299 -9
  14. data/pristine_app/soups/base/layout.snip +11 -7
  15. data/pristine_app/soups/base/start.snip +15 -14
  16. data/pristine_app/soups/system/current_snip.rb +2 -2
  17. data/pristine_app/soups/system/feed.rb +30 -0
  18. data/pristine_app/soups/system/index.rb +3 -3
  19. data/pristine_app/soups/system/link_to.rb +5 -1
  20. data/pristine_app/soups/system/link_to_current_snip.rb +2 -3
  21. data/pristine_app/soups/tutorial/tutorial-layout.snip +9 -2
  22. data/pristine_app/soups/tutorial/tutorial-links.snip +2 -1
  23. data/pristine_app/soups/tutorial/tutorial-removing.snip.markdown +8 -0
  24. data/pristine_app/soups/tutorial/tutorial-renderers.snip.markdown +10 -4
  25. data/pristine_app/soups/tutorial/tutorial.snip.markdown +0 -1
  26. data/pristine_app/soups/tutorial/vanilla-rb.snip +4 -6
  27. data/pristine_app/tmp/restart.txt +0 -0
  28. data/test/core/configuration_test.rb +89 -0
  29. data/test/{dynasnip_test.rb → core/dynasnip_test.rb} +0 -0
  30. data/test/{renderers → core/renderers}/base_renderer_test.rb +37 -0
  31. data/test/{renderers → core/renderers}/erb_renderer_test.rb +0 -0
  32. data/test/{renderers → core/renderers}/haml_renderer_test.rb +0 -0
  33. data/test/{renderers → core/renderers}/markdown_renderer_test.rb +0 -0
  34. data/test/{renderers → core/renderers}/raw_renderer_test.rb +0 -0
  35. data/test/{renderers → core/renderers}/ruby_renderer_test.rb +0 -0
  36. data/test/core/routing_test.rb +30 -0
  37. data/test/{snip_inclusion_test.rb → core/snip_inclusion_test.rb} +0 -0
  38. data/test/{snip_reference_parser_test.rb → core/snip_reference_parser_test.rb} +0 -0
  39. data/test/{test_helper.rb → core/test_helper.rb} +5 -4
  40. data/test/core/vanilla_app_test.rb +51 -0
  41. data/test/{vanilla_presenting_test.rb → core/vanilla_presenting_test.rb} +15 -1
  42. data/test/{vanilla_request_test.rb → core/vanilla_request_test.rb} +0 -0
  43. data/test/pristine_app/current_snip_test.rb +46 -0
  44. data/test/pristine_app/feed_test.rb +47 -0
  45. data/test/pristine_app/index_test.rb +34 -0
  46. data/test/pristine_app/link_to_current_snip_test.rb +11 -0
  47. data/test/pristine_app/link_to_test.rb +27 -0
  48. data/test/pristine_app/page_title_test.rb +15 -0
  49. data/test/pristine_app/raw_test.rb +24 -0
  50. data/test/pristine_app/test_helper.rb +25 -0
  51. metadata +83 -42
  52. data/lib/vanilla/routes.rb +0 -18
  53. data/test/dynasnips/link_to_current_snip_test.rb +0 -19
  54. data/test/dynasnips/link_to_test.rb +0 -27
  55. data/test/dynasnips/page_title_test.rb +0 -19
  56. data/test/vanilla_app_test.rb +0 -111
@@ -1,19 +1,20 @@
1
- <h1>Welcome to Vanilla.rb</h1>
1
+ <div id="welcome">
2
+ <h1>Welcome to <a href="/">Vanilla.rb</a></h1>
3
+ </div>
2
4
 
3
- <p>Vanilla.rb is a web-experiment (a <em>websperiment</em>?) about storing and reusing data on a website. It can also function as a <a href="http://www.wikipedia.com/wiki/Bliki">bliki</a>.</p>
5
+ <div class="grid_16 alpha">
6
+ <h2>First time?</h2>
4
7
 
5
- <p>From a technical perspective, vanilla is a Ruby rack application, and should play well within the rack ecosystem. It uses a simple document store called `soup` to store data.</p>
8
+ <p>Start at {link_to tutorial, the tutorial} for some orientation.</p>
6
9
 
7
- <h2>What now?</h2>
10
+ <h2>What is this?</h2>
11
+ <p>Vanilla is a simple web framework for playing with content. It can function as a a CMS, a wiki, a bliki, or anything in between.</p>
12
+
13
+ <p>Under the hood it is a Rack application, which means it should play nice in the Ruby web ecosystem. {link_to vanilla-rb, Learn more}.</p>
14
+
15
+ <h2>Adding your content</h2>
8
16
 
9
- <p>If this is your first time using vanilla, you should investigate the {link_to tutorial} for some orientation.</p>
17
+ <p>This is the {link_to start} snip, which is the default home page. You can find this content in <code>soups/base/start.snip</code>. You should replace this content with whatever you want on your site's home page.</p>
10
18
 
11
- <h2>What next?</h2>
12
-
13
- <p>This is the {link_to start} snip, which is the default home page. You can find this content in `start.snip`.</p>
14
-
15
- <p>You should replace this content with whatever you want on your site's home page.</p>
16
-
17
- <p>Once your site is ready to run, you'll probably want to remove the tutorial; you can do this by editing the configuration in `config.ru`, and deleting the `soups/tutorial` directory.</p>
18
-
19
- <p>Good luck!</p>
19
+ <p>Good luck!</p>
20
+ </div>
@@ -16,9 +16,9 @@ class CurrentSnip < Dynasnip
16
16
  def handle(attribute=nil)
17
17
  if app.request.snip
18
18
  if attribute ||= app.request.part
19
- "{#{app.request.snip_name}.#{attribute}}"
19
+ %|{"#{app.request.snip_name}"."#{attribute}"}|
20
20
  else
21
- "{#{app.request.snip_name}}"
21
+ %|{"#{app.request.snip_name}"}|
22
22
  end
23
23
  else
24
24
  app.response.status = 404
@@ -0,0 +1,30 @@
1
+ require "vanilla/dynasnip"
2
+
3
+ class Feed < Dynasnip
4
+ def handle(*args)
5
+ Atom::Feed.new do |f|
6
+ f.title = "blah"
7
+ f.updated = Time.now
8
+ f.id = "tag:x,2008-06-01:kind/x"
9
+ f.entries = entries
10
+ end.to_xml
11
+ end
12
+
13
+ private
14
+
15
+ def entries
16
+ app.soup.all_snips.map do |snip|
17
+ Atom::Entry.new do |e|
18
+ # e.published = snip.created_at
19
+ # e.updated = snip.updated_at || snip.created_at
20
+ e.content = Atom::Content::Html.new(app.render(snip))
21
+ # e.title = snip.name
22
+ # e.authors = [Atom::Person.new(:name => snip.author || domain)]
23
+ # e.links << Atom::Link.new(:href => "http://#{domain}#{url_to(snip.name)}")
24
+ # e.id = "tag:#{domain},#{(snip.created_at.to_s || Date.today.to_s).split[0]}:/#{snip.name}"
25
+ end
26
+ end
27
+ end
28
+
29
+ self
30
+ end
@@ -2,10 +2,10 @@ require 'vanilla/dynasnip'
2
2
 
3
3
  class Index < Dynasnip
4
4
  def get(*args)
5
- list = app.soup.instance_eval { @backend }.send(:all_snips).sort_by { |a| a.updated_at || Time.at(0) }.reverse.map { |snip|
6
- "<li>#{link_to snip.name}</li>"
5
+ list = app.soup.all_snips.sort_by { |a| a.updated_at || Time.at(0) }.reverse.map { |snip|
6
+ "<li>{link_to #{snip.name}}</li>"
7
7
  }
8
- "<ol>#{list}</ol>"
8
+ %{<ol id="index">#{list}</ol>}
9
9
  end
10
10
 
11
11
  self
@@ -9,7 +9,11 @@ The link_to dyna lets you create links between snips:
9
9
  would insert a link to the blah snip.|
10
10
 
11
11
  def handle(snip_name, link_text=snip_name, part=nil)
12
- link_to(link_text, snip_name, part)
12
+ if app.soup[snip_name]
13
+ %{<a href="#{url_to(snip_name, part)}">#{link_text}</a>}
14
+ else
15
+ %{<a class="missing" href="#{url_to(snip_name, part)}">#{link_text}</a>}
16
+ end
13
17
  end
14
18
 
15
19
  self
@@ -2,12 +2,11 @@ require 'vanilla/dynasnip'
2
2
 
3
3
  class LinkToCurrentSnip < Dynasnip
4
4
  usage %|
5
- Renders a link to the current snip, or the snip currently being edited
6
- (if we're currently editing)
5
+ Renders a link to the current snip
7
6
  |
8
7
 
9
8
  def handle(*args)
10
- link_to app.request.snip_name
9
+ %{<a href="#{url_to(app.request.snip_name)}">#{app.request.snip_name}</a>}
11
10
  end
12
11
 
13
12
  self
@@ -41,9 +41,16 @@ The second dynasnip used is `link_to_current_snip`, which returns an HTML link t
41
41
  Other layouts
42
42
  -------------
43
43
 
44
- Vanilla looks for a snip called `layout` by default, but this can be changed by passing in a `:default_layout` option to `Vanilla::App.new`, e.g.
44
+ Vanilla looks for a snip called `layout` by default, but this can be changed by setting the `default_layout` configuration option in your application, e.g.
45
45
 
46
- Vanilla::App.new(:default_layout => "my_layout")
46
+ class Application < Vanilla::App; end
47
+
48
+ Application.configure do |config|
49
+
50
+ # other stuff..
51
+
52
+ config.default_layout = "my_layout"
53
+ end
47
54
 
48
55
 
49
56
  You can also override the layout on a per-snip basis, simply by setting the `:layout` attribute of the snip to the name of the layout snip to use instead.
@@ -1,4 +1,5 @@
1
1
  {link_to tutorial, "Basics"}
2
2
  {link_to tutorial-layout, "Learn about Layouts"}
3
3
  {link_to tutorial-renderers, "Renderer fun"}
4
- {link_to tutorial-dynasnips, "More about Dynasnips"}
4
+ {link_to tutorial-dynasnips, "More about Dynasnips"}
5
+ {link_to tutorial-removing, "Cleaning up"}
@@ -0,0 +1,8 @@
1
+ {tutorial-links}
2
+
3
+ Removing this tutorial
4
+ ======================
5
+
6
+ Once your site is ready to run, you'll probably want to remove the tutorial; you can do this by editing the configuration in `application.rb`, and deleting the `soups/tutorial` directory.
7
+
8
+ {tutorial-links}
@@ -42,9 +42,15 @@ Adding renderers
42
42
 
43
43
  New renderers can be added as part of the application configuration:
44
44
 
45
- Vanilla::App.new(:renderers => {
46
- "rdoc" => MyRenderers::RDoc
47
- })
45
+ class Application < Vanilla::App; end
46
+
47
+ Application.configure do |config|
48
+
49
+ # other stuff..
50
+
51
+ config.renderers[:my_format] = MyRenderer # the class
52
+ end
53
+
48
54
 
49
55
  These will be added to the lookup, and can also used to override the defaults (changing the renderer for "markdown" snips to use RDiscount, or Redcarpet, for example).
50
56
 
@@ -57,7 +63,7 @@ The simplest renderer inherits from `Vanilla::Renderers::Base`, and reimplement
57
63
  module Vanilla::Renderers
58
64
  class Bold < Base
59
65
  def process_text(content)
60
- "<b>#{content}</b>"
66
+ "<b>#{content}</b>"
61
67
  end
62
68
  end
63
69
  end
@@ -65,5 +65,4 @@ Anyway - that should be enough to get you started.
65
65
 
66
66
  {tutorial-links}
67
67
 
68
-
69
68
  :updated_at: 2011-04-28 16:21:00 +01:00
@@ -2,15 +2,13 @@ Vanilla.rb is the software powering this site. It's a sort-of wiki/bliki thing,
2
2
 
3
3
  Here's the [introductory blog post][3].
4
4
 
5
- It's developed on [github][1], and has a [lighthouse bug tracker][2]. At the moment it's not very well documented, since I'm exploring how the concept might work and the internals are subject to change. However, please do play around with it.
5
+ It's developed on [github][1], and has a [bug tracker][2]. At the moment it's not very well documented, since I'm exploring how the concept might work and the internals are subject to change. However, please do play around with it.
6
6
 
7
- Here's the tutorial (helpfully included from {link_to tutorial}).
7
+ You may be able to view the {link_to tutorial} on this site, if it hasn't been removed.
8
8
 
9
- {tutorial}
10
9
 
11
-
12
- [1]: http://github.com/lazyatom/vanilla
13
- [2]: http://lazyatom.lighthouseapp.com/projects/11797-vanilla/tickets
10
+ [1]: http://github.com/lazyatom/vanilla-rb
11
+ [2]: http://github.com/lazyatom/vanilla-rb/issues
14
12
  [3]: http://interblah.net/introducing-vanilla-rb
15
13
 
16
14
  :render_as: Markdown
File without changes
@@ -0,0 +1,89 @@
1
+ require "test_helper"
2
+
3
+ context "Configuring a Vanilla app" do
4
+ class TestConfigurationApp < Vanilla::App
5
+ end
6
+
7
+ setup do
8
+ TestConfigurationApp.reset!
9
+ end
10
+
11
+ context "with defaults" do
12
+ should "set the soups to base and system" do
13
+ assert_equal ["soups/base", "soups/system"], TestConfigurationApp.new.config.soups
14
+ end
15
+
16
+ should "set the default layout snip to 'layout'" do
17
+ assert_equal "layout", TestConfigurationApp.new.config.default_layout_snip
18
+ end
19
+
20
+ should "set the default root directory to the current directory" do
21
+ assert_equal Dir.pwd, TestConfigurationApp.new.config.root
22
+ end
23
+
24
+ should "use Vanilla::Renderers::Base as the default renderer" do
25
+ assert_equal Vanilla::Renderers::Base, TestConfigurationApp.new.config.default_renderer
26
+ end
27
+ end
28
+
29
+ context "with a custom root" do
30
+ setup do
31
+ soup_dir = File.join(Dir.tmpdir, "my_soup")
32
+ FileUtils.mkdir_p(soup_dir)
33
+ File.open(File.join(soup_dir, "blah.snip"), "w") { |f| f.write "Hello superfriends" }
34
+
35
+ TestConfigurationApp.configure do |c|
36
+ c.root = Dir.tmpdir
37
+ c.soups = ["my_soup"]
38
+ end
39
+ end
40
+
41
+ should "expand soup paths relative to the root to aide loading external soups" do
42
+ assert_equal "Hello superfriends", TestConfigurationApp.new.soup['blah'].content
43
+ end
44
+ end
45
+
46
+ context "with a custom root_snip" do
47
+ setup do
48
+ TestConfigurationApp.configure do |c|
49
+ c.root_snip = "hello"
50
+ end
51
+ end
52
+
53
+ should "use the given snip as the root_snip" do
54
+ assert_equal "hello", TestConfigurationApp.new.config.root_snip
55
+ end
56
+ end
57
+
58
+ context "with a specific set of soups" do
59
+ setup do
60
+ TestConfigurationApp.configure do |c|
61
+ c.soups = ["blah", "monkey"]
62
+ end
63
+ end
64
+
65
+ should "use only the specified soups" do
66
+ assert_equal ["blah", "monkey"], TestConfigurationApp.new.config.soups
67
+ end
68
+ end
69
+
70
+ context "with new renderers" do
71
+ should "load new renderer constants presented as a string" do
72
+ class ::MyRenderer
73
+ end
74
+ TestConfigurationApp.configure do |c|
75
+ c.renderers[:my_renderer] = "MyRenderer"
76
+ end
77
+ snip = create_snip(:name => "blah", :render_as => "my_renderer")
78
+ assert_equal MyRenderer, TestConfigurationApp.new.renderer_for(snip)
79
+ end
80
+
81
+ should "allow existing renderers to be overridden" do
82
+ TestConfigurationApp.configure do |c|
83
+ c.renderers["markdown"] = "Vanilla::Renderers::Bold"
84
+ end
85
+ snip = create_snip(:name => "blah", :extension => "markdown")
86
+ assert_equal Vanilla::Renderers::Bold, TestConfigurationApp.new.renderer_for(snip)
87
+ end
88
+ end
89
+ end
File without changes
@@ -40,4 +40,41 @@ describe Vanilla::Renderers::Base do
40
40
  assert_response_body "include a [snip 'missing_snip' cannot be found]", "/blah"
41
41
  end
42
42
  end
43
+
44
+ context "when generating a link" do
45
+ setup do
46
+ snip = create_snip(:name => "blah")
47
+ @soup = stub('soup', :[] => snip)
48
+ @app = stub('app', :url_to => "/url", :soup => @soup)
49
+ @renderer = Vanilla::Renderers::Base.new(@app)
50
+ end
51
+
52
+ should "call url_to on the app to generate the url" do
53
+ @app.expects(:url_to).with("blah", nil).returns("/blah")
54
+ link = @renderer.link_to("blah")
55
+ assert_equal %{<a href="/blah">blah</a>}, link
56
+ end
57
+
58
+ should "use the snip name as the link text" do
59
+ link = @renderer.link_to("blah")
60
+ assert_equal %{<a href="/url">blah</a>}, link
61
+ end
62
+
63
+ should "use any explicit link text given" do
64
+ link = @renderer.link_to("something", "blah")
65
+ assert_equal %{<a href="/url">something</a>}, link
66
+ end
67
+
68
+ should "render a missing link if the snip couldn't be found" do
69
+ @soup.stubs(:[]).returns(nil)
70
+ link = @renderer.link_to("blah")
71
+ assert_equal %{<a class="missing" href="/url">blah</a>}, link
72
+ end
73
+
74
+ should "be able to link to a specified part" do
75
+ @app.expects(:url_to).with("blah", "part").returns("/blah/part")
76
+ link = @renderer.link_to("blah part", "blah", "part")
77
+ assert_equal %{<a href="/blah/part">blah part</a>}, link
78
+ end
79
+ end
43
80
  end
@@ -0,0 +1,30 @@
1
+ require "test_helper"
2
+
3
+ context "Parsing routes" do
4
+
5
+ { "/" => [nil, nil, nil],
6
+ "/blah" => ["blah", nil, nil],
7
+ "/blah-face" => ["blah-face", nil, nil],
8
+ "/blah+face" => ["blah face", nil, nil],
9
+ "/blah.text" => ["blah", nil, "text"],
10
+ "/blah.html" => ["blah", nil, "html"],
11
+ "/blah/part" => ["blah", "part", nil],
12
+ "/blah/part.raw" => ["blah", "part", "raw"]}.each do |path, (snip, part, format)|
13
+
14
+ context "parsing #{path}" do
15
+ setup { @parsed_route = Vanilla::Routing.parse(path) }
16
+
17
+ should "return #{snip.inspect} as the snip" do
18
+ assert_equal snip, @parsed_route[0]
19
+ end
20
+ should "return #{part.inspect} as the part" do
21
+ assert_equal part, @parsed_route[1]
22
+ end
23
+ should "return #{format.inspect} as the format" do
24
+ assert_equal format, @parsed_route[2]
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+ end
@@ -1,16 +1,16 @@
1
- $LOAD_PATH.unshift(File.expand_path("../../lib"), __FILE__)
1
+ $LOAD_PATH.unshift(File.expand_path("../../../lib"), __FILE__)
2
2
  require "kintama"
3
3
  require "kintama/mocha"
4
4
  require "vanilla/test_helper"
5
5
 
6
- class Application < Vanilla::App
6
+ class TestApplication < Vanilla::App
7
7
  end
8
8
 
9
9
  module TestHelper
10
10
  include Vanilla::TestHelper
11
-
11
+
12
12
  def create_simple_layout
13
- require File.expand_path("../../pristine_app/soups/system/current_snip", __FILE__)
13
+ require File.expand_path("../../../pristine_app/soups/system/current_snip", __FILE__)
14
14
  app.soup << CurrentSnip.snip_attributes
15
15
  create_snip :name => "layout", :content => "{current_snip}"
16
16
  end
@@ -20,6 +20,7 @@ Kintama.include TestHelper
20
20
 
21
21
  Kintama.setup do
22
22
  vanilla_setup
23
+ TestApplication.reset!
23
24
  create_simple_layout
24
25
  end
25
26
 
@@ -0,0 +1,51 @@
1
+ require "test_helper"
2
+ require "tmpdir"
3
+
4
+ describe Vanilla::App do
5
+ context "when behaving as a Rack application" do
6
+ should "return a valid rack response" do
7
+ create_snip(:name => "test", :content => "content")
8
+ get "/test.text"
9
+ assert_equal 200, last_response.status
10
+ assert_kind_of Hash, last_response.headers
11
+ assert_equal "content", last_response.body
12
+ end
13
+ end
14
+
15
+ context "when detecting the snip renderer" do
16
+ should "return the constant refered to in the render_as property of the snip" do
17
+ snip = create_snip(:name => "blah", :render_as => "Raw")
18
+ assert_equal Vanilla::Renderers::Raw, app.renderer_for(snip)
19
+ end
20
+
21
+ context "using the snip extension" do
22
+ {
23
+ "markdown" => Vanilla::Renderers::Markdown,
24
+ "textile" => Vanilla::Renderers::Textile,
25
+ "erb" => Vanilla::Renderers::Erb,
26
+ "rb" => Vanilla::Renderers::Ruby,
27
+ "haml" => Vanilla::Renderers::Haml
28
+ }.each do |extension, renderer|
29
+ should "return the renderer #{renderer} when the snip has extension #{extension}" do
30
+ snip = create_snip(:name => "blah", :extension => extension)
31
+ assert_equal renderer, app.renderer_for(snip)
32
+ end
33
+ end
34
+ end
35
+
36
+ should "return Vanilla::Renderers::Base if no render_as property exists" do
37
+ snip = create_snip(:name => "blah")
38
+ assert_equal Vanilla::Renderers::Base, app.renderer_for(snip)
39
+ end
40
+
41
+ should "return Vanilla::Renderers::Base if the render_as property is blank" do
42
+ snip = create_snip(:name => "blah", :render_as => '')
43
+ assert_equal Vanilla::Renderers::Base, app.renderer_for(snip)
44
+ end
45
+
46
+ should "raise an error if the specified renderer doesn't exist" do
47
+ snip = create_snip(:name => "blah", :render_as => "NonExistentClass")
48
+ assert_raises(NameError) { app.renderer_for(snip) }
49
+ end
50
+ end
51
+ end