【问题标题】:Read filename in Grunt task在 Grunt 任务中读取文件名
【发布时间】:2018-03-14 13:09:49
【问题描述】:

我已经将 Grunt 设置为使用 grunt-replace,这样我就可以在几百个 HTML 页面中找到一个 div,并将 div 中的文本替换为它所在的 HTML 文件的当前文件名。我是但是不确定如何执行此操作。我尝试使用window.loacation.href,但这只会在我运行任务时产生错误。

这是我的 Gruntfile.coffee:

module.exports = (grunt) ->
grunt.initConfig
    pkg: grunt.file.readJSON "package.json"
    gruntfile: "Gruntfile.coffee"

    replace:
        dist:
            options:
                patterns: [
                    match: "<div id'name_goes_here'></div>"
                    replacement: ->
                        "<div id'name_goes_here'>Filename: #{window.location.href}</div>"
                ]
            usePrefix: false
            files: [
                expand: true
                flatten: true
                src: [
                    "src/*.html"
                ],
                dest: "output/"
            ]

grunt.loadNpmTasks "grunt-replace";
grunt.registerTask "default", ["replace"];

顺便说一句,我尝试将一个包含简单字符串的变量传递到替换字符串中,这可以正常工作并将其替换为所有 HTML 页面,因此 Grunt 任务肯定可以正常工作。另外,替换是一个函数的原因是因为我计划稍后添加一些额外的东西,但现在只想让它工作。

任何帮助将不胜感激。

【问题讨论】:

    标签: javascript html coffeescript gruntjs rename


    【解决方案1】:

    编辑:更新了Gruntfile.js 中的正则表达式以处理&lt;div&gt; 标记,这些标记可能还包括除了id 之外的属性。例如:

    <!-- Also includes a class -->
    <div id="QUUX" class="foo">...</div>
    

    首先gruntNode.js 上运行,因此调用window.location.href 将产生错误,因为要处理的.html 文件未加载到Web 浏览器中。 window.location.hrefBOM 的约定,通常仅适用于浏览器环境。

    grunt-replace 使用标准任务配置不提供获取正在处理的文件名的机制。但是,由于grunt-replace 是一个multi-task 插件,因此可以通过使用自定义函数来动态创建replace 任务对象来满足您的要求。


    下面展示了如何实现这一点:

    Gruntfile.js

    module.exports = function (grunt) {
    
      grunt.initConfig( {
        replace: {} // <-- // Intentionally empty, will be generated dynamically.
      });
    
      /**
       * Helper function dynamically creates config object for `replace` Task.
       * We dynamically generate this to obtain the filename and use that for
       * the `replacement` value.
       */
      function replaceHtml() {
        var glob = 'src/*.html',
          config = {};
    
        grunt.file.expand({ filter: 'isFile' }, glob).forEach(function (filePath) {
          var fileName = filePath.split('/').pop().split('.')[0];
          config[fileName] = {
            options: {
              usePrefix: false,
              patterns: [{
                // Regex pattern explained here: https://regex101.com/r/uJVMOI/3
                match: /(<div.*?id=\"QUUX\".*?>)[\s\S]+?(<\/div>)/g,
                replacement: '$1' + fileName + '$2'
              }]
            },
            files: [{
              expand: true,
              flatten: true,
              src: filePath,
              dest: 'output/'
            }]
          }
        });
    
        grunt.config('replace', config);
        grunt.task.run(['replace']);
      }
    
      grunt.loadNpmTasks('grunt-replace');
      grunt.registerTask("default", replaceHtml);
    };
    

    备注

    1. replace 任务的配置故意设置为空对象。

    2. replaceHtml 函数利用grunt.file.expand 循环遍历通过glob 模式'src/*.html' 找到的每个文件。

    3. fileName变量是通过当前filePath获取的。

    4. forEach 语句的每个循环期间,会生成一个Target 并将其添加到config 对象中。

    5. 退出forEach循环时,config对象通过使用grunt.config添加到replace任务/对象,然后最终调用grunt.task.run

    正则表达式

    那么接下来的部分在做什么呢?

    patterns: [{
      match: /(<div.*?id=\"QUUX\".*?>)[\s\S]+?(<\/div>)/g,
      replacement: '$1' + fileName + '$2'
    }]
    

    match 部分使用正则表达式,在here 中有进一步的解释。它目前搜索以下实例:

    <div id="QUUX">...</div>
    

    所以,假设上面的 sn-p 位于一个名为 index.html 的文件中 - 然后生成的文件将显示为:

    <div id="QUUX">index</div>
    

    但是,如果在结果文件中它应该读取(即它应该包含文件后缀.html):

    <div id="QUUX">index.html</div>
    

    ...那么您需要在第 1 行更改 fileName 变量的赋值。 17 在Gruntfile.js 到:

    var fileName = filePath.split('/').pop();
    

    多个匹配

    要执行多个匹配,只需将另一个模式对象添加到 patterns 数组。例如:

    // ...
    patterns: [{
      match: /(<div.*?id=\"QUUX\".*?>)[\s\S]+?(<\/div>)/g,
      replacement: '$1' + fileName + '$2'
    }, {
      match: /(<div.*?id=\"FOOBAR\".*?>)[\s\S]+?(<\/div>)/g,
      replacement: '$1' + fileName + '$2'
    }]
    // ...
    

    假设正在处理的文件名为hello-world.html - 那么上面的示例将替换任何实例

    <div class="foo" id="QUUX">...</div>
    

    <div id="FOOBAR" class="foo">...</div>
    

    <div class="foo" id="QUUX">hello-world</div>
    

    <div id="FOOBAR" class="foo">hello-world</div>
    

    分别。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-23
      • 2014-05-05
      • 1970-01-01
      相关资源
      最近更新 更多