Bartosz Szewczyk
>5 @ Codete
2021
Me after half-marathon
Game I made in my free time
Rewriting code can be hard
Not covered
String that specifies a search pattern
/(import {[\s\S]*)(themeGet,)([\s\S]*} from 'styled-system';)/g
(import {[\s\S]*)
(themeGet,?)
([\s\S]*} from 'styled-system';)
Your code editor/IDE
Perl interpreter 🤓
MATCH="\
(import {[\s\S]*)\
(themeGet,?)\
([\s\S]*} from 'styled-system';)\
"
REPLACE="\
\1\3
import { themeGet } from '\@styled-system/theme-get'\;
"
perl -i -0pe "s|$MATCH|$REPLACE|gm" src/**/*.js
Just use any scripting language
const fs = require('fs')
const glob = require('glob')
const regexp = /.../g
const replace = '...'
glob('src/**/*.{ts,tsx}', (err, files) => {
files.forEach(filename => {
const contents =
fs.readFileSync(filename, { encoding: 'utf-8' })
if (contents.indexOf('themeGet') !== -1) {
fs.writeFileSync(
filename,
contents.replace(regexp, replace)
)
}
})
})
🧙♀️ regexp magic 🧙
Comby is a tool for searching and rewriting code
:[var]
:[var~regex]
:[~regex]
themeGet
importCOMBY_M="$(cat <<"MATCH"
import {
:[before]themeGet:[~,?]:[after]
} from 'styled-system'
MATCH
)"
COMBY_R="$(cat <<"REWRITE"
import {:[before]:[after]} from 'styled-system'
import { themeGet } from '@styled-system/theme-get'
REWRITE
)"
comby "$COMBY_M" "$COMBY_R" .js -i -d src
Code that rewrites code
Code that operate on code
Code that operate on code AST
light mode warning ⚠️
export const transform = (fileInfo, api) => {
const { jscodeshift: j } = api;
return j(fileInfo.source)
.find(/* styled-system import with themeGet */)
.replaceWith(/* import without themeGet */)
.insertAfter(/* @styled-system/theme-get import */)
.toSource();
};
const transform: Transform = (fileInfo, api) => {
const { jscodeshift: j } = api;
const isThemeGet = (specifier) =>
specifier.type === 'ImportSpecifier' &&
specifier.imported.name === 'themeGet';
return j(fileInfo.source)
.find(j.ImportDeclaration, {
source: { value: 'styled-system' },
specifiers: (specifiers) =>
specifiers?.some(isThemeGet) ?? false,
})
.replaceWith(({ node }) => {
const specifiersWithoutThemeGet =
node.specifiers?.filter(
(specifier) =>
!isThemeGet(specifier)
) ?? [];
return specifiersWithoutThemeGet.length > 0
? j.importDeclaration(
specifiersWithoutThemeGet,
node.source,
node.importKind
)
: null;
})
.insertAfter(
j.template
.statement`
import {
theme-get
} from '@styled-system/theme-get'
`
)
.toSource();
};
cli
jscodeshift -t theme-get.ts src/**/*.js
Code can be easily unit tested
defineInlineTest(
transform,
{},
`
import { a, themeGet, b } from 'styled-system';
`,
`
import { a, b } from 'styled-system';
import { themeGet } from '@styled-system/theme-get';
`
)
Is there the best option?
Bartosz Szewczyk
👨🏼💻 Tech Lead @ Codete
@sztobar