source: gs3-extensions/web-audio/trunk/js-mad/sink.js-master/build@ 28388

Last change on this file since 28388 was 28388, checked in by davidb, 11 years ago

Set of JS, CSS, PNG etc web resources to support a mixture of audio player/document display capabilities

File size: 10.6 KB
Line 
1#!/usr/bin/env node
2
3/* vim: set filetype=javascript */
4
5var sys = require('util');
6
7function print(){
8 [].slice.call(arguments).forEach(function(a){
9 sys.puts(a);
10 });
11}
12
13function _path(){
14 return [].slice.call(arguments).map(function(a){return/^(.+)\/?$/.exec(a)[1]}).join('/');
15}
16
17function fh(str){
18 return str.replace(/[<>]/g, function(a){return a==='<'?'&lt;':'&gt;'});
19}
20
21function findByParam(arr, name, value) {
22 return arr.filter(function(obj){
23 return obj[name] === value;
24 });
25}
26
27function __extend(obj){
28 var args = arguments,
29 l = args.length,
30 i, n;
31 for (i=1; i<l; i++){
32 for (n in args[i]){
33 if (args[i].hasOwnProperty(n)){
34 obj[n] = args[i][n];
35 }
36 }
37 }
38 return obj;
39}
40
41var paramon = require('paramon');
42var fs = require('fs');
43var Builder = require('script-builder');
44
45function ls(path, r){
46 path = path instanceof Array ? _path.apply(null, path) : path;
47 path = fs.readdirSync(path);
48 if (r){
49 for (var i=0; i<path.length; i++){
50 if (!r.exec(path[i])){
51 path.splice(i--, 1);
52 }
53 }
54 }
55 return path;
56}
57
58function read(path, encoding){
59 path = path instanceof Array ? _path.apply(null, path) : path;
60 encoding = encoding || 'UTF-8';
61 return fs.readFileSync(path, encoding);
62}
63
64function save(path, data, encoding){
65 path = path instanceof Array ? _path.apply(null, path) : path;
66 encoding = encoding || 'UTF-8';
67 return fs.writeFileSync(path, data, encoding);
68}
69
70var __define = (function(){
71
72 if (Object.defineProperty){
73 return Object.defineProperty;
74 } else if (Object.prototype.__defineGetter__){
75 return function(obj, prop, desc){
76 desc.get && obj.__defineGetter__(prop, desc.get);
77 desc.set && obj.__defineSetter__(prop, desc.set);
78 }
79 }
80
81}());
82
83function __defineConst(obj, prop, value, enumerable){
84 if (__define){
85 __define(obj, prop, {
86 get: function(){
87 return value;
88 },
89 enumerable: !!enumerable
90 });
91 } else {
92 // Cheap...
93 obj[prop] = value;
94 }
95}
96
97function logicalMods(obj, name, value){
98 if (arguments.length < 3){
99 value = obj[name];
100 }
101 var pos = ['major', 'minor', 'patch'];
102 __define(obj, name, {
103 set: function(val){
104 var op = typeof val === 'string' ? val.split(' ') : val;
105 var r = typeof value === 'string' ? value.split('.') : value;
106 var n = [];
107 if (op && op instanceof Array){
108 op.slice(1).forEach(function(o){
109 o = pos.indexOf(o);
110 o !== -1 && n.push(o);
111 });
112 !n.length && n.push(0);
113 n.forEach(function(n){
114 switch(op[0]){
115 case 'increment':
116 typeof r === 'number' ? r++ : r[n]++;
117 val = r instanceof Array ? r.join('.') : r;
118 break;
119 case 'decrement':
120 typeof r === 'number' ? r-- : r[n]--;
121 val = r instanceof Array ? r.join('.') : r;
122 break;
123 }
124 });
125 }
126 value = val;
127 },
128 get: function(){
129 return value;
130 },
131 });
132}
133
134var ArrayStuff = (function f(){
135var a = Array.prototype;
136a.copy = function(){return this.slice();};
137a.smap = function(s, r){
138 return this.map(function(t){
139 var x = r ? r.exec(t) : [t];
140 return s.replace(/\$([0-9]+)/g, function(q,n){
141 return x[n];
142 });
143 });
144};
145a.table = function(tabwidth){
146 tabwidth = isNaN(+tabwidth) ? 8 : +tabwidth;
147 var w = [];
148 this.forEach(function(r){
149 r.forEach(function(c, i){
150 w[i] = Math.max(Math.ceil(c.length / tabwidth), w[i] || 0);
151 });
152 });
153 return this.map(function(r){
154 var l = r.length - 1,
155 s = '',
156 i;
157 for (i=0; i<l; i++){
158 s += r[i] + Array(1 + w[i] - Math.floor(r[i].length / tabwidth)).join('\t');
159 }
160 return s + r[i];
161 }).join('\n');
162};
163return f;
164}());
165
166Builder.context(ArrayStuff);
167
168function builderContext(s){
169 s = s || {};
170
171 Builder.Comment.prototype.toString = function(){
172 return this.assignName || this.name || Object.prototype.toString.call(this);
173 };
174
175 var builder = Builder.Builder(s);
176 var cp = Builder.CommentParser();
177
178 function group(name){
179 arguments.length > 1 && group.apply(this, [].slice.call(arguments, 1));
180 var g = builder.variables[name + 's'] = [];
181 var sg = builder.variables['sub' + name + 's'] = [];
182 builder.instructions.push({
183 name: name,
184 exec: function(args){
185 args = args.split(/\s+/g);
186 args[1] = args[1] || args[0];
187 builder.variables[name + 's'].push({name: args[0], assignName: args[1]});
188 }
189 }, {
190 name: 'sub' + name,
191 exec: function(args){
192 args = args.split(/\s+/g);
193 args[2] = args[2] || args[0] + args[1];
194 builder.variables['sub' + name + 's'].push({subOf: args[0], name: args[1], assignName: args[2], toString: Builder.Comment.prototype.toString});
195 }
196 });
197 cp.commands.push({
198 name: name,
199 exec: function(args){
200 args = args ? args.split(/\s+/g) : [];
201 this.assignName = args[0];
202 !this.assignName && this.onfinish(function(){
203 this.assignName = this.name;
204 });
205 this[name] = true;
206 builder.variables[name + 's'].push(this);
207 }
208 }, {
209 name: 'sub' + name,
210 exec: function(args){
211 args = args ? args.split(/\s+/g) : [];
212 this.subOf = args[0];
213 this.assignName = args[1];
214 !this.name && !this.assignName && this.onfinish(function(){
215 this.assignName = args[0] + this.name;
216 });
217 this[name] = true;
218 this['sub' + name] = true;
219 builder.variables['sub' + name + 's'].push(this);
220 }
221 });
222 }
223
224 group('generator', 'effect', 'control', 'processor');
225
226 cp.commands.push({
227 name: 'param',
228 exec: function(args){
229 if (!args) return;
230 var params = this.params = this.params || [],
231 p = {},
232 s, x;
233 while (s = /^([^\s]+)\s*/.exec(args)){
234 args = args.substr(s[0].length);
235 s = s[1];
236
237 x = /^\{(.+)\}$/.exec(s);
238 if (x) {
239 p.type = x[1];
240 continue;
241 }
242
243 x = /^(.+):(.*)$/.exec(s);
244 if (x) {
245 p[x[1]] = x[2] || true;
246 continue;
247 }
248
249 p.name = s;
250 p.description = args;
251 args = '';
252 break;
253 }
254 params.push(p);
255 }
256 }, {
257 name: 'arg',
258 exec: function(args){
259 if (!args) return;
260 var arglist = this.arglist = this.arglist || [],
261 p = {},
262 s, x;
263 while (s = /^([^\s]+)\s*/.exec(args)){
264 args = args.substr(s[0].length);
265 s = s[1];
266
267 x = /^\{(.+)\}$/.exec(s);
268 if (x) {
269 p.type = x[1];
270 continue;
271 }
272
273 x = /^(.+):(.*)$/.exec(s);
274 if (x) {
275 p[x[1]] = x[2] || true;
276 continue;
277 }
278
279 while (/^[^\w]/.exec(s)) {
280 switch(s[0]) {
281 case '!':
282 p.optional = true; break;
283 case '=':
284 p.assignsToClass = true; break;
285 }
286 s = s.substr(1);
287 }
288 p.name = s;
289 p.description = args;
290 args = '';
291 break;
292 }
293 arglist.push(p);
294 }
295 }, {
296 name: 'return',
297 exec: function(args){
298 if (!args) return;
299 var p = {},
300 s, x, desc;
301 while (s = /^([^\s]+)\s*/.exec(args)){
302 desc = args;
303 args = args.substr(s[0].length);
304 s = s[1];
305
306 x = /^\{(.+)\}$/.exec(s);
307 if (x) {
308 p.type = x[1];
309 continue;
310 }
311
312 p.description = desc;
313 args = '';
314 break;
315 }
316 this.returns = p;
317 }
318 }, {
319 name: 'method',
320 exec: function(args){
321 args = args ? args.split(/\s+/g) : [];
322 this.method = true;
323 if (args[0]) {
324 this.methodOf = args[0];
325 }
326 }
327 }, {
328 name: 'static',
329 exec: function(args){
330 args = args ? args.split(/\s+/g) : [];
331 this.static = true;
332 this.method = true;
333 if (args[0]) {
334 this.methodOf = args[0];
335 }
336 }
337 }, {
338 name: 'class',
339 exec: function(args){
340 this.class = true;
341 }
342 });
343
344 builder.group = group;
345
346 builder.addPostProcessor(cp);
347 builder.commentParser = cp;
348
349 return builder;
350}
351
352
353if (process.argv.length < 3){
354 throw "Try build -h for help.";
355}
356
357var args = paramon.readFormat(process.argv, {
358 name: 'build',
359 usage: 'command [options]',
360 params: [
361 {
362 name: 'debug',
363 args: ['--debug', '-d'],
364 desc: 'Run in debug mode (more verbose error messages).',
365 maxParams: 0,
366 },
367 {
368 name: 'update',
369 args: ['update', '-u'],
370 desc: 'Update target (wrappers).',
371 minParams: 1,
372 maxParams: -1,
373 }
374 ],
375});
376
377!args.debug && process.on('uncaughtException', function(e){
378 print(e.toString());
379 process.exit(1);
380});
381
382args['$!stray'].forEach(function(e){
383 print('Unknown build command "' + e + '".');
384 process.exit();
385});
386
387var updatables = {
388 'docs': function(){
389 var builder = builderContext();
390 builder.run(read('sink.js'), 'sink.js');
391
392 builder.commentParser.comments.forEach(function(comment){
393 // This is probably unnecessary payload.
394 delete comment.body;
395 });
396
397 var comments = builder.commentParser.comments.filter(function (func) {
398 return func.assignName || func.class;
399 });
400
401 builder.commentParser.comments.forEach(function(func){
402 if (!func.method) return;
403 var parent = func.methodOf && findByParam(comments, 'name', func.methodOf)[0];
404 if (parent) {
405 parent.methods = parent.methods || [];
406 parent.methods.push(func);
407// } else {
408// methods.push(func);
409 }
410 });
411
412 var docs = '# sink.js\n\n';
413
414 comments.forEach(function (func) {
415 docs += '## ' + (func.static ? func.methodOf + '.' : '') + (func.assignName || func.name) + '\n\n';
416 docs += func.text + '\n\n';
417
418 if (func.arglist) {
419 docs += '### Arguments\n\n';
420 func.arglist.forEach(function(arg){
421 var info = arg.assignsToClass ? findByParam(func.params, 'name', arg.name)[0] || arg : arg;
422 docs += ' * ';
423 if (arg.optional) docs += '(Optional) ';
424 if (info.type) docs += '(' + fh(info.type) + ') ';
425 docs += info.name;
426 docs += ': ' + info.description;
427 docs += '\n';
428 });
429 docs += '\n';
430 }
431
432 if (func.methods) {
433 docs += '### Methods\n\n';
434 func.methods.forEach(function(method){
435 docs += '#### ';
436 if (method.static) {
437 docs += '(Static) ';
438 }
439 docs += method.name + '(';
440 if (method.arglist) {
441 docs += method.arglist.map(function(a){ return a.name }).join(', ');
442 }
443 docs += ')\n\n' + method.text + '\n\n';
444 if (method.arglist) {
445 docs += '##### Arguments\n\n';
446 method.arglist.forEach(function(arg){
447 var info = arg.assignsToClass ? findByParam(func.params, 'name', arg.name)[0] || arg : arg;
448 docs += ' * ';
449 if (arg.optional) docs += '(Optional) ';
450 if (info.type) docs += '(' + fh(info.type) + ') ';
451 docs += info.name;
452 docs += ': ' + info.description;
453 docs += '\n';
454 });
455 docs += '\n';
456 }
457
458 if (method.returns) {
459 docs += '##### Returns\n\n';
460 if (method.returns.type) docs += '(' + fh(method.returns.type) + ') ';
461 docs += method.returns.description;
462 docs += '\n\n';
463 }
464 });
465 }
466 });
467
468 save('DOCS.md', docs);
469 print('Documentation updated.');
470 },
471};
472
473if (args.update) {
474 args.update.forEach(function(e){
475 e = e.toLowerCase();
476 var k;
477 if (e === 'all') {
478 for (k in updatables){
479 if (updatables.hasOwnProperty(k)){
480 updatables[k]();
481 }
482 }
483 } else if (e in updatables) {
484 updatables[e]();
485 } else {
486 throw 'Unknown update target "' + e + '".';
487 }
488 });
489 process.exit();
490}
Note: See TracBrowser for help on using the repository browser.