curly-templates 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +20 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +3 -0
  5. data/.yardopts +3 -0
  6. data/CHANGELOG.md +28 -0
  7. data/Gemfile +4 -2
  8. data/README.md +76 -3
  9. data/Rakefile +3 -116
  10. data/circle.yml +1 -1
  11. data/curly-templates.gemspec +6 -83
  12. data/lib/curly.rb +1 -1
  13. data/lib/curly/compiler.rb +2 -12
  14. data/lib/curly/component_compiler.rb +6 -3
  15. data/lib/curly/presenter.rb +32 -20
  16. data/lib/curly/presenter_name_error.rb +16 -0
  17. data/lib/curly/rspec.rb +16 -0
  18. data/lib/curly/version.rb +3 -0
  19. metadata +14 -72
  20. data/perf/compile_benchmark.rb +0 -71
  21. data/perf/compile_profile.rb +0 -64
  22. data/perf/component_benchmark.rb +0 -41
  23. data/spec/attribute_scanner_spec.rb +0 -44
  24. data/spec/collection_blocks_spec.rb +0 -78
  25. data/spec/compiler/collections_spec.rb +0 -230
  26. data/spec/compiler/context_blocks_spec.rb +0 -106
  27. data/spec/compiler_spec.rb +0 -192
  28. data/spec/component_compiler_spec.rb +0 -107
  29. data/spec/component_scanner_spec.rb +0 -36
  30. data/spec/components_spec.rb +0 -43
  31. data/spec/conditional_blocks_spec.rb +0 -40
  32. data/spec/dummy/.gitignore +0 -1
  33. data/spec/dummy/app/controllers/application_controller.rb +0 -2
  34. data/spec/dummy/app/controllers/dashboards_controller.rb +0 -14
  35. data/spec/dummy/app/helpers/application_helper.rb +0 -5
  36. data/spec/dummy/app/presenters/dashboards/collection_presenter.rb +0 -7
  37. data/spec/dummy/app/presenters/dashboards/item_presenter.rb +0 -23
  38. data/spec/dummy/app/presenters/dashboards/new_presenter.rb +0 -29
  39. data/spec/dummy/app/presenters/dashboards/partials_presenter.rb +0 -5
  40. data/spec/dummy/app/presenters/dashboards/show_presenter.rb +0 -12
  41. data/spec/dummy/app/presenters/layouts/application_presenter.rb +0 -21
  42. data/spec/dummy/app/views/dashboards/_item.html.curly +0 -1
  43. data/spec/dummy/app/views/dashboards/collection.html.curly +0 -8
  44. data/spec/dummy/app/views/dashboards/new.html.curly +0 -7
  45. data/spec/dummy/app/views/dashboards/partials.html.curly +0 -3
  46. data/spec/dummy/app/views/dashboards/show.html.curly +0 -3
  47. data/spec/dummy/app/views/layouts/application.html.curly +0 -11
  48. data/spec/dummy/config.ru +0 -4
  49. data/spec/dummy/config/application.rb +0 -12
  50. data/spec/dummy/config/boot.rb +0 -5
  51. data/spec/dummy/config/environment.rb +0 -5
  52. data/spec/dummy/config/environments/test.rb +0 -36
  53. data/spec/dummy/config/routes.rb +0 -6
  54. data/spec/generators/controller_generator_spec.rb +0 -34
  55. data/spec/integration/application_layout_spec.rb +0 -22
  56. data/spec/integration/collection_blocks_spec.rb +0 -37
  57. data/spec/integration/context_blocks_spec.rb +0 -27
  58. data/spec/integration/partials_spec.rb +0 -24
  59. data/spec/matchers/have_structure.rb +0 -29
  60. data/spec/parser_spec.rb +0 -92
  61. data/spec/presenter_spec.rb +0 -247
  62. data/spec/scanner_spec.rb +0 -124
  63. data/spec/spec_helper.rb +0 -45
  64. data/spec/syntax_error_spec.rb +0 -12
  65. data/spec/template_handler_spec.rb +0 -209
@@ -1,192 +0,0 @@
1
- describe Curly::Compiler do
2
- include CompilationSupport
3
-
4
- describe ".compile" do
5
- it "raises ArgumentError if the presenter class is nil" do
6
- expect do
7
- Curly::Compiler.compile("foo", nil)
8
- end.to raise_exception(ArgumentError)
9
- end
10
-
11
- it "makes sure only public methods are called on the presenter object" do
12
- expect { render("{{bar}}") }.to raise_exception(Curly::InvalidComponent)
13
- end
14
-
15
- it "includes the invalid component when failing to compile" do
16
- begin
17
- render("{{bar}}")
18
- fail
19
- rescue Curly::InvalidComponent => e
20
- e.component.should == "bar"
21
- end
22
- end
23
-
24
- it "propagates yields to the caller" do
25
- define_presenter do
26
- def i_want
27
- "I want #{yield}!"
28
- end
29
- end
30
-
31
- render("{{i_want}}") { "$$$" }.should == "I want $$$!"
32
- end
33
-
34
- it "sends along arguments passed to yield" do
35
- define_presenter do
36
- def hello(&block)
37
- "Hello, #{block.call('world')}!"
38
- end
39
- end
40
-
41
- render("{{hello}}") {|v| v.upcase }.should == "Hello, WORLD!"
42
- end
43
-
44
- it "escapes non HTML safe strings returned from the presenter" do
45
- define_presenter do
46
- def dirty
47
- "<p>dirty</p>"
48
- end
49
- end
50
-
51
- render("{{dirty}}").should == "&lt;p&gt;dirty&lt;/p&gt;"
52
- end
53
-
54
- it "does not escape HTML safe strings returned from the presenter" do
55
- define_presenter do
56
- def dirty
57
- "<p>dirty</p>".html_safe
58
- end
59
- end
60
-
61
- render("{{dirty}}").should == "<p>dirty</p>"
62
- end
63
-
64
- it "does not escape HTML in the template itself" do
65
- render("<div>").should == "<div>"
66
- end
67
-
68
- it "treats all values returned from the presenter as strings" do
69
- define_presenter do
70
- def foo; 42; end
71
- end
72
-
73
- render("{{foo}}").should == "42"
74
- end
75
-
76
- it "removes comments from the output" do
77
- render("hello{{! I'm a comment, yo }}world").should == "helloworld"
78
- end
79
-
80
- it "removes text in false blocks" do
81
- define_presenter do
82
- def false?
83
- false
84
- end
85
- end
86
-
87
- render("{{#false?}}wut{{/false?}}").should == ""
88
- end
89
-
90
- it "keeps text in true blocks" do
91
- define_presenter do
92
- def true?
93
- true
94
- end
95
- end
96
-
97
- render("{{#true?}}yello{{/true?}}").should == "yello"
98
- end
99
-
100
- it "removes text in inverse true blocks" do
101
- define_presenter do
102
- def true?
103
- true
104
- end
105
- end
106
-
107
- render("{{^true?}}bar{{/true?}}").should == ""
108
- end
109
-
110
- it "keeps text in inverse false blocks" do
111
- define_presenter do
112
- def false?
113
- false
114
- end
115
- end
116
-
117
- render("{{^false?}}yeah!{{/false?}}").should == "yeah!"
118
- end
119
-
120
- it "passes an argument to blocks" do
121
- define_presenter do
122
- def hello?(value)
123
- value == "world"
124
- end
125
- end
126
-
127
- render("{{#hello.world?}}foo{{/hello.world?}}").should == "foo"
128
- render("{{#hello.mars?}}bar{{/hello.mars?}}").should == ""
129
- end
130
-
131
- it "passes attributes to blocks" do
132
- define_presenter do
133
- def square?(width:, height:)
134
- width.to_i == height.to_i
135
- end
136
- end
137
-
138
- render("{{#square? width=2 height=2}}yeah!{{/square?}}").should == "yeah!"
139
- end
140
-
141
- it "gives an error on incomplete blocks" do
142
- expect do
143
- render("{{#hello?}}")
144
- end.to raise_exception(Curly::IncompleteBlockError)
145
- end
146
-
147
- it "gives an error when closing unopened blocks" do
148
- expect do
149
- render("{{/goodbye?}}")
150
- end.to raise_exception(Curly::IncorrectEndingError)
151
- end
152
-
153
- it "gives an error on mismatching block ends" do
154
- expect do
155
- render("{{#x?}}{{#y?}}{{/x?}}{{/y?}}")
156
- end.to raise_exception(Curly::IncorrectEndingError)
157
- end
158
-
159
- it "does not execute arbitrary Ruby code" do
160
- render('#{foo}').should == '#{foo}'
161
- end
162
- end
163
-
164
- describe ".valid?" do
165
- it "returns true if only available methods are referenced" do
166
- define_presenter do
167
- def foo; end
168
- end
169
-
170
- validate("Hello, {{foo}}!").should == true
171
- end
172
-
173
- it "returns false if a missing method is referenced" do
174
- define_presenter
175
- validate("Hello, {{i_am_missing}}").should == false
176
- end
177
-
178
- it "returns false if an unavailable method is referenced" do
179
- define_presenter do
180
- def self.available_components
181
- []
182
- end
183
- end
184
-
185
- validate("Hello, {{inspect}}").should == false
186
- end
187
-
188
- def validate(template)
189
- Curly.valid?(template, ShowPresenter)
190
- end
191
- end
192
- end
@@ -1,107 +0,0 @@
1
- describe Curly::ComponentCompiler do
2
- describe ".compile" do
3
- let(:presenter_class) do
4
- Class.new do
5
- def title
6
- "Welcome!"
7
- end
8
-
9
- def i18n(key, fallback: nil)
10
- case key
11
- when "home.welcome" then "Welcome to our lovely place!"
12
- else fallback
13
- end
14
- end
15
-
16
- def summary(length = "long")
17
- case length
18
- when "long" then "This is a long summary"
19
- when "short" then "This is a short summary"
20
- end
21
- end
22
-
23
- def invalid(x, y)
24
- end
25
-
26
- def widget(size:, color: nil)
27
- s = "Widget (#{size})"
28
- s << " - #{color}" if color
29
- s
30
- end
31
-
32
- def form(&block)
33
- "some form"
34
- end
35
-
36
- def self.component_available?(name)
37
- true
38
- end
39
- end
40
- end
41
-
42
- it "compiles components with identifiers" do
43
- evaluate("i18n.home.welcome").should == "Welcome to our lovely place!"
44
- end
45
-
46
- it "compiles components with optional identifiers" do
47
- evaluate("summary").should == "This is a long summary"
48
- evaluate("summary.short").should == "This is a short summary"
49
- end
50
-
51
- it "compiles components with attributes" do
52
- evaluate("widget size=100px").should == "Widget (100px)"
53
- end
54
-
55
- it "compiles components with optional attributes" do
56
- evaluate("widget color=blue size=50px").should == "Widget (50px) - blue"
57
- end
58
-
59
- it "compiles context block components" do
60
- evaluate("form", type: :context).should == "some form"
61
- end
62
-
63
- it "allows both identifier and attributes" do
64
- evaluate("i18n.hello fallback=yolo").should == "yolo"
65
- end
66
-
67
- it "fails when an invalid attribute is used" do
68
- expect { evaluate("i18n.foo extreme=true") }.to raise_exception(Curly::Error)
69
- end
70
-
71
- it "fails when a component is missing a required identifier" do
72
- expect { evaluate("i18n") }.to raise_exception(Curly::Error)
73
- end
74
-
75
- it "fails when a component is missing a required attribute" do
76
- expect { evaluate("widget") }.to raise_exception(Curly::Error)
77
- end
78
-
79
- it "fails when an identifier is specified for a component that doesn't support one" do
80
- expect { evaluate("title.rugby") }.to raise_exception(Curly::Error)
81
- end
82
-
83
- it "fails when the method takes more than one argument" do
84
- expect { evaluate("invalid") }.to raise_exception(Curly::Error)
85
- end
86
-
87
- it "fails when a context block component is used with a method that doesn't take a block" do
88
- expect { evaluate("title", type: :context) }.to raise_exception(Curly::Error)
89
- end
90
- end
91
-
92
- def evaluate(text, type: nil, &block)
93
- name, identifier, attributes = Curly::ComponentScanner.scan(text)
94
- component = Curly::Parser::Component.new(name, identifier, attributes)
95
- code = Curly::ComponentCompiler.compile(presenter_class, component, type: type)
96
- presenter = presenter_class.new
97
- context = double("context", presenter: presenter)
98
-
99
- context.instance_eval(<<-RUBY)
100
- def self.render
101
- #{code}
102
- end
103
- RUBY
104
-
105
- context.render(&block)
106
- end
107
- end
@@ -1,36 +0,0 @@
1
- describe Curly::ComponentScanner do
2
- it "scans the component name, identifier, and attributes" do
3
- scan('hello.world weather="sunny"').should == [
4
- "hello",
5
- "world",
6
- { "weather" => "sunny" },
7
- []
8
- ]
9
- end
10
-
11
- it "allows context namespaces" do
12
- scan('island:beach:hello.world').should == [
13
- "hello",
14
- "world",
15
- {},
16
- ["island", "beach"]
17
- ]
18
- end
19
-
20
- it "allows a question mark after the identifier" do
21
- scan('hello.world?').should == ["hello?", "world", {}, []]
22
- end
23
-
24
- it 'allows spaces before and after component' do
25
- scan(' hello.world weather="sunny" ').should == [
26
- "hello",
27
- "world",
28
- { "weather" => "sunny" },
29
- []
30
- ]
31
- end
32
-
33
- def scan(component)
34
- described_class.scan(component)
35
- end
36
- end
@@ -1,43 +0,0 @@
1
- describe "Components" do
2
- include CompilationSupport
3
-
4
- example "with neither identifier nor attributes" do
5
- define_presenter do
6
- def title
7
- "A Clockwork Orange"
8
- end
9
- end
10
-
11
- render("{{title}}").should == "A Clockwork Orange"
12
- end
13
-
14
- example "with an identifier" do
15
- define_presenter do
16
- def reverse(str)
17
- str.reverse
18
- end
19
- end
20
-
21
- render("{{reverse.123}}").should == "321"
22
- end
23
-
24
- example "with attributes" do
25
- define_presenter do
26
- def double(number:)
27
- number.to_i * 2
28
- end
29
- end
30
-
31
- render("{{double number=3}}").should == "6"
32
- end
33
-
34
- example "with both identifier and attributes" do
35
- define_presenter do
36
- def a(href:, title:)
37
- content_tag :a, nil, href: href, title: title
38
- end
39
- end
40
-
41
- render(%({{a href="/welcome.html" title="Welcome!"}})).should == %(<a href="/welcome.html" title="Welcome!"></a>)
42
- end
43
- end
@@ -1,40 +0,0 @@
1
- describe "Conditional block components" do
2
- include CompilationSupport
3
-
4
- example "with neither identifier nor attributes" do
5
- define_presenter do
6
- def high?
7
- true
8
- end
9
-
10
- def low?
11
- false
12
- end
13
- end
14
-
15
- render("{{#high?}}yup{{/high?}}").should == "yup"
16
- render("{{#low?}}nah{{/low?}}").should == ""
17
- end
18
-
19
- example "with an identifier" do
20
- define_presenter do
21
- def even?(number)
22
- number.to_i % 2 == 0
23
- end
24
- end
25
-
26
- render("{{#even.42?}}even{{/even.42?}}").should == "even"
27
- render("{{#even.13?}}even{{/even.13?}}").should == ""
28
- end
29
-
30
- example "with attributes" do
31
- define_presenter do
32
- def square?(width:, height:)
33
- width.to_i == height.to_i
34
- end
35
- end
36
-
37
- render("{{#square? width=2 height=2}}square{{/square?}}").should == "square"
38
- render("{{#square? width=3 height=2}}square{{/square?}}").should == ""
39
- end
40
- end
@@ -1 +0,0 @@
1
- log
@@ -1,2 +0,0 @@
1
- class ApplicationController < ActionController::Base
2
- end
@@ -1,14 +0,0 @@
1
- class DashboardsController < ApplicationController
2
- def show
3
- @message = "Hello, World!"
4
- end
5
-
6
- def collection
7
- @name = "numbers"
8
- @items = ["uno", "dos", "tres!"]
9
- end
10
-
11
- def new
12
- @name = "test"
13
- end
14
- end