class Guard::Less
Public Class Methods
new(options = {})
click to toggle source
Calls superclass method
# File lib/guard/less.rb, line 8 def initialize(options = {}) defaults = { all_after_change: true, all_on_start: true, output: nil, import_paths: [], compress: false, patterns: [], yuicompress: false } super(defaults.merge(options)) end
Public Instance Methods
run(paths)
click to toggle source
# File lib/guard/less.rb, line 40 def run(paths) directories = nested_directory_map(paths) directories.each do |destination, stylesheets| stylesheets.each do |lessfile| # Skip partials basename = File.basename(lessfile) next if basename[0, 1] == '_' cssfile = File.join(destination, basename.gsub(/\.less$/, '.css')) # Just in case if cssfile == lessfile Compat::UI.info "Guard::Less: Skipping #{lessfile} since output and source are the same" elsif mtime(cssfile) >= mtime_including_imports(lessfile) Compat::UI.info "Guard::Less: Skipping #{lessfile} because #{cssfile} is already up-to-date" else Compat::UI.info "Guard::Less: #{lessfile} -> #{cssfile}\n" FileUtils.mkdir_p(File.expand_path(destination)) compile(lessfile, cssfile) end end end end
run_all()
click to toggle source
Call with Ctrl-/ signal This method should be principally used for long action like running all specs/tests/…
# File lib/guard/less.rb, line 28 def run_all Compat::UI.info 'Guard::Less: compiling all files' files = Dir.glob('**/*.*') paths = Compat.matching_files(self, files).uniq run(paths) end
run_on_changes(paths)
click to toggle source
Call on file(s) modifications
# File lib/guard/less.rb, line 36 def run_on_changes(paths) options[:all_after_change] ? run_all : run(paths) end
start()
click to toggle source
# File lib/guard/less.rb, line 21 def start Compat::UI.info "Guard::Less #{LessVersion::VERSION} is on the job!" run_all if options[:all_on_start] end
Private Instance Methods
compile(lessfile, cssfile)
click to toggle source
Parse the source lessfile and write to target cssfile
# File lib/guard/less.rb, line 68 def compile(lessfile, cssfile) import_paths = options[:import_paths].unshift(File.dirname(lessfile)) parser = ::Less::Parser.new paths: import_paths, filename: lessfile File.open(lessfile, 'r') do |infile| File.open(cssfile, 'w') do |outfile| tree = parser.parse(infile.read) outfile << tree.to_css(compress: options[:compress], yuicompress: options[:yuicompress]) end end true rescue StandardError => e Compat::UI.info "Guard::Less: Compiling #{lessfile} failed with message: #{e.message}" false end
mtime(file)
click to toggle source
mtime checking borrowed from the old official LESS Rails plugin:
https://github.com/cloudhead/more
# File lib/guard/less.rb, line 107 def mtime(file) return 0 unless File.file?(file) File.mtime(file).to_i end
mtime_including_imports(file)
click to toggle source
consider imports for mtime just 1 level deep so we do not get any looping/nesting errors
# File lib/guard/less.rb, line 114 def mtime_including_imports(file) mtimes = [mtime(file)] File.readlines(file).each do |line| next unless line =~ /^\s*@import ['"]([^'"]+)/ imported = File.join(File.dirname(file), Regexp.last_match[1]) # complete path given ? mod_time = if imported =~ /\.le?ss$/ mtime(imported) else # we need to add .less or .lss [mtime("#{imported}.less"), mtime("#{imported}.lss")].max end mtimes << mod_time end mtimes.max end
nested_directory_map(paths)
click to toggle source
Creates a hash of changed files keyed by their target nested directory, which is based on either the original source directory or the :output option, plus the regex match group in a watcher like:
%r{^app/stylesheets/(.+\.less)$}
# File lib/guard/less.rb, line 88 def nested_directory_map(paths) directories = {} options[:patterns].product(paths).each do |pattern, path| next unless (matches = path.match(pattern)) target = options[:output] || File.dirname(path) if (subpath = matches[1]) target = File.join(target, File.dirname(subpath)).gsub(/\/\.$/, '') end (directories[target] ||= []) << path end directories end