├── .gitignore
├── README.md
├── index.js
├── package-lock.json
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .vscode
3 | yarn.lock
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Babel plugin twin
2 |
3 |
4 |
5 |
6 |
7 | This plugin automatically adds the tw prop from [twin.macro](https://github.com/ben-rogerson/twin.macro) - no import required:
8 |
9 | ```diff
10 | - import "twin.macro"
11 |
12 | const Component = () =>
13 | ```
14 |
15 | You’ll also get the css prop from your css-in-js library:
16 |
17 | ```diff
18 | const Component = () =>
19 | ```
20 |
21 | ## Installation
22 |
23 | ```shell
24 | npm i -D babel-plugin-twin
25 | # or
26 | yarn add babel-plugin-twin -D
27 | ```
28 |
29 | Then add the plugin to your babel config:
30 |
31 | ```js
32 | module.exports = {
33 | plugins: [
34 | "babel-plugin-twin",
35 | "babel-plugin-macros",
36 | // ...
37 | ],
38 | };
39 | ```
40 |
41 | Note: You must add `"babel-plugin-twin"` before `"babel-plugin-macros"` in the plugins array.
42 |
43 | ## Options
44 |
45 | Add debug to your config to see some feedback:
46 |
47 | ```js
48 | module.exports = {
49 | plugins: [
50 | ["babel-plugin-twin", { debug: true }],
51 | "babel-plugin-macros",
52 | // ...
53 | ],
54 | };
55 | ```
56 |
57 | To avoid checking files or folders, supply `exclude` with an array of regex patterns:
58 |
59 | ```js
60 | module.exports = {
61 | plugins: [
62 | ["babel-plugin-twin", {
63 | "exclude": [
64 | "temp/",
65 | "..."
66 | ]
67 | },
68 | "babel-plugin-macros",
69 | // ...
70 | ],
71 | };
72 | ```
73 |
74 | ## Special thanks
75 |
76 | A big shoutout goes to [@euvs](https://github.com/euvs) for the plugin concept + code and [@mxsbr](https://github.com/mxstbr) for planting [the idea](https://github.com/ben-rogerson/twin.macro/issues/247).
77 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const template = require("@babel/template").default;
2 |
3 | const buildImport = template(`
4 | import 'twin.macro';
5 | `);
6 |
7 | function importTwinMacroPlugin(babel) {
8 | const importDeclaration = buildImport();
9 |
10 | return {
11 | visitor: {
12 | Program: (path, state) => {
13 | let shouldAddImport = true;
14 | const hasDebug = state.opts.debug === true;
15 | const matchedExclude = (state.opts.exclude ?? []).find((regex) =>
16 | RegExp(regex).test(state.file.opts.filename)
17 | );
18 |
19 | if (matchedExclude) {
20 | shouldAddImport = false;
21 | hasDebug &&
22 | console.log(
23 | `babel-plugin-twin: Matched exclude pattern “${matchedExclude}” on “${state.file.opts.filename}”`
24 | );
25 | } else {
26 | state.file.path.traverse({
27 | ImportDeclaration(path) {
28 | // Find the twin import path
29 | if (path.node.source.value !== "twin.macro") return;
30 | shouldAddImport = false;
31 | },
32 | });
33 | }
34 |
35 | if (!shouldAddImport) {
36 | hasDebug &&
37 | console.log(
38 | `babel-plugin-twin: Skipped injection in “${state.file.opts.filename}”`
39 | );
40 | return;
41 | }
42 |
43 | hasDebug &&
44 | console.log(
45 | `babel-plugin-twin: Injected import in “${state.file.opts.filename}”`
46 | );
47 |
48 | path.unshiftContainer("body", importDeclaration);
49 | },
50 | },
51 | };
52 | }
53 |
54 | module.exports = importTwinMacroPlugin;
55 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "babel-plugin-twin",
3 | "version": "1.1.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "babel-plugin-twin",
9 | "version": "1.1.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "@babel/template": "^7.12.13"
13 | }
14 | },
15 | "node_modules/@babel/code-frame": {
16 | "version": "7.12.13",
17 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
18 | "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
19 | "dependencies": {
20 | "@babel/highlight": "^7.12.13"
21 | }
22 | },
23 | "node_modules/@babel/helper-validator-identifier": {
24 | "version": "7.12.11",
25 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
26 | "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw=="
27 | },
28 | "node_modules/@babel/highlight": {
29 | "version": "7.12.13",
30 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
31 | "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
32 | "dependencies": {
33 | "@babel/helper-validator-identifier": "^7.12.11",
34 | "chalk": "^2.0.0",
35 | "js-tokens": "^4.0.0"
36 | }
37 | },
38 | "node_modules/@babel/parser": {
39 | "version": "7.12.17",
40 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.17.tgz",
41 | "integrity": "sha512-r1yKkiUTYMQ8LiEI0UcQx5ETw5dpTLn9wijn9hk6KkTtOK95FndDN10M+8/s6k/Ymlbivw0Av9q4SlgF80PtHg==",
42 | "bin": {
43 | "parser": "bin/babel-parser.js"
44 | },
45 | "engines": {
46 | "node": ">=6.0.0"
47 | }
48 | },
49 | "node_modules/@babel/template": {
50 | "version": "7.12.13",
51 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz",
52 | "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==",
53 | "dependencies": {
54 | "@babel/code-frame": "^7.12.13",
55 | "@babel/parser": "^7.12.13",
56 | "@babel/types": "^7.12.13"
57 | }
58 | },
59 | "node_modules/@babel/types": {
60 | "version": "7.12.17",
61 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.17.tgz",
62 | "integrity": "sha512-tNMDjcv/4DIcHxErTgwB9q2ZcYyN0sUfgGKUK/mm1FJK7Wz+KstoEekxrl/tBiNDgLK1HGi+sppj1An/1DR4fQ==",
63 | "dependencies": {
64 | "@babel/helper-validator-identifier": "^7.12.11",
65 | "lodash": "^4.17.19",
66 | "to-fast-properties": "^2.0.0"
67 | }
68 | },
69 | "node_modules/ansi-styles": {
70 | "version": "3.2.1",
71 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
72 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
73 | "dependencies": {
74 | "color-convert": "^1.9.0"
75 | },
76 | "engines": {
77 | "node": ">=4"
78 | }
79 | },
80 | "node_modules/chalk": {
81 | "version": "2.4.2",
82 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
83 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
84 | "dependencies": {
85 | "ansi-styles": "^3.2.1",
86 | "escape-string-regexp": "^1.0.5",
87 | "supports-color": "^5.3.0"
88 | },
89 | "engines": {
90 | "node": ">=4"
91 | }
92 | },
93 | "node_modules/chalk/node_modules/escape-string-regexp": {
94 | "version": "1.0.5",
95 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
96 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
97 | "engines": {
98 | "node": ">=0.8.0"
99 | }
100 | },
101 | "node_modules/color-convert": {
102 | "version": "1.9.3",
103 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
104 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
105 | "dependencies": {
106 | "color-name": "1.1.3"
107 | }
108 | },
109 | "node_modules/color-name": {
110 | "version": "1.1.3",
111 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
112 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
113 | },
114 | "node_modules/has-flag": {
115 | "version": "3.0.0",
116 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
117 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
118 | "engines": {
119 | "node": ">=4"
120 | }
121 | },
122 | "node_modules/js-tokens": {
123 | "version": "4.0.0",
124 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
125 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
126 | },
127 | "node_modules/lodash": {
128 | "version": "4.17.20",
129 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
130 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
131 | },
132 | "node_modules/supports-color": {
133 | "version": "5.5.0",
134 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
135 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
136 | "dependencies": {
137 | "has-flag": "^3.0.0"
138 | },
139 | "engines": {
140 | "node": ">=4"
141 | }
142 | },
143 | "node_modules/to-fast-properties": {
144 | "version": "2.0.0",
145 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
146 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
147 | "engines": {
148 | "node": ">=4"
149 | }
150 | }
151 | },
152 | "dependencies": {
153 | "@babel/code-frame": {
154 | "version": "7.12.13",
155 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
156 | "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
157 | "requires": {
158 | "@babel/highlight": "^7.12.13"
159 | }
160 | },
161 | "@babel/helper-validator-identifier": {
162 | "version": "7.12.11",
163 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
164 | "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw=="
165 | },
166 | "@babel/highlight": {
167 | "version": "7.12.13",
168 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
169 | "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
170 | "requires": {
171 | "@babel/helper-validator-identifier": "^7.12.11",
172 | "chalk": "^2.0.0",
173 | "js-tokens": "^4.0.0"
174 | }
175 | },
176 | "@babel/parser": {
177 | "version": "7.12.17",
178 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.17.tgz",
179 | "integrity": "sha512-r1yKkiUTYMQ8LiEI0UcQx5ETw5dpTLn9wijn9hk6KkTtOK95FndDN10M+8/s6k/Ymlbivw0Av9q4SlgF80PtHg=="
180 | },
181 | "@babel/template": {
182 | "version": "7.12.13",
183 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz",
184 | "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==",
185 | "requires": {
186 | "@babel/code-frame": "^7.12.13",
187 | "@babel/parser": "^7.12.13",
188 | "@babel/types": "^7.12.13"
189 | }
190 | },
191 | "@babel/types": {
192 | "version": "7.12.17",
193 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.17.tgz",
194 | "integrity": "sha512-tNMDjcv/4DIcHxErTgwB9q2ZcYyN0sUfgGKUK/mm1FJK7Wz+KstoEekxrl/tBiNDgLK1HGi+sppj1An/1DR4fQ==",
195 | "requires": {
196 | "@babel/helper-validator-identifier": "^7.12.11",
197 | "lodash": "^4.17.19",
198 | "to-fast-properties": "^2.0.0"
199 | }
200 | },
201 | "ansi-styles": {
202 | "version": "3.2.1",
203 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
204 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
205 | "requires": {
206 | "color-convert": "^1.9.0"
207 | }
208 | },
209 | "chalk": {
210 | "version": "2.4.2",
211 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
212 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
213 | "requires": {
214 | "ansi-styles": "^3.2.1",
215 | "escape-string-regexp": "^1.0.5",
216 | "supports-color": "^5.3.0"
217 | },
218 | "dependencies": {
219 | "escape-string-regexp": {
220 | "version": "1.0.5",
221 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
222 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
223 | }
224 | }
225 | },
226 | "color-convert": {
227 | "version": "1.9.3",
228 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
229 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
230 | "requires": {
231 | "color-name": "1.1.3"
232 | }
233 | },
234 | "color-name": {
235 | "version": "1.1.3",
236 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
237 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
238 | },
239 | "has-flag": {
240 | "version": "3.0.0",
241 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
242 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
243 | },
244 | "js-tokens": {
245 | "version": "4.0.0",
246 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
247 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
248 | },
249 | "lodash": {
250 | "version": "4.17.20",
251 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
252 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
253 | },
254 | "supports-color": {
255 | "version": "5.5.0",
256 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
257 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
258 | "requires": {
259 | "has-flag": "^3.0.0"
260 | }
261 | },
262 | "to-fast-properties": {
263 | "version": "2.0.0",
264 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
265 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
266 | }
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "babel-plugin-twin",
3 | "version": "1.1.0",
4 | "description": "",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/ben-rogerson/babel-plugin-twin.git"
9 | },
10 | "files": [
11 | "index.js"
12 | ],
13 | "keywords": [],
14 | "author": "Evgeny V and Ben Rogerson ",
15 | "license": "MIT",
16 | "bugs": {
17 | "url": "https://github.com/ben-rogerson/babel-plugin-twin/issues"
18 | },
19 | "homepage": "https://github.com/ben-rogerson/babel-plugin-twin#readme",
20 | "dependencies": {
21 | "@babel/template": "^7.12.13"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------