UNPKG

6.82 kBJavaScriptView Raw
1#!/usr/bin/env node
2/**
3 * @fileOverview
4 * A bootstrap script that creates some basic required objects
5 * for loading other scripts. This variant provides the glue
6 * to run on top of Node.js rather than Java+Rhino.
7 * @author Aaron Wirtz, me@awirtz.com
8 */
9
10// load the node.js libraries to be abstracted
11var fs = require('fs');
12var Script = process.binding('evals').Script;
13
14// define a few globals to be compatible with jsrun.jar
15global.arguments = process.argv.slice(2);
16load = function(file) {
17 Script.runInThisContext(fs.readFileSync(file), file);
18};
19print = console.log;
20quit = process.exit;
21
22/**
23 * @namespace Keep track of any messages from the running script.
24 */
25LOG = {
26 warn: function(msg, e) {
27 if (JSDOC.opt.q) return;
28 if (e) msg = e.fileName+", line "+e.lineNumber+": "+msg;
29
30 msg = ">> WARNING: "+msg;
31 LOG.warnings.push(msg);
32 if (LOG.out) LOG.out.write(msg+"\n");
33 else print(msg);
34 },
35
36 inform: function(msg) {
37 if (JSDOC.opt.q) return;
38 msg = " > "+msg;
39 if (LOG.out) LOG.out.write(msg+"\n");
40 else if (typeof LOG.verbose != "undefined" && LOG.verbose) print(msg);
41 }
42};
43LOG.warnings = [];
44LOG.verbose = false;
45LOG.out = undefined;
46
47/**
48 * @class Manipulate a filepath.
49 */
50FilePath = function(absPath, separator) {
51 this.slash = separator || "/";
52 this.root = this.slash;
53 this.path = [];
54 this.file = "";
55
56 var parts = absPath.split(/[\\\/]/);
57 if (parts) {
58 if (parts.length) this.root = parts.shift() + this.slash;
59 if (parts.length) this.file = parts.pop();
60 if (parts.length) this.path = parts;
61 }
62
63 this.path = this.resolvePath();
64}
65
66/** Collapse any dot-dot or dot items in a filepath. */
67FilePath.prototype.resolvePath = function() {
68 var resolvedPath = [];
69 for (var i = 0; i < this.path.length; i++) {
70 if (this.path[i] == "..") resolvedPath.pop();
71 else if (this.path[i] != ".") resolvedPath.push(this.path[i]);
72 }
73 return resolvedPath;
74}
75
76/** Trim off the filename. */
77FilePath.prototype.toDir = function() {
78 if (this.file) this.file = "";
79 return this;
80}
81
82/** Go up a directory. */
83FilePath.prototype.upDir = function() {
84 this.toDir();
85 if (this.path.length) this.path.pop();
86 return this;
87}
88
89FilePath.prototype.toString = function() {
90 return this.root
91 + this.path.join(this.slash)
92 + ((this.path.length > 0)? this.slash : "")
93 + this.file;
94}
95
96/**
97 * Turn a path into just the name of the file.
98 */
99FilePath.fileName = function(path) {
100 var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0);
101 return path.substring(nameStart);
102}
103
104/**
105 * Get the extension of a filename
106 */
107FilePath.fileExtension = function(filename) {
108 return filename.split(".").pop().toLowerCase();
109};
110
111/**
112 * Turn a path into just the directory part.
113 */
114FilePath.dir = function(path) {
115 var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0);
116 return path.substring(0, nameStart-1);
117}
118
119
120/**
121 * @namespace A collection of information about your system.
122 */
123SYS = {}
124/**
125 * Which way does your slash lean.
126 * @type string
127 */
128SYS.slash = "/";
129/**
130 * The absolute path to the directory containing this script.
131 * @type string
132 */
133SYS.pwd = __dirname+SYS.slash;
134
135
136/**
137 * @namespace A collection of functions that deal with reading a writing to disk.
138 */
139IO = {
140
141 /**
142 * Create a new file in the given directory, with the given name and contents.
143 */
144 saveFile: function(/**string*/ outDir, /**string*/ fileName, /**string*/ content) {
145 fs.writeFileSync(outDir + "/" + fileName, content, IO.encoding);
146 },
147
148 /**
149 * @type string
150 */
151 readFile: function(/**string*/ path) {
152 return fs.readFileSync(path, IO.encoding);
153 },
154
155 /**
156 * @param inFile
157 * @param outDir
158 * @param [fileName=The original filename]
159 */
160 copyFile: function(/**string*/ inFile, /**string*/ outDir, /**string*/ fileName) {
161 if (fileName == null) fileName = FilePath.fileName(inFile);
162
163 var inFile = fs.openSync(inFile, "r");
164 var outFile = fs.openSync(outDir+"/"+fileName, "w");
165
166 var buf = new Buffer(4096);
167
168 while (fs.readSync(inFile, buf, 0, buf.length) > 0) {
169 fs.writeSync(outFile, buf);
170 }
171
172 fs.closeSync(inFile);
173 fs.closeSync(outFile);
174 },
175
176 /**
177 * Creates a series of nested directories.
178 */
179 mkPath: function(/**Array*/ path) {
180 if (path.constructor != Array) path = path.split(/[\\\/]/);
181 var make = "";
182 for (var i = 0, l = path.length; i < l; i++) {
183 make += path[i] + SYS.slash;
184 if (! IO.exists(make)) {
185 IO.makeDir(make);
186 }
187 }
188 },
189
190 /**
191 * Creates a directory at the given path.
192 */
193 makeDir: function(/**string*/ path) {
194 fs.mkdirSync(path, 0777);
195 },
196
197 /**
198 * @type string[]
199 * @param dir The starting directory to look in.
200 * @param [recurse=1] How many levels deep to scan.
201 * @returns An array of all the paths to files in the given dir.
202 */
203 ls: function(/**string*/ dir, /**number*/ recurse, _allFiles, _path) {
204 if (_path === undefined) { // initially
205 var _allFiles = [];
206 var _path = [dir];
207 }
208 if (_path.length == 0) return _allFiles;
209 if (recurse === undefined) recurse = 1;
210
211 var s = fs.statSync(dir);
212 if (!s.isDirectory()) return [dir];
213 var files = fs.readdirSync(dir);
214
215 for (var f = 0; f < files.length; f++) {
216 var file = files[f];
217 if (file.match(/^\.[^\.\/\\]/)) continue; // skip dot files
218
219 if ((fs.statSync(_path.join("/")+"/"+file).isDirectory())) { // it's a directory
220 _path.push(file);
221 if (_path.length-1 < recurse) IO.ls(_path.join("/"), recurse, _allFiles, _path);
222 _path.pop();
223 }
224 else {
225 _allFiles.push((_path.join("/")+"/"+file).replace("//", "/"));
226 }
227 }
228
229 return _allFiles;
230 },
231
232 /**
233 * @type boolean
234 */
235 exists: function(/**string*/ path) {
236 try {
237 fs.statSync(path);
238 return true;
239 } catch(e) {
240 return false;
241 }
242 },
243
244 /**
245 *
246 */
247 open: function(/**string*/ path, /**boolean*/ append) {
248 if(append == null) append = true;
249 return fs.createWriteStream(path, {flags: (append ? "a" : "w")});
250 },
251
252 /**
253 * Sets {@link IO.encoding}.
254 * Encoding is used when reading and writing text to files,
255 * and in the meta tags of HTML output.
256 */
257 setEncoding: function(/**string*/ encoding) {
258 if (/UTF-8/i.test(encoding)) {
259 IO.encoding = "utf8";
260 }
261 else if (/ASCII/i.test(encoding)) {
262 IO.encoding = "ascii";
263 }
264 else {
265 throw("Unsupported encoding: "+encoding+" - perhaps you can use UTF-8?");
266 }
267 },
268
269 /**
270 * @default "utf8"
271 * @private
272 */
273 encoding: "utf8",
274
275 /**
276 * Load the given script.
277 */
278 include: function(relativePath) {
279 load(SYS.pwd+relativePath);
280 },
281
282 /**
283 * Loads all scripts from the given directory path.
284 */
285 includeDir: function(path) {
286 if (!path) return;
287
288 for (var lib = IO.ls(SYS.pwd+path), i = 0; i < lib.length; i++)
289 if (/\.js$/i.test(lib[i])) load(lib[i]);
290 }
291}
292
293// now run the application
294IO.include("frame.js");
295IO.include("main.js");
296
297main();