Skip to content

Commit 8dc4e6f

Browse files
committed
css codemod guide
1 parent d6fbec0 commit 8dc4e6f

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

website/docs/guides/css-codemods.mdx

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
---
2+
id: css-codemods
3+
title: CSS codemods via PostCSS
4+
slug: /css-codemods
5+
---
6+
7+
In some cases, it's possible that you may need to write a codemod that applies changes across different programming languages JS, CSS, etc.
8+
It could be because the package you're writing a codemod for has an API that spans across both JS and CSS, for example a Design System or CSS-in-JS library. Where some of your consumers may be using the JS interface and some the CSS interface.
9+
10+
In this scenario, it's possible to repurpose JSCodeshift to handle this by treating JSCodeshift purely as a "Runner", or in otherwords, as the entrypoint to the files you're looking to modify and substitute a transformation library of your choice.
11+
For example [PostCSS](https://postcss.org/), [Babel](https://babeljs.io/), etc.
12+
13+
However, this does come with drawbacks, you will no longer have access to JSCodeshift parsers and transformation API. This guide will explain how to handle these yourself.
14+
15+
As an example, We'll take the JS/CSS use-case and use the popular [PostCSS](https://postcss.org/) library as our substitute transformation library.
16+
17+
## Step 1: Installing dependencies
18+
19+
Get started by creating a new Codeshift package with `npx @codeshift/cli init --package-name css-codemod --preset update-css-api .`.
20+
21+
This will create a new Codeshift package with a configuration file and empty transform file for the preset you specified.
22+
23+
Navigate into your new directory with `cd css-codemod` and install the relevant dependencies: `npm install -s postcss`
24+
25+
## Step 2: Parsing
26+
27+
Now navigate to your transformer file, which should look something like this:
28+
29+
```js
30+
export default function transformer(file, { jscodeshift: j }, options) {
31+
const source = j(file.source);
32+
33+
// Transformation goes here
34+
35+
return source.toSource(options.printOptions);
36+
}
37+
```
38+
39+
You can remove the following lines:
40+
41+
```diff
42+
export default function transformer(
43+
file,
44+
- { jscodeshift: j },
45+
- options
46+
) {
47+
- const source = j(file.source);
48+
49+
// Transformation goes here
50+
51+
- return source.toSource(options.printOptions);
52+
}
53+
```
54+
55+
Now that we've removed JSCodeshift's parsing and output API, we can substitute PostCSS:
56+
57+
```diff
58+
+ import postcss from 'postcss';
59+
60+
export default function transformer(file) {
61+
+ return await postcss([plugin()]).process(file.source).css;
62+
}
63+
```
64+
65+
Here we set up PostCSS with a `plugin()` (more on that later) and pass in the raw file `file.source` for processing.
66+
Once processing is complete we return the raw file back to JSCodeshift for output via `.css`.
67+
68+
## Step 3: Transformation
69+
70+
Now that we've setup parsing we can turn our attention to transformation. The way that can be done in PostCSS is via [their plugin system](https://github.com/postcss/postcss/blob/main/docs/writing-a-plugin.md).
71+
72+
For example purposes, our transformation will simply reverse the names of CSS declarations like so:
73+
74+
```diff
75+
.my-class {
76+
- background: red;
77+
+ dnuorgkcab: red;
78+
}
79+
```
80+
81+
Very useful. Let's create the `plugin()` function that does this now.
82+
83+
To assist with writing PostCSS plugins, you can use [astexplorer.net](https://astexplorer.net/#/2uBU1BLuJ1).
84+
85+
```js
86+
const plugin = (): Plugin => {
87+
const processed = Symbol('processed');
88+
89+
return {
90+
postcssPlugin: 'UsingTokens',
91+
Declaration: decl => {
92+
if (decl[processed]) return;
93+
94+
decl.prop = decl.prop
95+
.split('')
96+
.reverse()
97+
.join('');
98+
99+
decl[processed] = true;
100+
},
101+
};
102+
};
103+
```
104+
105+
## Step 4: Running
106+
107+
You've created your very first CSS codemod, nice work! We can now run it against some code to verify that's it's working correctly.
108+
109+
```
110+
npx @codeshift/cli -t css-codemod/src/update-css-api.ts -e css path/to/src
111+
```

website/sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ module.exports = {
3535
'guides/understanding-asts',
3636
'guides/when-not-to-codemod',
3737
'guides/prompting-for-human-input',
38+
'guides/css-codemods',
3839
],
3940
},
4041
{

0 commit comments

Comments
 (0)