0

我正在使用 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

phpfile.md 中的 yaml

---
layout: php.hbt
filetype: ".php"
title: "php"
---

包.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"
  }
4

2 回答 2

2

您的问题是,当您执行时rename(ext),值ext仍然是undefined因为您的data(...)代码尚未运行。

Gulp 插件的工作方式如下:

  1. 您调用插件函数并向其传递任何必要的参数。在你的情况下rename(ext)
  2. 插件函数返回一个双工流
  3. 您将该双工流传递给.pipe()
  4. 只有在执行了所有 .pipe()调用之后,您才会开始流式传输。

rename(ext)用于构造流本身的函数调用也是如此。只有在流构建完成后,流才能开始运行

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按照我在此答案中对类似问题的建议使用。但是,在您的情况下,这并不是必需的,因为您已经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))
});
于 2016-09-08T06:25:52.253 回答
1

@Sven 的答案看起来像是要走的路,因为您希望能够推广到其他站点并且您不能放弃gulp-front-matter管道。

只是为了完成您拥有的代码:甚至

var ext = {extname: '.html'};
…
.pipe(rename(ext))
…

行不通:gulp-rename会说“我不知道如何处理我传递的那种数据。” 你需要做

var ext = '.html';
…
.pipe(rename({extname: ext})
…

(或者ext = 'html'and {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))
});
于 2016-09-08T07:18:03.093 回答