Skip to content

add support for file extensions beyond .css #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 39 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ console.log(styles.someClass); // prints Test__someClass___2Frqu
npm install --save-dev babel-plugin-css-modules-transform
```

**Include plugin to `.babelrc`**
**Include plugin in `.babelrc`**

```json
{
Expand All @@ -57,14 +57,15 @@ npm install --save-dev babel-plugin-css-modules-transform
{
"plugins": [
[
"css-modules-transform", {
"css-modules-transform", {
"generateScopedName": "[name]__[local]___[hash:base64:5]", // in case you don't want to use a function
"generateScopedName": "./path/to/module-exporting-a-function.js", // in case you want to use a function
"generateScopedName": "npm-module-name",
"preprocessCss": "./path/to/module-exporting-a-function.js",
"preprocessCss": "npm-module-name",
"processCss": "./path/to/module-exporting-a-function.js",
"processCss": "npm-module-name",
"extensions": [".css", ".scss", ".less"], // list extensions to process; defaults to .css
"append": [
"npm-module-name",
"./path/to/module-exporting-a-function.js"
Expand All @@ -79,6 +80,42 @@ npm install --save-dev babel-plugin-css-modules-transform
}
```

## Using a preprocessor

When using this plugin with a preprocessor, you'll need to configure it as such:


```
// ./path/to/module-exporting-a-function.js
var sass = require('node-sass');
var path = require('path');

module.exports = function processSass(data, filename) {
var result;
result = sass.renderSync({
data: data,
file: filename
}).css;
return result.toString('utf8');
};
```

and then add any relevant extensions to your plugin config:

```
{
"plugins": [
[
"css-modules-transform", {
"preprocessCss": "./path/to/module-exporting-a-function.js",
"extensions": [".css", ".scss"]
}
]
]
}

```

## License

MIT
29 changes: 23 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,25 @@ export default function transformCssModules({ types: t }) {
* @returns {Array} array of class names
*/
function requireCssFile(filepath, cssFile) {
const from = resolveModulePath(filepath);
return require(resolve(from, cssFile));
let filePathOrModuleName = cssFile;

// only resolve path to file when we have a file path
if (!/^\w/i.test(filePathOrModuleName)) {
const from = resolveModulePath(filepath);
filePathOrModuleName = resolve(from, filePathOrModuleName);
}
return require(filePathOrModuleName);
}

// is css modules require hook initialized?
let initialized = false;

let matchExtensions = /\.css/i;
function matcher(extensions = ['.css']) {
const extensionsPatern = extensions.join('|').replace('.', '\.');
return new RegExp(`(${extensionsPatern})`, 'i');
}

return {
visitor: {
Program(path, { opts }) {
Expand All @@ -47,6 +59,10 @@ export default function transformCssModules({ types: t }) {

const currentConfig = { ...defaultOptions, ...opts };

// match file extensions, speeds up transform by creating one
// RegExp ahead of execution time
matchExtensions = matcher(currentConfig.extensions);

// check if there are simple requires and if they are functions
simpleRequires.forEach(key => {
if (typeof currentConfig[key] !== 'string') {
Expand Down Expand Up @@ -133,17 +149,18 @@ export default function transformCssModules({ types: t }) {
return;
}

if (/\.css/i.test(args[0].value)) {
const [ { value: cssPath }] = args;
const [{ value: stylesheetPath }] = args;

if (matchExtensions.test(stylesheetPath)) {
// if parent expression is variable declarator, replace right side with tokens
if (!t.isVariableDeclarator(path.parent)) {
throw new Error(
`You can't import css file ${cssPath} to a module scope.`
`You can't import css file ${stylesheetPath} to a module scope.`
);
}

const tokens = requireCssFile(file.opts.filename, args[0].value);
const requiringFile = file.opts.filename;
const tokens = requireCssFile(requiringFile, stylesheetPath);

/* eslint-disable new-cap */
path.replaceWith(t.ObjectExpression(
Expand Down
4 changes: 4 additions & 0 deletions test/extensions.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.sassy {
display: block;
color: pink;
}
8 changes: 8 additions & 0 deletions test/fixtures/extensions.expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';

var css = {
'className': 'styles__className___385m0 parent__block___33Sxl'
};
var scss = {
'sassy': 'extensions__sassy___12Yag'
};
2 changes: 2 additions & 0 deletions test/fixtures/extensions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var css = require('../styles.css');
var scss = require('../extensions.scss');
4 changes: 4 additions & 0 deletions test/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,8 @@ describe('babel-plugin-css-modules-transform', () => {

stream.end();
});

it('should accept file extensions as an array', () => {
expect(transform('fixtures/extensions.js', {extensions: ['.scss', '.css']}).code).to.be.equal(readExpected('fixtures/extensions.expected.js'));
});
});