less_to_sass 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +70 -0
- data/bin/less2sass +12 -0
- data/bin/sass2less +12 -0
- data/lib/less2sass/constants.rb +5 -0
- data/lib/less2sass/error.rb +100 -0
- data/lib/less2sass/exec/base.rb +83 -0
- data/lib/less2sass/exec/conversion.rb +102 -0
- data/lib/less2sass/exec.rb +2 -0
- data/lib/less2sass/js/less_parser.js +48 -0
- data/lib/less2sass/less/ast_handler.rb +33 -0
- data/lib/less2sass/less/environment.rb +212 -0
- data/lib/less2sass/less/parser.rb +131 -0
- data/lib/less2sass/less/tree/alpha_node.rb +9 -0
- data/lib/less2sass/less/tree/anonymous_node.rb +43 -0
- data/lib/less2sass/less/tree/assignment_node.rb +10 -0
- data/lib/less2sass/less/tree/attribute_node.rb +11 -0
- data/lib/less2sass/less/tree/call_node.rb +65 -0
- data/lib/less2sass/less/tree/color_node.rb +27 -0
- data/lib/less2sass/less/tree/combinator_node.rb +18 -0
- data/lib/less2sass/less/tree/comment_node.rb +58 -0
- data/lib/less2sass/less/tree/condition_node.rb +13 -0
- data/lib/less2sass/less/tree/detached_ruleset_node.rb +10 -0
- data/lib/less2sass/less/tree/dimension_node.rb +26 -0
- data/lib/less2sass/less/tree/directive_node.rb +40 -0
- data/lib/less2sass/less/tree/element_node.rb +32 -0
- data/lib/less2sass/less/tree/expression_node.rb +73 -0
- data/lib/less2sass/less/tree/extend_node.rb +14 -0
- data/lib/less2sass/less/tree/import_node.rb +14 -0
- data/lib/less2sass/less/tree/keyword_node.rb +49 -0
- data/lib/less2sass/less/tree/media_node.rb +12 -0
- data/lib/less2sass/less/tree/mixin_call_node.rb +13 -0
- data/lib/less2sass/less/tree/mixin_definition_node.rb +24 -0
- data/lib/less2sass/less/tree/negative_node.rb +9 -0
- data/lib/less2sass/less/tree/node.rb +212 -0
- data/lib/less2sass/less/tree/operation_node.rb +63 -0
- data/lib/less2sass/less/tree/paren_node.rb +9 -0
- data/lib/less2sass/less/tree/quoted_node.rb +64 -0
- data/lib/less2sass/less/tree/rule_node.rb +119 -0
- data/lib/less2sass/less/tree/ruleset_call_node.rb +9 -0
- data/lib/less2sass/less/tree/ruleset_node.rb +82 -0
- data/lib/less2sass/less/tree/selector_node.rb +27 -0
- data/lib/less2sass/less/tree/unicode_descriptor_node.rb +9 -0
- data/lib/less2sass/less/tree/unit_node.rb +17 -0
- data/lib/less2sass/less/tree/url_node.rb +22 -0
- data/lib/less2sass/less/tree/value_node.rb +53 -0
- data/lib/less2sass/less/tree/variable_node.rb +43 -0
- data/lib/less2sass/less/tree.rb +34 -0
- data/lib/less2sass/less.rb +2 -0
- data/lib/less2sass/sass/ast_handler.rb +57 -0
- data/lib/less2sass/sass/parser.rb +20 -0
- data/lib/less2sass/sass.rb +2 -0
- data/lib/less2sass/util.rb +36 -0
- data/lib/less2sass.rb +9 -0
- metadata +163 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# A RuleNode in Less can be a CSS rule, or a
|
5
|
+
# variable definition.
|
6
|
+
#
|
7
|
+
# Examples:
|
8
|
+
# - color: @var;
|
9
|
+
# - @var: 50px;
|
10
|
+
#
|
11
|
+
# The Sass equivalent is {::Sass::Tree::VariableNode}
|
12
|
+
# or {::Sass::Tree::RuleNode}.
|
13
|
+
class RuleNode < Node
|
14
|
+
attr_accessor :name
|
15
|
+
attr_accessor :value
|
16
|
+
attr_accessor :important
|
17
|
+
attr_accessor :merge
|
18
|
+
attr_accessor :index
|
19
|
+
attr_accessor :currentFileInfo
|
20
|
+
attr_accessor :inline
|
21
|
+
attr_accessor :variable
|
22
|
+
|
23
|
+
attr_accessor :guarded
|
24
|
+
attr_accessor :global
|
25
|
+
|
26
|
+
# @see VariableNode#sass_name
|
27
|
+
def sass_name
|
28
|
+
@name[1..-1] if @name
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns whether the node is a variable definition.
|
32
|
+
#
|
33
|
+
# @return [Boolean]
|
34
|
+
def is_variable_definition?
|
35
|
+
@variable
|
36
|
+
end
|
37
|
+
|
38
|
+
# Checks, if the given variable is referenced by the variable's definition
|
39
|
+
#
|
40
|
+
# @param [Less2Sass::Less::Tree:RuleNode] variable the variable
|
41
|
+
# @param [String] variable the variable's name
|
42
|
+
# @return [Boolean]
|
43
|
+
def references?(variable)
|
44
|
+
if variable.is_a?(String)
|
45
|
+
@ref_vars.include?(variable)
|
46
|
+
else
|
47
|
+
@ref_vars.include?(variable.name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Converts this node to {::Sass::Tree::VariableNode}, if
|
52
|
+
# it's a variable definition. Otherwise it must be a CSS
|
53
|
+
# property declaration and gets converted to {::Sass::Tree::PropNode}.
|
54
|
+
#
|
55
|
+
# The 3rd param of `::Sass::Tree::PropNode` refers to the CSS
|
56
|
+
# syntax to be outputted. Its value can be:
|
57
|
+
# - `:new` using `a: b`-style syntax
|
58
|
+
# - `:old` using `:a b`-style syntax
|
59
|
+
#
|
60
|
+
# For the sake of simplicity, we'll use the new syntax only.
|
61
|
+
# Later could be set in cli arguments as option.
|
62
|
+
#
|
63
|
+
# @note Always put on a new line.
|
64
|
+
# @return [::Sass::Tree::VariableNode, ::Sass::Tree::PropNode]
|
65
|
+
# @see Node#to_sass
|
66
|
+
def to_sass
|
67
|
+
node ||=
|
68
|
+
begin
|
69
|
+
if is_variable_definition?
|
70
|
+
::Sass::Tree::VariableNode.new(
|
71
|
+
sass_name, @value.to_sass, @guarded, @global
|
72
|
+
)
|
73
|
+
else
|
74
|
+
# TODO: Don't forget about the `#{}`
|
75
|
+
::Sass::Tree::PropNode.new(
|
76
|
+
process_property_name, @value.to_sass, :new
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
node(node, line(:new))
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# Creates the Sass representation of the property name.
|
86
|
+
#
|
87
|
+
# @return [Array<String, ::Sass::Script::Tree::Node>]
|
88
|
+
def process_property_name
|
89
|
+
return [create_name] unless @name.is_a?(Array)
|
90
|
+
@name.inject([]) do |name, part|
|
91
|
+
name << create_name(part)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns a part of the property name.
|
96
|
+
#
|
97
|
+
# @param [VariableNode, #to_s] name part of the property name
|
98
|
+
# @return [String, ::Sass::Script::Tree::Node] converted
|
99
|
+
# part of property name
|
100
|
+
def create_name(name = @name)
|
101
|
+
if name.is_a?(VariableNode)
|
102
|
+
create_interpolation(name)
|
103
|
+
else
|
104
|
+
name.to_s
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Creates a Sass interpolation node
|
109
|
+
#
|
110
|
+
# @param [VariableNode] variable_node the variable node to convert
|
111
|
+
# @return [::Sass::Script::Tree::Interpolation] a Sass Interpolation node
|
112
|
+
def create_interpolation(variable_node)
|
113
|
+
var = ::Sass::Script::Tree::Variable.new(variable_node.name[1..-1])
|
114
|
+
node(::Sass::Script::Tree::Interpolation.new(nil, var, nil, false, false), line)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# The Ruleset node is the root node of every Less AST.
|
5
|
+
# It also means a block of selector and its inner rules.
|
6
|
+
#
|
7
|
+
# Its Sass equivalent is a {::Sass::Tree::RootNode}, or
|
8
|
+
# {::Sass::Tree::RuleNode}.
|
9
|
+
class RulesetNode < Node
|
10
|
+
attr_accessor :selectors, :rules, :_lookups,
|
11
|
+
:root, :firstRoot, :strictImports
|
12
|
+
|
13
|
+
def initialize(options = nil)
|
14
|
+
super
|
15
|
+
@options = options unless options.nil?
|
16
|
+
end
|
17
|
+
|
18
|
+
# @see Node#creates_context?
|
19
|
+
def creates_context?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
# Transforms the ruleset node by reordering the child nodes.
|
24
|
+
#
|
25
|
+
# 1. Creates a new environment and puts the child
|
26
|
+
# nodes into it.
|
27
|
+
#
|
28
|
+
# 2. Further traverses the tree of nodes and transforms them, as well.
|
29
|
+
#
|
30
|
+
# 3. Saves the re-ordered rules and child nodes.
|
31
|
+
#
|
32
|
+
# @param (see Node#transform)
|
33
|
+
# @return [Void]
|
34
|
+
def transform(env = nil)
|
35
|
+
env = Less2Sass::Less::Environment.new(env)
|
36
|
+
env.set_environment(@children)
|
37
|
+
env.build
|
38
|
+
super(env)
|
39
|
+
@rules = env.get_ordered_child_nodes
|
40
|
+
@children = @rules
|
41
|
+
end
|
42
|
+
|
43
|
+
# Converts node to {::Sass::Tree::RootNode} if it's root.
|
44
|
+
# Otherwise it converts to {::Sass::Tree::RuleNode}.
|
45
|
+
#
|
46
|
+
# In case of root node, all the children nodes have to be
|
47
|
+
# converted. Otherwise rule nodes only.
|
48
|
+
#
|
49
|
+
# @note I both cases the node is placed on a new line.
|
50
|
+
# @return [::Sass::Tree::RootNode, ::Sass::Tree::RuleNode]
|
51
|
+
# @see Node#to_sass
|
52
|
+
def to_sass(options = nil)
|
53
|
+
if @root
|
54
|
+
node = node(::Sass::Engine.new('', options).to_tree, line(:new))
|
55
|
+
children = @children
|
56
|
+
else
|
57
|
+
node = node(::Sass::Tree::RuleNode.new(get_full_selector), line(:new))
|
58
|
+
children = @rules.is_a?(Array) ? @rules : [@rules]
|
59
|
+
end
|
60
|
+
children.each { |c| node << c.to_sass }
|
61
|
+
node
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# Creates a list of selectors.
|
67
|
+
#
|
68
|
+
# @return [Array<String, Sass::Script::Tree::Node>] the list of selectors
|
69
|
+
def get_full_selector
|
70
|
+
raise UnknownError if @selectors.nil?
|
71
|
+
if @selectors.is_a?(Array)
|
72
|
+
# Creates a list of selectors {Array<String, Sass::Script::Tree::node>} separated by a comma
|
73
|
+
# and returns the list without the last, trailing comma
|
74
|
+
@selectors.inject([]) { |rule, selector| rule << [selector.to_sass, ','] }.flatten[0..-2]
|
75
|
+
else
|
76
|
+
[@selectors.to_sass].flatten
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# Represents the full selector of a given {RulesetNode}.
|
5
|
+
#
|
6
|
+
# No equivalent node is present in Sass, it's the `rule`
|
7
|
+
# member of {::Sass::Tree::PropNode}, instead.
|
8
|
+
class SelectorNode < Node
|
9
|
+
# @return [Array<Tree::ElementNode>]
|
10
|
+
attr_accessor :elements
|
11
|
+
attr_accessor :extendList
|
12
|
+
attr_accessor :condition
|
13
|
+
# @return [Hash]
|
14
|
+
attr_accessor :currentFileInfo
|
15
|
+
# @return [Boolean]
|
16
|
+
attr_accessor :evaldCondition
|
17
|
+
|
18
|
+
# see Node#to_sass
|
19
|
+
def to_sass
|
20
|
+
raise UnknownError if @elements.nil?
|
21
|
+
return @elements.to_sass unless @elements.is_a?(Array)
|
22
|
+
@elements.inject([]) { |selector, element| selector << element.to_sass }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
class UnitNode < Node
|
5
|
+
attr_accessor :numerator
|
6
|
+
attr_accessor :denominator
|
7
|
+
attr_accessor :backupUnit
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
val = @numerator[0].to_s
|
11
|
+
val += @denominator[0] unless @denominator.nil? || @denominator.empty?
|
12
|
+
val
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# Represents the CSS `url` function call.
|
5
|
+
#
|
6
|
+
# The Sass equivalent is {::Sass::Script::Tree::Funcall}.
|
7
|
+
class UrlNode < Node
|
8
|
+
attr_accessor :value
|
9
|
+
attr_accessor :currentFileInfo
|
10
|
+
attr_accessor :index
|
11
|
+
attr_accessor :isEvald
|
12
|
+
|
13
|
+
# @return [::Sass::Script::Tree::Funcall]
|
14
|
+
# @see https://github.com/sass/sass/blob/stable/lib/sass/script/tree/funcall.rb#L42-46
|
15
|
+
# @see Node#to_sass
|
16
|
+
def to_sass
|
17
|
+
node(::Sass::Script::Tree::Funcall.new('url', [@value.to_sass], ::Sass::Util::NormalizedMap.new, nil, nil), line)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# Represents the value of any Less AST node.
|
5
|
+
#
|
6
|
+
# It has no individual representation in Sass,
|
7
|
+
# so it returns its value node's Sass representation,
|
8
|
+
# when {#to_sass} gets called.
|
9
|
+
#
|
10
|
+
# Sass equivalents:
|
11
|
+
# - {::Sass::Script::Tree::Literal} if part of property declaration
|
12
|
+
# - {::Sass::Script::Tree::ListLiteral} if part of variable definition
|
13
|
+
#
|
14
|
+
# @see Node
|
15
|
+
class ValueNode < Node
|
16
|
+
# @todo update Sass and check out a lately commit regarding the deprecated SassScript usage in CSS rules
|
17
|
+
# @see https://github.com/sass/sass/commit/b671122234d2d4df088a6c6d4c54b64d6997d255
|
18
|
+
|
19
|
+
# The ValueNode is not the final value of a variable
|
20
|
+
# or a property.
|
21
|
+
#
|
22
|
+
# @return [Node, Array<Node>]
|
23
|
+
attr_accessor :value
|
24
|
+
|
25
|
+
# This node's value is either a single expression,
|
26
|
+
# or an array of those. The array needs to be further
|
27
|
+
# processed.
|
28
|
+
#
|
29
|
+
# @return [::Sass::Script::Tree::Literal, ::Sass::Script::Tree::ListLiteral]
|
30
|
+
# @see Node#to_sass
|
31
|
+
def to_sass
|
32
|
+
if @value.is_a?(Array)
|
33
|
+
# TODO: don't forget about interpolation. What if one of the expressions is a variable?
|
34
|
+
if @parent.is_variable_definition? || contains_variables?
|
35
|
+
elements = @value.inject([]) { |elements, elem| elements << elem.to_sass }
|
36
|
+
node(::Sass::Script::Tree::ListLiteral.new(elements, :comma), line)
|
37
|
+
else
|
38
|
+
value = @value.inject([]) do |value, elem|
|
39
|
+
substring = elem.to_sass
|
40
|
+
# TODO: describe solution for '"Source Code Pro", Monaco, monospace'
|
41
|
+
substring = substring.value.value if substring.is_a?(::Sass::Script::Tree::Literal)
|
42
|
+
value << substring
|
43
|
+
end.join(', ')
|
44
|
+
node(::Sass::Script::Tree::Literal.new(::Sass::Script::Value::String.new(value)), line)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
@value.to_sass
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# A node representing a variable.
|
5
|
+
# The Sass representation of it is {::Sass::Script::Tree:Variable}
|
6
|
+
class VariableNode < Node
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :name
|
9
|
+
# @return [Integer]
|
10
|
+
attr_accessor :index
|
11
|
+
# @return [Hash]
|
12
|
+
attr_accessor :currentFileInfo
|
13
|
+
|
14
|
+
# Returns the sass specific name property by
|
15
|
+
# removing the starting @.
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
# node.sass_name => "var1"
|
19
|
+
#
|
20
|
+
# @return [String]
|
21
|
+
def sass_name
|
22
|
+
@name[1..-1] if @name
|
23
|
+
end
|
24
|
+
|
25
|
+
# Checks, whether the variable node is an interpolation
|
26
|
+
#
|
27
|
+
# @return [Boolean]
|
28
|
+
def interpolation?
|
29
|
+
return false unless [ElementNode, RuleNode].include?(@parent.class)
|
30
|
+
return !@parent.is_variable_definition? if @parent.is_a?(RuleNode)
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
# @see Node#to_sass
|
35
|
+
def to_sass
|
36
|
+
variable = node(::Sass::Script::Tree::Variable.new(sass_name), line)
|
37
|
+
variable = node(::Sass::Script::Tree::Interpolation.new(nil, variable, nil, false, false), line) if interpolation?
|
38
|
+
variable
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'less2sass/less/tree/node'
|
2
|
+
require 'less2sass/less/tree/alpha_node'
|
3
|
+
require 'less2sass/less/tree/anonymous_node'
|
4
|
+
require 'less2sass/less/tree/assignment_node'
|
5
|
+
require 'less2sass/less/tree/attribute_node'
|
6
|
+
require 'less2sass/less/tree/call_node'
|
7
|
+
require 'less2sass/less/tree/color_node'
|
8
|
+
require 'less2sass/less/tree/combinator_node'
|
9
|
+
require 'less2sass/less/tree/comment_node'
|
10
|
+
require 'less2sass/less/tree/condition_node'
|
11
|
+
require 'less2sass/less/tree/detached_ruleset_node'
|
12
|
+
require 'less2sass/less/tree/dimension_node'
|
13
|
+
require 'less2sass/less/tree/directive_node'
|
14
|
+
require 'less2sass/less/tree/element_node'
|
15
|
+
require 'less2sass/less/tree/expression_node'
|
16
|
+
require 'less2sass/less/tree/extend_node'
|
17
|
+
require 'less2sass/less/tree/import_node'
|
18
|
+
require 'less2sass/less/tree/keyword_node'
|
19
|
+
require 'less2sass/less/tree/media_node'
|
20
|
+
require 'less2sass/less/tree/mixin_call_node'
|
21
|
+
require 'less2sass/less/tree/mixin_definition_node'
|
22
|
+
require 'less2sass/less/tree/negative_node'
|
23
|
+
require 'less2sass/less/tree/operation_node'
|
24
|
+
require 'less2sass/less/tree/paren_node'
|
25
|
+
require 'less2sass/less/tree/quoted_node'
|
26
|
+
require 'less2sass/less/tree/rule_node'
|
27
|
+
require 'less2sass/less/tree/ruleset_call_node'
|
28
|
+
require 'less2sass/less/tree/ruleset_node'
|
29
|
+
require 'less2sass/less/tree/selector_node'
|
30
|
+
require 'less2sass/less/tree/unicode_descriptor_node'
|
31
|
+
require 'less2sass/less/tree/unit_node'
|
32
|
+
require 'less2sass/less/tree/url_node'
|
33
|
+
require 'less2sass/less/tree/value_node'
|
34
|
+
require 'less2sass/less/tree/variable_node'
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Sass
|
3
|
+
# Wrapped Sass AST
|
4
|
+
class ASTHandler
|
5
|
+
# Creates an empty Sass AST.
|
6
|
+
#
|
7
|
+
# @param [::Sass::Tree::Node] tree the Sass AST
|
8
|
+
def initialize(tree)
|
9
|
+
@tree = tree
|
10
|
+
end
|
11
|
+
|
12
|
+
# Appends child notes to the empty Sass AST.
|
13
|
+
#
|
14
|
+
# Note, that this should be called only once.
|
15
|
+
#
|
16
|
+
# @param [::Sass::Tree::Node] child the rest
|
17
|
+
# of the converted Less AST
|
18
|
+
def <<(child)
|
19
|
+
# TODO: check if child.is_a?(::Sass::Tree::Node) and raise some error, if not
|
20
|
+
@tree << child
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_css
|
25
|
+
@tree.render
|
26
|
+
end
|
27
|
+
|
28
|
+
# Outputs the transformed and converted AST
|
29
|
+
# in the form of Sass code.
|
30
|
+
#
|
31
|
+
# @todo method cannot handle import nodes, yet - single files only
|
32
|
+
#
|
33
|
+
# @param [String, IO] destination the base directory
|
34
|
+
# or an IO Stream where the converted projects
|
35
|
+
# should be outputted.
|
36
|
+
def code_gen(destination = nil)
|
37
|
+
code = @tree.to_scss
|
38
|
+
return code unless destination
|
39
|
+
if destination.is_a?(String)
|
40
|
+
open_file(destination, 'w') { |file| file.write(code) }
|
41
|
+
else
|
42
|
+
destination.write(code)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def open_file(filename, flag = 'r')
|
47
|
+
return if filename.nil?
|
48
|
+
return File.open(filename, flag) unless block_given?
|
49
|
+
yield File.open(filename, flag)
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_yaml
|
53
|
+
@tree.to_yaml
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Sass
|
3
|
+
class Parser
|
4
|
+
def initialize(input)
|
5
|
+
@input = input
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse
|
9
|
+
sass_file_content = File.read(@input)
|
10
|
+
sass_file_path = File.expand_path(@input)
|
11
|
+
tree = ::Sass::Engine.new(
|
12
|
+
sass_file_content,
|
13
|
+
:syntax => :scss, :filename => sass_file_path
|
14
|
+
).to_tree
|
15
|
+
::Sass::Tree::Visitors::CheckNesting.visit(tree)
|
16
|
+
::Sass::Tree::Visitors::Perform.visit(tree)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Util
|
3
|
+
extend self
|
4
|
+
|
5
|
+
# Returns a file's path relative to the Less2Sass root directory.
|
6
|
+
#
|
7
|
+
# @param file [String] The filename relative to the Less2Sass root
|
8
|
+
# @return [String] The filename relative to the the working directory
|
9
|
+
def scope(file)
|
10
|
+
File.join(Less2Sass::ROOT_DIR, file)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Formats a multiline console input, so it can be passed as an argument
|
14
|
+
# to a console application.
|
15
|
+
#
|
16
|
+
# @return [String] properly formatted multiline argument
|
17
|
+
def read_stdin_as_multiline_arg
|
18
|
+
str = ''
|
19
|
+
puts 'Write your code below, so it can be converted for you.'
|
20
|
+
while line = gets
|
21
|
+
line["\n"] = "\\\n"
|
22
|
+
str << line
|
23
|
+
end
|
24
|
+
str
|
25
|
+
end
|
26
|
+
|
27
|
+
# Formats class names properly.
|
28
|
+
#
|
29
|
+
# @return [String] formatted class name
|
30
|
+
# @example formats dashed class name
|
31
|
+
# "anonymous_node".classify #=> "AnonymousNode"
|
32
|
+
def classify(str)
|
33
|
+
str.split('_').collect!(&:capitalize).join
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/less2sass.rb
ADDED