hamlit 2.11.0 → 2.13.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +17 -11
- data/CHANGELOG.md +29 -1
- data/Gemfile +1 -7
- data/LICENSE.txt +26 -23
- data/REFERENCE.md +4 -4
- data/bin/update-haml +125 -0
- data/ext/hamlit/hamlit.c +0 -1
- data/lib/hamlit/attribute_builder.rb +2 -2
- data/lib/hamlit/attribute_compiler.rb +3 -3
- data/lib/hamlit/compiler/children_compiler.rb +18 -4
- data/lib/hamlit/compiler/comment_compiler.rb +1 -0
- data/lib/hamlit/filters/escaped.rb +1 -1
- data/lib/hamlit/filters/markdown.rb +1 -0
- data/lib/hamlit/filters/preserve.rb +1 -1
- data/lib/hamlit/filters/text_base.rb +1 -1
- data/lib/hamlit/filters/tilt_base.rb +1 -1
- data/lib/hamlit/parser.rb +6 -2
- data/lib/hamlit/parser/haml_attribute_builder.rb +164 -0
- data/lib/hamlit/parser/haml_buffer.rb +20 -130
- data/lib/hamlit/parser/haml_compiler.rb +1 -553
- data/lib/hamlit/parser/haml_error.rb +29 -25
- data/lib/hamlit/parser/haml_escapable.rb +1 -0
- data/lib/hamlit/parser/haml_generator.rb +1 -0
- data/lib/hamlit/parser/haml_helpers.rb +41 -59
- data/lib/hamlit/parser/{haml_xss_mods.rb → haml_helpers/xss_mods.rb} +20 -15
- data/lib/hamlit/parser/haml_options.rb +53 -66
- data/lib/hamlit/parser/haml_parser.rb +103 -71
- data/lib/hamlit/parser/haml_temple_engine.rb +123 -0
- data/lib/hamlit/parser/haml_util.rb +10 -40
- data/lib/hamlit/rails_template.rb +1 -1
- data/lib/hamlit/string_splitter.rb +1 -0
- data/lib/hamlit/temple_line_counter.rb +31 -0
- data/lib/hamlit/version.rb +1 -1
- metadata +10 -6
- data/lib/hamlit/parser/MIT-LICENSE +0 -20
- data/lib/hamlit/parser/README.md +0 -30
@@ -1,10 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'strscan'
|
2
|
-
require 'hamlit/parser/haml_util'
|
3
|
-
require 'hamlit/parser/haml_error'
|
4
4
|
|
5
5
|
module Hamlit
|
6
6
|
class HamlParser
|
7
|
-
include
|
7
|
+
include Hamlit::HamlUtil
|
8
8
|
|
9
9
|
attr_reader :root
|
10
10
|
|
@@ -61,7 +61,7 @@ module Hamlit
|
|
61
61
|
SILENT_SCRIPT,
|
62
62
|
ESCAPE,
|
63
63
|
FILTER
|
64
|
-
]
|
64
|
+
].freeze
|
65
65
|
|
66
66
|
# The value of the character that designates that a line is part
|
67
67
|
# of a multiline string.
|
@@ -75,8 +75,8 @@ module Hamlit
|
|
75
75
|
#
|
76
76
|
BLOCK_WITH_SPACES = /do\s*\|\s*[^\|]*\s+\|\z/
|
77
77
|
|
78
|
-
MID_BLOCK_KEYWORDS = %w[else elsif rescue ensure end when]
|
79
|
-
START_BLOCK_KEYWORDS = %w[if begin case unless]
|
78
|
+
MID_BLOCK_KEYWORDS = %w[else elsif rescue ensure end when].freeze
|
79
|
+
START_BLOCK_KEYWORDS = %w[if begin case unless].freeze
|
80
80
|
# Try to parse assignments to block starters as best as possible
|
81
81
|
START_BLOCK_KEYWORD_REGEX = /(?:\w+(?:,\s*\w+)*\s*=\s*)?(#{START_BLOCK_KEYWORDS.join('|')})/
|
82
82
|
BLOCK_KEYWORD_REGEX = /^-?\s*(?:(#{MID_BLOCK_KEYWORDS.join('|')})|#{START_BLOCK_KEYWORD_REGEX.source})\b/
|
@@ -90,14 +90,16 @@ module Hamlit
|
|
90
90
|
ID_KEY = 'id'.freeze
|
91
91
|
CLASS_KEY = 'class'.freeze
|
92
92
|
|
93
|
-
def initialize(
|
94
|
-
@options
|
93
|
+
def initialize(options)
|
94
|
+
@options = HamlOptions.wrap(options)
|
95
95
|
# Record the indent levels of "if" statements to validate the subsequent
|
96
96
|
# elsif and else statements are indented at the appropriate level.
|
97
97
|
@script_level_stack = []
|
98
98
|
@template_index = 0
|
99
99
|
@template_tabs = 0
|
100
|
+
end
|
100
101
|
|
102
|
+
def call(template)
|
101
103
|
match = template.rstrip.scan(/(([ \t]+)?(.*?))(?:\Z|\r\n|\r|\n)/m)
|
102
104
|
# discard the last match which is always blank
|
103
105
|
match.pop
|
@@ -106,16 +108,14 @@ module Hamlit
|
|
106
108
|
end
|
107
109
|
# Append special end-of-document marker
|
108
110
|
@template << Line.new(nil, '-#', '-#', @template.size, self, true)
|
109
|
-
end
|
110
111
|
|
111
|
-
def parse
|
112
112
|
@root = @parent = ParseNode.new(:root)
|
113
113
|
@flat = false
|
114
114
|
@filter_buffer = nil
|
115
115
|
@indentation = nil
|
116
116
|
@line = next_line
|
117
117
|
|
118
|
-
raise
|
118
|
+
raise HamlSyntaxError.new(HamlError.message(:indenting_at_start), @line.index) if @line.tabs != 0
|
119
119
|
|
120
120
|
loop do
|
121
121
|
next_line
|
@@ -138,7 +138,7 @@ module Hamlit
|
|
138
138
|
end
|
139
139
|
|
140
140
|
if !flat? && @next_line.tabs - @line.tabs > 1
|
141
|
-
raise
|
141
|
+
raise HamlSyntaxError.new(HamlError.message(:deeper_indenting, @next_line.tabs - @line.tabs), @next_line.index)
|
142
142
|
end
|
143
143
|
|
144
144
|
@line = @next_line
|
@@ -146,7 +146,7 @@ module Hamlit
|
|
146
146
|
# Close all the open tags
|
147
147
|
close until @parent.type == :root
|
148
148
|
@root
|
149
|
-
rescue
|
149
|
+
rescue Hamlit::HamlError => e
|
150
150
|
e.backtrace.unshift "#{@options.filename}:#{(e.line ? e.line + 1 : @line.index + 1) + @options.line - 1}"
|
151
151
|
raise
|
152
152
|
end
|
@@ -158,7 +158,7 @@ module Hamlit
|
|
158
158
|
@indentation = line.whitespace
|
159
159
|
|
160
160
|
if @indentation.include?(?\s) && @indentation.include?(?\t)
|
161
|
-
raise
|
161
|
+
raise HamlSyntaxError.new(HamlError.message(:cant_use_tabs_and_spaces), line.index)
|
162
162
|
end
|
163
163
|
|
164
164
|
@flat_spaces = @indentation * (@template_tabs+1) if flat?
|
@@ -169,17 +169,17 @@ module Hamlit
|
|
169
169
|
return tabs if line.whitespace == @indentation * tabs
|
170
170
|
return @template_tabs + 1 if flat? && line.whitespace =~ /^#{@flat_spaces}/
|
171
171
|
|
172
|
-
message =
|
172
|
+
message = HamlError.message(:inconsistent_indentation,
|
173
173
|
human_indentation(line.whitespace),
|
174
174
|
human_indentation(@indentation)
|
175
175
|
)
|
176
|
-
raise
|
176
|
+
raise HamlSyntaxError.new(message, line.index)
|
177
177
|
end
|
178
178
|
|
179
179
|
private
|
180
180
|
|
181
181
|
# @private
|
182
|
-
|
182
|
+
Line = Struct.new(:whitespace, :text, :full, :index, :parser, :eod) do
|
183
183
|
alias_method :eod?, :eod
|
184
184
|
|
185
185
|
# @private
|
@@ -195,14 +195,39 @@ module Hamlit
|
|
195
195
|
end
|
196
196
|
|
197
197
|
# @private
|
198
|
-
|
198
|
+
ParseNode = Struct.new(:type, :line, :value, :parent, :children) do
|
199
199
|
def initialize(*args)
|
200
200
|
super
|
201
201
|
self.children ||= []
|
202
202
|
end
|
203
203
|
|
204
204
|
def inspect
|
205
|
-
%Q[(#{type} #{value.inspect}#{children.each_with_object('') {|c, s| s << "\n#{c.inspect.gsub!(/^/, ' ')}"}})]
|
205
|
+
%Q[(#{type} #{value.inspect}#{children.each_with_object(''.dup) {|c, s| s << "\n#{c.inspect.gsub!(/^/, ' ')}"}})].dup
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# @param [String] new - Hash literal including dynamic values.
|
210
|
+
# @param [String] old - Hash literal including dynamic values or Ruby literal of multiple Hashes which MUST be interpreted as method's last arguments.
|
211
|
+
DynamicAttributes = Struct.new(:new, :old) do
|
212
|
+
undef :old=
|
213
|
+
def old=(value)
|
214
|
+
unless value =~ /\A{.*}\z/m
|
215
|
+
raise ArgumentError.new('Old attributes must start with "{" and end with "}"')
|
216
|
+
end
|
217
|
+
self[:old] = value
|
218
|
+
end
|
219
|
+
|
220
|
+
# This will be a literal for Hamlit::HamlBuffer#attributes's last argument, `attributes_hashes`.
|
221
|
+
def to_literal
|
222
|
+
[new, stripped_old].compact.join(', ')
|
223
|
+
end
|
224
|
+
|
225
|
+
private
|
226
|
+
|
227
|
+
# For `%foo{ { foo: 1 }, bar: 2 }`, :old is "{ { foo: 1 }, bar: 2 }" and this method returns " { foo: 1 }, bar: 2 " for last argument.
|
228
|
+
def stripped_old
|
229
|
+
return nil if old.nil?
|
230
|
+
old.sub!(/\A{/, '').sub!(/}\z/m, '')
|
206
231
|
end
|
207
232
|
end
|
208
233
|
|
@@ -264,7 +289,7 @@ module Hamlit
|
|
264
289
|
end
|
265
290
|
|
266
291
|
def block_keyword(text)
|
267
|
-
return unless keyword = text.scan(BLOCK_KEYWORD_REGEX)[0]
|
292
|
+
return unless (keyword = text.scan(BLOCK_KEYWORD_REGEX)[0])
|
268
293
|
keyword[0] || keyword[1]
|
269
294
|
end
|
270
295
|
|
@@ -275,20 +300,20 @@ module Hamlit
|
|
275
300
|
|
276
301
|
def plain(line, escape_html = nil)
|
277
302
|
if block_opened?
|
278
|
-
raise
|
303
|
+
raise HamlSyntaxError.new(HamlError.message(:illegal_nesting_plain), @next_line.index)
|
279
304
|
end
|
280
305
|
|
281
306
|
unless contains_interpolation?(line.text)
|
282
307
|
return ParseNode.new(:plain, line.index + 1, :text => line.text)
|
283
308
|
end
|
284
309
|
|
285
|
-
escape_html = @options.escape_html if escape_html.nil?
|
286
|
-
line.text =
|
310
|
+
escape_html = @options.escape_html && @options.mime_type != 'text/plain' if escape_html.nil?
|
311
|
+
line.text = unescape_interpolation(line.text)
|
287
312
|
script(line, false).tap { |n| n.value[:escape_interpolation] = true if escape_html }
|
288
313
|
end
|
289
314
|
|
290
315
|
def script(line, escape_html = nil, preserve = false)
|
291
|
-
raise
|
316
|
+
raise HamlSyntaxError.new(HamlError.message(:no_ruby_code, '=')) if line.text.empty?
|
292
317
|
line = handle_ruby_multiline(line)
|
293
318
|
escape_html = @options.escape_html if escape_html.nil?
|
294
319
|
|
@@ -300,12 +325,12 @@ module Hamlit
|
|
300
325
|
end
|
301
326
|
|
302
327
|
def flat_script(line, escape_html = nil)
|
303
|
-
raise
|
328
|
+
raise HamlSyntaxError.new(HamlError.message(:no_ruby_code, '~')) if line.text.empty?
|
304
329
|
script(line, escape_html, :preserve)
|
305
330
|
end
|
306
331
|
|
307
332
|
def silent_script(line)
|
308
|
-
raise
|
333
|
+
raise HamlSyntaxError.new(HamlError.message(:no_end), line.index) if line.text[1..-1].strip == 'end'
|
309
334
|
|
310
335
|
line = handle_ruby_multiline(line)
|
311
336
|
keyword = block_keyword(line.text)
|
@@ -314,7 +339,7 @@ module Hamlit
|
|
314
339
|
|
315
340
|
if ["else", "elsif", "when"].include?(keyword)
|
316
341
|
if @script_level_stack.empty?
|
317
|
-
raise
|
342
|
+
raise Hamlit::HamlSyntaxError.new(HamlError.message(:missing_if, keyword), @line.index)
|
318
343
|
end
|
319
344
|
|
320
345
|
if keyword == 'when' and !@script_level_stack.last[2]
|
@@ -325,8 +350,8 @@ module Hamlit
|
|
325
350
|
end
|
326
351
|
|
327
352
|
if @script_level_stack.last[1] != @line.tabs
|
328
|
-
message =
|
329
|
-
raise
|
353
|
+
message = HamlError.message(:bad_script_indent, keyword, @script_level_stack.last[1], @line.tabs)
|
354
|
+
raise Hamlit::HamlSyntaxError.new(message, @line.index)
|
330
355
|
end
|
331
356
|
end
|
332
357
|
|
@@ -363,7 +388,6 @@ module Hamlit
|
|
363
388
|
|
364
389
|
preserve_tag = @options.preserve.include?(tag_name)
|
365
390
|
nuke_inner_whitespace ||= preserve_tag
|
366
|
-
preserve_tag = false if @options.ugly
|
367
391
|
escape_html = (action == '&' || (action != '!' && @options.escape_html))
|
368
392
|
|
369
393
|
case action
|
@@ -372,7 +396,7 @@ module Hamlit
|
|
372
396
|
when '='
|
373
397
|
parse = true
|
374
398
|
if value[0] == ?=
|
375
|
-
value =
|
399
|
+
value = unescape_interpolation(value[1..-1].strip)
|
376
400
|
escape_interpolation = true if escape_html
|
377
401
|
escape_html = false
|
378
402
|
end
|
@@ -381,50 +405,47 @@ module Hamlit
|
|
381
405
|
parse = true
|
382
406
|
preserve_script = (value[0] == ?~)
|
383
407
|
if value[1] == ?=
|
384
|
-
value =
|
408
|
+
value = unescape_interpolation(value[2..-1].strip)
|
385
409
|
escape_interpolation = true if escape_html
|
386
410
|
escape_html = false
|
387
411
|
else
|
388
412
|
value = value[1..-1].strip
|
389
413
|
end
|
390
414
|
elsif contains_interpolation?(value)
|
391
|
-
value =
|
415
|
+
value = unescape_interpolation(value)
|
392
416
|
escape_interpolation = true if escape_html
|
393
417
|
parse = true
|
394
418
|
escape_html = false
|
395
419
|
end
|
396
420
|
else
|
397
421
|
if contains_interpolation?(value)
|
398
|
-
value =
|
399
|
-
escape_interpolation = true if escape_html
|
422
|
+
value = unescape_interpolation(value, escape_html)
|
400
423
|
parse = true
|
401
424
|
escape_html = false
|
402
425
|
end
|
403
426
|
end
|
404
427
|
|
405
|
-
attributes =
|
406
|
-
|
428
|
+
attributes = HamlParser.parse_class_and_id(attributes)
|
429
|
+
dynamic_attributes = DynamicAttributes.new
|
407
430
|
|
408
431
|
if attributes_hashes[:new]
|
409
432
|
static_attributes, attributes_hash = attributes_hashes[:new]
|
410
|
-
|
411
|
-
|
433
|
+
HamlAttributeBuilder.merge_attributes!(attributes, static_attributes) if static_attributes
|
434
|
+
dynamic_attributes.new = attributes_hash
|
412
435
|
end
|
413
436
|
|
414
437
|
if attributes_hashes[:old]
|
415
438
|
static_attributes = parse_static_hash(attributes_hashes[:old])
|
416
|
-
|
417
|
-
|
439
|
+
HamlAttributeBuilder.merge_attributes!(attributes, static_attributes) if static_attributes
|
440
|
+
dynamic_attributes.old = attributes_hashes[:old] unless static_attributes || @options.suppress_eval
|
418
441
|
end
|
419
442
|
|
420
|
-
|
421
|
-
|
422
|
-
raise
|
423
|
-
raise ::Hamlit::HamlSyntaxError.new(::Hamlit::HamlError.message(:no_ruby_code, action), last_line - 1) if parse && value.empty?
|
424
|
-
raise ::Hamlit::HamlSyntaxError.new(::Hamlit::HamlError.message(:self_closing_content), last_line - 1) if self_closing && !value.empty?
|
443
|
+
raise HamlSyntaxError.new(HamlError.message(:illegal_nesting_self_closing), @next_line.index) if block_opened? && self_closing
|
444
|
+
raise HamlSyntaxError.new(HamlError.message(:no_ruby_code, action), last_line - 1) if parse && value.empty?
|
445
|
+
raise HamlSyntaxError.new(HamlError.message(:self_closing_content), last_line - 1) if self_closing && !value.empty?
|
425
446
|
|
426
447
|
if block_opened? && !value.empty? && !is_ruby_multiline?(value)
|
427
|
-
raise
|
448
|
+
raise HamlSyntaxError.new(HamlError.message(:illegal_nesting_line, tag_name), @next_line.index)
|
428
449
|
end
|
429
450
|
|
430
451
|
self_closing ||= !!(!block_opened? && value.empty? && @options.autoclose.any? {|t| t === tag_name})
|
@@ -433,7 +454,7 @@ module Hamlit
|
|
433
454
|
line = handle_ruby_multiline(line) if parse
|
434
455
|
|
435
456
|
ParseNode.new(:tag, line.index + 1, :name => tag_name, :attributes => attributes,
|
436
|
-
:
|
457
|
+
:dynamic_attributes => dynamic_attributes, :self_closing => self_closing,
|
437
458
|
:nuke_inner_whitespace => nuke_inner_whitespace,
|
438
459
|
:nuke_outer_whitespace => nuke_outer_whitespace, :object_ref => object_ref,
|
439
460
|
:escape_html => escape_html, :preserve_tag => preserve_tag,
|
@@ -462,13 +483,13 @@ module Hamlit
|
|
462
483
|
|
463
484
|
if contains_interpolation?(text)
|
464
485
|
parse = true
|
465
|
-
text =
|
486
|
+
text = unescape_interpolation(text)
|
466
487
|
else
|
467
488
|
parse = false
|
468
489
|
end
|
469
490
|
|
470
491
|
if block_opened? && !text.empty?
|
471
|
-
raise
|
492
|
+
raise HamlSyntaxError.new(Hamlit::HamlError.message(:illegal_nesting_content), @next_line.index)
|
472
493
|
end
|
473
494
|
|
474
495
|
ParseNode.new(:comment, @line.index + 1, :conditional => conditional, :text => text, :revealed => revealed, :parse => parse)
|
@@ -476,13 +497,13 @@ module Hamlit
|
|
476
497
|
|
477
498
|
# Renders an XHTML doctype or XML shebang.
|
478
499
|
def doctype(text)
|
479
|
-
raise
|
500
|
+
raise HamlSyntaxError.new(HamlError.message(:illegal_nesting_header), @next_line.index) if block_opened?
|
480
501
|
version, type, encoding = text[3..-1].strip.downcase.scan(DOCTYPE_REGEX)[0]
|
481
502
|
ParseNode.new(:doctype, @line.index + 1, :version => version, :type => type, :encoding => encoding)
|
482
503
|
end
|
483
504
|
|
484
505
|
def filter(name)
|
485
|
-
raise
|
506
|
+
raise HamlError.new(HamlError.message(:invalid_filter_name, name)) unless name =~ /^\w+$/
|
486
507
|
|
487
508
|
if filter_opened?
|
488
509
|
@flat = true
|
@@ -519,7 +540,7 @@ module Hamlit
|
|
519
540
|
|
520
541
|
# Post-process case statements to normalize the nesting of "when" clauses
|
521
542
|
return unless node.value[:keyword] == "case"
|
522
|
-
return unless first = node.children.first
|
543
|
+
return unless (first = node.children.first)
|
523
544
|
return unless first.type == :silent_script && first.value[:keyword] == "when"
|
524
545
|
return if first.children.empty?
|
525
546
|
# If the case node has a "when" child with children, it's the
|
@@ -531,7 +552,7 @@ module Hamlit
|
|
531
552
|
|
532
553
|
alias :close_script :close_silent_script
|
533
554
|
|
534
|
-
# This is a class method so it can be accessed from {
|
555
|
+
# This is a class method so it can be accessed from {Hamlit::HamlHelpers}.
|
535
556
|
#
|
536
557
|
# Iterates through the classes and ids supplied through `.`
|
537
558
|
# and `#` syntax, and returns a hash with them as attributes,
|
@@ -540,7 +561,7 @@ module Hamlit
|
|
540
561
|
attributes = {}
|
541
562
|
return attributes if list.empty?
|
542
563
|
|
543
|
-
list.scan(/([#.])([-:_a-zA-Z0-9]+)/) do |type, property|
|
564
|
+
list.scan(/([#.])([-:_a-zA-Z0-9\@]+)/) do |type, property|
|
544
565
|
case type
|
545
566
|
when '.'
|
546
567
|
if attributes[CLASS_KEY]
|
@@ -555,16 +576,22 @@ module Hamlit
|
|
555
576
|
attributes
|
556
577
|
end
|
557
578
|
|
579
|
+
# This method doesn't use Hamlit::HamlAttributeParser because currently it depends on Ripper and Rubinius doesn't provide it.
|
580
|
+
# Ideally this logic should be placed in Hamlit::HamlAttributeParser instead of here and this method should use it.
|
581
|
+
#
|
582
|
+
# @param [String] text - Hash literal or text inside old attributes
|
583
|
+
# @return [Hash,nil] - Return nil if text is not static Hash literal
|
558
584
|
def parse_static_hash(text)
|
559
585
|
attributes = {}
|
560
586
|
return attributes if text.empty?
|
561
587
|
|
588
|
+
text = text[1...-1] # strip brackets
|
562
589
|
scanner = StringScanner.new(text)
|
563
590
|
scanner.scan(/\s+/)
|
564
591
|
until scanner.eos?
|
565
|
-
return unless key = scanner.scan(LITERAL_VALUE_REGEX)
|
592
|
+
return unless (key = scanner.scan(LITERAL_VALUE_REGEX))
|
566
593
|
return unless scanner.scan(/\s*=>\s*/)
|
567
|
-
return unless value = scanner.scan(LITERAL_VALUE_REGEX)
|
594
|
+
return unless (value = scanner.scan(LITERAL_VALUE_REGEX))
|
568
595
|
return unless scanner.scan(/\s*(?:,|$)\s*/)
|
569
596
|
attributes[eval(key).to_s] = eval(value).to_s
|
570
597
|
end
|
@@ -573,13 +600,13 @@ module Hamlit
|
|
573
600
|
|
574
601
|
# Parses a line into tag_name, attributes, attributes_hash, object_ref, action, value
|
575
602
|
def parse_tag(text)
|
576
|
-
match = text.scan(/%([-:\w]+)([-:\w
|
577
|
-
raise
|
603
|
+
match = text.scan(/%([-:\w]+)([-:\w.#\@]*)(.+)?/)[0]
|
604
|
+
raise HamlSyntaxError.new(HamlError.message(:invalid_tag, text)) unless match
|
578
605
|
|
579
606
|
tag_name, attributes, rest = match
|
580
607
|
|
581
608
|
if !attributes.empty? && (attributes =~ /[.#](\.|#|\z)/)
|
582
|
-
raise
|
609
|
+
raise HamlSyntaxError.new(HamlError.message(:illegal_element))
|
583
610
|
end
|
584
611
|
|
585
612
|
new_attributes_hash = old_attributes_hash = last_line = nil
|
@@ -624,14 +651,17 @@ module Hamlit
|
|
624
651
|
nuke_inner_whitespace, action, value, last_line || @line.index + 1]
|
625
652
|
end
|
626
653
|
|
654
|
+
# @return [String] attributes_hash - Hash literal starting with `{` and ending with `}`
|
655
|
+
# @return [String] rest
|
656
|
+
# @return [Integer] last_line
|
627
657
|
def parse_old_attributes(text)
|
628
658
|
text = text.dup
|
629
659
|
last_line = @line.index + 1
|
630
660
|
|
631
661
|
begin
|
632
662
|
attributes_hash, rest = balance(text, ?{, ?})
|
633
|
-
rescue
|
634
|
-
if text.strip[-1] == ?, && e.message ==
|
663
|
+
rescue HamlSyntaxError => e
|
664
|
+
if text.strip[-1] == ?, && e.message == HamlError.message(:unbalanced_brackets)
|
635
665
|
text << "\n#{@next_line.text}"
|
636
666
|
last_line += 1
|
637
667
|
next_line
|
@@ -641,10 +671,12 @@ module Hamlit
|
|
641
671
|
raise e
|
642
672
|
end
|
643
673
|
|
644
|
-
attributes_hash = attributes_hash[1...-1] if attributes_hash
|
645
674
|
return attributes_hash, rest, last_line
|
646
675
|
end
|
647
676
|
|
677
|
+
# @return [Array<Hash,String,nil>] - [static_attributes (Hash), dynamic_attributes (nil or String starting with `{` and ending with `}`)]
|
678
|
+
# @return [String] rest
|
679
|
+
# @return [Integer] last_line
|
648
680
|
def parse_new_attributes(text)
|
649
681
|
scanner = StringScanner.new(text)
|
650
682
|
last_line = @line.index + 1
|
@@ -656,9 +688,9 @@ module Hamlit
|
|
656
688
|
break if name.nil?
|
657
689
|
|
658
690
|
if name == false
|
659
|
-
scanned =
|
691
|
+
scanned = Hamlit::HamlUtil.balance(text, ?(, ?))
|
660
692
|
text = scanned ? scanned.first : text
|
661
|
-
raise
|
693
|
+
raise Hamlit::HamlSyntaxError.new(HamlError.message(:invalid_attribute_list, text.inspect), last_line - 1)
|
662
694
|
end
|
663
695
|
attributes[name] = value
|
664
696
|
scanner.scan(/\s*/)
|
@@ -672,7 +704,7 @@ module Hamlit
|
|
672
704
|
end
|
673
705
|
|
674
706
|
static_attributes = {}
|
675
|
-
dynamic_attributes = "{"
|
707
|
+
dynamic_attributes = "{".dup
|
676
708
|
attributes.each do |name, (type, val)|
|
677
709
|
if type == :static
|
678
710
|
static_attributes[name] = val
|
@@ -687,7 +719,7 @@ module Hamlit
|
|
687
719
|
end
|
688
720
|
|
689
721
|
def parse_new_attribute(scanner)
|
690
|
-
unless name = scanner.scan(/[-:\w]+/)
|
722
|
+
unless (name = scanner.scan(/[-:\w]+/))
|
691
723
|
return if scanner.scan(/\)/)
|
692
724
|
return false
|
693
725
|
end
|
@@ -696,8 +728,8 @@ module Hamlit
|
|
696
728
|
return name, [:static, true] unless scanner.scan(/=/) #/end
|
697
729
|
|
698
730
|
scanner.scan(/\s*/)
|
699
|
-
unless quote = scanner.scan(/["']/)
|
700
|
-
return false unless var = scanner.scan(/(@@?|\$)?\w+/)
|
731
|
+
unless (quote = scanner.scan(/["']/))
|
732
|
+
return false unless (var = scanner.scan(/(@@?|\$)?\w+/))
|
701
733
|
return name, [:dynamic, var]
|
702
734
|
end
|
703
735
|
|
@@ -712,7 +744,7 @@ module Hamlit
|
|
712
744
|
|
713
745
|
return name, [:static, content.first[1]] if content.size == 1
|
714
746
|
return name, [:dynamic,
|
715
|
-
%!"#{content.each_with_object('') {|(t, v), s| s << (t == :str ? inspect_obj(v)[1...-1] : "\#{#{v}}")}}"!]
|
747
|
+
%!"#{content.each_with_object(''.dup) {|(t, v), s| s << (t == :str ? inspect_obj(v)[1...-1] : "\#{#{v}}")}}"!]
|
716
748
|
end
|
717
749
|
|
718
750
|
def next_line
|
@@ -780,7 +812,7 @@ module Hamlit
|
|
780
812
|
end
|
781
813
|
|
782
814
|
def balance(*args)
|
783
|
-
|
815
|
+
Hamlit::HamlUtil.balance(*args) or raise(HamlSyntaxError.new(HamlError.message(:unbalanced_brackets)))
|
784
816
|
end
|
785
817
|
|
786
818
|
def block_opened?
|