Gulp Nunjucks: Case insensitiv include? - gulp

I have a large project built on windows which uses loads of includes written in uppercase
{% include 'TEMPLATE.html' %}
but the files are named in lowercase template.html
Now the project won't build on Linux ... Is there a way to fix this in the gulpfile nunjucks.compile()?
Thanks

If gulp doesn't have the required option, you can use a custom loader or override include-tag.
Template test.html: TEST - {{result or 'Failed'}}
const nunjucks = require('nunjucks');
const fileLoader = new nunjucks.FileSystemLoader('views')
const MyLoader = nunjucks.Loader.extend({
getSource: path => fileLoader.getSource(path.toLowerCase())
});
const env = new nunjucks.Environment(new MyLoader(), {autoescape: true});
const html = env.render('TEST.html', {result: 'OK'});
console.log(html);

Related

Browser not reloading after gulp completes building the SPFx solution

The following is the gulp.js content created by the Yeomen SPFx generator.
'use strict';
const build = require('#microsoft/sp-build-web');
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
var getTasks = build.rig.getTasks;
build.rig.getTasks = function () {
var result = getTasks.call(build.rig);
result.set('serve', result.get('serve-deprecated'));
return result;
};
build.initialize(require('gulp'));
After the gulp does a build it used to automatically refresh, but the new gulp.js generated by the generator doesn't.
Though I found many examples using browser-sync, I'm not sure which one to use.
What is the right way to automatically refresh/reload the browser once the gulp is done with it's tasks?.

gulp: set multiple gulp.src and respective gulp.dest (on gulp-sass example)

Project structure:
📁 development
 📁 public
  📁 pug
  📁 1sass
  📁 2css
 📁 admin
  📁 pug
  📁 3sass
  📁 4css      
I add digits to folder names to imitate the situations when gulp can not guess somehow which output folder is respects to input ones.
Now, I want to compile .sass files in public/1sass and admin/3sass to .css and put it in public/2css and admin/4css respectively:
📁 public/1sass → 📁 public/2css
📁 admin/3sass → 📁 admin/4css
How I need to setup the sass task in gulpfile? Even if we put the paths array to gulp.src, how gulp will understand which output path respects to input ones?
Maybe gulp.parallel() becomes available in gulp 4.x will do?
Update
Two things that I did not understand yet:
How I should to setup the multiple output paths in gulp.dest()?
I learned that file.dirname = path.dirname(file.dirname); removes the last parent directory of the relative file path.But how I should to setup it for each of 1sass ans 3sass? Via array?
const gulp = require('gulp'),
sass = require('gulp-sass'),
path = require('path'),
rename = require('gulp-rename');
gulp.task('sass', function(){
return gulp.src([
`development/public/1sass/*.sass`,
`development/public/3sass/*.sass`])
.pipe(sass())
// As I can suppose, here we must to setup output paths for each input one
.pipe(rename(function(file){
file.dirname = path.dirname(file.dirname);
}))
.pipe(/* ??? */);
});
Simply in case of dynamic src and you want respective same dest (as received in src) then you can use following
Example Suppose we have array of scss file:
var gulp = require('gulp');
var sass = require('gulp-sass');
var scssArr = [
'src/asdf/test2.scss',
'src/qwerty/test1.scss'
];
function runSASS(cb) {
scssArr.forEach(function(p){
gulp.src(p, {base:'.'})
.pipe(sass({outputStyle: 'compressed'}))//outputStyle is optional or simply sass()
.pipe(gulp.dest('.')); //if othe folder including src path then use '/folder-name' instead of '.', so output path '/folder-name/{src-received-path}'
})
cb();
}
exports.runSASS = runSASS; // gulp runSASS
Run command gulp runSASS This will create following files:
src/asdf/test2.css
src/qwerty/test1.css
Happy Coding..
See my answer to a similar question: Gulp.dest for compiled sass. You should be able to modify that easily for your purposes. If you have trouble edit your question with your code and you will get help.
Even if we put the paths array to gulp.src, how gulp will understand which output path respects to input ones?
Gulp will retain the relative paths for each file that it processes. So, in your case, the files in public/1sass will all have their relative path info after sass processing still intact. And the files in admin/3sass will all have their relative path info as well. Thus you only need to find a way to modify that path info (parent directory structure) to redirect the files to a desired destination.
In your case, that would involve removing the immediate parent directory and replacing it with the 'css' directory. Gulp-rename is one way, not the only way, to do that. In gulp-rename you can examine and modify the parent directory structure - it is just string manipulation.
Maybe gulp.parallel() becomes available in gulp 4.x will do?
No, gulp.parallel() will not be of any help here. It will just order the execution and finishing of different tasks. It would not be necessary or of any real help in your case.
[EDIT]
var gulp = require("gulp");
var rename = require("gulp-rename");
var path = require("path");
var sass = require("gulp-sass");
gulp.task('modules-sass', function () {
// using .scss extensions for sass files
return gulp.src(`development/**/*.scss`)
.pipe(sass())
.pipe(rename(function (file) {
// file.dirname before any changes
console.log("file.dirname 1 = " + file.dirname);
// this removes the last directory
var temp = path.dirname(file.dirname);
console.log(" temp = " + temp);
// now add 'Css' to the end of the directory path
file.dirname = path.join(temp, 'Css');
console.log(" after = " + file.dirname);
}))
.pipe(gulp.dest('development'));
});
// this is the directory structure I assumed
// gulpfile.js is just above the 'development' directory
// development / Admin / Sass1 / file1.scss
// development / Admin / Sass1 / file2.scss
// development / Admin / Sass2 / file3.scss
// development / Admin / Sass2 / file4.scss
// development / Admin / Css
// development / Public / Sass1 / file5.scss
// development / Public / Sass1 / file6.scss
// development / Public / Sass2 / file7.scss
// development / Public / Sass1 / file8.scss
// development / Public / Css

gulp polymer-build not generating expected bundle?

I have the following gulp task (please see below), which I'm trying to run to automate the polymer build. However, all I'm seeing in the resulting /build folder is an index.html. No dependencies, and I was under the impression that the resulting file would be called shared-bundle.html. Also, it's not fetching any of my bower dependencies:
const PolymerProject = require('polymer-build').PolymerProject;
const project = new PolymerProject(require('./polymer.json'));
gulp.task('build', () => {
mergeStream(project.sources(), project.dependencies())
.pipe(project.bundler())
.pipe(gulp.dest('./build/'));
});
This is the documentation I was referencing: https://www.npmjs.com/package/polymer-build
Any ideas what I might be missing?
Apparently I was just missing the entrypoint param here:
const project = new PolymerProject({entrypoint: 'my-page.html'});

how to modify config files using gulp

I use gulp to configure complex local setup and need to auto-edit files.
The scenario is:
determine if certain file contains certain lines after certain other line (found using regular expression)
if line is not found, insert the line.
optionally, delete some lines found in the file.
I need this to amend system configuration files and compile scenarios.
What would be the best way to do it in gulp?
Gulp is plain javascript. So what I would do if I were you is to create a plugin to pipe to the original config file.
Gulp streams emit Vinyl files. So all you really got to do is to create a "pipe factory" that transforms the objects.
It would look something like this (using EventStream):
var es = require('event-stream');
// you could receive params in here if you're using the same
// plugin in different occasions.
function fixConfigFile() {
return es.map(function(file, cb) {
var fileContent = file.contents.toString();
// determine if certain file contains certain lines...
// if line is not found, insert the line.
// optionally, delete some lines found in the file.
// update the vinyl file
file.contents = new Buffer(fileContent);
// send the updated file down the pipe
cb(null, file);
});
}
gulp.task('fix-config', function() {
return gulp.src('path/to/original/*.config')
.pipe(fixConfigFile())
.pipe(gulp.dest('path/to/fixed/configs');
});
Or you can use vinyl-map:
const map = require('vinyl-map')
const gulp = require('gulp')
const modify = map((contents, filename) => {
contents = contents.toString()
// modify contents somehow
return contents
})
gulp.task('modify', () =>
gulp.src(['./index.js'])
.pipe(modify)
.pipe(gulp.dest('./dist'))
})

How do I pull multiple JSON files into SWIG on Node.js?

This is actually two questions...
I have a single SWIG template (index.html) that I would like to pull multiple JSON files into for compiling using Node.js. An "index.json" file with variables that pertain just to that page, then a "common.json" file that contains a set of common variables that I would like to use across the entire system.
I also then have a "header.html" template and a "footer.html" template inside "index.html". How would I get them to each pull their own "header.json" and "footer.json" files respectively?
Ultimately, I am trying to get this all working within GULP-SWIG since we already have a GULP process running at all times for the rest of the project.
UPDATE: GULP-SWIG automatically looks for a JSON file with the same name and processes it, but there is no documentation on including additional JSON files.
I tried it this way:
// Include gulp
var gulp = require('gulp');
// Include Our Plugins
var swig = require('gulp-swig');
// Swig Variables
var common = require('./json/common.json'); // <--- NEW CODE
var optEng = {
load_json: true,
json_path: 'json/',
data: {
locale: 'en_US',
currencyval: 'USD'
}
};
// Tasks
gulp.task('swig-eng', function() {
gulp.src('templates/*.html')
.pipe(swig(common)) // <--- NEW CODE
.pipe(swig(optEng))
.pipe(gulp.dest('./compiled/'));
});
gulp.task('watch', function() {
gulp.watch('templates/*.html', ['swig-eng']);
gulp.watch('includes/*.html', ['swig-eng']);
gulp.watch('json/*.json', ['swig-eng']);
});
gulp.task('build', ['swig-eng', 'watch']);
And I tried it this way:
// Include gulp
var gulp = require('gulp');
// Include Our Plugins
var swig = require('gulp-swig');
// Swig Variables
var optEng = {
common: require('./json/common.json'), // <--- NEW CODE
load_json: true,
json_path: 'json/',
data: {
locale: 'en_US',
currencyval: 'USD'
}
};
// Tasks
gulp.task('swig-eng', function() {
gulp.src('templates/*.html')
.pipe(swig(optEng))
.pipe(gulp.dest('./compiled/'));
});
gulp.task('watch', function() {
gulp.watch('templates/*.html', ['swig-eng']);
gulp.watch('includes/*.html', ['swig-eng']);
gulp.watch('json/*.json', ['swig-eng']);
});
gulp.task('build', ['swig-eng', 'watch']);
I have created a ZIP file containing the required file structure:
https://www.dropbox.com/s/psxsdn31rd5177h/Gulp-Swig%20Sample.zip
The gulpfile.js file is the ONLY file that should need to be updated.
require them
You can just require the json files and pass them as local variables to swig
swig.renderFile('/path/to/template.html', {
common: require('path/to/your/common.json'),
index: require('path/to/your/index.json')
// etc
});
Supossing you are...
"including" your header and footer templates as partials, i.e.
index.swig.html
{# ... #}
{% include "header.swig.html" %}
{# ... #}
{% include "footer.swig.html" %}
{# ... #}
They will receive all the local variables, unless you specify a with *whatever* only statement. Check the include docs for further understanding.
{% include "./partial.html" with my_obj only %}
You can...
require all your json files and pass them as local variables, specifying the objects you want to pass into.
swig.renderFile('/path/to/index.swig.html', {
common: require('path/to/your/common.json'),
index: require('path/to/your/index.json'),
header: require('path/to/your/header.json'),
footer: require('path/to/your/footer.json')
// etc
});
And on index.swig.html...
{# ... #}
{% include "header.swig.html" with header only %}
{# ... #}
{% include "footer.swig.html" with footer only %}
{# ... #}
You can use the setup option in gulp-swig which gives you direct access to the swig object. Once you have access, you can read the Swig documentation on how to pass data. Here's an example:
var opts = {
setup: function(swig) {
swig.setDefaults({
locals: {
common: require('path/to/your/common.json'),
header: require('path/to/your/header.json'),
footer: require('path/to/your/footer.json')
}
});
}
};
gulp.task('templates', function() {
gulp.src('./lib/*.html')
.pipe(swig(opts))
.pipe(gulp.dest('./dist/'))
});