mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
Make plain text parser better
This is very difficult for me to implement. Original implementation is Haml::Util in https://github.com/haml/haml. Thanks for MIT License.
This commit is contained in:
parent
773d1cf8f3
commit
2998f95ea5
4 changed files with 53 additions and 11 deletions
|
@ -1,4 +1,5 @@
|
|||
Copyright (c) 2015 Takashi Kokubun
|
||||
Copyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum
|
||||
|
||||
MIT License
|
||||
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
# NOTE: This compiler has an extremely bad effect for performance.
|
||||
require 'hamlit/concerns/string_literal'
|
||||
|
||||
# FIXME: This compiler has an extremely bad effect for performance.
|
||||
# We should optimize this.
|
||||
module Hamlit
|
||||
module Compilers
|
||||
module Text
|
||||
include Concerns::StringLiteral
|
||||
|
||||
def on_haml_text(exp)
|
||||
compile_text(exp)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# FIXME: This can't parse '!'
|
||||
def compile_text(exp)
|
||||
[:dynamic, "%Q!#{exp}!"]
|
||||
[:dynamic, string_literal(exp)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
44
lib/hamlit/concerns/string_literal.rb
Normal file
44
lib/hamlit/concerns/string_literal.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
module Hamlit
|
||||
module Concerns
|
||||
module StringLiteral
|
||||
def string_literal(str)
|
||||
unescape_interpolation(str)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def unescape_interpolation(str)
|
||||
res = ''
|
||||
rest = handle_interpolation(str.inspect) do |scan|
|
||||
escapes = (scan[2].size - 1) / 2
|
||||
res << scan.matched[0...-3 - escapes]
|
||||
if escapes % 2 == 1
|
||||
res << '#{'
|
||||
else
|
||||
content = eval('"' + balance(scan, ?{, ?}, 1)[0][0...-1] + '"')
|
||||
res << '#{' + content + '}'
|
||||
end
|
||||
end
|
||||
res + rest
|
||||
end
|
||||
|
||||
def handle_interpolation(str)
|
||||
scan = StringScanner.new(str)
|
||||
yield scan while scan.scan(/(.*?)(\\*)\#\{/)
|
||||
scan.rest
|
||||
end
|
||||
|
||||
def balance(scanner, start, finish, count = 0)
|
||||
str = ''
|
||||
scanner = StringScanner.new(scanner) unless scanner.is_a? StringScanner
|
||||
regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE)
|
||||
while scanner.scan(regexp)
|
||||
str << scanner.matched
|
||||
count += 1 if scanner.matched[-1] == start
|
||||
count -= 1 if scanner.matched[-1] == finish
|
||||
return [str.strip, scanner.rest] if count == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,11 +2,11 @@ describe Hamlit::Engine do
|
|||
describe 'text' do
|
||||
it 'renders string interpolation' do
|
||||
assert_render(<<-'HAML', <<-HTML)
|
||||
#{ "a#{3}a" }a" #{[1, 2]} b
|
||||
#{ "a#{3}a" }a" #{["1", 2]} b " !
|
||||
a#{{ a: 3 }}
|
||||
<ht#{2}ml>
|
||||
HAML
|
||||
a3aa" [1, 2] b
|
||||
a3aa" ["1", 2] b " !
|
||||
a{:a=>3}
|
||||
<ht2ml>
|
||||
HTML
|
||||
|
|
Loading…
Reference in a new issue