require "coffee-rails-source-maps/version" # Based on https://gist.github.com/naan/5096056 # config/initializers/source_maps.rb if Rails.env.development? require 'coffee-script' #make sure CoffeeScript is loaded before we overwrite it. module CoffeeScript class << self def compile(script, options = {}) script = script.read if script.respond_to?(:read) if options.key?(:no_wrap) && !options.key?(:bare) options[:bare] = options[:no_wrap] else options[:bare] = false end pathname = options[:pathname] if pathname.nil? return Source.context.call("CoffeeScript.compile", script, options) else clean_name = pathname.basename.to_s.split(".").first rel_path = if pathname.to_s.start_with?(Bundler.bundle_path.to_s) Pathname('bundler').join(pathname.relative_path_from(Bundler.bundle_path)).dirname else pathname.relative_path_from(Rails.root).dirname end map_dir = Rails.root.join("public/" + Rails.configuration.assets.prefix, "source_maps", rel_path) map_dir.mkpath map_file = map_dir.join("#{clean_name}.map") coffee_file = map_dir.join("#{clean_name}.coffee") options[:sourceMap] = true options[:filename] = "#{clean_name}.coffee" # coffee requires filename option to work with source maps (see http://coffeescript.org/documentation/docs/coffee-script.html#section-4) options[:sourceFiles] = ["/#{coffee_file.relative_path_from(Rails.root.join("public"))}"] # specify coffee source file explicitly (see http://coffeescript.org/documentation/docs/sourcemap.html#section-8) wrapper = <<-WRAPPER (function(script, options) { try { return CoffeeScript.compile(script, options); } catch (err) { if (err instanceof SyntaxError && err.location) { throw new SyntaxError([options.filename, err.location.first_line + 1, err.location.first_column + 1].join(":") + ": " + err.message) } else { throw err; } } }) WRAPPER file_path = "var sourcePath='#{pathname.basename}';\n" ret = Source.context.call(wrapper, file_path + script, options) coffee_file.open('w') {|f| f.puts script } map_file.open('w') {|f| f.puts ret["v3SourceMap"]} comment = "//# sourceMappingURL=/#{map_file.relative_path_from(Rails.root.join("public"))}\n" # This will add file source that can be used in directives or controllers return ret['js'] + comment end end end end # Monkeypatch this method to include the scripts' pathname require 'tilt/coffee' module Tilt class CoffeeScriptTemplate < Template def evaluate(scope, locals, &block) pathname = scope.respond_to?(:pathname) ? scope.pathname : nil @output ||= CoffeeScript.compile(data, options.merge(:pathname => pathname)) end end end end