Skip to content

Commit 148aca2

Browse files
authored
feat: enable compatibility with noUncheckedIndexedAccess (#177)
1 parent fb9d5e8 commit 148aca2

File tree

7 files changed

+103
-21
lines changed

7 files changed

+103
-21
lines changed

README.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,18 @@ const b = styles['my_other-class'];
9797

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

100-
| Option | Default value | Description |
101-
| -------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------ |
102-
| `classnameTransform` | `asIs` | See [`classnameTransform`](#classnameTransform) below. |
103-
| `customMatcher` | `"\\.module\\.(c\|le\|sa\|sc)ss$"` | Changes the file extensions that this plugin processes. |
104-
| `customRenderer` | `false` | See [`customRenderer`](#customRenderer) below. |
105-
| `customTemplate` | `false` | See [`customTemplate`](#customTemplate) below. |
106-
| `goToDefinition` | `false` | Enables jump to definition, with limited compatibility. See [`goToDefinition`](#goToDefinition) below. |
107-
| `namedExports` | `true` | Enables named exports for compatible classnames. |
108-
| `dotenvOptions` | `{}` | Provides options for [`dotenv`](https://github.com/motdotla/dotenv#options). |
109-
| `postcssOptions` | `{}` | See [`postcssOptions`](#postcssOptions) below. |
110-
| `rendererOptions` | `{}` | See [`rendererOptions`](#rendererOptions) below. |
100+
| Option | Default value | Description |
101+
| -------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------ |
102+
| `classnameTransform` | `asIs` | See [`classnameTransform`](#classnameTransform) below. |
103+
| `customMatcher` | `"\\.module\\.(c\|le\|sa\|sc)ss$"` | Changes the file extensions that this plugin processes. |
104+
| `customRenderer` | `false` | See [`customRenderer`](#customRenderer) below. |
105+
| `customTemplate` | `false` | See [`customTemplate`](#customTemplate) below. |
106+
| `goToDefinition` | `false` | Enables jump to definition, with limited compatibility. See [`goToDefinition`](#goToDefinition) below. |
107+
| `noUncheckedIndexedAccess` | `false` | Enable for compatibility with TypeScript's `noUncheckedIndexedAccess`. |
108+
| `namedExports` | `true` | Enables named exports for compatible classnames. |
109+
| `dotenvOptions` | `{}` | Provides options for [`dotenv`](https://github.com/motdotla/dotenv#options). |
110+
| `postcssOptions` | `{}` | See [`postcssOptions`](#postcssOptions) below. |
111+
| `rendererOptions` | `{}` | See [`rendererOptions`](#rendererOptions) below. |
111112

112113
```json
113114
{
@@ -195,7 +196,7 @@ The `classes` object represents all the classnames extracted from the CSS Module
195196

196197
#### `goToDefinition`
197198

198-
This allows an editor like Visual Studio Code to jump to a classname's definition (file and line).
199+
This allows an editor like Visual Studio Code to go to a classname's definition (file and line).
199200

200201
This is experimental, and only works with Sass (for now) and may not always work as expected.
201202

src/helpers/__tests__/__snapshots__/getDtsSnapshot.test.ts.snap

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,3 +855,52 @@ exports[`utils / cssSnapshots with includePaths in stylus options should find ex
855855
"include-path": "include-path-module__include-path---2f2uR",
856856
}
857857
`;
858+
859+
exports[`utils / cssSnapshots with noUncheckedIndexedAccess enabled should return a dts file with only possibly undefined strings 1`] = `
860+
"declare let classes: {
861+
'localClassInsideGlobal'?: string;
862+
'localClass'?: string;
863+
'localClass2'?: string;
864+
'localClassInsideLocal'?: string;
865+
'reservedWords'?: string;
866+
'default'?: string;
867+
'const'?: string;
868+
'nestedClassParent'?: string;
869+
'childClass'?: string;
870+
'nestedClassParentExtended'?: string;
871+
'section1'?: string;
872+
'section2'?: string;
873+
'section3'?: string;
874+
'section4'?: string;
875+
'section5'?: string;
876+
'section6'?: string;
877+
'section7'?: string;
878+
'section8'?: string;
879+
'section9'?: string;
880+
'classWithMixin'?: string;
881+
'appLogo'?: string;
882+
'appLogo'?: string;
883+
};
884+
export default classes;
885+
export let localClassInsideGlobal?: string;
886+
export let localClass?: string;
887+
export let localClass2?: string;
888+
export let localClassInsideLocal?: string;
889+
export let reservedWords?: string;
890+
export let nestedClassParent?: string;
891+
export let childClass?: string;
892+
export let nestedClassParentExtended?: string;
893+
export let section1?: string;
894+
export let section2?: string;
895+
export let section3?: string;
896+
export let section4?: string;
897+
export let section5?: string;
898+
export let section6?: string;
899+
export let section7?: string;
900+
export let section8?: string;
901+
export let section9?: string;
902+
export let classWithMixin?: string;
903+
export let appLogo?: string;
904+
export let appLogo?: string;
905+
"
906+
`;

src/helpers/__tests__/getDtsSnapshot.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,33 @@ describe('utils / cssSnapshots', () => {
253253
expect(dts).toMatchSnapshot();
254254
});
255255
});
256+
257+
describe('with noUncheckedIndexedAccess enabled', () => {
258+
const fileName = join(__dirname, 'fixtures', 'test.module.scss');
259+
const css = readFileSync(fileName, 'utf8');
260+
const options: Options = {
261+
classnameTransform: 'camelCaseOnly',
262+
noUncheckedIndexedAccess: true,
263+
};
264+
265+
const cssExports = getCssExports({
266+
css,
267+
fileName,
268+
logger,
269+
options,
270+
processor,
271+
compilerOptions,
272+
});
273+
274+
it('should return a dts file with only possibly undefined strings', () => {
275+
const dts = createDtsExports({
276+
cssExports,
277+
fileName,
278+
logger,
279+
options,
280+
});
281+
expect(dts).not.toMatch(/\w'?: string/);
282+
expect(dts).toMatchSnapshot();
283+
});
284+
});
256285
});

src/helpers/classTransforms.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import camelCase from 'lodash.camelcase';
22
import { ClassnameTransformOptions } from '../options';
33

44
// The below is based on the CSS Modules implementation found here:
5-
// https://github.com/webpack-contrib/css-loader/blob/master/lib/compile-exports.js
5+
// https://github.com/webpack-contrib/css-loader
66

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

src/helpers/createDtsExports.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ import { Logger } from './logger';
88
const isValidVariable = (className: string) =>
99
VALID_VARIABLE_REGEXP.test(className);
1010

11-
const classNameToProperty = (className: string) => `'${className}': string;`;
12-
const classNameToNamedExport = (className: string) =>
13-
`export let ${className}: string;`;
14-
1511
const flattenClassNames = (
1612
previousValue: string[] = [],
1713
currentValue: string[],
@@ -30,6 +26,13 @@ export const createDtsExports = ({
3026
}): string => {
3127
const classes = cssExports.classes;
3228

29+
const possiblyUndefined = Boolean(options.noUncheckedIndexedAccess);
30+
31+
const classNameToProperty = (className: string) =>
32+
`'${className}'${possiblyUndefined ? '?' : ''}: string;`;
33+
const classNameToNamedExport = (className: string) =>
34+
`export let ${className}${possiblyUndefined ? '?' : ''}: string;`;
35+
3336
const processedClasses = Object.keys(classes)
3437
.map(transformClasses(options.classnameTransform))
3538
.reduce(flattenClassNames, []);

src/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ function init({ typescript: ts }: { typescript: typeof tsModule }) {
3232
process.chdir(directory);
3333

3434
// User options for plugin.
35-
36-
const config = info.config as { options?: Options };
37-
const options = config.options ?? {};
35+
const options: Options =
36+
(info.config as { options?: Options }).options ?? {};
3837
logger.log(`options: ${JSON.stringify(options)}`);
3938

4039
// Load environment variables like SASS_PATH.

src/options.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ export interface Options {
2727
dotenvOptions?: DotenvConfigOptions;
2828
goToDefinition?: boolean;
2929
namedExports?: boolean;
30+
noUncheckedIndexedAccess?: boolean;
3031
postcssOptions?: PostcssOptions;
31-
/** @deprecated To align with other projects. */
32+
/** @deprecated To align with naming in other projects. */
3233
postCssOptions?: PostcssOptions;
3334
rendererOptions?: RendererOptions;
3435
}

0 commit comments

Comments
 (0)