I am using gulp to processes pages for a site, some of these pages are php files. The problem is that after all the pages are run through the template engine they have a .html
file extension. I am adding a property to the file that designates if it's supposed to be a file besides html and then renaming the file to match. However, for some reason gulp-rename keeps saying that the variable I am using to store the extension is undefined
.
Corresponding task in gulpfile.js:
var gulp = require('gulp'),
gutil = require('gulp-util'),
lodash = require('lodash'),
data = require('gulp-data'),
filesize = require('gulp-filesize'),
frontMatter = require('gulp-front-matter'),
rename = require('gulp-rename'),
util = require('util');
gulp.task('metalsmith', function(){
var ext; //Variable to store file extension
return gulp.src(CONTENT_DIR)
.pipe(frontMatter()).on("data", function(file){
lodash.assign(file, file.frontMatter);
delete file.frontMatter;
})
.pipe(data(function(file){ //ext is defined here
if(typeof file.filetype === 'undefined'){
ext = {extname: '.html'};
}else{
ext = {extname: file.filetype};
}
}))
.pipe(tap(function(file){
console.log(ext); //when I print to the console, ext is defined and correct
}))
.pipe(rename(ext)) //ext is undefined
.pipe(gulp.dest(BUILD_DIR))
});
when I run the above it errors with Unsupported renaming parameter type supplied
.
Also I have tried it having options obj on the same line as rename()
, with ext
only storing the file extension eg: .pipe(rename({extname: ext}))
which causes the files to have undefined added as the extension (instead of phpfile.php
the below md
file would be named phpfileundefined
)
yaml in phpfile.md
---
layout: php.hbt
filetype: ".php"
title: "php"
---
package.json
"devDependencies": {
"gulp": "^3.9.1",
"gulp-data": "^1.2.1",
"gulp-filter": "^4.0.0",
"gulp-front-matter": "^1.3.0",
"gulp-rename": "^1.2.2",
"gulp-util": "^3.0.7",
"lodash": "^4.11.1"
}
Your problem is that by the time you execute rename(ext)
the value of ext
is still undefined
because your data(...)
code hasn't run yet.
Gulp plugins work like this:
rename(ext)
..pipe()
.pipe()
calls have been executed does you stream start running.So rename(ext)
is a function call that is used to construct the stream itself. Only after the stream has been constructed can the stream start running.
However you set value of ext
only once the stream is running. You need the value of ext
before that when you are constructing the stream.
The easiest solution in your case is to simply do the renaming manually in your data(...)
function instead of relying on gulp-rename
. You can use the node.js built-in path
module for that (which is what gulp-rename
uses under the hood):
var path = require('path');
gulp.task('metalsmith', function(){
return gulp.src(CONTENT_DIR)
.pipe(frontMatter()).on("data", function(file){
lodash.assign(file, file.frontMatter);
delete file.frontMatter;
})
.pipe(data(function(file){
var ext;
if(typeof file.filetype === 'undefined'){
ext = '.html';
}else{
ext = file.filetype;
}
var parsedPath = path.parse(file.path);
file.path = path.join(parsedPath.dir, parsedPath.name + ext);
}))
.pipe(gulp.dest(BUILD_DIR))
});
Alternatively you could also use gulp-foreach
as I suggest in this answer to a similar question. However that's not really necessary in your case since you're already accessing the file
object directly in data(...)
.
EDIT: for completeness sake here's a version using gulp-foreach
:
var foreach = require('gulp-foreach');
gulp.task('metalsmith', function(){
return gulp.src(CONTENT_DIR)
.pipe(frontMatter()).on("data", function(file){
lodash.assign(file, file.frontMatter);
delete file.frontMatter;
})
.pipe(foreach(function(stream, file){
var ext;
if(typeof file.filetype === 'undefined'){
ext = {extname: '.html'};
}else{
ext = {extname: file.filetype};
}
return stream.pipe(rename(ext));
}))
.pipe(gulp.dest(BUILD_DIR))
});