gulp 一个管道中定义的变量在另一个管道中未定义
gulp var defined in one pipe is undefined in another
我正在使用 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
.
我也试过它在 rename()
的同一行上有选项 obj,ext
只存储文件扩展名,例如:.pipe(rename({extname: ext}))
导致文件添加了未定义作为扩展名(而不是 phpfile.php
下面的 md
文件将被命名为 phpfileundefined
)
phpfile.md
中的 yaml
---
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"
}
你的问题是当你执行 rename(ext)
时 ext
的值仍然是 undefined
因为你的 data(...)
代码没有 运行还。
Gulp 插件是这样工作的:
- 您调用插件函数并向其传递任何必要的参数。在你的情况下
rename(ext)
.
- 插件函数returns一个duplex stream
- 您将该双工流传递给
.pipe()
- 只有在 all
.pipe()
调用执行后,您才开始流式传输 运行ning.
所以 rename(ext)
是一个函数调用,用于 构造 流本身。流构建完成后才能开始流运行ning。
但是,您仅在流为 运行ning 时才设置 ext
的值。在构建流时,您需要 ext
before 的值。
在您的情况下,最简单的解决方案是简单地在 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
as I suggest in 来回答类似的问题。但是,在您的情况下,这并不是真正必要的,因为您已经直接在 data(...)
.
中访问 file
对象
编辑: 为了完整起见,这里有一个使用 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))
});
@Sven 的回答看起来像是要走的路,因为你希望得到一些可以推广到其他网站的东西,而且你不能放弃 gulp-front-matter
管道。
只是为了完成您拥有的代码:Even
var ext = {extname: '.html'};
…
.pipe(rename(ext))
…
行不通:gulp-rename
会说 "I don't know how to deal with the kind of data I was passed." 你需要做
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))
});
我正在使用 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
.
我也试过它在 rename()
的同一行上有选项 obj,ext
只存储文件扩展名,例如:.pipe(rename({extname: ext}))
导致文件添加了未定义作为扩展名(而不是 phpfile.php
下面的 md
文件将被命名为 phpfileundefined
)
phpfile.md
中的 yaml---
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"
}
你的问题是当你执行 rename(ext)
时 ext
的值仍然是 undefined
因为你的 data(...)
代码没有 运行还。
Gulp 插件是这样工作的:
- 您调用插件函数并向其传递任何必要的参数。在你的情况下
rename(ext)
. - 插件函数returns一个duplex stream
- 您将该双工流传递给
.pipe()
- 只有在 all
.pipe()
调用执行后,您才开始流式传输 运行ning.
所以 rename(ext)
是一个函数调用,用于 构造 流本身。流构建完成后才能开始流运行ning。
但是,您仅在流为 运行ning 时才设置 ext
的值。在构建流时,您需要 ext
before 的值。
在您的情况下,最简单的解决方案是简单地在 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
as I suggest in data(...)
.
file
对象
编辑: 为了完整起见,这里有一个使用 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))
});
@Sven 的回答看起来像是要走的路,因为你希望得到一些可以推广到其他网站的东西,而且你不能放弃 gulp-front-matter
管道。
只是为了完成您拥有的代码:Even
var ext = {extname: '.html'};
…
.pipe(rename(ext))
…
行不通:gulp-rename
会说 "I don't know how to deal with the kind of data I was passed." 你需要做
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))
});