diff --git a/src/codemods/__testfixtures__/semantic-colors-to-new-theme/color-in-single-quasis.input.tsx b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/color-in-single-quasis.input.tsx new file mode 100644 index 000000000..f2bf096b2 --- /dev/null +++ b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/color-in-single-quasis.input.tsx @@ -0,0 +1,6 @@ +import { Headline, SemanticColors } from '@freenow/wave' +import styled from 'styled-components' + +export const DetailsHeadline = styled(Headline).attrs({ as: 'h3', size: 'm' })` + color: ${SemanticColors.text.secondary}; +` \ No newline at end of file diff --git a/src/codemods/__testfixtures__/semantic-colors-to-new-theme/color-in-single-quasis.output.tsx b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/color-in-single-quasis.output.tsx new file mode 100644 index 000000000..e6bbcdc72 --- /dev/null +++ b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/color-in-single-quasis.output.tsx @@ -0,0 +1,6 @@ +import { Headline, getSemanticValue } from '@freenow/wave' +import styled from 'styled-components' + +export const DetailsHeadline = styled(Headline).attrs({ as: 'h3', size: 'm' })` + color: ${getSemanticValue('foreground-neutral-emphasized')}; +` \ No newline at end of file diff --git a/src/codemods/__testfixtures__/semantic-colors-to-new-theme/no-colors-usage.input.tsx b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/no-colors-usage.input.tsx new file mode 100644 index 000000000..45ea4e98b --- /dev/null +++ b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/no-colors-usage.input.tsx @@ -0,0 +1,20 @@ +import { Box, ChevronUp } from '@freenow/wave'; +import { useEffect } from 'react'; + +export const AlignedChevron = () => { + useEffect( + () => + function cleanUp() { + // when parsing back from AST to source, function declarations after an arrow function + // are wrapped in parenthesis, by expecting the output to not have the parenthesis we + // can test that instead of parsing back we are simply returning the original source + }, + [], + ) + + return ( + + + + ); +} diff --git a/src/codemods/__testfixtures__/semantic-colors-to-new-theme/no-colors-usage.output.tsx b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/no-colors-usage.output.tsx new file mode 100644 index 000000000..45ea4e98b --- /dev/null +++ b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/no-colors-usage.output.tsx @@ -0,0 +1,20 @@ +import { Box, ChevronUp } from '@freenow/wave'; +import { useEffect } from 'react'; + +export const AlignedChevron = () => { + useEffect( + () => + function cleanUp() { + // when parsing back from AST to source, function declarations after an arrow function + // are wrapped in parenthesis, by expecting the output to not have the parenthesis we + // can test that instead of parsing back we are simply returning the original source + }, + [], + ) + + return ( + + + + ); +} diff --git a/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-JSX.input.tsx b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-JSX.input.tsx new file mode 100644 index 000000000..e1f45d449 --- /dev/null +++ b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-JSX.input.tsx @@ -0,0 +1,5 @@ +import { CloseIcon, themeGet } from '@freenow/wave'; + +export const CloseIconWrapper = () => ( + +); diff --git a/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-JSX.output.tsx b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-JSX.output.tsx new file mode 100644 index 000000000..3073eaa33 --- /dev/null +++ b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-JSX.output.tsx @@ -0,0 +1,5 @@ +import { CloseIcon, getSemanticValue } from '@freenow/wave'; + +export const CloseIconWrapper = () => ( + +); diff --git a/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-template-literal.input.tsx b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-template-literal.input.tsx new file mode 100644 index 000000000..35e10625a --- /dev/null +++ b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-template-literal.input.tsx @@ -0,0 +1,6 @@ +import { Text, themeGet } from '@freenow/wave' +import styled from 'styled-components' + +export const TextSizeText = styled(Text)` + color: ${themeGet('semanticColors.text.primary')}; +` \ No newline at end of file diff --git a/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-template-literal.output.tsx b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-template-literal.output.tsx new file mode 100644 index 000000000..6406e353e --- /dev/null +++ b/src/codemods/__testfixtures__/semantic-colors-to-new-theme/theme-get-in-template-literal.output.tsx @@ -0,0 +1,6 @@ +import { Text, getSemanticValue } from '@freenow/wave' +import styled from 'styled-components' + +export const TextSizeText = styled(Text)` + color: ${getSemanticValue('foreground-primary')}; +` \ No newline at end of file diff --git a/src/codemods/__tests__/semantic-colors-to-new-theme-test.ts b/src/codemods/__tests__/semantic-colors-to-new-theme-test.ts index 3db9eef4d..ffb7387b6 100644 --- a/src/codemods/__tests__/semantic-colors-to-new-theme-test.ts +++ b/src/codemods/__tests__/semantic-colors-to-new-theme-test.ts @@ -2,8 +2,11 @@ jest.autoMockOff(); import { defineTest } from 'jscodeshift/dist/testUtils'; const tests = [ - 'color-in-JSX-multi-import' - // no-usage + 'color-in-JSX-multi-import', + 'no-colors-usage', + 'theme-get-in-JSX', + 'theme-get-in-template-literal', + 'color-in-single-quasis' ]; describe('semantic-colors-to-new-theme', () => { diff --git a/src/codemods/semantic-colors-to-new-theme.ts b/src/codemods/semantic-colors-to-new-theme.ts index 4cd4b5d29..5c5e5363b 100644 --- a/src/codemods/semantic-colors-to-new-theme.ts +++ b/src/codemods/semantic-colors-to-new-theme.ts @@ -1,10 +1,12 @@ import { API, ASTPath, + CallExpression, FileInfo, Identifier, ImportDeclaration, JSCodeshift, + Literal, MemberExpression, TemplateLiteral } from 'jscodeshift'; @@ -12,220 +14,219 @@ import { Options } from 'recast'; // TODO actual map const DeprecatedSemanticColorsToSemanticTokensMap = { - 'SemanticColors.text.primary': '', - 'SemanticColors.text.primaryInverted': '', - 'SemanticColors.text.secondary': '', - 'SemanticColors.text.secondaryInverted': '', - 'SemanticColors.text.tertiary': '', - 'SemanticColors.text.tertiaryInverted': '', - 'SemanticColors.text.disabled': '', - 'SemanticColors.text.disabledInverted': '', - 'SemanticColors.text.link': '', - 'SemanticColors.text.linkInverted': '', - 'SemanticColors.text.linkHover': '', - 'SemanticColors.text.linkHoverInverted': '', - 'SemanticColors.text.danger': '', - 'SemanticColors.text.dangerInverted': '', - 'SemanticColors.text.success': '', - 'SemanticColors.text.warning': '', - - 'SemanticColors.background.primary': '', - 'SemanticColors.background.secondary': '', - 'SemanticColors.background.info': '', - 'SemanticColors.background.danger': '', - 'SemanticColors.background.success': '', - 'SemanticColors.background.warning': '', - 'SemanticColors.background.primaryEmphasized': '', - 'SemanticColors.background.secondaryEmphasized': '', - 'SemanticColors.background.infoEmphasized': '', - 'SemanticColors.background.dangerEmphasized': '', - 'SemanticColors.background.successEmphasized': '', - 'SemanticColors.background.warningEmphasized': '', - - 'SemanticColors.icon.primary': '', - 'SemanticColors.icon.primaryInverted': '', - 'SemanticColors.icon.secondary': '', - 'SemanticColors.icon.secondaryInverted': '', - 'SemanticColors.icon.tertiary': '', - 'SemanticColors.icon.tertiaryInverted': '', - 'SemanticColors.icon.disabled': '', - 'SemanticColors.icon.disabledInverted': '', - 'SemanticColors.icon.action': '', - 'SemanticColors.icon.danger': '', - 'SemanticColors.icon.success': '', - 'SemanticColors.icon.warning': '', - - 'SemanticColors.border.primary': '', - 'SemanticColors.border.secondary': '', - 'SemanticColors.border.info': '', - 'SemanticColors.border.danger': '', - 'SemanticColors.border.success': '', - 'SemanticColors.border.warning': '', - 'SemanticColors.border.infoEmphasized': '', - 'SemanticColors.border.dangerEmphasized': '', - 'SemanticColors.border.successEmphasized': '', - 'SemanticColors.border.warningEmphasized': '', - - 'SemanticColors.button.primary.text': 'foreground-on-background-primary', - 'SemanticColors.button.primary.icon': 'foreground-on-background-primary', - 'SemanticColors.button.primary.background': 'background-element-primary-default', - 'SemanticColors.button.primary.border': 'background-element-primary-default', - - 'SemanticColors.button.primary.textHover': 'foreground-on-background-accent', - 'SemanticColors.button.primary.iconHover': 'foreground-on-background-accent', - 'SemanticColors.button.primary.backgroundHover': 'background-element-primary-emphasized', - 'SemanticColors.button.primary.borderHover': 'background-element-primary-emphasized', - - 'SemanticColors.button.primary.textDisabled': 'foreground-on-background-disabled', - 'SemanticColors.button.primary.iconDisabled': 'foreground-on-background-disabled', - 'SemanticColors.button.primary.backgroundDisabled': 'background-element-disabled-default', - 'SemanticColors.button.primary.borderDisabled': 'background-element-disabled-default', - - 'SemanticColors.button.primary.textInverted': '', // foreground-on-background-primary - 'SemanticColors.button.primary.iconInverted': '', // foreground-on-background-primary - 'SemanticColors.button.primary.backgroundInverted': '', // background-element-primary-default - 'SemanticColors.button.primary.borderInverted': '', // background-element-primary-default - - 'SemanticColors.button.primary.textHoverInverted': '', // foreground-on-background-accent - 'SemanticColors.button.primary.iconHoverInverted': '', // foreground-on-background-accent - 'SemanticColors.button.primary.backgroundHoverInverted': '', // background-element-primary-emphasized - 'SemanticColors.button.primary.borderHoverInverted': '', // background-element-primary-emphasized - - 'SemanticColors.button.primary.textDisabledInverted': '', // foreground-on-background-disabled - 'SemanticColors.button.primary.iconDisabledInverted': '', // foreground-on-background-disabled - 'SemanticColors.button.primary.backgroundDisabledInverted': '', // background-element-disabled-default - 'SemanticColors.button.primary.borderDisabledInverted': '', // background-element-disabled-default - - 'SemanticColors.button.secondary.text': '', - 'SemanticColors.button.secondary.icon': '', - 'SemanticColors.button.secondary.background': '', - 'SemanticColors.button.secondary.border': '', - - 'SemanticColors.button.secondary.textHover': '', - 'SemanticColors.button.secondary.iconHover': '', - 'SemanticColors.button.secondary.backgroundHover': '', - 'SemanticColors.button.secondary.borderHover': '', - - 'SemanticColors.button.secondary.textDisabled': '', - 'SemanticColors.button.secondary.iconDisabled': '', - 'SemanticColors.button.secondary.backgroundDisabled': '', - 'SemanticColors.button.secondary.borderDisabled': '', - - 'SemanticColors.button.secondary.textInverted': '', - 'SemanticColors.button.secondary.iconInverted': '', - 'SemanticColors.button.secondary.backgroundInverted': '', - 'SemanticColors.button.secondary.borderInverted': '', - - 'SemanticColors.button.secondary.textHoverInverted': '', - 'SemanticColors.button.secondary.iconHoverInverted': '', - 'SemanticColors.button.secondary.backgroundHoverInverted': '', - 'SemanticColors.button.secondary.borderHoverInverted': '', - - 'SemanticColors.button.secondary.textDisabledInverted': '', - 'SemanticColors.button.secondary.iconDisabledInverted': '', - 'SemanticColors.button.secondary.backgroundDisabledInverted': '', - 'SemanticColors.button.secondary.borderDisabledInverted': '', - - 'SemanticColors.button.danger.text': '', - 'SemanticColors.button.danger.icon': '', - 'SemanticColors.button.danger.background': '', - 'SemanticColors.button.danger.border': '', - - 'SemanticColors.button.danger.textHover': '', - 'SemanticColors.button.danger.iconHover': '', - 'SemanticColors.button.danger.backgroundHover': '', - 'SemanticColors.button.danger.borderHover': '', - - 'SemanticColors.button.danger.textDisabled': '', - 'SemanticColors.button.danger.iconDisabled': '', - 'SemanticColors.button.danger.backgroundDisabled': '', - 'SemanticColors.button.danger.borderDisabled': '', - - 'SemanticColors.button.danger.textInverted': '', - 'SemanticColors.button.danger.iconInverted': '', - 'SemanticColors.button.danger.backgroundInverted': '', - 'SemanticColors.button.danger.borderInverted': '', - - 'SemanticColors.button.danger.textHoverInverted': '', - 'SemanticColors.button.danger.iconHoverInverted': '', - 'SemanticColors.button.danger.backgroundHoverInverted': '', - 'SemanticColors.button.danger.borderHoverInverted': '', - - 'SemanticColors.button.danger.textDisabledInverted': '', - 'SemanticColors.button.danger.iconDisabledInverted': '', - 'SemanticColors.button.danger.backgroundDisabledInverted': '', - 'SemanticColors.button.danger.borderDisabledInverted': '', - - 'SemanticColors.textButton.primary.text': '', - 'SemanticColors.textButton.primary.icon': '', - 'SemanticColors.textButton.primary.textHover': '', - 'SemanticColors.textButton.primary.iconHover': '', - 'SemanticColors.textButton.primary.textDisabled': '', - 'SemanticColors.textButton.primary.iconDisabled': '', - - 'SemanticColors.textButton.primary.textInverted': '', - 'SemanticColors.textButton.primary.iconInverted': '', - 'SemanticColors.textButton.primary.textHoverInverted': '', - 'SemanticColors.textButton.primary.iconHoverInverted': '', - 'SemanticColors.textButton.primary.textDisabledInverted': '', - 'SemanticColors.textButton.primary.iconDisabledInverted': '', - - 'SemanticColors.textButton.danger.textInverted': '', - 'SemanticColors.textButton.danger.iconInverted': '', - 'SemanticColors.textButton.danger.textHoverInverted': '', - 'SemanticColors.textButton.danger.iconHoverInverted': '', - 'SemanticColors.textButton.danger.textDisabledInverted': '', - 'SemanticColors.textButton.danger.iconDisabledInverted': '', - - 'SemanticColors.forms.toggle.default.slideOff': '', - 'SemanticColors.forms.toggle.default.slideOn': '', - 'SemanticColors.forms.toggle.default.frameOff': '', - 'SemanticColors.forms.toggle.default.frameOn': '', - - 'SemanticColors.forms.toggle.error.slideOff': '', - 'SemanticColors.forms.toggle.error.slideOn': '', - 'SemanticColors.forms.toggle.error.frameOff': '', - 'SemanticColors.forms.toggle.error.frameOn': '', - - 'SemanticColors.forms.toggle.disabled.slideOff': '', - 'SemanticColors.forms.toggle.disabled.slideOn': '', - 'SemanticColors.forms.toggle.disabled.frameOff': '', - 'SemanticColors.forms.toggle.disabled.frameOn': '', - - 'SemanticColors.forms.datePicker.calendar.border': '', - 'SemanticColors.forms.datePicker.calendar.borderHover': '', - 'SemanticColors.forms.datePicker.calendar.borderRange': '', - 'SemanticColors.forms.datePicker.calendar.borderSelected': '', - 'SemanticColors.forms.datePicker.calendar.borderRangeHover': '', - 'SemanticColors.forms.datePicker.calendar.background': '', - 'SemanticColors.forms.datePicker.calendar.backgroundHover': '', - 'SemanticColors.forms.datePicker.calendar.backgroundRange': '', - 'SemanticColors.forms.datePicker.calendar.backgroundSelected': '', - 'SemanticColors.forms.datePicker.calendar.backgroundRangeHover': '', - - 'SemanticColors.table.skeleton': '', - 'SemanticColors.table.zebraStyles.backgroundSecondary': '', - 'SemanticColors.table.zebraStyles.backgroundHover': '', - 'SemanticColors.table.zebraStyles.backgroundActive': '', - 'SemanticColors.table.linesStyles.backgroundHover': '', - 'SemanticColors.table.linesStyles.backgroundActive': '', - 'SemanticColors.table.linesStyles.border': '', - 'SemanticColors.table.blank.backgroundHover': '', - 'SemanticColors.table.blank.backgroundActive': '', - 'SemanticColors.table.header.border': '', - - 'SemanticColors.dialog.dimming': '' + 'text.primary': 'foreground-primary', + 'text.primaryInverted': '', // foreground-primary + 'text.secondary': 'foreground-neutral-emphasized', + 'text.secondaryInverted': '', // foreground-neutral-emphasized + 'text.tertiary': '', // TODO where is it?? + 'text.tertiaryInverted': '', + 'text.disabled': 'foreground-disabled', + 'text.disabledInverted': '', // foreground-disabled is Colors.blue.primary[350], before was Colors.blue.primary[550] + 'text.link': '', + 'text.linkInverted': '', + 'text.linkHover': '', + 'text.linkHoverInverted': '', + 'text.danger': '', + 'text.dangerInverted': '', + 'text.success': '', + 'text.warning': '', + + 'background.primary': 'TODO', + 'background.secondary': '', + 'background.info': '', + 'background.danger': '', + 'background.success': '', + 'background.warning': '', + 'background.primaryEmphasized': '', + 'background.secondaryEmphasized': '', + 'background.infoEmphasized': 'TODO', + 'background.dangerEmphasized': '', + 'background.successEmphasized': '', + 'background.warningEmphasized': '', + + 'icon.primary': '', + 'icon.primaryInverted': '', + 'icon.secondary': '', + 'icon.secondaryInverted': '', + 'icon.tertiary': '', + 'icon.tertiaryInverted': '', + 'icon.disabled': '', + 'icon.disabledInverted': '', + 'icon.action': '', + 'icon.danger': '', + 'icon.success': '', + 'icon.warning': '', + + 'border.primary': '', + 'border.secondary': '', + 'border.info': '', + 'border.danger': '', + 'border.success': '', + 'border.warning': '', + 'border.infoEmphasized': '', + 'border.dangerEmphasized': '', + 'border.successEmphasized': '', + 'border.warningEmphasized': '', + + 'button.primary.text': 'foreground-on-background-primary', + 'button.primary.icon': 'foreground-on-background-primary', + 'button.primary.background': 'background-element-primary-default', + 'button.primary.border': 'background-element-primary-default', + + 'button.primary.textHover': 'foreground-on-background-accent', + 'button.primary.iconHover': 'foreground-on-background-accent', + 'button.primary.backgroundHover': 'background-element-primary-emphasized', + 'button.primary.borderHover': 'background-element-primary-emphasized', + + 'button.primary.textDisabled': 'foreground-on-background-disabled', + 'button.primary.iconDisabled': 'foreground-on-background-disabled', + 'button.primary.backgroundDisabled': 'background-element-disabled-default', + 'button.primary.borderDisabled': 'background-element-disabled-default', + + 'button.primary.textInverted': '', // foreground-on-background-primary + 'button.primary.iconInverted': '', // foreground-on-background-primary + 'button.primary.backgroundInverted': '', // background-element-primary-default + 'button.primary.borderInverted': '', // background-element-primary-default + + 'button.primary.textHoverInverted': '', // foreground-on-background-accent + 'button.primary.iconHoverInverted': '', // foreground-on-background-accent + 'button.primary.backgroundHoverInverted': '', // background-element-primary-emphasized + 'button.primary.borderHoverInverted': '', // background-element-primary-emphasized + + 'button.primary.textDisabledInverted': '', // foreground-on-background-disabled + 'button.primary.iconDisabledInverted': '', // foreground-on-background-disabled + 'button.primary.backgroundDisabledInverted': '', // background-element-disabled-default + 'button.primary.borderDisabledInverted': '', // background-element-disabled-default + + 'button.secondary.text': '', + 'button.secondary.icon': '', + 'button.secondary.background': '', + 'button.secondary.border': '', + + 'button.secondary.textHover': '', + 'button.secondary.iconHover': '', + 'button.secondary.backgroundHover': '', + 'button.secondary.borderHover': '', + + 'button.secondary.textDisabled': '', + 'button.secondary.iconDisabled': '', + 'button.secondary.backgroundDisabled': '', + 'button.secondary.borderDisabled': '', + + 'button.secondary.textInverted': '', + 'button.secondary.iconInverted': '', + 'button.secondary.backgroundInverted': '', + 'button.secondary.borderInverted': '', + + 'button.secondary.textHoverInverted': '', + 'button.secondary.iconHoverInverted': '', + 'button.secondary.backgroundHoverInverted': '', + 'button.secondary.borderHoverInverted': '', + + 'button.secondary.textDisabledInverted': '', + 'button.secondary.iconDisabledInverted': '', + 'button.secondary.backgroundDisabledInverted': '', + 'button.secondary.borderDisabledInverted': '', + + 'button.danger.text': '', + 'button.danger.icon': '', + 'button.danger.background': '', + 'button.danger.border': '', + + 'button.danger.textHover': '', + 'button.danger.iconHover': '', + 'button.danger.backgroundHover': '', + 'button.danger.borderHover': '', + + 'button.danger.textDisabled': '', + 'button.danger.iconDisabled': '', + 'button.danger.backgroundDisabled': '', + 'button.danger.borderDisabled': '', + + 'button.danger.textInverted': '', + 'button.danger.iconInverted': '', + 'button.danger.backgroundInverted': '', + 'button.danger.borderInverted': '', + + 'button.danger.textHoverInverted': '', + 'button.danger.iconHoverInverted': '', + 'button.danger.backgroundHoverInverted': '', + 'button.danger.borderHoverInverted': '', + + 'button.danger.textDisabledInverted': '', + 'button.danger.iconDisabledInverted': '', + 'button.danger.backgroundDisabledInverted': '', + 'button.danger.borderDisabledInverted': '', + + 'textButton.primary.text': '', + 'textButton.primary.icon': '', + 'textButton.primary.textHover': '', + 'textButton.primary.iconHover': '', + 'textButton.primary.textDisabled': '', + 'textButton.primary.iconDisabled': '', + + 'textButton.primary.textInverted': '', + 'textButton.primary.iconInverted': '', + 'textButton.primary.textHoverInverted': '', + 'textButton.primary.iconHoverInverted': '', + 'textButton.primary.textDisabledInverted': '', + 'textButton.primary.iconDisabledInverted': '', + + 'textButton.danger.textInverted': '', + 'textButton.danger.iconInverted': '', + 'textButton.danger.textHoverInverted': '', + 'textButton.danger.iconHoverInverted': '', + 'textButton.danger.textDisabledInverted': '', + 'textButton.danger.iconDisabledInverted': '', + + 'forms.toggle.default.slideOff': '', + 'forms.toggle.default.slideOn': '', + 'forms.toggle.default.frameOff': '', + 'forms.toggle.default.frameOn': '', + + 'forms.toggle.error.slideOff': '', + 'forms.toggle.error.slideOn': '', + 'forms.toggle.error.frameOff': '', + 'forms.toggle.error.frameOn': '', + + 'forms.toggle.disabled.slideOff': '', + 'forms.toggle.disabled.slideOn': '', + 'forms.toggle.disabled.frameOff': '', + 'forms.toggle.disabled.frameOn': '', + + 'forms.datePicker.calendar.border': '', + 'forms.datePicker.calendar.borderHover': '', + 'forms.datePicker.calendar.borderRange': '', + 'forms.datePicker.calendar.borderSelected': '', + 'forms.datePicker.calendar.borderRangeHover': '', + 'forms.datePicker.calendar.background': '', + 'forms.datePicker.calendar.backgroundHover': '', + 'forms.datePicker.calendar.backgroundRange': '', + 'forms.datePicker.calendar.backgroundSelected': '', + 'forms.datePicker.calendar.backgroundRangeHover': '', + + 'table.skeleton': '', + 'table.zebraStyles.backgroundSecondary': '', + 'table.zebraStyles.backgroundHover': '', + 'table.zebraStyles.backgroundActive': '', + 'table.linesStyles.backgroundHover': '', + 'table.linesStyles.backgroundActive': '', + 'table.linesStyles.border': '', + 'table.blank.backgroundHover': '', + 'table.blank.backgroundActive': '', + 'table.header.border': '', + + 'dialog.dimming': '' }; /** * Possible usages - * - As `CallExpression`? -> themeGet('semanticColors.border.primary') (inside template literal) - * - As `CallExpression`? -> themeGet('semanticColors.border.primary') (regular) - * - As constant -> SemanticColors.button.primary.backgroundDisabled (inside template literal) + * [DONE] As `CallExpression`? -> themeGet('border.primary') (regular) + * [DONE] As `CallExpression`? -> themeGet('border.primary') (inside template literal) * [DONE] As constant -> SemanticColors.button.primary.backgroundDisabled (regular) + * - As constant -> SemanticColors.button.primary.backgroundDisabled (inside template literal) */ -const CSS_VARS_COLORS_REPLACEMENT_TYPE = `ReadCssColorVariable`; const SEMANTIC_VALUE_GETTER_NAME = 'getSemanticValue'; const replaceColorsForCssVarsInTemplateLiterals = ( @@ -293,12 +294,12 @@ const replaceColorsForCssVarsInTemplateLiterals = ( const isMemberExpression = (path: any): path is ASTPath => path.value?.type === 'MemberExpression'; -const buildFullAccessedPropertiesPath = (initialPath: string, ex: ASTPath): string => { +const buildFullAccessedPropertiesPath = (ex: ASTPath, initialPath?: string): string => { const propertyName = (ex.node.property as Identifier).name; - const builtPath = `${initialPath}.${propertyName}`; + const builtPath = initialPath ? `${initialPath}.${propertyName}` : propertyName; // Recursively add more properties if the parent has more - if (isMemberExpression(ex.parentPath)) return buildFullAccessedPropertiesPath(builtPath, ex.parentPath); + if (isMemberExpression(ex.parentPath)) return buildFullAccessedPropertiesPath(ex.parentPath, builtPath); else return builtPath; }; @@ -307,12 +308,17 @@ const getHighesLevelMemberExpression = (ex: ASTPath): ASTPath< return ex; }; +const buildGetSemanticValueCall = (j: JSCodeshift, semanticToken: string): CallExpression => { + return j.callExpression(j.identifier('getSemanticValue'), [j.literal(semanticToken)]); +}; + export default (file: FileInfo, api: API, options: Options) => { const j = api.jscodeshift; const ast = j(file.source); const printOptions = options ?? { quote: 'single' }; const localColorNames: string[] = []; + const localThemeGetNames: string[] = []; // Find @freenow/wave imports const waveImports = ast.find(j.ImportDeclaration, { @@ -323,17 +329,25 @@ export default (file: FileInfo, api: API, options: Options) => { const waveNamedImports = waveImports.find(j.ImportSpecifier); - // Find SemanticColors named imports in @freenow/wave imports + // Find SemanticColors named imports in wave imports const colorsImports = waveNamedImports.filter(path => path.node.imported.name === 'SemanticColors'); + // Find themeGet named imports in wave imports + const themeGetImports = waveNamedImports.filter(path => path.node.imported.name === 'themeGet'); + // Early return in case no SemanticColors are imported - if (colorsImports.length === 0) return file.source; + if (colorsImports.length === 0 && themeGetImports.length === 0) return file.source; // Get the local SemanticColors import names colorsImports.forEach(spec => { if (spec.node.local?.name) localColorNames.push(spec.node.local.name); }); + // Get the local themeGet import names + themeGetImports.forEach(spec => { + if (spec.node.local?.name) localThemeGetNames.push(spec.node.local.name); + }); + // // Iterate over template strings // ast.find(j.TaggedTemplateExpression).forEach(el => { // // Get template literals in template expression @@ -341,6 +355,30 @@ export default (file: FileInfo, api: API, options: Options) => { // replaceColorsForCssVarsInTemplateLiterals(j, localColorNames, templateLiteral); // }); + // Find all themeGet CallExpressions (e.g. themeGet('text.primary')) + const themeGetExpressions = ast.find(j.CallExpression, { + callee: { + name: (colorName: string) => localThemeGetNames.includes(colorName) + } + }); + + themeGetExpressions.forEach(ex => { + // Get first argument of the call (i.e. the semantic color) + const firstArgument = ex.node.arguments[0] as Literal; + + // Remove the `semanticColors.` part of the string to later map to the token, 15 is the number of chars it has + const semanticColor = (firstArgument.value as string).substring(15); + + // Map the Color to a semantic token + const semanticToken = DeprecatedSemanticColorsToSemanticTokensMap[semanticColor]; + + if (!semanticToken) return; + + // Replace the themeGet usage for a getSemanticValue call with the new token (e.g. getSemanticValue('background-element-disabled-default')) + const getSemanticValueCall = buildGetSemanticValueCall(j, semanticToken); + ex.replace(getSemanticValueCall); + }); + // Find all remaining SemanticColors member usage (e.g. SemanticColors.x) const semanticColorsExpressions = ast.find(j.MemberExpression, { object: { @@ -349,11 +387,8 @@ export default (file: FileInfo, api: API, options: Options) => { }); semanticColorsExpressions.forEach(ex => { - // Get initial object name (e.g. SemanticColors) - const initialIdentifier = (ex.node.object as Identifier).name; - // Build full semantic color path (e.g. SemanticColors.button.primary.backgroundDisabled) - const semanticColorPath = buildFullAccessedPropertiesPath(initialIdentifier, ex); + const semanticColorPath = buildFullAccessedPropertiesPath(ex); // Map the Color to a semantic token const semanticToken = DeprecatedSemanticColorsToSemanticTokensMap[semanticColorPath]; @@ -363,9 +398,9 @@ export default (file: FileInfo, api: API, options: Options) => { // Find highest level MemberExpression (i.e. the one that contains the whole color path) const highestExpression = getHighesLevelMemberExpression(ex); - // Replace the SemanticColors usage for a call to getSemanticValue with the token (e.g. getSemanticValue('background-element-disabled-default')) - const semanticValueGetterNode = j.callExpression(j.identifier('getSemanticValue'), [j.literal(semanticToken)]); - highestExpression.replace(semanticValueGetterNode); + // Replace the SemanticColors usage for a getSemanticValue call with the new token (e.g. getSemanticValue('background-element-disabled-default')) + const getSemanticValueCall = buildGetSemanticValueCall(j, semanticToken); + highestExpression.replace(getSemanticValueCall); }); // Add an import for `getSemanticValue` @@ -375,6 +410,9 @@ export default (file: FileInfo, api: API, options: Options) => { // Remove the SemanticColors import colorsImports.remove(); + // Remove the themeGet import + themeGetImports.remove(); + // If SemanticColors is the only named import from wave, remove the whole Wave import if (waveImports.size() === 1 && waveNamedImports.size() === 1) { waveImports.remove();