Skip to content

Add silenceStyleNameErrors option #112

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 10 commits into from
Aug 22, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Allow more options to handle missing styleNames
This changes the option from a boolean “silenceStyleNameErrors” to an
enum “handleMissingStyleName” option, with possible values of “throw”
(default), “warn”, and “ignore”.
  • Loading branch information
IanVS committed Aug 20, 2017
commit 185e1ce71a39f7db8dce14c68832fb66c26d3270
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Configure the options for the plugin within your `.babelrc` as follows:
|`generateScopedName`|`?GenerateScopedNameConfigurationType`|Refer to [Generating scoped names](https://github.com/css-modules/postcss-modules#generating-scoped-names)|`[path]___[name]__[local]___[hash:base64:5]`|
|`removeImport`|`boolean`|Remove the matching style import. This option is used to enable server-side rendering.|`false`|
|`webpackHotModuleReloading`|`boolean`|Enables hot reloading of CSS in webpack|`false`|
|`silenceStyleNameErrors`|`boolean`|Prevents errors being thrown for undefined CSS modules (using a `styleName` for which there is no CSS module defined). Setting this option to `true` is equivalent to setting `errorWhenNotFound: false` in [react-css-modules](https://github.com/gajus/react-css-modules#errorwhennotfound). |`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"`|

Missing a configuration? [Raise an issue](https://github.com/gajus/babel-plugin-react-css-modules/issues/new?title=New%20configuration:).

Expand Down
57 changes: 39 additions & 18 deletions src/getClassName.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,70 @@

import type {
StyleModuleMapType,
StyleModuleImportMapType
StyleModuleImportMapType,
HandleMissingStyleNameOptionType
} from './types';
import optionsDefaults from './schemas/optionsDefaults';

const isNamespacedStyleName = (styleName: string): boolean => {
return styleName.indexOf('.') !== -1;
};

const getClassNameForNamespacedStyleName = (styleName: string, styleModuleImportMap: StyleModuleImportMapType, silenceErrors: boolean): ?string => {
const getClassNameForNamespacedStyleName = (
styleName: string,
styleModuleImportMap: StyleModuleImportMapType,
handleMissingStyleNameOption?: HandleMissingStyleNameOptionType
): ?string => {
// Note:
// Do not use the desctructing syntax with Babel.
// Desctructing adds _slicedToArray helper.
const styleNameParts = styleName.split('.');
const importName = styleNameParts[0];
const moduleName = styleNameParts[1];
const handleMissingStyleName = handleMissingStyleNameOption || optionsDefaults.handleMissingStyleName;

if (!moduleName) {
if (silenceErrors) {
return null;
} else {
if (handleMissingStyleName === 'throw') {
throw new Error('Invalid style name.');
} else if (handleMissingStyleName === 'warn') {
// eslint-disable-next-line no-console
console.warn('Invalid style name.');
} else {
return null;
}
}

if (!styleModuleImportMap[importName]) {
if (silenceErrors) {
return null;
} else {
if (handleMissingStyleName === 'throw') {
throw new Error('CSS module import does not exist.');
} else if (handleMissingStyleName === 'warn') {
// eslint-disable-next-line no-console
console.warn('CSS module import does not exist.');
} else {
return null;
}
}

if (!styleModuleImportMap[importName][moduleName]) {
if (silenceErrors) {
return null;
} else {
if (handleMissingStyleName === 'throw') {
throw new Error('CSS module does not exist.');
} else if (handleMissingStyleName === 'warn') {
// eslint-disable-next-line no-console
console.warn('CSS module does not exist.');
} else {
return null;
}
}

return styleModuleImportMap[importName][moduleName];
};

type OptionsType = {|
silenceStyleNameErrors: boolean
handleMissingStyleName: HandleMissingStyleNameOptionType
|};

export default (styleNameValue: string, styleModuleImportMap: StyleModuleImportMapType, options?: OptionsType): string => {
export default (styleNameValue: string, styleModuleImportMap: StyleModuleImportMapType, options: OptionsType): string => {
const styleModuleImportMapKeys = Object.keys(styleModuleImportMap);
const silenceStyleNameErrors = Boolean(options && options.silenceStyleNameErrors);

return styleNameValue
.split(' ')
Expand All @@ -59,7 +74,7 @@ export default (styleNameValue: string, styleModuleImportMap: StyleModuleImportM
})
.map((styleName) => {
if (isNamespacedStyleName(styleName)) {
return getClassNameForNamespacedStyleName(styleName, styleModuleImportMap, silenceStyleNameErrors);
return getClassNameForNamespacedStyleName(styleName, styleModuleImportMap, options.handleMissingStyleName);
}

if (styleModuleImportMapKeys.length === 0) {
Expand All @@ -72,14 +87,20 @@ export default (styleNameValue: string, styleModuleImportMap: StyleModuleImportM

const styleModuleMap: StyleModuleMapType = styleModuleImportMap[styleModuleImportMapKeys[0]];

if (!styleModuleMap[styleName] && !silenceStyleNameErrors) {
throw new Error('Could not resolve the styleName \'' + styleName + '\'.');
if (!styleModuleMap[styleName]) {
if (options.handleMissingStyleName === 'throw') {
throw new Error('Could not resolve the styleName \'' + styleName + '\'.');
}
if (options.handleMissingStyleName === 'warn') {
// eslint-disable-next-line no-console
console.warn('Could not resolve the styleName \'' + styleName + '\'.');
}
}

return styleModuleMap[styleName];
})
.filter((className) => {
// Remove any styles which could not be found (if silenceStyleNameErrors)
// Remove any styles which could not be found (if handleMissingStyleName === 'ignore')
return className;
})
.join(' ');
Expand Down
5 changes: 3 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import BabelTypes from 'babel-types';
import ajvKeywords from 'ajv-keywords';
import Ajv from 'ajv';
import optionsSchema from './schemas/optionsSchema.json';
import optionsDefaults from './schemas/optionsDefaults';
import createObjectExpression from './createObjectExpression';
import requireCssModule from './requireCssModule';
import resolveStringLiteral from './resolveStringLiteral';
Expand Down Expand Up @@ -188,7 +189,7 @@ export default ({
path,
filenameMap[filename].styleModuleImportMap,
styleNameAttribute,
{silenceStyleNameErrors: Boolean(stats.opts.silenceStyleNameErrors)}
{handleMissingStyleName: stats.opts.handleMissingStyleName || optionsDefaults.handleMissingStyleName}
);

return;
Expand All @@ -204,7 +205,7 @@ export default ({
styleNameAttribute,
filenameMap[filename].importedHelperIndentifier,
filenameMap[filename].styleModuleImportMapIdentifier,
{silenceStyleNameErrors: Boolean(stats.opts.silenceStyleNameErrors)}
{handleMissingStyleName: stats.opts.handleMissingStyleName || optionsDefaults.handleMissingStyleName}
);
}
},
Expand Down
10 changes: 8 additions & 2 deletions src/replaceJsxExpressionContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import BabelTypes, {
jSXExpressionContainer,
jSXIdentifier
} from 'babel-types';
import type {
HandleMissingStyleNameOptionType
} from './types';
import conditionalClassMerge from './conditionalClassMerge';
import createObjectExpression from './createObjectExpression';
import optionsDefaults from './schemas/optionsDefaults';

type OptionsType = {|
silenceStyleNameErrors: boolean
handleMissingStyleName: HandleMissingStyleNameOptionType
|};

export default (
Expand Down Expand Up @@ -42,7 +46,9 @@ export default (
styleModuleImportMapIdentifier
];

if (options.silenceStyleNameErrors) {
// Only provide options argument if the options are something other than default
// This helps save a few bits in the generated user code
if (options.handleMissingStyleName !== optionsDefaults.handleMissingStyleName) {
args.push(createObjectExpression(t, options));
}

Expand Down
5 changes: 3 additions & 2 deletions src/resolveStringLiteral.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import {
import conditionalClassMerge from './conditionalClassMerge';
import getClassName from './getClassName';
import type {
StyleModuleImportMapType
StyleModuleImportMapType,
HandleMissingStyleNameOptionType
} from './types';

type OptionsType = {|
silenceStyleNameErrors: boolean
handleMissingStyleName: HandleMissingStyleNameOptionType
|};

/**
Expand Down
5 changes: 5 additions & 0 deletions src/schemas/optionsDefaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const optionsDefaults = {
handleMissingStyleName: 'throw'
};

export default optionsDefaults;
4 changes: 2 additions & 2 deletions src/schemas/optionsSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
"webpackHotModuleReloading": {
"type": "boolean"
},
"silenceStyleNameErrors": {
"type": "boolean"
"handleMissingStyleName": {
"enum": ["throw", "warn", "ignore"]
}
},
"type": "object"
Expand Down
2 changes: 2 additions & 0 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export type StyleModuleImportMapType = {
export type GenerateScopedNameType = (localName: string, resourcePath: string) => string;

export type GenerateScopedNameConfigurationType = GenerateScopedNameType | string;

export type HandleMissingStyleNameOptionType = 'throw' | 'warn' | 'ignore';
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"../../../../src",
{
"generateScopedName": "[name]__[local]",
"silenceStyleNameErrors": true
"handleMissingStyleName": "ignore"
}
]
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ const _styleModuleImportMap = {
const styleNameFoo = 'a-c';

<div className={_getClassName(styleNameFoo, _styleModuleImportMap, {
'silenceStyleNameErrors': true
'handleMissingStyleName': 'ignore'
})}></div>;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"../../../../src",
{
"generateScopedName": "[name]__[local]",
"silenceStyleNameErrors": true
"handleMissingStyleName": "ignore"
}
]
]
Expand Down