gulp var, определенный в одной трубе, не определен в другой
Я использую gulp для обработки страниц сайта, некоторые из них являются файлами php. Проблема в том, что после того, как все страницы пройдут через механизм шаблонов, у них есть .html
расширение файла. Я добавляю в файл свойство, которое указывает, должен ли он быть файлом, кроме html, и затем переименовываю файл для соответствия. Однако по какой-то причине gulp-rename постоянно говорит, что переменная, которую я использую для хранения расширения, undefined
,
Соответствующее задание в 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))
});
когда я запускаю выше это ошибки с Unsupported renaming parameter type supplied
,
Кроме того, я попробовал это с опциями obj на той же строке, что и rename()
, с ext
хранить только расширение файла, например: .pipe(rename({extname: ext}))
что приводит к добавлению файлов в качестве расширения (вместо phpfile.php
нижеприведенное md
файл будет назван phpfileundefined
)
yaml в 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"
}
2 ответа
Ваша проблема в том, что к тому времени, когда вы выполняете rename(ext)
значение ext
все еще undefined
потому что ваш data(...)
код еще не запущен.
Плагины Gulp работают так:
- Вы вызываете функцию плагина и передаете ей любой необходимый параметр. В твоем случае
rename(ext)
, - Функция плагина возвращает дуплексный поток
- Вы передаете этот дуплексный поток
.pipe()
- Только ведь
.pipe()
звонки были выполнены, вы запускаете поток.
Так rename(ext)
это вызов функции, который используется для создания самого потока. Только после того, как поток был построен, поток может начать работать.
Однако вы устанавливаете значение ext
только когда поток запущен. Вам нужно значение ext
до этого, когда вы создаете поток.
Самое простое решение в вашем случае - просто сделать переименование вручную в вашем data(...)
функционировать вместо того, чтобы полагаться на gulp-rename
, Вы можете использовать встроенный в node.js path
модуль для этого (что к чему gulp-rename
использует под капотом):
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))
});
В качестве альтернативы вы также можете использовать gulp-foreach
как я предлагаю в этом ответе на аналогичный вопрос. Однако в вашем случае это не обязательно, так как вы уже получаете доступ к file
объект прямо в data(...)
,
РЕДАКТИРОВАТЬ: для полноты ради вот версия, использующая 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))
});
Ответ @ Свена выглядит как путь, так как вы надеетесь на что-то общее для других сайтов, и так как вы не можете отбросить gulp-front-matter
труба.
Просто чтобы закончить просмотр кода, который вы имели: даже
var ext = {extname: '.html'};
…
.pipe(rename(ext))
…
не сработает gulp-rename
сказал бы: "Я не знаю, как обращаться с данными, которые мне передали". Вам нужно сделать
var ext = '.html';
…
.pipe(rename({extname: ext})
…
(или же ext = 'html'
а также {extname: '.' + ext}
Например, если строка "html" была извлечена откуда-то еще и не имела ".")
Как мы обсуждали в чате, я надеялся обнаружить, что ваши php и html могут быть легко различены по имени файла или пути. Поскольку все ваши файлы php находятся в /blog
вы могли бы использовать gulp-filter
, Возможно, в конце концов, это не лучшее решение для этого сценария, но это полезный инструмент, о котором нужно знать, поэтому вот как это будет выглядеть:
var gulp = require('gulp'),
gutil = require('gulp-util'),
lodash = require('lodash'),
data = require('gulp-data'),
filesize = require('gulp-filesize'),
filter = require('gulp-filter'), // ADDED
frontMatter = require('gulp-front-matter'),
rename = require('gulp-rename'),
util = require('util');
gulp.task('metalsmith', function() {
const filterPHP = filter('blog/**/*', { restore: true });
const filterHTML = filter('!blog/**/*', { restore: true });
return gulp.src(CONTENT_DIR)
//---- if the only purpose of this particular gulp-front-matter pipe was to support the extension assignment, you could drop it
.pipe(frontMatter()).on("data", function(file) { //
lodash.assign(file, file.frontMatter); //
delete file.frontMatter; //
}) //
//---------
.pipe(filterPHP) // narrow down to just the files matched by filterPHP
.pipe(rename({ extname: '.php' }))
.pipe(filterPHP.restore) // widen back up to the full gulp.src
.pipe(filterHTML) // narrow down to just the files matched by filterHTML
.pipe(rename({ extname: '.html' }))
.pipe(filterHTML.restore) // widen back up
.pipe(gulp.dest(BUILD_DIR))
});