Glob /* doesn't match files starting with dot - gulp

I'm using gulp to copy all files from one dir to another using code like this:
gulp.src([ 'app/**/*' ]).pipe(gulp.dest('dist'));
Glob docs say * match all files, but in fact files which have names starting with dot, like .gitignore, are not copied.
How can it be worked around?

If you add the option dot: true, it should work. Eg:
gulp.task('something', function () {
return gulp.src([ 'app/**/*' ], {
dot: true
}).pipe(gulp.dest('dist'));
});
Reference

For instances where the glob pattern is the only available interface. This pattern will do the trick:
**/{,.,.*/**/,.*/**/.}*
This expands to become the following globs:
**/*
**/.*
**/.*/**/*
**/.*/**/.*
You can add app to the beginning for app/**/{,.,.*/**/,.*/**/.}*.

Related

Change dest folder for gulp

I'm using the plugin gulp-nunjucks-render with gulp as following:
gulp.task("nunjucks", () => {
return gulp
.src(src_folder + "pages/**/*.njk", {
base: src_folder,
since: gulp.lastRun("nunjucks"),
})
.pipe(plumber())
.pipe(
data(() =>
JSON.parse(fs.readFileSync(src_folder + "datas/dist/data.json"))
)
)
.pipe(nunjucks())
.pipe(beautify.html({ indent_size: 2 }))
.pipe(gulp.dest(dist_folder))
.pipe(browserSync.stream());
});
I want the generated html files to be inside the dist_folder and not inside dist_folder + "pages".
How can I achieve that?
You probably just need .pipe(dest('dist_folder')) appending as per these docs: https://gulpjs.com/docs/en/api/dest/
gulp.task("nunjucks", () => {
return gulp
.src(src_folder + "pages/**/*.njk", {
base: src_folder,
since: gulp.lastRun("nunjucks"),
})
.pipe(plumber())
.pipe(
data(() =>
JSON.parse(fs.readFileSync(src_folder + "datas/dist/data.json"))
)
)
.pipe(nunjucks())
.pipe(beautify.html({ indent_size: 2 }))
.pipe(gulp.dest(dist_folder))
.pipe(browserSync.stream())
.pipe(dest('dist_folder'));
});
You want to remove the pages directory so as mentioned here glob-base, pages needs to be part of your base:
A glob base - sometimes called glob parent - is the path segment
before any special characters in a glob string. As such, the glob base
of /src/js/**.js is /src/js/.
Vinyl instances generated by src() are constructed with the glob base
set as their base property. When written to the file system with
dest(), the base will be removed from the output path to preserve
directory structures.
It is naturally part of your base (it is before the globstar ** in your src) so if you remove the base property that you added you will get the behaviour you wanted since
"When written to the file system with
dest(), the base will be removed from the output path".
Gulp will automatically set the base to src_folder + "pages" if you remove the base option that you set.
Alternatively, if you do want to specifically set the base property you could use this:
return gulp
.src(src_folder + "pages/**/*.njk", {
base: src_folder + "pages",
since: gulp.lastRun("nunjucks"),
})
...
which in your specific case does exactly the same thing as not setting the base property at all!

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?

Use .styl file as dependency to compile another

I have two files:
1 - common.styl (this file has imports that will be used on all pages of my project.)
#import 'utils/variables.styl'
#import 'utils/fonts.styl'
#import 'utils/mixin.styl'
2 - home.styl (this file is only for home section of my project and depends on common.styl)
body
font-family CoolDown
.box
background $commonBg
In my gulpfile I've created two tasks, one to compile the common.styl and another to compile all the pages of my project.
Common task:
gulp.task('commonCSS', function () {
return gulp.src('src/styles/common.styl')
.pipe($.plumber())
.pipe($.stylus({
'include css': true,
use: [jeet(), nib(), rupture()],
import: ['jeet', 'nib', 'rupture']
}))
.pipe($.autoprefixer(stylBrowsers))
.pipe(gulp.dest(paths.build + 'css'))
.pipe(reload({ stream: true }));
});
My problem is the pages task, this only works if I put the common.styl file in the src path and concat them. But doing this way I need to put a name in the file. I would like to use the name of the current .styl being compiled.
gulp.task('pagesCSS', ['commonCSS'], function () {
return gulp.src(['src/styles/common.styl', 'src/styles/pages/**/*.styl'])
.pipe($.plumber())
.pipe($.concat('**page.css**')
.pipe($.stylus({
'include css': true,
use: [ jeet(), nib(), rupture() ],
import: ['jeet', 'nib', 'rupture']
}))
.pipe($.autoprefixer(stylBrowsers))
.pipe($.minifyCss())
.pipe(gulp.dest(paths.build + 'css'))
.pipe(reload({ stream: true }));
});
The question is: There is a way to include the common.styl to be used by pagesCSS task?
Maybe I'm missing something or using the wrong solution here.
Can't you just #import or #require common.styl in those files? #import "../../common" and Stylus will include them for every page, no need for concat.
Or...
You can use import option you're already have in your config object. Stylus will include common.styl at the beginning of each file by itself.
First add paths: ['node_modules', 'src/styles']. This way Stylus will know how to resolve paths for imports. You can probably skip this step if you provide full path in next one.
Now you can add your common.styl to import: ['jeet', 'nib', 'rupture', 'common'].
I'm using this configuration for my variables so I don't have to include them in each file.
Full example should look somewhat like that:
gulp.task('pagesCSS', ['commonCSS'], function () {
return gulp.src('src/styles/pages/**/*.styl') // <-- only pages styles are piped
.pipe($.plumber())
// .pipe($.concat('**page.css**') // <-- remove this line
.pipe($.stylus({
'include css': true,
use: [ jeet(), nib(), rupture() ],
paths: ['node_modules', 'src/styles'] // <-- resolve your styles path
import: ['jeet', 'nib', 'rupture', 'common'] // <-- add your shared file
}))
.pipe($.autoprefixer(stylBrowsers))
.pipe($.minifyCss())
.pipe(gulp.dest(paths.build + 'css'))
.pipe(reload({ stream: true }));
});

In Gulp, how do I only run a task on one file if any of multiple files are newer?

I'm probably trying to make gulp do something that's not idiomatic, but here goes.
I want my build task to only run if the source files are newer than the output file.
In gulp, it seems standard practice to create a build task that always runs, and then set up a watch task to only run that build task when certain files change. That's okay, but it means that you always build on the first run.
So, is it possible to do what I want? Here's what I've got so far (newer is gulp-newer):
gulp.task('build_lib', function() {
return gulp.src(["app/**/*.ts"])
.pipe(newer("out/outputLib.js")) //are any of these files newer than the output?
** NEED SOMETHING HERE **
how do I say, "If I got _any_ files from the step before, replace all of them with a single hardcoded file "app/scripts/LibSource.ts" "?
.pipe(typescript({
declaration: true,
sourcemap: true,
emitError: false,
safe: true,
target: "ES5",
out: "outputLib.js"
}))
.pipe(gulp.dest('out/'))
});
I tried using gulpif, but it doesn't seem to work if there are no files going into it to begin with.
.pipe(gulpif(are_there_any_files_at_all,
gulp.src(["app/scripts/LibSource.ts"])))
However, my condition function isn't even called because there are no files on which to call it. gulpif calls the truthy stream in this case, so LibSource gets added to my stream, which isn't what I want.
Maybe doing all of this in a single stream really isn't the right call, since the only reason I'm passing those files through the "gulp-newer" filter is to see if any of them is newer. I'm then discarding them and replacing them with another file. My question still stands though.
You can write your own through/transform stream to handle the condition like so:
// Additional core libs needed below
var path = require('path');
var fs = require('fs');
// Additional npm libs
var newer = require('gulp-newer');
var through = require('through');
var File = require('vinyl');
gulp.task('build_lib', function() {
return gulp.src(["app/**/*.ts"])
.pipe(newer("out/outputLib.js"))
.pipe(through(function(file) {
// If any files get through newer, just return the one entry
var libsrcpath = path.resolve('app', 'scripts', 'LibSource.ts');
// Pass libsrc through the stream
this.queue(new File({
base: path.dirname(libsrcpath),
path: libsrcpath,
contents: new Buffer(fs.readFileSync(libsrcpath))
}));
// Then end this stream by passing null to queue
// this will ignore any other additional files
this.queue(null);
}))
.pipe(typescript({
declaration: true,
sourcemap: true,
emitError: true,
safe: true,
target: "ES5",
out: "outputLib.js"
}))
.pipe(gulp.dest('out/'));
});
I know like, this question was posted over 4 years ago, however; I am sure this problem crosses the path of everyone, and although I think I understand the question that is being asked, I feel that there is an easier way to perform this task, off which, I posted a similar question recently on stackoverflow at New to GULP - Is it necessary to copy all files from src directory to dist directory for a project?
It uses gulp-changed, and for me, it worked like a charm, so for others who may look at this post for similar reasons, have a look at my post and see if it is what you are looking for.
Kind Regards
You don't need to build first. You can on your 'first run' only run the watch task from which you run all the other ones.
example:
// Create your 'watch' task
gulp.task( 'watch', function() {
gulp.watch( 'scripts/*.js', [ 'lint', 'test', 'scripts' ] );
gulp.watch( 'styles/sass/*.scss', [ 'sass_dev' ] );
} );
// On your first run you will only call the watch task
gulp.task( 'default', [ 'watch' ] );
This will avoid running any task on startup. I hope this will help you out.
May I suggest gulp-newy in which you can manipulate the path and filename in your own function. Then, just use the function as the callback to the newy(). This gives you complete control of the files you would like to compare.
This will allow 1:1 or many to 1 compares.
newy(function(projectDir, srcFile, absSrcFile) {
// do whatever you want to here.
// construct your absolute path, change filename suffix, etc.
// then return /foo/bar/filename.suffix as the file to compare against
}