vanilla 1.2 → 1.9.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/Rakefile +61 -60
  2. data/bin/vanilla +6 -35
  3. data/config.example.yml +6 -0
  4. data/config.ru +10 -0
  5. data/lib/defensio.rb +59 -0
  6. data/lib/tasks/vanilla.rake +173 -0
  7. data/lib/vanilla.rb +3 -10
  8. data/lib/vanilla/app.rb +48 -104
  9. data/lib/vanilla/console.rb +5 -19
  10. data/lib/vanilla/dynasnips/comments.rb +108 -0
  11. data/lib/vanilla/dynasnips/current_snip.rb +32 -0
  12. data/{pristine_app/soups → lib/vanilla}/dynasnips/debug.rb +3 -5
  13. data/lib/vanilla/dynasnips/edit.rb +60 -0
  14. data/lib/vanilla/dynasnips/edit_link.rb +20 -0
  15. data/{pristine_app/soups → lib/vanilla}/dynasnips/index.rb +2 -4
  16. data/{pristine_app/soups/extras → lib/vanilla/dynasnips}/kind.rb +12 -14
  17. data/{pristine_app/soups → lib/vanilla}/dynasnips/link_to.rb +0 -2
  18. data/lib/vanilla/dynasnips/link_to_current_snip.rb +16 -0
  19. data/lib/vanilla/dynasnips/login.rb +56 -0
  20. data/lib/vanilla/dynasnips/new.rb +14 -0
  21. data/lib/vanilla/dynasnips/notes.rb +42 -0
  22. data/{pristine_app/soups → lib/vanilla}/dynasnips/pre.rb +4 -6
  23. data/{pristine_app/soups/extras → lib/vanilla/dynasnips}/rand.rb +0 -2
  24. data/{pristine_app/soups → lib/vanilla}/dynasnips/raw.rb +5 -8
  25. data/{pristine_app/soups/extras → lib/vanilla/dynasnips}/url_to.rb +0 -0
  26. data/lib/vanilla/renderers/base.rb +22 -32
  27. data/lib/vanilla/renderers/bold.rb +2 -0
  28. data/lib/vanilla/renderers/erb.rb +2 -0
  29. data/lib/vanilla/renderers/markdown.rb +2 -0
  30. data/lib/vanilla/renderers/raw.rb +2 -0
  31. data/lib/vanilla/renderers/ruby.rb +5 -9
  32. data/lib/vanilla/renderers/textile.rb +2 -0
  33. data/lib/vanilla/request.rb +15 -16
  34. data/lib/vanilla/routes.rb +18 -5
  35. data/lib/vanilla/snip_reference.rb +534 -0
  36. data/lib/vanilla/snip_reference.treetop +48 -0
  37. data/lib/vanilla/snip_reference_parser.rb +99 -82
  38. data/lib/vanilla/snips/start.rb +28 -0
  39. data/lib/vanilla/snips/system.rb +77 -0
  40. data/lib/vanilla/snips/tutorial.rb +244 -0
  41. data/lib/vanilla/soup_with_timestamps.rb +21 -0
  42. data/public/hatch.png +0 -0
  43. data/public/javascripts/jquery.autogrow-textarea.js +54 -0
  44. data/public/javascripts/jquery.js +4376 -0
  45. data/public/javascripts/vanilla.js +22 -0
  46. data/spec/dynasnip_spec.rb +28 -0
  47. data/spec/renderers/base_renderer_spec.rb +40 -0
  48. data/spec/renderers/erb_renderer_spec.rb +27 -0
  49. data/spec/renderers/markdown_renderer_spec.rb +29 -0
  50. data/spec/renderers/raw_renderer_spec.rb +21 -0
  51. data/spec/renderers/ruby_renderer_spec.rb +59 -0
  52. data/spec/renderers/vanilla_app_detecting_renderer_spec.rb +35 -0
  53. data/spec/spec_helper.rb +70 -0
  54. data/spec/tmp/config.yml +2 -0
  55. data/spec/tmp/soup/current_snip.yml +15 -0
  56. data/spec/tmp/soup/system.yml +5 -0
  57. data/spec/vanilla_app_spec.rb +38 -0
  58. data/spec/vanilla_presenting_spec.rb +84 -0
  59. data/spec/vanilla_request_spec.rb +73 -0
  60. metadata +79 -170
  61. data/lib/vanilla/renderers.rb +0 -12
  62. data/lib/vanilla/renderers/haml.rb +0 -13
  63. data/lib/vanilla/static.rb +0 -28
  64. data/pristine_app/Gemfile +0 -3
  65. data/pristine_app/Gemfile.lock +0 -32
  66. data/pristine_app/README +0 -47
  67. data/pristine_app/config.ru +0 -26
  68. data/pristine_app/public/vanilla.css +0 -15
  69. data/pristine_app/soups/base/layout.snip +0 -18
  70. data/pristine_app/soups/base/start.snip +0 -19
  71. data/pristine_app/soups/dynasnips/current_snip.rb +0 -29
  72. data/pristine_app/soups/dynasnips/link_to_current_snip.rb +0 -14
  73. data/pristine_app/soups/dynasnips/page_title.rb +0 -9
  74. data/pristine_app/soups/extras/comments.rb +0 -78
  75. data/pristine_app/soups/tutorial/bad_dynasnip.snip +0 -8
  76. data/pristine_app/soups/tutorial/hello_world.snip +0 -20
  77. data/pristine_app/soups/tutorial/markdown_example.snip +0 -13
  78. data/pristine_app/soups/tutorial/snip.snip +0 -9
  79. data/pristine_app/soups/tutorial/soup.snip +0 -3
  80. data/pristine_app/soups/tutorial/test.snip +0 -30
  81. data/pristine_app/soups/tutorial/textile_example.snip +0 -11
  82. data/pristine_app/soups/tutorial/tutorial-another-snip.snip +0 -1
  83. data/pristine_app/soups/tutorial/tutorial-basic-snip-inclusion.snip +0 -1
  84. data/pristine_app/soups/tutorial/tutorial-dynasnips.snip.markdown +0 -56
  85. data/pristine_app/soups/tutorial/tutorial-layout.snip +0 -56
  86. data/pristine_app/soups/tutorial/tutorial-links.snip +0 -4
  87. data/pristine_app/soups/tutorial/tutorial-renderers.snip.markdown +0 -77
  88. data/pristine_app/soups/tutorial/tutorial.snip.markdown +0 -69
  89. data/pristine_app/soups/tutorial/vanilla-rb.snip +0 -16
  90. data/pristine_app/soups/tutorial/vanilla.snip +0 -8
  91. data/test/dynasnip_test.rb +0 -42
  92. data/test/dynasnips/link_to_current_snip_test.rb +0 -19
  93. data/test/dynasnips/link_to_test.rb +0 -27
  94. data/test/dynasnips/page_title_test.rb +0 -19
  95. data/test/renderers/base_renderer_test.rb +0 -43
  96. data/test/renderers/erb_renderer_test.rb +0 -29
  97. data/test/renderers/haml_renderer_test.rb +0 -35
  98. data/test/renderers/markdown_renderer_test.rb +0 -31
  99. data/test/renderers/raw_renderer_test.rb +0 -23
  100. data/test/renderers/ruby_renderer_test.rb +0 -59
  101. data/test/snip_inclusion_test.rb +0 -56
  102. data/test/snip_reference_parser_test.rb +0 -123
  103. data/test/test_helper.rb +0 -75
  104. data/test/vanilla_app_test.rb +0 -83
  105. data/test/vanilla_presenting_test.rb +0 -125
  106. data/test/vanilla_request_test.rb +0 -87
data/pristine_app/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source :rubygems
2
-
3
- gem 'vanilla', :path => File.expand_path("../..", __FILE__)
@@ -1,32 +0,0 @@
1
- PATH
2
- remote: /Users/james/Code/lazyatom/vanilla-rb
3
- specs:
4
- vanilla (1.14.1)
5
- BlueCloth (>= 1.0.0)
6
- RedCloth (>= 4.1.1)
7
- haml
8
- rack (>= 0.9.1)
9
- ratom (>= 0.3.5)
10
- soup (>= 1.0.6)
11
- treetop (>= 1.4.1)
12
-
13
- GEM
14
- remote: http://rubygems.org/
15
- specs:
16
- BlueCloth (1.0.1)
17
- RedCloth (4.2.7)
18
- haml (3.1.1)
19
- libxml-ruby (2.0.2)
20
- polyglot (0.3.1)
21
- rack (1.2.2)
22
- ratom (0.6.7)
23
- libxml-ruby (>= 1.1.2)
24
- soup (1.0.6)
25
- treetop (1.4.9)
26
- polyglot (>= 0.3.1)
27
-
28
- PLATFORMS
29
- ruby
30
-
31
- DEPENDENCIES
32
- vanilla!
data/pristine_app/README DELETED
@@ -1,47 +0,0 @@
1
- WELCOME IN VANILLA
2
- Vanilla
3
- vanilla
4
- .........vanillaaaaaAAAAAAAAAAA
5
-
6
- What you've got:
7
-
8
- Gemfile - specifying your dependencies
9
- config.ru - this is the rack configuration, which is used to start
10
- the application by your webserver
11
- soup/ - the default soup directory, where your snips are stored
12
-
13
-
14
- For an overview of vanilla, start your site and look at the tutorial:
15
-
16
- $ rackup # then open http://localhost:9292/tutorial
17
-
18
-
19
- Editing snips
20
- -------------
21
- You can edit any file in the soup directory using your favourite editor,
22
- and the changes will be reflected automatically. The snip files are
23
- slightly modified YAML files. Here's an example, which you might save
24
- in a file called 'soup.snip':
25
-
26
-
27
- Soup is a data store supporting the {link_to snip}-space that
28
- {link_to vanilla-rb} expects.
29
-
30
- It's hosted on github [here](http://github.com/lazyatom/soup).
31
-
32
- :created_at: 2011-05-23 14:14:16 +01:00
33
- :updated_at: 2009-05-23 15:23:22 +01:00
34
- :render_as: Markdown
35
-
36
-
37
- The 'content' of the snip is at the top of the file, followed by the
38
- rest of the snip attributes on lines starting with ':'.
39
-
40
-
41
- The console
42
- -----------
43
-
44
- Within a vanilla app directory, you can run `vanilla console` to start
45
- an IRB session and interact with your app and snips. The `app` method
46
- returns your application object, and `app.soup['start']` will return
47
- the start snip from your soup(s).
@@ -1,26 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
- $:.unshift File.join(File.dirname(__FILE__), *%w[lib])
4
-
5
- require 'vanilla'
6
-
7
- # You can partition your snips into subdirectories to keep things tidy. This
8
- # doesn't affect their URL structure on the site (everything is flat).
9
- soups = [
10
- "soups/base",
11
- "soups/dynasnips"
12
- ]
13
-
14
- # If you don't want the tutorial on your site, remove this and delete the directory
15
- soups << "soups/tutorial"
16
-
17
- # This is a dumping ground of ideas at the moment
18
- # soups << "soups/extras"
19
-
20
- app = Vanilla::App.new(:soups => soups)
21
-
22
- # If you running your site under a proper webserver, you probably don't need this.
23
- require 'vanilla/static'
24
- use Vanilla::Static, File.join(File.dirname(__FILE__), 'public')
25
-
26
- run app
@@ -1,15 +0,0 @@
1
- #controls {
2
- padding-left: 0;
3
- }
4
-
5
- #controls li {
6
- background: #eee;
7
- display: inline;
8
- padding: 0.2em 0.5em;
9
- }
10
-
11
- pre {
12
- margin-left: 1em;
13
- background-color: #ddd;
14
- padding: 1em;
15
- }
@@ -1,18 +0,0 @@
1
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2
- <html lang="en">
3
- <head>
4
- <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
5
- <title>{page_title}</title>
6
- <link rel="stylesheet" href="/vanilla.css" type="text/css" media="screen" title="no title" charset="utf-8">
7
- </head>
8
- <body>
9
- <ul id="controls">
10
- <li><a href="/">home</a></li>
11
- <li>{link_to index}</li>
12
- <li>you are viewing: {link_to_current_snip}</li>
13
- </ul>
14
- <div id="content">
15
- {current_snip}
16
- </div>
17
- </body>
18
- </html>
@@ -1,19 +0,0 @@
1
- <h1>Welcome to Vanilla.rb</h1>
2
-
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>
4
-
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>
6
-
7
- <h2>What now?</h2>
8
-
9
- <p>If this is your first time using vanilla, you should investigate the {link_to tutorial} for some orientation.</p>
10
-
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>
@@ -1,29 +0,0 @@
1
- require 'vanilla/dynasnip'
2
-
3
- class CurrentSnip < Dynasnip
4
- usage %|
5
- The current_snip dyna normally returns the result of rendering the snip named by the
6
- 'snip' value in the parameters. This way, it can be used in templates to place the currently
7
- requested snip, in its rendered form, within the page.
8
-
9
- It can also be used to determine an attribute of the current snip in a consistent way:
10
-
11
- {current_snip name}
12
-
13
- will output the name of the current snip.
14
- |
15
-
16
- def handle(attribute=nil)
17
- if app.request.snip
18
- if attribute ||= app.request.part
19
- "{#{app.request.snip_name}.#{attribute}}"
20
- else
21
- "{#{app.request.snip_name}}"
22
- end
23
- else
24
- app.response.status = 404
25
- %{Couldn't find snip "#{app.request.snip_name}"}
26
- end
27
- end
28
- self
29
- end
@@ -1,14 +0,0 @@
1
- require 'vanilla/dynasnip'
2
-
3
- class LinkToCurrentSnip < Dynasnip
4
- usage %|
5
- Renders a link to the current snip, or the snip currently being edited
6
- (if we're currently editing)
7
- |
8
-
9
- def handle(*args)
10
- link_to app.request.snip_name
11
- end
12
-
13
- self
14
- end
@@ -1,9 +0,0 @@
1
- require 'vanilla/dynasnip'
2
-
3
- class PageTitle < Dynasnip
4
- def handle
5
- app.request.snip.page_title || app.request.snip.name
6
- end
7
-
8
- self
9
- end
@@ -1,78 +0,0 @@
1
- require 'vanilla/dynasnip'
2
- require 'date'
3
-
4
- class Comments < Dynasnip
5
- usage %|
6
- Embed comments within snips!
7
-
8
- {comments <false>}
9
-
10
- This will embed a list of comments, and a comment form, in a snip
11
- If the snip is being rendered within another snip, it will show a link to the snip,
12
- with the number of comments. Add a parameter to disable new comments.
13
- |
14
-
15
- def get(disable_new_comments=false)
16
- return usage if self.class.snip_name == app.request.snip_name
17
- comments = app.soup.with(:commenting_on => enclosing_snip.name)
18
- comments_html = if app.request.snip_name == enclosing_snip.name
19
- rendered_comments = render_comments(comments)
20
- rendered_comments += comment_form.gsub('SNIP_NAME', enclosing_snip.name) unless disable_new_comments
21
- rendered_comments
22
- else
23
- %{<a href="#{url_to(enclosing_snip.name)}">#{comments.length} comments for #{enclosing_snip.name}</a>}
24
- end
25
- return comments_html
26
- end
27
-
28
- def post(*args)
29
- snip_name = app.request.params[:snip]
30
- existing_comments = app.soup.with(:commenting_on => snip_name)
31
- comment = app.request.params.reject { |k,v| ![:author, :email, :website, :content].include?(k) }
32
-
33
- return "You need to add some details!" if comment.empty?
34
- return "No spam today, thanks anyway" unless app.request.params[:human] == 'human'
35
-
36
- app.soup << comment.merge({
37
- :name => "#{snip_name}-comment-#{existing_comments.length + 1}",
38
- :commenting_on => snip_name,
39
- :created_at => Time.now
40
- })
41
- "Thanks for your comment! Back to {link_to #{snip_name}}"
42
- end
43
-
44
- def render_comments(comments)
45
- "<h2>Comments</h2><ol class='comments'>" + comments.map do |comment|
46
- rendered_comment = comment_template.gsub('COMMENT_CONTENT', app.render(comment)).
47
- gsub('COMMENT_DATE', comment.created_at.to_s)
48
- author = comment.author
49
- author = "Anonymous" unless author && author != ""
50
- if comment.website && comment.website != ""
51
- rendered_comment.gsub!('COMMENT_AUTHOR', "<a href=\"#{comment.website}\">#{author}</a>")
52
- else
53
- rendered_comment.gsub!('COMMENT_AUTHOR', author)
54
- end
55
- rendered_comment
56
- end.join + "</ol>"
57
- end
58
-
59
- attribute :comment_template, %{
60
- <li>
61
- <p>COMMENT_AUTHOR (COMMENT_DATE)</p>
62
- <div>COMMENT_CONTENT</div>
63
- </li>
64
- }
65
-
66
- attribute :comment_form, %{
67
- <form class="comments" action="/comments?snip=SNIP_NAME" method="POST">
68
- <label>Name: <input type="text" name="author"></input></label>
69
- <label>Email: <input type="text" name="email"></input></label>
70
- <label>Website: <input type="text" name="website"></input></label>
71
- <textarea name="content"></textarea>
72
- <label class="human">Type 'human' if you are one: <input type="text" name="human"></input></label>
73
- <button>Submit</button>
74
- </form>
75
- }
76
-
77
- self
78
- end
@@ -1,8 +0,0 @@
1
- class BadDynasnip
2
- def get(*args)
3
- raise "Oh no"
4
- end
5
- end
6
- BadDynasnip
7
-
8
- :render_as: Ruby
@@ -1,20 +0,0 @@
1
- class HelloWorld
2
- # although the name doesn't need to match the snip name,
3
- # it's simple to follow that convention where appropriate
4
-
5
- def handle(name=nil)
6
- if name
7
- "Hey #{name} - Hello World!"
8
- else
9
- "Hello World!"
10
- end
11
- end
12
-
13
- # note that this code must evaluate to a class. One way of achieving that is by
14
- # putting 'self' at the end of the class definition.
15
- self
16
- end
17
- # Another way is by referring to the class at the end of the content. Either works fine.
18
- HelloWorld
19
-
20
- :render_as: Ruby
@@ -1,13 +0,0 @@
1
-
2
- # testing header
3
-
4
- so, how are you?
5
-
6
- - item one
7
- - item two
8
- - item three
9
-
10
-
11
- what the *hell* are looking at, [beyotch](http://example.com)?
12
-
13
- :render_as: Markdown
@@ -1,9 +0,0 @@
1
- A snip is the basic building block of information for {link_to vanilla-rb}. Essentially, it is a piece of content with arbitrary attributes. Vanilla anticipates the presence of some key attributes:
2
-
3
- * `name` - the name of the snip, which is how it will be referred to. The `name` of this snip is _snip_.
4
- * `content` - the default part of the snip to render. You can see the `content` of this snip <a href="/snip/content.raw">here</a>.
5
- * `render_as` - the name of the renderer to use when rendering the content. The `render_as` of this snip is {snip.render_as}.
6
-
7
- One implementation of the snip store is {link_to soup}.
8
-
9
- :render_as: Markdown
@@ -1,3 +0,0 @@
1
- Soup is a data store supporting the {link_to snip}-space that {link_to vanilla-rb} expects.
2
-
3
- It's hosted on github <a href="http://github.com/lazyatom/soup">here</a>.
@@ -1,30 +0,0 @@
1
- Linking is good: {link_to bold}
2
- Here's a bold snip: {bold}
3
-
4
- - Here's a random number between 5 and 15: {rand 5,15}
5
- - Here's a random number between 1 and 90 (the default min): {rand 90}
6
- - Here's a random number between 1 and 100 (the default range): {rand}
7
-
8
- And lets include some textile:
9
-
10
- {textile_example}
11
-
12
- The source for that was
13
-
14
- {pre textile_example}
15
-
16
- And lets include some markdown!:
17
-
18
- {markdown_example}
19
-
20
- The source for that was
21
-
22
- {pre markdown_example}
23
-
24
- How about some {link_to debug} information: {debug}
25
-
26
- What about a missing snip? Lets try to include one: {monkey}
27
-
28
- And an error when running? {bad_dynasnip}
29
-
30
- :render_as: Markdown
@@ -1,11 +0,0 @@
1
-
2
- # testing lists
3
- # because lists are common things
4
-
5
- monkey
6
-
7
- what the *hell* are __you__ looking at?
8
-
9
- "Beyotch":http://example.com
10
-
11
- :render_as: Textile
@@ -1 +0,0 @@
1
- this is another snip!
@@ -1 +0,0 @@
1
- This is a snip, which includes another {link_to snip}: {tutorial-another-snip}
@@ -1,56 +0,0 @@
1
- {tutorial-links}
2
-
3
- Dynasnips
4
- =========
5
-
6
- As mentioned in the general {link_to tutorial}, dynamic content is built in vanilla using "dynasnips". These are snips who content depends on more than just their content.
7
-
8
- Typically they are rendered by the `Vanilla::Renderers::Ruby` renderer. Lets look again at the raw content of `link_to`:
9
-
10
- {raw link_to}
11
-
12
- As you can see, it simply refers to the Ruby class `LinkTo`, which is contained within the vanilla-rb codebase. When the Ruby renderer is called, expects the given code to evaulate to a Ruby class. It then instantiates the class, and calls a `handle` method on the instance, passing it any other arguments from the snip inclusion.
13
-
14
- You can pass arguments to dynasnips in a number of ways. All of the following are valid:
15
-
16
- * &#123;dynasnip apple&#125;
17
- * &#123;dynasnip apple, banana&#125;
18
- * &#123;dynasnip apple, big banana, cherry&#125;
19
- * &#123;dynasnip apple, big banana, "lovely lucious cherry"&#125;
20
- * &#123;dynasnip apple => true, banana => false&#125;
21
- * &#123;dynasnip apple: true, banana: false&#125;
22
-
23
- Where a simple list of arguments is given, these will be passed to the `handle` method as an array. If a ruby-hash-like syntax is used, a hash of these options will be passed.
24
-
25
- Of course, it depends entirely on the implementation of the dynasnip what arguments it expects and accepts; some may require a flat list, while others may require hash-like named arguments.
26
-
27
-
28
- Writing your own Dynasnips
29
- --------------------------
30
-
31
- While dynasnip classes can be provided as part of the vanilla codebase, it's envisioned that much of these will be created by end users in their own sites, either by refering to local classes, or defining the classes directly as the content. Here's an example of that, as the raw content of `hello_world`:
32
-
33
- {raw hello_world}
34
-
35
- It's important that the contents of the snip evaluate to a Ruby class; this is easy to achieve by placing `self` as the last statement in the class definition, or referencing the class at the end of the snip; both are shown above.
36
-
37
- If we include the dynasnip here as <tt>&#123;hello\_world&#125;</tt>, gives:
38
-
39
- > {hello_world}
40
-
41
- Note that the `handle` method can take one (optional) argument. Lets try including it with <tt>&#123;hello\_world Dave&#125;</tt>:
42
-
43
- > {hello_world Dave}
44
-
45
-
46
- HTTP Verbs
47
- ----------
48
-
49
- By default, the Ruby renderer will attempt to call `handle` on a dynasnip instance, but if the instance responds to methods corresponding to the HTTP Verbs - `get`, `post`, `put`, or `delete` - then these methods will be called instead.
50
-
51
- This means you can have a single dynasnip which responds differently when receiving a `POST` request - quite useful if you want to write dynasnips that generate and respond to forms, like the `comments` dynasnip in your `extras` soup directory.
52
-
53
- There's really no limit to what you can do with dynasnips - only what you can imagine.
54
-
55
-
56
- {tutorial-links}