Use .styl file as dependency to compile another - gulp

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

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!

Gulp task to only compile files that have changed

I need to write a gulp task that will only compile those Typescript files that have actually changed and came up with this:
var gulp = require('gulp');
var print = require('gulp-print');
var newer = require('gulp-newer');
var ts = require('gulp-typescript');
gulp.task('compile:ts', function () {
return gulp.src([
'typings/browser.d.ts',
'app/**/*.ts'
])
.pipe(newer('app'))
.pipe(print(function (filepath) {
return 'Compiling ' + filepath + '...';
}))
.pipe(ts({
target: 'es5',
module: 'commonjs',
moduleResolution: 'node',
sourceMap: true,
emitDecoratorMetadata: true,
experimentalDecorators: true,
removeComments: false,
noImplicitAny: false
}))
.pipe(gulp.dest('app'));
});
However, this task doesn't find any modified files although there are .ts files with more recent timestamps than their .js counterpart.
Where did I go wrong?
However, this task doesn't find any modified files although there are .ts files with more recent timestamps than their .js counterpart.
That's because you're not telling gulp-newer to compare .ts files with .js files. You're comparing .ts files with themselves, so there is no change to be detected.
You need to tell gulp-newer to compare each .ts file with its .js counterpart:
.pipe(newer({dest:'app',ext:'.js'}))
There is an easier method of compiling files when they change. Using gulp watch, you can run the function once and whenever you save a change, it'll run the compiling function.
gulp.task('watch', function() {
gulp.watch(['ts/filepaths','more/ts/filepaths'],
['compile:ts','otherFunctionsIfNeeded']);
});
If you rewrite compile:ts to only compile, using the function above, whenever you save a ts file, it will compile it for you

Gulp uglify - overwrite uglified files

I have a gulp task to uglify my JS:
gulp.task('uglify', ['eslint'], () => {
return gulp.src(jsDest + '/*.js')
.pipe(rename({suffix: '.min'}))
.pipe(stripDebug())
.pipe(uglify())
.pipe(gulp.dest(jsDest));
});
It works fine, but as I am using a wildcard to identify JS files, I end up with new files named name.min.min.js rather than existing minified files being overwritten.
A work around I have come up with is to have an additional task which cleans out these files before I uglify again:
gulp.task('cleanUglified', () => {
return del.sync('dist/js/*.min.js');
});
gulp.task('uglify', ['cleanUglified', 'eslint'], () => {
...
});
While this works fine, I'm sure there must be a way to have my task ignore anything named *.min* and in fact overwrite any that already exist.
Solved - I can ignore the already minified files and overwrite them by using this pattern to select the files to uglify:
return gulp.src(jsDest + '/*[^.min].js')
EDIT
Following the below comments, I have updated to:
return gulp.src(['*.js', '!*.min.js'])

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-html-minify .pipe destination to original folder structure

Hello people of the North, I am trying to minify my HTML using gulp because https://developers.google.com/speed/pagespeed/insights is telling me my site is too slow.
My original html files are in the structure of
/app/blog/page1.html
/app/contact/contactus.html
/app/xxx/xxx.html
With my current code the gulp output puts all of the html files into the _build folder, but this wont work for me since, on page load it will look for the html in the respective folder. Should I / can I put the minified html in its original folder so it is referenced automatically as normal?
gulp.task('minify-html', function () {
return gulp.src(configHTML.src)
.pipe(angularify())
.pipe(minifyHTML())
.pipe(gulp.dest('_build/'));
});
It's possible, you should try changing your code for:
gulp.src(configHTML.src, { base: "." })
.pipe(htmlmin({ collapseWhitespace: true, minifyCSS: true, minifyJS: true }))
.pipe(gulp.dest("."))
this will minify those files itself