diff --git a/README.md b/README.md index b41b56b..a4898fe 100644 --- a/README.md +++ b/README.md @@ -1,206 +1,140 @@ # Introduction -This is a babel plugin to transform all your string classes into css-module classes automatically. +🚀 A Webpack plugin to transform your React `classNames` into CSS module classnames automatically 🚀 -Its lets you use css-module classes without style object. -It is faster to write, improves code readability and supports multiple css-module using [named-module](#introducing-named-css-modules) +- Faster to write ⚡ +- Improves code readability 📖 +- Supports multiple CSS Modules using [Named modules](#named-modules) ✨ +- Works with CSS, SASS, and SCSS modules 🔥 -Also supports \*sass/scss modules. - -_\*you may need to use sass-loader with webpack_ - -# Installation - -- Install the plugin with npm: - -```sh -npm install --save-dev jsx-css-module-transforms -``` - - - If you are using babel, add this to your plugins: +```jsx +// Original: -```jsonc -// .babelrc +import "./style.module.css" -{ - "plugins": ["module:jsx-css-module-transforms"] +function Component() { + return
} -``` -- For Webpack, modify the babel-loader options to include the plugin: +// Transformed: -```js -// webpack.config.js - -module.exports = { - module: { - rules: [ - { - loader: "babel-loader", - options: { - plugins: [ "module:jsx-css-module-transforms", ... ], - }, - }, - ], - }, +import style from "./style.module.css" + +function Component() { + return
} ``` -> Note: _The plugin relies on the **JSX** syntax. Other plugins that executes early might transform JSX -> before it reaches to the plugin which might cause some problems. jsx-css-module-transforms plugin needs -> to be placed before(ideally, at the beginning) other plugins that transform JSX._ - -# Usage - -We can import the css-module like normal css import without any import variable. - -```jsx -import "./m1.module.css" -``` +# Installation -The plugin will automatically change the import statement to include style object, -which will be used to access the css-module classes. +- Install the plugin: -```jsx -import _style from "./m1.module.css" // modified +```bash +npm install --save-dev jsx-css-module-transforms ``` -If we want to use the css-module, we need to write all our css classes using -style object that we just imported: +- Add the plugin to the list of plugins in `webpack.config.js`: -```jsx -import _style from "./m1.module.css" +```js +import JsxCssModuleTransforms from "jsx-css-module-transforms" -function Component() { - return

...

+let config = { + plugins: [JsxCssModuleTransforms, ...otherPlugins] } -``` -This sometimes can get too verbose and hurts **code readibility**. -It would be nice if we could write classnames within a string and not -having to deal with any style objects. +export default config; +``` +# Usage -With the help of plugin, we don't have to use style object anymore, instead we can specify our classes by just using strings: +The plugin automatically transforms CSS module imports and CSS classnames as required. +Without the plugin, you may write your code like this: ```jsx -import "./m1.module.css" +import style from "./style.module.css" function Component() { - return

...

+ return <> +
+
+
+ } ``` +This can get quite verbose at times and hurts **code readibility** 😵 -This looks more readable and is faster to write as well. -__jsx-css-modules-transforms__ will modify the code to use css-module and its style object automatically without -us having to do anything: +With the help of this plugin, we can fix that! You can simply write your +classnames as strings and let the plugin handle the rest: ```jsx -// modified -import _style from "./m1.module.css" +import "./style.module.css" function Component() { - return

.....

+ return <> +
+
+
+ } ``` -The transformed code uses object bracket-notation instead of dot-notation as this allows -us to use `-` (dash) within our classnames (eg. `className="foo-bar"`). - -## Global Styles +This improves readability and follows the same pattern as regular CSS. -By default, If plugin finds **any** `'*.module.css'` import, it will transform **all** the css classes -to use style objects. To use global css classnames, we need to add `':g'` at the end of the classname. -This tells plugin not to transform these classes and keep them as is: - -```jsx -import "./m1.module.css" +## Global styles -function Component() { - return

...

-} -``` +When the plugin finds `'.module.css'` import in the file, it will transform +**all** CSS classnames to use the imported CSS module. However, you may want +to use regular CSS classnames and prevent transformations on them. This +can be done by adding `:g` at the end of the classname: ```jsx -// modified -import _style from "./m1.module.css" +import "./style.module.css" function Component() { - return

...

+ return
} ``` -In this example, `'bar'` might be declared in the global style-sheet, while `'foo'` and `'baz'` are -scoped to the imported css module. +In this example, `card-layout` may be declared in the global style-sheet, +whereas `card-rnd-1` is declared in the the imported CSS module. +## Imported CSS module -## Usage With Already Imported CSS-Module - -If you are already using CSS-Modules, the plugin will transform string (containing classnames) -that is given to any `className` attr. For example: - -```jsx -import style from "./component.module.css" - -function Component() { - return ( -
-

...

-
- ) -} -``` +If you've been using CSS modules in your project, you can keep the old +code as-is, while the new code can use strings for the classnames: ```jsx -// modified import style from "./component.module.css" function Component() { return (
-

...

+

) } ``` -# Introducing Named CSS-Modules +## Named modules -In most cases, we would be using single CSS-Module inside a component but sometimes, -It might make sense to create reusable CSS-Modules and apply them in multiple different components. +You can use multiple CSS module within a file using Named modules. -In order to work with named CSS-Modules, we need to give names to each css-module import -by adding `:` at the end of the path: +To use Named CSS modules, you can add labels to each CSS module import +in the file by adding `:` at the end of the path: ```jsx import "./layout.module.css:layout" import "./component.module.css:com" ``` -To access CSS-Module class, simply add `:` at the end of the classname that specifies which CSS-Module -to use for the class: +And use the same labels for writing your classnames: ```jsx function Component() { return (
    -
  • ...
  • -
  • ...
  • -
- ) -} -``` -Transformed code would look like this: - -```jsx -import _layout from "./layout.module.css" -import _com from "./component.module.css" - -function Component() { - return ( -
    -
  • ...
  • -
  • ...
  • +
  • +
) } diff --git a/src/transforms.ts b/src/transforms.ts index 45563aa..967a33b 100644 --- a/src/transforms.ts +++ b/src/transforms.ts @@ -53,6 +53,12 @@ export function createModuleMemberExpression(classname: string, module: string, moduleIdentifier = t.identifier(modules.namedModules[module]); } + // When a class has dashes in its name, e.g. `.my-class`, it can be + // read from the imported style object in two ways: + // - Remove dash and camelCase the class name: `style.myClass`. + // - Use the bracket syntax for reading object property: `style["my-class"]`. + // The latter has the benefit that we can avoid transforming the classname string + // and just use it in the generated MemberExpression. Set `computed` to true to use the bracket syntax return t.memberExpression(moduleIdentifier, classnameStringLiteral, true); }