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