UNPKG

5.19 kBJavaScriptView Raw
1var Path = require('path');
2var required = require('required');
3var fs = require('fs-extra');
4require('colors');
5var path = [];
6var index = 0;
7var modules;
8
9var prefix = "denodify('replace',function(require, module, exports, __filename, __dirname, process) {";
10var postfix = "});";
11
12//Utility functions to enable use of nodejs modules in the browser. Used in
13//[html-builder](http://github.com/Michieljoris/html-builder) and
14//[bb-server](http://github.com/Michieljoris/bb-server).
15
16//###wrap
17
18//Wrap a `string` of a nodejs module with the proper code to enable its use in
19//the browser. Specify the `language` your nodejs module is written in to match
20//the added code to the code of the module. Defaults to javascript.
21
22//If you leave 2 lines open at the top of every module wrap will replace the top
23//line with the prefix wrapping code. This way line numbers in your modules will
24//match the line numbers of the javascript file loaded in the browser
25exports.wrap = function(moduleid, string) {
26 console.log('in nodify.wrap', moduleid);
27 if (string[0] === '\n') string = string.slice(1);
28 var newPrefix = prefix.replace(/replace/g, Path.join('/', moduleid));
29 // postfix = postfix.replace(/__dirname/, Path.dirname(module));
30 return newPrefix + string + postfix;
31};
32
33//###script
34
35//Script to load in your html file before all denodified scripts.
36exports.script = fs.readFileSync(__dirname + '/denodify.js');
37
38//###tags
39
40//Given a main `module`, parses it for require calls, loads the corresponding
41//module files and recursively parses them. Once all dependencies are found
42//calls the `callback` with a list of tags that if loaded in the browser in the
43//listed order all dependencies would be fullfilled for each module.
44
45//Callback is called with an error if a circular dependency is found or a
46//dependency is found that is not in the `www` directory, or if any other error
47//occurs.
48
49//* `www` : the directory the server's root.
50//* `parent` : the path from `www` to the main module
51//* `module` : the id of the file if you were requiring it (without the js)
52//* `callback` : called as `callback(err, list)`.
53// Return a list of script tags to add to a html file.
54exports.tags = function(www, parent, module, callback, listOnly) {
55 list(www, parent, module, callback, false);
56};
57
58//###list
59
60//Same as tags, however returns only the properly ordered list of module ids and
61//corresponding file names.
62exports.list = function(www, parent, module, callback, listOnly) {
63 list(www, parent, module, callback, true);
64};
65
66exports.debug = false;
67
68function walk(module) {
69 modules[module.id] = module;
70 path.push(module.id);
71 module.index = -1;
72 module.deps.forEach(function(d) {
73 d = modules[d.id] || d;
74 if (d.index === undefined) walk(d);
75 else if (d.index < 0) {
76 var str = "Module " + module.id + " is dependent on module " + d.id +
77 '. However, module ' + d.id + ' is also directly or indirectly dependent on module ' +
78 module.id + ".\nDependency path to this point: \n" + path.join(' relies on \n') +
79 ' relies on ' + d.id;
80 console.log(str.red);
81 }
82 });
83 module.index = index++;
84 path.pop();
85}
86
87function endsWith(str, trail) {
88 return (str.substr(str.length-trail.length, str.length-1) === trail);
89};
90
91function trailWith(str, trail) {
92 return str ? (str + (!endsWith(str, trail) ? trail : '')) : undefined;
93};
94
95function list(www, parent, id, cb, listOnly) {
96 try
97 { www = Path.resolve(www);
98 parent = Path.resolve(www, parent);
99 debug('Resolving: ' + id + ' in directory ' + parent);
100 var fileName = Path.resolve(parent, trailWith(id, '.js'));
101 try {
102 fs.statSync(fileName);
103 } catch(e) { cb(e,null);
104 return;}
105
106 required(fileName, {
107 includeSource: false
108 }, function(err, deps) {
109 if (err) throw err;
110 else {
111
112 modules = [];
113 walk({
114 id: id,
115 filename: fileName,
116 deps: deps,
117 index: -1
118 });
119 var list = Object.keys(modules).map(function(m) {
120 m = modules[m];
121 var startWithWwwPath = m.filename.indexOf(www) === 0;
122 if (!startWithWwwPath)
123 throw 'Warning: ' + m.id + ' was found outside the www directory (' + www + ')';
124 m.route = m.filename.slice(www.length);
125 debug('module:',m);
126 return m;
127 }).sort(function(a, b) {
128 return a.index > b.index;
129 }).map(function(m) {
130 return listOnly ?
131 { id: m.id, route: m.route, filename: m.filename } :
132 "<script type=\"text/javascript\" src=\"" + m.route + "\"></script>";
133 });
134 debug('Debug:\n', list);
135 cb(null, list);
136 }
137 });
138 } catch(e) {
139 cb(e, null);
140 }
141};
142
143function debug() {
144 if (exports.debug) console.log.apply(console, arguments);
145}
146
147
148
149// list('../', './test', './m3', function(err, tags) {
150// console.log();
151// console.log(tags);
152// }, true);