UNPKG

4.8 kBJavaScriptView Raw
1var fs = require("fs"),
2 path = require("path"),
3 colors = require("colors");
4
5
6var excludes = [],
7 includes,
8 regex,
9 canReplace,
10 replaceFunc,
11 lineCount = 0,
12 limit = 400, // chars per line
13 options;
14
15module.exports = function(opts) {
16 options = opts;
17 var flags = "g"; // global multiline
18 if (options.ignoreCase) {
19 flags += "i";
20 }
21 if (options.multiline) {
22 flags += "m";
23 }
24 regex = new RegExp(options.regex, flags);
25 canReplace = !options.preview && options.replacement !== undefined;
26
27 if (options.include) {
28 includes = options.include.split(",").map(patternToRegex);
29 }
30 if (options.exclude) {
31 excludes = options.exclude.split(",");
32 }
33 var list = fs.readFileSync(options.excludeList, "utf-8").split("\n");
34 excludes = excludes.concat(list)
35 .filter(function(line) {
36 return line && line.indexOf("#");
37 })
38 .map(patternToRegex);
39
40 if (!options.silent) {
41 var verb = canReplace ? "Replaced" : "Found";
42 console.log(verb + " occurences in these files:");
43 }
44 if (options.funcFile) {
45 eval('replaceFunc = ' + fs.readFileSync(options.funcFile, "utf-8"));
46 }
47
48 for (var i = 0; i < options.path.length; i++) {
49 if(options.async) {
50 replacizeFile(options.path[i]);
51 }
52 else {
53 replacizeFileSync(options.path[i]);
54 }
55 }
56}
57
58function patternToRegex(pattern) {
59 return new RegExp("^" + pattern.replace(/\./g, '\\.').replace(/\*/g, '.*').trim() + "$");
60}
61
62function includeFile(file) {
63 if (includes) {
64 for (var i = 0; i < includes.length; i++) {
65 if (file.match(includes[i]))
66 return true;
67 }
68 return false;
69 }
70 else {
71 for (var i = 0; i < excludes.length; i++) {
72 if (file.match(excludes[i]))
73 return false;
74 }
75 return true;
76 }
77}
78
79function replacizeFile(file) {
80 fs.lstat(file, function(err, stats) {
81 if (err) throw err;
82
83 if (stats.isSymbolicLink()) {
84 // don't follow symbolic links for now
85 return;
86 }
87 if (stats.isFile()) {
88 if (!includeFile(file)) {
89 return;
90 }
91 fs.readFile(file, "utf-8", function(err, text) {
92 if (err) {
93 if (err.code == 'EMFILE') {
94 console.log('Too many files, try running `replace` without --async');
95 process.exit(1);
96 }
97 throw err;
98 }
99
100 text = replacizeText(text, file);
101 if(canReplace) {
102 fs.writeFile(file, text, function(err) {
103 if (err) throw err;
104 });
105 }
106 });
107 }
108 else if (stats.isDirectory() && options.recursive) {
109 fs.readdir(file, function(err, files) {
110 if (err) throw err;
111 for (var i = 0; i < files.length; i++) {
112 replacizeFile(path.join(file, files[i]));
113 }
114 });
115 }
116 });
117}
118
119function replacizeFileSync(file) {
120 var stats = fs.lstatSync(file);
121 if (stats.isSymbolicLink()) {
122 // don't follow symbolic links for now
123 return;
124 }
125 if (stats.isFile()) {
126 if (!includeFile(file)) {
127 return;
128 }
129 var text = fs.readFileSync(file, "utf-8");
130
131 text = replacizeText(text, file);
132 if (canReplace) {
133 fs.writeFileSync(file, text);
134 }
135 }
136 else if (stats.isDirectory() && options.recursive) {
137 var files = fs.readdirSync(file);
138 for (var i = 0; i < files.length; i++) {
139 replacizeFileSync(path.join(file, files[i]));
140 }
141 }
142}
143
144function replacizeText(text, file) {
145 var match = text.match(regex);
146 if (!match) {
147 return text;
148 }
149
150 if (!options.silent) {
151 var printout = "\t" + file;
152 if (options.count) {
153 printout += " (" + match.length + ")";
154 }
155 console.log(printout);
156 }
157 if (!options.silent && !options.quiet
158 && !(lineCount > options.maxLines)
159 && options.multiline) {
160 var lines = text.split("\n");
161 for (var i = 0; i < lines.length; i++) {
162 var line = lines[i];
163 if (line.match(regex)) {
164 if (++lineCount > options.maxLines) {
165 break;
166 }
167 var replacement = options.replacement || "$&";
168 line = line.replace(regex, replaceFunc || replacement[options.color]);
169 console.log("\t\t" + (i + 1) + ": " + line.slice(0, limit));
170 }
171 }
172 }
173 if (canReplace) {
174 return text.replace(regex, replaceFunc || options.replacement);
175 }
176}