Re: [selectors] Proposal: filtered sibling combinator

On 10/11/14, 7:58 AM, Tab Atkins Jr. wrote:
> On Fri, Oct 10, 2014 at 11:31 PM, Benjamin Poulain <bpoulain@apple.com> wrote:
>> Hi,
>>
>> One problem I am interested in solving is the inability to format documents that do not have a strong hierarchical structure.
>>
>> For example, let's take:
>>      <h1>Title 1</h1>
>>      <h2>Subtitle</h2>
>>      <p>Paragraph1</p>
>>      <p>Paragraph2</p>
>>      <h1>Title 2</h1>
>>      <p>Paragraph3</p>
>>      <p>Paragraph4</p>
>> A common use case is styling the first paragraph after a title (for example, using ::first-letter). We can try:
>>      h1+p::first-letter
>> but that is too strong, it does not patch Paragraph1. We can try:
>>      h1~p::first-letter
>> but that is too weak, every paragraph matches.
>>
>>
>> My current idea to solve those cases is to extend the ~ combinator to take a selector filtering the traversal. Something of the form:
>>      a ~(b) c
>>
>> Traversal to find "c" would
>> 1) Evaluate "c" on a sibling.
>> 2) If [1] fails, evaluate b on the sibling.
>> 3) If [2] succeed, go to the next sibling.
>> 4) If [2] fails, fail to match.
>>
>> The use case above can be written has:
>>      h1 ~(:not(h1, p)) p
>> Which is traverse from <h1> to a <p> but never skip over a <h1> or <p>.
>>
>>
>> The same principle could be used for descendant selector for generality.
>> For example, an image not in a link:
>>      img:not(:any-link *)
>> can be rewritten as
>>      * >>(:not(:any-link)) img
>> which is cleaner in my opinion.
> This one doesn't work - it'll match "<a><span><img></span></a>".  You
> need to verify that there's no <a> ancestors at all, like ":root
Well, it looks like you already more familiar than me with the extended 
combinators :)
>> Any interest?
> Thanks for bringing up this case explicitly. ^_^
>
> Okay, so it's a functional combinator somewhere between "next" and
> "general" (for both siblings and descendants), qualified with a
> selector to determine exactly what kinds of elements its allowed to
> skip over.  It looks like ~(*) and >>(*) are both equivalent to the ~
> and >> combinators by themselves, yes?
Yep.
> Overall, I think I like it.  I hadn't thought of actually making a
> functional combinator, so that's pretty cool.  It shouldn't be too
> much of a complication of the processing model, either - when running
> selectors backwards, it just means you're checking the selector
> against the previous siblings/ancestors.  It's basically just a
> helpful syntax, as you can achieve an identical effect by just
> repeating the selector multiple times, like `A + C, A + B + C, A + B +
> B + C, A + B + B + B + C, ...`.

Yep, that's the idea. It is a bit more general than that since the 
number of previous sibling "filtered" is arbitrary.

> Just to throw it out, an alternate syntax might be to lean on the
> /foo/ syntax for named combinators, which would look something like
> `h1 /sibling :not(h1,p)/ p` or `:root /child :not(:any-link)/ img`.  A
> benefit of this is that we no longer need to come up with *names* for
> the general forms of these combinators: if you don't pass any
> arguments, they just refer to the next child or sibling; if you want
> the general form, just pass a * argument, like `/sibling */`.
> (That'll close a comment if you don't have any whitespace between the
> * and /, but that's fine; as long as you're not in a comment, */ has
> no special meaning and is just two DELIM tokens.)
I would rather not create new names. There is value in extending the 
existing concepts, people are already familiar with the syntax.

A "problem" is extending the descendant combinator, the results looks a 
bit odd with the current syntax:
     :root (:not(:any-link)) img

Benjamin

Received on Monday, 13 October 2014 05:01:07 UTC