-
Notifications
You must be signed in to change notification settings - Fork 68
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
Fix shorthand sorting buggy #1730
Conversation
🦋 Changeset detectedLatest commit: 8b6edba The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Deploy Preview for compiled-css-in-js canceled.
|
.d { border: none; } | ||
.f { border-block-start-color: transparent; }" | ||
`); | ||
}); | ||
|
||
it('sorts a subset of atomic classes taken from a real stylesheet', () => { |
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 is a small subset of the jira stylesheet that i found was not being sorted correctly
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.
Got it, some other thoughts if they're not tested in here should be border > border-top > border-top-color
right?
Input:
._abcd1234 { border-top-color: red }
._abcd1234 { border-top: 1px solid }
._abcd1234 { border: none }
._abcd1234:hover { border-top-color: red }
._abcd1234:hover { border-top: 1px solid }
._abcd1234:hover { border: none }
@media (…) { ._abcd1234 { border-top-color: red } }
@media (…) { ._abcd1234 { border-top: 1px solid } }
@media (…) { ._abcd1234 { border: none } }
Output:
._abcd1234 { border: none }
._abcd1234 { border-top: 1px solid }
._abcd1234 { border-top-color: red }
._abcd1234:hover { border: none }
._abcd1234:hover { border-top: 1px solid }
._abcd1234:hover { border-top-color: red }
@media (…) { ._abcd1234 { border: none } }
@media (…) { ._abcd1234 { border-top: 1px solid } }
@media (…) { ._abcd1234 { border-top-color: red } }
The main question I'd have is do we still maintain this pseudo and media query sorting, the rest seems fine to me…
@@ -37,31 +37,19 @@ const sortNodes = (a: ChildNode, b: ChildNode): number => { | |||
|
|||
if (!aDecl?.prop || !bDecl?.prop) return 0; | |||
|
|||
const aShorthand = shorthandFor[aDecl.prop as ShorthandProperties]; |
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.
remove the previous logic that checked whether the property was a shorthand property of the other (e.g. padding
and paddingTop
)
the likelihood that we manage to sort two nodes such that a === padding && b in [paddingTop, paddingLeft, paddingBottom, paddingRight]
is pretty low, so it's much easier just to lean on the shorthand bucket logic later in the function
const bShorthandBucket = shorthandBuckets[bDecl.prop as ShorthandProperties]; | ||
// Why default to Infinity? Because if the property is not a shorthand property, | ||
// we want it to come after all of the other shorthand properties. | ||
const aShorthandBucket = shorthandBuckets[aDecl.prop as ShorthandProperties] ?? Infinity; |
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.
how the bucket system works is that every shorthand property is assigned a number
e.g. padding
is 1, padding-block
and padding-inline
is 2
padding-{left, top, right, bottom}
is assigned a number and so defaults to Infinity
when sorting, we ensure that properties with lower numbers come before properties with higher numbers
this also has the side effect of making the behaviour almost identical to runtime mode
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.
Yeah, this changed because mine originally was like "A is a shorthand of B", now it's more like "A is shorthand 5", "B is shorthand 3" and this change LGTM.
This doesn't sort padding-block-start
vs. padding-left
, but that's still fine, those are "siblings" and that's what we want. I can't think of any scenario where this isn't what we want…maybe like border-block-color
and border-top
are sorted as siblings now and there could be some odd conflicts…? But I'd say if we have issues with that we have like sort-logical-properties
or something—that's separate to this and should rarely come up (but likely does exist).
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 doesn't sort padding-block-start vs. padding-left, but that's still fine, those are "siblings" and that's what we want…maybe like border-block-color and border-top are sorted as siblings now and there could be some odd conflicts…?
I can add it to packages/utils/src/shorthand.ts
if you want :) just let me know
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.
No, let's not, I don't know what that should even be. It's fine as-is, and if we need to add this later we have a good path forward!
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.
Just one comment on an additional test I think, LGTM otherwise.
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.
Yeah, I see. I think my original intent was to simply sort padding
above paddingLeft
for example, and ignore everything else…and then it grew a lot since then.
Now it's more like bucketing, but still sorted, which makes sense to me. Will suggest a few scenarios to test is all.
.d { border: none; } | ||
.f { border-block-start-color: transparent; }" | ||
`); | ||
}); | ||
|
||
it('sorts a subset of atomic classes taken from a real stylesheet', () => { |
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.
Got it, some other thoughts if they're not tested in here should be border > border-top > border-top-color
right?
Input:
._abcd1234 { border-top-color: red }
._abcd1234 { border-top: 1px solid }
._abcd1234 { border: none }
._abcd1234:hover { border-top-color: red }
._abcd1234:hover { border-top: 1px solid }
._abcd1234:hover { border: none }
@media (…) { ._abcd1234 { border-top-color: red } }
@media (…) { ._abcd1234 { border-top: 1px solid } }
@media (…) { ._abcd1234 { border: none } }
Output:
._abcd1234 { border: none }
._abcd1234 { border-top: 1px solid }
._abcd1234 { border-top-color: red }
._abcd1234:hover { border: none }
._abcd1234:hover { border-top: 1px solid }
._abcd1234:hover { border-top-color: red }
@media (…) { ._abcd1234 { border: none } }
@media (…) { ._abcd1234 { border-top: 1px solid } }
@media (…) { ._abcd1234 { border-top-color: red } }
The main question I'd have is do we still maintain this pseudo and media query sorting, the rest seems fine to me…
|
||
const declarations = node.nodes.map(findDeclaration).filter(Boolean) as Declaration[]; | ||
|
||
if (declarations.length === 1) { |
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.
I deleted this as it would cause
@media (max-width: 100px) { ._abcd1234 { border-top: 1px solid } }
to be sorted with
._abcd1234 { border: 1px solid }
which overrides the sorting from the sort-at-rules
plugin and I don't think is intentional?
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.
If I had to guess, I think I had issues understanding what sorting even looked at in the beginning, eg. there's a lot of different types of styles, I wasn't really sure what we were sorting at times 😅
- a whole stylesheet with multiple classes, media, etc in it
- an
@media
query with multiple classes in it - a single
.class {property}
- A multiple
.class {property, webkitproperty}
— though I don't know if I even solved for that.
…so yeah, treat any of the code (if I wrote this) around here as possibly wrong!
._abcd1234 { border-top-color: red } | ||
._abcd1234:hover { border-top-color: red } | ||
._abcd1234:active { border-top-color: red } | ||
@media (max-width: 150px) { ._abcd1234 { border: none } } |
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.
note that the media query sorting is also being run here
font: 16px; | ||
outline-width: 1px; |
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.
i don't think this matters, because styles are atomicised in Compiled anyway
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.
Love your work, I think this is great and tests cover all my concerns really.
|
||
if (sortShorthandEnabled) { | ||
sortShorthandDeclarations(root.nodes); | ||
} |
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.
Got it, so it was just my bad this was ordered like this.
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.
it was my bad as well 😅 lots of subtle behaviour quirks and bugs i didn't spot even from working on it for hours
}: { sortAtRulesEnabled: boolean | undefined; sortShorthandEnabled: boolean | undefined } | ||
}: { sortAtRulesEnabled: boolean | undefined; sortShorthandEnabled: boolean | undefined } = { |
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.
Given this is now a required prop, I actually expect this to fail in TS anywhere sort()
is called…but yeah I guess we have to find them directly in code if we find them:
-sort(styles);
+sort(styles, { sortAtRulesEnabled: true, sortShorthandEnabled: true });
Not the best configuration experience, but we'll survive for now.
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.
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.
but yeah we would need to turn on sortShorthandEnabled
manually everywhere in order to roll it out
(how would we make sure we don't forget? 🤔 should we default to true instead?)
._abcd1234 { border: none } | ||
._abcd1234 { border-top: 1px solid } | ||
._abcd1234 { border-top-color: red } | ||
._abcd1234:hover { border: none } | ||
._abcd1234:hover { border-top: 1px solid } | ||
._abcd1234:hover { border-top-color: red } |
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.
Oh is this fixed now? 😮
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.
yeah i fixed it in 18adcbe
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.
whoops not that commit
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.
fixed in this one 8b6edba
What is this change?
Fix the shorthand property sorting being buggy when not using runtime mode (e.g. when using stylesheet extraction).
Why are we making this change?
@kylorhall-atlassian and I noticed that
sortShorthand
wasn't actually sorting the properties as it should.It turns out that a lot of the time in the sorting algorithm, the two properties being compared are
padding
is related topaddingLeft
, butpadding
is not related toborderColor
), andshorthandBuckets
As a result, there are cases where the stylesheet would not be sorted at all, simply because the wrong nodes were being compared and so the
sortNodes
function returns0
every time.How are we making this change?
Fix and simplify the
sortNodes
function:false
most of the time anyway.aShorthandBucket
andbShorthandBucket
, set the default value toInfinity
. This way, if one property is a shorthand property and the other property is not a shorthand property, we guarantee that the shorthand property will come in front. For example,margin
will come beforepaddingRight
(even though they're not related).PR checklist
Don't delete me!
I have...
website/