UNPKG

3.72 kBJavaScriptView Raw
1'use strict';
2
3var grunt = require('../grunt');
4
5// Get/set config data. If value was passed, set. Otherwise, get.
6var config = module.exports = function(prop, value) {
7 if (arguments.length === 2) {
8 // Two arguments were passed, set the property's value.
9 return config.set(prop, value);
10 } else {
11 // Get the property's value (or the entire data object).
12 return config.get(prop);
13 }
14};
15
16// The actual config data.
17config.data = {};
18
19// Escape any . in name with \. so dot-based namespacing works properly.
20config.escape = function(str) {
21 return str.replace(/\./g, '\\.');
22};
23
24// Return prop as a string.
25config.getPropString = function(prop) {
26 return Array.isArray(prop) ? prop.map(config.escape).join('.') : prop;
27};
28
29// Get raw, unprocessed config data.
30config.getRaw = function(prop) {
31 if (prop) {
32 // Prop was passed, get that specific property's value.
33 return grunt.util.namespace.get(config.data, config.getPropString(prop));
34 } else {
35 // No prop was passed, return the entire config.data object.
36 return config.data;
37 }
38};
39
40// Match '<%= FOO %>' where FOO is a propString, eg. foo or foo.bar but not
41// a method call like foo() or foo.bar().
42var propStringTmplRe = /^<%=\s*([a-z0-9_$]+(?:\.[a-z0-9_$]+)*)\s*%>$/i;
43
44// Get config data, recursively processing templates.
45config.get = function(prop) {
46 return config.process(config.getRaw(prop));
47};
48
49// Expand a config value recursively. Used for post-processing raw values
50// already retrieved from the config.
51config.process = function(raw) {
52 return grunt.util.recurse(raw, function(value) {
53 // If the value is not a string, return it.
54 if (typeof value !== 'string') { return value; }
55 // If possible, access the specified property via config.get, in case it
56 // doesn't refer to a string, but instead refers to an object or array.
57 var matches = value.match(propStringTmplRe);
58 var result;
59 if (matches) {
60 result = config.get(matches[1]);
61 // If the result retrieved from the config data wasn't null or undefined,
62 // return it.
63 if (result != null) { return result; }
64 }
65 // Process the string as a template.
66 return grunt.template.process(value, {data: config.data});
67 });
68};
69
70// Set config data.
71config.set = function(prop, value) {
72 return grunt.util.namespace.set(config.data, config.getPropString(prop), value);
73};
74
75// Deep merge config data.
76config.merge = function(obj) {
77 grunt.util._.merge(config.data, obj);
78 return config.data;
79};
80
81// Initialize config data.
82config.init = function(obj) {
83 grunt.verbose.write('Initializing config...').ok();
84 // Initialize and return data.
85 return (config.data = obj || {});
86};
87
88// Test to see if required config params have been defined. If not, throw an
89// exception (use this inside of a task).
90config.requires = function() {
91 var p = grunt.util.pluralize;
92 var props = grunt.util.toArray(arguments).map(config.getPropString);
93 var msg = 'Verifying propert' + p(props.length, 'y/ies') +
94 ' ' + grunt.log.wordlist(props) + ' exist' + p(props.length, 's') +
95 ' in config...';
96 grunt.verbose.write(msg);
97 var failProps = config.data && props.filter(function(prop) {
98 return config.get(prop) == null;
99 }).map(function(prop) {
100 return '"' + prop + '"';
101 });
102 if (config.data && failProps.length === 0) {
103 grunt.verbose.ok();
104 return true;
105 } else {
106 grunt.verbose.or.write(msg);
107 grunt.log.error().error('Unable to process task.');
108 if (!config.data) {
109 throw grunt.util.error('Unable to load config.');
110 } else {
111 throw grunt.util.error('Required config propert' +
112 p(failProps.length, 'y/ies') + ' ' + failProps.join(', ') + ' missing.');
113 }
114 }
115};