Skip to content

Commit 6b3cca7

Browse files
authored
Merge pull request #154 from stoivo/st-refactor-creation-of-rule-set
Changes to creation of rule set
2 parents 22fb126 + 219d43e commit 6b3cca7

13 files changed

+206
-102
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535

3636
- uses: ruby/setup-ruby@v1
3737
with:
38-
ruby-version: '2.7'
38+
ruby-version: '3.0'
3939
bundler-cache: true
4040

4141
- run: bundle exec rake rubocop

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
### Unreleased
44

5+
* Deprecate `add_rule!` (positional arguments)and `add_rule_with_offsets!` for `add_rule!` (keyword argument)
6+
* RuleSet initialize now takes keyword argument, positional arguments are still supported but deprecated
7+
* Removed OffsetAwareRuleSet, it's a RuleSet with optional attributes filename and offset
8+
59
### Version v1.18.0
610

711
* Drop Ruby 2.7 compatibility for parity with Premailer [#149](https://github.com/premailer/css_parser/pull/149)

Rakefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ Rake::TestTask.new do |test|
1313
test.verbose = true
1414
end
1515

16-
RuboCop::RakeTask.new
16+
RuboCop::RakeTask.new do |t|
17+
# allow you to run "$ rake rubocop -a" to autofix
18+
t.options << '-a' if ARGV.include?('-a')
19+
t.options << '-A' if ARGV.include?('-A')
20+
end
1721

1822
desc 'Run a performance evaluation.'
1923
task :benchmark do

lib/css_parser/parser.rb

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,44 @@ def add_block!(block, options = {})
164164
parse_block_into_rule_sets!(block, options)
165165
end
166166

167-
# Add a CSS rule by setting the +selectors+, +declarations+ and +media_types+.
167+
# Add a CSS rule by setting the +selectors+, +declarations+
168+
# and +media_types+. Optional pass +filename+ , +offset+ for source
169+
# reference too.
168170
#
169-
# +media_types+ can be a symbol or an array of symbols.
170-
def add_rule!(selectors, declarations, media_types = :all)
171-
rule_set = RuleSet.new(selectors, declarations)
172-
add_rule_set!(rule_set, media_types)
173-
rescue ArgumentError => e
174-
raise e if @options[:rule_set_exceptions]
171+
# +media_types+ can be a symbol or an array of symbols. default to :all
172+
# optional fields for source location for source location
173+
# +filename+ can be a string or uri pointing to the file or url location.
174+
# +offset+ should be Range object representing the start and end byte locations where the rule was found in the file.
175+
def add_rule!(*args, selectors: nil, block: nil, filename: nil, offset: nil, media_types: :all) # rubocop:disable Metrics/ParameterLists
176+
if args.any?
177+
media_types = nil
178+
if selectors || block || filename || offset || media_types
179+
raise ArgumentError, "don't mix positional and keyword arguments arguments"
180+
end
181+
182+
warn '[DEPRECATION] `add_rule!` with positional arguments is deprecated. ' \
183+
'Please use keyword arguments instead.', uplevel: 1
184+
185+
case args.length
186+
when 2
187+
selectors, block = args
188+
when 3
189+
selectors, block, media_types = args
190+
else
191+
raise ArgumentError
192+
end
193+
end
194+
195+
begin
196+
rule_set = RuleSet.new(
197+
selectors: selectors, block: block,
198+
offset: offset, filename: filename
199+
)
200+
201+
add_rule_set!(rule_set, media_types)
202+
rescue ArgumentError => e
203+
raise e if @options[:rule_set_exceptions]
204+
end
175205
end
176206

177207
# Add a CSS rule by setting the +selectors+, +declarations+, +filename+, +offset+ and +media_types+.
@@ -180,8 +210,11 @@ def add_rule!(selectors, declarations, media_types = :all)
180210
# +offset+ should be Range object representing the start and end byte locations where the rule was found in the file.
181211
# +media_types+ can be a symbol or an array of symbols.
182212
def add_rule_with_offsets!(selectors, declarations, filename, offset, media_types = :all)
183-
rule_set = OffsetAwareRuleSet.new(filename, offset, selectors, declarations)
184-
add_rule_set!(rule_set, media_types)
213+
warn '[DEPRECATION] `add_rule_with_offsets!` is deprecated. Please use `add_rule!` instead.', uplevel: 1
214+
add_rule!(
215+
selectors: selectors, block: declarations, media_types: media_types,
216+
filename: filename, offset: offset
217+
)
185218
end
186219

187220
# Add a CssParser RuleSet object.
@@ -360,11 +393,14 @@ def parse_block_into_rule_sets!(block, options = {}) # :nodoc:
360393
current_declarations.strip!
361394

362395
unless current_declarations.empty?
396+
add_rule_options = {
397+
selectors: current_selectors, block: current_declarations,
398+
media_types: current_media_queries
399+
}
363400
if options[:capture_offsets]
364-
add_rule_with_offsets!(current_selectors, current_declarations, options[:filename], (rule_start..offset.last), current_media_queries)
365-
else
366-
add_rule!(current_selectors, current_declarations, current_media_queries)
401+
add_rule_options.merge!(filename: options[:filename], offset: rule_start..offset.last)
367402
end
403+
add_rule!(**add_rule_options)
368404
end
369405

370406
current_selectors = String.new
@@ -430,11 +466,14 @@ def parse_block_into_rule_sets!(block, options = {}) # :nodoc:
430466
# check for unclosed braces
431467
return unless in_declarations > 0
432468

433-
unless options[:capture_offsets]
434-
return add_rule!(current_selectors, current_declarations, current_media_queries)
469+
add_rule_options = {
470+
selectors: current_selectors, block: current_declarations,
471+
media_types: current_media_queries
472+
}
473+
if options[:capture_offsets]
474+
add_rule_options.merge!(filename: options[:filename], offset: rule_start..offset.last)
435475
end
436-
437-
add_rule_with_offsets!(current_selectors, current_declarations, options[:filename], (rule_start..offset.last), current_media_queries)
476+
add_rule!(**add_rule_options)
438477
end
439478

440479
# Load a remote CSS file.

lib/css_parser/rule_set.rb

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,12 @@ def normalize_property(property)
223223

224224
extend Forwardable
225225

226+
# optional field for storing source reference
227+
# File offset range
228+
attr_reader :offset
229+
# the local or remote location
230+
attr_accessor :filename
231+
226232
# Array of selector strings.
227233
attr_reader :selectors
228234

@@ -237,9 +243,38 @@ def normalize_property(property)
237243
alias []= add_declaration!
238244
alias remove_declaration! delete
239245

240-
def initialize(selectors, block, specificity = nil)
246+
def initialize(*args, selectors: nil, block: nil, offset: nil, filename: nil, specificity: nil) # rubocop:disable Metrics/ParameterLists
247+
if args.any?
248+
if selectors || block || offset || filename || specificity
249+
raise ArgumentError, "don't mix positional and keyword arguments"
250+
end
251+
252+
warn '[DEPRECATION] positional arguments are deprecated use keyword instead.', uplevel: 1
253+
254+
case args.length
255+
when 2
256+
selectors, block = args
257+
when 3
258+
selectors, block, specificity = args
259+
when 4
260+
filename, offset, selectors, block = args
261+
when 5
262+
filename, offset, selectors, block, specificity = args
263+
else
264+
raise ArgumentError
265+
end
266+
end
267+
241268
@selectors = []
242269
@specificity = specificity
270+
271+
unless offset.nil? == filename.nil?
272+
raise ArgumentError, 'require both offset and filename or no offset and no filename'
273+
end
274+
275+
@offset = offset
276+
@filename = filename
277+
243278
parse_selectors!(selectors) if selectors
244279
parse_declarations!(block)
245280
end
@@ -650,18 +685,4 @@ def split_value_preserving_function_whitespace(value)
650685
end
651686
end
652687
end
653-
654-
class OffsetAwareRuleSet < RuleSet
655-
# File offset range
656-
attr_reader :offset
657-
658-
# the local or remote location
659-
attr_accessor :filename
660-
661-
def initialize(filename, offset, selectors, block, specificity = nil)
662-
super(selectors, block, specificity)
663-
@offset = offset
664-
@filename = filename
665-
end
666-
end
667688
end

test/test_css_parser_basic.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,20 @@ def test_adding_block_without_closing_brace
3535
end
3636

3737
def test_adding_a_rule
38-
@cp.add_rule!('div', 'color: blue;')
38+
@cp.add_rule!(selectors: 'div', block: 'color: blue;')
3939
assert_equal 'color: blue;', @cp.find_by_selector('div').join(' ')
4040
end
4141

4242
def test_adding_a_rule_set
43-
rs = CssParser::RuleSet.new('div', 'color: blue;')
43+
rs = CssParser::RuleSet.new(selectors: 'div', block: 'color: blue;')
4444
@cp.add_rule_set!(rs)
4545
assert_equal 'color: blue;', @cp.find_by_selector('div').join(' ')
4646
end
4747

4848
def test_removing_a_rule_set
49-
rs = CssParser::RuleSet.new('div', 'color: blue;')
49+
rs = CssParser::RuleSet.new(selectors: 'div', block: 'color: blue;')
5050
@cp.add_rule_set!(rs)
51-
rs2 = CssParser::RuleSet.new('div', 'color: blue;')
51+
rs2 = CssParser::RuleSet.new(selectors: 'div', block: 'color: blue;')
5252
@cp.remove_rule_set!(rs2)
5353
assert_equal '', @cp.find_by_selector('div').join(' ')
5454
end
@@ -72,7 +72,7 @@ def test_toggling_uri_conversion
7272
end
7373

7474
def test_converting_to_hash
75-
rs = CssParser::RuleSet.new('div', 'color: blue;')
75+
rs = CssParser::RuleSet.new(selectors: 'div', block: 'color: blue;')
7676
@cp.add_rule_set!(rs)
7777
hash = @cp.to_h
7878
assert_equal 'blue', hash['all']['div']['color']

test/test_css_parser_loading.rb

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -204,16 +204,4 @@ def test_toggling_not_found_exceptions
204204

205205
cp_without_exceptions.load_uri!("#{@uri_base}/no-exist.xyz")
206206
end
207-
208-
def test_rule_set_argument_exceptions
209-
cp_with_exceptions = Parser.new(rule_set_exceptions: true)
210-
211-
assert_raises ArgumentError, 'background-color value is empty' do
212-
cp_with_exceptions.add_rule!('body', 'background-color: !important')
213-
end
214-
215-
cp_without_exceptions = Parser.new(rule_set_exceptions: false)
216-
217-
cp_without_exceptions.add_rule!('body', 'background-color: !important')
218-
end
219207
end

test/test_css_parser_media_types.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,24 +135,24 @@ def test_adding_block_and_limiting_media_types
135135
end
136136

137137
def test_adding_rule_set_with_media_type
138-
@cp.add_rule!('body', 'color: black;', [:handheld, :tty])
139-
@cp.add_rule!('body', 'color: blue;', :screen)
138+
@cp.add_rule!(selectors: 'body', block: 'color: black;', media_types: [:handheld, :tty])
139+
@cp.add_rule!(selectors: 'body', block: 'color: blue;', media_types: :screen)
140140
assert_equal 'color: black;', @cp.find_by_selector('body', :handheld).join(' ')
141141
end
142142

143143
def test_adding_rule_set_with_media_query
144-
@cp.add_rule!('body', 'color: black;', 'aural and (device-aspect-ratio: 16/9)')
144+
@cp.add_rule!(selectors: 'body', block: 'color: black;', media_types: 'aural and (device-aspect-ratio: 16/9)')
145145
assert_equal 'color: black;', @cp.find_by_selector('body', 'aural and (device-aspect-ratio: 16/9)').join(' ')
146146
assert_equal 'color: black;', @cp.find_by_selector('body', :all).join(' ')
147147
end
148148

149149
def test_selecting_with_all_media_types
150-
@cp.add_rule!('body', 'color: black;', [:handheld, :tty])
150+
@cp.add_rule!(selectors: 'body', block: 'color: black;', media_types: [:handheld, :tty])
151151
assert_equal 'color: black;', @cp.find_by_selector('body', :all).join(' ')
152152
end
153153

154154
def test_to_s_includes_media_queries
155-
@cp.add_rule!('body', 'color: black;', 'aural and (device-aspect-ratio: 16/9)')
155+
@cp.add_rule!(selectors: 'body', block: 'color: black;', media_types: 'aural and (device-aspect-ratio: 16/9)')
156156
assert_equal "@media aural and (device-aspect-ratio: 16/9) {\n body {\n color: black;\n }\n}\n", @cp.to_s
157157
end
158158
end

test/test_css_parser_misc.rb

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,20 @@ def test_ruleset_with_braces
195195
# rulesets = []
196196
#
197197
# parser['div'].each do |declaration|
198-
# rulesets << RuleSet.new('div', declaration)
198+
# rulesets << RuleSet.new(selectors: 'div', block: declaration)
199199
# end
200200
#
201201
# merged = CssParser.merge(rulesets)
202202
#
203203
# result: # merged.to_s => "{ background-color: black !important; }"
204204

205-
new_rule = RuleSet.new('div', "{ background-color: black !important; }")
205+
new_rule = RuleSet.new(selectors: 'div', block: "{ background-color: black !important; }")
206206

207207
assert_equal 'div { background-color: black !important; }', new_rule.to_s
208208
end
209209

210210
def test_content_with_data
211-
rule = RuleSet.new('div', '{content: url(data:image/png;base64,LOTSOFSTUFF)}')
211+
rule = RuleSet.new(selectors: 'div', block: '{content: url(data:image/png;base64,LOTSOFSTUFF)}')
212212
assert_includes rule.to_s, "image/png;base64,LOTSOFSTUFF"
213213
end
214214

@@ -226,4 +226,48 @@ def test_enumerator_nonempty
226226
assert_equal 'color: black;', desc
227227
end
228228
end
229+
230+
def test_catching_argument_exceptions_for_add_rule
231+
cp_with_exceptions = Parser.new(rule_set_exceptions: true)
232+
assert_raises ArgumentError, 'background-color value is empty' do
233+
cp_with_exceptions.add_rule!(selectors: 'body', block: 'background-color: !important')
234+
end
235+
236+
cp_without_exceptions = Parser.new(rule_set_exceptions: false)
237+
cp_without_exceptions.add_rule!(selectors: 'body', block: 'background-color: !important')
238+
end
239+
240+
def test_catching_argument_exceptions_for_add_rule_positional
241+
cp_with_exceptions = Parser.new(rule_set_exceptions: true)
242+
243+
assert_raises ArgumentError, 'background-color value is empty' do
244+
_, err = capture_io do
245+
cp_with_exceptions.add_rule!('body', 'background-color: !important')
246+
end
247+
assert_includes err, "DEPRECATION"
248+
end
249+
250+
cp_without_exceptions = Parser.new(rule_set_exceptions: false)
251+
_, err = capture_io do
252+
cp_without_exceptions.add_rule!('body', 'background-color: !important')
253+
end
254+
assert_includes err, "DEPRECATION"
255+
end
256+
257+
def test_catching_argument_exceptions_for_add_rule_with_offsets
258+
cp_with_exceptions = Parser.new(capture_offsets: true, rule_set_exceptions: true)
259+
260+
assert_raises ArgumentError, 'background-color value is empty' do
261+
_, err = capture_io do
262+
cp_with_exceptions.add_rule_with_offsets!('body', 'background-color: !important', 'inline', 1)
263+
end
264+
assert_includes err, "DEPRECATION"
265+
end
266+
267+
cp_without_exceptions = Parser.new(capture_offsets: true, rule_set_exceptions: false)
268+
_, err = capture_io do
269+
cp_without_exceptions.add_rule_with_offsets!('body', 'background-color: !important', 'inline', 1)
270+
end
271+
assert_includes err, "DEPRECATION"
272+
end
229273
end

0 commit comments

Comments
 (0)