curly-templates 2.0.1 → 2.1.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +2 -0
- data/README.md +85 -5
- data/curly-templates.gemspec +37 -8
- data/lib/curly.rb +1 -1
- data/lib/curly/{attribute_parser.rb → attribute_scanner.rb} +6 -4
- data/lib/curly/compiler.rb +81 -72
- data/lib/curly/component_compiler.rb +37 -31
- data/lib/curly/component_scanner.rb +19 -0
- data/lib/curly/incomplete_block_error.rb +0 -7
- data/lib/curly/incorrect_ending_error.rb +0 -21
- data/lib/curly/parser.rb +171 -0
- data/lib/curly/presenter.rb +1 -1
- data/lib/curly/scanner.rb +23 -9
- data/spec/attribute_scanner_spec.rb +46 -0
- data/spec/collection_blocks_spec.rb +88 -0
- data/spec/compiler/context_blocks_spec.rb +42 -0
- data/spec/component_compiler_spec.rb +26 -77
- data/spec/component_scanner_spec.rb +19 -0
- data/spec/{integration/components_spec.rb → components_spec.rb} +0 -0
- data/spec/{integration/conditional_blocks_spec.rb → conditional_blocks_spec.rb} +0 -0
- data/spec/dummy/.gitignore +1 -0
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- data/spec/dummy/app/controllers/dashboards_controller.rb +13 -0
- data/spec/dummy/app/helpers/application_helper.rb +5 -0
- data/spec/dummy/app/presenters/dashboards/collection_presenter.rb +7 -0
- data/spec/dummy/app/presenters/dashboards/item_presenter.rb +7 -0
- data/spec/dummy/app/presenters/dashboards/new_presenter.rb +19 -0
- data/spec/dummy/app/presenters/dashboards/partials_presenter.rb +5 -0
- data/spec/dummy/app/presenters/dashboards/show_presenter.rb +12 -0
- data/spec/dummy/app/presenters/layouts/application_presenter.rb +9 -0
- data/spec/dummy/app/views/dashboards/_item.html.curly +1 -0
- data/spec/dummy/app/views/dashboards/collection.html.curly +5 -0
- data/spec/dummy/app/views/dashboards/new.html.curly +3 -0
- data/spec/dummy/app/views/dashboards/partials.html.curly +3 -0
- data/spec/dummy/app/views/dashboards/show.html.curly +3 -0
- data/spec/dummy/app/views/layouts/application.html.curly +8 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +12 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/routes.rb +6 -0
- data/spec/integration/application_layout_spec.rb +21 -0
- data/spec/integration/collection_blocks_spec.rb +17 -78
- data/spec/integration/context_blocks_spec.rb +21 -0
- data/spec/integration/partials_spec.rb +23 -0
- data/spec/parser_spec.rb +95 -0
- data/spec/scanner_spec.rb +24 -14
- data/spec/spec_helper.rb +4 -3
- metadata +49 -14
- data/lib/curly/component_parser.rb +0 -13
- data/spec/attribute_parser_spec.rb +0 -46
- data/spec/incorrect_ending_error_spec.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cfdffc4b7505394d372817977a7ac58c3eae42d
|
4
|
+
data.tar.gz: 55c4eb68a070f354e165c26895fa8168b9d2e28b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 755ce7ead9b1a2330e7416fb770c343bca17b877fcf582d5d38634ff2a83f7c87f6acfef8ad7bfada134d29a4eb49c4411d058d502c0ef2530325670ff9982b0
|
7
|
+
data.tar.gz: d947e0a11699021badcd38e870a9bb2b59ae0364011e61b87623db3f747c606f1e898052bc51eec6a5fe1129e3b6196db370abf26330dd689ac06516f456b343
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -28,6 +28,7 @@ or [Handlebars](http://handlebarsjs.com/), Curly is different in some key ways:
|
|
28
28
|
1. [Attributes](#attributes)
|
29
29
|
1. [Conditional blocks](#conditional-blocks)
|
30
30
|
1. [Collection blocks](#collection-blocks)
|
31
|
+
1. [Context blocks](#context-blocks)
|
31
32
|
1. [Setting up state](#setting-up-state)
|
32
33
|
2. [Escaping Curly syntax](#escaping-curly-syntax)
|
33
34
|
2. [Comments](#comments)
|
@@ -263,6 +264,84 @@ Collection blocks are an alternative to splitting out a separate template and re
|
|
263
264
|
that from the presenter – which solution is best depends on your use case.
|
264
265
|
|
265
266
|
|
267
|
+
### Context blocks
|
268
|
+
|
269
|
+
While collection blocks allow you to define the template that should be used to render
|
270
|
+
items in a collection right within the parent template, **context blocks** allow you
|
271
|
+
to define the template for an arbitrary context. This is very powerful, and can be used
|
272
|
+
to define widget-style components and helpers, and provide an easy way to work with
|
273
|
+
structured data. Let's say you have a comment form on your page, and you'd rather keep
|
274
|
+
the template inline. A simple template could look like:
|
275
|
+
|
276
|
+
```html
|
277
|
+
<!-- post.html.curly -->
|
278
|
+
<h1>{{title}}</h1>
|
279
|
+
{{body}}
|
280
|
+
|
281
|
+
{{@comment_form}}
|
282
|
+
<b>Name: </b> {{name_field}}<br>
|
283
|
+
<b>E-mail: </b> {{email_field}}<br>
|
284
|
+
{{comment_field}}
|
285
|
+
|
286
|
+
{{submit_button}}
|
287
|
+
{{/comment_form}}
|
288
|
+
```
|
289
|
+
|
290
|
+
Note that an `@` character is used to denote a context block. Like with
|
291
|
+
[collection blocks](#collection-blocks), a separate presenter class is used within the
|
292
|
+
block, and a simple convention is used to find it. The name of the context component
|
293
|
+
(in this case, `comment_form`) will be camel cased, and the current presenter's namespace
|
294
|
+
will be searched:
|
295
|
+
|
296
|
+
```ruby
|
297
|
+
class PostPresenter < Curly::Presenter
|
298
|
+
presents :post
|
299
|
+
def title; @post.title; end
|
300
|
+
def body; markdown(@post.body); end
|
301
|
+
|
302
|
+
# A context block method *must* take a block argument. The return value
|
303
|
+
# of the method will be used when rendering. Calling the block argument will
|
304
|
+
# render the nested template. If you pass a value when calling the block
|
305
|
+
# argument it will be passed to the presenter.
|
306
|
+
def comment_form(&block)
|
307
|
+
form_for(Comment.new, &block)
|
308
|
+
end
|
309
|
+
|
310
|
+
# The presenter name is automatically deduced.
|
311
|
+
class CommentFormPresenter < Curly::Presenter
|
312
|
+
# The value passed to the block argument will be passed in a parameter named
|
313
|
+
# after the component.
|
314
|
+
presents :comment_form
|
315
|
+
|
316
|
+
# Any parameters passed to the parent presenter will be forwarded to this
|
317
|
+
# presenter as well.
|
318
|
+
presents :post
|
319
|
+
|
320
|
+
def name_field
|
321
|
+
@comment_form.text_field :name
|
322
|
+
end
|
323
|
+
|
324
|
+
# ...
|
325
|
+
end
|
326
|
+
end
|
327
|
+
```
|
328
|
+
|
329
|
+
Context blocks were designed to work well with Rails' helper methods such as `form_for`
|
330
|
+
and `content_tag`, but you can also work directly with the block. For instance, if you
|
331
|
+
want to directly control the value that is passed to the nested presenter, you can call
|
332
|
+
the `call` method on the block yourself:
|
333
|
+
|
334
|
+
```ruby
|
335
|
+
def author(&block)
|
336
|
+
content_tag :div, class: "author" do
|
337
|
+
# The return value of `call` will be the result of rendering the nested template
|
338
|
+
# with the argument. You can post-process the string if you want.
|
339
|
+
block.call(@post.author)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
```
|
343
|
+
|
344
|
+
|
266
345
|
### Setting up state
|
267
346
|
|
268
347
|
Although most code in Curly presenters should be free of side effects, sometimes side
|
@@ -525,7 +604,7 @@ end
|
|
525
604
|
Static caching will only be enabled for presenters that define a non-nil `#cache_key`
|
526
605
|
method (see [Dynamic Caching.](#dynamic-caching))
|
527
606
|
|
528
|
-
In order to make a deploy expire the cache for a specific view, set the version of the
|
607
|
+
In order to make a deploy expire the cache for a specific view, set the `version` of the
|
529
608
|
view to something new, usually by incrementing by one:
|
530
609
|
|
531
610
|
```ruby
|
@@ -559,7 +638,6 @@ end
|
|
559
638
|
|
560
639
|
class Posts::CommentPresenter < Curly::Presenter
|
561
640
|
version 4
|
562
|
-
depends_on 'posts/comment'
|
563
641
|
|
564
642
|
def cache_key
|
565
643
|
# Some objects
|
@@ -567,11 +645,13 @@ class Posts::CommentPresenter < Curly::Presenter
|
|
567
645
|
end
|
568
646
|
```
|
569
647
|
|
570
|
-
Now, if the version of `Posts::CommentPresenter` is bumped, the cache keys for both
|
648
|
+
Now, if the `version` of `Posts::CommentPresenter` is bumped, the cache keys for both
|
571
649
|
presenters would change. You can register any number of view paths with `depends_on`.
|
572
650
|
|
573
|
-
|
574
|
-
|
651
|
+
Curly integrates well with the
|
652
|
+
[caching mechanism](http://guides.rubyonrails.org/caching_with_rails.html) in Rails 4 (or
|
653
|
+
[Cache Digests](https://github.com/rails/cache_digests) in Rails 3), so the dependencies
|
654
|
+
defined with `depends_on` will be tracked by Rails. This will allow you to deploy changes
|
575
655
|
to your templates and have the relevant caches automatically expire.
|
576
656
|
|
577
657
|
|
data/curly-templates.gemspec
CHANGED
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
|
|
4
4
|
s.rubygems_version = '1.3.5'
|
5
5
|
|
6
6
|
s.name = 'curly-templates'
|
7
|
-
s.version = '2.0.
|
8
|
-
s.date = '2014-
|
7
|
+
s.version = '2.1.0.beta1'
|
8
|
+
s.date = '2014-11-03'
|
9
9
|
|
10
10
|
s.summary = "Free your views!"
|
11
11
|
s.description = "A view layer for your Rails apps that separates structure and logic."
|
@@ -36,15 +36,16 @@ Gem::Specification.new do |s|
|
|
36
36
|
curly-templates.gemspec
|
37
37
|
lib/curly-templates.rb
|
38
38
|
lib/curly.rb
|
39
|
-
lib/curly/
|
39
|
+
lib/curly/attribute_scanner.rb
|
40
40
|
lib/curly/compiler.rb
|
41
41
|
lib/curly/component_compiler.rb
|
42
|
-
lib/curly/
|
42
|
+
lib/curly/component_scanner.rb
|
43
43
|
lib/curly/dependency_tracker.rb
|
44
44
|
lib/curly/error.rb
|
45
45
|
lib/curly/incomplete_block_error.rb
|
46
46
|
lib/curly/incorrect_ending_error.rb
|
47
47
|
lib/curly/invalid_component.rb
|
48
|
+
lib/curly/parser.rb
|
48
49
|
lib/curly/presenter.rb
|
49
50
|
lib/curly/presenter_not_found.rb
|
50
51
|
lib/curly/railtie.rb
|
@@ -55,15 +56,43 @@ Gem::Specification.new do |s|
|
|
55
56
|
lib/generators/curly/controller/templates/presenter.rb.erb
|
56
57
|
lib/generators/curly/controller/templates/view.html.curly.erb
|
57
58
|
lib/rails/projections.json
|
58
|
-
spec/
|
59
|
+
spec/attribute_scanner_spec.rb
|
60
|
+
spec/collection_blocks_spec.rb
|
59
61
|
spec/compiler/collections_spec.rb
|
62
|
+
spec/compiler/context_blocks_spec.rb
|
60
63
|
spec/compiler_spec.rb
|
61
64
|
spec/component_compiler_spec.rb
|
65
|
+
spec/component_scanner_spec.rb
|
66
|
+
spec/components_spec.rb
|
67
|
+
spec/conditional_blocks_spec.rb
|
68
|
+
spec/dummy/.gitignore
|
69
|
+
spec/dummy/app/controllers/application_controller.rb
|
70
|
+
spec/dummy/app/controllers/dashboards_controller.rb
|
71
|
+
spec/dummy/app/helpers/application_helper.rb
|
72
|
+
spec/dummy/app/presenters/dashboards/collection_presenter.rb
|
73
|
+
spec/dummy/app/presenters/dashboards/item_presenter.rb
|
74
|
+
spec/dummy/app/presenters/dashboards/new_presenter.rb
|
75
|
+
spec/dummy/app/presenters/dashboards/partials_presenter.rb
|
76
|
+
spec/dummy/app/presenters/dashboards/show_presenter.rb
|
77
|
+
spec/dummy/app/presenters/layouts/application_presenter.rb
|
78
|
+
spec/dummy/app/views/dashboards/_item.html.curly
|
79
|
+
spec/dummy/app/views/dashboards/collection.html.curly
|
80
|
+
spec/dummy/app/views/dashboards/new.html.curly
|
81
|
+
spec/dummy/app/views/dashboards/partials.html.curly
|
82
|
+
spec/dummy/app/views/dashboards/show.html.curly
|
83
|
+
spec/dummy/app/views/layouts/application.html.curly
|
84
|
+
spec/dummy/config.ru
|
85
|
+
spec/dummy/config/application.rb
|
86
|
+
spec/dummy/config/boot.rb
|
87
|
+
spec/dummy/config/environment.rb
|
88
|
+
spec/dummy/config/environments/test.rb
|
89
|
+
spec/dummy/config/routes.rb
|
62
90
|
spec/generators/controller_generator_spec.rb
|
63
|
-
spec/
|
91
|
+
spec/integration/application_layout_spec.rb
|
64
92
|
spec/integration/collection_blocks_spec.rb
|
65
|
-
spec/integration/
|
66
|
-
spec/integration/
|
93
|
+
spec/integration/context_blocks_spec.rb
|
94
|
+
spec/integration/partials_spec.rb
|
95
|
+
spec/parser_spec.rb
|
67
96
|
spec/presenter_spec.rb
|
68
97
|
spec/scanner_spec.rb
|
69
98
|
spec/spec_helper.rb
|
data/lib/curly.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
|
+
require 'curly/error'
|
2
|
+
|
1
3
|
module Curly
|
2
4
|
AttributeError = Class.new(Curly::Error)
|
3
5
|
|
4
|
-
class
|
5
|
-
def self.
|
6
|
+
class AttributeScanner
|
7
|
+
def self.scan(string)
|
6
8
|
return {} if string.nil?
|
7
|
-
new(string).
|
9
|
+
new(string).scan
|
8
10
|
end
|
9
11
|
|
10
12
|
def initialize(string)
|
11
13
|
@scanner = StringScanner.new(string)
|
12
14
|
end
|
13
15
|
|
14
|
-
def
|
16
|
+
def scan
|
15
17
|
attributes = scan_attributes
|
16
18
|
Hash[attributes]
|
17
19
|
end
|
data/lib/curly/compiler.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
require 'curly/scanner'
|
2
|
+
require 'curly/parser'
|
2
3
|
require 'curly/component_compiler'
|
3
|
-
require 'curly/component_parser'
|
4
4
|
require 'curly/error'
|
5
5
|
require 'curly/invalid_component'
|
6
|
-
require 'curly/incorrect_ending_error'
|
7
|
-
require 'curly/incomplete_block_error'
|
8
6
|
|
9
7
|
module Curly
|
10
8
|
|
@@ -26,7 +24,16 @@ module Curly
|
|
26
24
|
# Raises IncompleteBlockError if a block is not completed.
|
27
25
|
# Returns a String containing the Ruby code.
|
28
26
|
def self.compile(template, presenter_class)
|
29
|
-
|
27
|
+
if presenter_class.nil?
|
28
|
+
raise ArgumentError, "presenter class cannot be nil"
|
29
|
+
end
|
30
|
+
|
31
|
+
tokens = Scanner.scan(template)
|
32
|
+
nodes = Parser.parse(tokens)
|
33
|
+
|
34
|
+
compiler = new(presenter_class)
|
35
|
+
compiler.compile(nodes)
|
36
|
+
compiler.code
|
30
37
|
end
|
31
38
|
|
32
39
|
# Whether the Curly template is valid. This includes whether all
|
@@ -44,34 +51,22 @@ module Curly
|
|
44
51
|
false
|
45
52
|
end
|
46
53
|
|
47
|
-
|
48
|
-
|
49
|
-
def initialize(template, presenter_class)
|
50
|
-
@template = template
|
54
|
+
def initialize(presenter_class)
|
51
55
|
@presenter_classes = [presenter_class]
|
56
|
+
@parts = []
|
52
57
|
end
|
53
58
|
|
54
|
-
def compile
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
tokens = Scanner.scan(template)
|
60
|
-
|
61
|
-
@blocks = []
|
62
|
-
|
63
|
-
parts = tokens.map do |type, value|
|
64
|
-
send("compile_#{type}", value)
|
65
|
-
end
|
66
|
-
|
67
|
-
if @blocks.any?
|
68
|
-
raise IncompleteBlockError.new(@blocks.pop)
|
59
|
+
def compile(nodes)
|
60
|
+
nodes.each do |node|
|
61
|
+
send("compile_#{node.type}", node)
|
69
62
|
end
|
63
|
+
end
|
70
64
|
|
65
|
+
def code
|
71
66
|
<<-RUBY
|
72
67
|
buffer = ActiveSupport::SafeBuffer.new
|
73
68
|
presenters = []
|
74
|
-
#{parts.join("\n")}
|
69
|
+
#{@parts.join("\n")}
|
75
70
|
buffer
|
76
71
|
RUBY
|
77
72
|
end
|
@@ -82,100 +77,114 @@ module Curly
|
|
82
77
|
@presenter_classes.last
|
83
78
|
end
|
84
79
|
|
85
|
-
def
|
86
|
-
compile_conditional_block
|
80
|
+
def compile_conditional(block)
|
81
|
+
compile_conditional_block("if", block)
|
87
82
|
end
|
88
83
|
|
89
|
-
def
|
90
|
-
compile_conditional_block
|
84
|
+
def compile_inverse_conditional(block)
|
85
|
+
compile_conditional_block("unless", block)
|
91
86
|
end
|
92
87
|
|
93
|
-
def
|
94
|
-
|
95
|
-
method_call = ComponentCompiler.
|
88
|
+
def compile_collection(block)
|
89
|
+
component = block.component
|
90
|
+
method_call = ComponentCompiler.compile(presenter_class, component)
|
96
91
|
|
97
|
-
|
98
|
-
counter = "#{
|
92
|
+
name = component.name.singularize
|
93
|
+
counter = "#{name}_counter"
|
99
94
|
|
100
95
|
begin
|
101
|
-
item_presenter_class = presenter_class.presenter_for_name(
|
96
|
+
item_presenter_class = presenter_class.presenter_for_name(name)
|
102
97
|
rescue NameError
|
103
98
|
raise Curly::Error,
|
104
|
-
"cannot enumerate `#{
|
99
|
+
"cannot enumerate `#{name}`, could not find matching presenter class"
|
105
100
|
end
|
106
101
|
|
107
|
-
|
108
|
-
@presenter_classes.push(item_presenter_class)
|
109
|
-
|
110
|
-
<<-RUBY
|
102
|
+
output <<-RUBY
|
111
103
|
presenters << presenter
|
112
104
|
items = Array(#{method_call})
|
113
105
|
items.each_with_index do |item, index|
|
114
|
-
item_options = options.merge(:#{
|
106
|
+
item_options = options.merge(:#{name} => item, :#{counter} => index + 1)
|
115
107
|
presenter = #{item_presenter_class}.new(self, item_options)
|
116
108
|
RUBY
|
109
|
+
|
110
|
+
@presenter_classes.push(item_presenter_class)
|
111
|
+
compile(block.nodes)
|
112
|
+
@presenter_classes.pop
|
113
|
+
|
114
|
+
output <<-RUBY
|
115
|
+
end
|
116
|
+
presenter = presenters.pop
|
117
|
+
RUBY
|
117
118
|
end
|
118
119
|
|
119
|
-
def compile_conditional_block(keyword,
|
120
|
-
|
121
|
-
method_call = ComponentCompiler.
|
120
|
+
def compile_conditional_block(keyword, block)
|
121
|
+
component = block.component
|
122
|
+
method_call = ComponentCompiler.compile(presenter_class, component)
|
122
123
|
|
123
|
-
|
124
|
+
unless component.name.end_with?("?")
|
125
|
+
raise Curly::Error, "conditional components must end with `?`"
|
126
|
+
end
|
124
127
|
|
125
|
-
<<-RUBY
|
128
|
+
output <<-RUBY
|
126
129
|
#{keyword} #{method_call}
|
127
130
|
RUBY
|
128
|
-
end
|
129
131
|
|
130
|
-
|
131
|
-
validate_block_end(component)
|
132
|
+
compile(block.nodes)
|
132
133
|
|
133
|
-
<<-RUBY
|
134
|
+
output <<-RUBY
|
134
135
|
end
|
135
136
|
RUBY
|
136
137
|
end
|
137
138
|
|
138
|
-
def
|
139
|
+
def compile_context(block)
|
140
|
+
component = block.component
|
141
|
+
method_call = ComponentCompiler.compile(presenter_class, component, type: block.type)
|
142
|
+
|
143
|
+
name = component.name
|
144
|
+
|
145
|
+
begin
|
146
|
+
item_presenter_class = presenter_class.presenter_for_name(name)
|
147
|
+
rescue NameError
|
148
|
+
raise Curly::Error,
|
149
|
+
"cannot use context `#{name}`, could not find matching presenter class"
|
150
|
+
end
|
151
|
+
|
152
|
+
output <<-RUBY
|
153
|
+
presenters << presenter
|
154
|
+
old_buffer, buffer = buffer, ActiveSupport::SafeBuffer.new
|
155
|
+
old_buffer << #{method_call} do |item|
|
156
|
+
item_options = options.merge(:#{name} => item)
|
157
|
+
presenter = #{item_presenter_class}.new(self, item_options.with_indifferent_access)
|
158
|
+
RUBY
|
159
|
+
|
160
|
+
@presenter_classes.push(item_presenter_class)
|
161
|
+
compile(block.nodes)
|
139
162
|
@presenter_classes.pop
|
140
|
-
validate_block_end(component)
|
141
163
|
|
142
|
-
<<-RUBY
|
164
|
+
output <<-RUBY
|
143
165
|
end
|
166
|
+
buffer = old_buffer
|
144
167
|
presenter = presenters.pop
|
145
168
|
RUBY
|
146
169
|
end
|
147
170
|
|
148
171
|
def compile_component(component)
|
149
|
-
|
150
|
-
method_call = ComponentCompiler.compile_component(presenter_class, name, identifier, attributes)
|
172
|
+
method_call = ComponentCompiler.compile(presenter_class, component)
|
151
173
|
code = "#{method_call} {|*args| yield(*args) }"
|
152
174
|
|
153
|
-
"buffer.concat(#{code.strip}.to_s)"
|
175
|
+
output "buffer.concat(#{code.strip}.to_s)"
|
154
176
|
end
|
155
177
|
|
156
178
|
def compile_text(text)
|
157
|
-
"buffer.safe_concat(#{text.inspect})"
|
179
|
+
output "buffer.safe_concat(#{text.value.inspect})"
|
158
180
|
end
|
159
181
|
|
160
182
|
def compile_comment(comment)
|
161
|
-
|
162
|
-
end
|
163
|
-
|
164
|
-
def validate_block_end(component)
|
165
|
-
name, identifier, attributes = ComponentParser.parse(component)
|
166
|
-
last_block = @blocks.pop
|
167
|
-
|
168
|
-
if last_block.nil?
|
169
|
-
raise Curly::Error, "block ending not expected"
|
170
|
-
end
|
171
|
-
|
172
|
-
unless last_block == [name, identifier]
|
173
|
-
raise Curly::IncorrectEndingError.new([name, identifier], last_block)
|
174
|
-
end
|
183
|
+
# Do nothing.
|
175
184
|
end
|
176
185
|
|
177
|
-
def
|
178
|
-
@
|
186
|
+
def output(code)
|
187
|
+
@parts << code
|
179
188
|
end
|
180
189
|
end
|
181
190
|
end
|