vanilla 1.15.1 → 1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/Rakefile +2 -2
  2. data/lib/vanilla.rb +2 -1
  3. data/lib/vanilla/renderers/base.rb +2 -2
  4. data/lib/vanilla/routes.rb +5 -18
  5. data/lib/vanilla/snip_reference_parser.rb +87 -64
  6. data/pristine_app/Gemfile.lock +2 -2
  7. data/pristine_app/README +11 -0
  8. data/pristine_app/soups/dynasnips/current_snip.rb +7 -7
  9. data/pristine_app/soups/tutorial/vanilla-rb.snip +2 -2
  10. data/pristine_app/soups/tutorial/vanilla.snip +1 -1
  11. data/test/dynasnip_test.rb +13 -0
  12. data/test/dynasnips/link_to_current_snip_test.rb +19 -0
  13. data/test/dynasnips/link_to_test.rb +27 -0
  14. data/test/dynasnips/page_title_test.rb +19 -0
  15. data/test/{base_renderer_test.rb → renderers/base_renderer_test.rb} +0 -0
  16. data/test/{erb_renderer_test.rb → renderers/erb_renderer_test.rb} +0 -0
  17. data/test/{haml_renderer_test.rb → renderers/haml_renderer_test.rb} +0 -0
  18. data/test/{markdown_renderer_test.rb → renderers/markdown_renderer_test.rb} +0 -0
  19. data/test/{raw_renderer_test.rb → renderers/raw_renderer_test.rb} +0 -0
  20. data/test/{ruby_renderer_test.rb → renderers/ruby_renderer_test.rb} +0 -0
  21. data/test/{snip_reference_test.rb → snip_inclusion_test.rb} +1 -1
  22. data/test/snip_reference_parser_test.rb +110 -42
  23. data/test/vanilla_presenting_test.rb +1 -5
  24. metadata +46 -57
  25. data/lib/vanilla/snip_reference.rb +0 -754
  26. data/lib/vanilla/snip_reference.treetop +0 -67
  27. data/pristine_app/tmp/restart.txt +0 -0
  28. data/test/soup/blah.snip +0 -4
  29. data/test/soup/blah.snip.erb +0 -4
  30. data/test/soup/blah.snip.haml +0 -4
  31. data/test/soup/blah.snip.markdown +0 -4
  32. data/test/soup/blah.snip.rb +0 -4
  33. data/test/soup/blah.snip.textile +0 -4
  34. data/test/soup/current_snip.snip +0 -14
  35. data/test/soup/layout.snip +0 -4
  36. data/test/soup/test.snip +0 -3
  37. data/test/soup/test_dyna.snip +0 -7
data/Rakefile CHANGED
@@ -46,10 +46,10 @@ if Object.const_defined?(:Gem)
46
46
  s.add_dependency("ratom", ">= 0.3.5")
47
47
  s.add_dependency("RedCloth", ">= 4.1.1")
48
48
  s.add_dependency("BlueCloth", ">= 1.0.0")
49
- s.add_dependency("treetop", ">= 1.4.1")
50
49
  s.add_dependency("haml")
50
+ s.add_dependency("parslet", ">= 1.2.0")
51
51
 
52
- s.add_development_dependency("kintama", ">= 0.1.5") # add any other gems for testing/development
52
+ s.add_development_dependency("kintama", ">= 0.1.6") # add any other gems for testing/development
53
53
  s.add_development_dependency("mocha")
54
54
 
55
55
  # If you want to publish automatically to rubyforge, you'll may need
data/lib/vanilla.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Vanilla
2
- VERSION = "1.15.1"
2
+ VERSION = "1.16"
3
3
 
4
4
  autoload :Renderers, "vanilla/renderers"
5
5
  autoload :App, "vanilla/app"
@@ -7,6 +7,7 @@ module Vanilla
7
7
  autoload :Request, "vanilla/request"
8
8
  autoload :Routes, "vanilla/routes"
9
9
  autoload :Static, "vanilla/static"
10
+ autoload :SnipReferenceParser, "vanilla/snip_reference_parser"
10
11
  end
11
12
 
12
13
  # Load all the base dynasnip classes
@@ -26,7 +26,7 @@ module Vanilla
26
26
  end
27
27
 
28
28
  def self.snip_regexp
29
- %r{(\{[\w\-_\d\.\"]+(\s+[^\}.]+)?\})}
29
+ %r{(\{[\w\-_\d\.\"\'\s]+(\s+[^\}.]+)?\})}
30
30
  end
31
31
 
32
32
  def default_layout_snip
@@ -61,7 +61,7 @@ module Vanilla
61
61
  end
62
62
 
63
63
  def parse_snip_reference(string)
64
- @parser ||= SnipReferenceParser.new
64
+ @parser ||= Vanilla::SnipReferenceParser.new
65
65
  @parser.parse(string)
66
66
  end
67
67
 
@@ -2,7 +2,11 @@ module Vanilla
2
2
  # Expects to be able to call 'soup' on whatever it is included into
3
3
  module Routes
4
4
  def link_to(link_text, snip_name=link_text, part=nil)
5
- soup[snip_name] ? existing_link(link_text, snip_name, part) : new_link(snip_name)
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
6
10
  end
7
11
 
8
12
  def url_to(snip_name, part=nil)
@@ -10,22 +14,5 @@ module Vanilla
10
14
  url += "/#{part}" if part
11
15
  url
12
16
  end
13
-
14
- def url_to_raw(snip_name, part=nil)
15
- url = url_to(snip_name, part)
16
- url += ".raw"
17
- end
18
-
19
- def existing_link(link_text, snip_name=link_text, part=nil)
20
- %{<a href="#{url_to(snip_name, part)}">#{link_text}</a>}
21
- end
22
-
23
- def edit_link(snip_name, link_text)
24
- %[<a href="/edit?name=#{snip_name.gsub(" ", "+")}">#{link_text}</a>]
25
- end
26
-
27
- def new_link(snip_name="New")
28
- %[<a href="/new?name=#{snip_name ? snip_name.gsub(" ", "+") : nil}" class="new">#{snip_name}</a>]
29
- end
30
17
  end
31
18
  end
@@ -1,71 +1,94 @@
1
- module SnipReference
2
- module SnipCall
3
- def snip
4
- elements[1].name
5
- end
6
- def attribute
7
- elements[1].attribute
8
- end
9
- def arguments
10
- if elements[2] && elements[2].elements
11
- r = elements[2].elements[1].to_arguments
12
- r.flatten! if r.respond_to?(:flatten!)
13
- r
14
- else
15
- []
1
+ require "parslet"
2
+
3
+ module Vanilla
4
+ class SnipReferenceParser
5
+ class Reference
6
+ def initialize(attributes)
7
+ @attributes = attributes
16
8
  end
17
- end
18
- end
19
- module SnipName
20
- def name
21
- text_value
22
- end
23
- def attribute
24
- nil
25
- end
26
- end
27
- module SnipNameWithAttribute
28
- def name
29
- elements[0].text_value
30
- end
31
- def attribute
32
- elements[2].text_value
33
- end
34
- end
35
- module QuotedWord
36
- def text_value
37
- elements[1].text_value
38
- end
39
- end
40
- module ArgumentList
41
- def to_arguments
42
- args = elements[0].to_arguments
43
- if args.is_a?(Array)
44
- args << elements[1].elements[1].to_arguments if elements[1].elements
45
- elsif args.is_a?(Hash)
46
- args.merge!(elements[1].elements[1].to_arguments) if elements[1].elements
9
+ def snip
10
+ @attributes[:snip]
11
+ end
12
+ def attribute
13
+ @attributes[:attribute]
14
+ end
15
+ def arguments
16
+ @attributes[:arguments] || []
47
17
  end
48
- args
49
18
  end
50
- end
51
- module HashArgument
52
- def to_arguments
53
- key = elements[0].text_value
54
- key = $1 if key =~ /\A:(.*)\Z/
55
- {key.to_sym => elements[4].text_value}
19
+
20
+ def parse(string)
21
+ Reference.new(SnipTransform.new.apply(SnipParser.new.parse(string)))
56
22
  end
57
- end
58
- module NormalArgument
59
- def to_arguments
60
- [text_value]
23
+
24
+ class SnipParser < Parslet::Parser
25
+ rule(:spaces) { match('\s').repeat(1) }
26
+ rule(:spaces?) { spaces.maybe }
27
+ rule(:comma) { match(',') }
28
+ rule(:dot) { str(".") }
29
+ rule(:squote) { str("'") }
30
+ rule(:dquote) { str('"') }
31
+ rule(:escaped_dquote) { str('"') }
32
+ rule(:left_brace) { str("{") }
33
+ rule(:right_brace) { str("}") }
34
+
35
+ rule(:word) { match("[a-zA-Z0-9_\\-]").repeat(1) }
36
+ rule(:quotables) { word | comma | spaces }
37
+ rule(:double_quoted_string) do
38
+ dquote >> (quotables | squote).repeat(1).as(:string) >> dquote
39
+ end
40
+ rule(:single_quoted_string) do
41
+ squote >> (quotables | dquote).repeat(1).as(:string) >> squote
42
+ end
43
+ rule(:string) do
44
+ single_quoted_string | double_quoted_string | str("nil").as(:nil) | word.as(:string)
45
+ end
46
+ rule(:symbol) { str(":") >> string }
47
+
48
+ rule(:comma_separator) { spaces? >> comma >> spaces? }
49
+ rule(:hash_separator) { spaces? >> str("=>") >> spaces? }
50
+ rule(:named_separator) { spaces? >> str(":") >> spaces? }
51
+
52
+ rule(:hash_arg) { (symbol | string).as(:key) >> hash_separator >> string.as(:value) }
53
+ rule(:named_arg) { string.as(:key) >> named_separator >> string.as(:value) }
54
+
55
+ rule(:string_arg_list) { (string.as(:string_arg) >> further_string_args.repeat).as(:string_arg_list) }
56
+ rule(:further_string_args) { comma_separator >> string.as(:string_arg) }
57
+
58
+ rule(:hash_arg_list) { (hash_arg.as(:hash_arg) >> further_hash_args.repeat).as(:key_value_arg_list) }
59
+ rule(:further_hash_args) { comma_separator >> hash_arg.as(:hash_arg) }
60
+
61
+ rule(:named_arg_list) { (named_arg.as(:named_arg) >> further_named_args.repeat).as(:key_value_arg_list) }
62
+ rule(:further_named_args) { comma_separator >> named_arg.as(:named_arg) }
63
+
64
+ rule(:arguments) { hash_arg_list | named_arg_list | string_arg_list }
65
+ rule(:snip_part) { string.as(:snip) >> (dot >> string.as(:attribute)).maybe }
66
+
67
+ rule(:snip_reference) do
68
+ left_brace >> spaces? >>
69
+ snip_part >> (spaces >> arguments.as(:arguments)).maybe >>
70
+ spaces? >> right_brace
71
+ end
72
+
73
+ root(:snip_reference)
61
74
  end
62
- end
63
- module EmptyArgument
64
- def to_arguments
65
- [nil]
75
+
76
+ class SnipTransform < Parslet::Transform
77
+ rule(:nil => simple(:x)) { nil }
78
+ rule(:string => simple(:x)) { x.to_s }
79
+ rule(:string_arg => simple(:x)) { x }
80
+ rule(:string_arg_list => simple(:x)) { [x] }
81
+ rule(:string_arg_list => sequence(:x)) { x }
82
+
83
+ class Arg
84
+ def initialize(k, v); @k, @v = k, v; end
85
+ def to_h; {@k.to_sym => @v}; end
86
+ end
87
+
88
+ rule(:hash_arg => subtree(:x)) { Arg.new(x[:key], x[:value]) }
89
+ rule(:named_arg => subtree(:x)) { Arg.new(x[:key], x[:value]) }
90
+ rule(:key_value_arg_list => simple(:x)) { x.to_h }
91
+ rule(:key_value_arg_list => sequence(:x)) { x.inject({}) { |h, kv| h.merge(kv.to_h) } }
66
92
  end
67
93
  end
68
- end
69
-
70
- require 'treetop'
71
- require 'vanilla/snip_reference'
94
+ end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/james/Code/lazyatom/vanilla-rb
3
3
  specs:
4
- vanilla (1.15)
4
+ vanilla (1.14.1)
5
5
  BlueCloth (>= 1.0.0)
6
6
  RedCloth (>= 4.1.1)
7
7
  haml
@@ -15,7 +15,7 @@ GEM
15
15
  specs:
16
16
  BlueCloth (1.0.1)
17
17
  RedCloth (4.2.7)
18
- haml (3.0.25)
18
+ haml (3.1.1)
19
19
  libxml-ruby (2.0.2)
20
20
  polyglot (0.3.1)
21
21
  rack (1.2.2)
data/pristine_app/README CHANGED
@@ -16,6 +16,8 @@ For an overview of vanilla, start your site and look at the tutorial:
16
16
  $ rackup # then open http://localhost:9292/tutorial
17
17
 
18
18
 
19
+ Editing snips
20
+ -------------
19
21
  You can edit any file in the soup directory using your favourite editor,
20
22
  and the changes will be reflected automatically. The snip files are
21
23
  slightly modified YAML files. Here's an example, which you might save
@@ -34,3 +36,12 @@ in a file called 'soup.snip':
34
36
 
35
37
  The 'content' of the snip is at the top of the file, followed by the
36
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).
@@ -14,15 +14,15 @@ class CurrentSnip < Dynasnip
14
14
  |
15
15
 
16
16
  def handle(attribute=nil)
17
- if attribute
18
- app.request.snip.__send__(attribute)
19
- else
20
- if app.request.snip
21
- app.render(app.request.snip, app.request.part)
17
+ if app.request.snip
18
+ if attribute ||= app.request.part
19
+ "{#{app.request.snip_name}.#{attribute}}"
22
20
  else
23
- app.response.status = 404
24
- %{Couldn't find snip "#{app.request.snip_name}"}
21
+ "{#{app.request.snip_name}}"
25
22
  end
23
+ else
24
+ app.response.status = 404
25
+ %{Couldn't find snip "#{app.request.snip_name}"}
26
26
  end
27
27
  end
28
28
  self
@@ -4,9 +4,9 @@ Here's the [introductory blog post][3].
4
4
 
5
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.
6
6
 
7
- Here's the tutorial (helpfully included from {link_to vanilla-rb-tutorial}).
7
+ Here's the tutorial (helpfully included from {link_to tutorial}).
8
8
 
9
- {vanilla-rb-tutorial}
9
+ {tutorial}
10
10
 
11
11
 
12
12
  [1]: http://github.com/lazyatom/vanilla
@@ -1,4 +1,4 @@
1
- The bliki upon which {link_to vanilla-rb} is based, writen by [Christian Langreiter][1]
1
+ The bliki upon which {link_to vanilla-rb} is based, written by [Christian Langreiter][1]
2
2
 
3
3
  [Official Web HQ][2]
4
4
 
@@ -26,4 +26,17 @@ describe Dynasnip do
26
26
  assert_equal "altered content", TestDyna.new(@app).test_attribute
27
27
  end
28
28
  end
29
+
30
+ context "when rendering usage" do
31
+ class ::ShowUsage < Dynasnip
32
+ usage "This is the usage"
33
+ def handle
34
+ usage
35
+ end
36
+ end
37
+
38
+ should "show the usage defined in the snip" do
39
+ assert_equal "This is the usage", ShowUsage.new(@app).handle
40
+ end
41
+ end
29
42
  end
@@ -0,0 +1,19 @@
1
+ require "test_helper"
2
+ $LOAD_PATH.unshift File.expand_path("../../../pristine_app/soups/dynasnips", __FILE__)
3
+ require "link_to_current_snip"
4
+
5
+ context "The link_to_current_snip dynasnip" do
6
+ setup do
7
+ @app.soup << LinkToCurrentSnip.snip_attributes
8
+ create_snip :name => "test", :content => "test {link_to_current_snip}"
9
+ end
10
+
11
+ should "render a link to the snip that was requested" do
12
+ assert_response_body %{test <a href="/test">test</a>}, "/test"
13
+ end
14
+
15
+ should "render a link to the snip that was requested even if it isn't the snip that included the dyna" do
16
+ create_snip :name => "othertest", :content => "othertest {test}"
17
+ assert_response_body %{othertest test <a href="/othertest">othertest</a>}, "/othertest"
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ require "test_helper"
2
+ $LOAD_PATH.unshift File.expand_path("../../../pristine_app/soups/dynasnips", __FILE__)
3
+ require "link_to"
4
+
5
+ context "The link_to dynasnip" do
6
+ setup do
7
+ create_snip :name => "start", :content => "hello"
8
+ end
9
+
10
+ should "render a link to a snip that exists" do
11
+ assert_equal %{<a href="/start">start</a>}, render_dynasnip(LinkTo, "start")
12
+ end
13
+
14
+ should "allow specification of the link text" do
15
+ assert_equal %{<a href="/start">the start snip</a>}, render_dynasnip(LinkTo, "start", "the start snip")
16
+ end
17
+
18
+ should "mark snips that are missing with a class" do
19
+ assert_equal %{<a class="missing" href="/missing">missing</a>}, render_dynasnip(LinkTo, "missing")
20
+ end
21
+
22
+ private
23
+
24
+ def render_dynasnip(klass, *args)
25
+ klass.new(@app).handle(*args)
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ require "test_helper"
2
+ $LOAD_PATH.unshift File.expand_path("../../../pristine_app/soups/dynasnips", __FILE__)
3
+ require "page_title"
4
+
5
+ context "The page_title dynasnip" do
6
+ setup do
7
+ @app.soup << PageTitle.snip_attributes
8
+ end
9
+
10
+ should "render as the requested snip name if that snip has no title" do
11
+ create_snip :name => "test", :content => "{page_title}"
12
+ assert_response_body %{test}, "/test"
13
+ end
14
+
15
+ should "render as the requested snip's page_title when that attribute is present" do
16
+ create_snip :name => "test", :content => "{page_title}", :page_title => "This is a test"
17
+ assert_response_body %{This is a test}, "/test"
18
+ end
19
+ end
@@ -1,6 +1,6 @@
1
1
  require "test_helper"
2
2
 
3
- context "The SnipReference parser" do
3
+ context "When including snips in other snips" do
4
4
  setup do
5
5
  create_snip :name => "test", :content => "snip content"
6
6
  end
@@ -1,55 +1,123 @@
1
1
  require "test_helper"
2
- Treetop.load File.join(File.dirname(__FILE__), *%w[.. lib vanilla snip_reference])
3
2
 
4
3
  context "The SnipReference parser" do
4
+
5
5
  setup do
6
- @parser = SnipReferenceParser.new
6
+ @parser = Vanilla::SnipReferenceParser.new
7
7
  end
8
8
 
9
9
  examples = {
10
- %|{snip}| => {:snip => 'snip', :attribute => nil, :arguments => []},
11
- %|{snip argument}| => {:snip => 'snip', :attribute => nil, :arguments => ["argument"]},
12
- %|{"snip with spaces"}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => []},
13
- %|{snip-with-dashes}| => {:snip => 'snip-with-dashes', :attribute => nil, :arguments => []},
14
- %|{snip_with_underscores}| => {:snip => 'snip_with_underscores', :attribute => nil, :arguments => []},
15
- %|{"snip with spaces" argument}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => ['argument']},
16
- %|{'snip with spaces' argument}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => ['argument']},
17
- %|{snip "argument with spaces"}| => {:snip => 'snip', :attribute => nil, :arguments => ['argument with spaces']},
18
- %|{snip 'argument with spaces'}| => {:snip => 'snip', :attribute => nil, :arguments => ['argument with spaces']},
19
- %|{snip arg1,arg2}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg1', 'arg2']},
20
- %|{snip arg1, arg2}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg1', 'arg2']},
21
- %|{snip "argument with spaces", arg2}| => {:snip => 'snip', :attribute => nil, :arguments => ['argument with spaces', 'arg2']},
22
- %|{"snip with spaces" arg1, arg2}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => ['arg1', 'arg2']},
23
- %|{snip arg1,,arg3}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg1', nil, 'arg3']},
24
- %|{snip arg1, ,arg3}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg1', nil, 'arg3']},
25
- %|{snip.snip_attribute}| => {:snip => 'snip', :attribute => 'snip_attribute', :arguments => []},
26
- %|{snip."spaced attribute"}| => {:snip => 'snip', :attribute => 'spaced attribute', :arguments => []},
27
- %|{"snip with spaces".attribute}| => {:snip => 'snip with spaces', :attribute => 'attribute', :arguments => []},
28
- %|{snip.snip_attribute arg}| => {:snip => 'snip', :attribute => 'snip_attribute', :arguments => ['arg']},
29
- %|{snip arg with spaces}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg with spaces']},
30
- %|{snip arg with spaces, another arg}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg with spaces', 'another arg']},
31
- %|{snip key1=>value1, key2 => value2}| => {:snip => 'snip', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
32
- %|{snip.attribute key1=>value1}| => {:snip => 'snip', :attribute => 'attribute', :arguments => {:key1 => 'value1'}},
33
- %|{snip key1 => value1, key2 => value2}| => {:snip => 'snip', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
34
- %|{snip :key1 => value1, :key2 => value2}| => {:snip => 'snip', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
35
- %|{snip key1 => "value with spaces"}| => {:snip => 'snip', :arguments => {:key1 => "value with spaces"}},
36
- # %|{snip "key with spaces" => value} | => {:snip => 'snip', :arguments => {:"key with spaces" => "value"}},
37
- %|{snip key1:value1,key2:value2}| => {:snip => 'snip', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
38
- %|{snip key1:value1, key2:value2}| => {:snip => 'snip', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
39
- %|{snip key1: value1, key2: value2}| => {:snip => 'snip', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
40
- %|{snip key1:"value with spaces"}| => {:snip => 'snip', :arguments => {:key1 => 'value with spaces'}}
10
+ :snip_names => {
11
+ %|{snip}| => {:snip => 'snip', :attribute => nil, :arguments => []},
12
+ %|{Snip}| => {:snip => 'Snip', :attribute => nil, :arguments => []},
13
+ %|{123snip}| => {:snip => '123snip', :attribute => nil, :arguments => []},
14
+ %|{Snip123}| => {:snip => 'Snip123', :attribute => nil, :arguments => []},
15
+ %|{snip-with-dashes}| => {:snip => 'snip-with-dashes', :attribute => nil, :arguments => []},
16
+ %|{snip_with_underscores}| => {:snip => 'snip_with_underscores', :attribute => nil, :arguments => []},
17
+ },
18
+
19
+ :snip_attributes => {
20
+ %|{snip.snip_attribute}| => {:snip => 'snip', :attribute => 'snip_attribute', :arguments => []},
21
+ %|{snip.snip_attribute arg}| => {:snip => 'snip', :attribute => 'snip_attribute', :arguments => ['arg']},
22
+ %|{snip."spaced attribute"}| => {:snip => 'snip', :attribute => 'spaced attribute', :arguments => []},
23
+ %|{snip.'spaced attribute'}| => {:snip => 'snip', :attribute => 'spaced attribute', :arguments => []}
24
+ },
25
+
26
+ :simple_arguments => {
27
+ %|{snip argument}| => {:snip => 'snip', :attribute => nil, :arguments => ["argument"]},
28
+ %|{snip1 argument}| => {:snip => 'snip1', :attribute => nil, :arguments => ["argument"]},
29
+ %|{snip arg-dashes}| => {:snip => 'snip', :attribute => nil, :arguments => ["arg-dashes"]},
30
+ %|{snip arg_underscores}| => {:snip => 'snip', :attribute => nil, :arguments => ["arg_underscores"]},
31
+ %|{snip arg1,arg2}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg1', 'arg2']},
32
+ %|{snip arg1, arg2}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg1', 'arg2']},
33
+ %|{snip arg1, arg2}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg1', 'arg2']},
34
+ %|{snip 1ARG, arg_2, arg-3}| => {:snip => 'snip', :attribute => nil, :arguments => ['1ARG', 'arg_2', 'arg-3']}
35
+ },
36
+
37
+ :snip_name_spaces => {
38
+ %|{"snip with spaces"}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => []},
39
+ %|{'snip with spaces'}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => []},
40
+ %|{"snip with spaces" argument}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => ['argument']},
41
+ %|{'snip with spaces' argument}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => ['argument']},
42
+ %|{"snip with spaces" a, b}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => ['a', 'b']},
43
+ %|{'snip with spaces' a, b}| => {:snip => 'snip with spaces', :attribute => nil, :arguments => ['a', 'b']},
44
+ %|{"snip with spaces".attribute}| => {:snip => 'snip with spaces', :attribute => 'attribute', :arguments => []},
45
+ %|{'snip with spaces'.attribute}| => {:snip => 'snip with spaces', :attribute => 'attribute', :arguments => []}
46
+ },
47
+
48
+ :arguments_with_spaces => {
49
+ # %|{snip arg spaces}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg spaces']},
50
+ # %|{snip arg spaces, and this}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg spaces', 'and this']},
51
+ %|{snip "arg spaces"}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg spaces']},
52
+ %|{snip 'arg spaces'}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg spaces']},
53
+ %|{snip "arg spaces", arg2}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg spaces', 'arg2']}
54
+ },
55
+
56
+ :nil_arguments => {
57
+ %|{snip arg1,nil,arg3}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg1', nil, 'arg3']},
58
+ %|{snip arg1, nil ,arg3}| => {:snip => 'snip', :attribute => nil, :arguments => ['arg1', nil, 'arg3']}
59
+ },
60
+
61
+ :classic_ruby_hash_arguments => {
62
+ %|{s key1=>value1, key2 => value2}| => {:snip => 's', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
63
+ %|{s key1 => value1, key2 => value2}| => {:snip => 's', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
64
+ %|{s :key1 => value1, :key2 => value2}| => {:snip => 's', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
65
+ %|{s key1 => "value with spaces"}| => {:snip => 's', :arguments => {:key1 => "value with spaces"}},
66
+ %|{s.attr key1=>value1}| => {:snip => 's', :attribute => 'attr', :arguments => {:key1 => 'value1'}},
67
+ # %|{s "key with spaces" => value}| => {:snip => 's', :arguments => {:"key with spaces" => "value"}}
68
+ },
69
+
70
+ :named_arguments => {
71
+ %|{s key1:value1,key2:value2}| => {:snip => 's', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
72
+ %|{s key1:value1, key2:value2}| => {:snip => 's', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
73
+ %|{s key1: value1, key2: value2}| => {:snip => 's', :arguments => {:key1 => 'value1', :key2 => 'value2'}},
74
+ %|{s key1:"value with spaces"}| => {:snip => 's', :arguments => {:key1 => 'value with spaces'}}
75
+ },
76
+
77
+ :quoting_arguments => {
78
+ # %|{s "arg \\" double"}| => {:snip => 's', :attribute => nil, :arguments => ['arg " double']},
79
+ # %|{s 'arg \\' single'}| => {:snip => 's', :attribute => nil, :arguments => ["arg ' single"]},
80
+ %|{s "arg ' single"}| => {:snip => 's', :attribute => nil, :arguments => ["arg ' single"]},
81
+ %|{s 'arg " double'}| => {:snip => 's', :attribute => nil, :arguments => ['arg " double']},
82
+ %|{s "arg, comma"}| => {:snip => 's', :attribute => nil, :arguments => ['arg, comma']},
83
+ %|{s 'arg, comma'}| => {:snip => 's', :attribute => nil, :arguments => ['arg, comma']},
84
+ # %|{s "arg { open"}| => {:snip => 's', :attribute => nil, :arguments => ['arg { open']},
85
+ # %|{s "arg } close"}| => {:snip => 's', :attribute => nil, :arguments => ['arg } close']}
86
+ }
41
87
  }
42
88
 
43
- examples.each do |example, expected|
44
- should "parse '#{example}' into #{expected.inspect}" do
45
- reference = @parser.parse(example)
46
- if reference
47
- assert_equal expected[:snip], reference.snip
48
- assert_equal expected[:attribute], reference.attribute
49
- assert_equal expected[:arguments], reference.arguments
50
- else
51
- flunk "failed to parse: #{example}"
89
+ examples.each do |type, set|
90
+ context type.to_s.gsub("_", " ") do
91
+ set.each do |example, expected|
92
+ should "parse '#{example}' into #{expected.inspect}" do
93
+ reference = @parser.parse(example)
94
+ if reference
95
+ assert_equal expected[:snip], reference.snip
96
+ assert_equal expected[:attribute], reference.attribute
97
+ assert_equal expected[:arguments], reference.arguments
98
+ assert_parsable_by_vanilla example, expected
99
+ else
100
+ flunk "failed to parse: #{example} - #{@parser.failure_reason}"
101
+ end
102
+ end
52
103
  end
53
104
  end
54
105
  end
106
+
107
+ private
108
+
109
+ def assert_parsable_by_vanilla(example, expected)
110
+ create_snip_from_expected expected
111
+ create_snip :name => "test", :content => "alpha #{example} beta"
112
+ assert_response_body "alpha ok beta", "/test"
113
+ end
114
+
115
+ def create_snip_from_expected(expected)
116
+ simple_dyna = %|class SimpleDyna;def handle(*args); 'ok'; end;self;end|
117
+ attributes = {:name => expected[:snip], :content => simple_dyna, :render_as => "ruby"}
118
+ if expected[:attribute]
119
+ attributes[expected[:attribute]] = simple_dyna
120
+ end
121
+ create_snip(attributes)
122
+ end
55
123
  end