Skip to content

Instantly share code, notes, and snippets.

@metaskills
Created November 15, 2011 21:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save metaskills/1368396 to your computer and use it in GitHub Desktop.
Save metaskills/1368396 to your computer and use it in GitHub Desktop.
Failed ImportProcessor
module Less
module Rails
class ImportProcessor < Tilt::Template
IMPORT_SCANNER = /@import\s*['"]([^'"]+)['"]\s*;/.freeze
def prepare
end
def evaluate(context, locals, &block)
import_paths = data.scan(IMPORT_SCANNER).flatten.compact.uniq
import_paths.each do |path|
context.depend_on(path)
end
data
end
end
end
end
it 'must register our import processor' do
dummy_assets.bundle_processors['text/css'].must_include Less::Rails::ImportProcessor
end
initializer 'less-rails.before.load_config_initializers', :before => 'load_config_initializers', :group => :all do |app|
raise 'The less-rails plugin requires the asset pipeline to be enabled.' unless app.config.assets.enabled
app.assets.register_bundle_processor 'text/css', ImportProcessor
end
@metaskills
Copy link
Author

Possible method chain hackery?

  def self.register_rails_patches
    tree = @loader.require('less/tree')
    return if tree[:Import][:prototype][:toCSSWithOutLessRails]
    tree[:Import][:prototype][:toCSSWithOutLessRails] = tree[:Import][:prototype][:toCSS].dup
    tree[:Import][:prototype][:toCSS] = lambda do
      STDOUT.puts 'toCSSWithLessRails'
      tree[:Import][:prototype][:toCSSWithOutLessRails].call
    end
  end

@cowboyd
Copy link

cowboyd commented Nov 15, 2011

def self.register_rails_patches
    prototype = @loader.require('less/tree')[:Import].prototype
    return if prototype.toCSSWithOutLessRails
    prototype.toCSSWithOutLessRails = prototype.toCSS
    prototype.toCSS = lambda do |options|
      STDOUT.puts 'toCSSWithLessRails'
      prototype.toCSSWithOutLessRails.call(options)
    end
  end

@metaskills
Copy link
Author

Was just playing with this to see if I could override tree.Import constructor.

tree = {};

tree.Import = function (path, imports) {
  this.foo = 'bar';
};

tree.Import.prototype = {
  toCSS: function () {
    if (this.css) {
      return "this.css"
    } else {
      return "";
    }
  },
  eval: function (env) {
    return "origEval";
  }
};


tree.Import.ConstructorWithOutRails = tree.Import;
tree.Import = function (path, imports) {
  this.lessRails = true;
  tree.Import.ConstructorWithOutRails.apply(this, arguments);
}
t = new tree.Import;
t.lessRails

@metaskills
Copy link
Author

Was looking at this article about overriding constructor. Does not appear something that JS like to do. http://www.webdeveloper.com/forum/showthread.php?t=243971

@metaskills
Copy link
Author

Another good idea of @cowboyd's was to use the Fs#readFile method that made Less think it was using node still. Tho I could get a method chain in, I see no way of determining the root asset reading the file to attach the dependency on attribute path. Code was as follows.

module Less
  module Rails
    class Loader

      module Fs

        def self.included(base)
          base.class_eval do
            include InstanceMethods
            alias_method :readFileWithoutRails, :readFile
            alias_method :readFile, :readFileWithRails
          end
        end

        module InstanceMethods

          def readFileWithRails(path, encoding, callback)
            STDOUT.puts "\n\nreadFileWithRails:"
            STDOUT.puts({:path => path, :encoding => encoding, :callback => callback.class, :self => self}.inspect)
            readFileWithoutRails(path, encoding, callback)
          end

        end

      end

    end
  end
end

Less::Loader::Fs.send :include, Less::Rails::Loader::Fs

@metaskills
Copy link
Author

OK, a pre-processor does it

module Less  
  module Rails    
    class ImportProcessor < Tilt::Template

      IMPORT_SCANNER = /@import\s*['"]([^'"]+)['"]\s*;/.freeze

      def prepare
      end

      def evaluate(context, locals, &block)
        import_paths = data.scan(IMPORT_SCANNER).flatten.compact.uniq
        import_paths.each do |path|
          asset = context.environment[path]
          if asset && asset.pathname.to_s.ends_with?('.less')
            context.depend_on(asset.pathname)
          end
        end
        data
      end

    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment