-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Collapse multiple utilities #19147
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
Merged
Merged
Collapse multiple utilities #19147
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
f0b68ff
add `features` to the canonicalization options
RobinMalfait 6573318
add expand-declaration
RobinMalfait 4438411
add canonicalize tests for going from multiple to one class
RobinMalfait b84ec47
share options
RobinMalfait 271696b
add canonicalizeAst function
RobinMalfait ecbcb8c
move `resolveVariablesInValue` to its own function
RobinMalfait 88180de
combine walks into single walk
RobinMalfait 21faf2c
convert function to `enter` object
RobinMalfait da84979
sort declarations
RobinMalfait 0bd45f9
passthrough features to `signature` generation step
RobinMalfait 7526411
expand declarations during signature generation
RobinMalfait 15d2792
cache properties and values per utility
RobinMalfait 2822138
collapse properties
RobinMalfait 8da361e
Merge branch 'main' into feat/canonicalize-multiple-to-one
RobinMalfait 8f84633
add link to Gosper's hack
RobinMalfait 1466cf7
Merge branch 'main' into feat/canonicalize-multiple-to-one
RobinMalfait File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| import { describe, expect, test } from 'vitest' | ||
| import { toCss } from './ast' | ||
| import { parse } from './css-parser' | ||
| import { expandDeclaration } from './expand-declaration' | ||
| import { SignatureFeatures } from './signatures' | ||
| import { walk, WalkAction } from './walk' | ||
|
|
||
| const css = String.raw | ||
|
|
||
| function expand(input: string, options: SignatureFeatures): string { | ||
| let ast = parse(input) | ||
|
|
||
| walk(ast, (node) => { | ||
| if (node.kind === 'declaration') { | ||
| let result = expandDeclaration(node, options) | ||
| if (result) return WalkAction.ReplaceSkip(result) | ||
| } | ||
| }) | ||
|
|
||
| return toCss(ast) | ||
| } | ||
|
|
||
| describe('expand declarations', () => { | ||
| let options = SignatureFeatures.ExpandProperties | ||
|
|
||
| test('expand to 4 properties', () => { | ||
| let input = css` | ||
| .one { | ||
| inset: 10px; | ||
| } | ||
|
|
||
| .two { | ||
| inset: 10px 20px; | ||
| } | ||
|
|
||
| .three { | ||
| inset: 10px 20px 30px; | ||
| } | ||
|
|
||
| .four { | ||
| inset: 10px 20px 30px 40px; | ||
| } | ||
| ` | ||
|
|
||
| expect(expand(input, options)).toMatchInlineSnapshot(` | ||
| ".one { | ||
| top: 10px; | ||
| right: 10px; | ||
| bottom: 10px; | ||
| left: 10px; | ||
| } | ||
| .two { | ||
| top: 10px; | ||
| right: 20px; | ||
| bottom: 10px; | ||
| left: 20px; | ||
| } | ||
| .three { | ||
| top: 10px; | ||
| right: 20px; | ||
| bottom: 30px; | ||
| left: 20px; | ||
| } | ||
| .four { | ||
| top: 10px; | ||
| right: 20px; | ||
| bottom: 30px; | ||
| left: 40px; | ||
| } | ||
| " | ||
| `) | ||
| }) | ||
|
|
||
| test('expand to 2 properties', () => { | ||
| let input = css` | ||
| .one { | ||
| gap: 10px; | ||
| } | ||
|
|
||
| .two { | ||
| gap: 10px 20px; | ||
| } | ||
| ` | ||
|
|
||
| expect(expand(input, options)).toMatchInlineSnapshot(` | ||
| ".one { | ||
| row-gap: 10px; | ||
| column-gap: 10px; | ||
| } | ||
| .two { | ||
| row-gap: 10px; | ||
| column-gap: 20px; | ||
| } | ||
| " | ||
| `) | ||
| }) | ||
|
|
||
| test('expansion with `!important`', () => { | ||
| let input = css` | ||
| .one { | ||
| inset: 10px; | ||
| } | ||
|
|
||
| .two { | ||
| inset: 10px 20px; | ||
| } | ||
|
|
||
| .three { | ||
| inset: 10px 20px 30px !important; | ||
| } | ||
|
|
||
| .four { | ||
| inset: 10px 20px 30px 40px; | ||
| } | ||
| ` | ||
|
|
||
| expect(expand(input, options)).toMatchInlineSnapshot(` | ||
| ".one { | ||
| top: 10px; | ||
| right: 10px; | ||
| bottom: 10px; | ||
| left: 10px; | ||
| } | ||
| .two { | ||
| top: 10px; | ||
| right: 20px; | ||
| bottom: 10px; | ||
| left: 20px; | ||
| } | ||
| .three { | ||
| top: 10px !important; | ||
| right: 20px !important; | ||
| bottom: 30px !important; | ||
| left: 20px !important; | ||
| } | ||
| .four { | ||
| top: 10px; | ||
| right: 20px; | ||
| bottom: 30px; | ||
| left: 40px; | ||
| } | ||
| " | ||
| `) | ||
| }) | ||
| }) | ||
|
|
||
| describe('expand logical properties', () => { | ||
| let options = SignatureFeatures.ExpandProperties | SignatureFeatures.LogicalToPhysical | ||
|
|
||
| test('margin-block', () => { | ||
| let input = css` | ||
| .example { | ||
| margin-block: 10px 20px; | ||
| } | ||
| ` | ||
|
|
||
| expect(expand(input, options)).toMatchInlineSnapshot(` | ||
| ".example { | ||
| margin-top: 10px; | ||
| margin-bottom: 20px; | ||
| } | ||
| " | ||
| `) | ||
| }) | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| import { decl, type AstNode } from './ast' | ||
| import { SignatureFeatures } from './signatures' | ||
| import { segment } from './utils/segment' | ||
|
|
||
| function createPrefixedQuad( | ||
| prefix: string, | ||
| t = 'top', | ||
| r = 'right', | ||
| b = 'bottom', | ||
| l = 'left', | ||
| ): Record<number, [prop: string, index: number][]> { | ||
| return createBareQuad(`${prefix}-${t}`, `${prefix}-${r}`, `${prefix}-${b}`, `${prefix}-${l}`) | ||
| } | ||
|
|
||
| // prettier-ignore | ||
| function createBareQuad(t = 'top', r = 'right', b = 'bottom', l = 'left'): Record<number, [prop: string, index: number][]> { | ||
| return { | ||
| 1: [[t, 0], [r, 0], [b, 0], [l, 0]], | ||
| 2: [[t, 0], [r, 1], [b, 0], [l, 1]], | ||
| 3: [[t, 0], [r, 1], [b, 2], [l, 1]], | ||
| 4: [[t, 0], [r, 1], [b, 2], [l, 3]], | ||
| } as const; | ||
| } | ||
|
|
||
| // prettier-ignore | ||
| function createPair(lhs: string, rhs: string): Record<number, [prop: string, index: number][]> { | ||
| return { | ||
| 1: [[lhs, 0], [rhs, 0]], | ||
| 2: [[lhs, 0], [rhs, 1]], | ||
| } as const; | ||
| } | ||
|
|
||
| // Depending on the length of the value, map to different properties | ||
| let VARIADIC_EXPANSION_MAP: Record<string, Record<number, [prop: string, index: number][]>> = { | ||
| inset: createBareQuad(), | ||
| margin: createPrefixedQuad('margin'), | ||
| padding: createPrefixedQuad('padding'), | ||
| gap: createPair('row-gap', 'column-gap'), | ||
| } | ||
|
|
||
| // Depending on the length of the value, map to different properties | ||
| let VARIADIC_LOGICAL_EXPANSION_MAP: Record< | ||
| string, | ||
| Record<number, [prop: string, index: number][]> | ||
| > = { | ||
| 'inset-block': createPair('top', 'bottom'), | ||
| 'inset-inline': createPair('left', 'right'), | ||
| 'margin-block': createPair('margin-top', 'margin-bottom'), | ||
| 'margin-inline': createPair('margin-left', 'margin-right'), | ||
| 'padding-block': createPair('padding-top', 'padding-bottom'), | ||
| 'padding-inline': createPair('padding-left', 'padding-right'), | ||
| } | ||
|
|
||
| // The entire value is mapped to each property | ||
| let LOGICAL_EXPANSION_MAP: Record<string, string[]> = { | ||
| 'border-block': ['border-bottom', 'border-top'], | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These on the other hand map to the physical properties as-is. border-block: 1px solid red;Would map to: border-top: 1px solid red;
border-bottom: 1px solid red; |
||
| 'border-block-color': ['border-bottom-color', 'border-top-color'], | ||
| 'border-block-style': ['border-bottom-style', 'border-top-style'], | ||
| 'border-block-width': ['border-bottom-width', 'border-top-width'], | ||
| 'border-inline': ['border-left', 'border-right'], | ||
| 'border-inline-color': ['border-left-color', 'border-right-color'], | ||
| 'border-inline-style': ['border-left-style', 'border-right-style'], | ||
| 'border-inline-width': ['border-left-width', 'border-right-width'], | ||
| } | ||
|
|
||
| export function expandDeclaration( | ||
| node: Extract<AstNode, { kind: 'declaration' }>, | ||
| options: SignatureFeatures, | ||
| ): AstNode[] | null { | ||
| if (options & SignatureFeatures.LogicalToPhysical) { | ||
| if (node.property in VARIADIC_LOGICAL_EXPANSION_MAP) { | ||
| let args = segment(node.value!, ' ') | ||
| return VARIADIC_LOGICAL_EXPANSION_MAP[node.property][args.length]?.map(([prop, index]) => { | ||
| return decl(prop, args[index], node.important) | ||
| }) | ||
| } | ||
|
|
||
| if (node.property in LOGICAL_EXPANSION_MAP) { | ||
| return LOGICAL_EXPANSION_MAP[node.property]?.map((prop) => { | ||
| return decl(prop, node.value!, node.important) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| if (node.property in VARIADIC_EXPANSION_MAP) { | ||
| let args = segment(node.value!, ' ') | ||
| return VARIADIC_EXPANSION_MAP[node.property][args.length]?.map(([prop, index]) => { | ||
| return decl(prop, args[index], node.important) | ||
| }) | ||
| } | ||
|
|
||
| return null | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
These depend on the amount of arguments
inset: 10pxwill settop,right,bottom,leftto10px. But10px 20pxwill settopandbottomto10pxandleftandrightto20px