From 5cc7c13db3217abcd57c3733c7abd959f9d3ab65 Mon Sep 17 00:00:00 2001 From: AlbertLucianto Date: Thu, 21 Feb 2019 03:33:23 +0800 Subject: [PATCH 1/7] feat: add skipAbsentStyleName --- src/attributeNameExists.js | 38 ++++++++++++++++++++++++++++++++++ src/index.js | 15 +++++++++----- src/schemas/optionsSchema.json | 3 +++ 3 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 src/attributeNameExists.js diff --git a/src/attributeNameExists.js b/src/attributeNameExists.js new file mode 100644 index 0000000..33213d5 --- /dev/null +++ b/src/attributeNameExists.js @@ -0,0 +1,38 @@ +// @flow + +import optionsDefaults from './schemas/optionsDefaults'; + +const attributeNameExists = (path: *, stats: *): boolean => { + const programPath = path.findParent((parentPath) => { + return parentPath.isProgram(); + }); + + let exists = false; + + programPath.traverse({ + JSXElement (jSXpath: *) { + if (exists) { + return; + } + + let attributeNames = optionsDefaults.attributeNames; + + if (stats.opts && stats.opts.attributeNames) { + attributeNames = Object.assign({}, attributeNames, stats.opts.attributeNames); + } + + const attributes = jSXpath.node.openingElement.attributes + .filter((attribute) => { + return typeof attribute.name !== 'undefined' && typeof attributeNames[attribute.name.name] === 'string'; + }); + + if (attributes.length) { + exists = true; + } + } + }); + + return exists; +}; + +export default attributeNameExists; diff --git a/src/index.js b/src/index.js index 4bd892e..a94825c 100644 --- a/src/index.js +++ b/src/index.js @@ -14,6 +14,7 @@ import createObjectExpression from './createObjectExpression'; import requireCssModule from './requireCssModule'; import resolveStringLiteral from './resolveStringLiteral'; import replaceJsxExpressionContainer from './replaceJsxExpressionContainer'; +import attributeNameExists from './attributeNameExists'; const ajv = new Ajv({ // eslint-disable-next-line id-match @@ -118,7 +119,7 @@ export default ({ return resolve(targetFileDirectoryPath, path.node.source.value); } - return require.resolve(path.node.source.value); + return path.node.source.value; }; const isFilenameExcluded = (filename, exclude) => { @@ -147,6 +148,14 @@ export default ({ inherits: babelPluginJsxSyntax, visitor: { ImportDeclaration (path: *, stats: *): void { + if (stats.opts.webpackHotModuleReloading) { + addWebpackHotModuleAccept(path); + } + + if (stats.opts.skipAbsentStyleName && !attributeNameExists(path, stats)) { + return; + } + if (notForPlugin(path, stats)) { return; } @@ -174,10 +183,6 @@ export default ({ generateScopedName: stats.opts.generateScopedName }); - if (stats.opts.webpackHotModuleReloading) { - addWebpackHotModuleAccept(path); - } - if (stats.opts.removeImport) { path.remove(); } diff --git a/src/schemas/optionsSchema.json b/src/schemas/optionsSchema.json index e14e525..ec4e503 100644 --- a/src/schemas/optionsSchema.json +++ b/src/schemas/optionsSchema.json @@ -69,6 +69,9 @@ } }, "type": "object" + }, + "skipAbsentStyleName": { + "type": "boolean" } }, "type": "object" From ac973280102fa9b7f23af556801ce949967d2ab2 Mon Sep 17 00:00:00 2001 From: AlbertLucianto Date: Thu, 21 Feb 2019 03:35:10 +0800 Subject: [PATCH 2/7] test: add test case for skipAbsentStyleName --- .../does not apply plugin if no styleName/bar.css | 1 + .../does not apply plugin if no styleName/input.js | 3 +++ .../options.json | 11 +++++++++++ .../does not apply plugin if no styleName/output.js | 5 +++++ 4 files changed, 20 insertions(+) create mode 100644 test/fixtures/react-css-modules/does not apply plugin if no styleName/bar.css create mode 100644 test/fixtures/react-css-modules/does not apply plugin if no styleName/input.js create mode 100644 test/fixtures/react-css-modules/does not apply plugin if no styleName/options.json create mode 100644 test/fixtures/react-css-modules/does not apply plugin if no styleName/output.js diff --git a/test/fixtures/react-css-modules/does not apply plugin if no styleName/bar.css b/test/fixtures/react-css-modules/does not apply plugin if no styleName/bar.css new file mode 100644 index 0000000..5512dae --- /dev/null +++ b/test/fixtures/react-css-modules/does not apply plugin if no styleName/bar.css @@ -0,0 +1 @@ +.a {} diff --git a/test/fixtures/react-css-modules/does not apply plugin if no styleName/input.js b/test/fixtures/react-css-modules/does not apply plugin if no styleName/input.js new file mode 100644 index 0000000..9b3805b --- /dev/null +++ b/test/fixtures/react-css-modules/does not apply plugin if no styleName/input.js @@ -0,0 +1,3 @@ +import 'bar.css'; + +
; diff --git a/test/fixtures/react-css-modules/does not apply plugin if no styleName/options.json b/test/fixtures/react-css-modules/does not apply plugin if no styleName/options.json new file mode 100644 index 0000000..208be1a --- /dev/null +++ b/test/fixtures/react-css-modules/does not apply plugin if no styleName/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "../../../../src", + { + "generateScopedName": "[name]__[local]", + "skipAbsentStyleName": true + } + ] + ] +} diff --git a/test/fixtures/react-css-modules/does not apply plugin if no styleName/output.js b/test/fixtures/react-css-modules/does not apply plugin if no styleName/output.js new file mode 100644 index 0000000..f8754b6 --- /dev/null +++ b/test/fixtures/react-css-modules/does not apply plugin if no styleName/output.js @@ -0,0 +1,5 @@ +"use strict"; + +require("bar.css"); + +
; From 7227139dba445e00a2689c4a1b28e59f222b935c Mon Sep 17 00:00:00 2001 From: AlbertLucianto Date: Thu, 21 Feb 2019 03:57:07 +0800 Subject: [PATCH 3/7] feat: refactor skipAbsentStyleName traversal --- src/attributeNameExists.js | 6 +----- src/index.js | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/attributeNameExists.js b/src/attributeNameExists.js index 33213d5..db2937f 100644 --- a/src/attributeNameExists.js +++ b/src/attributeNameExists.js @@ -2,11 +2,7 @@ import optionsDefaults from './schemas/optionsDefaults'; -const attributeNameExists = (path: *, stats: *): boolean => { - const programPath = path.findParent((parentPath) => { - return parentPath.isProgram(); - }); - +const attributeNameExists = (programPath: *, stats: *): boolean => { let exists = false; programPath.traverse({ diff --git a/src/index.js b/src/index.js index a94825c..c1cf039 100644 --- a/src/index.js +++ b/src/index.js @@ -32,6 +32,8 @@ export default ({ }) => { const filenameMap = {}; + let skipImport = false; + const setupFileForRuntimeResolution = (path, filename) => { const programPath = path.findParent((parentPath) => { return parentPath.isProgram(); @@ -148,15 +150,7 @@ export default ({ inherits: babelPluginJsxSyntax, visitor: { ImportDeclaration (path: *, stats: *): void { - if (stats.opts.webpackHotModuleReloading) { - addWebpackHotModuleAccept(path); - } - - if (stats.opts.skipAbsentStyleName && !attributeNameExists(path, stats)) { - return; - } - - if (notForPlugin(path, stats)) { + if (skipImport || notForPlugin(path, stats)) { return; } @@ -183,6 +177,10 @@ export default ({ generateScopedName: stats.opts.generateScopedName }); + if (stats.opts.webpackHotModuleReloading) { + addWebpackHotModuleAccept(path); + } + if (stats.opts.removeImport) { path.remove(); } @@ -255,6 +253,10 @@ export default ({ filenameMap[filename] = { styleModuleImportMap: {} }; + + if (stats.opts.skipAbsentStyleName && !attributeNameExists(path, stats)) { + skipImport = true; + } } } }; From 3964d191c8538438a06d82232e4d19288d01868b Mon Sep 17 00:00:00 2001 From: AlbertLucianto Date: Thu, 21 Feb 2019 03:59:55 +0800 Subject: [PATCH 4/7] fix: readd require.resolve for resource path --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index c1cf039..6d45568 100644 --- a/src/index.js +++ b/src/index.js @@ -121,7 +121,7 @@ export default ({ return resolve(targetFileDirectoryPath, path.node.source.value); } - return path.node.source.value; + return require.resolve(path.node.source.value); }; const isFilenameExcluded = (filename, exclude) => { From fd90f0b39e2ae0aebbe62c718f99496fba9bcb14 Mon Sep 17 00:00:00 2001 From: AlbertLucianto Date: Thu, 21 Feb 2019 12:38:48 +0800 Subject: [PATCH 5/7] feat: update options naming --- src/index.js | 12 ++++++++---- src/schemas/optionsSchema.json | 2 +- .../options.json | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/index.js b/src/index.js index 6d45568..a584fe0 100644 --- a/src/index.js +++ b/src/index.js @@ -32,7 +32,7 @@ export default ({ }) => { const filenameMap = {}; - let skipImport = false; + let skip = false; const setupFileForRuntimeResolution = (path, filename) => { const programPath = path.findParent((parentPath) => { @@ -150,7 +150,7 @@ export default ({ inherits: babelPluginJsxSyntax, visitor: { ImportDeclaration (path: *, stats: *): void { - if (skipImport || notForPlugin(path, stats)) { + if (skip || notForPlugin(path, stats)) { return; } @@ -186,6 +186,10 @@ export default ({ } }, JSXElement (path: *, stats: *): void { + if (skip) { + return; + } + const filename = stats.file.opts.filename; if (stats.opts.exclude && isFilenameExcluded(filename, stats.opts.exclude)) { @@ -254,8 +258,8 @@ export default ({ styleModuleImportMap: {} }; - if (stats.opts.skipAbsentStyleName && !attributeNameExists(path, stats)) { - skipImport = true; + if (stats.opts.skip && !attributeNameExists(path, stats)) { + skip = true; } } } diff --git a/src/schemas/optionsSchema.json b/src/schemas/optionsSchema.json index ec4e503..2b3041f 100644 --- a/src/schemas/optionsSchema.json +++ b/src/schemas/optionsSchema.json @@ -70,7 +70,7 @@ }, "type": "object" }, - "skipAbsentStyleName": { + "skip": { "type": "boolean" } }, diff --git a/test/fixtures/react-css-modules/does not apply plugin if no styleName/options.json b/test/fixtures/react-css-modules/does not apply plugin if no styleName/options.json index 208be1a..88e0d9d 100644 --- a/test/fixtures/react-css-modules/does not apply plugin if no styleName/options.json +++ b/test/fixtures/react-css-modules/does not apply plugin if no styleName/options.json @@ -4,7 +4,7 @@ "../../../../src", { "generateScopedName": "[name]__[local]", - "skipAbsentStyleName": true + "skip": true } ] ] From 421ca41455d8c3bf40adfdff5d8ee45fe2534330 Mon Sep 17 00:00:00 2001 From: AlbertLucianto Date: Thu, 21 Feb 2019 12:45:21 +0800 Subject: [PATCH 6/7] docs: update for skip option --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0f636bc..9f9b6d6 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,7 @@ Configure the options for the plugin within your `.babelrc` as follows: |`webpackHotModuleReloading`|`boolean`|Enables hot reloading of CSS in webpack|`false`| |`handleMissingStyleName`|`"throw"`, `"warn"`, `"ignore"`|Determines what should be done for undefined CSS modules (using a `styleName` for which there is no CSS module defined). Setting this option to `"ignore"` is equivalent to setting `errorWhenNotFound: false` in [react-css-modules](https://github.com/gajus/react-css-modules#errorwhennotfound). |`"throw"`| |`attributeNames`|`?AttributeNameMapType`|Refer to [Custom Attribute Mapping](#custom-attribute-mapping)|`{"styleName": "className"}`| +|`skip`|`boolean`|Whether to apply plugin if no matching `attributeNames` found in the file|`false`| Missing a configuration? [Raise an issue](https://github.com/gajus/babel-plugin-react-css-modules/issues/new?title=New%20configuration:). From 777ebf46c4081236d68c194bc363f8286e1fe7f8 Mon Sep 17 00:00:00 2001 From: AlbertLucianto Date: Thu, 21 Feb 2019 13:00:02 +0800 Subject: [PATCH 7/7] refactor: traverse JSXAttribute instead of element --- src/attributeNameExists.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/attributeNameExists.js b/src/attributeNameExists.js index db2937f..6314634 100644 --- a/src/attributeNameExists.js +++ b/src/attributeNameExists.js @@ -5,24 +5,21 @@ import optionsDefaults from './schemas/optionsDefaults'; const attributeNameExists = (programPath: *, stats: *): boolean => { let exists = false; + let attributeNames = optionsDefaults.attributeNames; + + if (stats.opts && stats.opts.attributeNames) { + attributeNames = Object.assign({}, attributeNames, stats.opts.attributeNames); + } + programPath.traverse({ - JSXElement (jSXpath: *) { + JSXAttribute (attrPath: *) { if (exists) { return; } - let attributeNames = optionsDefaults.attributeNames; - - if (stats.opts && stats.opts.attributeNames) { - attributeNames = Object.assign({}, attributeNames, stats.opts.attributeNames); - } - - const attributes = jSXpath.node.openingElement.attributes - .filter((attribute) => { - return typeof attribute.name !== 'undefined' && typeof attributeNames[attribute.name.name] === 'string'; - }); + const attribute = attrPath.node; - if (attributes.length) { + if (typeof attribute.name !== 'undefined' && typeof attributeNames[attribute.name.name] === 'string') { exists = true; } }