UNPKG

5.27 kBJavaScriptView Raw
1
2/*
3 * grunt-replace
4 *
5 * Copyright (c) 2015 outaTiME
6 * Licensed under the MIT license.
7 * https://github.com/outaTiME/grunt-replace/blob/master/LICENSE-MIT
8 */
9
10'use strict';
11
12// plugin
13
14module.exports = function (grunt) {
15
16 var path = require('path');
17 var fs = require('fs');
18 var chalk = require('chalk');
19 var _ = require('lodash');
20 var Applause = require('applause');
21
22 grunt.registerMultiTask('replace', 'Replace text patterns with applause.', function () {
23
24 // took options
25
26 var options = this.options({
27 encoding: grunt.file.defaultEncoding,
28 // processContent/processContentExclude deprecated renamed to process/noProcess
29 processContentExclude: [],
30 mode: false,
31 patterns: [],
32 excludeBuiltins: false,
33 force: true,
34 silent: false
35 });
36
37 // attach builtins
38
39 var patterns = options.patterns;
40
41 if (options.excludeBuiltins !== true) {
42 patterns.push({
43 match: '__SOURCE_FILE__',
44 replacement: function (match, offset, string, source, target) {
45 return source;
46 },
47 builtin: true
48 }, {
49 match: '__SOURCE_PATH__',
50 replacement: function (match, offset, string, source, target) {
51 return path.dirname(source);
52 },
53 builtin: true
54 }, {
55 match: '__SOURCE_FILENAME__',
56 replacement: function (match, offset, string, source, target) {
57 return path.basename(source);
58 },
59 builtin: true
60 }, {
61 match: '__TARGET_FILE__',
62 replacement: function (match, offset, string, source, target) {
63 return target;
64 },
65 builtin: true
66 }, {
67 match: '__TARGET_PATH__',
68 replacement: function (match, offset, string, source, target) {
69 return path.dirname(target);
70 },
71 builtin: true
72 }, {
73 match: '__TARGET_FILENAME__',
74 replacement: function (match, offset, string, source, target) {
75 return path.basename(target);
76 },
77 builtin: true
78 });
79 }
80
81 // create applause instance
82
83 var applause = Applause.create(_.extend({}, options, {
84 // private
85 detail: true
86 }));
87
88 // took code from copy task
89
90 var tally = {
91 dirs: 0,
92 files: 0,
93 replacements: 0,
94 details: []
95 };
96
97 this.files.forEach(function (filePair) {
98 var dest = filePair.dest;
99 var isExpandedPair = filePair.orig.expand || false;
100 filePair.src.forEach(function (src) {
101 src = unixifyPath(src);
102 dest = unixifyPath(dest);
103 if (detectDestType(dest) === 'directory') {
104 dest = (isExpandedPair) ? dest : path.join(dest, src);
105 }
106 if (grunt.file.isDir(src)) {
107 grunt.file.mkdir(dest);
108 tally.dirs++;
109 } else {
110 var res = replace(src, dest, options, applause);
111 tally.details = tally.details.concat(res.detail);
112 tally.replacements += res.count;
113 tally.files++;
114 }
115 if (options.mode !== false) {
116 fs.chmodSync(dest, (options.mode === true) ? fs.lstatSync(src).mode : options.mode);
117 }
118 });
119 });
120
121 // warn for unmatched patterns in the file list
122
123 if (options.silent !== true) {
124 var count = 0;
125 patterns.forEach(function (pattern) {
126 if (pattern.builtin !== true) { // exclude builtins
127 var found = _.find(tally.details, 'source', pattern);
128 if (!found) {
129 count++;
130 }
131 }
132 });
133 if (count > 0) {
134 var strWarn = [
135 'Unable to match ',
136 count,
137 count === 1 ? ' pattern' : ' patterns'
138 ];
139 if (applause.options.usePrefix === true) {
140 strWarn.push(
141 ', remember for simple matches (String) we are using the prefix ',
142 applause.options.prefix,
143 ' for replacement lookup'
144 );
145 }
146 grunt.log.warn(strWarn.join(''));
147 }
148 var str = [
149 chalk.cyan(tally.replacements),
150 tally.replacements === 1 ? ' replacement' : ' replacements',
151 ' in ',
152 chalk.cyan(tally.files),
153 tally.files === 1 ? ' file' : ' files'
154 ];
155 grunt.log.writeln(str.join(''));
156 }
157
158 });
159
160 var detectDestType = function (dest) {
161 if (_.endsWith(dest, '/')) {
162 return 'directory';
163 } else {
164 return 'file';
165 }
166 };
167
168 var unixifyPath = function (filepath) {
169 if (process.platform === 'win32') {
170 return filepath.replace(/\\/g, '/');
171 } else {
172 return filepath;
173 }
174 };
175
176 var replace = function (source, target, options, applause) {
177 var res;
178 grunt.file.copy(source, target, {
179 encoding: options.encoding,
180 process: function (content) {
181 res = applause.replace(content, [source, target]);
182 var result = res.content;
183 // force contents
184 if (result === false && options.force === true) {
185 result = content;
186 }
187 if (result !== false) {
188 grunt.verbose.writeln('Replace ' + chalk.cyan(source) + ' → ' +
189 chalk.green(target));
190 }
191 return result;
192 },
193 noProcess: options.noProcess || options.processContentExclude
194 });
195 return res;
196 };
197
198};