Skip to content
This repository has been archived by the owner on Dec 24, 2020. It is now read-only.

Commit

Permalink
Transfering from logandk/more. Changing contributor attributions in R…
Browse files Browse the repository at this point in the history
…EADME and license.
  • Loading branch information
logandk committed Sep 13, 2009
1 parent 90997b8 commit 984ffdd
Show file tree
Hide file tree
Showing 13 changed files with 392 additions and 0 deletions.
20 changes: 20 additions & 0 deletions MIT-LICENSE
@@ -0,0 +1,20 @@
Copyright (c) 2009 Logan Raarup, August Lilleaas

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Empty file removed README
Empty file.
107 changes: 107 additions & 0 deletions README.markdown
@@ -0,0 +1,107 @@
`more`: LESS in Rails apps
==========================

**LESS** is a great gem that extends the standard CSS syntax with lots of good stuff. If you are not already using it, take
a look at [http://lesscss.org](http://lesscss.org).

By default, **LESS** does not include any Rails specific functionality, which is why you need this Rails plugin. The usage of
the plugin is very simple and you don't even need to change any of your code. The plugin does the following:

* Recursively looks for **LESS** (.less) files in `app/stylesheets`
* Ignores partials (prefixed with underscore: `_partial.less`) - these can be included with `@import` in your **LESS** files
* Saves the resulting CSS files to `public/stylesheets` using the same directory structure as `app/stylesheets`

Of course all this can be configured, see *Configuration* below.


Installation
============

As a Rails Plugin
-----------------

Use this to install as a plugin in a Ruby on Rails app:

$ script/plugin install git://github.com/cloudhead/more.git


As a Rails Plugin (using git submodules)
----------------------------------------

Use this if you prefer the idea of being able to easily switch between using edge or a tagged version:

$ git submodule add git://github.com/cloudhead/more.git vendor/plugins/more
$ script/runner vendor/plugins/more/install.rb


Usage
=====

When you have installed this plugin, a new directory will be created in `app/stylesheets`. Put your **LESS** files in
this directory and they will automatically be parsed on the next request.

Any **LESS** file in `app/stylesheets` will be parsed to an equivalent **CSS** file in `public/stylesheets`. Example:

app/stylesheets/clients/screen.less => public/stylesheets/clients/screen.css

If you prefix a file with an underscore, it is considered to be a partial, and will not be parsed unless included in another
file. Example:

<file: app/stylesheets/clients/partials/_form.less>
@text_dark: #222;

<file: app/stylesheets/clients/screen.less>
@import "partials/_form";

input { color: @text_dark; }


Configuration
-------------

If you want to configure `more` in a specific environment, put these configuration into the environment file, such
as `config/environments/development.rb`. If you wish to apply the configuration to all environments, put them in `config/environment.rb`.

To set the source path (the location of your **LESS** files)

Less::More.source_path = "/path/to/less/files"

To set the destination path (the location of the parsed **CSS** files)

Less::More.destination_path = "/path/to/css/files"

`more` can compress your files by removing extra line breaks. This is enabled by default in the `production` environment. To change
this setting, set

Less::More.compression = true


Tasks
=====

`more` provides a couple of Rake tasks to help manage your CSS files.

To parse all LESS files and save the resulting CSS files to the destination path, run

$ rake more:parse

To delete all generated CSS files, run

$ rake more:clean

This task will not delete any CSS files from the destination path, that does not have a corresponding LESS file in
the source path


Documentation
=============

To view the full RDoc documentation, go to [http://rdoc.info/projects/cloudhead/more](http://rdoc.info/projects/cloudhead/more)

For more information about LESS, see [http://lesscss.org](http://lesscss.org)


Contributors
============
* August Lilleaas
* Logan Raarup
23 changes: 23 additions & 0 deletions Rakefile
@@ -0,0 +1,23 @@
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'

desc 'Default: run unit tests.'
task :default => :test

desc 'Test the more plugin.'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end

desc 'Generate documentation for the more plugin.'
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'More'
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.rdoc_files.include('README.markdown')
rdoc.rdoc_files.include('lib/**/*.rb')
end
14 changes: 14 additions & 0 deletions init.rb
@@ -0,0 +1,14 @@
begin
require 'less'
rescue LoadError => e
e.message << " (You may need to install the less gem)"
raise e
end

require File.join(File.dirname(__FILE__), 'lib', 'more')

if Rails.env == "production"
config.after_initialize { Less::More.parse }
else
ActionController::Base.before_filter { Less::More.parse }
end
4 changes: 4 additions & 0 deletions install.rb
@@ -0,0 +1,4 @@
require "fileutils"
include FileUtils::Verbose

mkdir_p File.join(Rails.root, "app", "stylesheets")
115 changes: 115 additions & 0 deletions lib/more.rb
@@ -0,0 +1,115 @@
# Less::More provides methods for parsing LESS files in a rails application to CSS target files.
#
# When Less::More.parse is called, all files in Less::More.source_path will be parsed using LESS
# and saved as CSS files in Less::More.destination_path. If Less::More.compression is set to true,
# extra line breaks will be removed to compress the CSS files.
#
# By default, Less::More.parse will be called for each request in `development` environment and on
# application initialization in `production` environment.

class Less::More
class << self

attr_accessor_with_default :compression, (Rails.env == "production" ? true : false)

# Returns true if compression is enabled. By default, compression is enabled in the production environment
# and disabled in the development and test environments. This value can be changed using:
#
# Less::More.compression = true
#
# You can put this line into config/environments/development.rb to enable compression for the development environments
def compression?
self.compression
end

# Returns the LESS source path, see `source_path=`
def source_path
@source_path || Rails.root.join("app", "stylesheets")
end

# Sets the source path for LESS files. This directory will be scanned recursively for all *.less files. Files prefixed
# with an underscore is considered to be partials and are not parsed directly. These files can be included using `@import`
# statements. *Example partial filename: _form.less*
#
# Default value is app/stylesheets
#
# Examples:
# Less::More.source_path = "/path/to/less/files"
# Less::More.source_path = Pathname.new("/other/path")
def source_path=(path)
@source_path = Pathname.new(path.to_s)
end

# Returns the destination path for the parsed CSS files, see `destination_path=`
def destination_path
@destination_path || Rails.root.join("public", "stylesheets")
end

# Sets the destination path for the parsed CSS files. The directory structure from the source path will be retained, and
# all files, except partials prefixed with underscore, will be available with a .css extension.
#
# Default value is public/stylesheets
#
# Examples:
# Less::More.destination_path = "/path/to/css/files"
# Less::More.destination_path = Pathname.new("/other/path")
def destination_path=(path)
@destination_path = Pathname.new(path.to_s)
end

# Returns a collection of matching files in the source path, which will be parsed.
#
# Example:
# Less::More.map => [{ :source => #<Pathname:...>, :destination => #<Pathname:...> }, ...]
def map
files = Pathname.glob(self.source_path.join("**", "*.less")).reject { |f| f.basename.to_s.starts_with? "_" }

files.collect! do |file|
relative_path = file.relative_path_from(self.source_path)
{ :source => file, :destination => self.destination_path.join(relative_path.dirname, relative_path.basename(relative_path.extname).to_s + ".css") }
end
end

# Performs the core functionality of passing the LESS files from the source path through LESS and outputting CSS files to
# the destination path. The LESS files will only be parsed if the CSS file is not present, or if the modification time of
# the LESS file or any of its included files are newer than the CSS files. Imported files are recursively checked for updated
# modification times.
#
# If `compression` is enabled, extra line breaks will be removed.
#
# Example:
# Less::More.parse
def parse
self.map.each do |file|
file[:destination].dirname.mkpath unless file[:destination].dirname.exist?

modified = self.read_imports(file[:source]).push(file[:source]).max { |x, y| x.mtime <=> y.mtime }.mtime

if !file[:destination].exist? || modified > file[:destination].mtime
css = Less::Engine.new(file[:source].open).to_css
css = css.delete " \n" if self.compression?

file[:destination].open("w") { |f| f.write css }
end
end
end

# Recusively reads import statement from less files and returns an array of `Pathname`. It also checks that
# the files are present in the filesystem.
#
# Example:
# p = Pathname.new("/path/to/file")
# Less::More.read_imports(p) => [#<Pathname:/path/to/include1>, #<Pathname:/path/to/include2>, ...]
def read_imports(file)
imports = file.read.scan(/@import\s+(['"])(.*?)\1/i)

imports.collect! do |v|
path = file.dirname.join(v.last + ".less")
path.exist? ? self.read_imports(path).push(path) : nil
end

imports.flatten.compact.uniq
end

end
end
36 changes: 36 additions & 0 deletions tasks/more_tasks.rake
@@ -0,0 +1,36 @@
require 'less'
require File.join(File.dirname(__FILE__), '..', 'lib', 'more')

namespace :more do
desc "Generate CSS files from LESS files"
task :parse => :environment do
files = Less::More.parse

puts "Successfully parsed files:"

files.each do |f|
puts " - " + f[:source].relative_path_from(Less::More.source_path).to_s
end

puts "\nSaved to: " + Less::More.destination_path.to_s
end

desc "Remove generated CSS files"
task :clean => :environment do
files = Less::More.map

puts "Deleting files:"

files.each do |f|
if f[:destination].exist?
puts " - " + f[:destination]
f[:destination].delete

if f[:destination].parent.children.empty? and f[:destination].parent != Less::More.destination_path
puts " - " + f[:destination].parent
f[:destination].parent.delete
end
end
end
end
end
2 changes: 2 additions & 0 deletions test/less_files/_global.less
@@ -0,0 +1,2 @@
@text_light: #ffffff;
@text_dark: #222222;
3 changes: 3 additions & 0 deletions test/less_files/shared/_form.less
@@ -0,0 +1,3 @@
.allforms {
font-size: 110%;
}
11 changes: 11 additions & 0 deletions test/less_files/test.less
@@ -0,0 +1,11 @@
@import "_global";
@import "shared/_form";

body {
color: @text_dark;
}

form {
.allforms;
color: @text_light;
}
40 changes: 40 additions & 0 deletions test/more_test.rb
@@ -0,0 +1,40 @@
require 'test_helper'

class MoreTest < Test::Unit::TestCase
def test_compression
Less::More.compression = true
assert_equal Less::More.compression?, true

Less::More.compression = false
assert_equal Less::More.compression?, false
end

def test_source_path
Less::More.source_path = "/path/to/flaf"
assert_equal Less::More.source_path, Pathname.new("/path/to/flaf")
end

def test_destination_path
Less::More.destination_path = "/path/to/flaf"
assert_equal Less::More.destination_path, Pathname.new("/path/to/flaf")
end

def test_map
Less::More.source_path = File.join(File.dirname(__FILE__), 'less_files')
Less::More.destination_path = File.join(File.dirname(__FILE__), 'css_files')

assert_equal Less::More.map, [{ :source => Less::More.source_path.join("test.less"), :destination => Less::More.destination_path.join("test.css") }]
end

def test_parse
Less::More.source_path = File.join(File.dirname(__FILE__), 'less_files')
Less::More.destination_path = File.join(File.dirname(__FILE__), 'css_files')
Less::More.compression = true

Less::More.parse

assert_equal Less::More.destination_path.join("test.css").read, ".allforms{font-size:110%;}body{color:#222222;}form{font-size:110%;color:#ffffff;}"

Less::More.destination_path.join("test.css").delete
end
end

0 comments on commit 984ffdd

Please sign in to comment.