futursolo / stylist-rs

A CSS-in-Rust styling solution for WebAssembly Applications
https://crates.io/crates/stylist
MIT License
366 stars 22 forks source link

`a:hover {}` is invalid css #147

Open simbleau opened 8 months ago

simbleau commented 8 months ago

I get a cryptic message with the following:

css! {
    a:hover {
        color: white;
    }
}

Error: unexpected end of input, AttributeValue: unexpected end of input

If you change a:hover to anything else it works.

jsievenpiper commented 8 months ago

@simbleau should the css! macro be invoked in a function-like way? e.g. css!() instead of css!{}?

I've also found that stylist's ability to use bare css doesn't work in all cases: sometimes you'll need to switch to a stringified style ala:

css!(r#"
  a:hover {
    color: white;
  }
#")
simbleau commented 8 months ago

@simbleau should the css! macro be invoked in a function-like way? e.g. css!() instead of css!{}?

I've also found that stylist's ability to use bare css doesn't work in all cases: sometimes you'll need to switch to a stringified style ala:

css!(r#"
  a:hover {
    color: white;
  }
#")

AFAIK there is no difference between macro!{}, macro!() and macro![]

And yes, the stringify way works, but isn't addressing the problem.

jsievenpiper commented 8 months ago

AFAIK there is no difference between macro!{}, macro!() and macro![]

TIL these are interchangeable!

~For further context, things like parameter substitution don't work without stringifying it either. I had stumbled into stylist (sometimes) correctly parsing unquoted css like you're trying, but I don't see anywhere in the docs (at least skimming the surface level stuff) implying it's supported at all.~

EDIT: Turns out I was completely wrong here -- diving in a bit deeper, this is totally supposed to be supported! https://docs.rs/stylist/latest/stylist/macros/index.html#example-2

Apologies for the confusion!

WorldSEnder commented 7 months ago

The parsing code in https://github.com/futursolo/stylist-rs/blob/74e0fd07232cf39fc78c863bc70f8f574a5271ef/packages/stylist-macros/src/inline/parse/scope_content.rs#L33-L42 erroneously? assumes that a : hover is (the start of) an attribute declaration, not the block qualifier that is should be parsed as. Note that {} blocks are considered a potentially valid part of an attribute value, too. ^1 Hence, the whole thing is parsed as one attribute, with a missing terminating semicolon at the end.

The correct decision probably needs to reparse a potentially unbounded part of the input; Both <attr-name> : <attr-value> ; and <element-name> : <pseudo-class-rule> { } allow for arbitrarily complex token sequences (as attr-value and pseudo-class-rule) before breaking the tie by either observing a semicolon ; or an open brace {. Hence I'm a bit conflicted how to address this. Introducing unbounded backtracking into the parser isn't something I fancy.

You can, with probably good enough browser support, rewrite this as

:is(a):hover {
}

Note that generating class names tries to encourage you to not depend on the element type of the annotated element - hence why such an example is not shown. I suppose, in this case, you are trying to fix some global browser dictated style for <a> elements, instead of trying to introduce this declaration for a specific component?

simbleau commented 5 months ago

I suppose, in this case, you are trying to fix some global browser dictated style for <a> elements, instead of trying to introduce this declaration for a specific component?

Yes, in my case, this is the website's (global) style.

apoorv569 commented 1 month ago

I get a cryptic message with the following:

css! {
    a:hover {
        color: white;
    }
}

Error: unexpected end of input, AttributeValue: unexpected end of input

If you change a:hover to anything else it works.

If this css! is a part of an a tag, then you can try this,

                <a
                    class={
                        css! {
                            /* Other example styles */
                            background-color: black;

                            :hover {
                                color: white;
                            }
                        }
                    }
                />

You can also try the string literal way, by putting all the css code inside r#" HERE "#.