[484] | 1 | /* |
---|
| 2 | * grunt |
---|
| 3 | * http://gruntjs.com/ |
---|
| 4 | * |
---|
[516] | 5 | * Copyright (c) 2014 "Cowboy" Ben Alman |
---|
[484] | 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 | }; |
---|