Reputation: 5215
UPDATE -- See additional info below, added on 22 March...
I want to inject an SCSS variable into a code file with my Gulp process.
I think this is two steps:
Gulp the SCSS _variables.scss file so I can access the variable
Just do a simple gulp.replace to do a string-replace and drop the variable value into my file (like the answer here)
I'm stuck on step 1. Here's what I have... as best I can tell, the not-heavily-documented gulp-sass-variables
plugin is supposed to pull the variables from the SCSS file into the argv object. So I followed the example on that plugin page, and tried this:
gulp.task('test', function () {
gulp.src('sass/*')
.pipe(plugins.print())
.pipe(plugins.sassVariables({
$foundIt: argv.testSassVar
}))
console.log(argv);
});
The print()
call is just to confirm that it is reading my SCSS files (and it is). But it can't find $testSassVar
in my SCSS code, as you can see from this error message:
[12:53:04] Using gulpfile ~/dev/project/gulpfile.js
[12:53:04] Starting 'test'...
[12:53:04] 'test' errored after 15 ms
[12:53:04] ReferenceError: testSassVar is not defined
at Gulp.<anonymous> (...)
[12:53:04] sass/_mixins.scss <- this line and all below are from print()
[12:53:04] sass/_normalize.scss
[12:53:04] sass/_variables.scss
[12:53:04] sass/footer
[12:53:04] sass/header
[12:53:04] sass/landing
[12:53:04] sass/landing-style.scss
[12:53:04] sass/site
[12:53:04] sass/style.scss
I tried removing that $foundIt
assignment, and just trying to fill the argv object, but that ends up outputting an empty array:
[13:00:57] Using gulpfile ~/dev/project/gulpfile.js
[13:00:57] Starting 'test'...
{ _: [ 'test' ], '$0': 'gulp' }
[13:00:57] Finished 'test' after 41 ms
Any ideas how I can accomplish what I'm trying to do?!
Looks like I can partially accomplish this by going a different route and using the gulp-sass-json plugin:
gulp.task('sass-json', function () {
return gulp
.src(scss_base + '*')
.pipe(plugins.sassJson())
.pipe(gulp.dest(tmp + 'sass-vars.json'));
});
This writes a file to /tmp
with my SCSS variables compiled into a JSON file. Then I thought, ok, I can load the JSON file in gulp and parse it from there. Unfortunately, this plugin doesn't resolve 2nd level variables (i.e. variables that reference variables), so you get something like this:
{
# variables parsed from SCSS to JSON by gulp-sass-json
# these are ok
"font__main": "'Open Sans', sans-serif",
"font__heading": "'Open Sans', sans-serif",
"font__line-height-body": "1.5",
"testSassVar": "123",
"color__nbar": "#ffffff",
"color__nbar_bg": "#50B107",
"size_border-radius": "3px"
# these variables reference other variables, not parsed, ouch
"color__background-body": "$color__nbar",
"color__background-screen": "$color__nbar",
# and this is even worse, the SCSS function isn't parsed, double ouch
"color_test": "lighten($color__nbar, 50%)",
}
As you can see, the variables that are simple references to other variables could probably be fixed with a bit of Javascript to just parse them, but once you get into the SASS functions, that idea falls apart.
Ideally, the SCSS compiler could parse and variables that aren't static values. Is that possible (or is that starting to really get into the weeds to solve this problem)?
The only other thought I had was to move all my variables to a JSON file, then use a gulp plugin that moved in the other direction -- JSON to SASS variables. But then I wouldn't get the advantage of having the SCSS compiler to run functions, parse variables, etc, and then give those values back to my gulp file.
Since my goal is to have the SASS values in the (parsed) variables available to my gulp file, so I can turn around and drop them into another (HTML or PHP) code file doing a simple string replace. If there's an easier way to accomplish my final goal, I'm all ears...
Upvotes: 0
Views: 2146
Reputation: 5374
Here is my solution - you need to have gulp-inject
main.scss
file
...
/* inject:scss */
/* endinject */
...
gulpfile.js
file
var gulpInject = require('gulp-inject');
...
gulp.src('...your/main/scss/file.scss')
.pipe(
gulpInject(gulp.src('...your/partial/scss/**/*.scss'), {
relative: true,
transform: function (filePath) {
var fileWithoutExtension = filePath.replace('.scss', '');
return '@import \'' + fileWithoutExtension + '\';';
}
})
)
.pipe(...)
...
The above example will inject partial SCSS files into the main SCSS file.
Hopefully my code would be helpful.
Upvotes: 0
Reputation: 586
I've also authored a library for this kind of use case that uses native sass compiler feature to extract the variable values called sass-extract which also comes with a webpack loader and babel plugin depending on the use case.
The benefit is that is based on the native sass type system and thus supports all kinds of sass features like functions, mixins, lists, maps etc. It also handles imports, overrides, defaults etc as expected.
If you are open to using webpack you can simply import the sass file:
const style = require('sass-extract-loader!./style.scss');
to get the variables extracted, which would be the easiest option. Otherwise you can just use the core library directly as such:
const sassExtract = require('sass-extract');
sassExtract.render({
file: 'path/to/my/styles.scss'
})
.then(rendered => {
console.log(rendered.vars);
});
There is also a synchronous version available that you can use to integrate with your gulp pipelines.
Upvotes: 1
Reputation: 777
I recently had a similar issue, although I'm not using gulp.
I searched for npm packages that could accomplish this task (variable extraction from SCSS), but the couple I found were subpar.
So, I ended up writing my own lib (extract-scss-variables). We use it in production, it's tested against foundation and a couple of other common uses.
I sincerely don't remember how to produce a gulp plugin anymore, but this library in itself shouldn't be hard to integrate.
In your specific case I'd do something like:
var extractScssVariables = require('extract-scss-variables');
var variables = extractScssVariables({
entryPoint: 'path/to/sass/style.scss',
files: [
'path/to/sass/_mixins.scss',
'path/to/sass/_normalize.scss',
'path/to/sass/_variables.scss',
],
sassOptions: {
includePaths: ['path/to/libraries/to/include.scss'],
},
});
where the entryPoint
is the context where the variables are extracted (e.g. if you overwrite a variable declared in _mixins.scss
, the entryPoint
's one is used instead);
files
is the array of files where to extract SCSS variables from;
and sassOptions
are any command line sass options you are already using.
Upvotes: 1