【问题标题】:Can Yeoman generators update existing files?Yeoman 生成器可以更新现有文件吗?
【发布时间】:2013-10-04 10:04:37
【问题描述】:

所以只是为了给你一些背景信息,我正在尝试创建一个生成器,它将创建一些文件(当然基于用户输入)以及更新项目中的一些现有文件(例如添加一条新路线)。

使用this.template 创建文件没问题...问题是:有没有什么方法可以用 Yeoman 做到这一点,而不必使用 Node 读取文件并进行一些奇特的查找和替换?

【问题讨论】:

    标签: yeoman yeoman-generator


    【解决方案1】:

    好的,所以我找到了问题的答案。

    Addy Osmani 向我展示了在 this thread on twitter 中的位置,然后我找到了 this link,这正是我所需要的。

    它的要点归结为两个函数:readFileAsStringwrite。用法如下:

    var path = "/path/to/file.html",
        file = this.readFileAsString(path);
    
    /* make modifications to the file string here */
    
    this.write(path, file);
    

    编辑:我也在博客上写过这个on my blog

     编辑 1

    正如 Toilal 在 cmets 中提到的:

    write 方法已不存在,必须替换为writeFileFromString(参数也颠倒过来)——Toilal

    编辑 2

    然后,正如 ivoba 在 cmets 中提到的那样:

    this.writeFileFromStringthis.readFileAsString 已弃用,现在应该使用 github.com/yeoman/html-wiring,情况有所改变 :) – ivoba

    【讨论】:

    • write方法不存在了,必须换成writeFileFromString(参数也颠倒)
    • this.writeFileFromString 和 this.readFileAsString 已弃用,github.com/yeoman/html-wiring 现在应该使用,情况会发生变化:)
    • 有没有办法在一个生成器中执行两次?即使我将其中两个使用不同的hooks,它也只会应用第二个修改。
    • html-wiring 也已弃用。
    【解决方案2】:

    Yeoman 还使用mem-fs-editor 提供了一种更优雅的 fs 操作方式。

    您可以使用this.fs.copy,传递一个流程函数作为选项来对内容进行任何修改:

    this.fs.copy(path, newPath, {
        process: function(content) {
    
            /* Any modification goes here. Note that contents is a Buffer object */
    
            var regEx = new RegExp('old string', 'g');
            var newContent = content.toString().replace(regEx, 'new string');
            return newContent;
        }
    });
    

    这样您还可以利用mem-fs-editor 功能。

    【讨论】:

    • 使用 regEx 更新 js 文件很危险,Yeoman 文档不鼓励这样做,如@Wtower 所述
    • 我同意。虽然问题中没有提到源文件是js文件。
    【解决方案3】:

    结合@sepans 的出色回答,可以使用一些解析器,而不是使用正则表达式。

    来自约曼documentation

    提示:更新现有文件的内容

    更新预先存在的文件并不总是一项简单的任务。最可靠的方法是解析文件AST 并对其进行编辑。此解决方案的主要问题是编辑 AST 可能很冗长且有点难以掌握。

    一些流行的 AST 解析器是:

    • Cheerio 用于解析 HTML。
    • Esprima 用于解析 JavaScript - 您可能对 AST-Query 感兴趣,它提供了较低级别的 API 来编辑 Esprima 语法树。
    • 对于 JSON 文件,您可以使用原生的JSON object methods

    用正则表达式解析代码文件是危险的,在这样做之前,你应该阅读CS anthropological answers并掌握正则表达式解析的缺陷。如果您确实选择使用 RegEx 而不是 AST 树来编辑现有文件,请小心并提供完整的单元测试。 - 请不要破坏您用户的代码。

    更具体地说,当使用 esprima 时,您很可能还需要一些生成器,例如 escodegen 来生成 js。

    var templatePath = this.destinationPath(...);
    this.fs.copy(templatePath, templatePath, {
      process: function (content) {
        // here use the parser
        return ...
      }
    });
    

    请注意,您可以在 fromto 参数中使用相同的路径来替换现有文件。

    另一方面,这种解析器的缺点是在某些情况下它可能会过多地改变原始文件,虽然安全,但更具侵入性。

    【讨论】:

      【解决方案4】:

      您可以使用mem-fs-editor,并调用fs.append(filepath, contents, [options]) 方法。

      例如

      this.fs.append(this.contextRoot + "/index.html", "  <p>Appended text</p>");
      

      【讨论】:

      • 编辑html太复杂,无法使用append来获得有效结果。我会建议更简单的文件类型,例如这里。例如.gitignore
      【解决方案5】:

      使用var text = this.fs.read(filePath) 读取文件,使用this.fs.write(filePath, content) 写入某个位置的文件。

      【讨论】:

        猜你喜欢
        • 2020-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多