Prevent intermediate compass file output when piping - gulp

I'm using gulp-compass to compile scss files. However, I'm concatenating output into a single file.
This all works fine, but I'm noticing that compass itself is writing the individual files to the output directory.
I'm left with the individual files, as well as the concatenated result.
Is there any way to prevent that intermediate output?
gulp.task('compass:dev', function() {
return gulp.src(appPath + '/**/*.scss')
.pipe(plugins.compass({
css: distPath + '/css',
sass: appPath
}))
.pipe(plugins.concat('app.css'))
.pipe(gulp.dest(distPath + '/css'));
});

As mentioned before, gulp-compass has been blacklisted by the Gulp developers for violating against some "plugin rules" which have been established (for instance: you have to redefine input and output). Which means that you really, really shouldn't use it. However, gulp-ruby-sass as an option for allowing you to use compass imports. Consider this:
var sass = require('gulp-ruby-sass');
gulp.task('compass:dev', function() {
return sass(appPath + '/**/*.scss', { compass: true})
.pipe(plugins.concat('app.css'))
.pipe(gulp.dest(distPath + '/css'));
});
Depending on your setup, there still might be breaks.

Related

Glob watch multiple files, process one

I use Gulp 4 with gulp-sass. What I try to do is the following.
The code I provide here is just a fragment of the whole code, to show the important parts.
The watch should like it does, watch all .scss files.
In style(), only the current file is going to be processed.
If I save custom/components/header/header.scss, then only custom/components/header/header.scss should be processed, not all files.
The saved file should then have a filename like assets/css/dist/header/header.css
Both src and dest is unknown in this case because I don't have a single file to grab on to.
I see now that I also need to remove custom/components from the dest, but the important thing is that I can get the current file to start working with that.
gulp.watch('custom/components/**/*.scss', style);
function style() {
return gulp
.src()
.pipe(sass())
.on('error', sass.logError)
.pipe(gulp.dest('assets/css/dist'));
}
I just figure it out. It's possible to do it like this.
let watcher = gulp.watch(css.watch);
watcher.on('change', function(path) {
console.log(path);
style();
}

Negating folders with Gulp and then including a singular file from same directory

I'm using Gulp and I have a folder that has several .js files in in, of which I only need one of them; I read up on negating files within Gulp and from what I understood you should remove them first and then afterwards you can add them back in case you didn't want to negate them all.
I have this code for example:
var js_scripts = [
'js/dev/lib/**/*.js',
'js/dev/plugins/**/*.js',
'!js/dev/plugins/fancybox/*.js',
'js/dev/plugins/fancybox/jquery.fancybox-1.3.4.pack.js',
'!js/dev/plugins/inner/*.js',
'!js/dev/plugins/jquery.bxslider/**/*.js',
'js/dev/plugins/jquery.bxslider/jquery.bxslider.min.js',
// We have to set the bootstrap lines separately as some need to go before others
'js/dev/bootstrap/collapse.js',
'js/dev/bootstrap/dropdown.js',
'js/dev/bootstrap/tab.js',
'js/dev/bootstrap/transition.js',
'js/dev/scripts.js'
];
gulp.task('scripts', function() {
return gulp.src(js_scripts)
.pipe(sourcemaps.init())
.pipe(concat('scripts.js'))
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./js'));
});
gulp.task('uglify', ['scripts'], function() {
return gulp.src(js_scripts)
.pipe(gulpif('!**/*.min.js', uglify({mangle: false})))
.pipe(concat('scripts.min.js'))
.pipe(gulp.dest('./js'));
});
However I have just noticed that both js/dev/plugins/fancybox/jquery.fancybox-1.3.4.pack.js and js/dev/plugins/jquery.bxslider/jquery.bxslider.min.js have not been included in the output files even though I added them back in after initial removal.
According to the docs it states that:
Note that globs are evaluated in order, which means this is possible:
// exclude every JS file that starts with a b except bad.js
gulp.src(['*.js', '!b*.js', 'bad.js'])
So the fact that I first include the whole plugins directory and then remove everything inside js/dev/plugins/jquery.bxslider/ and then re-add the file js/dev/plugins/jquery.bxslider/jquery.bxslider.min.js for example then should should include that file?
I noticed if I removed this line: !js/dev/plugins/jquery.bxslider/**/*.js then it gets included.
What am I doing wrong here?

Get current file name in Gulp Stream

I've read Get the current file name in gulp.src(), and it seems like it's approaching what I am attempting to do, but I need help.
Consider the following function in a gulpfile.js:
function inline() {
return gulp.src('dist/**/*.html')
.pipe($.if(PRODUCTION, inliner('dist/css/app.css')))
.pipe(gulp.dest('dist'));
}
And inliner(), to be thorough (also in the gulpfile):
function inliner(css) {
var css = fs.readFileSync(css).toString();
var mqCss = siphon(css);
var pipe = lazypipe()
.pipe($.inlineCss, {
applyStyleTags: false,
removeStyleTags: false,
removeLinkTags: false
})
.pipe($.replace, '<!-- <style> -->', `<style>${mqCss}</style>`);
return pipe();
}
These functions take an external CSS file and inline them into the respective HTML for email.
I really want to know how to do something like this:
function inline() {
return gulp.src('dist/**/*.html')
.pipe($.if(PRODUCTION, inliner('dist/css/' + file.name + '.css')))
.pipe(gulp.dest('dist'));
}
And you might ask yourself, "why?" Well, I don't have just one CSS file. If everything from app.css was to be inlined, there would be a lot more styles applied than were actually necessary.
So I want to inline:
email1.css ---- to -------> email1.html
email2.css ---- to -------> email2.html
email3.css ---- to -------> email3.html
And so on. Essentially, I want to get the name of the HTML file being processed at that moment in the Gulp Stream, save it as a variable, and then pass it into the inliner('dist/css/' + file.name + '.css') bit. I've exhausted every bit of Gulp Knowledge I have and have come up completely and utterly blank.
Basically what you need to do is send each .html file in your stream down its own little sub stream with its own inliner(). The gulp-foreach plugin let's you do just that.
Then it's just a matter of determining the simple name of your file from its absolute path. The node.js built-in path.parse() got you covered there.
Putting it all together:
var path = require('path');
function inline() {
return gulp.src('dist/**/*.html')
.pipe($.if(PRODUCTION, $.foreach(function(stream, file) {
var name = path.parse(file.path).name;
return stream.pipe(inliner('dist/css/' + name + '.css'));
})))
.pipe(gulp.dest('dist'));
}

How should I create a complete build with Gulp?

Just learning Gulp. Looks great, but I can't find any information on how to make a complete distribution with it.
Let's say I want to use Gulp to concatenate and minify my CSS and JS, and optimise my images.
In doing so I change the location of JS scripts in my build directory (eg. from bower_components/jquery/dist/jquery.js to js/jquery.js).
How do I automatically update my build HTML/PHP documents to reference the correct files? What is the standard way of doing this?
How do I copy over the rest of my project files?. These are files that need to be included as part of the distribution, such as HTML, PHP, various txt, JSON and all sorts of other files. Surely I don't have to copy and paste those from my development directory each time I do a clean build with Gulp?
Sorry for asking what are probably very n00bish questions. It's possible I should be using something else other than Gulp to manage these, but I'm not sure where to start.
Many thanks in advance.
Point #1
The way i used to achieve this:
var scripts = [];
function getScriptStream(dir) { // Find it as a gulp module or create it
var devT = new Stream.Transform({objectMode: true});
devT._transform = function(file, unused, done) {
scripts.push(path.relative(dir, file.path));
this.push(file);
done();
};
return devT;
}
// Bower
gulp.task('build_bower', function() {
var jsFilter = g.filter('**/*.js');
var ngFilter = g.filter(['!**/angular.js', '!**/angular-mocks.js']);
return g.bowerFiles({
paths: {
bowerDirectory: src.vendors
},
includeDev: !prod
})
.pipe(ngFilter)
.pipe(jsFilter)
.pipe(g.cond(prod, g.streamify(g.concat.bind(null, 'libs.js'))))
.pipe(getScriptStream(src.html))
.pipe(jsFilter.restore())
.pipe(ngFilter.restore())
.pipe(gulp.dest(build.vendors));
});
// JavaScript
gulp.task('build_js', function() {
return gulp.src(src.js + '/**/*.js', {buffer: buffer})
.pipe(g.streamify(g.jshint))
.pipe(g.streamify(g.jshint.reporter.bind(null, 'default')))
.pipe(g.cond(prod, g.streamify(g.concat.bind(null,'app.js'))))
.pipe(g.cond(
prod,
g.streamify.bind(null, g.uglify),
g.livereload.bind(null, server)
))
.pipe(gulp.dest(build.js))
.pipe(getScriptStream(build.html));
});
// HTML
gulp.task('build_html', ['build_bower', 'build_js', 'build_views',
'build_templates'], function() {
fs.writeFile('scripts.json', JSON.stringify(scripts));
return gulp.src(src.html + '/index.html' , {buffer: true})
.pipe(g.replace(/(^\s+)<!-- SCRIPTS -->\r?\n/m, function($, $1) {
return $ + scripts.map(function(script) {
return $1 + '<script type="text/javascript" src="'+script+'"></script>';
}).join('\n') + '\n';
}))
.pipe(gulp.dest(build.html));
});
It has the advantages of concatenating and minifying everything for production while include every files for testing purpose keeping error line numbers coherent.
Point 2
Copying files with gulp is just as simple as doing this:
gulp.src(path).pipe(gulp.dest(buildPath));
Bonus
I generally proceed to deployment by creating a "build" branch and just cloning her in the production server. I created buildbranch for that matter:
// Publish task
gulp.task('publish', function(cb) {
buildBranch({
branch: 'build',
ignore: ['.git', '.token', 'www', 'node_modules']
}, function(err) {
if(err) {
throw err;
}
cb();
});
});
To loosely answer my own question, several years later:
How do I automatically update my build HTML/PHP documents to reference the correct files? What is the standard way of doing this?
Always link to dist version, but ensure sourcemaps are created, so the source is easy to debug. Of course, the watch task is a must.
How do I copy over the rest of my project files?. These are files that need to be included as part of the distribution, such as HTML, PHP, various txt, JSON and all sorts of other files. Surely I don't have to copy and paste those from my development directory each time I do a clean build with Gulp?
This usually isn't a problem as there aren't offer too many files. Large files and configuration are often kept out if the repo, besides.

Get the current file name in gulp.src()

In my gulp.js file I'm streaming all HTML files from the examples folder into the build folder.
To create the gulp task is not difficult:
var gulp = require('gulp');
gulp.task('examples', function() {
return gulp.src('./examples/*.html')
.pipe(gulp.dest('./build'));
});
But I can't figure out how retrieve the file names found (and processed) in the task, or I can't find the right plugin.
I'm not sure how you want to use the file names, but one of these should help:
If you just want to see the names, you can use something like gulp-debug, which lists the details of the vinyl file. Insert this anywhere you want a list, like so:
var gulp = require('gulp'),
debug = require('gulp-debug');
gulp.task('examples', function() {
return gulp.src('./examples/*.html')
.pipe(debug())
.pipe(gulp.dest('./build'));
});
Another option is gulp-filelog, which I haven't used, but sounds similar (it might be a bit cleaner).
Another options is gulp-filesize, which outputs both the file and it's size.
If you want more control, you can use something like gulp-tap, which lets you provide your own function and look at the files in the pipe.
I found this plugin to be doing what I was expecting: gulp-using
Simple usage example: Search all files in project with .jsx extension
gulp.task('reactify', function(){
gulp.src(['../**/*.jsx'])
.pipe(using({}));
....
});
Output:
[gulp] Using gulpfile /app/build/gulpfile.js
[gulp] Starting 'reactify'...
[gulp] Finished 'reactify' after 2.92 ms
[gulp] Using file /app/staging/web/content/view/logon.jsx
[gulp] Using file /app/staging/web/content/view/components/rauth.jsx
Here is another simple way.
var es, log, logFile;
es = require('event-stream');
log = require('gulp-util').log;
logFile = function(es) {
return es.map(function(file, cb) {
log(file.path);
return cb(null, file);
});
};
gulp.task("do", function() {
return gulp.src('./examples/*.html')
.pipe(logFile(es))
.pipe(gulp.dest('./build'));
});
You can use the gulp-filenames module to get the array of paths.
You can even group them by namespaces:
var filenames = require("gulp-filenames");
gulp.src("./src/*.coffee")
.pipe(filenames("coffeescript"))
.pipe(gulp.dest("./dist"));
gulp.src("./src/*.js")
.pipe(filenames("javascript"))
.pipe(gulp.dest("./dist"));
filenames.get("coffeescript") // ["a.coffee","b.coffee"]
// Do Something With it
For my case gulp-ignore was perfect.
As option you may pass a function there:
function condition(file) {
// do whatever with file.path
// return boolean true if needed to exclude file
}
And the task would look like this:
var gulpIgnore = require('gulp-ignore');
gulp.task('task', function() {
gulp.src('./**/*.js')
.pipe(gulpIgnore.exclude(condition))
.pipe(gulp.dest('./dist/'));
});
If you want to use #OverZealous' answer (https://stackoverflow.com/a/21806974/1019307) in Typescript, you need to import instead of require:
import * as debug from 'gulp-debug';
...
return gulp.src('./examples/*.html')
.pipe(debug({title: 'example src:'}))
.pipe(gulp.dest('./build'));
(I also added a title).