module HamlCoffeeAssets
  module ActionView
    class TemplateHandler
      def self.call(template)
        new(template).render
      end

      def initialize(template)
        @template = template
      end

      def render
        "ExecJS.compile(#{compilation_string}).eval(#{evaluation_string}).html_safe"
      end

      private

      def compilation_string
        (preamble + helpers + compiled_template).inspect
      end

      def evaluation_string
        string = "window.JST['#{@template.virtual_path}'](\#{local_assigns.to_json})"
        string.inspect.sub(/\\#/, "#")
      end

      def preamble
        "var window = {};\n"
      end

      def helpers
        ::HamlCoffeeAssets.helpers
      end

      def compiled_template
        ::HamlCoffeeAssets::Compiler.compile(
          @template.virtual_path,
          @template.source
        )
      end
    end
  end
end

module HamlCoffeeAssets
  module ActionView
    class TemplateHandler
      def self.call(template)
        new(template).render
      end

      def initialize(template, partial = false)
        @template = template
        @partial = partial
      end

      def render
        "ExecJS.compile(#{compilation_string}).eval(#{evaluation_string}).html_safe"
      end

      def compilation_string
        string = ""

        unless @partial
          string << preamble
          string << helpers
        end

        string << compiled_template

        if @partial
          string
        else
          string.inspect
        end
      end

      private

      def evaluation_string
        string = "window.JST['#{logical_path}'](\#{local_assigns.to_json})"
        string.inspect.sub(/\\#/, "#")
      end

      def preamble
        "var window = {};\n"
      end

      def helpers
        ::HamlCoffeeAssets.helpers
      end

      def compiled_template
        compiled = ::HamlCoffeeAssets::Compiler.compile(
          logical_path,
          @template.source
        )

        compiled.dup.scan(/window.JST\[["']([\w\/]+)["']\]/) do |match|
          path = match[0]

          next if path == logical_path

          partial = ::ActionView::Template.new(
            partial_source(path),
            path,
            self.class,
            :virtual_path => partial_path(path)
          )

          compiled << self.class.new(partial, true).compilation_string
        end

        compiled
      end

      def logical_path
        return @logical_path if defined?(@logical_path)

        path = @template.virtual_path.split("/")
        path.last.sub!(/^_/, "")
        @logical_path = path.join("/")
      end

      def partial_source(path)
        ::Rails.root.join(
          ::HamlCoffeeAssets.config.shared_template_path,
          partial_path(path) + ".hamlc"
        ).read
      end

      def partial_path(path)
        parts = path.split("/")
        parts[-1] = "_#{parts[-1]}"
        parts.join("/")
      end
    end
  end
end

Add support for server-side partials.
Add support for server-side partials.
