slim 1.1.1 → 1.2.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.
@@ -4,6 +4,7 @@ rvm:
4
4
  - ruby-head
5
5
  - jruby
6
6
  - rbx-18mode
7
+ - rbx-19mode
7
8
  env:
8
9
  - "TASK=test"
9
10
  - "TASK=test TEMPLE=master"
data/CHANGES CHANGED
@@ -1,3 +1,15 @@
1
+ 1.2.0
2
+
3
+ * Add option :shortcut which configures attribute shortcuts
4
+ Default setting:
5
+ Slim::Parser.default_options[:shortcut] = {'#' => 'id', '.' => 'class', '*' => '*'}
6
+ Define custom shortcut attribute (e.g. a@ajax-link renders <a role="ajax-link"></a>)
7
+ Slim::Parser.default_options[:shortcut] = {'@' => 'role'}
8
+ Define custom shortcut attribute with tag (e.g. @ajax-link renders <a role="ajax-link"></a>)
9
+ Slim::Parser.default_options[:shortcut] = {'@' => 'a role'}
10
+ * Add syntax for splat attributes (#109)
11
+ * Support for dynamic tags, e.g. *{:tag => 'img', :src => 'image.jpg'}
12
+
1
13
  1.1.1
2
14
 
3
15
  * Evaluating a html attribute now happens only once (#219)
data/README.md CHANGED
@@ -41,11 +41,16 @@ If you want to use the Slim template directly, you can use the Tilt interface:
41
41
 
42
42
  ## Syntax Highlighters
43
43
 
44
- Syntax highlight support for __Emacs__ is included in the `extra` folder. There are also [Vim](https://github.com/bbommarito/vim-slim) and [Textmate](https://github.com/fredwu/ruby-slim-tmbundle) plugins.
44
+ There are plugins for Vim, Emacs, Textmate and Espresso text editor:
45
+
46
+ * [Vim](https://github.com/bbommarito/vim-slim)
47
+ * [Textmate](https://github.com/fredwu/ruby-slim-tmbundle)
48
+ * [Emacs](https://github.com/minad/emacs-slim)
49
+ * [Espresso text editor](https://github.com/CiiDub/Slim-Sugar)
45
50
 
46
51
  ## Template Converters
47
52
 
48
- For Haml, there is a [Haml2Slim converter](https://github.com/fredwu/haml2slim). Please check out the [issue tracker](https://github.com/stonean/slim/issues) to see the status of the varies converters.
53
+ For Haml, there is a [Haml2Slim converter](https://github.com/fredwu/haml2slim). For HTML, there is a [HTML2Slim converter](https://github.com/joaomilho/html2slim).
49
54
 
50
55
  ## The syntax
51
56
 
@@ -124,7 +129,7 @@ Here's a quick example to demonstrate what a Slim template looks like:
124
129
 
125
130
  #### `/!`
126
131
 
127
- > Use the forward slash immediately followed by an exclamation mark for html comments (`<!-- -->`).
132
+ > Use the forward slash immediately followed by an exclamation mark for html comments (` <!-- --> `).
128
133
 
129
134
 
130
135
  ### Things to know
@@ -388,8 +393,19 @@ This project is released under the MIT license.
388
393
 
389
394
  ## Slim related projects
390
395
 
391
- * [Vim files](https://github.com/bbommarito/vim-slim)
396
+ * [Temple](https://github.com/judofyr/slim)
397
+
398
+ * [Vim syntax highlighting](https://github.com/bbommarito/vim-slim)
399
+ * [Emacs syntax highlighting](https://github.com/minad/emacs-slim)
392
400
  * [Textmate bundle](https://github.com/fredwu/ruby-slim-tmbundle)
401
+ * [Slim support for the Espresso text editor from MacRabbits](https://github.com/CiiDub/Slim-Sugar)
402
+
393
403
  * [Haml2Slim converter](https://github.com/fredwu/haml2slim)
404
+ * [Html2Slim converter](https://github.com/joaomilho/html2slim)
405
+
394
406
  * [Rails 3 Generators](https://github.com/leogalmeida/slim-rails)
407
+
408
+ * [Skim (Slim for Javascript)](https://github.com/jfirebaugh/skim)
395
409
  * [Slim for Clojure](https://github.com/chaslemley/slim.clj)
410
+ * [Hamlet.rb (Similar template language)](https://github.com/gregwebs/hamlet.rb)
411
+ * [Coffee script plugin for Slim](https://github.com/yury/coffee-views)
@@ -1,7 +1,16 @@
1
1
  module Slim
2
- # Compiles Slim expressions into Temple::HTML expressions.
3
2
  # @api private
4
3
  class Compiler < Filter
4
+ def call(exp)
5
+ @attr_delimiter, @splat_used = unique_name, false
6
+ exp = compile(exp)
7
+ if @splat_used
8
+ [:multi, [:code, "#{@attr_delimiter} = #{@options[:attr_delimiter].inspect}"], exp]
9
+ else
10
+ exp
11
+ end
12
+ end
13
+
5
14
  # Handle control expression `[:slim, :control, code, content]`
6
15
  #
7
16
  # @param [String] ruby code
@@ -19,7 +28,11 @@ module Slim
19
28
  # @param [Array] content Temple expression
20
29
  # @return [Array] Compiled temple expression
21
30
  def on_slim_condcomment(condition, content)
22
- [:html, :comment, [:multi, [:static, "[#{condition}]>"], compile(content), [:static, '<![endif]']]]
31
+ [:html, :comment,
32
+ [:multi,
33
+ [:static, "[#{condition}]>"],
34
+ compile(content),
35
+ [:static, '<![endif]']]]
23
36
  end
24
37
 
25
38
  # Handle output expression `[:slim, :output, escape, code, content]`
@@ -54,6 +67,53 @@ module Slim
54
67
  end
55
68
  end
56
69
 
70
+ # Handle tag expression `[:slim, :tag, name, attrs, content]`
71
+ #
72
+ # @param [String] name Tag name
73
+ # @param [Array] attrs Temple expression
74
+ # @param [Array] content Temple expression
75
+ # @return [Array] Compiled temple expression
76
+ def on_slim_tag(name, attrs, content = nil)
77
+ if name == '*'
78
+ hash, merger, formatter = splat_attributes(attrs[2..-1])
79
+ tmp = unique_name
80
+ tag = [:multi,
81
+ merger,
82
+ [:code, "#{tmp} = #{hash}.delete('tag').to_s"],
83
+ [:if, "#{tmp}.empty?",
84
+ [:code, "#{tmp} = #{@options[:default_tag].inspect}"]],
85
+ [:static, '<'],
86
+ [:dynamic, "#{tmp}"],
87
+ formatter]
88
+ tag << if content
89
+ [:multi,
90
+ [:static, '>'],
91
+ compile(content),
92
+ [:static, '</'],
93
+ [:dynamic, "#{tmp}"],
94
+ [:static, '>']]
95
+ else
96
+ [:static, '/>']
97
+ end
98
+ else
99
+ tag = [:html, :tag, name, compile(attrs)]
100
+ content ? (tag << compile(content)) : tag
101
+ end
102
+ end
103
+
104
+ # Handle attributes expression `[:slim, :attrs, *attrs]`
105
+ #
106
+ # @param [Array] *attrs Array of temple expressions
107
+ # @return [Array] Compiled temple expression
108
+ def on_slim_attrs(*attrs)
109
+ if attrs.any? {|attr| attr[1] == :splat}
110
+ hash, merger, formatter = splat_attributes(attrs)
111
+ [:multi, merger, formatter]
112
+ else
113
+ [:html, :attrs, *attrs.map {|a| compile(a) }]
114
+ end
115
+ end
116
+
57
117
  # Handle attribute expression `[:slim, :attr, escape, code]`
58
118
  #
59
119
  # @param [Boolean] escape Escape html
@@ -62,10 +122,8 @@ module Slim
62
122
  def on_slim_attr(name, escape, code)
63
123
  value = case code
64
124
  when 'true'
65
- escape = false
66
125
  [:static, name]
67
126
  when 'false', 'nil'
68
- escape = false
69
127
  [:multi]
70
128
  else
71
129
  tmp = unique_name
@@ -75,15 +133,67 @@ module Slim
75
133
  ['true', [:static, name]],
76
134
  ['false, nil', [:multi]],
77
135
  [:else,
78
- [:dynamic,
136
+ [:escape, escape, [:dynamic,
79
137
  if delimiter = options[:attr_delimiter][name]
80
138
  "#{tmp}.respond_to?(:join) ? #{tmp}.flatten.compact.join(#{delimiter.inspect}) : #{tmp}"
81
139
  else
82
140
  tmp
83
141
  end
84
- ]]]]
142
+ ]]]]]
85
143
  end
86
- [:html, :attr, name, [:escape, escape, value]]
144
+ [:html, :attr, name, value]
145
+ end
146
+
147
+ protected
148
+
149
+ def splat_attributes(attrs)
150
+ @splat_used = true
151
+
152
+ hash, name, value, tmp = unique_name, unique_name, unique_name, unique_name
153
+
154
+ merger = [:multi, [:code, "#{hash} = {}"]]
155
+ attrs.each do |attr|
156
+ merger << if attr[0] == :html && attr[1] == :attr
157
+ [:multi,
158
+ [:capture, tmp, compile(attr[3])],
159
+ [:code, "(#{hash}[#{attr[2].inspect}] ||= []) << #{tmp}"]]
160
+ elsif attr[0] == :slim
161
+ if attr[1] == :attr
162
+ [:code, "(#{hash}[#{attr[2].inspect}] ||= []) << (#{attr[4]})"]
163
+ elsif attr[1] == :splat
164
+ [:code, "(#{attr[2]}).each {|#{name},#{value}| (#{hash}[#{name}.to_s] ||= []) << (#{value}) }"]
165
+ else
166
+ attr
167
+ end
168
+ else
169
+ attr
170
+ end
171
+ end
172
+
173
+ merger << [:block, "#{hash}.keys.each do |#{name}|",
174
+ [:multi,
175
+ [:code, "#{value} = #{hash}[#{name}]"],
176
+ [:code, "#{value}.flatten!"],
177
+ [:block, "#{value}.map! do |#{tmp}|",
178
+ [:case, tmp,
179
+ ['true', [:code, name]],
180
+ ['false, nil', [:multi]],
181
+ [:else, [:code, tmp]]]],
182
+ [:if, "#{value}.size > 1 && !#{@attr_delimiter}[#{name}]",
183
+ [:code, "raise(\"Multiple #\{#{name}\} attributes specified\")"]],
184
+ [:code, "#{hash}[#{name}] = #{value}.compact.join(#{@attr_delimiter}[#{name}].to_s)"]]]
185
+
186
+ attr = [:multi,
187
+ [:static, ' '],
188
+ [:dynamic, name],
189
+ [:static, "=#{options[:attr_wrapper]}"],
190
+ [:escape, true, [:dynamic, value]],
191
+ [:static, options[:attr_wrapper]]]
192
+ attr = [:if, "!#{value}.empty?", attr] if options[:remove_empty_attrs]
193
+ enumerator = options[:sort_attrs] ? "#{hash}.sort_by {|#{name},#{value}| #{name} }" : hash
194
+ formatter = [:block, "#{enumerator}.each do |#{name},#{value}|", attr]
195
+
196
+ return hash, merger, formatter
87
197
  end
88
198
  end
89
199
  end
@@ -179,6 +179,7 @@ module Slim
179
179
  register :rdoc, InterpolateTiltEngine
180
180
  register :creole, InterpolateTiltEngine
181
181
  register :wiki, InterpolateTiltEngine
182
+ register :mediawiki, InterpolateTiltEngine
182
183
 
183
184
  # These engines are executed at compile time
184
185
  register :coffee, TagEngine, :tag => :script, :attributes => { :type => 'text/javascript' }, :engine => StaticTiltEngine
@@ -9,10 +9,12 @@ module Slim
9
9
  #
10
10
  # This overwrites some temple default options.
11
11
  set_default_options :pretty => false,
12
+ :sort_attrs => true,
12
13
  :attr_wrapper => '"',
13
14
  :attr_delimiter => {'class' => ' '},
14
- :generator => Temple::Generators::ArrayBuffer
15
-
15
+ :remove_empty_attrs => true,
16
+ :generator => Temple::Generators::ArrayBuffer,
17
+ :default_tag => 'div'
16
18
  #
17
19
  # Document all supported options with purpose, type etc.
18
20
  #
@@ -22,6 +24,7 @@ module Slim
22
24
  # Integer | :tabsize | 4 | Number of whitespaces per tab (used by the parser)
23
25
  # String | :encoding | "utf-8" | Set encoding of template
24
26
  # String | :default_tag | "div" | Default tag to be used if tag name is omitted
27
+ # Hash | :shortcut | {'.' => 'class', ...} | Attribute shortcuts
25
28
  # String list | :enable_engines | All enabled | List of enabled embedded engines (whitelist)
26
29
  # String list | :disable_engines | None disabled | List of disabled embedded engines (blacklist)
27
30
  # Boolean | :sections | false | Enable sections mode (logic-less)
@@ -56,12 +59,12 @@ module Slim
56
59
  # It is recommended to set the default settings only once in the code and avoid duplication. Only use
57
60
  # `set_default_options` when you have to override some default settings.
58
61
  #
59
- use Slim::Parser, :file, :tabsize, :encoding, :default_tag
62
+ use Slim::Parser, :file, :tabsize, :encoding, :shortcut, :default_tag
60
63
  use Slim::EmbeddedEngine, :enable_engines, :disable_engines, :pretty
61
64
  use Slim::Interpolation
62
65
  use Slim::Sections, :sections, :dictionary, :dictionary_access
63
66
  use Slim::EndInserter
64
- use Slim::Compiler, :disable_capture, :attr_delimiter
67
+ use Slim::Compiler, :disable_capture, :attr_delimiter, :attr_wrapper, :sort_attrs, :remove_empty_attrs, :default_tag
65
68
  html :AttributeMerger, :attr_delimiter
66
69
  html :AttributeSorter, :sort_attrs
67
70
  html :AttributeRemover, :remove_empty_attrs
@@ -26,5 +26,16 @@ module Slim
26
26
  def on_slim_output(code, escape, content)
27
27
  [:slim, :output, code, escape, compile(content)]
28
28
  end
29
+
30
+ # Pass-through handler
31
+ def on_slim_attrs(*attrs)
32
+ [:slim, :attrs, *attrs.map {|a| compile(a) }]
33
+ end
34
+
35
+ # Pass-through handler
36
+ def on_slim_tag(name, attrs, content = nil)
37
+ tag = [:slim, :tag, name, compile(attrs)]
38
+ content ? (tag << compile(content)) : tag
39
+ end
29
40
  end
30
41
  end
@@ -5,14 +5,19 @@ module Slim
5
5
  extend Temple::Grammar
6
6
 
7
7
  Expression <<
8
- [:slim, :control, String, Expression] |
9
- [:slim, :condcomment, String, Expression] |
10
- [:slim, :output, Bool, String, Expression] |
11
- [:slim, :interpolate, String] |
12
- [:slim, :embedded, String, Expression]
8
+ [:slim, :control, String, Expression] |
9
+ [:slim, :condcomment, String, Expression] |
10
+ [:slim, :output, Bool, String, Expression] |
11
+ [:slim, :interpolate, String] |
12
+ [:slim, :embedded, String, Expression] |
13
+ [:slim, :tag, String, SlimAttrs, 'Expression?']
13
14
 
14
- HTMLAttr <<
15
- [:slim, :attr, String, Bool, String]
15
+ SlimAttrs <<
16
+ [:slim, :attrs, 'SlimAttr*']
16
17
 
18
+ SlimAttr <<
19
+ HTMLAttr |
20
+ [:slim, :attr, String, Bool, String] |
21
+ [:slim, :splat, String]
17
22
  end
18
23
  end
@@ -16,7 +16,7 @@ module Slim
16
16
  case string
17
17
  when /\A\\#\{/
18
18
  # Escaped interpolation
19
- # HACK: Use :slim :output because this is used by InterpolateTiltEngine
19
+ # Use [:slim, :output] because this is used by InterpolateTiltEngine
20
20
  # to filter out protected strings (Issue #141).
21
21
  block << [:slim, :output, false, '\'#{\'', [:multi]]
22
22
  string = $'
@@ -4,9 +4,12 @@ module Slim
4
4
  class Parser
5
5
  include Temple::Mixins::Options
6
6
 
7
- set_default_options :tabsize => 4,
7
+ set_default_options :tabsize => 4,
8
8
  :encoding => 'utf-8',
9
- :default_tag => 'div'
9
+ :shortcut => {
10
+ '#' => 'id',
11
+ '.' => 'class'
12
+ }
10
13
 
11
14
  class SyntaxError < StandardError
12
15
  attr_reader :error, :file, :line, :lineno, :column
@@ -33,6 +36,17 @@ module Slim
33
36
  def initialize(options = {})
34
37
  super
35
38
  @tab = ' ' * @options[:tabsize]
39
+ @shortcut = {}
40
+ @options[:shortcut].each do |k,v|
41
+ @shortcut[k] = if v =~ /\A([^\s]+)\s+([^\s]+)\Z/
42
+ [$1, $2]
43
+ else
44
+ [@options[:default_tag], v]
45
+ end
46
+ end
47
+ shortcut = "[#{Regexp.escape @shortcut.keys.join}]"
48
+ @shortcut_regex = /\A(#{shortcut})(\w[\w-]*\w|\w+)/
49
+ @tag_regex = /\A(?:#{shortcut}|\*(?=[^\s]+)|(\w[\w:-]*\w|\w+))/
36
50
  end
37
51
 
38
52
  # Compile string to Temple expression
@@ -66,15 +80,10 @@ module Slim
66
80
  '{' => '}',
67
81
  }.freeze
68
82
 
69
- ATTR_SHORTCUT = {
70
- '#' => 'id',
71
- '.' => 'class',
72
- }.freeze
73
-
74
- DELIMITER_REGEX = /\A[\(\[\{]/
75
- ATTR_NAME_REGEX = '\A\s*(\w[:\w-]*)'
76
- CLASS_ID_REGEX = /\A(#|\.)(\w[\w-]*\w|\w+)/
77
- TAG_REGEX = /\A([#\.]|\w[\w:-]*\w|\w+)/
83
+ DELIMITER_REGEX = /\A[#{Regexp.escape DELIMITERS.keys.join}]/
84
+ ATTR_NAME = '\A\s*(\w[:\w-]*)'
85
+ QUOTED_ATTR_REGEX = /#{ATTR_NAME}=("|')/
86
+ CODE_ATTR_REGEX = /#{ATTR_NAME}=/
78
87
 
79
88
  def reset(lines = nil, stacks = nil)
80
89
  # Since you can indent however you like in Slim, we need to keep a list
@@ -208,8 +217,9 @@ module Slim
208
217
  when /\Adoctype\s+/i
209
218
  # Found doctype declaration
210
219
  @stacks.last << [:html, :doctype, $'.strip]
211
- when TAG_REGEX
220
+ when @tag_regex
212
221
  # Found a HTML tag.
222
+ @line = $' if $1
213
223
  parse_tag($&)
214
224
  else
215
225
  syntax_error! 'Unknown line indicator'
@@ -279,25 +289,20 @@ module Slim
279
289
  end
280
290
 
281
291
  def parse_tag(tag)
282
- if tag == '#' || tag == '.'
283
- tag = options[:default_tag]
284
- else
285
- @line.slice!(0, tag.size)
286
- end
287
-
288
- tag = [:html, :tag, tag, parse_attributes]
292
+ tag = [:slim, :tag, @shortcut[tag] ? @shortcut[tag][0] : tag, parse_attributes]
289
293
  @stacks.last << tag
290
294
 
291
295
  case @line
292
296
  when /\A\s*:\s*/
293
297
  # Block expansion
294
298
  @line = $'
295
- (@line =~ TAG_REGEX) || syntax_error!('Expected tag')
299
+ (@line =~ @tag_regex) || syntax_error!('Expected tag')
300
+ @line = $' if $1
296
301
  content = [:multi]
297
302
  tag << content
298
303
  i = @stacks.size
299
304
  @stacks << content
300
- parse_tag($1)
305
+ parse_tag($&)
301
306
  @stacks.delete_at(i)
302
307
  when /\A\s*=(=?)('?)/
303
308
  # Handle output code
@@ -321,13 +326,14 @@ module Slim
321
326
  end
322
327
 
323
328
  def parse_attributes
324
- attributes = [:html, :attrs]
329
+ attributes = [:slim, :attrs]
330
+ attribute = nil
325
331
 
326
- # Find any literal class/id attributes
327
- while @line =~ CLASS_ID_REGEX
332
+ # Find any shortcut attributes
333
+ while @line =~ @shortcut_regex
328
334
  # The class/id attribute is :static instead of :slim :text,
329
335
  # because we don't want text interpolation in .class or #id shortcut
330
- attributes << [:html, :attr, ATTR_SHORTCUT[$1], [:static, $2]]
336
+ attributes << [:html, :attr, @shortcut[$1][1], [:static, $2]]
331
337
  @line = $'
332
338
  end
333
339
 
@@ -338,54 +344,67 @@ module Slim
338
344
  @line.slice!(0)
339
345
  end
340
346
 
341
- orig_line = @orig_line
342
- lineno = @lineno
347
+ if delimiter
348
+ boolean_attr_regex = /#{ATTR_NAME}(?=(\s|#{Regexp.escape delimiter}))/
349
+ end_regex = /\A\s*#{Regexp.escape delimiter}/
350
+ end
351
+
343
352
  while true
344
- # Parse attributes
345
- attr_regex = delimiter ? /#{ATTR_NAME_REGEX}(=|\s|(?=#{Regexp.escape delimiter}))/ : /#{ATTR_NAME_REGEX}=/
346
- while @line =~ attr_regex
353
+ case @line
354
+ when /\A\s*\*(?=[^\s]+)/
355
+ # Splat attribute
356
+ @line = $'
357
+ attributes << [:slim, :splat, parse_ruby_code(delimiter)]
358
+ when QUOTED_ATTR_REGEX
359
+ # Value is quoted (static)
347
360
  @line = $'
361
+ attributes << [:html, :attr, $1, [:slim, :interpolate, parse_quoted_attribute($2)]]
362
+ when CODE_ATTR_REGEX
363
+ # Value is ruby code
364
+ @line = $'
365
+ escape = @line[0] != ?=
366
+ @line.slice!(0) unless escape
348
367
  name = $1
349
- if delimiter && $2 != '='
350
- attributes << [:slim, :attr, name, false, 'true']
351
- elsif @line =~ /\A["']/
352
- # Value is quoted (static)
368
+ value = parse_ruby_code(delimiter)
369
+ # Remove attribute wrapper which doesn't belong to the ruby code
370
+ # e.g id=[hash[:a] + hash[:b]]
371
+ value = value[1..-2] if value =~ DELIMITER_REGEX &&
372
+ DELIMITERS[$&] == value[-1, 1]
373
+ syntax_error!('Invalid empty attribute') if value.empty?
374
+ attributes << [:slim, :attr, name, escape, value]
375
+ else
376
+ break unless delimiter
377
+
378
+ case @line
379
+ when boolean_attr_regex
380
+ # Boolean attribute
353
381
  @line = $'
354
- attributes << [:html, :attr, name, [:slim, :interpolate, parse_quoted_attribute($&)]]
382
+ attributes << [:slim, :attr, $1, false, 'true']
383
+ when end_regex
384
+ # Find ending delimiter
385
+ @line = $'
386
+ break
355
387
  else
356
- # Value is ruby code
357
- escape = @line[0] != ?=
358
- @line.slice!(0) unless escape
359
- attributes << [:slim, :attr, name, escape, parse_ruby_attribute(delimiter)]
388
+ # Found something where an attribute should be
389
+ @line.lstrip!
390
+ syntax_error!('Expected attribute') unless @line.empty?
391
+
392
+ # Attributes span multiple lines
393
+ @stacks.last << [:newline]
394
+ orig_line, lineno = @orig_line, @lineno
395
+ next_line || syntax_error!("Expected closing delimiter #{delimiter}",
396
+ :orig_line => orig_line,
397
+ :lineno => lineno,
398
+ :column => orig_line.size)
360
399
  end
361
400
  end
362
-
363
- # No ending delimiter, attribute end
364
- break unless delimiter
365
-
366
- # Find ending delimiter
367
- if @line =~ /\A\s*#{Regexp.escape delimiter}/
368
- @line = $'
369
- break
370
- end
371
-
372
- # Found something where an attribute should be
373
- @line.lstrip!
374
- syntax_error!('Expected attribute') unless @line.empty?
375
-
376
- # Attributes span multiple lines
377
- @stacks.last << [:newline]
378
- next_line || syntax_error!("Expected closing delimiter #{delimiter}",
379
- :orig_line => orig_line,
380
- :lineno => lineno,
381
- :column => orig_line.size)
382
401
  end
383
402
 
384
403
  attributes
385
404
  end
386
405
 
387
- def parse_ruby_attribute(outer_delimiter)
388
- value, count, delimiter, close_delimiter = '', 0, nil, nil
406
+ def parse_ruby_code(outer_delimiter)
407
+ code, count, delimiter, close_delimiter = '', 0, nil, nil
389
408
 
390
409
  # Attribute ends with space or attribute delimiter
391
410
  end_regex = /\A[\s#{Regexp.escape outer_delimiter.to_s}]/
@@ -401,18 +420,10 @@ module Slim
401
420
  count = 1
402
421
  delimiter, close_delimiter = $&, DELIMITERS[$&]
403
422
  end
404
- value << @line.slice!(0)
423
+ code << @line.slice!(0)
405
424
  end
406
-
407
- syntax_error!("Expected closing attribute delimiter #{close_delimiter}") if count != 0
408
- syntax_error!('Invalid empty attribute') if value.empty?
409
-
410
- # Remove attribute wrapper which doesn't belong to the ruby code
411
- # e.g id=[hash[:a] + hash[:b]]
412
- value = value[1..-2] if value =~ DELIMITER_REGEX &&
413
- DELIMITERS[$&] == value[-1, 1]
414
-
415
- value
425
+ syntax_error!("Expected closing delimiter #{close_delimiter}") if count != 0
426
+ code
416
427
  end
417
428
 
418
429
  def parse_quoted_attribute(quote)