npm package: @mlaursen/scss
Description: Common utils for compiling sass
Author: Mikkel Laursen
Latest version: 0.0.1

# @mlaursen/scss

This is a package that I normally use for documentation or when I want to
compile SCSS outside of bundlers.

## Installation

```sh
npm install @mlaursen/scss
```

<!-- examples-start -->

## compileScss

### Node Example

```ts
import { compileScss } from "@mlaursen/scss";
import { readFileSync } from "node:fs";

// start by setting a base path for everything. using process.cwd() is
// usually the easiest
const basePath = process.cwd();
const code = readFileSync("./some/path/to/file.scss", "utf8");

const { css } = compileScss({
  code,
  // add a synchronous load function
  load: (filePath) => readFileSync(filePath, "utf8"),

  // add the base path
  basePath,
});

// do something with css
```

### Browser Example

```ts
import { compileScss } from "@mlaursen/scss";

// the browser example is a bit more difficult as you need to create a
// lookup for all the file paths and reference them in the load function
// this should be any absolute path other than `/` and unique enough to be
// replaced easily
const basePath = "/__home__";

// NOTE: This can be generated by "abusing" the node API. see the next example

const SCSS_LOOKUP: Record<string, string> = {
  [`${basePath}/file1.scss`]: "contents of that file",
  [`${basePath}/node_modules/dependency-name/package.json`]: JSON.stringify({
    exports: {
      ".": {
        sass: "./dist/_main.scss",
      },
    },
  }),
};

const { css } = compileScss({
  code,
  load: (filePath) => {
    const contents = SCSS_LOOKUP[filePath];
    if (!contents) {
      throw new Error("Not found");
    }

    return contents;
  },
  basePath,
});
```

### Generating SCSS Lookup

```ts
import { assertScssResolvePackageJson, compileScss } from "@mlaursen/scss";
import { readFileSync, writeFileSync } from "node:fs";
import { format } from "prettier";

const basePath = process.cwd();
const browserBasePath = "/__home__";
const browserOutFilePath = "./src/generated/scssLookup.ts";

const lookup: Record<string, string> = {};
compileScss({
  code: "@use 'everything';",
  load: (filePath) => {
    const contents = readFileSync(filePath, "utf8");
    const browserName = filePath.replace(basePath, "/__home__");
    if (filePath.endsWith("package.json")) {
      const parsed = JSON.parse(contents);
      assertScssResolvePackageJson(parsed);

      // can trim down the exports if needed
      lookup[browserName] = JSON.stringify({
        exports: parsed.exports,
        sass: parsed.sass,
        main: parsed.main,
      });
    } else {
      // can trim down the contents if needed. like removing comments
      lookup[browserName] = contents;
    }

    return contents;
  },
  basePath,
});

const lookupString = JSON.stringify(lookup);
writeFileSync(
  browserOutFilePath,
  await format(
    `
export const SCSS_LOOKUP: Record<string, string> = ${lookupString}
`,
    { parser: "typescript" }
  ),
  "utf8"
);
```

## compileScssModule

### Simple Example

```ts
import { compileScssModule } from "@mlaursen/scss";
import { readFileSync } from "node:fs";
import { basename } from "node:path";

const filePath = "./src/Example.scss";
const code = readFileSync(filePath, "utf8");
const { css } = compileScssModule({
  code,
  load: (filePath) => readFileSync(filePath, "utf8"),
  basePath: process.cwd(),
  componentName: basename(filePath, ".scss"),
});

// do something with css
```

## createFakeCssModules

### Simple Example

```tsx
const styles = createFakeCssModules("./ExampleFile.scss");

<div className={styles.container}>{children}</div>;
```

## getFakeCssModuleClassName

### Simple Example

```ts
getFakeCssModuleClassName("./ExampleFile.scss", "container");
```

## minifyCss

### Simple Example

```ts
import { readFileSync, writeFileSync } from "node:fs"
import { compileScss, minifyCss } from "@mlaursen/scss";

const filePath = "./some/path/to/file.scss"
const code = readFileSync(filePath, 'utf8');

const compileResult = compileScss({
  code,
  load: (filePath) => readFileSync(filePath, "utf8"),
  basePath: process.cwd(),
});

const minifyResult = minifyCss({
  css: compileResult.css
  from: filePath,
});

writeFileSync("example.min.css", minifyResult.css);
```

<!-- examples-end -->