lesslateral 1.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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