lesslateral 1.2.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG +62 -0
  3. data/LICENSE +179 -0
  4. data/README.md +48 -0
  5. data/Rakefile +52 -0
  6. data/VERSION +1 -0
  7. data/bin/lessc +103 -0
  8. data/less.gemspec +134 -0
  9. data/lib/less.rb +36 -0
  10. data/lib/less/command.rb +108 -0
  11. data/lib/less/engine.rb +52 -0
  12. data/lib/less/engine/grammar/common.tt +29 -0
  13. data/lib/less/engine/grammar/entity.tt +144 -0
  14. data/lib/less/engine/grammar/less.tt +341 -0
  15. data/lib/less/engine/nodes.rb +9 -0
  16. data/lib/less/engine/nodes/element.rb +281 -0
  17. data/lib/less/engine/nodes/entity.rb +79 -0
  18. data/lib/less/engine/nodes/function.rb +93 -0
  19. data/lib/less/engine/nodes/literal.rb +171 -0
  20. data/lib/less/engine/nodes/property.rb +232 -0
  21. data/lib/less/engine/nodes/ruleset.rb +12 -0
  22. data/lib/less/engine/nodes/selector.rb +44 -0
  23. data/lib/less/ext.rb +60 -0
  24. data/lib/less/notification.rb +59 -0
  25. data/spec/command_spec.rb +102 -0
  26. data/spec/css/accessors.css +18 -0
  27. data/spec/css/big.css +3768 -0
  28. data/spec/css/colors.css +14 -0
  29. data/spec/css/comments.css +9 -0
  30. data/spec/css/css-3.css +21 -0
  31. data/spec/css/css.css +50 -0
  32. data/spec/css/dash-prefix.css +12 -0
  33. data/spec/css/functions.css +6 -0
  34. data/spec/css/import-with-extra-paths.css +8 -0
  35. data/spec/css/import-with-partial-in-extra-path.css +6 -0
  36. data/spec/css/import.css +12 -0
  37. data/spec/css/lazy-eval.css +1 -0
  38. data/spec/css/mixins-args.css +32 -0
  39. data/spec/css/mixins.css +28 -0
  40. data/spec/css/operations.css +28 -0
  41. data/spec/css/parens.css +20 -0
  42. data/spec/css/rulesets.css +17 -0
  43. data/spec/css/scope.css +11 -0
  44. data/spec/css/selectors.css +13 -0
  45. data/spec/css/strings.css +12 -0
  46. data/spec/css/variables.css +8 -0
  47. data/spec/css/whitespace.css +7 -0
  48. data/spec/engine_spec.rb +127 -0
  49. data/spec/less/accessors.less +20 -0
  50. data/spec/less/big.less +1264 -0
  51. data/spec/less/colors.less +35 -0
  52. data/spec/less/comments.less +46 -0
  53. data/spec/less/css-3.less +52 -0
  54. data/spec/less/css.less +104 -0
  55. data/spec/less/dash-prefix.less +21 -0
  56. data/spec/less/exceptions/mixed-units-error.less +3 -0
  57. data/spec/less/exceptions/name-error-1.0.less +3 -0
  58. data/spec/less/exceptions/syntax-error-1.0.less +3 -0
  59. data/spec/less/extra_import_path/extra.less +1 -0
  60. data/spec/less/extra_import_path/import/import-test-a.css +1 -0
  61. data/spec/less/extra_import_path/import/import-test-a.less +4 -0
  62. data/spec/less/functions.less +6 -0
  63. data/spec/less/hidden.less +25 -0
  64. data/spec/less/import-with-extra-paths.less +4 -0
  65. data/spec/less/import.less +8 -0
  66. data/spec/less/import/import-test-a.less +2 -0
  67. data/spec/less/import/import-test-b.less +8 -0
  68. data/spec/less/import/import-test-c.less +7 -0
  69. data/spec/less/import/import-test-d.css +1 -0
  70. data/spec/less/lazy-eval.less +6 -0
  71. data/spec/less/literal-css.less +11 -0
  72. data/spec/less/mixins-args.less +59 -0
  73. data/spec/less/mixins.less +43 -0
  74. data/spec/less/operations.less +39 -0
  75. data/spec/less/parens.less +26 -0
  76. data/spec/less/rulesets.less +30 -0
  77. data/spec/less/scope.less +32 -0
  78. data/spec/less/selectors.less +24 -0
  79. data/spec/less/strings.less +14 -0
  80. data/spec/less/variables.less +29 -0
  81. data/spec/less/whitespace.less +34 -0
  82. data/spec/spec.css +50 -0
  83. data/spec/spec_helper.rb +8 -0
  84. metadata +159 -0
data/less.gemspec ADDED
@@ -0,0 +1,134 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{lesslateral}
8
+ s.version = "1.2.21"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["cloudhead"]
12
+ s.date = %q{2010-01-13}
13
+ s.default_executable = %q{lessc}
14
+ s.description = %q{LESS is leaner CSS}
15
+ s.email = %q{self@cloudhead.net}
16
+ s.executables = ["lessc"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".gitignore",
23
+ "CHANGELOG",
24
+ "LICENSE",
25
+ "README.md",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/lessc",
29
+ "less.gemspec",
30
+ "lib/less.rb",
31
+ "lib/less/command.rb",
32
+ "lib/less/engine.rb",
33
+ "lib/less/notification.rb",
34
+ "lib/less/engine/grammar/common.tt",
35
+ "lib/less/engine/grammar/entity.tt",
36
+ "lib/less/engine/grammar/less.tt",
37
+ "lib/less/engine/nodes.rb",
38
+ "lib/less/engine/nodes/element.rb",
39
+ "lib/less/engine/nodes/entity.rb",
40
+ "lib/less/engine/nodes/function.rb",
41
+ "lib/less/engine/nodes/literal.rb",
42
+ "lib/less/engine/nodes/property.rb",
43
+ "lib/less/engine/nodes/ruleset.rb",
44
+ "lib/less/engine/nodes/selector.rb",
45
+ "lib/less/ext.rb",
46
+ "spec/command_spec.rb",
47
+ "spec/css/accessors.css",
48
+ "spec/css/big.css",
49
+ "spec/css/colors.css",
50
+ "spec/css/comments.css",
51
+ "spec/css/css-3.css",
52
+ "spec/css/css.css",
53
+ "spec/css/dash-prefix.css",
54
+ "spec/css/functions.css",
55
+ "spec/css/import-with-extra-paths.css",
56
+ "spec/css/import-with-partial-in-extra-path.css",
57
+ "spec/css/import.css",
58
+ "spec/css/lazy-eval.css",
59
+ "spec/css/mixins-args.css",
60
+ "spec/css/mixins.css",
61
+ "spec/css/operations.css",
62
+ "spec/css/parens.css",
63
+ "spec/css/rulesets.css",
64
+ "spec/css/scope.css",
65
+ "spec/css/selectors.css",
66
+ "spec/css/strings.css",
67
+ "spec/css/variables.css",
68
+ "spec/css/whitespace.css",
69
+ "spec/engine_spec.rb",
70
+ "spec/less/accessors.less",
71
+ "spec/less/big.less",
72
+ "spec/less/colors.less",
73
+ "spec/less/comments.less",
74
+ "spec/less/css-3.less",
75
+ "spec/less/css.less",
76
+ "spec/less/dash-prefix.less",
77
+ "spec/less/exceptions/mixed-units-error.less",
78
+ "spec/less/exceptions/name-error-1.0.less",
79
+ "spec/less/exceptions/syntax-error-1.0.less",
80
+ "spec/less/extra_import_path/extra.less",
81
+ "spec/less/extra_import_path/import/import-test-a.css",
82
+ "spec/less/extra_import_path/import/import-test-a.less",
83
+ "spec/less/functions.less",
84
+ "spec/less/hidden.less",
85
+ "spec/less/import-with-extra-paths.less",
86
+ "spec/less/import.less",
87
+ "spec/less/import/import-test-a.less",
88
+ "spec/less/import/import-test-b.less",
89
+ "spec/less/import/import-test-c.less",
90
+ "spec/less/import/import-test-d.css",
91
+ "spec/less/lazy-eval.less",
92
+ "spec/less/literal-css.less",
93
+ "spec/less/mixins-args.less",
94
+ "spec/less/mixins.less",
95
+ "spec/less/operations.less",
96
+ "spec/less/parens.less",
97
+ "spec/less/rulesets.less",
98
+ "spec/less/scope.less",
99
+ "spec/less/selectors.less",
100
+ "spec/less/strings.less",
101
+ "spec/less/variables.less",
102
+ "spec/less/whitespace.less",
103
+ "spec/spec.css",
104
+ "spec/spec_helper.rb"
105
+ ]
106
+ s.homepage = %q{http://www.lesscss.org}
107
+ s.rdoc_options = ["--charset=UTF-8"]
108
+ s.require_paths = ["lib"]
109
+ s.rubyforge_project = %q{less}
110
+ s.rubygems_version = %q{1.3.5}
111
+ s.summary = %q{LESS compiler}
112
+ s.test_files = [
113
+ "spec/command_spec.rb",
114
+ "spec/engine_spec.rb",
115
+ "spec/spec_helper.rb"
116
+ ]
117
+
118
+ if s.respond_to? :specification_version then
119
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
120
+ s.specification_version = 3
121
+
122
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
123
+ s.add_runtime_dependency(%q<treetop>, [">= 1.4.2"])
124
+ s.add_runtime_dependency(%q<mutter>, [">= 0.4.2"])
125
+ else
126
+ s.add_dependency(%q<treetop>, [">= 1.4.2"])
127
+ s.add_dependency(%q<mutter>, [">= 0.4.2"])
128
+ end
129
+ else
130
+ s.add_dependency(%q<treetop>, [">= 1.4.2"])
131
+ s.add_dependency(%q<mutter>, [">= 0.4.2"])
132
+ end
133
+ end
134
+
data/lib/less.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'cgi'
2
+ require 'treetop'
3
+ require 'mutter'
4
+ require 'delegate'
5
+
6
+ LESS_ROOT = File.expand_path(File.dirname(__FILE__))
7
+ LESS_PARSER = File.join(LESS_ROOT, 'less', 'engine', 'parser.rb')
8
+ LESS_GRAMMAR = File.join(LESS_ROOT, 'less', 'engine', 'grammar')
9
+
10
+ $LESS_LOAD_PATH = []
11
+
12
+ $:.unshift File.dirname(__FILE__)
13
+
14
+ require 'less/ext'
15
+ require 'less/command'
16
+ require 'less/engine'
17
+
18
+ module Less
19
+ MixedUnitsError = Class.new(RuntimeError)
20
+ PathError = Class.new(RuntimeError)
21
+ VariableNameError = Class.new(NameError)
22
+ MixinNameError = Class.new(NameError)
23
+ SyntaxError = Class.new(RuntimeError)
24
+ ImportError = Class.new(RuntimeError)
25
+ CompileError = Class.new(RuntimeError)
26
+
27
+ $verbose = false
28
+
29
+ def self.version
30
+ File.read( File.join( File.dirname(__FILE__), '..', 'VERSION') ).strip
31
+ end
32
+
33
+ def self.parse less
34
+ Engine.new(less).to_css
35
+ end
36
+ end
@@ -0,0 +1,108 @@
1
+ module Less
2
+ class Command
3
+ attr_accessor :source, :destination, :options
4
+
5
+ def initialize options
6
+ $verbose = options[:debug]
7
+ @source = options[:source]
8
+ @destination = (options[:destination] || options[:source]).gsub /\.(less|lss)/, '.css'
9
+ @options = options
10
+ @mutter = Mutter.new.clear
11
+ end
12
+
13
+ def watch?() @options[:watch] end
14
+ def compress?() @options[:compress] end
15
+ def debug?() @options[:debug] end
16
+
17
+ # little function which allows us to
18
+ # Ctrl-C exit inside the passed block
19
+ def watch
20
+ begin
21
+ yield
22
+ rescue Interrupt
23
+ puts
24
+ exit 0
25
+ end
26
+ end
27
+
28
+ def run!
29
+ if watch?
30
+ parse(true) unless File.exist? @destination
31
+
32
+ log "Watching for changes in #@source... Ctrl-C to abort.\n: "
33
+
34
+ # Main watch loop
35
+ loop do
36
+ watch { sleep 1 }
37
+
38
+ # File has changed
39
+ if File.stat( @source ).mtime > File.stat( @destination ).mtime
40
+ print Time.now.strftime("%H:%M:%S -- ") if @options[:timestamps]
41
+ print "Change detected... "
42
+
43
+ # Loop until error is fixed
44
+ until parse
45
+ log "Press [return] to continue..."
46
+ watch { $stdin.gets }
47
+ end
48
+ end
49
+ end
50
+ else
51
+ parse
52
+ end
53
+ end
54
+
55
+ def parse new = false
56
+ begin
57
+ # Create a new Less object with the contents of a file
58
+ css = Less::Engine.new(File.new(@source), @options).to_css
59
+ css = css.delete " \n" if compress?
60
+
61
+ File.open( @destination, "w" ) do |file|
62
+ file.write css
63
+ end
64
+
65
+ act, file = (new ? 'Created' : 'Updated'), @destination.split('/').last
66
+ print "#{o("* #{act}", :green)} #{file}\n: " if watch?
67
+ # Growl.notify "#{act} #{file}", :title => 'LESS' if @options[:growl] && @options[:verbose]
68
+ Notifier.notify "#{act} #{file}", :title => 'LESS' if @options[:growl] && @options[:verbose]
69
+ rescue Errno::ENOENT => e
70
+ abort "#{e}"
71
+ rescue SyntaxError => e
72
+ err "#{e}\n", "Syntax"
73
+ rescue CompileError => e
74
+ err "#{e}\n", "Compile"
75
+ rescue MixedUnitsError => e
76
+ err "`#{e}` you're mixing units together! What do you expect?\n", "Mixed Units"
77
+ rescue PathError => e
78
+ err "`#{e}` was not found.\n", "Path"
79
+ rescue VariableNameError => e
80
+ err "#{o(e, :yellow)} is undefined.\n", "Variable Name"
81
+ rescue MixinNameError => e
82
+ err "#{o(e, :yellow)} is undefined.\n", "Mixin Name"
83
+ else
84
+ true
85
+ end
86
+ end
87
+
88
+ # Just a logging function to avoid typing '*'
89
+ def log s = ''
90
+ print '* ' + s.to_s
91
+ end
92
+
93
+ def err s = '', type = ''
94
+ type = type.strip + ' ' unless type.empty?
95
+ $stderr.print "#{o("! #{type}Error", :red)}: #{s}"
96
+ if @options[:growl]
97
+ Notifier.notify "#{type}Error in #@source!", :title => "LESS"
98
+ false
99
+ end
100
+ end
101
+
102
+ private
103
+
104
+ def o ex, *styles
105
+ @mutter.process(ex.to_s, *(@options[:color] ? styles : []))
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,52 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'engine/nodes'
4
+
5
+ begin
6
+ require 'engine/parser'
7
+ rescue LoadError
8
+ Treetop.load File.join(LESS_GRAMMAR, 'less.tt')
9
+ end
10
+
11
+ module Less
12
+ class Engine
13
+ attr_reader :css, :less
14
+
15
+ def initialize obj, options = {}
16
+ @less = if obj.is_a? File
17
+ @path = File.dirname File.expand_path(obj.path)
18
+ obj.read
19
+ elsif obj.is_a? String
20
+ obj.dup
21
+ else
22
+ raise ArgumentError, "argument must be an instance of File or String!"
23
+ end
24
+
25
+ @options = options
26
+ @parser = StyleSheetParser.new
27
+ end
28
+
29
+ def parse build = true, env = Node::Element.new
30
+ root = @parser.parse(self.prepare)
31
+
32
+ return root unless build
33
+
34
+ if root
35
+ @tree = root.build env.tap {|e| e.file = @path }
36
+ else
37
+ raise SyntaxError, @parser.failure_message(@options[:color])
38
+ end
39
+
40
+ @tree
41
+ end
42
+ alias :to_tree :parse
43
+
44
+ def to_css
45
+ @css || @css = self.parse.group.to_css
46
+ end
47
+
48
+ def prepare
49
+ @less.gsub(/\r\n/, "\n").gsub(/\t/, ' ')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,29 @@
1
+ module Less
2
+ module StyleSheet
3
+ grammar Common
4
+ #
5
+ # Whitespace
6
+ #
7
+ rule s
8
+ [ ]*
9
+ end
10
+
11
+ rule S
12
+ [ ]+
13
+ end
14
+
15
+ rule ws
16
+ [\n ]*
17
+ end
18
+
19
+ rule WS
20
+ [\n ]+
21
+ end
22
+
23
+ # Non-space char
24
+ rule ns
25
+ ![ ;,!})\n] .
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,144 @@
1
+ require 'grammar/common'
2
+
3
+ module Less
4
+ module StyleSheet
5
+ grammar Entity
6
+ #
7
+ # Entity: Any whitespace delimited token
8
+ #
9
+ rule entity
10
+ url / alpha / function / accessor / keyword / variable / literal / font
11
+ end
12
+
13
+ rule fonts
14
+ font family:(s ',' s font)+ {
15
+ def build
16
+ Node::FontFamily.new(all.map(&:build))
17
+ end
18
+
19
+ def all
20
+ [font] + family.elements.map {|f| f.font }
21
+ end
22
+ }
23
+ end
24
+
25
+ rule font
26
+ [a-zA-Z] [-a-zA-Z0-9]* !ns {
27
+ def build
28
+ Node::Keyword.new(text_value)
29
+ end
30
+ } / string {
31
+ def build
32
+ Node::Quoted.new(text_value)
33
+ end
34
+ }
35
+ end
36
+
37
+ #
38
+ # Tokens which don't need to be evaluated
39
+ #
40
+ rule literal
41
+ color / (dimension / [-a-z]+) '/' dimension {
42
+ def build
43
+ Node::Anonymous.new(text_value)
44
+ end
45
+ } / number unit {
46
+ def build
47
+ Node::Number.new(number.text_value, unit.text_value)
48
+ end
49
+ } / string {
50
+ def build
51
+ Node::Quoted.new(text_value)
52
+ end
53
+ }
54
+ end
55
+
56
+ #
57
+ # `blue`, `small`, `normal` etc.
58
+ #
59
+ rule keyword
60
+ [-a-zA-Z]+ !ns {
61
+ def build
62
+ Node::Keyword.new(text_value)
63
+ end
64
+ }
65
+ end
66
+
67
+ #
68
+ # 'hello world' / "hello world"
69
+ #
70
+ rule string
71
+ "'" content:(!"'" . )* "'" {
72
+ def value
73
+ content.text_value
74
+ end
75
+ } / ["] content:(!["] . )* ["] {
76
+ def value
77
+ content.text_value
78
+ end
79
+ }
80
+ end
81
+
82
+ #
83
+ # Numbers & Units
84
+ #
85
+ rule dimension
86
+ number unit
87
+ end
88
+
89
+ rule number
90
+ '-'? [0-9]* '.' [0-9]+ / '-'? [0-9]+
91
+ end
92
+
93
+ rule unit
94
+ ('px'/'em'/'pc'/'%'/'ex'/'in'/'deg'/'s'/'pt'/'cm'/'mm')?
95
+ end
96
+
97
+ #
98
+ # Color
99
+ #
100
+ rule color
101
+ '#' rgb {
102
+ def build
103
+ Node::Color.new(*rgb.build)
104
+ end
105
+ } / fn:(('hsl'/'rgb') 'a'?) arguments {
106
+ def build
107
+ Node::Function.new(fn.text_value, arguments.build.flatten)
108
+ end
109
+ }
110
+ end
111
+
112
+ #
113
+ # 00ffdd / 0fd
114
+ #
115
+ rule rgb
116
+ r:(hex hex) g:(hex hex) b:(hex hex) {
117
+ def build
118
+ [r.text_value, g.text_value, b.text_value]
119
+ end
120
+ } / r:hex g:hex b:hex {
121
+ def build
122
+ [r.text_value, g.text_value, b.text_value].map {|c| c * 2 }
123
+ end
124
+ }
125
+ end
126
+
127
+ rule hex
128
+ [a-fA-F0-9]
129
+ end
130
+
131
+ #
132
+ # Special case for IE alpha filter
133
+ #
134
+ rule alpha
135
+ "alpha" '(' "opacity=" variable ')' {
136
+ def build env
137
+ var = variable.text_value
138
+ Node::Quoted.new(text_value.sub(var, env.nearest(var).evaluate.to_i.to_s))
139
+ end
140
+ }
141
+ end
142
+ end
143
+ end
144
+ end