hexp 0.4.3 → 0.4.4
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/.travis.yml +33 -9
- data/Changelog.md +7 -1
- data/Rakefile +9 -0
- data/code_of_conduct.md +32 -0
- data/hexp.gemspec +0 -1
- data/lib/hexp.rb +0 -2
- data/lib/hexp/css_selector.rb +30 -22
- data/lib/hexp/css_selector/parser.rb +47 -61
- data/lib/hexp/version.rb +1 -1
- data/spec/shared_helper.rb +5 -2
- data/spec/unit/hexp/css_selector/attribute_spec.rb +7 -9
- data/spec/unit/hexp/css_selector/parser_spec.rb +4 -7
- metadata +4 -18
- data/lib/hexp/css_selector/sass_parser.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9c632d0e470fa5f4c296f3eea2ae8069eef7b54
|
4
|
+
data.tar.gz: 4d22a65fe1a865974c745846bf2e4f350b807a12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe5cdf5086cb3c3a44b4a3a5b06ffa8787084865af31d607a253b4ecb8373f5611f270c70f780d1ee1f991f20dab4770aec803b423fe78cf0a665121b3df641c
|
7
|
+
data.tar.gz: bd4927fdc7ab98569707f1ef9966b15ffcb2eed58524212511b9cf62976ada17bc94adda6c86f30fce5c7b2cc8f45d2e1544fdfc27b45970c94ac7e20e9eb5df
|
data/.travis.yml
CHANGED
@@ -1,22 +1,46 @@
|
|
1
|
-
# Currently fails on JRuby, partly due to Nokogiri behaving differently,
|
2
|
-
# and partly for some other reason I'm not sure about regarding
|
3
|
-
# Hexp::Node::Normalize
|
4
1
|
language: ruby
|
5
|
-
|
2
|
+
|
3
|
+
script: bundle exec rake $TASK
|
4
|
+
|
5
|
+
sudo: false
|
6
|
+
|
6
7
|
rvm:
|
7
8
|
- 1.9.3
|
8
|
-
- 2.0
|
9
|
-
- 2.1.1
|
10
|
-
- 2.1.2
|
11
|
-
- 2.1.3
|
9
|
+
- 2.0
|
12
10
|
- 2.1
|
13
|
-
-
|
11
|
+
- 2.2
|
14
12
|
- jruby
|
15
13
|
- jruby-head
|
14
|
+
- rbx
|
16
15
|
- ruby-head
|
16
|
+
|
17
|
+
env:
|
18
|
+
- TASK=rspec
|
19
|
+
- TASK=mutant
|
20
|
+
|
17
21
|
matrix:
|
22
|
+
# Jruby should be taken out of this list. It fails now because of a
|
23
|
+
# subtle Nokogiri incompatibility
|
18
24
|
allow_failures:
|
19
25
|
- rvm: jruby
|
20
26
|
- rvm: ruby-head
|
21
27
|
- rvm: jruby-head
|
22
28
|
- rvm: rbx
|
29
|
+
- env: TASK=mutant
|
30
|
+
|
31
|
+
# Only run mutant on 2.2
|
32
|
+
exclude:
|
33
|
+
- rvm: 1.9.3
|
34
|
+
env: TASK=mutant
|
35
|
+
- rvm: 2.0
|
36
|
+
env: TASK=mutant
|
37
|
+
- rvm: 2.1
|
38
|
+
env: TASK=mutant
|
39
|
+
- rvm: jruby
|
40
|
+
env: TASK=mutant
|
41
|
+
- rvm: jruby-head
|
42
|
+
env: TASK=mutant
|
43
|
+
- rvm: rbx
|
44
|
+
env: TASK=mutant
|
45
|
+
- rvm: ruby-head
|
46
|
+
env: TASK=mutant
|
data/Changelog.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
### Development
|
2
2
|
|
3
|
-
[full diff](http://github.com/plexus/hexp/compare/v0.4.
|
3
|
+
[full diff](http://github.com/plexus/hexp/compare/v0.4.4...master)
|
4
|
+
|
5
|
+
### v0.4.4
|
6
|
+
|
7
|
+
* Drop the dependency on SASS, use Nokogiri instead for parsing CSS
|
8
|
+
selectors
|
9
|
+
|
4
10
|
|
5
11
|
### v0.4.3
|
6
12
|
|
data/Rakefile
CHANGED
@@ -46,9 +46,18 @@ end
|
|
46
46
|
require 'mutant'
|
47
47
|
task :default => :mutant
|
48
48
|
|
49
|
+
desc "run mutant"
|
49
50
|
task :mutant do
|
50
51
|
pattern = ENV.fetch('PATTERN', 'Hexp*')
|
51
52
|
opts = ENV.fetch('MUTANT_OPTS', '').split(' ')
|
52
53
|
result = Mutant::CLI.run(%w[-Ilib -rhexp --use rspec --score 100] + opts + [pattern])
|
53
54
|
fail unless result == Mutant::CLI::EXIT_SUCCESS
|
54
55
|
end
|
56
|
+
|
57
|
+
require 'rspec/core/rake_task'
|
58
|
+
|
59
|
+
desc "run rspec"
|
60
|
+
RSpec::Core::RakeTask.new(:rspec) do |t, task_args|
|
61
|
+
t.rspec_opts = "-Ispec"
|
62
|
+
t.pattern = "spec"
|
63
|
+
end
|
data/code_of_conduct.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect
|
4
|
+
all people who contribute through reporting issues, posting feature
|
5
|
+
requests, updating documentation, submitting pull requests or patches,
|
6
|
+
and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a
|
9
|
+
harassment-free experience for everyone, regardless of level of
|
10
|
+
experience, gender, gender identity and expression, sexual
|
11
|
+
orientation, disability, personal appearance, body size, race, age, or
|
12
|
+
religion.
|
13
|
+
|
14
|
+
Examples of unacceptable behavior by participants include the use of
|
15
|
+
sexual language or imagery, derogatory comments or personal attacks,
|
16
|
+
trolling, public or private harassment, insults, or other
|
17
|
+
unprofessional conduct.
|
18
|
+
|
19
|
+
Project maintainers have the right and responsibility to remove, edit,
|
20
|
+
or reject comments, commits, code, wiki edits, issues, and other
|
21
|
+
contributions that are not aligned to this Code of Conduct. Project
|
22
|
+
maintainers who do not follow the Code of Conduct may be removed from
|
23
|
+
the project team.
|
24
|
+
|
25
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior
|
26
|
+
may be reported by opening an issue or contacting one or more of the
|
27
|
+
project maintainers.
|
28
|
+
|
29
|
+
This Code of Conduct is adapted from the
|
30
|
+
[Contributor Covenant](http:contributor-covenant.org), version 1.0.0,
|
31
|
+
available at
|
32
|
+
[http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/hexp.gemspec
CHANGED
@@ -17,7 +17,6 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = `git ls-files -- spec`.split($/)
|
18
18
|
gem.extra_rdoc_files = %w[README.md]
|
19
19
|
|
20
|
-
gem.add_runtime_dependency 'sass', '~> 3.2.19'
|
21
20
|
gem.add_runtime_dependency 'nokogiri', '~> 1.6'
|
22
21
|
gem.add_runtime_dependency 'equalizer', '~> 0.0'
|
23
22
|
gem.add_runtime_dependency 'concord', '~> 0.0'
|
data/lib/hexp.rb
CHANGED
@@ -3,7 +3,6 @@ require 'forwardable'
|
|
3
3
|
require 'pathname'
|
4
4
|
|
5
5
|
require 'nokogiri'
|
6
|
-
require 'sass'
|
7
6
|
require 'equalizer'
|
8
7
|
require 'concord'
|
9
8
|
|
@@ -112,7 +111,6 @@ require 'hexp/list'
|
|
112
111
|
require 'hexp/dom'
|
113
112
|
|
114
113
|
require 'hexp/css_selector'
|
115
|
-
require 'hexp/css_selector/sass_parser'
|
116
114
|
require 'hexp/css_selector/parser'
|
117
115
|
|
118
116
|
require 'hexp/errors'
|
data/lib/hexp/css_selector.rb
CHANGED
@@ -100,9 +100,13 @@ module Hexp
|
|
100
100
|
#
|
101
101
|
# @api private
|
102
102
|
def matches?(element)
|
103
|
-
members.any? do |
|
104
|
-
|
105
|
-
|
103
|
+
members.any? do |member|
|
104
|
+
case member
|
105
|
+
when Sequence
|
106
|
+
member.members.count == 1 && member.head_matches?(element)
|
107
|
+
else
|
108
|
+
member.matches?(element)
|
109
|
+
end
|
106
110
|
end
|
107
111
|
end
|
108
112
|
|
@@ -164,6 +168,10 @@ module Hexp
|
|
164
168
|
class SimpleSequence
|
165
169
|
include Members
|
166
170
|
|
171
|
+
def matches_path?(path)
|
172
|
+
matches?(path.last)
|
173
|
+
end
|
174
|
+
|
167
175
|
# Does the element match all parts of this SimpleSequence
|
168
176
|
#
|
169
177
|
# @params [Hexp::Node] element
|
@@ -176,12 +184,17 @@ module Hexp
|
|
176
184
|
simple.matches?(element)
|
177
185
|
end
|
178
186
|
end
|
187
|
+
alias head_matches? matches?
|
179
188
|
end
|
180
189
|
|
181
190
|
# A CSS element declaration, like 'div'
|
182
191
|
class Element
|
183
192
|
include Named
|
184
193
|
|
194
|
+
def matches_path?(path)
|
195
|
+
matches?(path.last)
|
196
|
+
end
|
197
|
+
|
185
198
|
# Does the node match this element selector
|
186
199
|
#
|
187
200
|
# @param [Hexp::Node] element
|
@@ -196,6 +209,10 @@ module Hexp
|
|
196
209
|
|
197
210
|
# Match any element, '*'
|
198
211
|
class Universal
|
212
|
+
def self.new
|
213
|
+
@@instance ||= super
|
214
|
+
end
|
215
|
+
|
199
216
|
def matches?(element)
|
200
217
|
true
|
201
218
|
end
|
@@ -250,9 +267,9 @@ module Hexp
|
|
250
267
|
#
|
251
268
|
# @api private
|
252
269
|
class Attribute
|
253
|
-
include Equalizer.new(:name, :
|
270
|
+
include Equalizer.new(:name, :operator, :value)
|
254
271
|
|
255
|
-
attr_reader :name, :
|
272
|
+
attr_reader :name, :operator, :value
|
256
273
|
|
257
274
|
# Construct a new Attribute selector
|
258
275
|
#
|
@@ -261,23 +278,17 @@ module Hexp
|
|
261
278
|
#
|
262
279
|
# @param [String] name
|
263
280
|
# Name of the attribute, like 'href'
|
264
|
-
# @param [String] namespace
|
265
|
-
# unused
|
266
281
|
# @param [nil, String] operator
|
267
282
|
# Operator like '~=', '^=', ... Use blank to simply test attribute
|
268
283
|
# presence.
|
269
284
|
# @param [String] value
|
270
285
|
# Value to test for, operator dependent
|
271
|
-
# @param [Object] flags
|
272
|
-
# unused
|
273
286
|
#
|
274
287
|
# @api private
|
275
|
-
def initialize(name,
|
288
|
+
def initialize(name, operator, value)
|
276
289
|
@name = name.freeze
|
277
|
-
@namespace = namespace.freeze
|
278
290
|
@operator = operator.freeze
|
279
291
|
@value = value.freeze
|
280
|
-
@flag = flags.freeze
|
281
292
|
end
|
282
293
|
|
283
294
|
# Debugging representation
|
@@ -286,7 +297,7 @@ module Hexp
|
|
286
297
|
#
|
287
298
|
# @api private
|
288
299
|
def inspect
|
289
|
-
"<#{self.class.name.split('::').last} name=#{name}
|
300
|
+
"<#{self.class.name.split('::').last} name=#{name} operator=#{operator.inspect} value=#{value.inspect}>"
|
290
301
|
end
|
291
302
|
|
292
303
|
# Does the node match this attribute selector
|
@@ -301,9 +312,6 @@ module Hexp
|
|
301
312
|
return false unless element[name]
|
302
313
|
attribute = element[name]
|
303
314
|
|
304
|
-
# TODO: check the spec with regards to IDENTIFIERS vs STRINGS as value
|
305
|
-
# see if we can lett SASS parse the string instead of unwrapping
|
306
|
-
# it ourselves
|
307
315
|
value = self.value
|
308
316
|
value = $1.gsub('\"', '"') if value =~ /\A"?(.*?)"?\z/
|
309
317
|
|
@@ -311,19 +319,19 @@ module Hexp
|
|
311
319
|
# CSS 2
|
312
320
|
when nil
|
313
321
|
true
|
314
|
-
when '='
|
322
|
+
when :equal # '=': exact match
|
315
323
|
attribute == value
|
316
|
-
when '~='
|
324
|
+
when :includes # '~=': space separated list contains
|
317
325
|
attribute.split(' ').include?(value)
|
318
|
-
when '|='
|
326
|
+
when :dash_match # '|=' equal to, or starts with followed by a dash
|
319
327
|
attribute =~ /\A#{Regexp.escape(value)}(-|\z)/
|
320
328
|
|
321
329
|
# CSS 3
|
322
|
-
when '^='
|
330
|
+
when :prefix_match #'^=': starts with
|
323
331
|
attribute.index(value) == 0
|
324
|
-
when '$='
|
332
|
+
when :suffix_match # '$=': ends with
|
325
333
|
attribute =~ /#{Regexp.escape(value)}\z/
|
326
|
-
when '*='
|
334
|
+
when :substring_match # '*=': contains
|
327
335
|
!!(attribute =~ /#{Regexp.escape(value)}/)
|
328
336
|
|
329
337
|
else
|
@@ -28,7 +28,11 @@ module Hexp
|
|
28
28
|
#
|
29
29
|
# @api private
|
30
30
|
def parse
|
31
|
-
|
31
|
+
CommaSequence.new(
|
32
|
+
::Nokogiri::CSS.parse(@selector).map do |node|
|
33
|
+
node.accept(self)
|
34
|
+
end
|
35
|
+
)
|
32
36
|
end
|
33
37
|
|
34
38
|
# Parse a CSS selector in one go
|
@@ -41,77 +45,59 @@ module Hexp
|
|
41
45
|
new(selector).parse
|
42
46
|
end
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
# @param [Sass::Selector::CommaSequence] comma_sequence
|
49
|
-
# @return [Hexp::CssSelector::CommaSequence]
|
50
|
-
#
|
51
|
-
# @api private
|
52
|
-
def rewrite_comma_sequence(comma_sequence)
|
53
|
-
CommaSequence.new(comma_sequence.members.map{|sequence| rewrite_sequence(sequence)})
|
48
|
+
def visit_descendant_selector(node)
|
49
|
+
Sequence.new(
|
50
|
+
node.value.map {|child| child.accept(self) }
|
51
|
+
)
|
54
52
|
end
|
55
53
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
54
|
+
def visit_conditional_selector(node)
|
55
|
+
head, tail = node.value
|
56
|
+
children = [head]
|
57
|
+
while tail.type == :COMBINATOR
|
58
|
+
head, tail = tail.value
|
59
|
+
children << head
|
60
|
+
end
|
61
|
+
children << tail
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
# @return [Hexp::CssSelector::SimpleSequence]
|
70
|
-
#
|
71
|
-
# @api private
|
72
|
-
def rewrite_simple_sequence(simple_sequence)
|
73
|
-
SimpleSequence.new(simple_sequence.members.map{|simple| rewrite_simple(simple)})
|
63
|
+
SimpleSequence.new(
|
64
|
+
children.map {|child| child.accept(self) }
|
65
|
+
)
|
74
66
|
end
|
75
67
|
|
76
|
-
|
77
|
-
|
78
|
-
# @param [Sass::Selector::Simple] comma_sequence
|
79
|
-
# @return [Hexp::CssSelector::Simple]
|
80
|
-
#
|
81
|
-
# @api private
|
82
|
-
def rewrite_simple(simple)
|
83
|
-
case simple
|
84
|
-
when ::Sass::Selector::Element # span
|
85
|
-
Element.new(simple.name.first)
|
86
|
-
when ::Sass::Selector::Class # .foo
|
87
|
-
Class.new(simple.name.first)
|
88
|
-
when ::Sass::Selector::Id # #main
|
89
|
-
Id.new(simple.name.first)
|
90
|
-
when ::Sass::Selector::Attribute # [href^="http://"]
|
91
|
-
raise "CSS attribute selector flags are curently ignored by Hexp (not implemented)" unless simple.flags.nil?
|
92
|
-
raise "CSS attribute namespaces are curently ignored by Hexp (not implemented)" unless simple.namespace.nil?
|
93
|
-
raise "CSS attribute operator #{simple.operator} not understood by Hexp" unless %w[= ~= ^= |= $= *=].include?(simple.operator) || simple.operator.nil?
|
94
|
-
Attribute.new(
|
95
|
-
simple.name.first,
|
96
|
-
simple.namespace,
|
97
|
-
simple.operator,
|
98
|
-
simple.value ? simple.value.first : nil,
|
99
|
-
simple.flags
|
100
|
-
)
|
101
|
-
when ::Sass::Selector::Universal # *
|
68
|
+
def visit_element_name(node)
|
69
|
+
if node.value == ["*"]
|
102
70
|
Universal.new
|
103
71
|
else
|
104
|
-
|
72
|
+
Element.new(node.value.first)
|
105
73
|
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def visit_class_condition(node)
|
77
|
+
Class.new(node.value.first)
|
78
|
+
end
|
106
79
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
80
|
+
def visit_id(node)
|
81
|
+
Id.new(node.value.first.sub(/^#/, ''))
|
82
|
+
end
|
83
|
+
|
84
|
+
# ul > li
|
85
|
+
def visit_child_selector(node)
|
86
|
+
raise "not implemented"
|
87
|
+
end
|
113
88
|
|
89
|
+
# [href^="http://"]
|
90
|
+
def visit_attribute_condition(node)
|
91
|
+
element, operator, value = node.value
|
92
|
+
name = element.value.first
|
93
|
+
Attribute.new(name.sub(/^@/, ''), operator, value)
|
114
94
|
end
|
95
|
+
|
96
|
+
# li:first / li:nth-child(3n)
|
97
|
+
def visit_pseudo_selector(node)
|
98
|
+
raise "not implemented"
|
99
|
+
end
|
100
|
+
|
115
101
|
end
|
116
102
|
end
|
117
103
|
end
|
data/lib/hexp/version.rb
CHANGED
data/spec/shared_helper.rb
CHANGED
@@ -7,8 +7,11 @@ RSpec::Matchers.define :dom_eq do |other_dom|
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
RSpec.configure do |
|
11
|
-
|
10
|
+
RSpec.configure do |rspec|
|
11
|
+
rspec.mock_with :rspec do |configuration|
|
12
12
|
configuration.syntax = :expect
|
13
13
|
end
|
14
|
+
rspec.around(:each) do |example|
|
15
|
+
Timeout.timeout(1, &example)
|
16
|
+
end
|
14
17
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Hexp::CssSelector::Attribute do
|
4
|
-
subject(:selector) { described_class.new(name,
|
4
|
+
subject(:selector) { described_class.new(name, operator, value) }
|
5
5
|
let(:name) { nil }
|
6
|
-
let(:namespace) { nil }
|
7
6
|
let(:operator) { nil }
|
8
7
|
let(:value) { nil }
|
9
|
-
let(:flags) { nil }
|
10
8
|
|
11
9
|
describe 'without an operator' do
|
12
10
|
let(:name) { 'href' }
|
@@ -26,7 +24,7 @@ describe Hexp::CssSelector::Attribute do
|
|
26
24
|
|
27
25
|
describe 'with the "=" operator' do
|
28
26
|
let(:name) { 'class' }
|
29
|
-
let(:operator) {
|
27
|
+
let(:operator) { :equal }
|
30
28
|
let(:value) { 'foo' }
|
31
29
|
|
32
30
|
it "should match if the attribute's value is exactly equal to the given value" do
|
@@ -44,7 +42,7 @@ describe Hexp::CssSelector::Attribute do
|
|
44
42
|
|
45
43
|
describe 'the "~=" operator' do
|
46
44
|
let(:name) { 'class' }
|
47
|
-
let(:operator) {
|
45
|
+
let(:operator) { :includes }
|
48
46
|
let(:value) { 'foo' }
|
49
47
|
|
50
48
|
it 'should match an entry in a space separated list' do
|
@@ -62,7 +60,7 @@ describe Hexp::CssSelector::Attribute do
|
|
62
60
|
|
63
61
|
describe 'the "|=" operator' do
|
64
62
|
let(:name) { 'id' }
|
65
|
-
let(:operator) {
|
63
|
+
let(:operator) { :dash_match }
|
66
64
|
let(:value) { 'foo' }
|
67
65
|
|
68
66
|
it 'should match if the attribute starts with the value, followed by a dash' do
|
@@ -80,7 +78,7 @@ describe Hexp::CssSelector::Attribute do
|
|
80
78
|
|
81
79
|
describe 'the "^=" operator' do
|
82
80
|
let(:name) { 'id' }
|
83
|
-
let(:operator) {
|
81
|
+
let(:operator) { :prefix_match }
|
84
82
|
let(:value) { 'foo' }
|
85
83
|
|
86
84
|
it 'should match if the attribute is just the value' do
|
@@ -98,7 +96,7 @@ describe Hexp::CssSelector::Attribute do
|
|
98
96
|
|
99
97
|
describe 'the "$=" operator' do
|
100
98
|
let(:name) { 'id' }
|
101
|
-
let(:operator) {
|
99
|
+
let(:operator) { :suffix_match }
|
102
100
|
let(:value) { 'foo' }
|
103
101
|
|
104
102
|
it 'should match if the attribute is just the value' do
|
@@ -116,7 +114,7 @@ describe Hexp::CssSelector::Attribute do
|
|
116
114
|
|
117
115
|
describe 'the "*=" operator' do
|
118
116
|
let(:name) { 'id' }
|
119
|
-
let(:operator) {
|
117
|
+
let(:operator) { :substring_match }
|
120
118
|
let(:value) { 'foo' }
|
121
119
|
|
122
120
|
it 'should match if the attribute is just the value' do
|
@@ -9,10 +9,7 @@ describe Hexp::CssSelector::Parser do
|
|
9
9
|
context 'with a single tag' do
|
10
10
|
let(:selector) { 'body' }
|
11
11
|
it {
|
12
|
-
should eq HC::CommaSequence[
|
13
|
-
HC::Sequence[
|
14
|
-
HC::SimpleSequence[
|
15
|
-
HC::Element.new('body')]]]
|
12
|
+
should eq HC::CommaSequence[HC::Element.new('body')]
|
16
13
|
}
|
17
14
|
end
|
18
15
|
|
@@ -29,6 +26,7 @@ describe Hexp::CssSelector::Parser do
|
|
29
26
|
should eq HC::CommaSequence[
|
30
27
|
HC::Sequence[
|
31
28
|
HC::SimpleSequence[
|
29
|
+
HC::Universal.new,
|
32
30
|
HC::Id.new('main')],
|
33
31
|
HC::SimpleSequence[
|
34
32
|
HC::Element.new('a'),
|
@@ -40,11 +38,10 @@ describe Hexp::CssSelector::Parser do
|
|
40
38
|
let(:selector) { 'div[link=href]' }
|
41
39
|
it {
|
42
40
|
should eq HC::CommaSequence[
|
43
|
-
HC::Sequence[
|
44
41
|
HC::SimpleSequence[
|
45
42
|
HC::Element.new('div'),
|
46
|
-
HC::Attribute.new('link',
|
47
|
-
]]
|
43
|
+
HC::Attribute.new('link', :equal, 'href'),
|
44
|
+
]]
|
48
45
|
}
|
49
46
|
end
|
50
47
|
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hexp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arne Brasseur
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-02-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: sass
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 3.2.19
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 3.2.19
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: nokogiri
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -153,6 +139,7 @@ files:
|
|
153
139
|
- README.md
|
154
140
|
- Rakefile
|
155
141
|
- bench/node/rewrite_bench.rb
|
142
|
+
- code_of_conduct.md
|
156
143
|
- config/devtools.yml
|
157
144
|
- config/flay.yml
|
158
145
|
- config/flog.yml
|
@@ -173,7 +160,6 @@ files:
|
|
173
160
|
- lib/hexp/core_ext/nil.rb
|
174
161
|
- lib/hexp/css_selector.rb
|
175
162
|
- lib/hexp/css_selector/parser.rb
|
176
|
-
- lib/hexp/css_selector/sass_parser.rb
|
177
163
|
- lib/hexp/dom.rb
|
178
164
|
- lib/hexp/dsl.rb
|
179
165
|
- lib/hexp/errors.rb
|
@@ -249,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
249
235
|
version: '0'
|
250
236
|
requirements: []
|
251
237
|
rubyforge_project:
|
252
|
-
rubygems_version: 2.
|
238
|
+
rubygems_version: 2.4.5
|
253
239
|
signing_key:
|
254
240
|
specification_version: 4
|
255
241
|
summary: Generate and manipulate HTML documents and nodes.
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Hexp
|
2
|
-
module CssSelector
|
3
|
-
# A CSS Parser that only knows how to parse CSS selectors
|
4
|
-
#
|
5
|
-
class SassParser < ::Sass::SCSS::CssParser
|
6
|
-
# Initialize the parser with the selector to parse
|
7
|
-
#
|
8
|
-
# @param [String] selector
|
9
|
-
#
|
10
|
-
# @api private
|
11
|
-
def initialize(selector)
|
12
|
-
# TODO this is a private API and has before changed in minor versions,
|
13
|
-
# see if there is a more robust call.
|
14
|
-
super(selector, '', 0)
|
15
|
-
end
|
16
|
-
|
17
|
-
# Parse the selector
|
18
|
-
#
|
19
|
-
# @return [Sass::Selector::CommaSequence]
|
20
|
-
#
|
21
|
-
# @api private
|
22
|
-
def parse
|
23
|
-
init_scanner!
|
24
|
-
result = selector_comma_sequence
|
25
|
-
raise "Invalid CSS selector : unconsumed input #{@scanner.rest}" unless @scanner.eos?
|
26
|
-
result
|
27
|
-
end
|
28
|
-
|
29
|
-
# Parse a CSS selector in one go
|
30
|
-
#
|
31
|
-
# @param [String] selector
|
32
|
-
# @return [Sass::Selector::CommaSequence]
|
33
|
-
#
|
34
|
-
# @api private
|
35
|
-
def self.call(selector)
|
36
|
-
self.new(selector).parse
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|