css-native 0.1.2 → 0.1.3
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-native.rb +1 -28
- data/lib/css-native/errors.rb +41 -7
- data/lib/css-native/rule.rb +72 -134
- data/lib/css-native/rule/constants.rb +96 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b43f3acebaa6a120dbf30767223cf2ad94c7517498d4e0df41a5b4b6b95a7bb9
|
4
|
+
data.tar.gz: d2333285b9a95b1ef6ef396c4005bc44e9a6b19e7e9ced18e623b1e81d9f090b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d2c91d4ac29d3ef89eacfa52829277feae315397aae88c47a9825603cc4dc4bfbd4c1167c402f3c8de52bdac85639b5a158785a22a53c2ec8bf61243fe4ec9b
|
7
|
+
data.tar.gz: fdb8421c46210b287ce282a9caa8df4b2e049367540e87f26606609e5a6134ef9e1ad8de1c36c4ea084541ff4a44d2b710e55d3349b98863a3101765c4e3b79b
|
data/lib/css-native.rb
CHANGED
@@ -9,33 +9,6 @@ class CSSNative
|
|
9
9
|
sheet
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.format_element(name)
|
13
|
-
name.to_s
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.format_class(name)
|
17
|
-
".#{name}"
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.format_id(name)
|
21
|
-
"##{name}"
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.format_attribute(name, operation = :none, value = nil, case_sensitive: true)
|
25
|
-
op = case operation.to_sym
|
26
|
-
when :none then ""
|
27
|
-
when :equals then "="
|
28
|
-
when :include then "~="
|
29
|
-
when :matches then "|="
|
30
|
-
when :starts_with then "^="
|
31
|
-
when :ends_with then "$="
|
32
|
-
when :contains then "*="
|
33
|
-
else
|
34
|
-
raise AttributeError.new("undefined comparison '#{operation}' for css attribute selector")
|
35
|
-
end
|
36
|
-
"[#{name}#{op}#{value.nil? ? "" : "\"#{value}\""}#{case_sensitive ? "" : " i"}]"
|
37
|
-
end
|
38
|
-
|
39
12
|
attr_reader :rules
|
40
13
|
def initialize
|
41
14
|
@rules = []
|
@@ -73,7 +46,7 @@ class CSSNative
|
|
73
46
|
when :attribute
|
74
47
|
attribute(name, *args)
|
75
48
|
else
|
76
|
-
raise RuleError.new(
|
49
|
+
raise RuleError.new(rule: type)
|
77
50
|
end
|
78
51
|
end
|
79
52
|
|
data/lib/css-native/errors.rb
CHANGED
@@ -1,16 +1,53 @@
|
|
1
1
|
class CSSNative
|
2
2
|
class CSSError < StandardError
|
3
|
+
def initialize(msg = "Invalid CSS")
|
4
|
+
super(msg)
|
5
|
+
end
|
3
6
|
end
|
4
7
|
|
5
8
|
class RuleError < CSSError
|
9
|
+
def initialize(msg = "Invalid rule type", rule: nil)
|
10
|
+
if rule.nil?
|
11
|
+
super(msg)
|
12
|
+
else
|
13
|
+
super("Invalid rule type '#{rule}'")
|
14
|
+
end
|
15
|
+
end
|
6
16
|
end
|
7
|
-
|
8
|
-
class
|
9
|
-
def initialize(
|
10
|
-
super(
|
17
|
+
|
18
|
+
class AttributeError < CSSError
|
19
|
+
def initialize(msg = "Invalid attribute structure")
|
20
|
+
super(msg)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class AttributeComparisonError < AttributeError
|
25
|
+
def initialize(msg = "Invalid attrubute comparison", comparison: nil)
|
26
|
+
if comparison.nil?
|
27
|
+
super(msg)
|
28
|
+
else
|
29
|
+
super(msg + " '#{comparison}'")
|
30
|
+
end
|
11
31
|
end
|
12
32
|
end
|
13
33
|
|
34
|
+
class SelectorError < RuleError
|
35
|
+
def initialize(msg = "Selector not valid", element: nil, previous: nil)
|
36
|
+
if element.nil? && previous.nil?
|
37
|
+
super(msg)
|
38
|
+
elsif previous.nil?
|
39
|
+
super("Selector '#{element}' not valid")
|
40
|
+
else
|
41
|
+
super("Selector '#{element}' not valid after '#{previous}' selector part")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class JoinError < RuleError
|
47
|
+
def initialize(msg = "Cannot join a rule to a non-rule")
|
48
|
+
super(msg)
|
49
|
+
end
|
50
|
+
end
|
14
51
|
class PseudoClassError < RuleError
|
15
52
|
def initialize(msg = "invalid pseudo-class", argument: nil, method: nil)
|
16
53
|
if argument.nil? && method.nil?
|
@@ -34,7 +71,4 @@ class CSSNative
|
|
34
71
|
end
|
35
72
|
end
|
36
73
|
end
|
37
|
-
|
38
|
-
class AttributeError < CSSError
|
39
|
-
end
|
40
74
|
end
|
data/lib/css-native/rule.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "css-native/rule/stylesheet"
|
2
|
+
require "css-native/rule/constants"
|
2
3
|
class CSSNative
|
3
4
|
class Rule
|
4
5
|
def initialize(parent, name = "", previous: nil)
|
@@ -10,27 +11,23 @@ class CSSNative
|
|
10
11
|
|
11
12
|
# basic selectors
|
12
13
|
def with_element(name, &block)
|
13
|
-
|
14
|
-
|
15
|
-
@selector += CSSNative::format_element(name)
|
14
|
+
selector_error(name) if previous_selector?
|
15
|
+
append_selector(format_element(name), :element)
|
16
16
|
chain(&block)
|
17
17
|
end
|
18
18
|
|
19
19
|
def with_class(name, &block)
|
20
|
-
|
21
|
-
@selector += CSSNative::format_class(name)
|
20
|
+
append_selector(format_class(name), :class)
|
22
21
|
chain(&block)
|
23
22
|
end
|
24
23
|
|
25
24
|
def with_id(name, &block)
|
26
|
-
|
27
|
-
@selector += CSSNative::format_id(name)
|
25
|
+
append_selector(format_id(name), :id)
|
28
26
|
chain(&block)
|
29
27
|
end
|
30
28
|
|
31
|
-
def with_attribute(name,
|
32
|
-
|
33
|
-
@selector += CSSNative::format_attribute(name, operation, value, case_sensitive: case_sensitive)
|
29
|
+
def with_attribute(name, op = :none, value = nil, case_sensitive: true, &block)
|
30
|
+
append_selector(format_attribute(name, op, value, case_sensitive: case_sensitive), :attribute)
|
34
31
|
chain(&block)
|
35
32
|
end
|
36
33
|
|
@@ -49,166 +46,68 @@ class CSSNative
|
|
49
46
|
when :attribute
|
50
47
|
with_attribute(name, *args, &block)
|
51
48
|
else
|
52
|
-
raise
|
49
|
+
raise RuleError.new("undefined rule type '#{type}' for css selector")
|
53
50
|
end
|
54
51
|
end
|
55
52
|
alias_method :select, :with
|
56
53
|
|
57
54
|
def all(&block)
|
58
|
-
|
59
|
-
|
60
|
-
@selector += "*"
|
55
|
+
selector_error("*") if previous_selector?
|
56
|
+
append_selector("*", :all)
|
61
57
|
chain(&block)
|
62
58
|
end
|
63
59
|
|
64
60
|
# Grouping selectors
|
65
|
-
def join(rule = nil)
|
66
|
-
raise
|
67
|
-
|
68
|
-
|
61
|
+
def join(rule = nil, &block)
|
62
|
+
raise JoinError unless rule.kind_of?(Rule) || rule.nil?
|
63
|
+
selector_error(",") if previous_combinator?
|
64
|
+
|
69
65
|
if rule.kind_of? Rule
|
70
|
-
|
66
|
+
selector = rule.instance_variable_get(:@selector)
|
67
|
+
previous = rule.instance_variable_get(:@previous)
|
68
|
+
|
69
|
+
append_selector("," + selector, previous)
|
70
|
+
previous_combinator? ? self : chain(&block)
|
71
71
|
else
|
72
|
-
|
72
|
+
append_selector(",", :join)
|
73
|
+
self
|
73
74
|
end
|
74
|
-
self
|
75
75
|
end
|
76
76
|
|
77
77
|
# Combinators
|
78
|
-
COMBINATORS = {
|
79
|
-
descendant: " ",
|
80
|
-
child: " > ",
|
81
|
-
sibling: " + ",
|
82
|
-
adjacent: " + ",
|
83
|
-
column: " || "
|
84
|
-
}
|
85
|
-
|
86
78
|
def combinator(c)
|
87
79
|
m = c.to_sym
|
88
|
-
|
89
|
-
|
90
|
-
@selector += COMBINATORS[m]
|
80
|
+
selector_error(COMBINATORS[m].strip) if previous_combinator?
|
81
|
+
append_selector(COMBINATORS[m], :combinator)
|
91
82
|
self
|
92
83
|
end
|
93
84
|
|
94
|
-
# pseudo-classes
|
95
|
-
# name of value is pseudo-class, array values are acceptad options
|
96
|
-
# Equality is compared by <option> === <value>, allowing
|
97
|
-
# classes to test for instances or regex matching
|
98
|
-
# If array is empty, there's no limitations (in the code, foraml CSS may differ)
|
99
|
-
# If array is nil, it takes no options
|
100
|
-
PSEUDO_CLASSES = {
|
101
|
-
# Linguistic
|
102
|
-
dir: ["ltr", "rtl"],
|
103
|
-
lang: [],
|
104
|
-
# Location
|
105
|
-
"any_link": nil,
|
106
|
-
link: nil,
|
107
|
-
visited: nil,
|
108
|
-
"local_link": nil,
|
109
|
-
target: nil,
|
110
|
-
"target_within": nil,
|
111
|
-
scope: nil,
|
112
|
-
# User action
|
113
|
-
hover: nil,
|
114
|
-
active: nil,
|
115
|
-
focus: nil,
|
116
|
-
"focus_visible": nil,
|
117
|
-
"focus_within": nil,
|
118
|
-
# Time_dimensional _ ill_defined
|
119
|
-
current: nil,
|
120
|
-
past: nil,
|
121
|
-
future: nil,
|
122
|
-
# Resource state
|
123
|
-
playing: nil,
|
124
|
-
paused: nil,
|
125
|
-
# Input
|
126
|
-
enabled: nil,
|
127
|
-
disabled: nil,
|
128
|
-
"read_only": nil,
|
129
|
-
"read_write": nil,
|
130
|
-
"placeholder_shown": nil,
|
131
|
-
default: nil,
|
132
|
-
checked: nil,
|
133
|
-
indeterminate: nil,
|
134
|
-
blank: nil,
|
135
|
-
valid: nil,
|
136
|
-
invalid: nil,
|
137
|
-
"in_range": nil,
|
138
|
-
"out_of_range": nil,
|
139
|
-
required: nil,
|
140
|
-
optional: nil,
|
141
|
-
"user_invalid": nil,
|
142
|
-
root: nil,
|
143
|
-
empty: nil,
|
144
|
-
"nth_child": ["odd", "even", /^\d+(n(\s*\+\s*\d+)?)?$/],
|
145
|
-
"nth_last_child": ["odd", "even", /^\d+(n(\s*\+\s*\d+)?)?$/],
|
146
|
-
"first_child": nil,
|
147
|
-
"last_child": nil,
|
148
|
-
"only_child": nil,
|
149
|
-
"nth_of_type": ["odd", "even", /^\d+(n(\s*\+\s*\d+)?)?$/],
|
150
|
-
"nth_last_of_type": ["odd", "even", /^\d+(n(\s*\+\s*\d+)?)?$/],
|
151
|
-
"first_of_type": nil,
|
152
|
-
"last_of_type": nil,
|
153
|
-
"only_of_type": nil,
|
154
|
-
}
|
155
|
-
|
156
85
|
def pseudo_class(name, *args, &block)
|
157
86
|
pc = name.to_s.gsub("_", "-")
|
158
87
|
m = name.to_s.gsub("-", "_").to_sym
|
159
88
|
raise PseudoClassError.new(method: pc) unless PSEUDO_CLASSES.key?(m)
|
160
89
|
|
161
|
-
args.
|
162
|
-
|
163
|
-
raise PseudoClassError.new(argument: arg, method: pc)
|
164
|
-
end
|
90
|
+
unless args.all? {|arg| valid_arg?(PSEUDO_CLASSES[m], arg.to_s)}
|
91
|
+
raise PseudoClassError.new(argument: arg, method: pc)
|
165
92
|
end
|
166
93
|
|
167
|
-
|
168
|
-
|
169
|
-
@selector += "(#{args.join(" ")})" unless args.empty?
|
94
|
+
selector = ":#{pc}" + (args.empty? ? "" : "(#{args.join(" ")})")
|
95
|
+
append_selector(selector, :pseudo_class)
|
170
96
|
chain(&block)
|
171
97
|
end
|
172
98
|
|
173
|
-
# pseudo-elements
|
174
|
-
# definition semantics same as pseudo-classes
|
175
|
-
PSEUDO_ELEMENTS = {
|
176
|
-
after: nil,
|
177
|
-
before: nil,
|
178
|
-
backdrop: nil,
|
179
|
-
cue: nil,
|
180
|
-
"cue_region": nil,
|
181
|
-
"first_letter": nil,
|
182
|
-
"first_line": nil,
|
183
|
-
"file_selector_button": nil,
|
184
|
-
"grammar_error": nil,
|
185
|
-
marker: nil,
|
186
|
-
part: [/[-a-zA-Z]+( [-a-zA-Z]+)?/],
|
187
|
-
placeholder: nil,
|
188
|
-
selection: nil,
|
189
|
-
slotted: [],
|
190
|
-
"spelling_error": nil,
|
191
|
-
"target_text": nil,
|
192
|
-
}
|
193
|
-
|
194
99
|
def pseudo_element(name, *args, &block)
|
195
100
|
pe = name.to_s.gsub("_", "-")
|
196
101
|
m = name.to_s.gsub("-", "_").to_sym
|
197
102
|
raise PseudoElementError.new(method: pe) unless PSEUDO_ELEMENTS.key?(m)
|
198
103
|
|
199
|
-
args.
|
200
|
-
|
201
|
-
raise PseudoElementError.new(argument: arg, method: pe)
|
202
|
-
end
|
104
|
+
unless args.all? {|arg| valid_arg?(PSEUDO_ELEMENTS[m], arg.to_s)}
|
105
|
+
raise PseudoElementError.new(argument: arg, method: pe)
|
203
106
|
end
|
204
|
-
|
205
|
-
@previous = :pseudo_element
|
206
|
-
@selector += "::#{pe}"
|
207
|
-
@selector += "(#{args.join(" ")})" unless args.empty?
|
208
107
|
|
209
|
-
|
210
|
-
|
211
|
-
|
108
|
+
selector = "::#{pe}" + (args.empty? ? "" : "(#{args.join(" ")})")
|
109
|
+
append_selector(selector, :pseudo_element)
|
110
|
+
chain(&block)
|
212
111
|
end
|
213
112
|
|
214
113
|
def method_missing(m, *args, &block)
|
@@ -259,12 +158,51 @@ class CSSNative
|
|
259
158
|
end
|
260
159
|
end
|
261
160
|
|
262
|
-
def
|
161
|
+
def append_selector(item, symbol)
|
162
|
+
@selector += item
|
163
|
+
@previous = symbol
|
164
|
+
end
|
165
|
+
|
166
|
+
def selector_error(name)
|
167
|
+
raise SelectorError.new(element: name, previous: @previous)
|
168
|
+
end
|
169
|
+
|
170
|
+
def valid_arg?(defs, arg)
|
263
171
|
if defs.nil?
|
264
172
|
arg.nil?
|
265
173
|
else
|
266
174
|
defs.empty? || defs.any? {|d| d === arg}
|
267
175
|
end
|
268
176
|
end
|
177
|
+
|
178
|
+
def format_element(name)
|
179
|
+
name.to_s
|
180
|
+
end
|
181
|
+
|
182
|
+
def format_class(name)
|
183
|
+
".#{name}"
|
184
|
+
end
|
185
|
+
|
186
|
+
def format_id(name)
|
187
|
+
"##{name}"
|
188
|
+
end
|
189
|
+
|
190
|
+
def format_attribute(name, operation = :none, value = nil, case_sensitive: true)
|
191
|
+
# Other case not possible because of positional arguments
|
192
|
+
raise AttributeError if operation != :none && value.nil?
|
193
|
+
|
194
|
+
op = case operation.to_sym
|
195
|
+
when :none then ""
|
196
|
+
when :equals then "="
|
197
|
+
when :include then "~="
|
198
|
+
when :matches then "|="
|
199
|
+
when :starts_with then "^="
|
200
|
+
when :ends_with then "$="
|
201
|
+
when :contains then "*="
|
202
|
+
else
|
203
|
+
raise AttributeComparisonError.new(operation: operation)
|
204
|
+
end
|
205
|
+
"[#{name}#{op}#{value.nil? ? "" : "\"#{value}\""}#{case_sensitive ? "" : " i"}]"
|
206
|
+
end
|
269
207
|
end
|
270
208
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
class CSSNative
|
2
|
+
class Rule
|
3
|
+
private
|
4
|
+
|
5
|
+
COMBINATORS = {
|
6
|
+
descendant: " ",
|
7
|
+
child: " > ",
|
8
|
+
sibling: " + ",
|
9
|
+
adjacent: " + ",
|
10
|
+
column: " || "
|
11
|
+
}
|
12
|
+
|
13
|
+
# pseudo-classes
|
14
|
+
# name of value is pseudo-class, array values are acceptad options
|
15
|
+
# Equality is compared by <option> === <value>, allowing
|
16
|
+
# classes to test for instances or regex matching
|
17
|
+
# If array is empty, there's no limitations (in the code, foraml CSS may differ)
|
18
|
+
# If array is nil, it takes no options
|
19
|
+
PSEUDO_CLASSES = {
|
20
|
+
# Linguistic
|
21
|
+
dir: ["ltr", "rtl"],
|
22
|
+
lang: [],
|
23
|
+
# Location
|
24
|
+
"any_link": nil,
|
25
|
+
link: nil,
|
26
|
+
visited: nil,
|
27
|
+
"local_link": nil,
|
28
|
+
target: nil,
|
29
|
+
"target_within": nil,
|
30
|
+
scope: nil,
|
31
|
+
# User action
|
32
|
+
hover: nil,
|
33
|
+
active: nil,
|
34
|
+
focus: nil,
|
35
|
+
"focus_visible": nil,
|
36
|
+
"focus_within": nil,
|
37
|
+
# Time_dimensional _ ill_defined
|
38
|
+
current: nil,
|
39
|
+
past: nil,
|
40
|
+
future: nil,
|
41
|
+
# Resource state
|
42
|
+
playing: nil,
|
43
|
+
paused: nil,
|
44
|
+
# Input
|
45
|
+
enabled: nil,
|
46
|
+
disabled: nil,
|
47
|
+
"read_only": nil,
|
48
|
+
"read_write": nil,
|
49
|
+
"placeholder_shown": nil,
|
50
|
+
default: nil,
|
51
|
+
checked: nil,
|
52
|
+
indeterminate: nil,
|
53
|
+
blank: nil,
|
54
|
+
valid: nil,
|
55
|
+
invalid: nil,
|
56
|
+
"in_range": nil,
|
57
|
+
"out_of_range": nil,
|
58
|
+
required: nil,
|
59
|
+
optional: nil,
|
60
|
+
"user_invalid": nil,
|
61
|
+
root: nil,
|
62
|
+
empty: nil,
|
63
|
+
"nth_child": ["odd", "even", /^\d+(n(\s*\+\s*\d+)?)?$/],
|
64
|
+
"nth_last_child": ["odd", "even", /^\d+(n(\s*\+\s*\d+)?)?$/],
|
65
|
+
"first_child": nil,
|
66
|
+
"last_child": nil,
|
67
|
+
"only_child": nil,
|
68
|
+
"nth_of_type": ["odd", "even", /^\d+(n(\s*\+\s*\d+)?)?$/],
|
69
|
+
"nth_last_of_type": ["odd", "even", /^\d+(n(\s*\+\s*\d+)?)?$/],
|
70
|
+
"first_of_type": nil,
|
71
|
+
"last_of_type": nil,
|
72
|
+
"only_of_type": nil,
|
73
|
+
}
|
74
|
+
|
75
|
+
# pseudo-elements
|
76
|
+
# definition semantics same as pseudo-classes
|
77
|
+
PSEUDO_ELEMENTS = {
|
78
|
+
after: nil,
|
79
|
+
before: nil,
|
80
|
+
backdrop: nil,
|
81
|
+
cue: nil,
|
82
|
+
"cue_region": nil,
|
83
|
+
"first_letter": nil,
|
84
|
+
"first_line": nil,
|
85
|
+
"file_selector_button": nil,
|
86
|
+
"grammar_error": nil,
|
87
|
+
marker: nil,
|
88
|
+
part: [/[-a-zA-Z]+( [-a-zA-Z]+)?/],
|
89
|
+
placeholder: nil,
|
90
|
+
selection: nil,
|
91
|
+
slotted: [],
|
92
|
+
"spelling_error": nil,
|
93
|
+
"target_text": nil,
|
94
|
+
}
|
95
|
+
end
|
96
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: css-native
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kellen Watt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-02-
|
11
|
+
date: 2021-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A CSS generator designed to make writing CSS-compatible code cleaner
|
14
14
|
and easier to undestand
|
@@ -20,6 +20,7 @@ files:
|
|
20
20
|
- lib/css-native.rb
|
21
21
|
- lib/css-native/errors.rb
|
22
22
|
- lib/css-native/rule.rb
|
23
|
+
- lib/css-native/rule/constants.rb
|
23
24
|
- lib/css-native/rule/stylesheet.rb
|
24
25
|
homepage: https://github.com/KellenWatt/css-native
|
25
26
|
licenses:
|