xdissent-less 0.8.12
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/LICENSE +179 -0
- data/README.md +30 -0
- data/Rakefile +61 -0
- data/VERSION +1 -0
- data/bin/lessc +72 -0
- data/less.gemspec +67 -0
- data/lib/less/command.rb +95 -0
- data/lib/less/engine.rb +154 -0
- data/lib/less/tree.rb +82 -0
- data/lib/less.rb +24 -0
- data/spec/command_spec.rb +106 -0
- data/spec/css/less-0.8.10.css +30 -0
- data/spec/css/less-0.8.11.css +31 -0
- data/spec/css/less-0.8.12.css +28 -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 +39 -0
- data/spec/spec.css +29 -0
- data/spec/spec.less +149 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/tree_spec.rb +5 -0
- metadata +80 -0
data/lib/less/tree.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
module Less
|
2
|
+
class Tree < Hash
|
3
|
+
def initialize init = {}
|
4
|
+
self.replace init
|
5
|
+
end
|
6
|
+
|
7
|
+
def var k
|
8
|
+
self[:variables] ? self[:variables][ k ] : nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def vars?
|
12
|
+
self.include? :variables
|
13
|
+
end
|
14
|
+
|
15
|
+
def vars
|
16
|
+
self[:variables] ? self[:variables] : nil
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Find a variable or mixin from a specific path
|
21
|
+
#
|
22
|
+
def find what = :var, path = []
|
23
|
+
path.inject(self) do |branch, k|
|
24
|
+
if what == :var && k == path.last
|
25
|
+
branch[:variables][ k ]
|
26
|
+
else
|
27
|
+
branch = branch[ k ] or raise PathError, path.join(' > ')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Find the nearest variable in the hierarchy
|
34
|
+
#
|
35
|
+
def nearest var, path
|
36
|
+
values = []
|
37
|
+
path.inject(self) do |branch, k|
|
38
|
+
values << branch.var( var )
|
39
|
+
branch[ k ]
|
40
|
+
end
|
41
|
+
values.compact.last
|
42
|
+
end
|
43
|
+
|
44
|
+
def traverse by = :leaf, path = [], &blk
|
45
|
+
#
|
46
|
+
# Traverse the whole tree, returning each leaf or branch (recursive)
|
47
|
+
#
|
48
|
+
###
|
49
|
+
# Aside from the key & value, we yield the full path of the leaf,
|
50
|
+
# aswell as the branch which contains it (self).
|
51
|
+
# Note that in :branch mode, we only return 'twigs', branches which contain leaves.
|
52
|
+
#
|
53
|
+
self.each do |key, value| # `self` is the current node, starting with the trunk
|
54
|
+
if value.is_a? Hash and key != :variables # If the node is a branch, we can go deeper
|
55
|
+
path << key # Add the current branch to the path
|
56
|
+
yield path, self[ key ] if by == :branch # The node is a branch, yield it to the block
|
57
|
+
self[ key ] = value.to_tree. # Make sure any change is saved to the main tree
|
58
|
+
traverse by, path, &blk # Recurse, with the current node becoming `self`
|
59
|
+
path.pop # We're returning from a branch, pop the last path element
|
60
|
+
elsif by == :leaf and key.is_a? String
|
61
|
+
yield key, value, path, self # The node is a leaf, yield it to the block
|
62
|
+
else
|
63
|
+
next
|
64
|
+
end
|
65
|
+
end
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Convert the tree to css, using full paths
|
71
|
+
#
|
72
|
+
def to_css chain, css = []
|
73
|
+
self.traverse :branch do |path, node|
|
74
|
+
properties = node.inject("") do |s, (k, v)|
|
75
|
+
v.is_a?(String) ? (s + "#{k}: #{CGI.unescape(v)}; ") : s # Add the property to the list
|
76
|
+
end
|
77
|
+
css << path * ( chain == :desc ? ' ' : ' > ') + " { " + properties + "}" unless properties.empty? # Add the rule-set to the CSS
|
78
|
+
end
|
79
|
+
css.join "\n"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/less.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
require 'less/command'
|
6
|
+
require 'less/engine'
|
7
|
+
require 'less/tree'
|
8
|
+
|
9
|
+
module Less
|
10
|
+
MixedUnitsError = Class.new(Exception)
|
11
|
+
PathError = Class.new(Exception)
|
12
|
+
CompoundOperationError = Class.new(Exception)
|
13
|
+
|
14
|
+
def self.version
|
15
|
+
File.read( File.join( File.dirname(__FILE__), '..', 'VERSION') )
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Hash
|
20
|
+
# Convert a hash into a Tree
|
21
|
+
def to_tree
|
22
|
+
Less::Tree.new self
|
23
|
+
end
|
24
|
+
end
|
@@ -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,30 @@
|
|
1
|
+
ul li:first-child { border-top: none; }
|
2
|
+
.duplicate { color: blue; width: 11px; }
|
3
|
+
q:lang(no) { quotes: '~' '~'; }
|
4
|
+
.no-semi-column { color: orange; }
|
5
|
+
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; }
|
6
|
+
td, tr, table { border-width: 4px; }
|
7
|
+
div > a, a span { color: grey; }
|
8
|
+
.space { color: purple; font-color: yellow; }
|
9
|
+
blockquote:before { color: red; }
|
10
|
+
.root a:hover, a:focus { color: orange; }
|
11
|
+
.root a { display: none; color: blue; }
|
12
|
+
.root .first .second .third { border-color: blue; font-size: 8px; background-color: blue; color: red; }
|
13
|
+
.root .first .second { }
|
14
|
+
.root .first { color: green; }
|
15
|
+
.root { }
|
16
|
+
.p:first-letter { color: red; }
|
17
|
+
.extra .dark-borders { border-color: #444444; }
|
18
|
+
.extra .light-borders { border-color: #888; }
|
19
|
+
.extra { }
|
20
|
+
a:link, a:hover { color: brown; }
|
21
|
+
ul li:first-child, ul li:last-child { background-color: #333; }
|
22
|
+
div { color: purple; }
|
23
|
+
.borders { }
|
24
|
+
.root:hover a { display: block; }
|
25
|
+
.operations div { width: 80px; }
|
26
|
+
.operations { colorb: #333333; font-size: 66; colorc: #777777; line-height: 7px; border-width: 16px; color: #eeeeee; font: 12px/16px; width: 110px; }
|
27
|
+
:focus { outline: 0; content: '*}#f~ '; }
|
28
|
+
.theme { background-color: #aaa; color: #ccc; }
|
29
|
+
blockquote:before, blockquote:after, q:before, q:after { content: ''; }
|
30
|
+
.transparent_box { opacity: 0.6; background-color: #FFF; filter: alpha(opacity=60); }
|
@@ -0,0 +1,31 @@
|
|
1
|
+
ul li:first-child { border-top: none; }
|
2
|
+
.duplicate { color: blue; width: 11px; }
|
3
|
+
q:lang(no) { quotes: '~' '~'; }
|
4
|
+
.no-semi-column { color: orange; }
|
5
|
+
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; }
|
6
|
+
td, tr, table { border-width: 4px; }
|
7
|
+
div > a, a span { color: grey; }
|
8
|
+
.space { color: purple; font-color: yellow; }
|
9
|
+
blockquote:before { color: red; }
|
10
|
+
.root a:hover, a:focus { color: orange; }
|
11
|
+
.root a { display: none; color: blue; }
|
12
|
+
.root .first .second .third { border-color: blue; font-size: 8px; background-color: blue; color: red; }
|
13
|
+
.root .first .second { }
|
14
|
+
.root .first { color: green; }
|
15
|
+
.root { }
|
16
|
+
.p:first-letter { color: red; }
|
17
|
+
.extra .dark-borders { border-color: #444444; }
|
18
|
+
.extra .light-borders { border-color: #888; }
|
19
|
+
.extra { }
|
20
|
+
a:link, a:hover { color: brown; }
|
21
|
+
ul li:first-child, ul li:last-child { background-color: #333; }
|
22
|
+
div { color: purple; }
|
23
|
+
input[type='text'] { background-color: blue; }
|
24
|
+
.borders { }
|
25
|
+
.root:hover a { display: block; }
|
26
|
+
.operations div { width: 80px; }
|
27
|
+
.operations { colorb: #333333; font-size: 66; colorc: #777777; line-height: 7px; border-width: 16px; color: #eeeeee; font: 12px/16px; width: 110px; }
|
28
|
+
:focus { outline: 0; content: '*}#f~ '; }
|
29
|
+
.theme { background-color: #aaa; color: #ccc; }
|
30
|
+
blockquote:before, blockquote:after, q:before, q:after { content: ''; }
|
31
|
+
.transparent_box { opacity: 0.6; background-color: #FFF; filter: alpha(opacity=60); }
|
@@ -0,0 +1,28 @@
|
|
1
|
+
ul li:first-child { border-top: none; }
|
2
|
+
h5:focus { outline: 0; content: '*}#f~ '; }
|
3
|
+
.duplicate { color: blue; width: 11px; }
|
4
|
+
body, div > p a, h2 a > span:first-child { font-family: sans-serif; }
|
5
|
+
q:lang(no) { quotes: '~' '~'; }
|
6
|
+
.no-semi-column { color: orange; }
|
7
|
+
body { text-shadow: #333 -1px 1px 2px; font-size: 10px; margin: -5px 0 5px 10px; background-color: #aaa; border: solid 1px #000; font-family: 'Lucida Grande', 'Helvetica', Verdana, sans-serif; -moz-border-radius: 3px; color: #ccc; }
|
8
|
+
td, tr, table { border-width: 88px; }
|
9
|
+
div > a, a span { color: grey; }
|
10
|
+
.space { color: purple; font-color: yellow; }
|
11
|
+
blockquote:before { color: red; }
|
12
|
+
#operations { font-size: 66; colorb: #333333; colorc: #777777; color: #eeeeee; font: 12px/16px; width: 110px; }
|
13
|
+
#operations div { width: 80px; }
|
14
|
+
.root a:hover, a:focus { color: orange; }
|
15
|
+
.root a { display: none; color: blue; }
|
16
|
+
.root .first { color: green; }
|
17
|
+
.root .first .second .third { font-size: 8px; border-color: red; background-color: blue; color: red; }
|
18
|
+
.p:first-letter { color: red; }
|
19
|
+
.extra .dark-borders { border-color: #444444; }
|
20
|
+
.extra .light-borders { border-color: #888; }
|
21
|
+
a:link, a:hover { color: brown; }
|
22
|
+
ul li:first-child, ul li:last-child { background-color: #333; }
|
23
|
+
div { color: purple; }
|
24
|
+
input[type='text'] { background-color: blue; }
|
25
|
+
.root:hover a { display: block; }
|
26
|
+
.theme { background-color: #aaa; color: #ccc; }
|
27
|
+
blockquote:before, blockquote:after, q:before, q:after { content: ''; }
|
28
|
+
.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,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; font: 12px/16px; 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,39 @@
|
|
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 an empty string for p {}" do
|
14
|
+
lessify('p {}').should == ''
|
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 { color: red; }\n#header a { font-weight: bold; text-decoration: none; }"
|
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
|
+
|
33
|
+
it "should parse tag attributes" do
|
34
|
+
lessify("input[type=text] { color: red; }").should == "input[type=text] { color: red; }"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
data/spec/spec.css
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
.theme { color: #ccc; background-color: #aaa; }
|
2
|
+
.extra > .dark-borders { border-color: #444444; }
|
3
|
+
.extra > .light-borders { border-color: #888; }
|
4
|
+
body, div > p a, h2 a > span:first-child { font-family: sans-serif; }
|
5
|
+
.root > a { color: blue; display: none; }
|
6
|
+
.root > a:hover, a:focus { color: orange; }
|
7
|
+
.root > .first { color: green; }
|
8
|
+
.root > .first > .second > .third { background-color: blue; font-size: 8px; color: red; border-color: red; }
|
9
|
+
.root:hover a { display: block; }
|
10
|
+
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; }
|
11
|
+
#operations { font: 12px/16px; width: 110px; font-size: 66; color: #eeeeee; colorb: #333333; colorc: #777777; }
|
12
|
+
#operations > div { width: 80px; }
|
13
|
+
td, tr, table { border-width: 88px; }
|
14
|
+
blockquote:before, blockquote:after, q:before, q:after { content: ''; }
|
15
|
+
a:link, a:hover { color: brown; }
|
16
|
+
div > a, a span { color: grey; }
|
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
|
+
h5:focus { outline: 0; content: '*}#f~ '; }
|
21
|
+
q:lang(no) { quotes: '~' '~'; }
|
22
|
+
blockquote:before { color: red; }
|
23
|
+
div { color: purple; }
|
24
|
+
.duplicate { width: 11px; color: blue; }
|
25
|
+
.loading { background: 'http://'; }
|
26
|
+
input[type='text'] { background-color: blue; }
|
27
|
+
.transparent_box { background-color: #FFF; filter: alpha(opacity=60); opacity: 0.6; }
|
28
|
+
.space { color: purple; font-color: yellow; }
|
29
|
+
.no-semi-column { color: orange; }
|
data/spec/spec.less
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
// ------------------------------------------------
|
2
|
+
// LESS Spec
|
3
|
+
// www.lesscss.org
|
4
|
+
// ------------------------------------------------
|
5
|
+
|
6
|
+
// Global vars
|
7
|
+
@main-color: #444;
|
8
|
+
@dark-color: #111;
|
9
|
+
@between-color: @main-color - @dark-color;
|
10
|
+
|
11
|
+
// Mixins
|
12
|
+
.theme {
|
13
|
+
color: #ccc;
|
14
|
+
background-color: #aaa;
|
15
|
+
}
|
16
|
+
.extra {
|
17
|
+
@main: #888;
|
18
|
+
.dark-borders {
|
19
|
+
border-color: @main / 2;
|
20
|
+
}
|
21
|
+
.light-borders {
|
22
|
+
border-color: @main;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
// Complex Selectors
|
27
|
+
body, div > p a, h2 a > span:first-child {
|
28
|
+
font-family: sans-serif;
|
29
|
+
}
|
30
|
+
|
31
|
+
// Hierarchy
|
32
|
+
.root {
|
33
|
+
a {
|
34
|
+
color: blue;
|
35
|
+
display: none;
|
36
|
+
}
|
37
|
+
a:hover, a:focus {
|
38
|
+
color: orange;
|
39
|
+
}
|
40
|
+
.first {
|
41
|
+
@size: 8px;
|
42
|
+
@dark-color: green;
|
43
|
+
@main-color: red;
|
44
|
+
color: @dark-color; // 'green'
|
45
|
+
.second {
|
46
|
+
@color: blue;
|
47
|
+
.third {
|
48
|
+
background-color: @color; // blue
|
49
|
+
font-size: @size; // 8px
|
50
|
+
color: @main-color; // red
|
51
|
+
border-color: @main-color; // 'red'
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
.root:hover a {
|
57
|
+
display: block;
|
58
|
+
}
|
59
|
+
|
60
|
+
// Standard CSS properties and shorthand
|
61
|
+
body {
|
62
|
+
font-size: 10px;
|
63
|
+
font-family: "Lucida Grande", 'Helvetica', Verdana, sans-serif;
|
64
|
+
margin: -5px 0 5px 10px;
|
65
|
+
border: solid 1px #000;
|
66
|
+
text-shadow: #333 -1px 1px 2px;
|
67
|
+
-moz-border-radius: 3px; /* CSS3 for older Firefox */
|
68
|
+
.theme;
|
69
|
+
}
|
70
|
+
|
71
|
+
// Operations
|
72
|
+
#operations {
|
73
|
+
@ten: 10;
|
74
|
+
@dark: #111;
|
75
|
+
@box: 100px;
|
76
|
+
@border_width: 10px;
|
77
|
+
font: 12px/16px; // 12px/16px
|
78
|
+
width: @box + @border_width; // 110px
|
79
|
+
div { width: @box - 2 * @border_width; } // 80px
|
80
|
+
font-size: 10 - 4 + 6 * @ten; // 66
|
81
|
+
color: #fff - #111; // #eeeeee
|
82
|
+
colorb: #111 + #222222; // #333333
|
83
|
+
colorc: @dark + #222 * 3; // #777777
|
84
|
+
}
|
85
|
+
|
86
|
+
td, tr, table {
|
87
|
+
border-width: 88px;
|
88
|
+
}
|
89
|
+
|
90
|
+
// More complex CSS selectors
|
91
|
+
blockquote:before, blockquote:after, q:before, q:after { content: ""; }
|
92
|
+
a:link,
|
93
|
+
a:hover {
|
94
|
+
color:brown;
|
95
|
+
}
|
96
|
+
div > a, a span {
|
97
|
+
color: grey;
|
98
|
+
}
|
99
|
+
ul li:first-child {
|
100
|
+
border-top: none;
|
101
|
+
}
|
102
|
+
ul li:first-child, ul li:last-child {
|
103
|
+
background-color: #333;
|
104
|
+
}
|
105
|
+
.p:first-letter {
|
106
|
+
color: red;
|
107
|
+
}
|
108
|
+
h5:focus {
|
109
|
+
outline: 0;
|
110
|
+
content: "*}#f~ ";
|
111
|
+
}
|
112
|
+
q:lang(no) {
|
113
|
+
quotes: "~" "~";
|
114
|
+
}
|
115
|
+
blockquote:before {
|
116
|
+
color: red;
|
117
|
+
}
|
118
|
+
|
119
|
+
// Duplicates
|
120
|
+
div {
|
121
|
+
width: 9px;
|
122
|
+
}
|
123
|
+
div {
|
124
|
+
color: purple;
|
125
|
+
}
|
126
|
+
.duplicate {
|
127
|
+
width: 9px;
|
128
|
+
height: 11px;
|
129
|
+
}
|
130
|
+
.duplicate {
|
131
|
+
width: 11px;
|
132
|
+
color: blue;
|
133
|
+
}
|
134
|
+
.loading { background: "http://"; }
|
135
|
+
input[type="text"] {
|
136
|
+
background-color: blue;
|
137
|
+
}
|
138
|
+
.transparent_box {
|
139
|
+
background-color:#FFF;
|
140
|
+
filter:alpha(opacity=60); /* for IE */
|
141
|
+
opacity:0.6; /* CSS3 standard */
|
142
|
+
}
|
143
|
+
|
144
|
+
// Spacing
|
145
|
+
.space
|
146
|
+
{ color: purple ;font-color:yellow; }
|
147
|
+
|
148
|
+
// No semi-column
|
149
|
+
.no-semi-column { color: orange }
|
data/spec/spec_helper.rb
ADDED