From d2ed383d86a6520d740be786f3302815d123c948 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Mon, 30 Mar 2015 17:16:32 +0900 Subject: [PATCH] Accept string interpolation in sass filter --- lib/hamlit/compilers/text.rb | 10 ++---- ...ing_literal.rb => string_interpolation.rb} | 6 +++- lib/hamlit/filters/base.rb | 11 +++++-- lib/hamlit/filters/sass.rb | 18 +++------- lib/hamlit/filters/tilt.rb | 33 +++++++++++++++++++ spec/hamlit/filters/sass_spec.rb | 18 ++++++++++ 6 files changed, 70 insertions(+), 26 deletions(-) rename lib/hamlit/concerns/{string_literal.rb => string_interpolation.rb} (92%) create mode 100644 lib/hamlit/filters/tilt.rb diff --git a/lib/hamlit/compilers/text.rb b/lib/hamlit/compilers/text.rb index 87586f24..67f47425 100644 --- a/lib/hamlit/compilers/text.rb +++ b/lib/hamlit/compilers/text.rb @@ -1,21 +1,15 @@ -require 'hamlit/concerns/string_literal' +require 'hamlit/concerns/string_interpolation' module Hamlit module Compilers module Text - include Concerns::StringLiteral + include Concerns::StringInterpolation def on_haml_text(exp) return [:static, exp] unless contains_interpolation?(exp) [:dynamic, string_literal(exp)] end - - private - - def contains_interpolation?(str) - /#[\{$@]/ === str - end end end end diff --git a/lib/hamlit/concerns/string_literal.rb b/lib/hamlit/concerns/string_interpolation.rb similarity index 92% rename from lib/hamlit/concerns/string_literal.rb rename to lib/hamlit/concerns/string_interpolation.rb index 44e0c61c..24cd2164 100644 --- a/lib/hamlit/concerns/string_literal.rb +++ b/lib/hamlit/concerns/string_interpolation.rb @@ -1,10 +1,14 @@ module Hamlit module Concerns - module StringLiteral + module StringInterpolation def string_literal(str) unescape_interpolation(str) end + def contains_interpolation?(str) + /#[\{$@]/ === str + end + private def unescape_interpolation(str) diff --git a/lib/hamlit/filters/base.rb b/lib/hamlit/filters/base.rb index d20aad00..34e5d044 100644 --- a/lib/hamlit/filters/base.rb +++ b/lib/hamlit/filters/base.rb @@ -3,7 +3,12 @@ module Hamlit class Base attr_reader :options - def initialize(options) + def self.indent_source(source, indent_width: 0) + lines = source.split("\n") + self.new.compile_lines(lines, indent_width: indent_width) + end + + def initialize(options = {}) @options = options end @@ -11,8 +16,6 @@ module Hamlit raise NotImplementedError end - private - def compile_lines(lines, indent_width: 0) base = (lines.first || '').index(/[^\s]/) || 0 width = indent_width - base @@ -26,6 +29,8 @@ module Hamlit text end + private + # NOTE: empty line is reserved for preserve filter. def strip_last(lines) lines = lines.dup diff --git a/lib/hamlit/filters/sass.rb b/lib/hamlit/filters/sass.rb index f856ce0b..6b974748 100644 --- a/lib/hamlit/filters/sass.rb +++ b/lib/hamlit/filters/sass.rb @@ -1,21 +1,11 @@ -require 'tilt' -require 'hamlit/filters/base' +require 'hamlit/filters/tilt' module Hamlit module Filters - class Sass < Base + class Sass < Filters::Tilt def compile(lines) - result = compile_with_tilt(lines) - content = [:multi, [:static, "\n"], result] - [:html, :tag, 'style', [:html, :attrs], content] - end - - private - - def compile_with_tilt(lines) - source = lines.join("\n") - result = ::Tilt['t.sass'].new { source }.render - [:static, compile_lines(result.split("\n"), indent_width: 2)] + ast = [:html, :tag, 'style', [:html, :attrs]] + compile_with_tilt('sass', lines.join("\n"), ast) end end end diff --git a/lib/hamlit/filters/tilt.rb b/lib/hamlit/filters/tilt.rb new file mode 100644 index 00000000..3d1c6d47 --- /dev/null +++ b/lib/hamlit/filters/tilt.rb @@ -0,0 +1,33 @@ +require 'tilt' +require 'hamlit/concerns/string_interpolation' +require 'hamlit/filters/base' + +module Hamlit + module Filters + class Tilt < Filters::Base + include Concerns::StringInterpolation + + def self.render(name, source) + result = ::Tilt["t.#{name}"].new { source }.render + indent_source(result, indent_width: 2) + end + + private + + def compile_with_tilt(name, source, ast) + return runtime_compile(name, source, ast) if contains_interpolation?(source) + + result = [:static, Filters::Tilt.render(name, source)] + content = [:multi, [:static, "\n"], result] + ast << content + end + + def runtime_compile(name, source, ast) + literal = string_literal(source) + code = "::Hamlit::Filters::Tilt.render(#{name.inspect}, #{literal})" + content = [:multi, [:static, "\n"], [:dynamic, code]] + ast << content + end + end + end +end diff --git a/spec/hamlit/filters/sass_spec.rb b/spec/hamlit/filters/sass_spec.rb index ff169878..d1666bac 100644 --- a/spec/hamlit/filters/sass_spec.rb +++ b/spec/hamlit/filters/sass_spec.rb @@ -15,5 +15,23 @@ describe Hamlit::Filters::Sass do HTML end + + it 'renders sass filter with string interpolation' do + assert_render(<<-'HAML', <<-HTML) + - width = 1200 + - height = 800 + :sass + .users_controller + .show_action + width: #{width}px + height: #{height}px + HAML + + HTML + end end end