1
0
Fork 0
mirror of https://github.com/haml/haml.git synced 2022-11-09 12:33:31 -05:00
haml--haml/lib/hamlit/compilers/new_attribute.rb
2015-03-30 10:14:37 +09:00

107 lines
2.4 KiB
Ruby

require 'hamlit/concerns/ripperable'
# This module compiles new-style attributes, which is
# surrounded by parentheses.
module Hamlit
module Compilers
module NewAttribute
include Concerns::Ripperable
def compile_new_attribute(str)
str = str.gsub(/\A\(|\)\Z/, '')
attrs = parse_new_attributes(str)
attrs.map do |key, value|
next true_attribute(key) if value == 'true'
[:html, :attr, key, [:dynamic, value]]
end
end
private
def parse_new_attributes(str)
attributes = {}
while str.length > 0
tokens = Ripper.lex(str)
key = read_key!(tokens)
val = read_value!(tokens)
if key && val
attributes[key] = val
elsif key
attributes[key] = 'true'
end
token = tokens.first
break unless token
pos = token.first.last
str = str[pos..-1]
end
attributes
end
def read_key!(tokens)
skip_tokens!(tokens, :on_sp)
(row, col), type, key = tokens.shift
key
end
def read_value!(tokens)
skip_tokens!(tokens, :on_sp)
(row, col), type, str = tokens.shift
return nil if str != '='
skip_tokens!(tokens, :on_sp)
return if tokens.empty?
case tokens.first[TYPE_POSITION]
when :on_tstring_beg
val = fetch_balanced_quotes(tokens)
else
val = fetch_until(tokens, :on_sp)
end
val.length.times { tokens.shift }
val.map(&:last).join
end
def fetch_balanced_quotes(all_tokens)
tokens = []
open_count = 0
all_tokens.each do |token|
(row, col), type, str = token
case type
when :on_tstring_beg then open_count += 1
when :on_tstring_end then open_count -= 1
end
tokens << token
break if open_count == 0
end
tokens
end
def fetch_until(all_tokens, type)
tokens = []
all_tokens.each do |token|
break if token[TYPE_POSITION] == type
tokens << token
end
tokens
end
def true_attribute(key)
case options[:format]
when :xhtml
[:html, :attr, key, [:static, key]]
else
[:html, :attr, key, [:multi]]
end
end
end
end
end