less_to_sass 0.1.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.
- 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,32 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# Represents the elements of a {SelectorNode}.
|
5
|
+
# These elements are usually separated by a
|
6
|
+
# {CombinatorNode}.
|
7
|
+
#
|
8
|
+
# No equivalent in Sass.
|
9
|
+
class ElementNode < Node
|
10
|
+
# @return [Tree::CombinatorNode]
|
11
|
+
attr_accessor :combinator
|
12
|
+
# @return [String]
|
13
|
+
attr_accessor :value
|
14
|
+
# @return [Integer]
|
15
|
+
attr_accessor :index
|
16
|
+
# @return [Hash]
|
17
|
+
attr_accessor :currentFileInfo
|
18
|
+
|
19
|
+
# @see Node#to_sass
|
20
|
+
def to_sass
|
21
|
+
if @value.is_a?(VariableNode)
|
22
|
+
@value.to_sass
|
23
|
+
elsif @value.is_a?(String)
|
24
|
+
@combinator.to_s + @value
|
25
|
+
else
|
26
|
+
raise FeatureConversionError, self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# Represents the expression in the Less AST.
|
5
|
+
#
|
6
|
+
# Sass does not have an Expression node. It is usually
|
7
|
+
# represented as the `expr` member of the {::Sass::Tree::VariableNode},
|
8
|
+
# that represents a variable definition.
|
9
|
+
#
|
10
|
+
# The Sass equivalent is either {::Sass::Script::Value::Base}
|
11
|
+
# wrapped in {::Sass::Script::Tree::Literal} or {::Sass::Tree::Node}.
|
12
|
+
class ExpressionNode < Node
|
13
|
+
attr_accessor :value
|
14
|
+
|
15
|
+
# @return [::Sass::Script::Tree::Literal, ::Sass::Script::Tree::ListLiteral, ::Sass::Tree::Node]
|
16
|
+
# @see Node#to_sass
|
17
|
+
def to_sass
|
18
|
+
if @value.is_a?(Array)
|
19
|
+
# TODO: document solution of: method to_sass is invoked on "to right":String, deal with it
|
20
|
+
if is_multiword_keyword?
|
21
|
+
multiword_keyword_argument
|
22
|
+
elsif should_be_literal?
|
23
|
+
@value.inject([]) { |value, elem| value << elem.to_s }.join(' ')
|
24
|
+
else
|
25
|
+
elements = @value.inject([]) do |value, elem|
|
26
|
+
node = elem.to_sass
|
27
|
+
node = node(::Sass::Script::Tree::Literal.new(node), line) if node.is_a?(::Sass::Script::Value::Base)
|
28
|
+
value << node
|
29
|
+
end
|
30
|
+
node(::Sass::Script::Tree::ListLiteral.new(elements, :space), line)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
value = @value.to_sass
|
34
|
+
return value unless value.is_a?(::Sass::Script::Value::Base)
|
35
|
+
node(::Sass::Script::Tree::Literal.new(value), line)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
LITERAL_PROPERTIES = %w(font transition).freeze
|
42
|
+
|
43
|
+
# @todo: should be checked once more
|
44
|
+
def is_multiword_keyword?
|
45
|
+
@value.select { |elem| !elem.is_a?(KeywordNode) }.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
# Checks, whether the expression contains a {VariableNode}.
|
49
|
+
# Some properties in Less store their values as string literals
|
50
|
+
# instead of list literals.
|
51
|
+
#
|
52
|
+
# @return [Boolean] true if the expression should be converted
|
53
|
+
# to {::Sass::Script::Tree::Literal}
|
54
|
+
def should_be_literal?
|
55
|
+
grandparent = @parent.parent
|
56
|
+
return false unless grandparent.is_a?(RuleNode)
|
57
|
+
LITERAL_PROPERTIES.include?(grandparent.name.value) && !contains_variables?
|
58
|
+
end
|
59
|
+
|
60
|
+
# Creates a {::Sass::Script::Tree::ListLiteral} out of
|
61
|
+
# multiple keywords - usually referencing a complex CSS keyword.
|
62
|
+
#
|
63
|
+
# Example (`to right` is an example of multiword keyword):
|
64
|
+
# `list-style-image: linear-gradient(to right, rgba(255,0,0,0), rgba(255,0,0,1));`
|
65
|
+
#
|
66
|
+
def multiword_keyword_argument
|
67
|
+
keywords = @value.inject([]) { |value, elem| value << elem.to_sass }
|
68
|
+
node(::Sass::Script::Tree::ListLiteral.new(keywords, :space), line)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
class ExtendNode < Node
|
5
|
+
attr_accessor :selector
|
6
|
+
attr_accessor :option
|
7
|
+
attr_accessor :index
|
8
|
+
attr_accessor :object_id
|
9
|
+
attr_accessor :parent_ids
|
10
|
+
attr_accessor :currentFileInfo
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# Represents the CSS property names and
|
5
|
+
# a little bit more.
|
6
|
+
#
|
7
|
+
# It can represent the name of a CSS rule,
|
8
|
+
# or it can be a part of a variable definition's
|
9
|
+
# value.
|
10
|
+
#
|
11
|
+
# In the latter case its Sass equivalents are:
|
12
|
+
# - {::Sass::Script::Value::Bool}
|
13
|
+
# - {::Sass::Script::Value::Null}
|
14
|
+
class KeywordNode < Node
|
15
|
+
attr_accessor :value
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
@value.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def empty?
|
22
|
+
@value.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns a SassScript Value node.
|
26
|
+
#
|
27
|
+
# Usually will be called in case of a variable
|
28
|
+
# definition and its parent node would be a
|
29
|
+
# {ExpressionNode}, which would wrap it up into a
|
30
|
+
# {::Sass::Script::Tree::Literal}.
|
31
|
+
#
|
32
|
+
# @raise FeatureConversionError if this node's value is not expected.
|
33
|
+
# @return [::Sass::Script::Value::Base]
|
34
|
+
# @see Node#to_sass
|
35
|
+
def to_sass
|
36
|
+
case @value
|
37
|
+
when 'true' then ::Sass::Script::Value::Bool.new(true)
|
38
|
+
when 'false' then ::Sass::Script::Value::Bool.new(false)
|
39
|
+
when 'null' then ::Sass::Script::Value::Null.new
|
40
|
+
else
|
41
|
+
raise FeatureConversionError, self unless @value.respond_to?(:to_s)
|
42
|
+
string = ::Sass::Script::Value::String.new(@value.to_s)
|
43
|
+
node(::Sass::Script::Tree::Literal.new(string), line)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
class MixinDefinitionNode < Node
|
5
|
+
attr_accessor :name
|
6
|
+
attr_accessor :selectors
|
7
|
+
attr_accessor :params
|
8
|
+
attr_accessor :condition
|
9
|
+
attr_accessor :variadic
|
10
|
+
attr_accessor :arity
|
11
|
+
attr_accessor :rules
|
12
|
+
attr_accessor :_lookups
|
13
|
+
attr_accessor :required
|
14
|
+
attr_accessor :optionalParameters
|
15
|
+
attr_accessor :frames
|
16
|
+
|
17
|
+
# @see Node#creates_environment?
|
18
|
+
def creates_environment?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
require 'less2sass/less/environment'
|
2
|
+
|
3
|
+
module Less2Sass
|
4
|
+
module Less
|
5
|
+
module Tree
|
6
|
+
# The base node class of the Less AST.
|
7
|
+
class Node
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
# The parent node of this node.
|
11
|
+
#
|
12
|
+
# @return [Less2Sass::Less::Tree::Node]
|
13
|
+
attr_accessor :parent
|
14
|
+
|
15
|
+
# Whether or not this node has parent node.
|
16
|
+
#
|
17
|
+
# @return [Boolean]
|
18
|
+
attr_reader :has_parent
|
19
|
+
|
20
|
+
# The child nodes of this node.
|
21
|
+
#
|
22
|
+
# @return [Array<Less2Sass::Less::Tree::Node>]
|
23
|
+
attr_accessor :children
|
24
|
+
|
25
|
+
# Whether or not this node has child nodes.
|
26
|
+
#
|
27
|
+
# @return [Boolean]
|
28
|
+
attr_reader :has_children
|
29
|
+
|
30
|
+
# Sets the line number of the node
|
31
|
+
#
|
32
|
+
# @return [Void]
|
33
|
+
attr_writer :line
|
34
|
+
|
35
|
+
# This member gets set if the node's children contain
|
36
|
+
# referenced {VariableNode}s.
|
37
|
+
#
|
38
|
+
# @return [Array<String>] referenced variable names
|
39
|
+
attr_accessor :ref_vars
|
40
|
+
|
41
|
+
# The environment, where the nodes sits lexically.
|
42
|
+
# TODO: Consider to set a reference to the lexical scope (the environment) of the node.
|
43
|
+
# @return [Less2Sass::Less::Environment]
|
44
|
+
# attr_reader :env
|
45
|
+
|
46
|
+
# The current line number the conversion process is at
|
47
|
+
@@lines = 0
|
48
|
+
|
49
|
+
def initialize(parent)
|
50
|
+
@children = []
|
51
|
+
@parent = parent
|
52
|
+
@creates_new_line = false
|
53
|
+
end
|
54
|
+
|
55
|
+
# @private
|
56
|
+
def parent=(parent)
|
57
|
+
@has_parent ||= !parent.nil?
|
58
|
+
@parent = parent
|
59
|
+
end
|
60
|
+
|
61
|
+
# @private
|
62
|
+
def children=(children)
|
63
|
+
@has_children ||= !children.empty?
|
64
|
+
@children = children
|
65
|
+
end
|
66
|
+
|
67
|
+
# @private
|
68
|
+
def ref_vars
|
69
|
+
@ref_vars || get_referenced_variable_names
|
70
|
+
end
|
71
|
+
|
72
|
+
# Tells, whether the node creates a new context
|
73
|
+
# or variable environment.
|
74
|
+
#
|
75
|
+
# @return [Boolean]
|
76
|
+
def creates_context?
|
77
|
+
false
|
78
|
+
end
|
79
|
+
|
80
|
+
# Appends a child to the node.
|
81
|
+
#
|
82
|
+
# @param [Less2Sass::Less::Tree::Node, Array<Less2Sass::Less::Tree::Node>] child
|
83
|
+
# The child node or nodes
|
84
|
+
def <<(child)
|
85
|
+
return if child.nil?
|
86
|
+
if child.is_a?(Array)
|
87
|
+
child.each { |c| self << c }
|
88
|
+
else
|
89
|
+
@has_children = true
|
90
|
+
child.parent = self
|
91
|
+
@children << child
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Compares this node and another object (only other {Less2Sass::Less::Tree::Node}s will be equal).
|
96
|
+
#
|
97
|
+
# @param [Object] other The object to compare with
|
98
|
+
# @return [Boolean] Whether or not this node and the other object
|
99
|
+
# are the same
|
100
|
+
def ==(other)
|
101
|
+
self.class == other.class && other.children == children
|
102
|
+
end
|
103
|
+
|
104
|
+
# Iterates through each node in the tree rooted at this node
|
105
|
+
# in a pre-order walk.
|
106
|
+
#
|
107
|
+
# @yield node
|
108
|
+
# @yieldparam node [Less2Sass::Less::Tree::Node] a node in the tree
|
109
|
+
def each
|
110
|
+
yield self
|
111
|
+
children.each { |c| c.each { |n| yield n } }
|
112
|
+
end
|
113
|
+
|
114
|
+
# The base implementation of transform.
|
115
|
+
#
|
116
|
+
# Transforms the tree by its traversal. Each respective node type
|
117
|
+
# should implement the specific transformation and calling `#super`.
|
118
|
+
# The position, where `#super` is called determines the walking order.
|
119
|
+
# The standard should be post-order walk - transforming the child nodes
|
120
|
+
# first and self as last.
|
121
|
+
#
|
122
|
+
# Should be overridden by subclasses adding specific implementation.
|
123
|
+
#
|
124
|
+
# @param [Less2Sass::Less::Environment] env parent environment
|
125
|
+
# @return [Void]
|
126
|
+
def transform(env = nil)
|
127
|
+
# TODO: Consider to set a reference to the lexical scope (the environment) of the node.
|
128
|
+
# @env = env
|
129
|
+
@children.each { |c| c.transform(env) }
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns the line number and sets the class level
|
133
|
+
# current line number based on the passed option.
|
134
|
+
#
|
135
|
+
# @param [Symbol] opt the line number option
|
136
|
+
# @option opt [Symbol] :new tells the method to
|
137
|
+
# return the next line and increments @@lines
|
138
|
+
# @option opt [Symbol] :current tells the method to
|
139
|
+
# return the current line the converter is "processing"
|
140
|
+
#
|
141
|
+
# @return [Fixnum] the line number based on the given option
|
142
|
+
def line(opt = :current)
|
143
|
+
case opt
|
144
|
+
when :current
|
145
|
+
@@lines
|
146
|
+
when :new
|
147
|
+
@@lines = @@lines.next
|
148
|
+
else
|
149
|
+
raise StandardError, "Option can't be other than :current or :new"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Converts this node to the equivalent Sass node
|
154
|
+
#
|
155
|
+
# Should be overwritten by subclasses.
|
156
|
+
# All subclasses should also set the line number
|
157
|
+
# of the resulting Sass node.
|
158
|
+
#
|
159
|
+
# @raise NotImplementedError if called on the base node object
|
160
|
+
# or subclass method not implemented, yet.
|
161
|
+
def to_sass
|
162
|
+
raise NotImplementedError
|
163
|
+
end
|
164
|
+
|
165
|
+
# Loops through the children nodes and
|
166
|
+
# searches for variable occurrences.
|
167
|
+
#
|
168
|
+
# @return [Array<String>] list of variable names
|
169
|
+
# contained in the value's expressions
|
170
|
+
# @note Use on {Less2Sass::Less::Tree::RuleNode}s. It's a good practice
|
171
|
+
# to check first if it's a variable definition.
|
172
|
+
# See (Less2Sass::Less::Tree::RuleNode#is_variable_definition?)
|
173
|
+
def get_referenced_variable_names
|
174
|
+
if is_a?(VariableNode)
|
175
|
+
[@name]
|
176
|
+
else
|
177
|
+
@children.inject([]) { |vars, c| vars + c.get_referenced_variable_names }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Checks, whether a variable is referenced in the scope of the node.
|
182
|
+
#
|
183
|
+
# @return [Boolean]
|
184
|
+
def contains_variables?
|
185
|
+
variables = nil
|
186
|
+
each do |child|
|
187
|
+
if child.is_a?(VariableNode)
|
188
|
+
variables = true
|
189
|
+
break
|
190
|
+
end
|
191
|
+
end
|
192
|
+
variables
|
193
|
+
end
|
194
|
+
|
195
|
+
protected
|
196
|
+
|
197
|
+
# Sets up a node with the mandatory options (line, options).
|
198
|
+
#
|
199
|
+
# @param [::Sass::Tree::Node, ::Sass::Script::Tree::Node] node
|
200
|
+
# the node to be set up
|
201
|
+
# @param [Fixnum] line the line number, where the node sits lexically
|
202
|
+
# @param [Hash] options the options to pass to the node
|
203
|
+
# @return [::Sass::Tree::Node, ::Sass::Script::Tree::Node] the set up node
|
204
|
+
def node(node, line, options = { :style => :nested })
|
205
|
+
node.line = line if line
|
206
|
+
node.options = options if node.class.method_defined?(:options=)
|
207
|
+
node
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# Node representing the operation with 2 operands.
|
5
|
+
#
|
6
|
+
# Converts to {::Sass::Script::Tree::Operation}.
|
7
|
+
class OperationNode < Node
|
8
|
+
attr_accessor :op
|
9
|
+
attr_accessor :operands
|
10
|
+
attr_accessor :isSpaced
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
@operands[0].to_s + @op + @operands[1].to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
# @see Node#to_sass
|
17
|
+
def to_sass
|
18
|
+
node(::Sass::Script::Tree::Operation.new(@operands[0].to_sass, @operands[1].to_sass, sass_operator), line)
|
19
|
+
end
|
20
|
+
|
21
|
+
# A hash from operator strings to the corresponding token types.
|
22
|
+
#
|
23
|
+
# Copied from Sass' lexer
|
24
|
+
# @see https://github.com/sass/sass/blob/stable/lib/sass/script/lexer.rb#L44-L69
|
25
|
+
OPERATORS = {
|
26
|
+
'+' => :plus,
|
27
|
+
'-' => :minus,
|
28
|
+
'*' => :times,
|
29
|
+
'/' => :div,
|
30
|
+
'%' => :mod,
|
31
|
+
'=' => :single_eq,
|
32
|
+
':' => :colon,
|
33
|
+
'(' => :lparen,
|
34
|
+
')' => :rparen,
|
35
|
+
',' => :comma,
|
36
|
+
'and' => :and,
|
37
|
+
'or' => :or,
|
38
|
+
'not' => :not,
|
39
|
+
'==' => :eq,
|
40
|
+
'!=' => :neq,
|
41
|
+
'>=' => :gte,
|
42
|
+
'<=' => :lte,
|
43
|
+
'>' => :gt,
|
44
|
+
'<' => :lt,
|
45
|
+
'#{' => :begin_interpolation,
|
46
|
+
'}' => :end_interpolation,
|
47
|
+
';' => :semicolon,
|
48
|
+
'{' => :lcurly,
|
49
|
+
'...' => :splat
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
# Returns the sass operator symbol, that is used internally.
|
53
|
+
#
|
54
|
+
# @param [String] op the operator to look for
|
55
|
+
# @return [Symbol] the operator symbol
|
56
|
+
def sass_operator(op = @op)
|
57
|
+
raise Less2Sass::OperatorConversionError, op unless OPERATORS[op]
|
58
|
+
OPERATORS[op]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Less2Sass
|
2
|
+
module Less
|
3
|
+
module Tree
|
4
|
+
# Represents a single or double-quoted string in Less.
|
5
|
+
#
|
6
|
+
# The Sass equivalent is a {::Sass::Script::Value::String}
|
7
|
+
# wrapped in {::Sass::Script::Tree::Literal}.
|
8
|
+
class QuotedNode < Node
|
9
|
+
attr_accessor :escaped
|
10
|
+
attr_accessor :value
|
11
|
+
attr_accessor :quote
|
12
|
+
attr_accessor :index
|
13
|
+
attr_accessor :currentFileInfo
|
14
|
+
|
15
|
+
# Returns the Sass equivalent for a quoted string.
|
16
|
+
#
|
17
|
+
# @return [::Sass::Script::Tree::Literal] simple string literal
|
18
|
+
# @return [::Sass::Script::Tree::StringInterpolation] interpolation node,
|
19
|
+
# if the string contains interpolations
|
20
|
+
# @see Node#to_sass
|
21
|
+
def to_sass
|
22
|
+
if string_interpolation?
|
23
|
+
interpolation_node(@value)
|
24
|
+
else
|
25
|
+
node(::Sass::Script::Tree::Literal.new(::Sass::Script::Value::String.new(@value, :string)), line)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the string's raw value without passing the type of quote.
|
30
|
+
#
|
31
|
+
# Sass has its own standards regarding the quotes, it should be in
|
32
|
+
# Sass' competences to choose what type of quote to use.
|
33
|
+
def to_s
|
34
|
+
@value
|
35
|
+
end
|
36
|
+
|
37
|
+
# Checks, whether the quoted string contains an interpolation.
|
38
|
+
#
|
39
|
+
# @return [Boolean]
|
40
|
+
def string_interpolation?(value = @value)
|
41
|
+
!value.index(INTERPOLATION).nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
INTERPOLATION = /(@\{[\w_-]*\})/
|
47
|
+
VARIABLE_NAME = /@\{([\w_-]*)\}/
|
48
|
+
|
49
|
+
# Creates a {::Sass::Script::Tree::StringInterpolation} node.
|
50
|
+
#
|
51
|
+
# @param [String] value the string containing interpolation(s)
|
52
|
+
# @return [::Sass::Script::Tree::StringInterpolation] the interpolation node
|
53
|
+
def interpolation_node(value)
|
54
|
+
parts = value.split(INTERPOLATION, 2) # Must be split maximally into 3 parts
|
55
|
+
parts[2] = '' if parts.length == 2 # Always must have 3 parts
|
56
|
+
before = node(::Sass::Script::Tree::Literal.new(::Sass::Script::Value::String.new(parts[0], :string)), line)
|
57
|
+
mid = node(::Sass::Script::Tree::Variable.new(parts[1].match(VARIABLE_NAME)[1]), line)
|
58
|
+
after = string_interpolation?(parts[2]) ? interpolation_node(parts[2]) : node(::Sass::Script::Tree::Literal.new(::Sass::Script::Value::String.new(parts[2], :string)), line)
|
59
|
+
node(::Sass::Script::Tree::StringInterpolation.new(before, mid, after), line)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|