UNPKG

4.69 kBJavaScriptView Raw
1var
2 when = require('when'),
3 fs = require('final-fs'),
4 parseOptions = require('./parse_options'),
5 pathjs = require('path'),
6 _ = require('underscore'),
7 join = require('path').join,
8 debugBase = require('debug'),
9 debug = debugBase('loaddir:file'),
10 File
11 ;
12
13File = function(options) {
14
15 var
16 self = this;
17 self.options = options;
18
19 parseOptions.call(self);
20
21 debug('File'.magenta, 'constructor'.blue, self.path.green);
22
23 // large files take time to be written to disk, this prevents reading too early
24 self._watchHandler = _.debounce( _.bind(self._watchHandler, self), 500);
25
26 options.toFilename = options.toFilename || toFilename;
27
28 if (_.include(IMAGE_FORMATS, pathjs.extname(self.path).toLowerCase()))
29 self.binary = 'binary';
30
31 return self;
32
33};
34
35File.prototype.load = function() {
36
37 var self = this;
38
39 debug('File'.magenta, 'load'.blue, this.path.green);
40
41 return when().then(function(){
42 if (self.require) {
43 self.fileContents = require(self.path);
44
45 } else {
46 return self.read().then(function(){
47
48 if (self.precompiled) return delete self.precompiled;
49
50 try {
51 if (self.compile)
52 return self.compile(self.fileContents);
53 } catch (er) {
54 debug('error compiling'.red, self.path.blue, er, er.stack);
55 }
56 })
57 .then(function(){
58 try {
59 if (self.callback)
60 return self.callback(self);
61 } catch (er) {
62 debug('error calling back'.red, self.path.blue, er, er.stack);
63 }
64
65 });
66 }
67 })
68 .then(function(){
69
70 if (self.destination) {
71 write_path = self.toFilename(
72 join(self.destination, self.baseName),
73 self.extension || pathjs.extname(self.fileName)
74 );
75 fs.writeFile(write_path, self.fileContents, self.binary);
76 };
77
78 // We wrap our fileContents with the filename for consistency
79 self.key = join( self.asObject ? '' : self.relativePath, self.baseName );
80 self.output[self.key] = self.fileContents;
81 if (self.watch == true || (self.watch !== false && self.loaddir.watch !== false))
82 self._watch()
83
84 })
85 // Allow delete to short circuit writing to self.output without throwing error
86 .otherwise(function(er) {
87 debug('Error loading file -- stack'.red, self.path.blue, er, er.stack);
88 });
89
90
91};
92
93File.prototype._watch = function() {
94
95 var self = this;
96 if (_.include(self.watchedPaths, self.path)) return;
97
98 debug('File'.magenta, 'start_watching'.blue, self.path.green);
99
100 self.watchedPaths.push(self.path);
101
102 if (self.fastWatch) {
103 self.fileWatcher = fs.watch(self.path, self._watchHandler);
104 self.watchers.push(self.fileWatcher);
105 } else {
106 fs.watchFile(self.path, self._watchHandler);
107 };
108
109};
110
111File.prototype.read = function() {
112
113 var self = this;
114
115 debug('File'.magenta, 'read'.blue, self.path.magenta, 'Path Only: ' + self.pathsOnly);
116
117 if (self.pathsOnly) {
118
119 self.fileContents = self.path;
120 return when(self.fileContents = self.path);
121
122 } else if (
123 self.existingManifest &&
124 self.stats.mtime.getTime() == new Date(self.existingManifest.mtime).getTime()
125 ) {
126 self.fileData = self.existingManifest.fileData;
127 self.fileContents = self.existingManifest.fileContents;
128 delete self.existingManifest;
129 self.precompiled = true;
130 return when();
131 } else
132 return self.readFile();
133};
134
135File.prototype.readFile = function(){
136 var self = this;
137
138 return fs.readFile(self.path, self.binary)
139 .then(function(fileContents) {
140 // fileContents gets compiled, converted, required, etc
141 // so we keep the original fileData
142 self.fileData = self.fileContents = fileContents.toString();
143 })
144 .otherwise(function(er) {
145
146 debug('Error reading file'.red, er, er.stack)
147
148 if (_.contains(self.watchedPaths, self.path))
149 self.watchedPaths.splice(_.indexOf(self.watchedPaths, self.path), 1);
150
151 delete self.output[self.key];
152
153 if (self.fast_watch) {
154 if (_.contains(self.watchers, self.fileWatcher))
155 self.watchers.splice(_.indexOf(self.watchers, self.fileWatcher), 1);
156 self.fileWatcher && self.fileWatcher.close();
157 } else
158 fs.unwatchFile(self.path);
159
160 throw er;
161 });
162
163};
164
165File.prototype._watchHandler = function() {
166
167 var self = this;
168 debugBase('loaddir:watch')('File'.magenta, 'watchHandler'.blue, this.path.green);
169
170 if (self.watchHandler)
171 self.watchHandler();
172 else
173 self.load();
174
175}
176
177var IMAGE_FORMATS = [
178 '.png',
179 '.gif',
180 '.jpg',
181 '.jpeg',
182];
183
184// Default is just combine the same baseName and extension
185var toFilename = function(baseName, ext) {
186 return baseName + ext;
187};
188
189module.exports = File;