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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 755affad3180d9aa85746a5f471a5f339b4d377c78e87c33450391639c82844a
4
- data.tar.gz: 91378f2f7a663c8b74519abf0473c40c99018553dbc19861ad34593d8bc44be6
3
+ metadata.gz: b43f3acebaa6a120dbf30767223cf2ad94c7517498d4e0df41a5b4b6b95a7bb9
4
+ data.tar.gz: d2333285b9a95b1ef6ef396c4005bc44e9a6b19e7e9ced18e623b1e81d9f090b
5
5
  SHA512:
6
- metadata.gz: f50f885a37fd7e92bbf560d5fc56e55033fa0e6baabf54babc81d65b473bdfe394343c49a0901d0c099939f2e16e54349b78d7021969719dbd0b535c9e78e948
7
- data.tar.gz: caf0bcd21952347361973ea9a6d5ce3a93cad0f777773f4cb77f7738f6327abcda7e99b6e3b874bfa65eeaab54dde09723f5c5a8e8324e860b92d4ee89746fd1
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("undefined rule type '#{type}' for css selector")
49
+ raise RuleError.new(rule: type)
77
50
  end
78
51
  end
79
52
 
@@ -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 GrammarError < RuleError
9
- def initialize(element = nil)
10
- super("Rule selector#{element.nil? ? "" : " #{element}"} not valid in current position")
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
@@ -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
- raise GrammarError.new(name) if previous_selector?
14
- @previous = :element
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
- @previous = :class
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
- @previous = :id
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, operation = :none, value = nil, case_sensitive: true, &block)
32
- @previous = :attribute
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 CSSNative::RuleError.new("undefined rule type '#{type}' for css selector")
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
- raise GrammarError.new("*") if previous_selector?
59
- @previous = :all
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 GrammarError.new(",") if previous_combinator?
67
- @previous = :join
68
- @selector += ","
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
- @selector += rule.instance_variable_get(:@selector)
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
- @selector += rule.to_s
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
- raise GrammarError.new(COMBINATORS[m].strip) if previous_combinator?
89
- @previous = :combinator
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.each? do |arg|
162
- unless matches_arg_defs?(PSEUDO_CLASSES[m], arg.to_s)
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
- @previous = :pseudo_class
168
- @selector += ":#{pc}"
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.each? do |arg|
200
- unless matches_arg_defs?(PSEUDO_ELEMENTS[m], arg.to_s)
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
- # Not "chain" because a pseudo-element is always the final selector
210
- @stylesheet.instance_exec(@stylesheet, &block)
211
- @parent.rules << to_s
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 matches_arg_defs?(defs, arg)
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.2
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-10 00:00:00.000000000 Z
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: