vanilla 1.0.2 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +112 -109
- data/bin/vanilla +35 -6
- data/lib/vanilla.rb +10 -14
- data/lib/vanilla/app.rb +109 -41
- data/lib/vanilla/console.rb +22 -2
- data/lib/vanilla/dynasnip.rb +4 -36
- data/lib/vanilla/renderers.rb +12 -0
- data/lib/vanilla/renderers/base.rb +58 -34
- data/lib/vanilla/renderers/bold.rb +0 -2
- data/lib/vanilla/renderers/erb.rb +1 -3
- data/lib/vanilla/renderers/haml.rb +13 -0
- data/lib/vanilla/renderers/markdown.rb +0 -2
- data/lib/vanilla/renderers/raw.rb +0 -2
- data/lib/vanilla/renderers/ruby.rb +12 -6
- data/lib/vanilla/renderers/textile.rb +0 -2
- data/lib/vanilla/request.rb +19 -17
- data/lib/vanilla/routes.rb +9 -20
- data/lib/vanilla/snip_reference_parser.rb +94 -0
- data/lib/vanilla/static.rb +28 -0
- data/pristine_app/Gemfile +3 -0
- data/pristine_app/Gemfile.lock +32 -0
- data/pristine_app/README +47 -0
- data/pristine_app/config.ru +26 -0
- data/pristine_app/public/vanilla.css +15 -0
- data/pristine_app/soups/base/layout.snip +18 -0
- data/pristine_app/soups/base/start.snip +19 -0
- data/pristine_app/soups/dynasnips/current_snip.rb +29 -0
- data/{lib/vanilla → pristine_app/soups}/dynasnips/debug.rb +5 -3
- data/pristine_app/soups/dynasnips/index.rb +12 -0
- data/{lib/vanilla → pristine_app/soups}/dynasnips/link_to.rb +4 -2
- data/pristine_app/soups/dynasnips/link_to_current_snip.rb +14 -0
- data/pristine_app/soups/dynasnips/page_title.rb +9 -0
- data/{lib/vanilla → pristine_app/soups}/dynasnips/pre.rb +7 -5
- data/{lib/vanilla → pristine_app/soups}/dynasnips/raw.rb +8 -5
- data/pristine_app/soups/extras/comments.rb +78 -0
- data/{lib/vanilla/dynasnips → pristine_app/soups/extras}/kind.rb +19 -17
- data/{lib/vanilla/dynasnips → pristine_app/soups/extras}/rand.rb +2 -0
- data/pristine_app/soups/extras/url_to.rb +7 -0
- data/pristine_app/soups/tutorial/bad_dynasnip.snip +8 -0
- data/pristine_app/soups/tutorial/hello_world.snip +20 -0
- data/pristine_app/soups/tutorial/markdown_example.snip +13 -0
- data/pristine_app/soups/tutorial/snip.snip +9 -0
- data/pristine_app/soups/tutorial/soup.snip +3 -0
- data/pristine_app/soups/tutorial/test.snip +30 -0
- data/pristine_app/soups/tutorial/textile_example.snip +11 -0
- data/pristine_app/soups/tutorial/tutorial-another-snip.snip +1 -0
- data/pristine_app/soups/tutorial/tutorial-basic-snip-inclusion.snip +1 -0
- data/pristine_app/soups/tutorial/tutorial-dynasnips.snip.markdown +56 -0
- data/pristine_app/soups/tutorial/tutorial-layout.snip +56 -0
- data/pristine_app/soups/tutorial/tutorial-links.snip +4 -0
- data/pristine_app/soups/tutorial/tutorial-renderers.snip.markdown +77 -0
- data/pristine_app/soups/tutorial/tutorial.snip.markdown +69 -0
- data/pristine_app/soups/tutorial/vanilla-rb.snip +16 -0
- data/pristine_app/soups/tutorial/vanilla.snip +8 -0
- data/test/dynasnip_test.rb +42 -0
- data/test/dynasnips/link_to_current_snip_test.rb +19 -0
- data/test/dynasnips/link_to_test.rb +27 -0
- data/test/dynasnips/page_title_test.rb +19 -0
- data/test/renderers/base_renderer_test.rb +43 -0
- data/test/renderers/erb_renderer_test.rb +29 -0
- data/test/renderers/haml_renderer_test.rb +35 -0
- data/test/renderers/markdown_renderer_test.rb +31 -0
- data/test/renderers/raw_renderer_test.rb +23 -0
- data/test/renderers/ruby_renderer_test.rb +59 -0
- data/test/snip_inclusion_test.rb +56 -0
- data/test/snip_reference_parser_test.rb +123 -0
- data/test/test_helper.rb +75 -0
- data/test/vanilla_app_test.rb +83 -0
- data/test/vanilla_presenting_test.rb +125 -0
- data/test/vanilla_request_test.rb +87 -0
- metadata +179 -78
- data/config.example.yml +0 -5
- data/config.ru +0 -9
- data/lib/defensio.rb +0 -59
- data/lib/tasks/vanilla.rake +0 -177
- data/lib/vanilla/dynasnips/comments.rb +0 -108
- data/lib/vanilla/dynasnips/current_snip.rb +0 -32
- data/lib/vanilla/dynasnips/edit.rb +0 -63
- data/lib/vanilla/dynasnips/edit_link.rb +0 -24
- data/lib/vanilla/dynasnips/index.rb +0 -11
- data/lib/vanilla/dynasnips/link_to_current_snip.rb +0 -16
- data/lib/vanilla/dynasnips/login.rb +0 -56
- data/lib/vanilla/dynasnips/new.rb +0 -14
- data/lib/vanilla/dynasnips/notes.rb +0 -42
- data/lib/vanilla/dynasnips/url_to.rb +0 -7
- data/lib/vanilla/snip_handling.rb +0 -33
- data/lib/vanilla/snips/start.rb +0 -27
- data/lib/vanilla/snips/system.rb +0 -76
- data/lib/vanilla/snips/tutorial.rb +0 -157
- data/lib/vanilla/test_snips.rb +0 -85
- data/public/hatch.png +0 -0
- data/public/javascripts/jquery.js +0 -3549
- data/public/javascripts/vanilla.js +0 -21
- data/spec/dynasnip_spec.rb +0 -31
- data/spec/renderers/base_renderer_spec.rb +0 -40
- data/spec/renderers/erb_renderer_spec.rb +0 -27
- data/spec/renderers/markdown_renderer_spec.rb +0 -29
- data/spec/renderers/raw_renderer_spec.rb +0 -21
- data/spec/renderers/ruby_renderer_spec.rb +0 -42
- data/spec/renderers/vanilla_app_detecting_renderer_spec.rb +0 -35
- data/spec/spec_helper.rb +0 -64
- data/spec/vanilla_app_spec.rb +0 -38
- data/spec/vanilla_presenting_spec.rb +0 -84
- data/spec/vanilla_request_spec.rb +0 -73
- data/spec/vanilla_snip_finding_spec.rb +0 -28
data/lib/vanilla/console.rb
CHANGED
@@ -1,3 +1,23 @@
|
|
1
1
|
require 'vanilla'
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
module Vanilla
|
4
|
+
class RackShim
|
5
|
+
def run(app)
|
6
|
+
app # return it
|
7
|
+
end
|
8
|
+
def use(*args)
|
9
|
+
# ignore
|
10
|
+
end
|
11
|
+
def get_binding
|
12
|
+
binding
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def app(reload=false)
|
18
|
+
if !@__vanilla_console_app || reload
|
19
|
+
shim_binding = Vanilla::RackShim.new.get_binding
|
20
|
+
@__vanilla_console_app = eval File.read("config.ru"), shim_binding
|
21
|
+
end
|
22
|
+
@__vanilla_console_app
|
23
|
+
end
|
data/lib/vanilla/dynasnip.rb
CHANGED
@@ -29,48 +29,16 @@ class Dynasnip < Vanilla::Renderers::Base
|
|
29
29
|
attribute :usage, escape_curly_braces(str).strip
|
30
30
|
end
|
31
31
|
|
32
|
-
def self.persist_all!(overwrite=false)
|
33
|
-
all.each do |dynasnip|
|
34
|
-
dynasnip.persist!(overwrite)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.build_snip
|
39
|
-
Snip.new(snip_attributes)
|
40
|
-
end
|
41
|
-
|
42
32
|
def self.snip_attributes
|
43
33
|
full_snip_attributes = {:name => snip_name, :content => self.name, :render_as => "Ruby"}
|
44
34
|
@attributes ? full_snip_attributes.merge!(@attributes) : full_snip_attributes
|
45
35
|
end
|
46
36
|
|
47
|
-
|
48
|
-
if overwrite
|
49
|
-
snip = Soup[snip_name]
|
50
|
-
if snip
|
51
|
-
if snip.is_a?(Array)
|
52
|
-
snip.each { |s| s.destroy }
|
53
|
-
else
|
54
|
-
snip.destroy
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
snip = Soup[snip_name]
|
59
|
-
snip = snip[0] if snip.is_a?(Array)
|
60
|
-
if snip
|
61
|
-
snip_attributes.each do |name, value|
|
62
|
-
snip.set_value(name, value)
|
63
|
-
end
|
64
|
-
else
|
65
|
-
snip = build_snip
|
66
|
-
end
|
67
|
-
snip.save
|
68
|
-
snip
|
69
|
-
end
|
37
|
+
attr_accessor :enclosing_snip
|
70
38
|
|
71
39
|
def method_missing(method, *args)
|
72
|
-
if snip
|
73
|
-
snip.
|
40
|
+
if snip
|
41
|
+
snip.__send__(method)
|
74
42
|
elsif part = self.class.attribute(method)
|
75
43
|
part
|
76
44
|
else
|
@@ -88,7 +56,7 @@ class Dynasnip < Vanilla::Renderers::Base
|
|
88
56
|
end
|
89
57
|
|
90
58
|
def snip
|
91
|
-
|
59
|
+
app.soup[snip_name]
|
92
60
|
end
|
93
61
|
|
94
62
|
def show_usage
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Vanilla
|
2
|
+
module Renderers
|
3
|
+
autoload :Base, "vanilla/renderers/base"
|
4
|
+
autoload :Bold, "vanilla/renderers/bold"
|
5
|
+
autoload :Erb, "vanilla/renderers/erb"
|
6
|
+
autoload :Haml, "vanilla/renderers/haml"
|
7
|
+
autoload :Markdown, "vanilla/renderers/markdown"
|
8
|
+
autoload :Raw, "vanilla/renderers/raw"
|
9
|
+
autoload :Ruby, "vanilla/renderers/ruby"
|
10
|
+
autoload :Textile, "vanilla/renderers/textile"
|
11
|
+
end
|
12
|
+
end
|
@@ -1,74 +1,98 @@
|
|
1
|
-
require 'vanilla/
|
1
|
+
require 'vanilla/snip_reference_parser'
|
2
2
|
|
3
3
|
module Vanilla
|
4
4
|
module Renderers
|
5
5
|
class Base
|
6
|
-
|
6
|
+
include Routes
|
7
|
+
|
7
8
|
# Render a snip.
|
8
9
|
def self.render(snip, part=:content)
|
9
10
|
new(app).render(snip, part)
|
10
11
|
end
|
11
|
-
|
12
|
+
|
12
13
|
def self.escape_curly_braces(str)
|
13
14
|
str.gsub("{", "{").gsub("}", "}")
|
14
15
|
end
|
15
|
-
|
16
|
+
|
16
17
|
attr_reader :app
|
17
|
-
|
18
|
+
|
18
19
|
def initialize(app)
|
19
20
|
@app = app
|
20
21
|
end
|
21
|
-
|
22
|
+
|
23
|
+
# defined for the routes
|
24
|
+
def soup
|
25
|
+
@app.soup
|
26
|
+
end
|
27
|
+
|
22
28
|
def self.snip_regexp
|
23
|
-
%r{
|
24
|
-
|
25
|
-
|
26
|
-
|
29
|
+
%r{(\{[\w\-_\d\.\"\'\s]+(\s+[^\}.]+)?\})}
|
30
|
+
end
|
31
|
+
|
32
|
+
def default_layout_snip
|
33
|
+
app.default_layout_snip
|
34
|
+
end
|
35
|
+
|
36
|
+
def layout_for(snip)
|
37
|
+
layout_snip = (snip && snip.layout) ? soup[snip.layout] : default_layout_snip
|
27
38
|
end
|
28
|
-
|
39
|
+
|
29
40
|
# Default behaviour to include a snip's content
|
30
|
-
def include_snips(content)
|
41
|
+
def include_snips(content, enclosing_snip)
|
31
42
|
content.gsub(Vanilla::Renderers::Base.snip_regexp) do
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
43
|
+
snip_tree = parse_snip_reference($1)
|
44
|
+
if snip_tree
|
45
|
+
snip_name = snip_tree.snip
|
46
|
+
snip_attribute = snip_tree.attribute
|
47
|
+
snip_args = snip_tree.arguments
|
48
|
+
|
49
|
+
# Render the snip or snip part with the given args, and the current
|
50
|
+
# context, but with the default renderer for that snip. We dispatch
|
51
|
+
# *back* out to the root Vanilla.render method to do this.
|
52
|
+
if snip = soup[snip_name]
|
53
|
+
app.render(snip, snip_attribute, snip_args, enclosing_snip)
|
54
|
+
else
|
55
|
+
render_missing_snip(snip_name)
|
56
|
+
end
|
42
57
|
else
|
43
|
-
|
58
|
+
"malformed snip reference: #{$1.inspect}"
|
44
59
|
end
|
45
60
|
end
|
46
61
|
end
|
47
|
-
|
62
|
+
|
63
|
+
def parse_snip_reference(string)
|
64
|
+
@parser ||= Vanilla::SnipReferenceParser.new
|
65
|
+
@parser.parse(string)
|
66
|
+
end
|
67
|
+
|
68
|
+
def render_missing_snip(snip_name)
|
69
|
+
"[snip '#{snip_name}' cannot be found]"
|
70
|
+
end
|
71
|
+
|
48
72
|
# Default rendering behaviour. Subclasses shouldn't really need to touch this.
|
49
|
-
def render(snip, part=:content, args=[])
|
50
|
-
prepare(snip, part, args)
|
73
|
+
def render(snip, part=:content, args=[], enclosing_snip=snip)
|
74
|
+
prepare(snip, part, args, enclosing_snip)
|
51
75
|
processed_text = render_without_including_snips(snip, part)
|
52
|
-
include_snips(processed_text)
|
76
|
+
include_snips(processed_text, snip)
|
53
77
|
end
|
54
|
-
|
78
|
+
|
55
79
|
# Subclasses should override this to perform any actions required before
|
56
80
|
# rendering
|
57
|
-
def prepare(snip, part, args)
|
81
|
+
def prepare(snip, part, args, enclosing_snip)
|
58
82
|
# do nothing, by default
|
59
83
|
end
|
60
|
-
|
84
|
+
|
61
85
|
def render_without_including_snips(snip, part=:content)
|
62
86
|
process_text(raw_content(snip, part))
|
63
87
|
end
|
64
|
-
|
65
|
-
# Handles processing the text of the content.
|
66
|
-
# Subclasses should override this method to do fancy text processing
|
88
|
+
|
89
|
+
# Handles processing the text of the content.
|
90
|
+
# Subclasses should override this method to do fancy text processing
|
67
91
|
# like markdown, or loading the content as Ruby code.
|
68
92
|
def process_text(content)
|
69
93
|
content
|
70
94
|
end
|
71
|
-
|
95
|
+
|
72
96
|
# Returns the raw content for the selected part of the selected snip
|
73
97
|
def raw_content(snip, part)
|
74
98
|
snip.__send__((part || :content).to_sym)
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'vanilla/renderers/base'
|
2
|
-
|
3
1
|
module Vanilla::Renderers
|
4
2
|
# Snips that render_as "Ruby" should define a class.
|
5
3
|
# The class should have instance methods for any HTTP request methods that the dynasnip
|
@@ -13,9 +11,10 @@ module Vanilla::Renderers
|
|
13
11
|
# itself), it should be a subclass of Dynasnip (or define an initializer
|
14
12
|
# that accepts the context as its first argument).
|
15
13
|
class Ruby < Base
|
16
|
-
def prepare(snip, part=:content, args=[])
|
14
|
+
def prepare(snip, part=:content, args=[], enclosing_snip=snip)
|
17
15
|
@args = args
|
18
16
|
@snip = snip
|
17
|
+
@enclosing_snip = enclosing_snip
|
19
18
|
end
|
20
19
|
|
21
20
|
def process_text(content)
|
@@ -25,10 +24,17 @@ module Vanilla::Renderers
|
|
25
24
|
else
|
26
25
|
handler_klass.new
|
27
26
|
end
|
28
|
-
|
29
|
-
|
27
|
+
instance.enclosing_snip = @enclosing_snip if instance.respond_to?(:enclosing_snip)
|
28
|
+
|
29
|
+
if app.request && (method = app.request.method) && instance.respond_to?(method)
|
30
|
+
message = method
|
31
|
+
else
|
32
|
+
message = :handle
|
33
|
+
end
|
34
|
+
if @args.is_a?(Array)
|
35
|
+
instance.send(message, *@args).to_s
|
30
36
|
else
|
31
|
-
instance.
|
37
|
+
instance.send(message, @args).to_s
|
32
38
|
end
|
33
39
|
end
|
34
40
|
end
|
data/lib/vanilla/request.rb
CHANGED
@@ -4,10 +4,12 @@ module Vanilla
|
|
4
4
|
# Create a request with symbolised access to the params, and some special
|
5
5
|
# accessors to the snip, part and format based on our routing.
|
6
6
|
class Request
|
7
|
-
attr_reader :snip_name, :part, :format, :method
|
8
|
-
|
9
|
-
def initialize(env)
|
7
|
+
attr_reader :snip_name, :part, :format, :method, :env
|
8
|
+
|
9
|
+
def initialize(env, app)
|
10
|
+
@env = env
|
10
11
|
@rack_request = Rack::Request.new(env)
|
12
|
+
@app = app
|
11
13
|
determine_request_uri_parts
|
12
14
|
end
|
13
15
|
|
@@ -15,46 +17,46 @@ module Vanilla
|
|
15
17
|
# Don't you just love how terse functional programming tends to look like maths?
|
16
18
|
@symbolised_params ||= @rack_request.params.inject({}) { |p, (k,v)| p[k.to_sym] = v; p }
|
17
19
|
end
|
18
|
-
|
20
|
+
|
19
21
|
# Returns the snip referenced by the request's URL. Performs no exception
|
20
22
|
# handling, so if the snip does not exist, an exception will be thrown.
|
21
23
|
def snip
|
22
|
-
|
24
|
+
@app.soup[snip_name]
|
23
25
|
end
|
24
|
-
|
26
|
+
|
25
27
|
def cookies
|
26
28
|
@rack_request.cookies
|
27
29
|
end
|
28
|
-
|
30
|
+
|
29
31
|
def ip
|
30
32
|
@rack_request.env["REMOTE_ADDR"]
|
31
33
|
end
|
32
|
-
|
34
|
+
|
33
35
|
def session
|
34
36
|
@rack_request.env["rack.session"]
|
35
37
|
end
|
36
|
-
|
38
|
+
|
37
39
|
private
|
38
|
-
|
40
|
+
|
39
41
|
def determine_request_uri_parts
|
40
42
|
@snip_name, @part, @format = request_uri_parts(@rack_request)
|
41
43
|
@format ||= 'html'
|
42
44
|
@method = (params.delete(:_method) || @rack_request.request_method).downcase
|
43
45
|
end
|
44
|
-
|
46
|
+
|
45
47
|
def uri_path(request)
|
46
48
|
request.path_info
|
47
49
|
end
|
48
|
-
|
49
|
-
URL_ROOT = /\A
|
50
|
+
|
51
|
+
URL_ROOT = /\A\/?\Z/ # i.e. / or nothing
|
50
52
|
URL_SNIP = /\A\/([\w\-\s]+)(\/|\.(\w+))?\Z/ # i.e. /start, /start.html
|
51
53
|
URL_SNIP_AND_PART = /\A\/([\w\-\s]+)\/([\w\-\s]+)(\/|\.(\w+))?\Z/ # i.e. /blah/part, /blah/part.raw
|
52
|
-
|
54
|
+
|
53
55
|
# Returns an array of the requested snip, part and format
|
54
56
|
def request_uri_parts(request)
|
55
57
|
case CGI.unescape(uri_path(request))
|
56
58
|
when URL_ROOT
|
57
|
-
['start', nil, 'html']
|
59
|
+
[@app.config[:root_snip] || 'start', nil, 'html']
|
58
60
|
when URL_SNIP
|
59
61
|
[$1, nil, $3]
|
60
62
|
when URL_SNIP_AND_PART
|
@@ -63,6 +65,6 @@ module Vanilla
|
|
63
65
|
[]
|
64
66
|
end
|
65
67
|
end
|
66
|
-
|
68
|
+
|
67
69
|
end
|
68
|
-
end
|
70
|
+
end
|
data/lib/vanilla/routes.rb
CHANGED
@@ -1,29 +1,18 @@
|
|
1
1
|
module Vanilla
|
2
|
+
# Expects to be able to call 'soup' on whatever it is included into
|
2
3
|
module Routes
|
3
4
|
def link_to(link_text, snip_name=link_text, part=nil)
|
4
|
-
|
5
|
+
if soup[snip_name]
|
6
|
+
%{<a href="#{url_to(snip_name, part)}">#{link_text}</a>}
|
7
|
+
else
|
8
|
+
%{<a class="missing" href="#{url_to(snip_name, part)}">#{link_text}</a>}
|
9
|
+
end
|
5
10
|
end
|
6
|
-
|
11
|
+
|
7
12
|
def url_to(snip_name, part=nil)
|
8
|
-
url = "/#{snip_name}"
|
13
|
+
url = "/#{snip_name.gsub(" ", "+")}"
|
9
14
|
url += "/#{part}" if part
|
10
15
|
url
|
11
16
|
end
|
12
|
-
|
13
|
-
def url_to_raw(snip_name, part=nil)
|
14
|
-
url = "/#{snip_name}"
|
15
|
-
url += "/#{part}" if part
|
16
|
-
url += ".raw"
|
17
|
-
end
|
18
|
-
|
19
|
-
def edit_link(snip_name, link_text)
|
20
|
-
%[<a href="/edit?name=#{snip_name}">#{link_text}</a>]
|
21
|
-
end
|
22
|
-
|
23
|
-
def new_link(snip_name="New")
|
24
|
-
%[<a href="/new?name=#{snip_name}" class="new">#{snip_name}</a>]
|
25
|
-
end
|
26
|
-
|
27
|
-
extend self
|
28
17
|
end
|
29
|
-
end
|
18
|
+
end
|