使用copyTpl复制整个文件夹时重命名单个文件名

问题描述 投票:0回答:5

我的 yeoman 生成器将文件从模板复制到目标路径:

this.fs.copyTpl(
            this.templatePath(),
            this.destinationPath(), {
                appName: this.props.appName
            });

在项目生成过程中,我需要将

this.props.appName
的值分配给某些文件名。

不幸的是,我不能像在这个文件中那样做:

<%=appName%>-project.sln

所有需要重命名的文件名称中都有

appTemplate
,所以我需要做的就是将
appTemplate
替换为
this.props.appName
的值。

我可以以某种方式配置

copyTpl
来重命名某些文件,同时将它们复制到另一个目的地吗?

node.js yeoman yeoman-generator
5个回答
9
投票

好的,我找到了解决方案。根据 yeoman 文档

任何生成器作者都可以注册一个transformStream来修改文件路径和/或内容。

使用此方法:

this.registerTransformStream();

这意味着我可以通过某个脚本传输所有生成的文件:

var rename = require("gulp-rename");
//other dependecies...

module.exports = yeoman.Base.extend({

    //some other things generator do...

    writing: function() {
        var THAT = this;
        this.registerTransformStream(rename(function(path) {
            path.basename = path.basename.replace(/(666replacethat666)/g, THAT.props.appName);
            path.dirname = path.dirname.replace(/(666replacethat666)/g, THAT.props.appName);
        }));
        this.fs.copyTpl(
            this.templatePath(),
            this.destinationPath(), {
                appName: this.props.appName
            });
    }
});

此脚本将通过 gulp-rename 传输所有文件,将

666replacethat666
更改为更智能的内容。


1
投票

如果您因为在 Yeoman 中使用

registerTransformStream
功能(断开转换流注册)而无法使用
composeWith()
,则可以使用
processDestinationPath
,它在您选择多个文件时起作用(而不是在您指定特定文件时起作用)在第一个参数中,出于某种原因)。

this.fs.copyTpl(
  this.templatePath("**/{.*,*}"),
  this.destinationPath(),
  { /* usually your prompt answers are here */ },
  {},
  {
    processDestinationPath: (filePath: string) =>
      filePath.replace(/somedir\/a-file.js/g, 'newdir/better-filename.js'),
  },
);

文档选项来源:https://yeoman.github.io/generator/actions_fs.html#.copyTemplate

这是基于 https://github.com/SBoudrias/mem-fs-editor#copyfrom-to-options-context-templateoptions-


0
投票

registerTransformStream
gulp-rename
仍然是一个问题。不过,我可以让它与 glob 一起使用。

const glob = require('glob');

writing() {
    const files = glob.sync('**', { dot: true, nodir: true, cwd: this.templatePath() })
    for (let i in files) {
        this.fs.copyTpl(
            this.templatePath(files[i]),
            this.destinationPath( this.props.destinationFolderPath + '\\' + files[i].replace(/__fileName__/g,this.props.fileName)),
            this.props
        )
    }
}

0
投票

复制后,迭代输出目录的路径,并用正则表达式替换所有出现的位置。


const getReplacement = (base, pathRel, match, replace) => {
  let pathRelNew = pathRel.replace(match, replace);

  let oldPathAbs = path.join(base, pathRel);
  let newPathAbs = path.join(base, pathRelNew);

  if (oldPathAbs != newPathAbs) {
    return {
      oldPath: oldPathAbs,
      newPath: newPathAbs
    }
  }
}

const getReplacementsRecursive = (base, match, replace, replacements = []) => {
  let pathsRel = fs.readdirSync(base);

  pathsRel.forEach(pathRel => {
    if (fs.statSync(path.join(base, pathRel)).isDirectory()) {
      replacements = getReplacementsRecursive(path.join(base, pathRel), match, replace, replacements);

      var replacement = getReplacement(base, pathRel, match, replace)
      if (replacement) replacements.push(replacement);
    } else {
      var replacement = getReplacement(base, pathRel, match, replace)
      if (replacement) replacements.push(replacement);
    }
  });

  return replacements;
};

function replaceMatches(dir, match, replace) {
  var replacements = getReplacementsRecursive(dir, match, replace);

  replacements.forEach(function(replacement) {
    fs.renameSync(replacement.oldPath, replacement.newPath);
  });
}

module.exports = class extends Generator {
  // ...

  writing() {
    // don't forget to set the output directory
    let OUTPUT_DIR = "./out";

    // this.fs.copyTpl(...);

    // setTimeout is used to give some time for the copyTpl to finish
    setTimeout(
      () => {
        var match = new RegExp( "666replacethat666", 'g' );
        replaceMatches(OUTPUT_DIR, match, this.props.appName);
      }, 1000);
  }
}

0
投票

我建议在模板操作后简单地重命名目标文件。

我从这个讨论中得到了这个解决方案:在 Yeoman 复制模板文件后重命名文件

示例:

// start by doing the large template operation with a glob
this.fs.copyTpl(
    this.templatePath("**/*"),
    this.destinationPath(),
    this.answers,
);

// Example of a directory rename - moving the ApplicationName directory and everything in it
this.fs.move(
    this.destinationPath('src', 'ApplicationName', '**/*'),
    this.destinationPath('src', this.answers.appName, '**/*')
);

// Renaming a single file.  Note how we are now operating within the renamed directory
this.fs.move(
    this.destinationPath('src', this.answers.appName, 'ApplicationName.csproj'), 
    this.destinationPath('src', this.answers.appName, this.answers.appName + '.csproj')
);
© www.soinside.com 2019 - 2024. All rights reserved.