babel-plugin-sass-vars v0.3.1
Unmaintained / Obsolete (Nov 2019)
This project is unmaintained, as most of its functionality can now be replicated by
exporting CSS variables and using getComputedStyle().getPropertyValue()
. Please fork if
need be!
babel-plugin-sass-vars
Extract sass/scss variables at build time.
import styles from "style.scss";
import {primaryColor} from "style.scss";
Features
- Import all global sass variables, across all
@import
ed files - All sass functions, variable substitutions, etc. are evaluated by the official node-sass compiler
- Both sass and scss are supported and can be intermingled to the extent supported by node-sass
Install
This package is available on npm and can be installed with
npm install -D babel-plugin-sass-vars
Note that the package is a babel plugin and must be used as part of a babel build step.
Babel configuration
This plugin can be activated by adding it to the plugins
array within babel's
config. For example,
{
"plugins": [
["babel-plugin-sass-vars", {
"sassCase": // ...
"outputCase": // ...
}]
]
}
Usage
The plugin transforms certain import
and require
statements and in general has the
following behavior:
- The target filename must contain an
.scss
or.sass
extension to be considered - All sass values are stringified without further processing, so for example
$var: 42
becomesvar: "42"
,$var: 42px
becomesvar: "42px"
, and$var: "hello"
becomesvar: "hello"
Default import
To extract all global variables into a single object, just import the "default export" of the stylesheet:
import STYLE from "./styles.scss";
This import statement will then be replaced with an assignment like
const STYLE = Object.freeze({
var: "value",
// ...
});
so that each variable can be accessed through STYLE
.
Named imports
To import just a known subset of variables, the named form can be applied as usual:
import {myVar, otherVar as coolVar} from "./styles.scss";
This statement will then be replaced with assignments like
const myVar = "...";
const coolVar = "...";
Note that both import forms can be used together if desired:
import STYLE, {myVar} from "./styles.scss";
CommonJS require
import
The CommonJS import form is also supported:
let myStyles = require("./styles.scss");
This will then be transformed to something like
let myStyles = Object.freeze({
var: "value",
// ...
});
Options
The options object for the plugin can contain the following parameters.
sassCase
This option identifies the casing format of the variables within any imported stylesheets. All named import identifiers will be converted to this case before looking them up in the stylesheet. This means that variables written in camelCase in the javascript file can correspond to variables written in param-case in the stylesheet.
If only the default-import form is used, this option has no effect and can be left unset.
The value should be a string corresponding to one of the top-level functions of the
change-case
package, for example
"paramCase"
or "camelCase"
.
outputCase
This option identifies how the casing of sass variables should be transformed when they're exported to javascript via the default-import object or a named import variable. Note that when using the named-import form, the named identifiers must also be in this case style.
Its value should be given in the same format as sassCase
.
baseDir
This option identifies base directory for imports.
Its value should be given as string path
.
Examples
Basic examples
These examples assume a stylesheet with the contents
$primary-color: turqoise;
$secondary-color: salmon;
$alt-color: $primary-color;
$main-padding: 32;
$main-border: 1px solid #000;
is stored at the location ../styles/app.scss
relative to the javascript files.
Then with the following plugin options,
{
sassCase: "paramCase",
outputCase: "camelCase",
}
the following input
import styles from "../styles/app.scss"
import {primaryColor, secondaryColor as SECONDARY_COLOR} from "../styles/app.scss";
would be transformed to something like this output:
const styles = Object.freeze({
primaryColor: "turqoise",
secondaryColor: "salmon",
altColor: "turqoise",
mainPadding: "32",
mainBorder: "1px solid #000",
});
const primaryColor = "turqoise";
const SECONDARY_COLOR = "salmon";
Alternatively, if the babel options were set to output in constant case:
{
sassCase: "paramCase",
outputCase: "constantCase",
}
then the input file
import styles from "../styles/app.scss"
import {PRIMARY_COLOR, SECONDARY_COLOR as secondary} from "../styles/app.scss";
would be transformed to something like
const styles = Object.freeze({
PRIMARY_COLOR: "turqoise",
SECONDARY_COLOR: "salmon",
ALT_COLOR: "turqoise",
MAIN_PADDING: "32",
MAIN_BORDER: "1px solid #000",
});
const PRIMARY_COLOR = "turqoise";
const secondary = "salmon";
CSS framework example
This example shows how the plugin can be applied to a project that uses a large CSS framework. In this case, we'll consider a stylesheet that pulls in bulma:
$primary: aqua;
@import "../node_modules/bulma/bulma.sass";
Since bulma uses param-case for its variables, we set sassCase
to paramCase
, and
arbitrarily choose camelCase
for outputCase
:
{
sassCase: "paramCase",
outputCase: "camelCase",
}
With this configuration, the following input file
import styles, {primary, info, familyMonospace} from "../styles/app.scss";
would be transformed to something like the following:
const styles = Object.freeze({
"primary": "aqua",
"black": "#0a0a0a",
"greyDarker": "#363636",
"greyDark": "#4a4a4a",
"grey": "#7a7a7a",
"greyLight": "#b5b5b5",
"greyLighter": "#dbdbdb",
"familyMonospace": "monospace",
"renderMode": "optimizeLegibility",
"light": "whitesmoke",
"dark": "#363636",
"orangeInvert": "#fff",
"info": "#3273dc",
// All other bulma variables...
});
const primary = "aqua";
const info = "#3273dc";
const familyMonospace = "monospace";
How it works
This plugin is pretty much a hack, but there doesn't seem to be any existing interface provided by node-sass for getting at variable assignments. As such, the following procedure is used to extract these variables indirectly:
- Create a set of desired variables:
- If the default-import form is used, we need to find all global variables that could be accessed. To do so, the root stylesheet and any further imported stylesheets are traversed and parsed (using gonzales-pe) to extract variable names defined at the top level.
- If the named-import form is used, then the given names are simply transformed to sass case and used as the set.
- Generate a stylesheet that
@import
s the root stylesheet and assigns each desired sass variable to an associated "unique" custom property. - Transform this generated stylesheet to a CSS stylesheet using node-sass, which performs function evaluation, variable substitution, and all its other processing and assigns each custom property the final value of each variable.
- Parse this CSS stylesheet (using gonzales-pe), extract each custom property, and associate the value with each corresponding sass variable.