-
Notifications
You must be signed in to change notification settings - Fork 47
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
Add codemod to transform foundation to css variable #1781
Merged
yangwooseong
merged 20 commits into
channel-io:alpha
from
yangwooseong:feat/codemod-for-foundation
Dec 12, 2023
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
4663732
feat(bezier-codemod): add transform function for foundation theme
yangwooseong 6a4a6a7
feat(bezier-codemod): add transform function for foundation border
yangwooseong a44297d
feat(bezier-codemod): add transform function for foundation elevation
yangwooseong 01480e2
feat(bezier-codemod): add transform function for foundation rounding
yangwooseong 90e3010
feat(bezier-codemod): add transform function for foundation transition
yangwooseong 54a1c0a
feat(bezier-codemod): add test code
yangwooseong 6ebeb4d
feat(bezier-codemod): add transform to map in App.tsx
yangwooseong dd1efeb
refactor(bezier-codemod): separate arrow function getter logic
yangwooseong 19ee73f
refactor(bezier-codemod): separate test util function
yangwooseong b3a8db3
feat(bezier-codemod): add combined transform function for foundation
yangwooseong 7a89ded
feat(bezier-codemod): add changeset
yangwooseong 2fb9bc6
feat(bezier-codemod): add README.md
yangwooseong 693f595
fix(bezier-codemod): resolve test failed
yangwooseong 4dbe61b
feat(bezier-codemod): separate test code according to whether transfo…
yangwooseong ac63e74
feat(bezier-codemod): add bg-color to elevation transform
yangwooseong 79a3bfa
refactor(bezier-codemod): use shorthand css variable for transition t…
yangwooseong d406693
feat(beizer-codemod): modify README.md
yangwooseong 2fedd1e
fix(bezier-codemod): typo fix
yangwooseong 2a10dcf
fix(bezier-codemod): add overflow: hidden to rounding transform
yangwooseong d112f31
refactor(bezier-codemod): adopt border-style property so that transfo…
yangwooseong 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 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,6 @@ | ||
--- | ||
"@channel.io/bezier-codemod": minor | ||
--- | ||
|
||
Add transform functions to help to migrate foundation to css variable generated by `@channel.io/bezier-tokens` package. | ||
They cover theme, transition, elevation, rounding, and border of foundation. |
This file contains 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 |
---|---|---|
|
@@ -21,20 +21,31 @@ Update the import syntax for the icon source moved from `@channel.io/bezier-reac | |
For example: | ||
|
||
```tsx | ||
import React from 'react' | ||
import { AllIcon, Button, CheckIcon as CheckIconSource, Icon, type IconName, IconSize } from '@channel.io/bezier-react' | ||
|
||
import Foo from './foo' | ||
import React from "react"; | ||
import { | ||
AllIcon, | ||
Button, | ||
CheckIcon as CheckIconSource, | ||
Icon, | ||
type IconName, | ||
IconSize, | ||
} from "@channel.io/bezier-react"; | ||
|
||
import Foo from "./foo"; | ||
``` | ||
|
||
Transforms into: | ||
|
||
```tsx | ||
import React from 'react' | ||
import { AllIcon, CheckIcon as CheckIconSource, type IconName } from '@channel.io/bezier-icons' | ||
import { Button, Icon, IconSize } from '@channel.io/bezier-react' | ||
|
||
import Foo from './foo' | ||
import React from "react"; | ||
import { | ||
AllIcon, | ||
CheckIcon as CheckIconSource, | ||
type IconName, | ||
} from "@channel.io/bezier-icons"; | ||
import { Button, Icon, IconSize } from "@channel.io/bezier-react"; | ||
|
||
import Foo from "./foo"; | ||
``` | ||
|
||
### Enum Member to String Literal | ||
|
@@ -46,29 +57,74 @@ Replace deprecated enum usage to string literal. | |
For example: | ||
|
||
```tsx | ||
import { ProgressBar, ProgressBarSize, ProgressBarVariant } from '@channel.io/bezier-react' | ||
import { | ||
ProgressBar, | ||
ProgressBarSize, | ||
ProgressBarVariant, | ||
} from "@channel.io/bezier-react"; | ||
|
||
export default () => ( | ||
<ProgressBar | ||
width='100%' | ||
width="100%" | ||
size={ProgressBarSize.M} | ||
variant={ProgressBarVariant.GreenAlt} | ||
value={uploadProgressPercentage / 100} | ||
/> | ||
) | ||
); | ||
``` | ||
|
||
Transforms into: | ||
|
||
```tsx | ||
import { ProgressBar } from '@channel.io/bezier-react' | ||
import { ProgressBar } from "@channel.io/bezier-react"; | ||
|
||
export default () => ( | ||
<ProgressBar | ||
width='100%' | ||
size='m' | ||
variant='green-alt' | ||
width="100%" | ||
size="m" | ||
variant="green-alt" | ||
value={uploadProgressPercentage / 100} | ||
/> | ||
) | ||
); | ||
``` | ||
|
||
### Foundation to CSS Variable | ||
|
||
**`foundation-to-css-variable`** | ||
|
||
Replace foundation to css variable | ||
You can also use individual transform function such as `foundation-to-css-theme`, `foundation-to-css-rounding`, and so on. | ||
|
||
For example: | ||
|
||
```tsx | ||
import { styled } from "@channel.io/bezier-react"; | ||
|
||
const Wrapper = styled.div` | ||
color: ${({ foundation }) => foundation?.theme?.["txt-black-dark"]}; | ||
${({ foundation }) => foundation?.rounding.round12}; | ||
${({ foundation }) => | ||
foundation?.border?.getBorder(0.5, foundation.theme["bdr-black-light"], { | ||
top: false, | ||
right: false, | ||
left: false, | ||
})}; | ||
${({ foundation }) => foundation?.elevation?.ev1()}; | ||
${({ foundation }) => foundation?.transition?.getTransitionsCSS("color")}; | ||
`; | ||
``` | ||
|
||
Transforms into: | ||
|
||
```tsx | ||
import { styled } from "@channel.io/bezier-react"; | ||
|
||
const Wrapper = styled.div` | ||
color: var(--txt-black-dark); | ||
border-radius: var(--radius-12); | ||
border-bottom: 0.5px solid var(--bdr-black-light); | ||
background-color: var(--bg-white-low); | ||
box-shadow: var(--ev-1); | ||
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. 기존 elevation에 background-color도 포함되어있어서, bgColor, shadow 2개 속성을 포함하도록 변환해줘야할 거 같습니다! |
||
transition: color var(--transition-s); | ||
`; | ||
``` |
This file contains 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
83 changes: 83 additions & 0 deletions
83
packages/bezier-codemod/src/transforms/foundation-to-css-variable-border.ts
This file contains 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,83 @@ | ||
/* eslint-disable no-template-curly-in-string */ | ||
import { | ||
type CallExpression, | ||
Node, | ||
type SourceFile, | ||
SyntaxKind, | ||
type ts, | ||
} from 'ts-morph' | ||
|
||
import { getArrowFunctionsWithOneArgument } from '../utils/function.js' | ||
|
||
const getBorderStyle = (borderCallExpression: CallExpression<ts.CallExpression>) => { | ||
const width = borderCallExpression | ||
.getArguments() | ||
.find(Node.isNumericLiteral) | ||
?.getText() | ||
|
||
const color = borderCallExpression | ||
.getArguments() | ||
.find(Node.isElementAccessExpression) | ||
?.getArgumentExpression() | ||
?.getText() | ||
.slice(1, -1) | ||
|
||
if (!color || !width) { return null } | ||
|
||
const borderDirection = borderCallExpression | ||
.getArguments() | ||
.find(Node.isObjectLiteralExpression) | ||
|
||
const hasBorders = ['top', 'right', 'bottom', 'left'] | ||
.map((value) => borderDirection?.getProperty(value)?.getText() !== `${value}: false`) | ||
|
||
let borderStyle = '' | ||
|
||
if (hasBorders.every((v => v))) { | ||
borderStyle = `border: ${width}px solid var(--${color});\n` | ||
} else { | ||
borderStyle += `border-color: var(--${color});\n` | ||
borderStyle += ` border-style: ${hasBorders | ||
.map((hasBorder) => (hasBorder ? 'solid' : 'none')) | ||
.join(' ') | ||
};\n` | ||
borderStyle += ` border-width: ${width}px;\n` | ||
} | ||
|
||
return borderStyle | ||
} | ||
|
||
const hasBorderFoundation = (node: Node) => node.getText().includes('getBorder') | ||
|
||
const replaceBorder = (sourceFile: SourceFile) => { | ||
const oldSourceFileText = sourceFile.getText() | ||
sourceFile.forEachDescendant((node) => { | ||
if (Node.isTemplateExpression(node)) { | ||
const borderCallExpression = node | ||
.getDescendantsOfKind(SyntaxKind.CallExpression) | ||
.find(hasBorderFoundation) | ||
|
||
if (!borderCallExpression) { return } | ||
|
||
const borderArrowFunctions = getArrowFunctionsWithOneArgument( | ||
node, hasBorderFoundation, | ||
) | ||
const borderStyle = getBorderStyle(borderCallExpression) | ||
|
||
if (!borderStyle) { return } | ||
|
||
borderArrowFunctions | ||
.map((v) => v.getText()) | ||
.forEach((text) => { | ||
node.replaceWithText( | ||
node.getText() | ||
.replace(`\${${text}};\n` ?? '', borderStyle) | ||
.replace(`\${${text}}\n` ?? '', borderStyle), | ||
) | ||
}) | ||
} | ||
}) | ||
return sourceFile.getText() !== oldSourceFileText | ||
} | ||
|
||
export default replaceBorder |
58 changes: 58 additions & 0 deletions
58
packages/bezier-codemod/src/transforms/foundation-to-css-variable-elevation.ts
This file contains 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,58 @@ | ||
/* eslint-disable no-template-curly-in-string */ | ||
import { | ||
Node, | ||
type SourceFile, | ||
} from 'ts-morph' | ||
|
||
import { getArrowFunctionsWithOneArgument } from '../utils/function.js' | ||
|
||
const getElevationNum = (text: string) => text.match(/ev(\d+)/)?.[1] | ||
|
||
const bgColorByElevationNum = (ev?: string) => { | ||
switch (ev) { | ||
case '1': | ||
case '2': | ||
return 'bg-white-low' | ||
case '3': | ||
case '4': | ||
case '5': | ||
case '6': | ||
default: | ||
return 'bg-white-high' | ||
} | ||
} | ||
|
||
const getCssVarCode = (arrowFn: string) => { | ||
const ev = getElevationNum(arrowFn) | ||
let css = '' | ||
css += `background-color: var(--${bgColorByElevationNum(ev)});\n` | ||
css += ` box-shadow: var(--ev-${getElevationNum(arrowFn)});` | ||
|
||
return css | ||
} | ||
|
||
const isElevationTheme = (node: Node) => | ||
node.getText().includes('foundation?.elevation') || node.getText().includes('foundation.elevation') | ||
|
||
const replaceElevation = (sourceFile: SourceFile) => { | ||
const oldSourceFileText = sourceFile.getText() | ||
sourceFile.forEachDescendant((node) => { | ||
if (Node.isTemplateExpression(node)) { | ||
const elevationArrowFunctions = getArrowFunctionsWithOneArgument( | ||
node, isElevationTheme, | ||
) | ||
elevationArrowFunctions | ||
.map((v => v.getText())) | ||
.forEach(text => { | ||
node.replaceWithText( | ||
node.getText() | ||
.replace(`\${${text}}`, getCssVarCode(text)) | ||
.replaceAll(';;', ';'), | ||
) | ||
}) | ||
} | ||
}) | ||
return sourceFile.getText() !== oldSourceFileText | ||
} | ||
|
||
export default replaceElevation |
41 changes: 41 additions & 0 deletions
41
packages/bezier-codemod/src/transforms/foundation-to-css-variable-rounding.ts
This file contains 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,41 @@ | ||
/* eslint-disable no-template-curly-in-string */ | ||
import { | ||
Node, | ||
type SourceFile, | ||
} from 'ts-morph' | ||
|
||
import { getArrowFunctionsWithOneArgument } from '../utils/function.js' | ||
|
||
const getRound = (text: string) => text.match(/round(\d+)/)?.[1] | ||
|
||
const isRoundingTheme = (node: Node) => node.getText().includes('foundation?.rounding') | ||
|
||
const getRoundStyle = (text: string) => { | ||
let roundStyle = '' | ||
roundStyle += 'overflow: hidden;\n' | ||
roundStyle += ` border-radius: var(--radius-${getRound(text)});` | ||
return roundStyle | ||
} | ||
|
||
const replaceRound = (sourceFile: SourceFile) => { | ||
const oldSourceFileText = sourceFile.getText() | ||
sourceFile.forEachDescendant((node) => { | ||
if (Node.isTemplateExpression(node)) { | ||
const roundArrowFunctions = getArrowFunctionsWithOneArgument( | ||
node, isRoundingTheme, | ||
) | ||
roundArrowFunctions | ||
.map((v) => v.getText()) | ||
.forEach(text => { | ||
node.replaceWithText( | ||
node.getText() | ||
.replace(`\${${text}}`, getRoundStyle(text)) | ||
.replaceAll(';;', ';'), | ||
) | ||
}) | ||
} | ||
}) | ||
return oldSourceFileText !== sourceFile.getText() | ||
} | ||
|
||
export default replaceRound |
36 changes: 36 additions & 0 deletions
36
packages/bezier-codemod/src/transforms/foundation-to-css-variable-theme.ts
This file contains 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,36 @@ | ||
/* eslint-disable no-template-curly-in-string */ | ||
import { | ||
Node, | ||
type SourceFile, | ||
} from 'ts-morph' | ||
|
||
import { getArrowFunctionsWithOneArgument } from '../utils/function.js' | ||
|
||
const getColor = (text: string) => text.match(/\['([a-z-]+)'\]/)?.[1] ?? '' | ||
|
||
const isFoundationTheme = (node: Node) => node.getText().includes('foundation?.theme') && !node.getText().includes('getBorder') | ||
|
||
const replaceTheme = (sourceFile: SourceFile) => { | ||
const oldSourceFileText = sourceFile.getText() | ||
sourceFile.forEachDescendant((node) => { | ||
if (Node.isTemplateExpression(node)) { | ||
const themeArrowFunctions = getArrowFunctionsWithOneArgument(node, isFoundationTheme) | ||
|
||
themeArrowFunctions | ||
.map(v => v.getText()) | ||
.forEach(text => { | ||
const color = getColor(text) | ||
|
||
if (color) { | ||
node.replaceWithText( | ||
node.getText() | ||
.replace(`\${${text}}`, `var(--${getColor(text)})`), | ||
) | ||
} | ||
}) | ||
} | ||
}) | ||
return sourceFile.getText() !== oldSourceFileText | ||
} | ||
|
||
export default replaceTheme |
Oops, something went wrong.
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.
기존 radius도
overflow:hidden
스타일을 가지고 있어요. 큰 문제는 없을 거 같지만, 안전한 마이그레이션을 위해서 추가해주면 좋을 거 같습니다.