-
Notifications
You must be signed in to change notification settings - Fork 129
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
feat(color): Refactor existing color parsing to better align with spec #308
Conversation
Add public structs Hue and AlphaValue. Add methods parse_hue() and parse_alpha_value() to public trait ColorComponentParser. Add or update documentation to include links to relevant sections of css-color-4 draft.
Ah, sorry, I had missed this one, feel free to explicitly request review so I don't miss it in the future. I'll take a look asap. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Not opposed to introducing Hue
or AlphaValue
(though I wonder if it'd make sense to do that separately, reusing parse_number_or_percentage
).
I wonder what's the reasoning for changing the parsing code? At a glance seems it should be slower and without any obvious benefit, but it might have more obvious of benefit with following changes?
In any case we'd need to allow constructing Hue
/ AlphaValue
externally.
) -> Result<Hue, ParseError<'i, Self::Error>> { | ||
let location = input.current_source_location(); | ||
Ok(match *input.next()? { | ||
Token::Number { value: degrees, .. } => Hue { degrees }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the reason this (parse_angle_or_number
, etc) are in ColorComponentParser
is so that we can add calc()
support externally e.g., in Firefox. However Hue
is not constructible outside of this crate so that's not feasible. That needs to at least be fixed
fn parse_alpha_value<'t>( | ||
&self, | ||
input: &mut Parser<'i, 't>, | ||
) -> Result<AlphaValue, ParseError<'i, Self::Error>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
// https://drafts.csswg.org/css-values/#angles | ||
let hue_degrees = component_parser.parse_angle_or_number(arguments)?.degrees(); | ||
// Try to parse legacy syntax first. | ||
let legacy_syntax_result = arguments.try_parse(|input| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This refactoring seems somewhat gratuituous? What advantages does it give us? At a glance it seems it would make parsing a bit slower / rewind more.
☔ The latest upstream changes (presumably #309) made this pull request unmergeable. Please resolve the merge conflicts. |
I didn't/don't seem to have the permissions to be able to do that.
As I mentioned above, I would have already removed
I laid out my reasoning in #293 (comment). The motivation for this refactoring is to make maintenance easier, based on how the spec is structured. I did not optimize for speed, nor is it clear to me that the difference is significant. My implementation of
I'm not sure I'm following what you mean here. As far as I can tell, the existing |
My point is, how do we re-implement ColorComponentParser::parse_hue to support e.g. calc() if the hue degrees member is not public and there's no function to construct a Hue? Sorry if I wasn't clear on that point, or if I've missed something. And yeah, let's remove parse_number_or_percentage. Having a function that gets never called on an interface is silly, and it doesn't particularly help backwards compat (this should be published as a breaking change regardless). |
I think that's a problem with NumberOrPercentage and AngleOrNumber because they're enums that doesn't exist for Hue and AlphaValue because they're structs. For example, this is what I've been using to get the values out for tests, which is annoying: if let AngleOrNumber::Angle { degrees } = ColorComponentParser::parse_angle_or_number(
&DefaultComponentParser,
&mut Parser::new(&mut ParserInput::new("123deg")),
)
.unwrap()
{
degrees
} else {
unreachable!()
}; But I think for the new stuff we can just do something like this: let x = Hue { degrees: 0. };
let y = x.degrees; I'll dig around to confirm after I finish with this other thing I'm working on.
Oh, cool. |
Unclear why you wouldn't be able to just use
Yes, all of them. |
You mean for the value being parsed? I'm testing angle parsing in this example.
Oooooh. That was unintentional; I'll fix it. (I think I was actually confusing
👍🏻 |
} | ||
} | ||
/// https://w3c.github.io/csswg-drafts/css-color-4/#hue-syntax | ||
pub struct Hue { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps a newtype as there is only one value:
pub struct Hue(f32);
} | ||
|
||
/// https://w3c.github.io/csswg-drafts/css-color-4/#alpha-syntax | ||
pub struct AlphaValue { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, also we know it's a value so just Alpha
would suffice.
|
||
/// Parse a `<hue>` value. | ||
/// https://w3c.github.io/csswg-drafts/css-color-4/#typedef-hue | ||
fn parse_hue<'t>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function doesn't really parse hue values, but angles. Should there be a specific abstraction for hue values only?
NumberOrPercentage::Percentage { unit_value } => (clamp_unit_f32(unit_value), false), | ||
}; | ||
// Try to parse legacy syntax first. | ||
let legacy_syntax_result = arguments.try_parse(|input| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function ends up being very long and duplicates quite a bit of code. That and the fact that the hsl and hwb versions are also on their own now, duplicating code, I'm not sure this is an improvement over the original.
The abstractions for Hue
and Alpha
doesn't add much value on their own. If you are the consumer of the parse_hue function you don't even know what unit you're getting back. Adding some unit function might help, e.g. Hue::as_degrees(..)
, Hue::as_percentage(..)
or Hue::as_unit(..)
. This of course is that NumberOrPercentage
does with enums.
Just to checkpoint this, since it's taking a while... My initial approach in this PR was to do this refactoring iteratively so as to preserve backwards compatibility. However, given the feedback above, I have now opted to perform a complete rewrite of color support all at once, based directly on the css-color-4 spec (as opposed to the hybrid between css-color-3 and css-color-4 that currently exists in the codebase). This will allow the addition of a handful of new features straight away and will make it easier to add the remaining support in the future. I am also attempting to draw the line more firmly between parsing and processing, so that more parsing things can be done in this library, but some other processing things are deferred to code that makes use of it. My work has been complicated by the refactoring that was done as part of #309, but I think I've gotten through that and am now tweaking and tidying up edgecases. That being said, it will likely be a couple more weeks before I have a new PR ready to present. (Until then, I'll leave this one open.) |
Superseded by #314. |
Add public structs
Hue
andAlphaValue
.Add methods
parse_hue()
andparse_alpha_value()
to public traitColorComponentParser
.Add or update documentation to include links to relevant sections of css-color-4 draft.
Following on from my comment on #293, I've gone ahead and refactored the color parsing code to better align with the text of the draft css-color-4 spec, which also allows for easier extension to support the multitude of new functionality that is being specified. (I already have a working implementation of the
none
keyword nearing completion based on these changes, for example.)I don't know the policy on removing public features, so I've left in the
NumberOrPercentage
andAngleOrNumber
enums and theparse_angle_or_number()
andparse_number_or_percentage()
methods ofColorComponentParser
, even though I think they are now redundant. I'd be happy to remove them in a later PR, if that's deemed appropriate.For reference, the latest draft of css-color-4 is available here:
https://w3c.github.io/csswg-drafts/css-color-4/