-
-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interesting psuedo class to keep an eye on :in()
#224
Comments
It seems to match the current element and/or any element under it which matches the complex selector with the pseudo-class. I'm not quite sure exactly all the ways the "end" boundary affects things. I assume that the parent element either matches the scope (and also doesn't match the end scope) or a child of the current element is matched if it matches the scope but doesn't match the end scope relative to the parent. I think it sounds more complicated than it will be to implement...I think. At first blush, it seems that we could convert: el:in(.whatever .this, .is / .not, .this) to something like this: el:is(:is(.whatever .this, .is), :is(.whatever .this, .is) *):not(:is(.not, .this), :is(.not, .this) *) I'm not at all sure though 🙃. It may be interesting to prototype. |
Threw together a prototype, and it seems to work pretty well. From reading, it appears that So, let's consider an example. Here we will target from bs4 import _soup
html = """
<div class="this">
<div class="nada">
<span class="that good">one</span>
<span class="that bad">two</span>
<span>three</span>
</div>
</div>
<div class="what">
<div class="nope">
<span class="that bad">one</span>
<span class="that good">two</span>
<span>three</span>
</div>
</div>
<div class="this that"></div>
"""
soup = _soup(html, 'html.parser')
print(soup.select('.that:in(.this, .what / .nada, .bad)')) This gives us:
Assuming I interpreted the spec correctly, this should also be correct and match nothing: from bs4 import _soup
html = """
<div class=".bad">
<div class="this">
<div class="nada">
<span class="that good">one</span>
<span class="that bad">two</span>
<span>three</span>
</div>
</div>
</bad>
"""
soup = _soup(html, 'html.parser')
print(soup.select('.that:in(.this, .what / .nada, .bad)')) Output:
Yes, the wrapper
There are absolutely no examples out is this is very new, but I can see this potentially being a useful selector. This is assuming this actually makes it to a browser and doesn't get dropped in the spec. It also assumes they don't make it a lot more complicated to implement. |
NOTES: I imagine, if worse came to worse, and we had to ensure the end boundary was under the start boundary, we could tag the inclusive selector list with a While the CSS engine will favor the closest element based on a given selector, selectors in a selector list are not sorted by proximity. We may have to track the last index tried in the inclusive list so we can retry at the next index if the scope is negated by the exclusive list. Basically, we may have to wrap are inclusive/exclusive list in some special |
My interpretation is not exactly right. After reading A New Donut Selector, I think I better understand. If we want to implement this experimental selector, I imagine we will target the main element, walk itself and its parents seeing if we find the upper boundary, then walk its parents again to see if the lower boundary gets in the way. We would stop as soon as we hit the upper boundary. The lower boundary must come under the upper boundary (they can't be the same). The target element can also be the lower boundary. In some ways, this makes things easier on us and in other ways a little more complicated. I think it is doable though. Again, the name may change, the spec may change, a lot of things could change, so if we wanted to make use before the spec is rock solid, we'd use a |
Refactor went nice, and while there needs to be some cleanup and checks for corner cases, it seems that we are able to find a tag between two clear boundaries, unlike the initial implementation. I'm optimistic this could be pretty useful. I may get an experimental branch up sometime soon-ish. |
The experimental branch is up via PR #228. No tests are currently present, but it does appear to work as described in the CSS document. I've seen the selector described as
|
Sounds like CSS is backing away from using a selector for things like So, what this means is that there will be no official pseudo-class for us to implement. We could implement our own pseudo-class despite CSS not implementing one. Or, we could allow Or, we could just pass on doing anything as there is no official selector and we aren't obligated to implement some I still think though that there something like |
If we do this, it is likely to be pretty basic in approach. An easy way of looking at it is simply that an element is matched, and then we look at the closest parent that satisfies the start limit, if that matches, we check if it has an even closer parent that matches the lower limit. If the lower limit is found, we are out of bounds and cannot match. The element that is the lower limit, in this case, could still match itself though. I guess that is a question though, do the limits themselves qualify as a match? I guess this is an inclusive/exclusive question, and I know the official Another thing I was thinking about...why couldn't this be its own function, like sv.in_scope(pattern, start, end) Anyways, |
https://drafts.csswg.org/css-cascade-6/#in-scope-selector
It would be way too early to expect that this gets implemented officially or that the spec wouldn't change right under us, but something to keep an eye on. It may be fun to play with to see how the code would actually look and how useful it is.
If I'm feeling adventurous, maybe implement it under something like
:--soup-in()
for experimental purposes.The text was updated successfully, but these errors were encountered: