less 0.8.7 → 0.8.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -0
- data/Rakefile +20 -0
- data/VERSION +1 -1
- data/bin/lessc +0 -1
- data/less.gemspec +18 -3
- data/lib/less.rb +6 -3
- data/lib/less/command.rb +21 -14
- data/lib/less/engine.rb +19 -13
- data/lib/less/tree.rb +1 -1
- data/spec/command_spec.rb +106 -0
- data/spec/css/less-0.8.5.css +24 -0
- data/spec/css/less-0.8.6.css +24 -0
- data/spec/css/less-0.8.7.css +24 -0
- data/spec/css/less-0.8.8.css +25 -0
- data/spec/engine_spec.rb +35 -0
- data/spec/spec.css +25 -0
- data/spec/spec.less +4 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/tree_spec.rb +5 -0
- metadata +16 -4
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -38,4 +38,24 @@ begin
|
|
38
38
|
end
|
39
39
|
rescue LoadError
|
40
40
|
puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
|
41
|
+
end
|
42
|
+
|
43
|
+
begin
|
44
|
+
require 'spec/rake/spectask'
|
45
|
+
|
46
|
+
Spec::Rake::SpecTask.new("spec") do |t|
|
47
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
48
|
+
t.spec_opts = ['--color', '--format=specdoc']
|
49
|
+
end
|
50
|
+
|
51
|
+
task :test do
|
52
|
+
Rake::Task['spec'].invoke
|
53
|
+
end
|
54
|
+
|
55
|
+
Spec::Rake::SpecTask.new("rcov_spec") do |t|
|
56
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
57
|
+
t.spec_opts = ['--color']
|
58
|
+
t.rcov = true
|
59
|
+
t.rcov_opts = ['--exclude', '^spec,/gems/']
|
60
|
+
end
|
41
61
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.8
|
data/bin/lessc
CHANGED
data/less.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{less}
|
5
|
-
s.version = "0.8.
|
5
|
+
s.version = "0.8.8"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["cloudhead"]
|
9
|
-
s.date = %q{2009-06-
|
9
|
+
s.date = %q{2009-06-17}
|
10
10
|
s.default_executable = %q{lessc}
|
11
11
|
s.description = %q{LESS is leaner CSS}
|
12
12
|
s.email = %q{alexis@cloudhead.net}
|
@@ -27,7 +27,16 @@ Gem::Specification.new do |s|
|
|
27
27
|
"lib/less/command.rb",
|
28
28
|
"lib/less/engine.rb",
|
29
29
|
"lib/less/tree.rb",
|
30
|
-
"spec/
|
30
|
+
"spec/command_spec.rb",
|
31
|
+
"spec/css/less-0.8.5.css",
|
32
|
+
"spec/css/less-0.8.6.css",
|
33
|
+
"spec/css/less-0.8.7.css",
|
34
|
+
"spec/css/less-0.8.8.css",
|
35
|
+
"spec/engine_spec.rb",
|
36
|
+
"spec/spec.css",
|
37
|
+
"spec/spec.less",
|
38
|
+
"spec/spec_helper.rb",
|
39
|
+
"spec/tree_spec.rb"
|
31
40
|
]
|
32
41
|
s.has_rdoc = true
|
33
42
|
s.homepage = %q{http://www.lesscss.org}
|
@@ -36,6 +45,12 @@ Gem::Specification.new do |s|
|
|
36
45
|
s.rubyforge_project = %q{less}
|
37
46
|
s.rubygems_version = %q{1.3.1}
|
38
47
|
s.summary = %q{LESS compiler}
|
48
|
+
s.test_files = [
|
49
|
+
"spec/command_spec.rb",
|
50
|
+
"spec/engine_spec.rb",
|
51
|
+
"spec/spec_helper.rb",
|
52
|
+
"spec/tree_spec.rb"
|
53
|
+
]
|
39
54
|
|
40
55
|
if s.respond_to? :specification_version then
|
41
56
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
data/lib/less.rb
CHANGED
@@ -1,20 +1,23 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
1
3
|
require 'cgi'
|
2
4
|
|
3
5
|
require 'less/command'
|
4
6
|
require 'less/engine'
|
5
7
|
require 'less/tree'
|
6
8
|
|
7
|
-
module Less
|
9
|
+
module Less
|
8
10
|
MixedUnitsError = Class.new(Exception)
|
9
11
|
PathError = Class.new(Exception)
|
10
|
-
|
12
|
+
CompoundOperationError = Class.new(Exception)
|
13
|
+
|
11
14
|
def self.version
|
12
15
|
File.read( File.join( File.dirname(__FILE__), '..', 'VERSION') )
|
13
16
|
end
|
14
17
|
end
|
15
18
|
|
16
19
|
class Hash
|
17
|
-
# Convert a hash into a Tree
|
20
|
+
# Convert a hash into a Tree
|
18
21
|
def to_tree
|
19
22
|
Less::Tree.new self
|
20
23
|
end
|
data/lib/less/command.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
module Less
|
2
2
|
class Command
|
3
|
+
CSS = '.css'
|
4
|
+
|
5
|
+
attr_accessor :source, :destination, :options
|
6
|
+
|
3
7
|
def initialize options
|
4
|
-
@source
|
8
|
+
@source = options[:source]
|
9
|
+
@destination = (options[:destination] || options[:source]).gsub /\.(less|lss)/, CSS
|
5
10
|
@options = options
|
6
11
|
end
|
7
|
-
|
12
|
+
|
8
13
|
def watch?() @options[:watch] end
|
9
14
|
def compress?() @options[:compress] end
|
10
15
|
def debug?() @options[:debug] end
|
11
|
-
|
12
|
-
# little function which allows us to
|
16
|
+
|
17
|
+
# little function which allows us to
|
13
18
|
# Ctrl-C exit inside the passed block
|
14
19
|
def watch &block
|
15
20
|
begin
|
@@ -22,18 +27,18 @@ module Less
|
|
22
27
|
|
23
28
|
def run!
|
24
29
|
compile(true) unless File.exist? @destination
|
25
|
-
|
30
|
+
|
26
31
|
if watch?
|
27
32
|
log "Watching for changes in #@source ...Ctrl-C to abort.\n"
|
28
|
-
|
33
|
+
|
29
34
|
# Main watch loop
|
30
35
|
loop do
|
31
36
|
watch { sleep 1 }
|
32
|
-
|
37
|
+
|
33
38
|
# File has changed
|
34
39
|
if File.stat( @source ).mtime > File.stat( @destination ).mtime
|
35
40
|
log "Change detected... "
|
36
|
-
|
41
|
+
|
37
42
|
# Loop until error is fixed
|
38
43
|
until compile
|
39
44
|
log "Press [enter] to continue..."
|
@@ -45,13 +50,13 @@ module Less
|
|
45
50
|
compile
|
46
51
|
end
|
47
52
|
end
|
48
|
-
|
53
|
+
|
49
54
|
def compile new = false
|
50
55
|
begin
|
51
56
|
# Create a new Less object with the contents of a file
|
52
57
|
css = Less::Engine.new( File.read( @source ) ).to_css @options[:inheritance]
|
53
58
|
css = css.delete " \n" if compress?
|
54
|
-
|
59
|
+
|
55
60
|
File.open( @destination, "w" ) do |file|
|
56
61
|
file.write css
|
57
62
|
end
|
@@ -59,24 +64,26 @@ module Less
|
|
59
64
|
rescue Errno::ENOENT => e
|
60
65
|
abort "#{e}"
|
61
66
|
rescue SyntaxError
|
62
|
-
error = debug?? $! : $!.message.split("\n")[1..-1].collect {|e|
|
63
|
-
e.gsub(/\(eval\)\:(\d+)\:\s/, 'line \1: ')
|
67
|
+
error = debug?? $! : $!.message.split("\n")[1..-1].collect {|e|
|
68
|
+
e.gsub(/\(eval\)\:(\d+)\:\s/, 'line \1: ')
|
64
69
|
} * "\n"
|
65
70
|
err "errors were found in the .less file! \n#{error}\n"
|
66
71
|
rescue MixedUnitsError => e
|
67
72
|
err "`#{e}` you're mixing units together! What do you expect?\n"
|
73
|
+
rescue CompoundOperationError => e
|
74
|
+
err "`#{e}` operations in compound declarations aren't allowed, sorry!\n"
|
68
75
|
rescue PathError => e
|
69
76
|
err "`#{e}` was not found.\n"
|
70
77
|
else
|
71
78
|
true
|
72
79
|
end
|
73
80
|
end
|
74
|
-
|
81
|
+
|
75
82
|
# Just a logging function to avoid typing '}'
|
76
83
|
def log s = ''
|
77
84
|
print '* ' + s.to_s
|
78
85
|
end
|
79
|
-
|
86
|
+
|
80
87
|
def err s = ''
|
81
88
|
print "!! #{s}"
|
82
89
|
end
|
data/lib/less/engine.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
module Less
|
2
2
|
class Engine < String
|
3
|
+
# Compound properties, such as `border: 1px solid black`
|
4
|
+
COMPOUND = ['font', 'background', 'border']
|
3
5
|
REGEX = {
|
4
|
-
:path => /([#.][->#.\w ]+)?( ?> ?)
|
6
|
+
:path => /([#.][->#.\w ]+)?( ?> ?)?/, # #header > .title
|
5
7
|
:selector => /[-\w #.,>*:\(\)]/, # .cow .milk > a
|
6
8
|
:variable => /@([-\w]+)/, # @milk-white
|
7
9
|
:property => /@[-\w]+|[-a-z]+/, # font-size
|
@@ -65,8 +67,9 @@ module Less
|
|
65
67
|
# Evaluate operations (2+2)
|
66
68
|
#
|
67
69
|
# Units are: 1px, 1em, 1%, #111
|
68
|
-
@tree = @tree.traverse :leaf do |key, value, path, node|
|
70
|
+
@tree = @tree.traverse :leaf do |key, value, path, node|
|
69
71
|
node[ key ] = value.gsub /(#{REGEX[:operand]}(\s?)[-+\/*](\4))+(#{REGEX[:operand]})/ do |operation|
|
72
|
+
raise CompoundOperationError, "#{key}: #{value}" if COMPOUND.include? key # Disallow operations on compound declarations
|
70
73
|
if (unit = operation.scan(/#{REGEX[:numeric]}|(#)/i).flatten.compact.uniq).size <= 1
|
71
74
|
unit = unit.join
|
72
75
|
operation = if unit == '#'
|
@@ -95,26 +98,29 @@ module Less
|
|
95
98
|
#
|
96
99
|
# Evaluate variables
|
97
100
|
#
|
98
|
-
def evaluate key,
|
99
|
-
if
|
100
|
-
|
101
|
+
def evaluate key, expression, path, node
|
102
|
+
if expression.is_a? String and expression.include? '@' # There's a var to evaluate
|
103
|
+
expression.scan /#{REGEX[:path]}#{REGEX[:variable]}/ do |var|
|
104
|
+
name = var.last
|
101
105
|
var = var.join.delete ' '
|
102
|
-
|
103
|
-
|
106
|
+
|
107
|
+
value = if var.include? '>'
|
108
|
+
@tree.find :var, var.split('>') # Try finding it in a specific namespace
|
104
109
|
else
|
105
|
-
node.var(
|
110
|
+
node.var(var) or @tree.nearest var, path # Try local first, then nearest scope
|
106
111
|
end
|
107
|
-
|
108
|
-
if
|
109
|
-
|
112
|
+
|
113
|
+
if value
|
114
|
+
# Substitute variable with value
|
115
|
+
node[ key ] = node[ key ].gsub /#{REGEX[:path]}@#{name}/, value
|
110
116
|
else
|
111
|
-
node.delete key
|
117
|
+
node.delete key # Discard the declaration if the variable wasn't found
|
112
118
|
end
|
113
119
|
end
|
114
120
|
end
|
115
121
|
end
|
116
122
|
|
117
|
-
def to_css chain
|
123
|
+
def to_css chain = :desc
|
118
124
|
self.compile.to_css chain
|
119
125
|
end
|
120
126
|
|
data/lib/less/tree.rb
CHANGED
@@ -69,7 +69,7 @@ module Less
|
|
69
69
|
#
|
70
70
|
# Convert the tree to css, using full paths
|
71
71
|
#
|
72
|
-
def to_css chain
|
72
|
+
def to_css chain, css = []
|
73
73
|
self.traverse :branch do |path, node|
|
74
74
|
properties = node.inject("") do |s, (k, v)|
|
75
75
|
v.is_a?(String) ? (s + "#{k}: #{CGI.unescape(v)}; ") : s # Add the property to the list
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
module LessCommandSpecHelper
|
4
|
+
def required_options
|
5
|
+
{:source => File.dirname(__FILE__) + '/spec.less'}
|
6
|
+
end
|
7
|
+
|
8
|
+
def valid_options
|
9
|
+
{:destination => File.dirname(__FILE__) + '/spec.css', :watch => true, :chain => true, :debug => false}.merge(required_options)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Less::Command do
|
14
|
+
include LessCommandSpecHelper
|
15
|
+
|
16
|
+
describe "required options" do
|
17
|
+
before(:each) do
|
18
|
+
@command = Less::Command.new(required_options)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should set the source" do
|
22
|
+
@command.source.should == required_options[:source]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should set the destination using a gsub" do
|
26
|
+
@command.destination.should == valid_options[:destination]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should set the options with what was passed" do
|
30
|
+
@command.options.should == required_options
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "valid options" do
|
35
|
+
before(:each) do
|
36
|
+
@command = Less::Command.new(valid_options)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should set the @source" do
|
40
|
+
@command.source.should == required_options[:source]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should set the @destionation" do
|
44
|
+
@command.destination.should == valid_options[:destination]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should set the watch" do
|
48
|
+
@command.options[:watch].should == valid_options[:watch]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should set the chain" do
|
52
|
+
@command.options[:chain].should == valid_options[:chain]
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should set the debug" do
|
56
|
+
@command.options[:debug].should == valid_options[:debug]
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should set the options with what was passed" do
|
60
|
+
@command.options.should == valid_options
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "executing run!" do
|
65
|
+
before(:each) do
|
66
|
+
@command = Less::Command.new(required_options)
|
67
|
+
end
|
68
|
+
after(:each) do
|
69
|
+
@command.run!
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "when not watching" do
|
73
|
+
describe "and the destination file doesn't exist" do
|
74
|
+
before(:each) do
|
75
|
+
@command.stub!(:watch?).and_return(false)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should verify if we need to watch the file or not" do
|
79
|
+
@command.should_receive(:watch?).and_return(false)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should attempt to re-compile" do
|
83
|
+
@command.should_receive(:compile).with().once
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "and the destination file does exist" do
|
88
|
+
it "should not attempt to create a new file"
|
89
|
+
it "should attempt to re-compile"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "when watching" do
|
94
|
+
describe "and the destination file doesn't exist" do
|
95
|
+
it "should attempt to compile to a new file"
|
96
|
+
it "should begin to watch the file"
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "and the destination file does exist" do
|
100
|
+
it "should not attempt to compile to a new file"
|
101
|
+
it "should begin to watch the existing file"
|
102
|
+
it "should re-compile when the existing file changes"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
ul li:first-child { border-top: none; }
|
2
|
+
q:lang(no) { quotes: '~' '~'; }
|
3
|
+
.no-semi-column { color: orange; }
|
4
|
+
body { text-shadow: #333 -1px 1px 2px; border-color: #888; font-size: 10px; margin: -5px 0 5px 10px; background-color: #aaa; border: solid 1px #000; -moz-border-radius: 3px; font-family: 'Lucida Grande', 'Helvetica', Verdana, sans-serif; color: #ccc; }
|
5
|
+
td, tr, table { border-width: 4px; }
|
6
|
+
.space { color: purple; font-color: yellow; }
|
7
|
+
blockquote:before { color: red; }
|
8
|
+
.root > a:hover, a:focus { color: orange; }
|
9
|
+
.root > a { display: none; color: blue; }
|
10
|
+
.root > .first > .second > .third { border-color: blue; font-size: 8px; background-color: blue; color: red; }
|
11
|
+
.root > .first > .second { }
|
12
|
+
.root > .first { color: green; }
|
13
|
+
.root { }
|
14
|
+
.p:first-letter { color: red; }
|
15
|
+
.extra > .dark-borders { border-color: #444444; }
|
16
|
+
.extra > .light-borders { border-color: #888; }
|
17
|
+
.extra { }
|
18
|
+
ul li:first-child, ul li:last-child { background-color: #333; }
|
19
|
+
.borders { }
|
20
|
+
.root:hover a { display: block; }
|
21
|
+
.operations { colorb: #333333; font-size: 66; colorc: #777777; line-height: 7px; border-width: 16px; color: #eeeeee; }
|
22
|
+
:focus { outline: 0; content: '*}#f~ '; }
|
23
|
+
.theme { background-color: #aaa; color: #ccc; }
|
24
|
+
.transparent_box { opacity: 0.6; background-color: #FFF; filter: alpha(opacity=60); }
|
@@ -0,0 +1,24 @@
|
|
1
|
+
ul li:first-child { border-top: none; }
|
2
|
+
q:lang(no) { quotes: '~' '~'; }
|
3
|
+
.no-semi-column { color: orange; }
|
4
|
+
body { text-shadow: #333 -1px 1px 2px; border-color: #888; font-size: 10px; margin: -5px 0 5px 10px; background-color: #aaa; border: solid 1px #000; -moz-border-radius: 3px; font-family: 'Lucida Grande', 'Helvetica', Verdana, sans-serif; color: #ccc; }
|
5
|
+
td, tr, table { border-width: 4px; }
|
6
|
+
.space { color: purple; font-color: yellow; }
|
7
|
+
blockquote:before { color: red; }
|
8
|
+
.root a:hover, a:focus { color: orange; }
|
9
|
+
.root a { display: none; color: blue; }
|
10
|
+
.root .first .second .third { border-color: blue; font-size: 8px; background-color: blue; color: red; }
|
11
|
+
.root .first .second { }
|
12
|
+
.root .first { color: green; }
|
13
|
+
.root { }
|
14
|
+
.p:first-letter { color: red; }
|
15
|
+
.extra .dark-borders { border-color: #444444; }
|
16
|
+
.extra .light-borders { border-color: #888; }
|
17
|
+
.extra { }
|
18
|
+
ul li:first-child, ul li:last-child { background-color: #333; }
|
19
|
+
.borders { }
|
20
|
+
.root:hover a { display: block; }
|
21
|
+
.operations { colorb: #333333; font-size: 66; colorc: #777777; line-height: 7px; border-width: 16px; color: #eeeeee; }
|
22
|
+
:focus { outline: 0; content: '*}#f~ '; }
|
23
|
+
.theme { background-color: #aaa; color: #ccc; }
|
24
|
+
.transparent_box { opacity: 0.6; background-color: #FFF; filter: alpha(opacity=60); }
|
@@ -0,0 +1,24 @@
|
|
1
|
+
ul li:first-child { border-top: none; }
|
2
|
+
q:lang(no) { quotes: '~' '~'; }
|
3
|
+
.no-semi-column { color: orange; }
|
4
|
+
body { text-shadow: #333 -1px 1px 2px; border-color: #888; font-size: 10px; margin: -5px 0 5px 10px; background-color: #aaa; border: solid 1px #000; -moz-border-radius: 3px; font-family: 'Lucida Grande', 'Helvetica', Verdana, sans-serif; color: #ccc; }
|
5
|
+
td, tr, table { border-width: 4px; }
|
6
|
+
.space { color: purple; font-color: yellow; }
|
7
|
+
blockquote:before { color: red; }
|
8
|
+
.root a:hover, a:focus { color: orange; }
|
9
|
+
.root a { display: none; color: blue; }
|
10
|
+
.root .first .second .third { border-color: blue; font-size: 8px; background-color: blue; color: red; }
|
11
|
+
.root .first .second { }
|
12
|
+
.root .first { color: green; }
|
13
|
+
.root { }
|
14
|
+
.p:first-letter { color: red; }
|
15
|
+
.extra .dark-borders { border-color: #444444; }
|
16
|
+
.extra .light-borders { border-color: #888; }
|
17
|
+
.extra { }
|
18
|
+
ul li:first-child, ul li:last-child { background-color: #333; }
|
19
|
+
.borders { }
|
20
|
+
.root:hover a { display: block; }
|
21
|
+
.operations { colorb: #333333; font-size: 66; colorc: #777777; line-height: 7px; border-width: 16px; color: #eeeeee; }
|
22
|
+
:focus { outline: 0; content: '*}#f~ '; }
|
23
|
+
.theme { background-color: #aaa; color: #ccc; }
|
24
|
+
.transparent_box { opacity: 0.6; background-color: #FFF; filter: alpha(opacity=60); }
|
@@ -0,0 +1,25 @@
|
|
1
|
+
ul li:first-child { border-top: none; }
|
2
|
+
q:lang(no) { quotes: '~' '~'; }
|
3
|
+
.no-semi-column { color: orange; }
|
4
|
+
body { text-shadow: #333 -1px 1px 2px; border-color: #888; font-size: 10px; margin: -5px 0 5px 10px; background-color: #aaa; border: solid 1px #000; -moz-border-radius: 3px; font-family: 'Lucida Grande', 'Helvetica', Verdana, sans-serif; color: #ccc; }
|
5
|
+
td, tr, table { border-width: 4px; }
|
6
|
+
.space { color: purple; font-color: yellow; }
|
7
|
+
blockquote:before { color: red; }
|
8
|
+
.root a:hover, a:focus { color: orange; }
|
9
|
+
.root a { display: none; color: blue; }
|
10
|
+
.root .first .second .third { border-color: blue; font-size: 8px; background-color: blue; color: red; }
|
11
|
+
.root .first .second { }
|
12
|
+
.root .first { color: green; }
|
13
|
+
.root { }
|
14
|
+
.p:first-letter { color: red; }
|
15
|
+
.extra .dark-borders { border-color: #444444; }
|
16
|
+
.extra .light-borders { border-color: #888; }
|
17
|
+
.extra { }
|
18
|
+
ul li:first-child, ul li:last-child { background-color: #333; }
|
19
|
+
.borders { }
|
20
|
+
.root:hover a { display: block; }
|
21
|
+
.operations div { width: 80px; }
|
22
|
+
.operations { colorb: #333333; font-size: 66; colorc: #777777; line-height: 7px; border-width: 16px; color: #eeeeee; width: 110px; }
|
23
|
+
:focus { outline: 0; content: '*}#f~ '; }
|
24
|
+
.theme { background-color: #aaa; color: #ccc; }
|
25
|
+
.transparent_box { opacity: 0.6; background-color: #FFF; filter: alpha(opacity=60); }
|
data/spec/engine_spec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
module LessEngineSpecHelper
|
4
|
+
def lessify(string)
|
5
|
+
return Less::Engine.new(string).to_css(:desc)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Less::Engine do
|
10
|
+
include LessEngineSpecHelper
|
11
|
+
|
12
|
+
describe "to_css" do
|
13
|
+
it "should return p {} for p {}" do
|
14
|
+
lessify('p {}').should == 'p { }'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return css with variable usage" do
|
18
|
+
lessify("@brand_color: #4D926F;\n #header { color: @brand_color; }").should == "#header { color: #4D926F; }"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return css as shown on home page" do
|
22
|
+
lessify("#header { \n color: red;\n a {\n font-weight: bold;\n text-decoration: none;\n }\n}").should == "#header a { font-weight: bold; text-decoration: none; }\n#header { color: red; }"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should handle :hover" do
|
26
|
+
lessify("a:hover {\n color: red; }").should == "a:hover { color: red; }"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should handle instances of double-quotes" do
|
30
|
+
lessify("blockquote:before, blockquote:after, q:before, q:after {\n content: \"\"; }").should == "blockquote:before, blockquote:after, q:before, q:after { content: ''; }"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
data/spec/spec.css
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
.theme { color: #ccc; background-color: #aaa; }
|
2
|
+
.extra > .dark-borders { border-color: #444444; }
|
3
|
+
.extra > .light-borders { border-color: #888; }
|
4
|
+
.extra { }
|
5
|
+
.borders { }
|
6
|
+
.root > a { color: blue; display: none; }
|
7
|
+
.root > a:hover, a:focus { color: orange; }
|
8
|
+
.root > .first > .second > .third { background-color: blue; font-size: 8px; color: red; border-color: blue; }
|
9
|
+
.root > .first > .second { }
|
10
|
+
.root > .first { color: green; }
|
11
|
+
.root { }
|
12
|
+
.root:hover a { display: block; }
|
13
|
+
body { font-size: 10px; font-family: 'Lucida Grande', 'Helvetica', Verdana, sans-serif; margin: -5px 0 5px 10px; border: solid 1px #000; text-shadow: #333 -1px 1px 2px; -moz-border-radius: 3px; color: #ccc; background-color: #aaa; border-color: #888; }
|
14
|
+
.operations > div { width: 80px; }
|
15
|
+
.operations { width: 110px; border-width: 16px; font-size: 66; line-height: 7px; color: #eeeeee; colorb: #333333; colorc: #777777; }
|
16
|
+
td, tr, table { border-width: 4px; }
|
17
|
+
ul li:first-child { border-top: none; }
|
18
|
+
ul li:first-child, ul li:last-child { background-color: #333; }
|
19
|
+
.p:first-letter { color: red; }
|
20
|
+
:focus { outline: 0; content: '*}#f~ '; }
|
21
|
+
q:lang(no) { quotes: '~' '~'; }
|
22
|
+
blockquote:before { color: red; }
|
23
|
+
.transparent_box { background-color: #FFF; filter: alpha(opacity=60); opacity: 0.6; }
|
24
|
+
.space { color: purple; font-color: yellow; }
|
25
|
+
.no-semi-column { color: orange; }
|
data/spec/spec.less
CHANGED
@@ -74,6 +74,10 @@ body {
|
|
74
74
|
.operations {
|
75
75
|
@ten: 10;
|
76
76
|
@dark: #111;
|
77
|
+
@box: 100px;
|
78
|
+
@border_width: 10px;
|
79
|
+
width: @box + @border_width; // 110px
|
80
|
+
div { width: @box - 2 * @border_width; } // 80px
|
77
81
|
border-width: .borders > @thick * 5 - 4px; // 16px
|
78
82
|
font-size: 10 - 4 + 6 * @ten; // 66
|
79
83
|
line-height: @ten - .operations > @ten + .root > .first > @size - 1; // 7px
|
data/spec/spec_helper.rb
ADDED
data/spec/tree_spec.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: less
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- cloudhead
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-17 00:00:00 -04:00
|
13
13
|
default_executable: lessc
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -34,7 +34,16 @@ files:
|
|
34
34
|
- lib/less/command.rb
|
35
35
|
- lib/less/engine.rb
|
36
36
|
- lib/less/tree.rb
|
37
|
+
- spec/command_spec.rb
|
38
|
+
- spec/css/less-0.8.5.css
|
39
|
+
- spec/css/less-0.8.6.css
|
40
|
+
- spec/css/less-0.8.7.css
|
41
|
+
- spec/css/less-0.8.8.css
|
42
|
+
- spec/engine_spec.rb
|
43
|
+
- spec/spec.css
|
37
44
|
- spec/spec.less
|
45
|
+
- spec/spec_helper.rb
|
46
|
+
- spec/tree_spec.rb
|
38
47
|
has_rdoc: true
|
39
48
|
homepage: http://www.lesscss.org
|
40
49
|
post_install_message:
|
@@ -61,5 +70,8 @@ rubygems_version: 1.3.1
|
|
61
70
|
signing_key:
|
62
71
|
specification_version: 2
|
63
72
|
summary: LESS compiler
|
64
|
-
test_files:
|
65
|
-
|
73
|
+
test_files:
|
74
|
+
- spec/command_spec.rb
|
75
|
+
- spec/engine_spec.rb
|
76
|
+
- spec/spec_helper.rb
|
77
|
+
- spec/tree_spec.rb
|