Skip to content

Document new allow any classnames #182

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 2 commits into from
Dec 4, 2022
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
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pnpm-lock.yaml
/dist/
*.snap
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ Please note that no options are required. However, depending on your configurati

| Option | Default value | Description |
| -------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `allowUnknownClassnames` | `false` | Disables TypeScript warnings on unknown classnames (for default imports only). |
| `classnameTransform` | `asIs` | See [`classnameTransform`](#classnameTransform) below. |
| `customMatcher` | `"\\.module\\.(c\|le\|sa\|sc)ss$"` | Changes the file extensions that this plugin processes. |
| `customRenderer` | `false` | See [`customRenderer`](#customRenderer) below. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ exports[`utils / cssSnapshots with a custom renderer should process a file and l
}
`;

exports[`utils / cssSnapshots with allowAdditionalClasses enabled should return a dts file that allows any string value 1`] = `
exports[`utils / cssSnapshots with allowUnknownClassnames enabled should return a dts file that allows any string value 1`] = `
"declare let classes: {
'localClassInsideGlobal': string;
'localClass': string;
Expand Down
6 changes: 3 additions & 3 deletions src/helpers/__tests__/classTransforms.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { transformClasses } from '../classTransforms';
import { ClassnameTransformOptions } from '../../options';

describe('utils / classTransforms', () => {
const classNames = [
const classnames = [
'class-name-a',
'classNameB',
'class-Name-C',
Expand All @@ -18,14 +18,14 @@ describe('utils / classTransforms', () => {

it('should not transform classes when no option is set', () => {
const transformer = transformClasses();
const transformedClasses = classNames.map(transformer);
const transformedClasses = classnames.map(transformer);
expect(transformedClasses).toMatchSnapshot();
});

tests.forEach((option) => {
it(`should transform classes correctly when \`classnameTransform\` set to \`${option}\``, () => {
const transformer = transformClasses(option);
const transformedClasses = classNames.map(transformer);
const transformedClasses = classnames.map(transformer);
expect(transformedClasses).toMatchSnapshot();
});
});
Expand Down
4 changes: 2 additions & 2 deletions src/helpers/__tests__/getDtsSnapshot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,12 @@ describe('utils / cssSnapshots', () => {
});
});

describe('with allowAdditionalClasses enabled', () => {
describe('with allowUnknownClassnames enabled', () => {
const fileName = join(__dirname, 'fixtures', 'test.module.scss');
const css = readFileSync(fileName, 'utf8');
const options: Options = {
classnameTransform: 'camelCaseOnly',
allowAdditionalClasses: true,
allowUnknownClassnames: true,
};

const cssExports = getCssExports({
Expand Down
24 changes: 12 additions & 12 deletions src/helpers/classTransforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,42 @@ import { ClassnameTransformOptions } from '../options';
// The below is based on the CSS Modules implementation found here:
// https://github.com/webpack-contrib/css-loader

const dashCase = (className: string): string =>
className.replace(/-+(\w)/g, (_match: string, firstLetter: string) =>
const dashCase = (classname: string): string =>
classname.replace(/-+(\w)/g, (_match: string, firstLetter: string) =>
firstLetter.toUpperCase(),
);

export const transformClasses =
(camelCaseOption?: ClassnameTransformOptions) =>
(className: string): string[] => {
(classname: string): string[] => {
const entries: string[] = [];

switch (camelCaseOption) {
case 'camelCase': {
entries.push(className);
const targetClassName = camelCase(className);
if (targetClassName !== className) {
entries.push(classname);
const targetClassName = camelCase(classname);
if (targetClassName !== classname) {
entries.push(targetClassName);
}
break;
}
case 'camelCaseOnly':
entries.push(camelCase(className));
entries.push(camelCase(classname));
break;
case 'dashes': {
entries.push(className);
const targetClassName = dashCase(className);
if (targetClassName !== className) {
entries.push(classname);
const targetClassName = dashCase(classname);
if (targetClassName !== classname) {
entries.push(targetClassName);
}
break;
}
case 'dashesOnly':
entries.push(dashCase(className));
entries.push(dashCase(classname));
break;
case 'asIs':
default:
entries.push(className);
entries.push(classname);
break;
}

Expand Down
30 changes: 15 additions & 15 deletions src/helpers/createDtsExports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { CSSExportsWithSourceMap } from './getCssExports';
import { VALID_VARIABLE_REGEXP } from './validVarRegexp';
import { Logger } from './logger';

const isValidVariable = (className: string) =>
VALID_VARIABLE_REGEXP.test(className);
const isValidVariable = (classname: string) =>
VALID_VARIABLE_REGEXP.test(classname);

const flattenClassNames = (
previousValue: string[] = [],
Expand All @@ -28,22 +28,22 @@ export const createDtsExports = ({

const possiblyUndefined = Boolean(options.noUncheckedIndexedAccess);

const classNameToProperty = (className: string) =>
`'${className}'${possiblyUndefined ? '?' : ''}: string;`;
const classNameToNamedExport = (className: string) =>
`export let ${className}${possiblyUndefined ? '?' : ''}: string;`;
const classnameToProperty = (classname: string) =>
`'${classname}'${possiblyUndefined ? '?' : ''}: string;`;
const classnameToNamedExport = (classname: string) =>
`export let ${classname}${possiblyUndefined ? '?' : ''}: string;`;

const processedClasses = Object.keys(classes)
.map(transformClasses(options.classnameTransform))
.reduce(flattenClassNames, []);
const filteredClasses = processedClasses
.filter(isValidVariable)
.map(classNameToNamedExport);
.map(classnameToNamedExport);

let dts = `\
declare let classes: {
${processedClasses.map(classNameToProperty).join('\n ')}${
options.allowAdditionalClasses ? '\n [key: string]: string;' : ''
${processedClasses.map(classnameToProperty).join('\n ')}${
options.allowUnknownClassnames ? '\n [key: string]: string;' : ''
}
};
export default classes;
Expand All @@ -65,15 +65,15 @@ export default classes;

// Create a list of filtered classnames and hashed classnames.
const filteredClasses = Object.entries(cssExports.classes)
.map(([className, hashedClassName]) => [
.map(([classname, hashedClassname]) => [
// TODO: Improve this. It may return multiple valid classnames and we
// want to handle all of those.
transformClasses(options.classnameTransform)(className)[0],
hashedClassName,
transformClasses(options.classnameTransform)(classname)[0],
hashedClassname,
])
.filter(([className]) => isValidVariable(className));
.filter(([classname]) => isValidVariable(classname));

filteredClasses.forEach(([className, hashedClassName]) => {
filteredClasses.forEach(([classname, hashedClassName]) => {
const matchedLine = cssLines.findIndex((line) =>
line.includes(hashedClassName),
);
Expand All @@ -85,7 +85,7 @@ export default classes;
column: matchedColumn >= 0 ? matchedColumn : 0,
});
dtsLines[lineNumber ? lineNumber - 1 : 0] +=
classNameToNamedExport(className);
classnameToNamedExport(classname);
});

dts = dtsLines.join('\n');
Expand Down
2 changes: 1 addition & 1 deletion src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface RendererOptions {
}

export interface Options {
allowAdditionalClasses?: boolean;
allowUnknownClassnames?: boolean;
classnameTransform?: ClassnameTransformOptions;
customMatcher?: string;
customRenderer?: string;
Expand Down