gulp task that dynamically create folder with name based on file name - node.js

I have the following gulp task that is currently not working.
gulp.task('emails', function() {
gulp.src('views/emails/src/**/*.html')
.pipe(inky())
.pipe(gulp.dest('views/emails/dist/'+debug()+"/html.ejs"));
});
I would like to iterate over the /views/emails/src/ directory, find all html files, then use inky to convert them to html, and then copy the resulting html file to...
views/emails/dist/'+ folderName +"/html.ejs
where folderName is the name of the .html file that was processed.
I need this in order to get the file structure in the format that the npm email-templates package requires.

That's a job for gulp-rename:
var rename = require('gulp-rename');
var path = require('path');
gulp.task('emails', function() {
gulp.src('views/emails/src/**/*.html')
.pipe(inky())
.pipe(rename(function(file) {
file.dirname = path.join(file.dirname, file.basename);
file.basename = 'html';
file.extname = '.ejs';
}))
.pipe(gulp.dest('views/emails/dist/'));
});

Related

Lambda ENOENT: no such file or directory

I am trying to read a file .yml inside an AWS Lambda function (Node 6.10.0).
console.log(__dirname + '/gameOptions.yml');
console.log(path.resolve('./gameOptions.yml'));
console.log(path.resolve('/gameOptions.yml'));
console.log('./gameOptions.yml');
console.log(process.cwd() + '/api/lib/gameOptions.yml');
let doc = yaml.safeLoad(fs.readFileSync(path.resolve('./gameOptions.yml'), 'utf8'));
I have tried all possibles ways to do it, but always get ENOENT: no such file or directory.
The file is at the same folder and it is an .yml so require('') also doesnt work.
The results for the above code are:
/Users\marcus\Documents\Workspace\proak-api\proak-api\api\lib/gameOptions.yml
/var/task/gameOptions.yml
/gameOptions.yml
./gameOptions.yml
/var/task/api/lib/gameOptions.yml
And it works locally.
To solve this you need to care of two things:
Optimize
If you are using something to minify the code, E.g. serverless-plugin-optimize:
Include the file to not be minified.
myLambda:
handler: mySubFolder/myLambda.handler
optimize:
includePaths: ['mySubFolder/myFile.json']
Resolve the path.
path.resolve(process.env.LAMBDA_TASK_ROOT, '_optimize', process.env.AWS_LAMBDA_FUNCTION_NAME, 'mySubFolder/myFile.json')
If you dont use minify, you also need to require the .yml file into the Lambda, to compile into the function.
Require require('file.yml') gives you an error. So you let to:
var fs = require('fs')
, yaml = require('js-yaml');
require.extensions['.yaml'] =
require.extensions['.yml'] = function(module, filename) {
var content = fs.readFileSync(filename, 'utf8');
// Parse the file content and give to module.exports
content = yaml.load(content);
module.exports = content;
};

gulp - wrap plugin (which uses through2) output with string

I would like to know how exactly can I manipulate the output of my Gulp plugin so, for example, no matter how many files are passed to the plugin, it will wrap the output with a string. Currently I cannot know when does the last file is done.
The super simplified example below will iterate on 3 files and will create a new file named output.js and in it there will be three times the string xxx (xxxxxxxxx).
I would like the plugin itself to wrap the contents so the output will
be: +xxxxxxxxx+.
How can I do this?
Thanks!
Gulpfile
var gulp = require('gulp');
var concat = require('gulp-concat');
var foo = require('./index');
gulp.task('default', function() {
gulp.src([a.html, b.html, c.html])
.pipe(foo())
.pipe(concat('output.js'))
.pipe(gulp.dest('./test/output'))
});
The most basic gulp plugin (index.js):
var through2 = require('through2'),
gutil = require('gulp-util');
var PLUGIN_NAME = 'foo';
module.exports = function( options ){
// through2.obj(fn) is a convenience wrapper around
// through2({ objectMode: true }, fn)
return through2.obj(function( file, enc, callback ){
file.contents = new Buffer( 'xxx' );
this.push(file);
callback();
});
}
I understand the files are currently simply returned modified, but what I don't understand is how to append text and return the concatenated result that I want, while keeping it OK with Gulp working standards.
The "real" plugin should actually wrap the files results with:
var foo = { FILES_CONTENT }
where FILES_CONTENT will actually be a a concatenated string of all the files:
"file_name" : "file_content",
"file_name" : "file_content",
...
I would make the following changes to your gulpfile.js:
var gulp = require('gulp');
var foo = require('./index.js');
gulp.task('default', function() {
return gulp.src(['a.html', 'b.html', 'c.html'])
.pipe(foo({fileName:'output.js', varName:'bar'}))
.pipe(gulp.dest('./test/output'))
});
Since your foo() plugin itself will concatenate all the files, there's no need to use gulp-concat at all. Instead your plugin should accept an option fileName that provides the name of the generated file. I've also added another option varName that will provide the name of the var in the output file.
I'll assume that a.html, b.html and c.html are simple HTML files, something like this:
<h1 class="header">a</h1>
As you've already realized you need to concat all the files in the plugin itself. That's not really difficult however and doesn't require a lot of code. Here's a index.js which does exactly that:
var through2 = require('through2'),
gutil = require('gulp-util'),
path = require('path'),
File = require('vinyl');
var PLUGIN_NAME = 'foo';
module.exports = function(options) {
var files = { };
var outputFile = null;
return through2.obj(function(file, enc, callback){
outputFile = outputFile || file;
var filePath = path.relative(file.base, file.path);
files[filePath] = file.contents.toString();
callback();
}, function(callback) {
outputFile = outputFile ? outputFile.clone() : new File();
outputFile.path = path.resolve(outputFile.base, options.fileName);
outputFile.contents = new Buffer(
'var ' + options.varName + ' = ' +
JSON.stringify(files, null, 2) + ';'
);
this.push(outputFile);
callback();
});
}
Since you want to output a key/value mapping from file names to file contents our transformFunction just stores both of those things in a regular JavaScript object files. None of the input files themselves are emitted. Their names and contents are just stored until we have all of them.
The only tricky part is making sure that we respect the .base property of each file as is customary for gulp plugins. This allows the user to provide a custom base folder using the base option in gulp.src().
Once all files have been processed through2 calls the flushFunction. In there we create our output file with the provided fileName (once again making sure we respect the .base property).
Creating the output file contents is then just a matter of serializing our files object using JSON.stringify() (which automatically takes care of any escaping that has to be done).
The resulting ./test/output/output.js will then look like this:
var bar = {
"a.html": "<h1 class=\"header\">a</h1>\n",
"b.html": "<h1 class=\"header\">b</h1>\n",
"c.html": "<h1 class=\"header\">c</h1>\n"
};
You should use the gulp pipeline technique (standard).
This means that you can use the gulp-insert package in order
to add the string xxx.
var insert = require('gulp-insert');
.pipe(insert.append('xxx')); // Appends 'xxx' to the contents of every file
You can also prepend, append and wrap with this package and it support of course the gulp standards.
So the full example will be:
var gulp = require('gulp');
var concat = require('gulp-concat');
var foo = require('./index');
var insert = require('gulp-insert');
gulp.task('default', function() {
gulp.src([a.html, b.html, c.html])
.pipe(foo()
.pipe(insert.append('xxx'))
.pipe(concat('output.js'))
.pipe(gulp.dest('./test/output'))
});

Gulp copy single file (src pipe dest) with wildcarded directory

I am trying to copy a specific file src C:\Project\dir1\dirv-1.0.0\tools\file.exe to a specific directory dest C:\Project\dir2\ using gulp.
The version number in dirv-1.0.0 could change in the future, so I want to wildcard the version number.
Here is the task I have for that (gulpfile.js is in C:\Project):
gulp.task('copy', function(){
return gulp
.src('dir1\dirv-*\tools\file.exe')
.pipe(gulp.dest('dir2'));
});
This ends up generating the following dest file: C:\Project\dir2\dirv-1.0.0\tools\file.exe. What I want is C:\Project\dir2\file.exe.
How do I do this gulp copy task so that I can wildcard the src path but only copy file.exe to the dest path?
Use gulp-flatten
var gulp = require('gulp');
var flatten = require('gulp-flatten');
gulp.task('default', function(){
return gulp.src('./dir1/dirv-*1/test.txt')
.pipe(flatten())
.pipe(gulp.dest('dir2'));
});

Can you gulp clean all files in a directory except for a single file?

Is there a way to use gulp-clean such that instead of passing in the files or directories I want to delete, to delete everything that does not match a specific file name in the directory?
For example, If I have 3 files in directory "dir":
dir/a.js
dir/b.js
dir/c.js
Sample Pseudocode of what I want to do, (delete everything in /dir/ thats not a.js:
gulp.src('!./dir/a.js').pipe(clean());
This should work:
var gulp = require('gulp');
var del = require('del');
gulp.task('clean', function(cb) {
del(['dir/**/*', '!dir/a.js'], cb);
});
If the excluded file is in a sub directory you need to exclude that dir from deletion. For example:
del(['dir/**/*', '!dir/subdir', '!dir/subdir/a.js'], cb);
or:
del(['dir/**/*', '!dir/subdir{,/a.js}'], cb);
gulp-filter can be used to filter files from a gulp stream:
var gulp = require('gulp');
var filter = require('gulp-filter');
gulp.src('**/*.js')
.pipe(filter(['*', '!dir/a.js']))
.pipe(clean());

How to rename all files in a folder using gulp js?

I have a bunch of html files in a partials directory. Using gulp js, I want to minify and rename these files to .min.html. Please show me how to achieve this.
See here, using gulp-rename, if you just want to rename the files.
Something in the line of below should do:
var rename = require('gulp-rename');
gulp.src("./partials/**/*.hmtl")
.pipe(rename(function (path) {
path.suffix += ".min";
}))
.pipe(gulp.dest("./dist"));
In order to minify, you can use gulp-htmlmin. Pretty straightforward from the documentation:
var htmlmin = require('gulp-htmlmin');
gulp.task('compress', function() {
gulp.src('./partials/**/*.html')
.pipe(htmlmin())
.pipe(gulp.dest('dist'))
});
You can certainly combine the two to obtain the desired effect.

Resources