@mlaursen/scss
v0.0.8
Published
Common utils for compiling sass
Readme
@mlaursen/scss
This is a package that I normally use for documentation or when I want to compile SCSS outside of bundlers.
Installation
npm install @mlaursen/scsscompileScss
Node Example
import { readFileSync } from "node:fs";
import { compileScss } from "@mlaursen/scss";
// 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 cssBrowser Example
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
import { readFileSync, writeFileSync } from "node:fs";
import { format } from "oxfmt";
import { assertScssResolvePackageJson, compileScss } from "@mlaursen/scss";
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);
const formatted = await format(
browserOutFilePath,
`export const SCSS_LOOKUP: Record<string, string> = ${lookupString};`,
);
writeFileSync(browserOutFilePath, formatted.code, "utf8");compileScssModule
Simple Example
import { readFileSync } from "node:fs";
import { basename } from "node:path";
import { compileScssModule } from "@mlaursen/scss";
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 csscreateFakeCssModules
Simple Example
const styles = createFakeCssModules("./ExampleFile.scss");
<div className={styles.container}>{children}</div>;getFakeCssModuleClassName
Simple Example
getFakeCssModuleClassName("./ExampleFile.scss", "container");Minifying CSS
This is no longer part of this package, but it can be easily done using lightningcss:
import { compileScss } from "@mlaursen/scss";
import browserslist from "browserslist";
import { browserslistToTargets, transform } from "lightningcss";
import { readFileSync } from "node:fs";
const basePath = process.cwd();
const fileName = "./some/path/to/file.scss";
const load = (filePath: string): string => readFileSync(filePath, "utf8");
const code = load(fileName);
const compiled = compileScss({
code,
load,
basePath,
});
const minified = transform({
code: Buffer.from(compiled.css, "utf8"),
minify: true,
filename: fileName,
targets: browserslistToTargets(
browserslist("last 2 versions and not dead and > 0.5%"),
),
sourceMap: true,
inputSourceMap: compiled.sourceMap && JSON.stringify(compiled.sourceMap),
});
const css = minified.code.toString();
const map = minified.map?.toString();