less 2.1.0 → 2.2.0

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.
data/.gitignore CHANGED
@@ -4,3 +4,4 @@
4
4
  *.rbc
5
5
  .yardoc
6
6
  Gemfile.lock
7
+ nbproject
data/.travis.yml CHANGED
@@ -3,6 +3,8 @@ rvm:
3
3
  - 1.9.2
4
4
  - 1.9.3
5
5
  - ree
6
+ - jruby-18mode
7
+ - jruby-19mode
6
8
  notifications:
7
9
  recipients:
8
10
  - cowboyd@thefrontside.net
data/Gemfile CHANGED
@@ -1,3 +1,7 @@
1
1
  source :rubygems
2
2
 
3
- gemspec
3
+ gemspec
4
+
5
+
6
+ gem "therubyracer", "~> 0.10.0", :require => nil, :platforms => :ruby
7
+ gem "therubyrhino", "~> 1.73.3", :require => nil, :platforms => :jruby
data/less.gemspec CHANGED
@@ -22,10 +22,9 @@ Gem::Specification.new do |s|
22
22
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
23
  s.require_paths = ["lib"]
24
24
 
25
- s.add_dependency "therubyracer", "~> 0.10.0"
26
- s.add_dependency "commonjs", "~> 0.2.0"
27
-
25
+ s.add_dependency "commonjs", "~> 0.2.6"
28
26
  s.add_development_dependency "rake"
29
27
  s.add_development_dependency "rspec", "~> 2.0"
28
+
30
29
  end
31
30
 
data/lib/less/defaults.rb CHANGED
@@ -1,13 +1,13 @@
1
-
2
1
  module Less
3
2
  module Defaults
4
3
 
5
4
  def defaults
6
- @defaults ||= {:paths => []}
5
+ @defaults ||= { :paths => [] }
7
6
  end
8
7
 
9
8
  def paths
10
9
  defaults[:paths]
11
10
  end
11
+
12
12
  end
13
13
  end
@@ -0,0 +1,41 @@
1
+ module Less
2
+
3
+ class Error < ::StandardError
4
+
5
+ def initialize(cause, value = nil)
6
+ @value = value
7
+ message = nil
8
+ if @value # 2 args passed
9
+ message = @value['message']
10
+ else # allow passing only value as first arg cause :
11
+ if cause.respond_to?(:'[]') && message = cause['message']
12
+ @value = cause
13
+ end
14
+ end
15
+
16
+ if cause.is_a?(::Exception)
17
+ @cause = cause
18
+ super(message || cause.message)
19
+ else
20
+ super(message || cause)
21
+ end
22
+ end
23
+
24
+ def cause
25
+ @cause
26
+ end
27
+
28
+ def backtrace
29
+ @cause ? @cause.backtrace : super
30
+ end
31
+
32
+ # function LessError(e, env) { ... }
33
+ %w{ type filename index line stack column extract }.each do |key|
34
+ class_eval "def #{key}; @value && @value['#{key}']; end"
35
+ end
36
+
37
+ end
38
+
39
+ class ParseError < Error; end
40
+
41
+ end
@@ -0,0 +1,110 @@
1
+ begin
2
+ require 'rhino' unless defined?(Rhino)
3
+ rescue LoadError => e
4
+ warn "[WARNING] Please install gem 'therubyrhino' to use Less under JRuby."
5
+ raise e
6
+ end
7
+
8
+ require 'rhino/version'
9
+ if Rhino::VERSION < '1.73.3'
10
+ raise LoadError, "expected gem 'therubyrhino' '>= 1.73.3' but got '#{Rhino::VERSION}'"
11
+ end
12
+
13
+ module Less
14
+ module JavaScript
15
+ class RhinoContext
16
+
17
+ def self.instance
18
+ return new # NOTE: for Rhino a context should be kept open per thread !
19
+ end
20
+
21
+ def initialize(globals = nil)
22
+ @rhino_context = Rhino::Context.new :java => true
23
+ if @rhino_context.respond_to?(:version)
24
+ @rhino_context.version = '1.8'
25
+ apply_1_8_compatibility! if @rhino_context.version.to_s != '1.8'
26
+ else
27
+ apply_1_8_compatibility!
28
+ end
29
+ fix_memory_limit! @rhino_context
30
+ globals.each { |key, val| @rhino_context[key] = val } if globals
31
+ end
32
+
33
+ def unwrap
34
+ @rhino_context
35
+ end
36
+
37
+ def exec(&block)
38
+ @rhino_context.open(&block)
39
+ rescue Rhino::JSError => e
40
+ handle_js_error(e)
41
+ end
42
+
43
+ def eval(source, options = {})
44
+ source = source.encode('UTF-8') if source.respond_to?(:encode)
45
+
46
+ source_name = options[:source_name] || "<eval>"
47
+ line_number = options[:line_number] || 1
48
+ @rhino_context.eval("(#{source})", source_name, line_number)
49
+ rescue Rhino::JSError => e
50
+ handle_js_error(e)
51
+ end
52
+
53
+ def call(properties, *args)
54
+ options = args.last.is_a?(::Hash) ? args.pop : {} # extract_option!
55
+
56
+ source_name = options[:source_name] || "<eval>"
57
+ line_number = options[:line_number] || 1
58
+ @rhino_context.eval(properties, source_name, line_number).call(*args)
59
+ rescue Rhino::JSError => e
60
+ handle_js_error(e)
61
+ end
62
+
63
+ def method_missing(symbol, *args)
64
+ if @rhino_context.respond_to?(symbol)
65
+ @rhino_context.send(symbol, *args)
66
+ else
67
+ super
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def handle_js_error(e)
74
+ if e.value && e.value['type'] # LessError
75
+ raise Less::ParseError.new(e, e.value)
76
+ end
77
+ if e.unwrap.to_s == "missing closing `}`"
78
+ raise Less::ParseError.new(e.unwrap.to_s)
79
+ end
80
+ if e.message && e.message[0, 12] == "Syntax Error"
81
+ raise Less::ParseError.new(e)
82
+ else
83
+ raise Less::Error.new(e)
84
+ end
85
+ end
86
+
87
+ # Disables bytecode compiling which limits you to 64K scripts
88
+ def fix_memory_limit!(context)
89
+ if context.respond_to?(:optimization_level=)
90
+ context.optimization_level = -1
91
+ else
92
+ context.instance_eval { @native.setOptimizationLevel(-1) }
93
+ end
94
+ end
95
+
96
+ def apply_1_8_compatibility!
97
+ # TODO rather load ecma-5.js ...
98
+ @rhino_context.eval("
99
+ // String
100
+ if ( ! String.prototype.trim ) {
101
+ String.prototype.trim = function () {
102
+ return this.replace(/^\s+|\s+$/g,'');
103
+ };
104
+ }
105
+ ")
106
+ end
107
+
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,88 @@
1
+ begin
2
+ require 'v8' unless defined?(V8)
3
+ rescue LoadError => e
4
+ warn "[WARNING] Please install gem 'therubyracer' to use Less."
5
+ raise e
6
+ end
7
+
8
+ require 'pathname'
9
+
10
+ module Less
11
+ module JavaScript
12
+ class V8Context
13
+
14
+ def self.instance
15
+ return new
16
+ end
17
+
18
+ def initialize(globals = nil)
19
+ lock do
20
+ @v8_context = V8::Context.new
21
+ globals.each { |key, val| @v8_context[key] = val } if globals
22
+ end
23
+ end
24
+
25
+ def unwrap
26
+ @v8_context
27
+ end
28
+
29
+ def exec(&block)
30
+ lock(&block)
31
+ end
32
+
33
+ def eval(source, options = nil) # passing options not supported
34
+ source = source.encode('UTF-8') if source.respond_to?(:encode)
35
+
36
+ lock do
37
+ @v8_context.eval("(#{source})")
38
+ end
39
+ end
40
+
41
+ def call(properties, *args)
42
+ args.last.is_a?(::Hash) ? args.pop : nil # extract_options!
43
+
44
+ lock do
45
+ @v8_context.eval(properties).call(*args)
46
+ end
47
+ end
48
+
49
+ def method_missing(symbol, *args)
50
+ if @v8_context.respond_to?(symbol)
51
+ @v8_context.send(symbol, *args)
52
+ else
53
+ super
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def lock(&block)
60
+ do_lock(&block)
61
+ rescue V8::JSError => e
62
+ if e.value["name"] == "SyntaxError" || e.in_javascript?
63
+ raise Less::ParseError.new(e)
64
+ else
65
+ raise Less::Error.new(e)
66
+ end
67
+ end
68
+
69
+ def do_lock
70
+ result, exception = nil, nil
71
+ V8::C::Locker() do
72
+ begin
73
+ result = yield
74
+ rescue Exception => e
75
+ exception = e
76
+ end
77
+ end
78
+
79
+ if exception
80
+ raise exception
81
+ else
82
+ result
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,34 @@
1
+ module Less
2
+ module JavaScript
3
+
4
+ def self.default_context_wrapper
5
+ if defined?(JRUBY_VERSION)
6
+ require 'less/java_script/rhino_context'
7
+ RhinoContext
8
+ else
9
+ require 'less/java_script/v8_context'
10
+ V8Context
11
+ end
12
+ end
13
+
14
+ @@context_wrapper = nil
15
+
16
+ def self.context_wrapper
17
+ @@context_wrapper ||= default_context_wrapper
18
+ end
19
+
20
+ def self.context_wrapper=(klass)
21
+ @@context_wrapper = klass
22
+ end
23
+
24
+ # execute a block as JS
25
+ def self.exec(&block)
26
+ context_wrapper.instance.exec(&block)
27
+ end
28
+
29
+ def self.eval(source)
30
+ context_wrapper.instance.eval(source)
31
+ end
32
+
33
+ end
34
+ end
data/lib/less/loader.rb CHANGED
@@ -1,26 +1,29 @@
1
+ require 'pathname'
1
2
  require 'commonjs'
2
3
 
3
4
  module Less
4
5
  class Loader
5
- include CallJS
6
-
6
+
7
7
  attr_reader :environment
8
-
8
+
9
9
  def initialize
10
- @cxt = V8::Context.new
11
- @environment = CommonJS::Environment.new(@cxt, :path => Pathname(__FILE__).dirname.join('js','lib').to_s)
10
+ context_wrapper = Less::JavaScript.context_wrapper.instance
11
+ @context = context_wrapper.unwrap
12
+ @context['process'] = Process.new
13
+ @context['console'] = Console.new
14
+ path = Pathname(__FILE__).dirname.join('js', 'lib')
15
+ @environment = CommonJS::Environment.new(@context, :path => path.to_s)
12
16
  @environment.native('path', Path.new)
13
17
  @environment.native('util', Sys.new)
14
18
  @environment.native('fs', Fs.new)
15
-
16
- @cxt['process'] = Process.new
17
- @cxt['console'] = Console.new
18
19
  end
19
-
20
+
20
21
  def require(module_id)
21
22
  @environment.require(module_id)
22
23
  end
23
-
24
+
25
+ # stubbed JS modules required by less.js
26
+
24
27
  class Path
25
28
  def join(*components)
26
29
  File.join(*components)
@@ -34,7 +37,7 @@ module Less
34
37
  File.basename(path)
35
38
  end
36
39
  end
37
-
40
+
38
41
  class Sys
39
42
  def error(*errors)
40
43
  raise errors.join(' ')
@@ -49,7 +52,6 @@ module Less
49
52
  def readFile(path, encoding, callback)
50
53
  callback.call(nil, File.read(path))
51
54
  end
52
-
53
55
  end
54
56
 
55
57
  class Process
@@ -58,9 +60,10 @@ module Less
58
60
  end
59
61
 
60
62
  class Console
61
- def log(*msgs)
62
- puts msgs.join(',')
63
+ def self.log(*msgs)
64
+ puts msgs.join(', ')
63
65
  end
64
66
  end
67
+
65
68
  end
66
69
  end
data/lib/less/parser.rb CHANGED
@@ -1,45 +1,7 @@
1
-
2
1
  module Less
3
-
4
- # Utility for calling into the JavaScript runtime.
5
- module CallJS
6
-
7
- # @private
8
- # Wrap JavaScript invocations with uniform error handling
9
- #
10
- # @yield code to wrap
11
- def calljs
12
- lock do
13
- yield
14
- end
15
- rescue V8::JSError => e
16
- raise ParseError.new(e)
17
- end
18
-
19
- # @private
20
- # Ensure proper locking before entering the V8 API
21
- #
22
- # @yield code to wrap in lock
23
- def lock
24
- result, exception = nil, nil
25
- V8::C::Locker() do
26
- begin
27
- result = yield
28
- rescue Exception => e
29
- exception = e
30
- end
31
- end
32
- if exception
33
- raise exception
34
- else
35
- result
36
- end
37
- end
38
- end
39
-
2
+
40
3
  # Convert lesscss source into an abstract syntax Tree
41
4
  class Parser
42
- include CallJS
43
5
 
44
6
  # Construct and configure new Less::Parser
45
7
  #
@@ -51,62 +13,49 @@ module Less
51
13
  Less.defaults.merge(options).each do |k,v|
52
14
  stringy[k.to_s] = v.is_a?(Array) ? v.map(&:to_s) : v.to_s
53
15
  end
54
- lock do
55
- @parser = Less.Parser.new(stringy)
56
- end
16
+ @parser = Less::JavaScript.exec { Less['Parser'].new(stringy) }
57
17
  end
58
18
 
59
19
  # Convert `less` source into a abstract syntaxt tree
60
20
  # @param [String] less the source to parse
61
21
  # @return [Less::Tree] the parsed tree
62
22
  def parse(less)
63
- calljs do
64
- tree = nil
65
- @parser.parse(less, lambda {|*args|
66
- this, e, t = *args
67
- fail e.message unless e.nil?
68
- tree = t
23
+ error, tree = nil, nil
24
+ Less::JavaScript.exec do
25
+ @parser.parse(less, lambda { |*args| # (error, tree)
26
+ # v8 >= 0.10 passes this as first arg :
27
+ if args.size > 2
28
+ error, tree = args[-2], args[-1]
29
+ else
30
+ error, tree = *args
31
+ end
32
+ fail error.message unless error.nil?
69
33
  })
70
- Tree.new(tree) if tree
71
34
  end
72
- end
73
- end
74
-
75
- # Abstract LessCSS syntax tree Less. Mainly used to emit CSS
76
- class Tree
77
- include CallJS
78
- # Create a tree from a native javascript object.
79
- # @param [V8::Object] tree the native less.js tree
80
- def initialize(tree)
81
- @tree = tree
82
- end
83
-
84
- # Serialize this tree into CSS.
85
- # By default this will be in pretty-printed form.
86
- # @param [Hash] opts modifications to the output
87
- # @option opts [Boolean] :compress minify output instead of pretty-printing
88
- def to_css(options = {})
89
- calljs do
90
- @tree.toCSS(options)
35
+ Tree.new(tree) if tree
36
+ end
37
+
38
+ private
39
+
40
+ # Abstract LessCSS syntax tree Less. Mainly used to emit CSS
41
+ class Tree
42
+
43
+ # Create a tree from a native javascript object.
44
+ # @param [V8::Object] tree the native less.js tree
45
+ def initialize(tree)
46
+ @tree = tree
91
47
  end
92
- end
93
- end
94
-
95
- # Thrown whenever an error occurs parsing
96
- # and/or serializing less source. It is intended
97
- # to wrap a native V8::JSError
98
- class ParseError < StandardError
99
48
 
100
- # Copies over `error`'s message and backtrace
101
- # @param [V8::JSError] error native error
102
- def initialize(error)
103
- super(error.message)
104
- @backtrace = error.backtrace
105
- end
106
-
107
- # @return [Array] the backtrace frames
108
- def backtrace
109
- @backtrace
49
+ # Serialize this tree into CSS.
50
+ # By default this will be in pretty-printed form.
51
+ # @param [Hash] opts modifications to the output
52
+ # @option opts [Boolean] :compress minify output instead of pretty-printing
53
+ def to_css(options = {})
54
+ Less::JavaScript.exec { @tree.toCSS(options) }
55
+ end
56
+
110
57
  end
58
+
111
59
  end
60
+
112
61
  end
data/lib/less/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Less
2
- VERSION = '2.1.0'
2
+ VERSION = '2.2.0'
3
3
  end
data/lib/less.rb CHANGED
@@ -1,18 +1,25 @@
1
- require 'v8'
2
- require 'pathname'
3
- require 'less/parser'
1
+
2
+ require 'less/defaults'
3
+ require 'less/errors'
4
4
  require 'less/loader'
5
+ require 'less/parser'
5
6
  require 'less/version'
6
- require 'less/defaults'
7
+ require 'less/java_script'
7
8
 
8
9
  module Less
9
10
  extend Less::Defaults
10
-
11
+
12
+ # NOTE: keep the @loader as less-rails depends on
13
+ # it as it overrides some less/tree.js functions!
11
14
  @loader = Less::Loader.new
12
15
  @less = @loader.require('less/index')
13
16
 
17
+ def self.[](name)
18
+ @less[name]
19
+ end
20
+
14
21
  def self.Parser
15
- @less['Parser']
22
+ self['Parser']
16
23
  end
17
24
 
18
25
  end
@@ -3,7 +3,11 @@ require 'spec_helper'
3
3
  describe Less::Parser do
4
4
 
5
5
  cwd = Pathname(__FILE__).dirname
6
-
6
+
7
+ it "instantiates" do
8
+ expect { Less::Parser.new }.should_not raise_error
9
+ end
10
+
7
11
  describe "simple usage" do
8
12
  it "parse less into a tree" do
9
13
  root = subject.parse(".class {width: 1+1}")
@@ -15,16 +19,12 @@ describe Less::Parser do
15
19
  end
16
20
  end
17
21
 
18
- it "throws a ParseError if the lesscss is bogus" do
19
- expect {subject.parse('{^)')}.should raise_error(Less::ParseError)
20
- end
21
-
22
22
  it "passes exceptions from the less compiler" do
23
- expect {subject.parse('body { color: @a; }').to_css}.should raise_error(Less::ParseError, /variable @a is undefined/)
23
+ expect { subject.parse('body { color: @a; }').to_css }.should raise_error(Less::ParseError, /variable @a is undefined/)
24
24
  end
25
25
 
26
26
  describe "when configured with multiple load paths" do
27
- subject {Less::Parser.new :paths => [cwd.join('one'), cwd.join('two'), cwd.join('faulty')]}
27
+ subject { Less::Parser.new :paths => [ cwd.join('one'), cwd.join('two'), cwd.join('faulty') ] }
28
28
 
29
29
  it "will load files from both paths" do
30
30
  subject.parse('@import "one.less";').to_css.gsub(/\n/,'').strip.should eql ".one { width: 1;}"
@@ -32,7 +32,7 @@ describe Less::Parser do
32
32
  end
33
33
 
34
34
  it "passes exceptions from less imported less files" do
35
- expect {subject.parse('@import "faulty.less";').to_css}.should raise_error(Less::ParseError, /variable @a is undefined/)
35
+ expect { subject.parse('@import "faulty.less";').to_css }.should raise_error(Less::ParseError, /variable @a is undefined/)
36
36
  end
37
37
 
38
38
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
- $:.unshift Pathname(__FILE__).dirname.join('..','lib')
1
+ require 'pathname'
2
2
 
3
- require 'less'
3
+ $:.unshift Pathname(__FILE__).dirname.join('..', 'lib').to_s
4
+
5
+ require 'less'
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: 2.1.0
4
+ version: 2.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,33 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-29 00:00:00.000000000 Z
12
+ date: 2012-04-25 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: therubyracer
16
- requirement: &2158173480 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: 0.10.0
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: *2158173480
25
14
  - !ruby/object:Gem::Dependency
26
15
  name: commonjs
27
- requirement: &2158172980 !ruby/object:Gem::Requirement
16
+ requirement: &2151889720 !ruby/object:Gem::Requirement
28
17
  none: false
29
18
  requirements:
30
19
  - - ~>
31
20
  - !ruby/object:Gem::Version
32
- version: 0.2.0
21
+ version: 0.2.6
33
22
  type: :runtime
34
23
  prerelease: false
35
- version_requirements: *2158172980
24
+ version_requirements: *2151889720
36
25
  - !ruby/object:Gem::Dependency
37
26
  name: rake
38
- requirement: &2158172600 !ruby/object:Gem::Requirement
27
+ requirement: &2151888660 !ruby/object:Gem::Requirement
39
28
  none: false
40
29
  requirements:
41
30
  - - ! '>='
@@ -43,10 +32,10 @@ dependencies:
43
32
  version: '0'
44
33
  type: :development
45
34
  prerelease: false
46
- version_requirements: *2158172600
35
+ version_requirements: *2151888660
47
36
  - !ruby/object:Gem::Dependency
48
37
  name: rspec
49
- requirement: &2158172000 !ruby/object:Gem::Requirement
38
+ requirement: &2151887500 !ruby/object:Gem::Requirement
50
39
  none: false
51
40
  requirements:
52
41
  - - ~>
@@ -54,7 +43,7 @@ dependencies:
54
43
  version: '2.0'
55
44
  type: :development
56
45
  prerelease: false
57
- version_requirements: *2158172000
46
+ version_requirements: *2151887500
58
47
  description: Invoke the Less CSS compiler from Ruby
59
48
  email:
60
49
  - cowboyd@thefrontside.net
@@ -73,6 +62,10 @@ files:
73
62
  - less.gemspec
74
63
  - lib/less.rb
75
64
  - lib/less/defaults.rb
65
+ - lib/less/errors.rb
66
+ - lib/less/java_script.rb
67
+ - lib/less/java_script/rhino_context.rb
68
+ - lib/less/java_script/v8_context.rb
76
69
  - lib/less/loader.rb
77
70
  - lib/less/parser.rb
78
71
  - lib/less/version.rb
@@ -356,7 +349,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
356
349
  version: '0'
357
350
  segments:
358
351
  - 0
359
- hash: -105846769214785865
352
+ hash: 2145882749298948818
360
353
  required_rubygems_version: !ruby/object:Gem::Requirement
361
354
  none: false
362
355
  requirements:
@@ -365,7 +358,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
365
358
  version: '0'
366
359
  segments:
367
360
  - 0
368
- hash: -105846769214785865
361
+ hash: 2145882749298948818
369
362
  requirements: []
370
363
  rubyforge_project: less
371
364
  rubygems_version: 1.8.17