Skip to content
Open
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
10 changes: 3 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# 🎁 typed-scss-modules

<!-- TODO: (if needed) add a disclaimer about breaking changes for `implementation` and `importer` around here, in #239 -->

[![npm version](https://img.shields.io/npm/v/typed-scss-modules.svg?style=flat)](https://www.npmjs.com/package/typed-scss-modules)

Generate TypeScript definitions (`.d.ts`) files for CSS Modules that are written in SCSS (`.scss`). Check out [this post to learn more](https://skovy.dev/generating-typescript-definitions-for-css-modules-using-sass/) about the rationale and inspiration behind this package.
Expand Down Expand Up @@ -88,12 +90,6 @@ A pattern or an array of glob patterns to exclude files that match and avoid gen

An array of paths to look in to attempt to resolve your `@import` declarations. This example will search the `src/core` directory when resolving imports.

### `--implementation`

- **Type**: `"node-sass" | "sass"`
- **Default**: If an option is passed, it will always use the provided package implementation. If an option is not passed, it will first check if `node-sass` is installed. If it is, it will be used. Otherwise, it will then check if `sass` is installed. If it is, it will be used. Finally, falling back to `node-sass` if all checks and validations fail.
- **Example**: `typed-scss-modules src --implementation sass`

### `--aliases` (`-a`)

- **Type**: `object`
Expand Down Expand Up @@ -350,7 +346,7 @@ In addition to all CLI options, the following are options only available with th

Define a [single custom SASS importer or an array of SASS importers](https://github.com/sass/sass/blob/f355f602fc15f55b0a0a795ebe6eb819963e08a5/js-api-doc/legacy/importer.d.ts#L51-L149). This should only be necessary if custom SASS importers are already being used in the build process. This is used internally to implement `aliases` and `aliasPrefixes`.

Refer to [`lib/sass/importer.ts`](/blob/master/lib/sass/importer.ts) for more details and the `node-sass` and `sass` importer type definitions.
Refer to [`lib/sass/importer.ts`](/blob/master/lib/sass/importer.ts) for more details and the `sass` importer type definition.

### `--allowArbitraryExtensions`

Expand Down
212 changes: 2 additions & 210 deletions __tests__/__snapshots__/main.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`node-sass implementation main outputs the correct files when outputFolder is passed 1`] = `
exports[`main outputs the correct files when outputFolder is passed 1`] = `
[
{
"contents": "export declare const myCustomClass: string;
Expand Down Expand Up @@ -68,215 +68,7 @@ export declare const logo: string;
]
`;

exports[`node-sass implementation main reads options from the configuration file 1`] = `
[
{
"contents": "export type Styles = {
myCustomClass: string;
nestedAnother: string;
nestedClass: string;
nestedStyles: string;
number1: string;
someStyles: string;
whereSelector: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
",
"path": "dummy-styles/alias-prefixes.scss.d.ts",
},
{
"contents": "export type Styles = {
myCustomClass: string;
nestedAnother: string;
nestedClass: string;
number1: string;
someClass: string;
someStyles: string;
whereSelector: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
",
"path": "dummy-styles/aliases.scss.d.ts",
},
{
"contents": "export type Styles = {
nestedAnother: string;
nestedClass: string;
number1: string;
someStyles: string;
whereSelector: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
",
"path": "dummy-styles/complex.scss.d.ts",
},
{
"contents": "export type Styles = {
composedClass: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
",
"path": "dummy-styles/composes.scss.d.ts",
},
{
"contents": "export type Styles = {
app: string;
appHeader: string;
logo: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
",
"path": "dummy-styles/dashes.scss.d.ts",
},
{
"contents": "export type Styles = {
globalStyle: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
",
"path": "dummy-styles/global-variables.scss.d.ts",
},
{
"contents": "export type Styles = {
randomClass: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
",
"path": "dummy-styles/invalid.scss.d.ts",
},
{
"contents": "export type Styles = {
nestedStyles: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
",
"path": "dummy-styles/nested-styles/style.scss.d.ts",
},
{
"contents": "export type Styles = {
someClass: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
",
"path": "dummy-styles/style.scss.d.ts",
},
]
`;

exports[`sass implementation main outputs the correct files when outputFolder is passed 1`] = `
[
{
"contents": "export declare const myCustomClass: string;
export declare const nestedAnother: string;
export declare const nestedClass: string;
export declare const nestedStyles: string;
export declare const number1: string;
export declare const someStyles: string;
export declare const whereSelector: string;
",
"path": "../__generated__/__tests__/dummy-styles/alias-prefixes.scss.d.ts",
},
{
"contents": "export declare const myCustomClass: string;
export declare const nestedAnother: string;
export declare const nestedClass: string;
export declare const number1: string;
export declare const someClass: string;
export declare const someStyles: string;
export declare const whereSelector: string;
",
"path": "../__generated__/__tests__/dummy-styles/aliases.scss.d.ts",
},
{
"contents": "export declare const nestedAnother: string;
export declare const nestedClass: string;
export declare const number1: string;
export declare const someStyles: string;
export declare const whereSelector: string;
",
"path": "../__generated__/__tests__/dummy-styles/complex.scss.d.ts",
},
{
"contents": "export declare const composedClass: string;
",
"path": "../__generated__/__tests__/dummy-styles/composes.scss.d.ts",
},
{
"contents": "export declare const app: string;
export declare const appHeader: string;
export declare const logo: string;
",
"path": "../__generated__/__tests__/dummy-styles/dashes.scss.d.ts",
},
{
"contents": "export declare const globalStyle: string;
",
"path": "../__generated__/__tests__/dummy-styles/global-variables.scss.d.ts",
},
{
"contents": "export declare const randomClass: string;
",
"path": "../__generated__/__tests__/dummy-styles/invalid.scss.d.ts",
},
{
"contents": "export declare const nestedStyles: string;
",
"path": "../__generated__/__tests__/dummy-styles/nested-styles/style.scss.d.ts",
},
{
"contents": "export declare const someClass: string;
",
"path": "../__generated__/__tests__/dummy-styles/style.scss.d.ts",
},
]
`;

exports[`sass implementation main reads options from the configuration file 1`] = `
exports[`main reads options from the configuration file 1`] = `
[
{
"contents": "export type Styles = {
Expand Down
52 changes: 24 additions & 28 deletions __tests__/core/generate.test.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,32 @@
import fs from "fs";
import { generate } from "../../lib/core";
import { describeAllImplementations } from "../helpers";

describeAllImplementations((implementation) => {
describe("generate", () => {
beforeEach(() => {
// Only mock the write, so the example files can still be read.
fs.writeFileSync = jest.fn();
console.log = jest.fn(); // avoid console logs showing up
});

it("generates types for all files matching the pattern", async () => {
const pattern = `${__dirname}/../dummy-styles/**/*.scss`;
describe("generate", () => {
beforeEach(() => {
// Only mock the write, so the example files can still be read.
fs.writeFileSync = jest.fn();
console.log = jest.fn(); // avoid console logs showing up
});

await generate(pattern, {
banner: "",
watch: false,
ignoreInitial: false,
exportType: "named",
exportTypeName: "ClassNames",
exportTypeInterface: "Styles",
listDifferent: false,
ignore: [],
implementation,
quoteType: "single",
updateStaleOnly: false,
logLevel: "verbose",
outputFolder: null,
allowArbitraryExtensions: false,
});
it("generates types for all files matching the pattern", async () => {
const pattern = `${__dirname}/../dummy-styles/**/*.scss`;

expect(fs.writeFileSync).toHaveBeenCalledTimes(6);
await generate(pattern, {
banner: "",
watch: false,
ignoreInitial: false,
exportType: "named",
exportTypeName: "ClassNames",
exportTypeInterface: "Styles",
listDifferent: false,
ignore: [],
quoteType: "single",
updateStaleOnly: false,
logLevel: "verbose",
outputFolder: null,
allowArbitraryExtensions: false,
});

expect(fs.writeFileSync).toHaveBeenCalledTimes(6);
});
});
Loading