UNPKG

3.08 kBJavaScriptView Raw
1'use strict';
2
3var fs = require('fs-extra'),
4 path = require('path'),
5 Plugin = require('broccoli-plugin'),
6 hashStrings = require('broccoli-kitchen-sink-helpers').hashStrings;
7
8function ConfigReplace(inputNode, configNode, options) {
9 options = options || {};
10
11 // this._super();
12 Plugin.call(this, [inputNode, configNode], {
13 annotation: options.annotation
14 });
15
16 this.options = options;
17 this._cache = {};
18}
19
20ConfigReplace.prototype = Object.create(Plugin.prototype);
21ConfigReplace.prototype.constructor = ConfigReplace;
22
23ConfigReplace.prototype.build = function () {
24 var inputPath = this.inputPaths[0],
25 config = this.getConfig();
26
27 this.options.files.forEach(function(file) {
28 var key = this.deriveCacheKey(file),
29 entry = this._cache[key.hash],
30 contents, filePath;
31
32 if (entry) {
33 filePath = entry.file;
34 contents = entry.contents
35 } else {
36 filePath = file;
37 contents = this.processFile(config, filePath);
38 this.updateCache(key, contents);
39 }
40
41 filePath = path.join(this.outputPath, filePath);
42 this.writeFile(filePath, contents);
43 }, this);
44};
45
46ConfigReplace.prototype.deriveCacheKey = function(file) {
47 var stats = fs.statSync(this.getConfigPath());
48
49 if (stats.isDirectory()) {
50 throw new Error('Must provide a path for the config file, you supplied a directory');
51 }
52
53 var patterns = this.options.patterns.reduce(function(a, b) {
54 return a + b.match;
55 }, '');
56
57 return {
58 file: file,
59 hash: hashStrings([
60 file,
61 this.configPath,
62 patterns,
63 stats.size,
64 stats.mode,
65 stats.mtime.getTime()
66 ])
67 };
68};
69
70ConfigReplace.prototype.processFile = function(config, filePath) {
71 filePath = path.join(this.inputPaths[0], filePath);
72 var contents = fs.readFileSync(filePath, { encoding: 'utf8' });
73
74 this.options.patterns.forEach(function(pattern) {
75 var replacement = pattern.replacement;
76
77 if (typeof replacement === 'function') {
78 replacement = function() {
79 var args = Array.prototype.slice.call(arguments);
80 return pattern.replacement.apply(null, [config].concat(args));
81 }
82 }
83
84 contents = contents.replace(pattern.match, replacement);
85 });
86
87 return contents;
88};
89
90ConfigReplace.prototype.writeFile = function(destPath, contents) {
91 if (!fs.existsSync(path.dirname(destPath))) {
92 fs.mkdirSync(path.dirname(destPath));
93 }
94
95 fs.writeFileSync(destPath, contents, { encoding: 'utf8' });
96};
97
98ConfigReplace.prototype.updateCache = function(key, contents) {
99 Object.keys(this._cache).forEach(function(hash) {
100 if (this._cache[hash].file === key.file) {
101 delete this._cache[hash];
102 }
103 }, this);
104
105 this._cache[key.hash] = {
106 file: key.file,
107 contents: contents
108 };
109};
110
111ConfigReplace.prototype.getConfigPath = function() {
112 return path.join(this.inputPaths[1], this.options.configPath);
113};
114
115ConfigReplace.prototype.getConfig = function() {
116 var contents = fs.readFileSync(this.getConfigPath(), { encoding: 'utf8' });
117 return JSON.parse(contents);
118};
119
120module.exports = ConfigReplace;