UNPKG

5.76 kBJavaScriptView Raw
1var FS = require('fs'),
2 PATH = require('path'),
3 FREEZE = require('./freeze'),
4 INHERIT = require('inherit'),
5 U = require('./util'),
6 VOW = require('vow');
7
8function _inherit(d, s) {
9 return INHERIT(this, d, s);
10}
11
12exports.Tech = INHERIT({
13
14 __constructor: function(opts) {
15 this.opts = opts;
16
17 /**
18 * Hash of processed files to remove duplicates.
19 * @type {Object}
20 */
21 this.processedFiles = {};
22 },
23
24 createFile: function(path, type, parent) {
25 var file = new this.File(this, path, type, parent);
26 if (type == 'include') file.read();
27 return file;
28 },
29
30 process: function() {
31 var res;
32 var path = this.opts.input;
33 if (path) {
34 res = this.createFile(path, 'include').process(path);
35 } else {
36 var fakeFile = PATH.join(this.opts.basePath, 'borschik.fakefile');
37 var file = new this.File(this, fakeFile, 'include');
38 file.content = file.parse(this.opts.inputString);
39 //TODO: i call ctor with path and then call method with same path. WTF?
40 res = file.process(fakeFile);
41 }
42 // NOTE: Passing path of source file into process(). This could lead to
43 // incorrect paths in the resulting file if it will be stored in another
44 // directory then source file.
45
46 var out = this.opts.output;
47 if (this.opts.minimize) {
48 try {
49 res = this.minimize(res);
50
51 } catch(e) {
52 if (this.opts.inputString && !out.path) {
53 return VOW.reject(e);
54 }
55
56 var errorMessage = e.toString();
57
58 // if output is the path
59 if (out.path) {
60 // close current output stream
61 out.end();
62
63 if (path != out.path) {
64 // remove empty output file if input != ouput
65 FS.unlinkSync(out.path);
66 }
67 }
68
69 // open new stream for error result
70 var errorFilename;
71 if (out.path) {
72 errorFilename = out.path + '.borschik-error';
73 } else {
74 errorFilename = PATH.resolve(process.cwd(), 'borschik-error');
75 }
76
77 out = FS.createWriteStream(errorFilename, {
78 encoding: 'utf8'
79 });
80
81 errorMessage += '\nError result in ' + errorFilename;
82
83 return this.write(out, res).then(function() {
84 throw errorMessage;
85 });
86
87 }
88 }
89
90 if (this.opts.inputString && !this.opts.output.path) {
91 return VOW.resolve(res);
92 } else {
93 return this.write(out, res);
94 }
95 },
96
97 write: U.writeFile,
98
99 minimize: function(content) {
100 return content;
101 },
102
103 File: exports.File = INHERIT({
104
105 __constructor: function(tech, path, type, parent) {
106 this.tech = tech;
107 // realpathSync processes path with "follow_symlinks" directive
108 this.path = PATH.resolve(PATH.dirname(path), FREEZE.realpathSync(path));
109 this.childType = type || 'include';
110 this.parent = parent;
111 this.children = {};
112 },
113
114 read: function() {
115 this.content = this.parse(FS.readFileSync(this.processPath(this.path)));
116 return this;
117 },
118
119 processPath: function(path) {
120 return path;
121 },
122
123 parse: function(content) {
124 return this.childType == 'include'?
125 this.parseInclude(content) : this.parseLink(content);
126 },
127
128 parseInclude: function(content) {
129 return content;
130 },
131
132 parseLink: function(content) {
133 return this.path;
134 },
135
136 process: function(path) {
137 return this.childType == 'include'?
138 this.processInclude(path) : this.processLink(path);
139 },
140
141 processInclude: function(path) {
142 return this.content;
143 },
144
145 processLink: function(path) {
146 return this.pathFrom(path);
147 },
148
149 child: function(type, path) {
150 var children = this.children,
151 key = type + '|' + path;
152 return children[key] || (children[key] = this.tech.createFile(this.pathTo(path), type, this));
153 },
154
155 /**
156 * Returns absolute path to resource relative to current file.
157 * @param {string} resourcePath Path to resource relative to current file.
158 * @returns {string}
159 * @example
160 * // current file (this.path) /home/user/site/css/page.css
161 * this.pathTo(img/bg.png); // /home/user/site/css/img/bg.png
162 */
163 pathTo: function(resourcePath) {
164 return U.pathToUnix(PATH.resolve(PATH.dirname(this.path), resourcePath));
165 },
166
167 pathFrom: function(path) {
168 return U.pathToUnix(PATH.relative(PATH.dirname(path), this.path));
169 }
170
171 }, {
172 inherit: _inherit
173 })
174
175 }, {
176 inherit: _inherit
177 });