Skip to content

Support a custom TS transformer for final DTS output #73

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 5 commits into from
Feb 27, 2020
Merged
Show file tree
Hide file tree
Changes from 2 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
46 changes: 37 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,15 @@ const b = styles['my_other-class'];

Please note that no options are required. However, depending on your configuration, you may need to customise these options.

| Option | Default value | Description |
| -------------------- | ---------------------------------- | ---------------------------------------------------------------------------- |
| `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. |
| `dotenvOptions` | `{}` | Provides options for [`dotenv`](https://github.com/motdotla/dotenv#options). |
| `postCssOptions` | `{}` | See [`postCssOptions`](#postCssOptions) below. |
| `rendererOptions` | `{}` | See [`rendererOptions`](#rendererOptions) below. |
| Option | Default value | Description |
| ----------------------------- | ---------------------------------- | ---------------------------------------------------------------------------- |
| `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. |
| `customTypescriptTransformer` | `false` | See [`customTypescriptTransformer`](#customTypescriptTransformer) below. |
| `dotenvOptions` | `{}` | Provides options for [`dotenv`](https://github.com/motdotla/dotenv#options). |
| `postCssOptions` | `{}` | See [`postCssOptions`](#postCssOptions) below. |
| `rendererOptions` | `{}` | See [`rendererOptions`](#rendererOptions) below. |

```json
{
Expand Down Expand Up @@ -112,7 +113,7 @@ When a custom renderer is provided, not other renderers will be used.

The path to the `customRenderer` must be relative to the project root (i.e. `./myRenderer.js`).

The custom renderer itself should be a JavaScript file. The function will be called with two arguments: a `css` string, and an `options` object (see [`options.ts`](https://github.com/mrmckeb/typescript-plugin-css-modules/blob/master/src/options.ts#L36-L39)). It must be synchronous, and must return valid CSS.
The custom renderer itself should be a JavaScript file. The function will be called with two arguments: a `css` string, and an `options` object (see [`options.ts`](https://github.com/mrmckeb/typescript-plugin-css-modules/blob/master/src/options.ts#L33-L41)). It must be synchronous, and must return valid CSS.

```js
module.exports = (css, { fileName, logger }) => {
Expand All @@ -129,6 +130,33 @@ You can find an example custom renderer in our test fixtures ([`customRenderer.j

The [internal `logger`](https://github.com/mrmckeb/typescript-plugin-css-modules/blob/master/src/helpers/logger.ts) is provided for [debugging](#troubleshooting).

#### `customTypescriptTransformer`

The `customTypescriptTransformer` is an advanced option, letting you provide a transformer of the generated typescript declarations.

When a custom typescript transformer is provided, its output is used as the virtual typescript file.

The path to the `customTypescriptTransformer` must be relative to the project root (i.e. `./myTypescriptTransformer.js`).

The custom renderer itself should be a JavaScript file. The function will be called with two arguments: a `dts` string, and an `options` object (see [`options.ts`](https://github.com/mrmckeb/typescript-plugin-css-modules/blob/master/src/options.ts#L43-L52)). It must be synchronous, and must return valid TypeScript Declaration code (code found in a .d.ts file only).

```js
module.exports = (dts, { classes, fileName, logger }) => {
try {
// ...transform the dts here
return transformedDts;
} catch (error) {
logger.error(error.message);
}
};
```

You can find an example custom typescript transformer in our test fixtures ([`customTypescriptTransformer.js`](https://github.com/mrmckeb/typescript-plugin-css-modules/blob/master/src/helpers/__tests__/fixtures/customTypescriptTransformer.js)).

The [internal `logger`](https://github.com/mrmckeb/typescript-plugin-css-modules/blob/master/src/helpers/logger.ts) is provided for [debugging](#troubleshooting).

The `classes` object represents all the classnames extracted form the CSS Module. They are available if you want to add a custom representation of the CSS classes.

#### `postCssOptions`

| Option | Default value | Description |
Expand Down
181 changes: 181 additions & 0 deletions src/helpers/__tests__/__snapshots__/getDtsSnapshot.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ export default classes;

exports[`utils / cssSnapshots with file 'empty.module.less' getClasses should return an object matching expected CSS 1`] = `Object {}`;

exports[`utils / cssSnapshots with file 'empty.module.less' with a custom typescript transformer should transform the generated dts 1`] = `
"/* eslint-disable */
declare const classes: {

};
export default classes;

export const __cssModule: true;
export type AllClassNames = '';"
`;

exports[`utils / cssSnapshots with file 'empty.module.sass' createExports should create an exports file 1`] = `
"declare const classes: {

Expand All @@ -29,6 +40,17 @@ export default classes;

exports[`utils / cssSnapshots with file 'empty.module.sass' getClasses should return an object matching expected CSS 1`] = `Object {}`;

exports[`utils / cssSnapshots with file 'empty.module.sass' with a custom typescript transformer should transform the generated dts 1`] = `
"/* eslint-disable */
declare const classes: {

};
export default classes;

export const __cssModule: true;
export type AllClassNames = '';"
`;

exports[`utils / cssSnapshots with file 'empty.module.scss' createExports should create an exports file 1`] = `
"declare const classes: {

Expand All @@ -39,6 +61,17 @@ export default classes;

exports[`utils / cssSnapshots with file 'empty.module.scss' getClasses should return an object matching expected CSS 1`] = `Object {}`;

exports[`utils / cssSnapshots with file 'empty.module.scss' with a custom typescript transformer should transform the generated dts 1`] = `
"/* eslint-disable */
declare const classes: {

};
export default classes;

export const __cssModule: true;
export type AllClassNames = '';"
`;

exports[`utils / cssSnapshots with file 'import.module.css' createExports should create an exports file 1`] = `
"declare const classes: {
'classA': string;
Expand Down Expand Up @@ -73,6 +106,30 @@ Object {
}
`;

exports[`utils / cssSnapshots with file 'import.module.css' with a custom typescript transformer should transform the generated dts 1`] = `
"/* eslint-disable */
declare const classes: {
'classA': string;
'ClassB': string;
'class-c': string;
'class_d': string;
'parent': string;
'childA': string;
'childB': string;
'nestedChild': string;
};
export default classes;
export const classA: string;
export const ClassB: string;
export const parent: string;
export const childA: string;
export const childB: string;
export const nestedChild: string;

export const __cssModule: true;
export type AllClassNames = 'classA' | 'ClassB' | 'class-c' | 'class_d' | 'parent' | 'childA' | 'childB' | 'nestedChild';"
`;

exports[`utils / cssSnapshots with file 'import.module.less' createExports should create an exports file 1`] = `
"declare const classes: {
'nested-class-parent': string;
Expand Down Expand Up @@ -105,6 +162,26 @@ Object {
}
`;

exports[`utils / cssSnapshots with file 'import.module.less' with a custom typescript transformer should transform the generated dts 1`] = `
"/* eslint-disable */
declare const classes: {
'nested-class-parent': string;
'child-class': string;
'selector-blue': string;
'selector-green': string;
'selector-red': string;
'column-1': string;
'column-2': string;
'column-3': string;
'column-4': string;
'color-set': string;
};
export default classes;

export const __cssModule: true;
export type AllClassNames = 'nested-class-parent' | 'child-class' | 'selector-blue' | 'selector-green' | 'selector-red' | 'column-1' | 'column-2' | 'column-3' | 'column-4' | 'color-set';"
`;

exports[`utils / cssSnapshots with file 'test.module.css' createExports should create an exports file 1`] = `
"declare const classes: {
'classA': string;
Expand Down Expand Up @@ -139,6 +216,30 @@ Object {
}
`;

exports[`utils / cssSnapshots with file 'test.module.css' with a custom typescript transformer should transform the generated dts 1`] = `
"/* eslint-disable */
declare const classes: {
'classA': string;
'ClassB': string;
'class-c': string;
'class_d': string;
'parent': string;
'childA': string;
'childB': string;
'nestedChild': string;
};
export default classes;
export const classA: string;
export const ClassB: string;
export const parent: string;
export const childA: string;
export const childB: string;
export const nestedChild: string;

export const __cssModule: true;
export type AllClassNames = 'classA' | 'ClassB' | 'class-c' | 'class_d' | 'parent' | 'childA' | 'childB' | 'nestedChild';"
`;

exports[`utils / cssSnapshots with file 'test.module.less' createExports should create an exports file 1`] = `
"declare const classes: {
'nested-class-parent': string;
Expand Down Expand Up @@ -171,6 +272,26 @@ Object {
}
`;

exports[`utils / cssSnapshots with file 'test.module.less' with a custom typescript transformer should transform the generated dts 1`] = `
"/* eslint-disable */
declare const classes: {
'nested-class-parent': string;
'child-class': string;
'selector-blue': string;
'selector-green': string;
'selector-red': string;
'column-1': string;
'column-2': string;
'column-3': string;
'column-4': string;
'color-set': string;
};
export default classes;

export const __cssModule: true;
export type AllClassNames = 'nested-class-parent' | 'child-class' | 'selector-blue' | 'selector-green' | 'selector-red' | 'column-1' | 'column-2' | 'column-3' | 'column-4' | 'color-set';"
`;

exports[`utils / cssSnapshots with file 'test.module.sass' createExports should create an exports file 1`] = `
"declare const classes: {
'local-class-inside-global': string;
Expand Down Expand Up @@ -223,6 +344,36 @@ Object {
}
`;

exports[`utils / cssSnapshots with file 'test.module.sass' with a custom typescript transformer should transform the generated dts 1`] = `
"/* eslint-disable */
declare const classes: {
'local-class-inside-global': string;
'local-class': string;
'local-class-2': string;
'local-class-inside-local': string;
'reserved-words': string;
'default': string;
'const': string;
'nested-class-parent': string;
'child-class': string;
'nested-class-parent--extended': string;
'section-1': string;
'section-2': string;
'section-3': string;
'section-4': string;
'section-5': string;
'section-6': string;
'section-7': string;
'section-8': string;
'section-9': string;
'class-with-mixin': string;
};
export default classes;

export const __cssModule: true;
export type AllClassNames = 'local-class-inside-global' | 'local-class' | 'local-class-2' | 'local-class-inside-local' | 'reserved-words' | 'default' | 'const' | 'nested-class-parent' | 'child-class' | 'nested-class-parent--extended' | 'section-1' | 'section-2' | 'section-3' | 'section-4' | 'section-5' | 'section-6' | 'section-7' | 'section-8' | 'section-9' | 'class-with-mixin';"
`;

exports[`utils / cssSnapshots with file 'test.module.scss' createExports should create an exports file 1`] = `
"declare const classes: {
'local-class-inside-global': string;
Expand Down Expand Up @@ -275,6 +426,36 @@ Object {
}
`;

exports[`utils / cssSnapshots with file 'test.module.scss' with a custom typescript transformer should transform the generated dts 1`] = `
"/* eslint-disable */
declare const classes: {
'local-class-inside-global': string;
'local-class': string;
'local-class-2': string;
'local-class-inside-local': string;
'reserved-words': string;
'default': string;
'const': string;
'nested-class-parent': string;
'child-class': string;
'nested-class-parent--extended': string;
'section-1': string;
'section-2': string;
'section-3': string;
'section-4': string;
'section-5': string;
'section-6': string;
'section-7': string;
'section-8': string;
'section-9': string;
'class-with-mixin': string;
};
export default classes;

export const __cssModule: true;
export type AllClassNames = 'local-class-inside-global' | 'local-class' | 'local-class-2' | 'local-class-inside-local' | 'reserved-words' | 'default' | 'const' | 'nested-class-parent' | 'child-class' | 'nested-class-parent--extended' | 'section-1' | 'section-2' | 'section-3' | 'section-4' | 'section-5' | 'section-6' | 'section-7' | 'section-8' | 'section-9' | 'class-with-mixin';"
`;

exports[`utils / cssSnapshots with includePaths in sass options should find external file from includePaths 1`] = `
Object {
"big-font": "include-path-module__big-font---Td7hY",
Expand Down
9 changes: 9 additions & 0 deletions src/helpers/__tests__/fixtures/customTypescriptTransformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = (dts, { classes, logger }) => {
logger.log('Example log');
return [
'/* eslint-disable */',
dts,
'export const __cssModule: true;',
`export type AllClassNames = '${Object.keys(classes).join("' | '")}';`
].join('\n');
}
21 changes: 20 additions & 1 deletion src/helpers/__tests__/getDtsSnapshot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,29 @@ describe('utils / cssSnapshots', () => {

describe('createExports', () => {
it('should create an exports file', () => {
const exports = createExports(classes, {});
const exports = createExports(classes, {}, fullFileName, mockLogger);
expect(exports).toMatchSnapshot();
});
});

describe('with a custom typescript transformer', () => {
it('should transform the generated dts', () => {
const customTypescriptTransformer = join(
__dirname,
'fixtures',
'customTypescriptTransformer.js',
);
const overrideOptions: Options = { customTypescriptTransformer };

const dts = createExports(
classes,
overrideOptions,
fullFileName,
mockLogger,
);
expect(dts).toMatchSnapshot();
});
});
});
});

Expand Down
Loading