I have a problem with Style Lint. I have set the selector-max-specificity at 0,2,0 with some ignored rules : ignoreSelectors: [":focus", ":hover", etc..]
Now, I want to ignore the :not(.myClass) selector but this doesn't work :(
For example i have my class with this name : .track a:not(.track-visual)
I have tried with regex selector "/:not\\(.*\\)/" or even with "/.*:not\\(.*\\)/"
But no chance :'(
If you have a solution, i'm interested :)
Thank you
I'm guessing that here we would be wishing to capture those with :not, which in that event, we would be starting with a simple expression such as:
.+?:not\(.+?\)
Demo
RegEx Circuit
jex.im visualizes regular expressions:
Don't think this can be done. The latest code for the rule includes the following:
const ownSpecificity =
ownValue === ':not' || ownValue === ':matches'
? // :not and :matches don't add specificity themselves, but their children do
zeroSpecificity()
: simpleSpecificity(ownValue);
As per the comment, this is not including the :not itself as something that would add specificity but is including its children, which is what the regex would be checking.
Related
I am trying to write a nested selector that selects a certain tag that has a certain attribute, for example
<li foo="bar">
To select this, li[foo="bar"] would work, but I want to nest it under [foo="bar"] using the scss & notation because I have other things with the [foo="bar"] attribute (e.g., <div foo="bar" class="baz">), and I want to group them together. When I try:
[foo = "bar"]{
&li{
...
}
&.baz{
...
}
}
It returns an error that says li may only be used at the beginning of a compound selector, and if I try:
[foo = "bar"]{
li&{
...
}
&.baz{
...
}
}
then it says & may only be used at the beginning of a compound selector. How can I do this correctly?
The right syntax nowadays would be li#{&}.
Last I heard, this is actually an upcoming feature in SASS 3.3 or 3.4.
See this thread for a question similar to yours and this thread for the proposed solution to be included (which, at the time of writing, seems to be &__element).
The issue here isn't the use of [] and & together - it's the use of a plain element in the selector. Your example with .baz should work as expected.
The MDN page on #font-face describes its syntax as:
#font-face {
[font-family: <family-name>;]?
[src: [ <uri> [format(<string>#)]? | <font-face-name> ]#;]?
[unicode-range: <urange>#;]?
[font-variant: <font-variant>;]?
[font-feature-settings: normal|<feature-tag-value>#;]?
[font-stretch: <font-stretch>;]?
[font-weight: <weight>];
[font-style: <style>];
}
But I don't know how to read such a specification and I can't find any documentation on it.
I found this Value definition syntax on MDN.
It uses the syntax of W3C CSS specs. The definition of the various parts can be found at http://www.w3.org/TR/CSS21/about.html#property-defs
In the example above, the ? means the part proceeding is optional, and the | between options indicates either one or the other options must be present, but not both.
Right now I have a selector working with jQuery as follows:
.original-tweet:not([data-is-reply-to="true"],.retweeted)
However this doesn't seem to work using the Nokogiri gem in ruby:
doc.css('.original-tweet:not([data-is-reply-to="true"],.retweeted)')
The above causes a cash, but each of the parts of the not independently work:
doc.css('.original-tweet:not([data-is-reply-to="true"])')
and
doc.css('.original-tweet:not(.retweeted)')
What's the best way to actually get the selector I want. Is this something that just isn't supported in nokogiri?
Okay, I solved it with XPATH
The following worked (note: the xpath I created was entirely computer generated)
doc.xpath("//*[contains(concat(' ', #class, ' '), ' original-tweet ') and not(#data-is-reply-to = \"true\") and not(#data-retweet-id)]")
Edit: further inspection shows that this is still selecting items with the retweeted class (turns out this was a false assumption on my part, I should have been looking for the data-retweet-id attribute instead of the retweet class)
github.com/sparklemotion/nokogiri/issues/451 - this issue relates to why I needed to use xpath here.
While the selector may work with jQuery, it's not a valid CSS selector:
> $$('.original-tweet:not([data-is-reply-to="true"], .retweeted)')
Error: SyntaxError: DOM Exception 12
.original-tweet:not([data-is-reply-to="true"]):not(.retweeted) should work.
For now a possible workaround might be:
doc.css('.original-tweet:not([data-is-reply-to="true"])') - doc.css('.retweeted')
I'm working on a Ruby script that will parse and manipulate some XML files. I'm using Nokogiri for the XML handling.
The problem I have is that there are several constructs like this one:
<USER_ELEMENT>
<NAME>ATTRIBUTE01</NAME>
<VALUE>XXX</VALUE>
</USER_ELEMENT>
I need to set the <VALUE> tag that's within the same of a particular <VALUE>ATTRIBUEnn</VALUE>. My current approach is using
xml.css('USER_ELEMENT').find { |node| node.at_css('NAME').text == 'ATTRIBUTEnn'}.at_css('VALUE').content = 'NEW_VALUE'
but it looks rather ugly.
I'm wondering which would be a cleaner way of dealing with the situation?
Using XPath:
attnn = "ATTRIBUTE01"
xml.at_xpath("//USER_ELEMENT[NAME='#{attnn}']/VALUE").content = "Yay"
puts xml
#=> <USER_ELEMENT>
#=> <NAME>ATTRIBUTE01</NAME>
#=> <VALUE>Yay</VALUE>
#=> </USER_ELEMENT>
In English, that XPath says:
//USER_ELEMENT - find elements with this name anywhere in the document
[…] - but only if…
NAME="ATTRIBUTE01" - …you can find a child NAME element with this text
/VALUE - and now find the child VALUE elements of these
The css selector for siblings is ~:
xml.at('USER_ELEMENT > NAME[text()="ATTRIBUTE01"] ~ VALUE').content = 'NEW_VALUE'
I don't know if nokogiri supports CSS3, but if it does, this should work
xml.css('USER_ELEMENT NAME:content("ATTRIBUTEnn") + VALUE').content = "NEW_VALUE"
I've spent my requisite two hours Googling this, and I can not find any good answers, so let's see if humans can beat Google computers.
I want to parse a stylesheet in Ruby so that I can apply those styles to elements in my document (to make the styles inlined). So, I want to take something like
<style>
.mystyle {
color:white;
}
</style>
And be able to extract it into a Nokogiri object of some sort.
The Nokogiri class "CSS::Parser" (http://nokogiri.rubyforge.org/nokogiri/Nokogiri/CSS/Parser.html) certainly has a promising name, but I can't find any documentation on what it is or how it works, so I have no idea if it can do what I'm after here.
My end goal is to be able to write code something like:
a_web_page = Nokogiri::HTML(html_page_as_string)
parsed_styles = Nokogiri::CSS.parse(html_page_as_string)
parsed_styles.each do |style|
existing_inlined_style = a_web_page.css(style.declaration) || ''
a_web_page.css(style.declaration)['css'] = existing_inlined_style + style.definition
end
Which would extract styles from a stylesheet and add them all as inlined styles to my document.
Nokogiri can't parse CSS stylesheets.
The CSS::Parser that you came across parses CSS expressions. It is used whenever you traverse a HTML tree by CSS selectors rather than XPath (this is a cool feature of Nokogiri).
There is a Ruby CSS parser, though. You can use it together with Nokogiri to achieve what you want.
require "nokogiri"
require "css_parser"
html = Nokogiri::HTML(html_string)
css = CssParser::Parser.new
css.add_block!(css_string)
css.each_selector do |selector, declarations, specificity|
html.css(selector).each do |element|
style = element.attributes["style"]&.value || ""
element.set_attribute('style', [style, declarations].compact.join(" "))
end
end
#molf definitely had a great start there, but it still required debugging a handful of problems to get it working in production. Here is the current, tested version of this:
html = Nokogiri::HTML(html_string)
css = CssParser::Parser.new
css.add_block!(html_string) # Warning: This line modifies the string passed into it. In potentially bad ways. Make sure the string has been duped and stored elsewhere before passing this.
css.each_selector do |selector, declarations, specificity|
next unless selector =~ /^[\d\w\s\#\.\-]*$/ # Some of the selectors given by css_parser aren't actually selectors.
begin
elements = html.css(selector)
elements.each do |match|
match["style"] = [match["style"], declarations].compact.join(" ")
end
rescue
logger.info("Couldn't parse selector '#{selector}'")
end
end
html_with_inline_styles = html.to_s