Change dest folder for gulp - 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!

Related

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 }));
});

Creating a style guide / pattern library with gulp

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.

gulp-changed has different behaviours

In my website build-process, I use gulp-changed to prevent doing all task if unnecessary. However, sometimes it has different behaviours even if declarations are similar.
Does anyone know what I am doing wrong?
case 1 : building htlm / php using partials.
works fine! the task process only the first time, if I run it twice in a row
gulp.task('pages', function () {
var toBuild = src + config.pages.src_pages; // many php/html files
var partials = src + config.pages.src_partials; // "to be included"
var DEST = target;
return gulp.src([toBuild, "!" + partials])
.pipe(changed(DEST))
.pipe(fileinclude({ prefix: '##', basepath: '#file' }))
.pipe(size())
.pipe(gulp.dest(DEST));
});
case 2 : building a SVG sprite from multiple svg files.
doesn't work! the task runs again if I run it twice in a row
gulp.task('vector', function () {
var DEST = target + config.assets.images.vector_dest;
var configsvg = { // ... config stuff // };
return gulp.src(src + config.assets.images.vector_src)
.pipe(changed(DEST))
.pipe(svgo())
.pipe(svgSprite(configsvg)).on('error', function (error) {
console.log(error);
})
.pipe(size())
.pipe(gulp.dest(DEST));
});
The solution is to use gulp-newer module in case of "many to one" file compilation (concatenation etc...)
Thank you to Lim H.
gulp-newer vs gulp-changed
May I also 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
}

Prevent intermediate compass file output when piping

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.

Glob /* doesn't match files starting with dot

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/**/{,.,.*/**/,.*/**/.}*.