Skip to content
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

[styles] Safer prefix logic #11943

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
18 changes: 11 additions & 7 deletions packages/material-ui/src/styles/createGenerateClassName.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ import warning from 'warning';
// We need to use a global.
global.__MUI_GENERATOR_COUNTER__ = 0;

const escapeRegex = /([[\].#*$><+~=|^:(),"'`\s])/g;

function safePrefix(classNamePrefix) {
const prefix = String(classNamePrefix);
warning(prefix.length < 100, `Material-UI: the class name prefix is too long: ${prefix}.`);
// Sanitize the string as will be used to prefix the generated class name.
return prefix.replace(escapeRegex, '-');
}

// Returns a function which generates unique class names based on counters.
// When new generator function is created, rule counter is reset.
// We need to reset the rule counter for SSR for each request.
Expand All @@ -14,7 +23,6 @@ global.__MUI_GENERATOR_COUNTER__ = 0;
// https://github.com/cssinjs/jss/blob/4e6a05dd3f7b6572fdd3ab216861d9e446c20331/src/utils/createGenerateClassName.js
export default function createGenerateClassName(options = {}) {
const { dangerouslyUseGlobalCSS = false, productionPrefix = 'jss' } = options;
const escapeRegex = /([[\].#*$><+~=|^:(),"'`\s])/g;
let ruleCounter = 0;

// - HMR can lead to many class name generators being instantiated,
Expand Down Expand Up @@ -49,9 +57,7 @@ export default function createGenerateClassName(options = {}) {
// Code branch the whole block at the expense of more code.
if (dangerouslyUseGlobalCSS) {
if (styleSheet && styleSheet.options.classNamePrefix) {
let prefix = styleSheet.options.classNamePrefix;
// Sanitize the string as will be used to prefix the generated class name.
prefix = prefix.replace(escapeRegex, '-');
const prefix = safePrefix(styleSheet.options.classNamePrefix);

if (prefix.match(/^Mui/)) {
return `${prefix}-${rule.key}`;
Expand All @@ -74,9 +80,7 @@ export default function createGenerateClassName(options = {}) {
}

if (styleSheet && styleSheet.options.classNamePrefix) {
let prefix = styleSheet.options.classNamePrefix;
// Sanitize the string as will be used to prefix the generated class name.
prefix = prefix.replace(escapeRegex, '-');
const prefix = safePrefix(styleSheet.options.classNamePrefix);

return `${prefix}-${rule.key}-${ruleCounter}`;
}
Expand Down
7 changes: 7 additions & 0 deletions packages/material-ui/src/styles/withStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ const withStyles = (stylesOrCreator, options = {}) => Component => {

if (process.env.NODE_ENV !== 'production' && !meta) {
meta = getDisplayName(Component);
warning(
typeof meta === 'string',
[
'Material-UI: the component displayName is invalid. It needs to be a string.',
`Please fix the following component: ${Component}.`,
].join('\n'),
);
}

const sheet = this.jss.createStyleSheet(styles, {
Expand Down