@channel.io/bezier-codemod
Advanced tools
Comparing version 0.5.0-alpha.4 to 0.5.0-alpha.5
@@ -16,7 +16,9 @@ import React, { useCallback, useEffect, useState, } from 'react'; | ||
import importFromBezierToStyledComponents from './transforms/v2-import-from-bezier-to-styled-components/transform.js'; | ||
import inputInterpolationToCssVariable from './transforms/v2-input-interpolation-to-css-variable/transform.js'; | ||
import interpolationToCssVariableInput from './transforms/v2-interpolation-to-css-variable/input.js'; | ||
import interpolationToCssVariableRounding from './transforms/v2-interpolation-to-css-variable/rounding.js'; | ||
import interpolationToCssVariable from './transforms/v2-interpolation-to-css-variable/transform.js'; | ||
import interpolationToCssVariableTypography from './transforms/v2-interpolation-to-css-variable/typography.js'; | ||
import interpolationToCssVariableZIndex from './transforms/v2-interpolation-to-css-variable/zIndex.js'; | ||
import removeAlphaFromAlphaComponents from './transforms/v2-remove-alpha-from-alpha-components/transform.js'; | ||
import textComponentInterface from './transforms/v2-text-component-interface/transform.js'; | ||
import typographyInterpolationToCssVariable from './transforms/v2-typography-interpolation-to-css-variable/transform.js'; | ||
import zIndexInterpolationToCssVariable from './transforms/v2-z-index-interpolation-to-css-variable/transform.js'; | ||
var Step; | ||
@@ -34,2 +36,3 @@ (function (Step) { | ||
Option["EnumMemberToStringLiteral"] = "enum-member-to-string-literal"; | ||
Option["V2FoundationToCssVariable"] = "v2-foundation-to-css-variable"; | ||
Option["V2FoundationToCssVariableTheme"] = "v2-foundation-to-css-variable-theme"; | ||
@@ -41,6 +44,7 @@ Option["V2FoundationToCssVariableBorder"] = "v2-foundation-to-css-variable-border"; | ||
Option["V2FoundationToCssVariableSpacing"] = "v2-foundation-to-css-variable-spacing"; | ||
Option["V2FoundationToCssVariable"] = "v2-foundation-to-css-variable"; | ||
Option["V2InputInterpolationToCssVariable"] = "v2-input-interpolation-to-css-variable"; | ||
Option["V2TypographyInterpolationToCssVariable"] = "v2-typography-interpolation-to-css-variable"; | ||
Option["V2ZIndexInterpolationToCssVariable"] = "v2-z-index-interpolation-to-css-variable"; | ||
Option["V2InterpolationToCssVariable"] = "v2-interpolation-to-css-variable"; | ||
Option["V2InterpolationToCssVariableInput"] = "v2-interpolation-to-css-variable-input"; | ||
Option["V2InterpolationToCssVariableTypography"] = "v2-interpolation-to-css-variable-typography"; | ||
Option["V2InterpolationToCssVariableZIndex"] = "v2-interpolation-to-css-variable-z-index"; | ||
Option["V2InterpolationToCssVariableRounding"] = "v2-interpolation-to-css-variable-rounding"; | ||
Option["V2RemoveAlphaFromAlphaComponents"] = "v2-remove-alpha-from-alpha-components"; | ||
@@ -62,7 +66,9 @@ Option["V2TextComponentInterface"] = "v2-text-component-interface"; | ||
[Option.V2FoundationToCssVariable]: foundationToCssVariable, | ||
[Option.V2InputInterpolationToCssVariable]: inputInterpolationToCssVariable, | ||
[Option.V2TypographyInterpolationToCssVariable]: typographyInterpolationToCssVariable, | ||
[Option.V2InterpolationToCssVariable]: interpolationToCssVariable, | ||
[Option.V2InterpolationToCssVariableInput]: interpolationToCssVariableInput, | ||
[Option.V2InterpolationToCssVariableTypography]: interpolationToCssVariableTypography, | ||
[Option.V2InterpolationToCssVariableRounding]: interpolationToCssVariableRounding, | ||
[Option.V2InterpolationToCssVariableZIndex]: interpolationToCssVariableZIndex, | ||
[Option.V2ImportFromBezierToStyledComponents]: importFromBezierToStyledComponents, | ||
[Option.V2RemoveAlphaFromAlphaComponents]: removeAlphaFromAlphaComponents, | ||
[Option.V2ZIndexInterpolationToCssVariable]: zIndexInterpolationToCssVariable, | ||
[Option.V2TextComponentInterface]: textComponentInterface, | ||
@@ -69,0 +75,0 @@ }; |
import { SyntaxKind, } from 'ts-morph'; | ||
import { renameEnumMember } from '../utils/enum.js'; | ||
import { hasNamedImportInImportDeclaration } from '../utils/import.js'; | ||
import { hasNamedImportInImportDeclaration, removeUnusedNamedImport, } from '../utils/import.js'; | ||
export const transformEnumToStringLiteralInBezier = (sourceFile, enumTransforms) => { | ||
@@ -23,3 +23,3 @@ const transformedEnumNames = []; | ||
if (transformedEnumNames.length > 0) { | ||
sourceFile.fixUnusedIdentifiers(); | ||
removeUnusedNamedImport(sourceFile, ['@channel.io/bezier-react']); | ||
return true; | ||
@@ -26,0 +26,0 @@ } |
@@ -15,3 +15,3 @@ /* eslint-disable no-template-curly-in-string */ | ||
const hasCssImport = hasNamedImport(sourceFile, 'css'); | ||
if (!node.wasForgotten() && node.getText().includes(from)) { | ||
if (!node.wasForgotten() && node.getText().includes(`${from}}`)) { | ||
if (!hasCssImport) { | ||
@@ -18,0 +18,0 @@ if (bezierReactImport) { |
/* eslint-disable no-template-curly-in-string */ | ||
import { Node, SyntaxKind, } from 'ts-morph'; | ||
import { getArrowFunctionsWithOneArgument } from '../../utils/function.js'; | ||
import { removeUnusedNamedImport } from '../../utils/import.js'; | ||
const cssVarByDuration = { | ||
@@ -49,3 +50,3 @@ 'TransitionDuration.S': 'var(--transition-s)', | ||
if (oldSourceFile !== sourceFile.getText()) { | ||
sourceFile.fixUnusedIdentifiers(); | ||
removeUnusedNamedImport(sourceFile, ['@channel.io/bezier-react']); | ||
} | ||
@@ -52,0 +53,0 @@ } |
import { changeAttrProperty, changeComponentProp, } from '../../utils/component.js'; | ||
import { removeUnusedNamedImport } from '../../utils/import.js'; | ||
const STYLED_ATTRS_TRANSFORM_MAP = { | ||
@@ -24,7 +25,9 @@ Text: { | ||
const JSX_PROP_TRANSFORM_MAP = { | ||
Text: { | ||
keyMapper: { | ||
keyMapper: { | ||
Text: { | ||
marginAll: 'margin', | ||
}, | ||
valueMapper: { | ||
}, | ||
valueMapper: { | ||
typo: { | ||
'{Typography.Size11}': '"11"', | ||
@@ -46,6 +49,9 @@ '{Typography.Size12}': '"12"', | ||
const transformTextComponentProps = (sourceFile) => { | ||
const oldSourceFile = sourceFile.getText(); | ||
changeComponentProp(sourceFile, JSX_PROP_TRANSFORM_MAP); | ||
changeAttrProperty(sourceFile, STYLED_ATTRS_TRANSFORM_MAP); | ||
sourceFile.fixUnusedIdentifiers(); | ||
if (oldSourceFile !== sourceFile.getText()) { | ||
removeUnusedNamedImport(sourceFile, ['@channel.io/bezier-react']); | ||
} | ||
}; | ||
export default transformTextComponentProps; |
@@ -7,2 +7,5 @@ import { testTransformFunction } from '../../utils/test.js'; | ||
}); | ||
it('should transform typography enum to string literal and margin properties to be shorthand when component name is not Text', () => { | ||
testTransformFunction(__dirname, 'other-text-component-props', textTransform); | ||
}); | ||
it('should transform properties in attrs object of styled component', () => { | ||
@@ -9,0 +12,0 @@ testTransformFunction(__dirname, 'text-component-attrs', textTransform); |
import { type SourceFile } from 'ts-morph'; | ||
type Component = string; | ||
type Props = string; | ||
type From = string; | ||
type To = string; | ||
export type ComponentTransformMap = Record<Component, { | ||
keyMapper?: Record<From, To>; | ||
valueMapper?: Record<From, To>; | ||
type FromToMap = Record<From, To>; | ||
export type StyledAttrsTransformMap = Record<Component, { | ||
keyMapper?: FromToMap; | ||
valueMapper?: FromToMap; | ||
}>; | ||
export type ComponentTransformMap = { | ||
keyMapper?: Record<Component, FromToMap>; | ||
valueMapper?: Record<Props, FromToMap>; | ||
}; | ||
export declare const changeComponentProp: (sourceFile: SourceFile, componentPropTransformMap: ComponentTransformMap) => void; | ||
export declare const changeAttrProperty: (sourceFile: SourceFile, transformMap: ComponentTransformMap) => void; | ||
export declare const changeAttrProperty: (sourceFile: SourceFile, transformMap: StyledAttrsTransformMap) => void; | ||
export {}; |
import { SyntaxKind, } from 'ts-morph'; | ||
const getName = (node) => node.getTagNameNode().getText(); | ||
export const changeComponentProp = (sourceFile, componentPropTransformMap) => { | ||
const componentNames = new Set(Object.keys(componentPropTransformMap)); | ||
const keyMapper = componentPropTransformMap.keyMapper; | ||
if (!keyMapper) { | ||
return; | ||
} | ||
const componentNames = Object.keys(keyMapper); | ||
[SyntaxKind.JsxSelfClosingElement, SyntaxKind.JsxOpeningElement] | ||
.flatMap((v) => sourceFile.getDescendantsOfKind(v)) | ||
.filter((node) => componentNames.has(getName(node))) | ||
.filter((node) => componentNames.includes(getName(node))) | ||
.forEach((jsxElement) => { | ||
const elementName = getName(jsxElement); | ||
const { keyMapper, valueMapper } = componentPropTransformMap[elementName]; | ||
const mapper = keyMapper[elementName]; | ||
jsxElement | ||
.getDescendantsOfKind(SyntaxKind.JsxAttribute) | ||
.forEach((attribute) => { | ||
if (keyMapper) { | ||
const propKeyFrom = attribute.getFirstChild()?.getText(); | ||
if (propKeyFrom && keyMapper[propKeyFrom]) { | ||
attribute.getFirstChild()?.replaceWithText(keyMapper[propKeyFrom]); | ||
} | ||
const from = attribute.getFirstChild()?.getText(); | ||
if (from && mapper[from]) { | ||
attribute.getFirstChild()?.replaceWithText(mapper[from]); | ||
} | ||
if (valueMapper) { | ||
const propValueFrom = attribute.getLastChild()?.getText(); | ||
if (propValueFrom && valueMapper[propValueFrom]) { | ||
attribute.getLastChild()?.replaceWithText(valueMapper[propValueFrom]); | ||
} | ||
}); | ||
}); | ||
const valueMapper = componentPropTransformMap.valueMapper; | ||
if (!valueMapper) { | ||
return; | ||
} | ||
const propsNames = Object.keys(valueMapper); | ||
[SyntaxKind.JsxSelfClosingElement, SyntaxKind.JsxOpeningElement] | ||
.flatMap((v) => sourceFile.getDescendantsOfKind(v)) | ||
.filter((v) => v.getDescendantsOfKind(SyntaxKind.JsxAttribute).some((attr) => propsNames.includes(attr.getFirstChild()?.getText() ?? ''))) | ||
.forEach((jsxElement) => { | ||
jsxElement | ||
.getDescendantsOfKind(SyntaxKind.JsxAttribute) | ||
.forEach((attribute) => { | ||
const prop = attribute.getFirstChild()?.getText() ?? ''; | ||
const valueFrom = attribute.getLastChild()?.getText(); | ||
const mapper = valueMapper[prop]; | ||
if (valueFrom && mapper?.[valueFrom]) { | ||
attribute.getLastChild()?.replaceWithText(mapper[valueFrom]); | ||
} | ||
@@ -26,0 +42,0 @@ }); |
@@ -8,3 +8,3 @@ import { type SourceFile } from 'ts-morph'; | ||
export declare const removeNamedImport: (sourceFile: SourceFile, namedImport: string) => void | undefined; | ||
export declare const removeUnusedNamedImport: (sourceFile: SourceFile) => void; | ||
export declare const removeUnusedNamedImport: (sourceFile: SourceFile, importDeclarations?: string[]) => void; | ||
export declare const renameNamedImport: (sourceFile: SourceFile, targets: string[], renameFn: (name: string) => string) => void; |
@@ -21,3 +21,4 @@ import { SyntaxKind, } from 'ts-morph'; | ||
export const removeNamedImport = (sourceFile, namedImport) => getNamedImport(sourceFile, namedImport)?.remove(); | ||
export const removeUnusedNamedImport = (sourceFile) => { | ||
export const removeUnusedNamedImport = (sourceFile, importDeclarations) => { | ||
const trimQuoteAtBothEnds = (text) => text.match(/^['"](.*)['"]$/)?.[1]; | ||
sourceFile.getImportDeclarations() | ||
@@ -27,2 +28,12 @@ .flatMap((declaration) => declaration.getNamedImports()) | ||
.forEach((v) => v.remove()); | ||
if (importDeclarations) { | ||
sourceFile | ||
.getImportDeclarations() | ||
.filter((v) => importDeclarations.includes(trimQuoteAtBothEnds(v.getModuleSpecifier().getText()) ?? '')) | ||
.forEach((v) => { | ||
if (!v.getImportClause()) { | ||
v.remove(); | ||
} | ||
}); | ||
} | ||
}; | ||
@@ -29,0 +40,0 @@ export const renameNamedImport = (sourceFile, targets, renameFn) => { |
{ | ||
"name": "@channel.io/bezier-codemod", | ||
"version": "0.5.0-alpha.4", | ||
"version": "0.5.0-alpha.5", | ||
"description": "Codemod transformations to help upgrade app using Bezier design system.", | ||
@@ -5,0 +5,0 @@ "repository": { |
@@ -149,5 +149,5 @@ # Bezier Codemod | ||
**`v2-input-interpolation-to-css-variable`** | ||
**`v2-interpolation-to-css-variable`** | ||
Replace input interpolation to css variable | ||
Replace various interpolation such as `Typography`, `ZIndex`, `InputWrapperStyle`, `Rounding` to css variable | ||
For example: | ||
@@ -158,8 +158,13 @@ | ||
styled, | ||
Typography, | ||
inputWrapperStyle, | ||
focusedInputWrapperStyle, | ||
erroredInputWrapperStyle, | ||
ZIndex, | ||
Rounding, | ||
} from "@channel.io/bezier-react"; | ||
const Wrapper = styled.div` | ||
${Typography.Size11}; | ||
${inputWrapperStyle}; | ||
@@ -172,2 +177,6 @@ | ||
${inputPlaceholderStyle}; | ||
z-index: ${ZIndex.Hide}; | ||
${Rounding.round12}; | ||
`; | ||
@@ -182,2 +191,6 @@ ``` | ||
const Wrapper = styled.div` | ||
/* NOTE: Do not use font-related css variables below separately, use Text component instead */ | ||
font-size: var(--typography-size-11-font-size); | ||
line-height: var(--typography-size-11-line-height); | ||
box-shadow: var(--input-box-shadow); | ||
@@ -196,56 +209,13 @@ | ||
} | ||
`; | ||
``` | ||
**`v2-typography-interpolation-to-css-variable`** | ||
z-index: var(--z-index-hidden); | ||
Replace typography interpolation to css variable | ||
For example: | ||
```tsx | ||
import { styled, Typography } from "@channel.io/bezier-react"; | ||
const Wrapper = styled.div` | ||
${Typography.Size11}; | ||
overflow: hidden; | ||
border-radius: var(--radius-12); | ||
`; | ||
``` | ||
Transforms into: | ||
It also handles when `ZIndex` is used in object. | ||
```tsx | ||
import { styled } from "@channel.io/bezier-react"; | ||
const Wrapper = styled.div` | ||
/* NOTE: Do not use font-related css variables below separately, use Text component instead */ | ||
font-size: var(--typography-size-11-font-size); | ||
line-height: var(--typography-size-11-line-height); | ||
`; | ||
``` | ||
**`v2-z-index-interpolation-to-css-variable`** | ||
Replace z-index interpolation and z-index enum with css variable | ||
For example: | ||
```tsx | ||
import { ZIndex, styled } from "@channel.io/bezier-react"; | ||
const Wrapper = styled.div` | ||
z-index: ${ZIndex.Hide}; | ||
`; | ||
``` | ||
Transforms into: | ||
```tsx | ||
import { styled } from "@channel.io/bezier-react"; | ||
const Wrapper = styled.div` | ||
z-index: var(--z-index-hidden); | ||
`; | ||
``` | ||
Also, | ||
```tsx | ||
import { ZIndex } from "@channel.io/bezier-react"; | ||
@@ -252,0 +222,0 @@ |
85363
1419
403