ben-rogerson / babel-plugin-twin Goto Github PK
View Code? Open in Web Editor NEWActivate twin.macro’s tw prop without adding the twin import. A companion plugin for twin.
Activate twin.macro’s tw prop without adding the twin import. A companion plugin for twin.
I have a babel preset I use across many packages. Some use twin and others don't.
Currently, when this plugin imports twin.macro even if you are in a file or package that doesn't use it.
A workaround is to conditionally include the plugin in overrides
, but this becomes an unmaintainable mess.
I wonder if it could search the AST for uses of tw
...or maybe this wouldn't be very performant.
Another idea would be to use read-pkg-up
to find the package.json
and check if twin.macro
is declared. If so, then include it. This comes with its own fs
performance issues.
Applying the configurations provided in your documentation, does not work for me inside storybook. Only if I had twin.macro manually. Can you confirm that?
It'd be great to be able to pass additional styles to more complex components (not wrapped with styled-component/emotion syntax).
For example:
function Button() {
// ...logic...
return <div tw="bg-white text-xs"><span>Inner</span>-<span>content</span></div>;
}
<Button tw="bg-black" />
Right now it outputs:
<div tw="bg-white text-xs"><span>Inner</span>-<span>content</span></div>
It would be nice if it instead output:
<div tw="bg-white text-xs bg-black"><span>Inner</span>-<span>content</span></div>
(with bg-black
appended to the root node).
I know I can pass this as a custom prop but this would just be easier.
Hi,
So i'm using babel-plugin-twin, it works fine locally and installed it as DevDependecy , but when trying to deploy to Heroku I'm getting the following error:
Uncaught Error: Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find module 'babel-plugin-twin'
Require stack:
- /app/node_modules/@babel/core/lib/config/files/plugins.js
- /app/node_modules/@babel/core/lib/config/files/index.js
- /app/node_modules/@babel/core/lib/index.js
- /app/node_modules/rollup-plugin-babel/dist/rollup-plugin-babel.cjs.js
- /app/node_modules/workbox-build/build/lib/bundle.js
- /app/node_modules/workbox-webpack-plugin/build/generate-sw.js
- /app/node_modules/workbox-webpack-plugin/build/index.js
- /app/node_modules/react-scripts/config/webpack.config.js
- /app/node_modules/@craco/craco/lib/cra.js
- /app/node_modules/@craco/craco/scripts/start.js
at Function.Module._resolveFilename (/internal/modules/cjs/loader.js:889)
at resolve (/internal/modules/cjs/helpers.js:98)
at resolveStandardizedName (/app/node_modules/@babel/core/lib/config/files/plugins.js:111)
at resolvePlugin (/app/node_modules/@babel/core/lib/config/files/plugins.js:55)
at loadPlugin (/app/node_modules/@babel/core/lib/config/files/plugins.js:63)
at loadPlugin.next (<anonymous>)
at createDescriptor (/app/node_modules/@babel/core/lib/config/config-descriptors.js:187)
at createDescriptor.next (<anonymous>)
at evaluateSync (/app/node_modules/gensync/index.js:251)
at /app/node_modules/gensync/index.js:31
at Object../node_modules/webpack/hot/dev-server.js (main.chunk.js:32)
at __webpack_require__ (bootstrap:851)
at fn (bootstrap:150)
at Object.1 (main.chunk.js:54)
at __webpack_require__ (bootstrap:851)
at checkDeferredModules (bootstrap:45)
at Array.webpackJsonpCallback [as push] (bootstrap:32)
at main.chunk.js:1
craco.config.js
module.exports = {
babel: {
presets: [],
plugins: [
'babel-plugin-twin',
'babel-plugin-macros',
[
'@emotion/babel-plugin-jsx-pragmatic',
{
export: 'jsx',
import: '__cssprop',
module: '@emotion/react',
},
],
[
'@babel/plugin-transform-react-jsx',
{
pragma: '__cssprop',
pragmaFrag: 'React.Fragment',
},
],
],
},
};
What might be the reason for this error?
On my first install and run of this plugin (with { debug: true }
on in our .babelrc.js
file), I am getting a series of messages in the console and would like to find out more about what they mean. I also looked for this information in the Readme.
As a new user, it would be nice to add more clarity.
babel-plugin-twin: Injected import in “/Users/jeremy/Sites/joinbonsai/client/src/marketingRoutes.tsx”
babel-plugin-twin: Skipped injection in “/Users/jeremy/Sites/joinbonsai/client/src/components/marketing/shared/section.tsx”
Before digging into why I am getting them, I wonder if more clarity could be added by grouping output messages by Injected and Skipped and offering a one-line note about why and what could be done? Or just adding a block of text to the README.
Thank you for working on this!
I am unable to build a project with this plugin with the Vite toolchain.
I reproduced this with the vite-emotion-typescript
example in twin.examples
, diffing:
diff --git a/vite-emotion-typescript/package.json b/vite-emotion-typescript/package.json
index 47498d2..8480ae9 100644
--- a/vite-emotion-typescript/package.json
+++ b/vite-emotion-typescript/package.json
@@ -21,6 +21,7 @@
"@types/react": "^17.0.36",
"@types/react-dom": "^17.0.11",
"@vitejs/plugin-react": "^1.0.9",
+ "babel-plugin-twin": "^1.0.2",
"tailwindcss": "^2.2.19",
"twin.macro": "^2.8.1",
"typescript": "^4.5.2",
diff --git a/vite-emotion-typescript/vite.config.ts b/vite-emotion-typescript/vite.config.ts
index daeba20..1ddf194 100644
--- a/vite-emotion-typescript/vite.config.ts
+++ b/vite-emotion-typescript/vite.config.ts
@@ -7,6 +7,7 @@ export default defineConfig({
react({
babel: {
plugins: [
+ 'babel-plugin-twin',
'babel-plugin-macros',
[
'@emotion/babel-plugin-jsx-pragmatic',
Build output:
blissful@splendor > yarn build
yarn run v1.22.17
warning package.json: No license field
$ tsc && vite build
vite v2.6.14 building for production...
transforming (1) index.html(node:211339) [DEP0148] DeprecationWarning: Use of deprecated folder mapping "./" in the "exports" field module resolution of the package at /home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/postcss/package.json.
Update this package.json to use a subpath pattern like "./*".
(Use `node --trace-deprecation ...` to show where the warning was created)
transforming (3) src/main.tsxThere was an error trying to load the config "twin" for the macro imported from "twin.macro. Please see the error thrown for more information.
✓ 4 modules transformed.
[vite:react-babel] /home/blissful/sources/twin.examples/vite-emotion-typescript/commonjsHelpers.js: The argument 'path' must be a string or Uint8Array without null bytes. Received '/home/blissful/sources/twin.examples/vite-emotion-typescript/\x00commonjsHelpers.js'
file: commonjsHelpers.js
error during build:
TypeError [PLUGIN_ERROR]: /home/blissful/sources/twin.examples/vite-emotion-typescript/commonjsHelpers.js: The argument 'path' must be a string or Uint8Array without null bytes. Received '/home/blissful/sources/twin.examples/vite-emotion-typescript/\x00commonjsHelpers.js'
at Object.statSync (node:fs:1531:10)
at isTypeSync (/home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/path-type/index.js:28:24)
at getDirectorySync (/home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/babel-plugin-macros/node_modules/cosmiconfig/dist/getDirectory.js:28:61)
at ExplorerSync.searchSync (/home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/babel-plugin-macros/node_modules/cosmiconfig/dist/ExplorerSync.js:26:63)
at getConfigFromFile (/home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/babel-plugin-macros/dist/index.js:260:39)
at getConfig (/home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/babel-plugin-macros/dist/index.js:298:24)
at applyMacros (/home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/babel-plugin-macros/dist/index.js:214:18)
at ImportDeclaration (/home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/babel-plugin-macros/dist/index.js:114:28)
at NodePath._call (/home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/@babel/traverse/lib/path/context.js:53:20)
at NodePath.call (/home/blissful/sources/twin.examples/vite-emotion-typescript/node_modules/@babel/traverse/lib/path/context.js:40:17)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
When using it with emotion + twin + Next 13, it always shows the followig error
../../node_modules/.pnpm/[email protected]/node_modules/jiti/dist/jiti.js:1:71925
Module not found: Can't resolve 'perf_hooks'
https://nextjs.org/docs/messages/module-not-found
Import trace for requested module:
../../node_modules/.pnpm/[email protected]/node_modules/jiti/lib/index.js
../../node_modules/.pnpm/[email protected][email protected]/node_modules/tailwindcss/lib/lib/load-config.js
../../node_modules/.pnpm/[email protected][email protected]/node_modules/tailwindcss/lib/public/load-config.js
../../node_modules/.pnpm/[email protected][email protected]/node_modules/tailwindcss/loadConfig.js
../../node_modules/.pnpm/[email protected][email protected]/node_modules/twin.macro/macro.js
./pages/_app.tsx
Here is the Next config:
/** @type {import('next').NextConfig} */
const { resolve } = require('node:path')
console.log(require('perf_hooks'))
// The folders containing files importing twin.macro
const includedDirs = [resolve(__dirname, 'app'), resolve(__dirname, 'pages'), resolve(__dirname, 'components')]
function withTwin(nextConfig) {
return {
...nextConfig,
webpack(config, options) {
const { dev, isServer } = options
config.module = config.module || {}
config.module.rules = config.module.rules || []
const patchedDefaultLoaders = options.defaultLoaders.babel;
patchedDefaultLoaders.options.hasServerComponents = false;
config.module.rules.push({
test: /\.(tsx|ts)$/,
include: includedDirs,
use: [
patchedDefaultLoaders,
{
loader: 'babel-loader',
options: {
sourceMaps: dev,
presets: [
[
'@babel/preset-react',
{ runtime: 'automatic', importSource: '@emotion/react' },
],
],
plugins: [
require.resolve('babel-plugin-macros'),
require.resolve('babel-plugin-twin'),
require.resolve('@emotion/babel-plugin'),
[
require.resolve('@babel/plugin-syntax-typescript'),
{ isTSX: true },
],
[
require.resolve('babel-plugin-import'),
{
'libraryName': 'lodash',
'libraryDirectory': '',
'camel2DashComponentName': false,
}
],
],
},
},
],
})
if (!isServer) {
config.resolve.fallback = {
...(config.resolve.fallback || {}),
fs: false,
module: false,
path: false,
os: false,
crypto: false,
}
}
if (typeof nextConfig.webpack === 'function') {
return nextConfig.webpack(config, options)
} else {
return config
}
},
}
}
const nextConfig = withTwin({
transpilePackages: ['jotai-devtools'],
reactStrictMode: true,
})
module.exports = nextConfig
There is a typo in the npm readme: npm i -D babel-plugin twin
-- the second dash in the package name is missing.
I am getting the following TS warning when I try to use tw="...":
Type '{ children: Element; tw: string; }' is not assignable to type 'ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & { css?: Interpolation<Theme>; }'.
Property 'tw' does not exist on type 'ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & { css?: Interpolation<Theme>; }'.ts(2322)
Am I missing something in the config for it to work?
If I add import tw from 'twin.macro'
, the warning disappears but the line is shown as unused. Confusing...
This plugin has the ability to provide helpful feedback when we forget to import tw from "twin.macro"
and attempt to use tw``
.
This would be a great feature and shouldn't be too difficult to add.
It seems like you're encountering an issue with Storybook's Vite builder. The problem appears to be related to using a virtual package with a name that includes a . (dot), and it seems that the package cannot be found when cloned.
[vite:react-babel] /virtual:/@storybook/builder-vite/vite-app.js: Cannot find module 'twin.macro' from '/virtual:/@storybook/builder-vite'
file: /virtual:/@storybook/builder-vite/vite-app.js
=> Failed to build the preview
Error: /virtual:/@storybook/builder-vite/vite-app.js: Cannot find module 'twin.macro' from '/virtual:/@storybook/builder-vite'
at Function.resolveSync [as sync] (./node_modules/resolve/lib/sync.js:111:15)
at nodeResolvePath (./node_modules/babel-plugin-macros/dist/index.js:62:18)
at applyMacros (./node_modules/babel-plugin-macros/dist/index.js:203:23)
at ImportDeclaration (./node_modules/babel-plugin-macros/dist/index.js:110:28)
at NodePath._call (./node_modules/@babel/traverse/lib/path/context.js:46:20)
at NodePath.call (./node_modules/@babel/traverse/lib/path/context.js:36:17)
at NodePath.visit (./node_modules/@babel/traverse/lib/path/context.js:82:31)
at TraversalContext.visitQueue (./node_modules/@babel/traverse/lib/context.js:86:16)
at TraversalContext.visitMultiple (./node_modules/@babel/traverse/lib/context.js:61:17)
at TraversalContext.visit (./node_modules/@babel/traverse/lib/context.js:107:19)
at traverseNode (./node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at traverse (./node_modules/@babel/traverse/lib/index.js:52:34)
at NodePath.traverse (./node_modules/@babel/traverse/lib/path/index.js:101:24)
at PluginPass.Program (./node_modules/babel-plugin-macros/dist/index.js:91:18)
at newFn (./node_modules/@babel/traverse/lib/visitors.js:160:14)
at NodePath._call (./node_modules/@babel/traverse/lib/path/context.js:46:20)
at NodePath.call (./node_modules/@babel/traverse/lib/path/context.js:36:17)
at NodePath.visit (./node_modules/@babel/traverse/lib/path/context.js:82:31)
at TraversalContext.visitQueue (./node_modules/@babel/traverse/lib/context.js:86:16)
at TraversalContext.visitSingle (./node_modules/@babel/traverse/lib/context.js:65:19)
at TraversalContext.visit (./node_modules/@babel/traverse/lib/context.js:109:19)
at traverseNode (./node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at traverse (./node_modules/@babel/traverse/lib/index.js:52:34)
at transformFile (./node_modules/@babel/core/lib/transformation/index.js:82:31)
at transformFile.next (<anonymous>)
at run (./node_modules/@babel/core/lib/transformation/index.js:24:12)
at run.next (<anonymous>)
at transform (./node_modules/@babel/core/lib/transform.js:22:33)
at transform.next (<anonymous>)
at step (./node_modules/gensync/index.js:261:32)
at ./node_modules/gensync/index.js:273:13
at async.call.result.err.err (./node_modules/gensync/index.js:223:11)
at ./node_modules/gensync/index.js:189:28
at ./node_modules/@babel/core/lib/gensync-utils/async.js:67:7
at ./node_modules/gensync/index.js:113:33
at step (./node_modules/gensync/index.js:287:14)
at ./node_modules/gensync/index.js:273:13
at async.call.result.err.err (./node_modules/gensync/index.js:223:11)
storybookjs/builder-vite#535
storybookjs/builder-vite#367
I looked into these issues.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.