css_compare 0.1.3 → 0.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.
- checksums.yaml +4 -4
- data/lib/css_compare/constants.rb +1 -1
- data/lib/css_compare/css.rb +1 -0
- data/lib/css_compare/css/component/base.rb +13 -2
- data/lib/css_compare/css/component/property.rb +7 -2
- data/lib/css_compare/css/component/value.rb +18 -41
- data/lib/css_compare/css/engine.rb +5 -2
- data/lib/css_compare/css/value/base.rb +84 -0
- data/lib/css_compare/css/value/function.rb +65 -0
- data/lib/css_compare/css/value/list_literal.rb +26 -0
- data/lib/css_compare/css/value/literal.rb +58 -0
- data/lib/css_compare/css/value/url.rb +20 -0
- data/lib/css_compare/css/value_factory.rb +29 -0
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fca000673eaa0c61fd27e1183311064be28dedc7
|
4
|
+
data.tar.gz: 78a349c577139e8e94f866f46bb2f5bcbacde6d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8943b8ac544e8e76b302f9c3cd03671d02f74676ae6fca0886d86c7772d9f3ef64695f2641d5f7e0de0ee8796c7725c8174ba714497794d13a320ae151de722d
|
7
|
+
data.tar.gz: 3b451d7188514141afd63dc1fedc135bf306a94c47cbfba45efb96eedc4d39627cb199eeb77cda4403712e10f0dd4dc69176923979ca972073a00d50f23c8b79
|
data/lib/css_compare/css.rb
CHANGED
@@ -11,10 +11,21 @@ module CssCompare
|
|
11
11
|
# @param [Hash] that second hash to compare
|
12
12
|
# @return [Boolean]
|
13
13
|
def ==(this, that)
|
14
|
-
keys = this
|
15
|
-
keys.uniq!
|
14
|
+
keys = merge_keys(this, that)
|
16
15
|
keys.all? { |key| this[key] && that[key] && this[key] == that[key] }
|
17
16
|
end
|
17
|
+
|
18
|
+
def equals?(this, that)
|
19
|
+
keys = merge_keys(this, that)
|
20
|
+
keys.all? { |key| this[key] && that[key] && this[key].equals?(that[key]) }
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def merge_keys(this, that)
|
26
|
+
keys = this.keys + that.keys
|
27
|
+
keys.uniq
|
28
|
+
end
|
18
29
|
end
|
19
30
|
end
|
20
31
|
end
|
@@ -28,7 +28,7 @@ module CssCompare
|
|
28
28
|
def initialize(node, conditions)
|
29
29
|
@name = node.resolved_name
|
30
30
|
@values = {}
|
31
|
-
value = Value.new(node
|
31
|
+
value = Value.new(node)
|
32
32
|
conditions.each { |c| set_value(value.clone, c) }
|
33
33
|
end
|
34
34
|
|
@@ -42,7 +42,8 @@ module CssCompare
|
|
42
42
|
# with.
|
43
43
|
# @return [Boolean]
|
44
44
|
def ==(other)
|
45
|
-
super(@values, other.values)
|
45
|
+
return super(@values, other.values) unless font?
|
46
|
+
equals?(@values, other.values)
|
46
47
|
end
|
47
48
|
|
48
49
|
# Merges the property with another one.
|
@@ -141,6 +142,10 @@ module CssCompare
|
|
141
142
|
val.to_s.include?('!important')
|
142
143
|
end
|
143
144
|
|
145
|
+
def font?
|
146
|
+
@name['font']
|
147
|
+
end
|
148
|
+
|
144
149
|
# Breaks down complex properties like `border` into
|
145
150
|
# smaller chunks (`border-width`, `border-style`, `border-color`)
|
146
151
|
#
|
@@ -4,10 +4,10 @@ module CssCompare
|
|
4
4
|
# Represents the value of a CSS property under
|
5
5
|
# certain conditions declared by @media queries.
|
6
6
|
class Value < Base
|
7
|
-
# @return [
|
7
|
+
# @return [CssCompare::CSS::Value::Base]
|
8
8
|
attr_accessor :value
|
9
9
|
|
10
|
-
# @param [
|
10
|
+
# @param [Sass::Tree::PropNode] val the value of the property
|
11
11
|
def initialize(val)
|
12
12
|
self.value = val
|
13
13
|
end
|
@@ -16,23 +16,25 @@ module CssCompare
|
|
16
16
|
# Equal values mean, that the actual value and
|
17
17
|
# the importance, as well, are set equally.
|
18
18
|
#
|
19
|
-
# @param [Value] other the value to compare this with
|
19
|
+
# @param [CssCompare::CSS::Value::Base] other the value to compare this with
|
20
20
|
# @return [Boolean]
|
21
21
|
def ==(other)
|
22
|
-
@value
|
22
|
+
@value == other.value
|
23
|
+
end
|
24
|
+
|
25
|
+
def equals?(other)
|
26
|
+
@value.equals?(other.value)
|
23
27
|
end
|
24
28
|
|
25
|
-
# Sets the value and the importance of
|
26
|
-
# the {Value} node.
|
27
|
-
#
|
28
29
|
# @private
|
29
|
-
def value=(
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
def value=(val)
|
31
|
+
if val.is_a?(self.class)
|
32
|
+
@is_important = val.important?
|
33
|
+
@value = val.value
|
34
|
+
else
|
35
|
+
@value = ValueFactory.create(val.value)
|
36
|
+
@is_important = @value.important?
|
37
|
+
end
|
36
38
|
end
|
37
39
|
|
38
40
|
# Tells, whether or not the value is marked as !important
|
@@ -44,34 +46,9 @@ module CssCompare
|
|
44
46
|
|
45
47
|
# @return [String] the String representation of this node
|
46
48
|
def to_s
|
47
|
-
@value.to_s
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
CONTAIN_STRING = /['"](.*)['"]/
|
53
|
-
|
54
|
-
# Normalizes string values.
|
55
|
-
#
|
56
|
-
# We can assume, that a value describes a path
|
57
|
-
# if following the removal of leading and trailing
|
58
|
-
# quotes it begins with a `./`. It can be safely
|
59
|
-
# removed without affecting the real value of
|
60
|
-
# the CSS property.
|
61
|
-
#
|
62
|
-
# Examples:
|
63
|
-
# "'path/to/file.css'" #=> "path/to/file.css"
|
64
|
-
# ""\"path/to/file.css\""" #=> ""path/to/file.css""
|
65
|
-
# "./path/to/file.css" #=> "path/to/file.css"
|
66
|
-
#
|
67
|
-
# @param [String] value the string to sanitize
|
68
|
-
# @return [String] sanitized string
|
69
|
-
def sanitize_value(value)
|
70
|
-
value = value.sub(/\A['"](.*)['"]\Z/, '\1').gsub(/\\"|"|'/, '"') # Solves first two examples
|
71
|
-
value = value.sub('./', '') if value.start_with?('url(') # Solves third if it's a url value
|
72
|
-
value
|
49
|
+
@value.to_s
|
73
50
|
end
|
74
51
|
end
|
75
52
|
end
|
76
53
|
end
|
77
|
-
end
|
54
|
+
end
|
@@ -54,6 +54,9 @@ module CssCompare
|
|
54
54
|
attr_accessor :selectors, :keyframes, :namespaces,
|
55
55
|
:pages, :supports, :charset
|
56
56
|
|
57
|
+
# @note UTF-8 is assumed as default charset
|
58
|
+
# @see https://www.w3.org/TR/CSS2/syndata.html#x52
|
59
|
+
#
|
57
60
|
# @param [String, Sass::Tree::Node] input the source file of
|
58
61
|
# the CSS project, or its AST
|
59
62
|
def initialize(input)
|
@@ -76,7 +79,7 @@ module CssCompare
|
|
76
79
|
@pages = {}
|
77
80
|
@supports = {}
|
78
81
|
@unsupported = []
|
79
|
-
@charset
|
82
|
+
@charset = 'UTF-8'
|
80
83
|
end
|
81
84
|
|
82
85
|
# Checks, whether two engines are equal.
|
@@ -278,7 +281,7 @@ module CssCompare
|
|
278
281
|
# a small change in the the selector's name.
|
279
282
|
#
|
280
283
|
# @param [Sass::Tree:RuleNode] node the Rule node
|
281
|
-
# @param [Array<String>]
|
284
|
+
# @param [Array<String>] conditions processed parent_query_list of the
|
282
285
|
# parent media node. If the rule is global, it will be assigned
|
283
286
|
# to the media query equal to `@media all {}`.
|
284
287
|
# @return [Void]
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'color'
|
2
|
+
|
3
|
+
module CssCompare
|
4
|
+
module CSS
|
5
|
+
module Value
|
6
|
+
# The base class for wrapping the CSS property values
|
7
|
+
class Base
|
8
|
+
# @return [Sass::Script::Tree::Node]
|
9
|
+
attr_accessor :value
|
10
|
+
|
11
|
+
# @param [Sass::Script::Tree::Node] value the SassScript value to be wrapped
|
12
|
+
def initialize(value)
|
13
|
+
@value = value
|
14
|
+
end
|
15
|
+
|
16
|
+
# Checks, whether the CSS values are equal
|
17
|
+
#
|
18
|
+
# @return [Boolean]
|
19
|
+
def ==(other)
|
20
|
+
self.class == other.class
|
21
|
+
end
|
22
|
+
|
23
|
+
def equals?(other)
|
24
|
+
self == other
|
25
|
+
end
|
26
|
+
|
27
|
+
# Checks, whether the CSS values are flagged as !important.
|
28
|
+
#
|
29
|
+
# @return [Boolean]
|
30
|
+
def important?
|
31
|
+
@value.to_sass.include?('!important')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Checks, whether the CSS value is a color. Subclasses may
|
35
|
+
# override this method.
|
36
|
+
#
|
37
|
+
# @return [Boolean]
|
38
|
+
def color?
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [String]
|
43
|
+
def to_s
|
44
|
+
@value.to_sass
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
# Normalizes the quoted string values.
|
50
|
+
#
|
51
|
+
# @param [String] value the string to sanitize
|
52
|
+
# @return [String] sanitized string
|
53
|
+
def sanitize_string(value)
|
54
|
+
value.sub(/\A['"](.*)['"]\Z/, '\1').gsub(/\\"|"|'/, '"')
|
55
|
+
end
|
56
|
+
|
57
|
+
def sanitize_font(value)
|
58
|
+
value.gsub(/\\"|"|'/, '')
|
59
|
+
end
|
60
|
+
|
61
|
+
# Normalizes the url paths.
|
62
|
+
#
|
63
|
+
# We can assume, that a value describes a path
|
64
|
+
# if following the removal of leading and trailing
|
65
|
+
# quotes it begins with a `./`. It can be safely
|
66
|
+
# removed without affecting the real value of
|
67
|
+
# the CSS property.
|
68
|
+
#
|
69
|
+
# Examples:
|
70
|
+
# "'path/to/file.css'" #=> "path/to/file.css"
|
71
|
+
# ""\"path/to/file.css\""" #=> ""path/to/file.css""
|
72
|
+
# "./path/to/file.css" #=> "path/to/file.css"
|
73
|
+
#
|
74
|
+
# @param [String] value the url path to normalize
|
75
|
+
# @return [String] the normalized path
|
76
|
+
def sanitize_url(value)
|
77
|
+
value = sanitize_string(value)
|
78
|
+
value = value.sub('./', '') if value.start_with?('./')
|
79
|
+
value
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module CssCompare
|
2
|
+
module CSS
|
3
|
+
module Value
|
4
|
+
# Wraps the SassScript Funcall object
|
5
|
+
class Function < Base
|
6
|
+
|
7
|
+
# Checks, whether two function expressions are equal.
|
8
|
+
#
|
9
|
+
# @param [Function] other the other function expression
|
10
|
+
# @return [Boolean]
|
11
|
+
def ==(other)
|
12
|
+
if color?
|
13
|
+
return false unless other.color?
|
14
|
+
::Color.equivalent?(color, other.color)
|
15
|
+
else
|
16
|
+
return false unless super
|
17
|
+
arg1 = @value.args.length
|
18
|
+
arg2 = other.value.args.length
|
19
|
+
return false unless arg1 == arg2
|
20
|
+
args1 = @value.args.collect { |x| ValueFactory.create(x) }
|
21
|
+
args2 = other.value.args.collect { |x| ValueFactory.create(x) }
|
22
|
+
args1.each_index { |i| args1[i] == args2[i] }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# @see Base#color?
|
27
|
+
def color?
|
28
|
+
rgb? || hsl?
|
29
|
+
end
|
30
|
+
|
31
|
+
def color
|
32
|
+
raise StandardError, 'Function not a color' unless color?
|
33
|
+
args = @value.args.collect { |x| x.value.value }
|
34
|
+
if rgb?
|
35
|
+
::Color::RGB.new(args[0], args[1], args[2])
|
36
|
+
elsif hsl?
|
37
|
+
::Color::HSL.new(args[0], args[1], args[2])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def alpha?
|
42
|
+
@value.args.length == 4
|
43
|
+
end
|
44
|
+
|
45
|
+
def alpha
|
46
|
+
return @value.args[3] if alpha?
|
47
|
+
false
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
RGB_COLOR_FUNCTIONS = %w(rgb rgba)
|
53
|
+
HSL_COLOR_FUNCTIONS = %w(hsl hsla)
|
54
|
+
|
55
|
+
def rgb?
|
56
|
+
RGB_COLOR_FUNCTIONS.include?(@value.name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def hsl?
|
60
|
+
HSL_COLOR_FUNCTIONS.include?(@value.name)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module CssCompare
|
2
|
+
module CSS
|
3
|
+
module Value
|
4
|
+
# Wraps the SassScript ListLiteral object.
|
5
|
+
class ListLiteral < Base
|
6
|
+
|
7
|
+
# Checks, whether two list literals are equal.
|
8
|
+
#
|
9
|
+
# @param [ListLiteral] other the other list literal
|
10
|
+
# @return [Boolean]
|
11
|
+
def ==(other)
|
12
|
+
return false unless super
|
13
|
+
elements1 = @value.elements.length
|
14
|
+
elements2 = other.value.elements.length
|
15
|
+
return false unless elements1 == elements2
|
16
|
+
@value.elements.each_index do |i|
|
17
|
+
value1 = sanitize_string(@value.elements[i].to_sass)
|
18
|
+
value2 = sanitize_string(other.value.elements[i].to_sass)
|
19
|
+
return false unless value1 == value2
|
20
|
+
end
|
21
|
+
true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module CssCompare
|
2
|
+
module CSS
|
3
|
+
module Value
|
4
|
+
# Wraps the SassScript Literal object.
|
5
|
+
class Literal < Base
|
6
|
+
|
7
|
+
# Checks, whether two literals are equal.
|
8
|
+
#
|
9
|
+
# @param [Literal] other the other literal
|
10
|
+
# @return [Boolean]
|
11
|
+
def ==(other)
|
12
|
+
if color?
|
13
|
+
return false unless other.color?
|
14
|
+
::Color.equivalent?(color, other.color)
|
15
|
+
else
|
16
|
+
return false unless super
|
17
|
+
value1 = sanitize_string(@value.to_sass)
|
18
|
+
value2 = sanitize_string(other.value.to_sass)
|
19
|
+
value1 == value2
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def equals?(other)
|
24
|
+
value1 = sanitize_font(@value.to_sass)
|
25
|
+
value2 = sanitize_font(other.value.to_sass)
|
26
|
+
value1 == value2
|
27
|
+
end
|
28
|
+
|
29
|
+
def color?
|
30
|
+
named_color? || hex_color?
|
31
|
+
end
|
32
|
+
|
33
|
+
def color
|
34
|
+
return nil unless color?
|
35
|
+
hex_color? ? hex_color : named_color
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
HEX_COLOR_LITERAL = /^#(?:[a-f0-9]{3}){1,2}$/i
|
41
|
+
|
42
|
+
def named_color?
|
43
|
+
::Color::CSS[@value.to_sass]
|
44
|
+
end
|
45
|
+
|
46
|
+
alias_method :named_color, :named_color?
|
47
|
+
|
48
|
+
def hex_color?
|
49
|
+
@value.to_sass =~ HEX_COLOR_LITERAL
|
50
|
+
end
|
51
|
+
|
52
|
+
def hex_color
|
53
|
+
::Color::RGB.by_hex(@value.to_sass)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CssCompare
|
2
|
+
module CSS
|
3
|
+
module Value
|
4
|
+
# Wraps the SassScript `url` Funcall.
|
5
|
+
class Url < Base
|
6
|
+
|
7
|
+
# Checks, whether two url calls are equal.
|
8
|
+
#
|
9
|
+
# @param [Url] other the other url call
|
10
|
+
# @return [Boolean]
|
11
|
+
def ==(other)
|
12
|
+
return false unless super
|
13
|
+
value1 = sanitize_url(@value.args[0].value.value)
|
14
|
+
value2 = sanitize_url(other.value.args[0].value.value)
|
15
|
+
value1 == value2
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'css_compare/css/value/base'
|
2
|
+
require 'css_compare/css/value/literal'
|
3
|
+
require 'css_compare/css/value/list_literal'
|
4
|
+
require 'css_compare/css/value/function'
|
5
|
+
require 'css_compare/css/value/url'
|
6
|
+
|
7
|
+
module CssCompare
|
8
|
+
module CSS
|
9
|
+
module ValueFactory
|
10
|
+
|
11
|
+
# Creates the value object by applying the appropriate wrapper class.
|
12
|
+
#
|
13
|
+
# @param [Sass::Script::Tree::Node] value the CSS property's value
|
14
|
+
# @return [CssCompare::CSS::Value::Base] the wrapped property value
|
15
|
+
def self.create(value)
|
16
|
+
if value.is_a?(Sass::Script::Tree::Literal)
|
17
|
+
Value::Literal.new(value)
|
18
|
+
elsif value.is_a?(Sass::Script::Tree::ListLiteral)
|
19
|
+
Value::ListLiteral.new(value)
|
20
|
+
elsif value.is_a?(Sass::Script::Tree::Funcall)
|
21
|
+
return Value::Function.new(value) unless value.name == 'url'
|
22
|
+
Value::Url.new(value)
|
23
|
+
else
|
24
|
+
raise StandardError, 'Unsupported type of CSS value'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: css_compare
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Attila Večerek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sass
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: color
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.8'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.8'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,6 +96,12 @@ files:
|
|
82
96
|
- lib/css_compare/css/component/value.rb
|
83
97
|
- lib/css_compare/css/engine.rb
|
84
98
|
- lib/css_compare/css/parser.rb
|
99
|
+
- lib/css_compare/css/value/base.rb
|
100
|
+
- lib/css_compare/css/value/function.rb
|
101
|
+
- lib/css_compare/css/value/list_literal.rb
|
102
|
+
- lib/css_compare/css/value/literal.rb
|
103
|
+
- lib/css_compare/css/value/url.rb
|
104
|
+
- lib/css_compare/css/value_factory.rb
|
85
105
|
- lib/css_compare/engine.rb
|
86
106
|
- lib/css_compare/exec.rb
|
87
107
|
- lib/css_compare/util.rb
|