Grunt - 解析非字符串(例如数组)模板

时间:2013-04-12 20:35:00

标签: javascript gruntjs

假设我的grunt配置中有一个变量,数组为值。真实世界的示例是来自grunt-regarde插件的grunt.regarde.changed,其中列出了所有已更改的文件。

我想使用模板解析该数组,以便我可以(在这种情况下)复制更改的文件:

  copy: {
    staticWeb: {
      src: '<%= grunt.regarde.changed %>',
      dest: 'someDir'
    },

在这种情况下,src得到的是一个以逗号分隔的字符串而不是数组。 Grunt的文件处理器不解析字符串,因此无法找到src文件。

我无法删除模板周围的单引号,因为它是无效的javascript。

那么如何将grunt.regarde.changed数组传递给src变量?

3 个答案:

答案 0 :(得分:10)

一旦你知道如何,只需几行代码就可以很容易地修复这个问题,但是我花了很长时间才从Grunt源代码中挖掘出所有相关信息,以便了解该怎么做,所以当我带你穿过背景时,请忍受我...


配置对象上获取属性的一般方法很简单:

<%= some.property %> // fetches grunt.config.get('some.property')

适用于grunt.config对象上设置的所有属性,当然这些属性包含传递给grunt.initConfig()的配置。这就是您可以直接引用其他任务变量的原因,例如在<%= concat.typescriptfiles.dest %>中,因为配置对象中的所有属性都在模板自己的范围内。

从技术上讲,当(LoDash)模板与options对象(如果已定义)或grunt.config对象一起传递给模板处理器(LoDash'template函数时,会发生此扩展)。

因此,这适用于已在配置中设置的值,或通过grunt.config.set()使用动态分配的值。有关详细信息,请参阅API docs

以不同方式工作的是访问配置对象上不可用的值。似乎由于某种原因我不太确定,所有其他值总是以字符串结尾。无论您是直接访问还是通过方法调用,都会发生这种情况。例如,尝试通过grunt.config.get()访问配置上的数组会获得一个字符串。

保留文件顺序的问题的解决方法

接受的答案在某种程度上起作用,但由于全局语法,它将被glob()模块解析,而不保留文件顺序。这对我的构建来说是禁忌。

如果您要使用的阵列在配置对象上不可用,则解决方法是通过中间任务将其添加到配置中。以下内容应该有效:

// This variable will be used twice to demonstrate the difference
// between directly setting an attribute on the grunt object
// and using the setter method on the grunt.config object
var myFiles = ['c/file1.txt', 'a/file2.txt', 'b/file3.txt']
module.exports = function(grunt){

    grunt.initConfig({

        debug : {
            using_attribute: {
                src : '<%= grunt.value_as_attribute %>' // will be a string
            },
            using_task: {
                src : '<%= value_by_setter %>' // will be an array
            },
            no_task_direct_setter: {
                src : '<%= value_by_setter_early %>' // will be an array
            }
        }        
    });

    grunt.registerTask('myValSetter', function() {
        grunt.config.set('value_by_setter', myFiles );
    });

    // a task that will report information on our set values
    grunt.registerMultiTask('debug', function(){
        grunt.log.writeln('data.src: ', this.data.src);
        grunt.log.writeln('type: ', Array.isArray(this.data.src)? "Array" : typeof this.data.src);
    });

    grunt.value_as_attribute = myFiles;

    grunt.config.set('value_by_setter_early', myFiles );

    grunt.registerTask('default',['myValSetter', 'debug']);
}

这将输出

$ grunt
Running "myValSetter" task

Running "debug:using_attribute" (debug) task
data.src:  c/file1.txt,a/file2.txt,b/file3.txt
type:  string

Running "debug:using_task" (debug) task
data.src:  [ 'c/file1.txt', 'a/file2.txt', 'b/file3.txt' ]
type:  Array

Running "debug:no_task_direct_setter" (debug) task
data.src:  [ 'c/file1.txt', 'a/file2.txt', 'b/file3.txt' ]
type:  Array

Done, without errors.

此示例仅用于说明概念,但您应该能够轻松地将其自定义为您的实例:)

答案 1 :(得分:8)

我和你的问题完全相同,用大括号包围你的模板来解决它。

所以这是你的代码,经过修改

copy: {
  staticWeb: {
    src: '{<%= grunt.regarde.changed %>}', // added curly brackets
    dest: 'someDir'
  }
}

它会将src输出为{source1,source2,source3},这与使用数组相同。 (见Globbing Patterns in Grunt Documentation

答案 2 :(得分:-2)

你试过了吗?

copy: {
  staticWeb: {
    src: '<%= grunt.regarde.changed.split(",") %>',
    dest: 'someDir'
  }
}