I'm attempting to migrate from Sass to postCSS and testing out postcss-simple-vars gulp plugin.
I'm using Webstorm IDE, which automatically uses javascript style comments (//) in .scss files, so my non-block comments are all // comments, not /* */.
postcss-simple-vars throws errors at all // comments, even with the silent option set to true.
Here's my gulp task:
gulp.task('postcss', function () {
return gulp
.src('./styles/sass2/*.scss')
.pipe($.postcss(
[
vars({
silent: true,
variables: colors
})
]))
.pipe(gulp.dest('./dest'));
});
Am I missing something really obvious? Is there some way to get postcss-simple-vars to ignore // style comments?
HOW I SOLVED IT:
I replaced all the // comments with /* */ comments with gulp-replace ($.replace).
gulp.task('replace-comments', function() {
return gulp
.src(config.scss)
.pipe($.replace(/\/\/.*/g, function(comment){
return '/*' + comment.substring(2) + ( '*/');
}))
.pipe(gulp.dest('./styles/sass3'));
});
The problem is not in postcss-simple-vars. It's that the default parser for postcss expects standard CSS, and // comments are not standard: they break the parser.
To run uncompiled SCSS with // comments through postcss, you should use the alternate parser postcss-scss. The documentation in that README and for gulp-postcss should explain how to use it.
Related
I know there is already a tonne of automated tools to create a style guide / pattern library but in the interest of learning I'd like to see if I can roll my own.
Compiling the SASS is straight forward. Same with the js. I can also see how to wrap blocks of HTML from multiple files with a class and compiled into a single file. Ideal for displaying all the 'partials' together on one page.
gulp.task('inject:wrap', function(){
return gulp.src('./_patterns/*/*/*.html')
/// get the partial html filename here and insert below ###
.pipe(inject.wrap('<div id="###" class="pattern">', '</div>'))
.pipe(concat('patterns.html'))
.pipe(gulp.dest('build'));
});
gulp.task('process', ['inject:wrap']);
What I struggling with is how I can get the filename of the block - let's say _button.html - and pass this to the wrapper as the element id "###" above. Which I can then use to build the style guides navigation / anchor links.
Here's a sample code I've got, uses jade template language (which takes care of injections, partials, evaluation etc. by itself); There are two tasks, one generates static HTML pages, other pre-compiles templates to be used as runtime template functions wrapped in AMD
// preprocess & render jade static templates
gulp.task('views:preprocess', function () {
return gulp.src([ 'source/views/*.jade', '!source/views/layout.jade' ])
.pipe(plumber()) // plumber, because why not?
.pipe(data(function (file) {
// prepare data to be passed to the template
// here we can use the file name to map specific data to each file
return _.assign(settingsData, { timestamp: timestamp });
}))
// render template with data
.pipe(jade())
.pipe(gulp.dest('destination'));
});
// precompile jade runtime templates
gulp.task('views:precompile', function () {
// grab folder names
var folders = fs.readdirSync('source/templates').filter(function (file) {
return fs.statSync(path.join('source/templates', file)).isDirectory();
});
// create a separate task for each folder
var tasks = folders.map(function (folder) {
return gulp.src(path.join('source/templates', folder, '*.jade'))
.pipe(plumber())
// pre-compile the template as functions, for runtime
.pipe(jade({
client: true
}))
// wrap it in AMD, so we can use stuff like require.js to fetch them later
.pipe(wrap({
moduleRoot: 'source/templates',
modulePrefix: 'templates',
deps: [ 'jade' ],
params: [ 'jade' ]
}))
// concat all the templates in each folder to a single .js file
.pipe(concat(folder + '.js'))
.pipe(uglify())
.pipe(header(banner, { package: packageData }))
.pipe(gulp.dest('destination/scripts/templates'));
});
return merge(tasks);
});
Modules I've used are merge-stream, path, gulp, fs, gulp-data, gulp-jade, gulp-plumber etc.
Didn't quite understand what you're trying to achieve, but I hope this gives you some clues.
I'm compiling bootstrap-sass with the gulp task:
gulp.task('build-bootstrap-sass', function () {
return gulp.src('styles/styles.sass')
.pipe(sourcemaps.init())
.pipe(sass({includePaths: ['node_modules/bootstrap-sass/assets/stylesheets/']}).on('error', sass.logError))
.pipe(rename({basename:'bootstrap'}))
.pipe(autoprefixer())
.pipe(minifyCss())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('dist/' ));
});
But this gives me the following error:
[09:32:38] Using gulpfile d:\Code\Templates\App\gulpfile.js
[09:32:38] Starting 'build-bootstrap-sass'...
d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\text\escape-store.js:49
var index = this.restoreMatcher.exec(placeholder)[1];
^
TypeError: Cannot read property '1' of null
at EscapeStore.restore (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\text\escape-store.js:49:52)
at UrlsProcessor.restore (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\text\urls-processor.js:61:35)
at Object.restore (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\clean.js:195:28)
at store (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\source-maps.js:12:21)
at value (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\helpers.js:102:5)
at property (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\helpers.js:91:5)
at body (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\helpers.js:77:5)
at all (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\helpers.js:140:9)
at stringify (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\source-maps.js:74:3)
at SelectorsOptimizer.process (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\selectors\optimizer.js:20:10)
The issue seems to be when I use sourcemaps; If I remove it, the task passes. But I'm on the "latest" version for all my gulp dependencies; and the gulp-minify-css changelog indicates it got support for sourcemaps < 1.1.6.
The build also passes when I use sourcemaps without minify.
gulp-sourcemaps does not support gulp-minify-css.
You can find all supported plugins here: https://github.com/floridoo/gulp-sourcemaps/wiki/Plugins-with-gulp-sourcemaps-support
You could consider using gulp-cssnano for minifying css files.
As the question states. I know gulp-uglify can uglify with a simple:
gulp.src('filename')
.pipe(uglify())
Is there a way to tell it to strip out console.log statements too?
Yes there is!
As gulp-uglifyjs documentation mentions you can pass extra options ( gulp-uglifyjs documentation):
uglify([filename], [options])
All available options can be found on the compressor UglifyJS documentation page. From that 'drop_console: true' should help:
uglify([filename], {
compress: {
drop_console: true
}
})
Much better still: you can use the specialized gulp plugin: gulp-strip-debug. It doesn't only strip out console statements, but also alerts and debugger statements.
Strip console, alert, and debugger statements from JavaScript code with strip-debug
install it using:
npm install --save-dev gulp-strip-debug
and use it like:
var gulp = require('gulp');
var stripDebug = require('gulp-strip-debug');
gulp.task('default', function () {
return gulp.src('src/app.js')
.pipe(stripDebug())
.pipe(gulp.dest('dist'));
});
With gulp-uglify (not gulp-uglifyjs) you can remove arbitrary code by using a strategy similar to compilations constants with the compression configuration (Link goes to gulp-uglifyjs, but should be the same for gulp-uglify):
.pipe(uglify({
compress: {
global_defs: {
"DEBUG": false
}
}
}))
And then in your code write something like
if (DEBUG)
{
console.log("Application started...");
//...
}
if you set DEBUG in global_defs to true, gulp-uglify will remove the conditional but leave the inner branch. In case DEBUG is set to false, it will remove both.
drop_console as in Fill's answer does not seem to be supported in gulp-uglify.
I'm trying to get gulp to compile some sass, however I can't seem to get it to write out anything. I'm not seeing an error and using sass to compile myself is successful. Here is what my config looks like:
var sass = require('gulp-sass');
var baseOutputDir = '../publish/homepage';
var cssOutputDir = baseOutputDir + '/css';
gulp.task('sass', function () {
gulp.src(['./css-lib/Bootstrap/3.3.1/assets/stylesheets/_bootstrap.scss'])
.pipe(sass())
.on('error', function (err) { console.log(err.message); })
.pipe(gulp.dest(cssOutputDir));
})
The bootstrap is a clone of https://github.com/twbs/bootstrap-sass
I'm use to LESS and not Sass. A file with an underscore in front won't generate a css file.
I had the same problem. As #Steven pointed out _filename do not generate css files. Just rename/copy the _bootstrap.scss to something without leading underscore
gulp.src(['./css-lib/Bootstrap/3.3.1/assets/stylesheets/bootstrap.scss'])
I need to apply a build task for specific files. For finding them, I use the typical template. But I can't understood how to pass the arguments (file path) from gulp.src.
Desirable solution.
gulp.task('bundles', function() {
gulp.src('bundles/**/*.js').
pipe(gulp.start('build', file.path));
});
gulp.task('build', function (path) {
// use here
});
Question is a bit stale and I am not sure I totally understand what you're trying to achieve here, but I think what you're looking for is lazypipe
You might want to clarify your question if that's not what you're looking for
Example Usage:
var lazypipe = require('lazypipe'),
g = require('gulp-load-plugins')({lazy: true}),
jsTransformPipe = lazypipe()
.pipe(g.jshint) // <-- Notice the notation: g.jshint, not g.jshint()
.pipe(g.concat, 'bundle.js'), // <-- Notice how the param is passed to g.concat, as a second param to .pipe()
jsSourcePipe = lazypipe()
.pipe(gulp.src, './**/*.js');
gulp.task('bundle', function() {
jsSourcePipe()
.pipe(jsTransformPipe()) // <-- You execute the lazypipe by calling it as a function
.pipe(gulp.dest('../build/');
});
With lazypipe you basically create a pipe for future use; hope this help
(Can't comment because of rep, sorry)
I assume that your sample code isn't filled with everything, but why don't you merge those tasks and use your gulp.src() in your build task instead of calling another task.
Maybe it's useful for you but with what you're showing I can't find an explanation for why you do this instead of simply going with something like :
gulp.task('build', function (path) {
gulp.src('bundles/**/*.js)
//Your code for this task
});
Of course, it removes the bundles task, but it's not useful as is.
Don't hesitate to comment if I'm wrong and I'll try to help you as much as I can.
First off, gulp.task('build', function (path) won't ever work. The only valid argument for gulp tasks is a callback to signal asynchronous task completion. If you tried to do run the above, gulp would expect path to be a function and the task would never complete unless that function was called. In this example, the 'build' task should be a regular function called from the 'bundles' pipe, not a task.
The better question would be: How do I run a custom function inside a gulp pipe? Plugins like gulp-tap might get you close, but it's not difficult to create what is essentially an inline gulp plugin to call your function.
Gulp pipes receive a through2 object stream containing a vinyl file object, an encoding and a callback. Here's a basic skeleton for calling any arbitrary function against the files in a gulp pipe:
var gulp = require('gulp');
var through = require('through2');
gulp.task('stack', function() {
return gulp.src('./src/*.js')
.pipe(through.obj(function(file, enc, cb) {
// file.path is the full path to the file
myBuildFunction(file.path);
cb(null, file);
}))
.pipe(gulp.dest('./build/'));
})
This can be incredibly powerful. To modify the file's contents, just change the file.contents buffer. To rename or relocate the file, change file.path. Everything can be done in gulp's native pipes.