From 321758e62c472b677de9870bb74ddc7bd2db6f19 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Sun, 29 Mar 2015 03:15:46 +0900 Subject: [PATCH] Refactor filters --- lib/hamlit/compilers/filter.rb | 10 +- lib/hamlit/concerns/line_reader.rb | 12 +- lib/hamlit/filters/base.rb | 33 +++++ lib/hamlit/filters/css.rb | 23 +--- lib/hamlit/filters/javascript.rb | 14 +++ lib/hamlit/filters/plain.rb | 16 +-- lib/hamlit/filters/preserve.rb | 6 +- spec/hamlit/filters/javascript_spec.rb | 164 ++++++++++++------------- 8 files changed, 152 insertions(+), 126 deletions(-) create mode 100644 lib/hamlit/filters/base.rb create mode 100644 lib/hamlit/filters/javascript.rb diff --git a/lib/hamlit/compilers/filter.rb b/lib/hamlit/compilers/filter.rb index 813fa13e..e2321cbb 100644 --- a/lib/hamlit/compilers/filter.rb +++ b/lib/hamlit/compilers/filter.rb @@ -2,6 +2,7 @@ require 'hamlit/concerns/included' require 'hamlit/concerns/registerable' require 'hamlit/filters/css' require 'hamlit/filters/escaped' +require 'hamlit/filters/javascript' require 'hamlit/filters/plain' require 'hamlit/filters/preserve' @@ -13,10 +14,11 @@ module Hamlit included do extend Concerns::Registerable - register :css, Filters::Css - register :escaped, Filters::Escaped - register :plain, Filters::Plain - register :preserve, Filters::Preserve + register :css, Filters::Css + register :escaped, Filters::Escaped + register :javascript, Filters::Javascript + register :plain, Filters::Plain + register :preserve, Filters::Preserve end def on_haml_filter(name, lines) diff --git a/lib/hamlit/concerns/line_reader.rb b/lib/hamlit/concerns/line_reader.rb index 7f0d3dd4..79b5228f 100644 --- a/lib/hamlit/concerns/line_reader.rb +++ b/lib/hamlit/concerns/line_reader.rb @@ -30,17 +30,21 @@ module Hamlit end def read_lines - lines = [] - spaces = ' ' * (@current_indent * 2) + lines = [] while read_line? - lines << @lines[@current_lineno + 1].gsub(/\A#{spaces}/, '') + lines << @lines[@current_lineno + 1] @current_lineno += 1 end - lines + trim_lines(lines) end private + def trim_lines(lines) + size = (lines.first || '').index(/[^\s]/) || 0 + lines.map { |line| line.gsub(/\A {#{size}}/, '') } + end + def read_line? return true if count_indent(next_line, strict: false) >= @current_indent diff --git a/lib/hamlit/filters/base.rb b/lib/hamlit/filters/base.rb new file mode 100644 index 00000000..52e6d8e8 --- /dev/null +++ b/lib/hamlit/filters/base.rb @@ -0,0 +1,33 @@ +module Hamlit + module Filters + class Base + def compile(lines) + raise NotImplementedError + end + + private + + def compile_lines(lines, indent_width: 0) + base = (lines.first || '').index(/[^\s]/) || 0 + width = indent_width - base + width = 0 if width < 0 + + lines = strip_last(lines).map do |line| + ' ' * width + line + end + + text = lines.join("\n") + "\n" + text + end + + # NOTE: empty line is reserved for preserve filter. + def strip_last(lines) + lines = lines.dup + while lines.last && lines.last.length == 0 + lines.delete_at(-1) + end + lines + end + end + end +end diff --git a/lib/hamlit/filters/css.rb b/lib/hamlit/filters/css.rb index 6acc4eb3..d9ccb365 100644 --- a/lib/hamlit/filters/css.rb +++ b/lib/hamlit/filters/css.rb @@ -1,31 +1,14 @@ +require 'hamlit/filters/base' + module Hamlit module Filters - class Css + class Css < Base def compile(lines) ast = [:haml, :text, compile_lines(lines, indent_width: 2)] ast = [:multi, [:static, "\n"], ast] ast = [:html, :tag, 'style', [:html, :attrs], ast] ast end - - private - - def compile_lines(lines, indent_width: 0) - text = strip_last(lines).map { |line| - ' ' * indent_width + line - }.join("\n") - text += "\n" if text.length > 0 - text - end - - # NOTE: empty line is reserved for preserve filter. - def strip_last(lines) - lines = lines.dup - while lines.last && lines.last.length == 0 - lines.delete_at(-1) - end - lines - end end end end diff --git a/lib/hamlit/filters/javascript.rb b/lib/hamlit/filters/javascript.rb new file mode 100644 index 00000000..ee3aee83 --- /dev/null +++ b/lib/hamlit/filters/javascript.rb @@ -0,0 +1,14 @@ +require 'hamlit/filters/base' + +module Hamlit + module Filters + class Javascript < Base + def compile(lines) + ast = [:haml, :text, compile_lines(lines, indent_width: 2)] + ast = [:multi, [:static, "\n"], ast] + ast = [:html, :tag, 'script', [:html, :attrs], ast] + ast + end + end + end +end diff --git a/lib/hamlit/filters/plain.rb b/lib/hamlit/filters/plain.rb index f1421ced..f82d4ad7 100644 --- a/lib/hamlit/filters/plain.rb +++ b/lib/hamlit/filters/plain.rb @@ -1,11 +1,13 @@ +require 'hamlit/filters/base' + module Hamlit module Filters - class Plain + class Plain < Base def compile(lines) ast = [:multi] - text = strip_last(lines).join("\n") + text = compile_lines(lines) + text.gsub!(/\n\Z/, '') unless string_interpolated?(text) ast << [:haml, :text, text] - ast << [:static, "\n"] if string_interpolated?(text) ast end @@ -14,14 +16,6 @@ module Hamlit def string_interpolated?(text) text =~ /\#{[^\#{}]*}/ end - - def strip_last(lines) - lines = lines.dup - while lines.last && lines.last.length == 0 - lines.delete_at(-1) - end - lines - end end end end diff --git a/lib/hamlit/filters/preserve.rb b/lib/hamlit/filters/preserve.rb index ab2ad8a5..8ec30101 100644 --- a/lib/hamlit/filters/preserve.rb +++ b/lib/hamlit/filters/preserve.rb @@ -1,12 +1,8 @@ -require 'hamlit/helpers' - module Hamlit module Filters class Preserve def compile(lines) - ast = [:multi] - ast << [:haml, :text, lines.join(' ')] - ast + [:multi, [:haml, :text, lines.join(' ')]] end end end diff --git a/spec/hamlit/filters/javascript_spec.rb b/spec/hamlit/filters/javascript_spec.rb index e2b59db8..11ecdcbe 100644 --- a/spec/hamlit/filters/javascript_spec.rb +++ b/spec/hamlit/filters/javascript_spec.rb @@ -1,82 +1,82 @@ -# describe Hamlit::Filters::Javascript do -# describe '#compile' do -# it 'just renders script tag for empty filter' do -# assert_render(<<-HAML, <<-HTML) -# before -# :javascript -# after -# HAML -# before -# -# after -# HTML -# end -# -# it 'compiles javascript filter' do -# assert_render(<<-HAML, <<-HTML) -# before -# :javascript -# alert('hello'); -# after -# HAML -# before -# -# after -# HTML -# end -# -# it 'accepts illegal indentation' do -# assert_render(<<-HAML, <<-HTML) -# :javascript -# if { -# alert('hello'); -# } -# :javascript -# if { -# alert('hello'); -# } -# HAML -# -# -# HTML -# end -# -# it 'accepts illegal indentation' do -# assert_render(<<-HAML, <<-HTML) -# :javascript -# if { -# alert('a'); -# } -# HAML -# -# HTML -# end -# -# it 'parses string interpolation' do -# assert_render(<<-'HAML', <<-HTML) -# :javascript -# var a = #{[1, 2]}; -# HAML -# -# HTML -# end -# end -# end +describe Hamlit::Filters::Javascript do + describe '#compile' do + it 'just renders script tag for empty filter' do + assert_render(<<-HAML, <<-HTML) + before + :javascript + after + HAML + before + + after + HTML + end + + it 'compiles javascript filter' do + assert_render(<<-HAML, <<-HTML) + before + :javascript + alert('hello'); + after + HAML + before + + after + HTML + end + + it 'accepts illegal indentation' do + assert_render(<<-HAML, <<-HTML) + :javascript + if { + alert('hello'); + } + :javascript + if { + alert('hello'); + } + HAML + + + HTML + end + + it 'accepts illegal indentation' do + assert_render(<<-HAML, <<-HTML) + :javascript + if { + alert('a'); + } + HAML + + HTML + end + + it 'parses string interpolation' do + assert_render(<<-'HAML', <<-HTML) + :javascript + var a = #{[1, 2]}; + HAML + + HTML + end + end +end