js2 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ 0.3.6
2
+ * Verbosity mode
3
+ * Fixed ruby file "watch" mode
4
+ * Cleaned up rack hooks
5
+
1
6
  0.3.5
2
7
  * Added scope and binding support to shorthand functions
3
8
  * Added support for modules
@@ -0,0 +1,278 @@
1
+ (function (root) {
2
+ // temporarily set root
3
+ // to JS2 global var for this scope
4
+ function mainFunction (arg) {
5
+ if (typeof arg == 'string') {
6
+ return JS2.Parser.parse(arg).toString();
7
+ } else if (arg instanceof Array) {
8
+ return new JS2.Array(arg);
9
+ } else {
10
+ return new JS2.Array();
11
+ }
12
+ }
13
+
14
+
15
+ if (!root.console) {
16
+ root.console = {};
17
+ console.log = function (m) {};
18
+ }
19
+
20
+ var JS2 = root.JS2 = mainFunction;
21
+ var js2 = root.js2 = JS2;
22
+ js2.VERSION = "0.3.6";
23
+
24
+ JS2.ROOT = JS2;
25
+
26
+
27
+ // CLASS HELPERS
28
+ (function (undefined, JS2) {
29
+
30
+ var OO = function (klass, par) {
31
+ this.klass = klass;
32
+ this.par = par;
33
+
34
+ this.members = {};
35
+ this.staticMembers = {};
36
+ this.children = [];
37
+ this.included = [];
38
+
39
+ if (this.par) this.par.OO.children.push(klass);
40
+ };
41
+
42
+ OO.prototype = {
43
+ forbiddenMembers: {
44
+ 'prototype': undefined,
45
+ 'OO': undefined
46
+ },
47
+
48
+ include: function(module) {
49
+ this.included.push(module);
50
+ var members = module.OO.members;
51
+ for (var name in members) {
52
+ if (members.hasOwnProperty(name)) {
53
+ this.addMember(name, members[name]);
54
+ }
55
+ }
56
+
57
+ var staticMembers = module.OO.staticMembers;
58
+ for (var name in staticMembers) {
59
+ if (staticMembers.hasOwnProperty(name)) {
60
+ this.addStaticMember(name, staticMembers[name]);
61
+ }
62
+ }
63
+
64
+ if (typeof staticMembers['included'] == 'function') {
65
+ staticMembers['included'](this.klass);
66
+ }
67
+ },
68
+
69
+ createNamespace: function(name) {
70
+ var splitted = name.split('.');
71
+ var klassName = splitted.pop();
72
+ var root = JS2.ROOT;
73
+
74
+ while (splitted.length > 0) {
75
+ var name = splitted.shift();
76
+ if (!root[name]) root[name] = JS2.Class.extend({});
77
+ root = root[name];
78
+ }
79
+
80
+ return [ root, klassName ];
81
+ },
82
+
83
+ makeSuper: function(newMethod, oldMethod) {
84
+ if (!oldMethod) return newMethod;
85
+
86
+ return function() {
87
+ this.$super = oldMethod;
88
+ return newMethod.apply(this, arguments);
89
+ };
90
+ },
91
+
92
+ addMember: function(name, member) {
93
+ if (this.forbiddenMembers.hasOwnProperty(name)) return;
94
+
95
+ var proto = this.klass.prototype;
96
+ if (typeof proto[name] == 'function' && !(proto[name] instanceof RegExp)) {
97
+ member = this.makeSuper(member, proto[name]);
98
+ }
99
+
100
+ proto[name] = member;
101
+ this.members[name] = member;
102
+ },
103
+
104
+ addStaticMember: function(name, member) {
105
+ if (this.forbiddenMembers.hasOwnProperty(name)) return;
106
+
107
+ if (typeof this.klass[name] == 'function') {
108
+ if (!this.klass.hasOwnProperty(name)) {
109
+ member = this.makeSuper(member, this.klass[name]);
110
+ }
111
+ }
112
+
113
+ this.klass[name] = member;
114
+ this.staticMembers[name] = member;
115
+ }
116
+ };
117
+
118
+ JS2.Class = function() { this.initialize.apply(this, arguments); };
119
+ JS2.Class.OO = new OO(JS2.Class);
120
+ JS2.Class.prototype = {
121
+ initialize: function () {},
122
+ oo: JS2.Class.OO
123
+ };
124
+
125
+ var namedClasses = {};
126
+ JS2.getClass = function(name) {
127
+ return namedClasses[name];
128
+ };
129
+
130
+ var noInit = false;
131
+ JS2.Class.extend = function(name, klassDef) {
132
+ var klass = function() { if (!noInit) this.initialize.apply(this, arguments); };
133
+ klass.OO = new OO(klass, this);
134
+
135
+ if (typeof name != 'string') {
136
+ klassDef = name;
137
+ } else {
138
+ namedClasses[name] = klass;
139
+ var namespace = this.OO.createNamespace(name);
140
+ namespace[0][namespace[1]] = klass;
141
+ }
142
+
143
+ // create instance of this as prototype for new this
144
+ noInit = true;
145
+ var proto = new this();
146
+ noInit = false;
147
+
148
+ klass.prototype = proto;
149
+ var oo = klass.OO;
150
+ proto.OO = oo;
151
+
152
+ for (var name in this) {
153
+ oo.addStaticMember(name, this[name]);
154
+ }
155
+
156
+ if (typeof klassDef == 'function') {
157
+ klassDef(klass, oo);
158
+ } else {
159
+ for (var name in klassDef) {
160
+ oo.addMember(name, klassDef[name]);
161
+ }
162
+ }
163
+
164
+ return klass;
165
+ };
166
+
167
+ JS2.Module = JS2.Class;
168
+
169
+ var assert = {
170
+ 'eq': function(expected, actual) { if (expected != actual) console.log("Expected "+expected+", but got "+actual+".") },
171
+ 'isFalse': function(val) { if (val) console.log("Expected false, but got "+val+".") },
172
+ 'isTrue': function(val) { if (!val) console.log("Expected true, but got " +val+".") }
173
+ };
174
+
175
+ JS2.test = function(message, callback) {
176
+ if (!callback) callback = message;
177
+ callback(assert);
178
+ };
179
+
180
+
181
+ return JS2;
182
+ })(undefined, JS2);
183
+
184
+ JS2.Array = function (arr) {
185
+ if (arr instanceof Array) {
186
+ this.append(arr);
187
+ }
188
+ };
189
+
190
+ JS2.Array.prototype = new Array();
191
+ JS2.Array.prototype.each = function(f) {
192
+ for (var i=0; i<this.length; i++) {
193
+ f.call(this, this[i], i );
194
+ }
195
+ return this;
196
+ };
197
+
198
+ JS2.Array.prototype.toString = function() {
199
+ return this.join(',');
200
+ };
201
+
202
+
203
+ JS2.Array.prototype.until = function(f) {
204
+ for (var i=0; i<this.length; i++) {
205
+ if (f.call(this, this[i], i )) return true;;
206
+ }
207
+ return false;
208
+ };
209
+
210
+
211
+ JS2.Array.prototype.collect = function(f) {
212
+ var ret = new JS2.Array();
213
+ var self = this;
214
+ this.each(function($1,$2,$3){ ret.push(f.call(self, $1, $2)) });
215
+ return ret;
216
+ };
217
+
218
+ // http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/reduce
219
+ JS2.Array.prototype.reduce = function(f, val) {
220
+ if (this.length == 0) return val;
221
+ if (this.length == 1) return val == null ? f(this[0]) : f(val, this[0]);
222
+
223
+ var i = 0;
224
+ if (val == null) val = this[i++];
225
+
226
+ for (var n=this.length;i<n;i++) {
227
+ val = f(val, this[i]);
228
+ }
229
+
230
+ return val;
231
+ };
232
+
233
+ JS2.Array.prototype.reject = function(f) {
234
+ var ret = new JS2.Array();
235
+ if (f instanceof RegExp) {
236
+ this.each(function($1,$2,$3){ if (!$1.match(f)) ret.push($1) });
237
+ } else if (typeof f == 'string' || typeof f == 'number') {
238
+ this.each(function($1,$2,$3){ if ($1 != f) ret.push($1) });
239
+ } else if (typeof f == 'function') {
240
+ var self = this;
241
+ this.each(function($1,$2,$3){ if (!f.call(self, $1, $2)) ret.push($1) });
242
+ }
243
+ return ret;
244
+ };
245
+
246
+ JS2.Array.prototype.select = function(f) {
247
+ var ret = new JS2.Array();
248
+ if (f instanceof RegExp) {
249
+ this.each(function($1,$2,$3){ if ($1.match(f)) ret.push($1) });
250
+ } else if (typeof f == 'string' || typeof f == 'number') {
251
+ this.each(function($1,$2,$3){ if ($1 == f) ret.push($1) });
252
+ } else if (typeof f == 'function') {
253
+ var self = this;
254
+ this.each(function($1,$2,$3){ if (f.call(self, $1, $2)) ret.push($1) });
255
+ }
256
+ return ret;
257
+ };
258
+
259
+ JS2.Array.prototype.append = function(arr) {
260
+ this.push.apply(this, arr);
261
+ return this;
262
+ };
263
+
264
+ JS2.Array.prototype.empty = function() {
265
+ return this.length == 0;
266
+ };
267
+
268
+ JS2.Array.prototype.any = function() {
269
+ return this.length > 0;
270
+ };
271
+
272
+
273
+
274
+ js2.ROOT = root;
275
+
276
+ return JS2;
277
+
278
+ })(window);
data/lib/js2/fs.rb CHANGED
@@ -47,7 +47,7 @@ class JS2::FS
47
47
 
48
48
  def setInterval(code, time)
49
49
  while true
50
- @ctx.eval(code)
50
+ code.call()
51
51
  sleep(time/1000)
52
52
  end
53
53
  end
data/lib/js2/js2.js CHANGED
@@ -14,7 +14,7 @@ function mainFunction (arg) {
14
14
 
15
15
  var JS2 = root.JS2 = mainFunction;
16
16
  var js2 = root.js2 = JS2;
17
- js2.VERSION = "0.3.5";
17
+ js2.VERSION = "0.3.6";
18
18
 
19
19
  JS2.ROOT = JS2;
20
20
 
@@ -1233,6 +1233,7 @@ JS2.Class.extend('Updater', function(KLASS, OO){
1233
1233
  if (! this.fs.isDirectory(dir)) this.fs.mkpath(dir);
1234
1234
 
1235
1235
  if (force || this.fs.mtime(file) > this.fs.mtime(outFile)) {
1236
+ JS2.LOGGER.info(file + ' -> ' + outFile);
1236
1237
  if (funct) {
1237
1238
  this.fs.write(outFile, funct(JS2(this.fs.read(file))));
1238
1239
  } else {
@@ -1244,11 +1245,13 @@ JS2.Class.extend('Updater', function(KLASS, OO){
1244
1245
 
1245
1246
 
1246
1247
  JS2.Class.extend('Config', function(KLASS, OO){
1247
- OO.addMember("CLI_REGEX",/^-(r|i|f)(=(\w+))$/);
1248
+ OO.addMember("CLI_REGEX",/^-(r|i|f|n|v|m)(=(\w+))?$/);
1248
1249
  OO.addMember("optsLookup",{
1249
1250
  'n': 'non-recursive',
1250
1251
  'i': 'interval',
1251
- 'f': 'format'
1252
+ 'f': 'format',
1253
+ 'v': 'verbose',
1254
+ 'm': 'use_mtime'
1252
1255
  });
1253
1256
 
1254
1257
  OO.addMember("initialize",function (fs, argv) {
@@ -1292,8 +1295,10 @@ JS2.Class.extend('Config', function(KLASS, OO){
1292
1295
  this.interval = config['interval'] ? config['interval'] : this.interval;
1293
1296
  this.sourceDir = config['source-dir'] || this.sourceDir;
1294
1297
  this.outDir = config['out-dir'] || this.outDir;
1298
+ this.verbose = ('verbose' in config) ? config['verbose'] : false;
1295
1299
 
1296
1300
  this['non-recursive'] = config['non-recursive'];
1301
+ this['use-mtime'] = config['use-mtime'];
1297
1302
 
1298
1303
  return true;
1299
1304
  } catch(e) {
@@ -1308,31 +1313,32 @@ JS2.Class.extend('Config', function(KLASS, OO){
1308
1313
 
1309
1314
  JS2.Class.extend('Commander', function(KLASS, OO){
1310
1315
  OO.addMember("BANNER","js2 <command> [options] <arguments>\n" +
1311
- "VERSION: " + js2.VERSION + "\n" +
1316
+ "VERSION: " + JS2.VERSION + "\n" +
1312
1317
  "Commands:\n" +
1313
1318
  " * run <file> -- Executes file\n" +
1314
1319
  " * render <file> -- Shows JS2 compiled output\n" +
1315
1320
  " * compile <inDir> [outDir] -- Compiles a directory and puts js files into outDir. If outDir is not specified, inDir will be used\n" +
1316
1321
  " Options:\n" +
1317
1322
  " -n -- Do NOT traverse directories recursively\n" +
1323
+ " -v -- Verbose \n" +
1318
1324
  " -f=<format> -- Compile for different formats: node, ringo, or browser\n" +
1319
1325
  " * compile <file> -- Compiles a single js2 file into js\n" +
1320
1326
  " * watch <inDir> <outDir> -- Similar to compile, but update will keep looping while watching for modifications\n" +
1321
1327
  " Options:\n" +
1322
1328
  " -n -- Do NOT traverse directories recursively\n" +
1323
1329
  " -f=<format> -- Compile for different formats: node, ringo, or browser\n" +
1330
+ " -v -- Verbose \n" +
1324
1331
  " -i=<seconds> -- Interval time in seconds between loops\n");
1325
1332
 
1326
- OO.addMember("DEFAULT_CONFIG",{
1327
- compile: { inDir: 'src', outDir: 'lib', recursive: true, decorator: 'Node' },
1328
- watch: { inDir: 'src', outDir: 'lib', recursive: true, decorator: 'Node' }
1329
- });
1330
-
1331
1333
  OO.addMember("initialize",function (argv) {
1332
1334
  this.fs = JS2.fs;
1333
1335
  this.config = new JS2.Config(this.fs, argv);
1334
1336
  this.command = this.config.command;
1335
1337
 
1338
+ // HACK for now
1339
+ JS2.VERBOSE = this.config.verbose || false;
1340
+ JS2.LOGGER = { info: function($1,$2,$3){ if (JS2.VERBOSE) console.log($1) } };
1341
+
1336
1342
  switch(this.config.format) {
1337
1343
  case 'ringo': JS2.DECORATOR = new JS2.RingoDecorator(); break;
1338
1344
  case 'node': JS2.DECORATOR = new JS2.NodeDecorator(); break;
@@ -1349,7 +1355,7 @@ JS2.Class.extend('Commander', function(KLASS, OO){
1349
1355
  });
1350
1356
 
1351
1357
  OO.addMember("render",function () {
1352
- console.log(js2.render(this.fs.read(this.config.args[0])));
1358
+ JS2.LOGGER.info(js2.render(this.fs.read(this.config.args[0])));
1353
1359
  });
1354
1360
 
1355
1361
  OO.addMember("run",function () {
@@ -1362,7 +1368,8 @@ JS2.Class.extend('Commander', function(KLASS, OO){
1362
1368
 
1363
1369
  OO.addMember("compile",function () {
1364
1370
  var self = this;
1365
- this.getUpdater().update(true, function($1,$2,$3){ return JS2.DECORATOR.file($1); });
1371
+ var force = this.config['use-mtime'] ? false : true;
1372
+ this.getUpdater().update(force, function($1,$2,$3){ return JS2.DECORATOR.file($1); });
1366
1373
  });
1367
1374
 
1368
1375
  OO.addMember("getUpdater",function () {
@@ -1375,12 +1382,13 @@ JS2.Class.extend('Commander', function(KLASS, OO){
1375
1382
  var updater = this.getUpdater();
1376
1383
  var self = this;
1377
1384
  var interval = this.config.interval || 2;
1378
- console.log('Input Directory:' + updater.inDir + ' -> Output Directory:' + updater.outDir);
1379
- if (updater.recursive) console.log('RECURSIVE');
1385
+ JS2.LOGGER.info('Input Directory:' + updater.inDir + ' -> Output Directory:' + updater.outDir);
1386
+ if (updater.recursive) JS2.LOGGER.info('RECURSIVE');
1380
1387
 
1381
1388
  // HACK to get this integrated with ruby
1382
- updater.update();
1383
- setInterval(function($1,$2,$3){ console.log('updating'); updater.update(true, function($1,$2,$3){ return JS2.DECORATOR.file($1); }); }, interval * 1000);
1389
+ var decor = function($1,$2,$3){ return JS2.DECORATOR.file($1) };
1390
+ updater.update(true, decor);
1391
+ this.fs.setInterval(function($1,$2,$3){ JS2.LOGGER.info('updating'); updater.update(false, decor); }, interval * 1000);
1384
1392
  });
1385
1393
 
1386
1394
  OO.addMember("showBanner",function () {
data/lib/js2/rack.rb CHANGED
@@ -6,21 +6,23 @@ module JS2
6
6
  ROOT = File.expand_path(Dir.getwd)
7
7
 
8
8
  DEFAULT_CONFIG = {
9
- 'in_dir' => "#{ROOT}/app/js2",
10
- 'out_dir' => "#{ROOT}/public/javascripts",
11
- 'bin' => (`which js2`.chomp rescue nil)
9
+ 'source_dir' => "#{ROOT}/app/js2",
10
+ 'out_dir' => "#{ROOT}/public/javascripts",
11
+ 'bin' => (`which js2`.chomp rescue nil),
12
+ 'copy_js2' => true
12
13
  }
13
14
 
14
15
  def initialize(app)
15
16
  @app = app
16
17
 
17
- @config = YAML.read_file(ROOT + '/config/js2.yml') rescue DEFAULT_CONFIG
18
+ config = YAML.load_file(ROOT + '/config/js2.yml') rescue DEFAULT_CONFIG
18
19
 
19
- @in_dir = @config['in_dir']
20
- @out_dir = @config['out_dir']
21
- @bin = @config['bin']
20
+ @source_dir = config['source_dir'] || './app/js2'
21
+ @out_dir = config['out_dir'] || './public/javascripts'
22
+ @bin = config['bin'] || 'js2'
23
+ @copy_js2 = config.has_key?('copy_js2') ? config['copy_js2'] : true
22
24
 
23
- @valid = @in_dir && @out_dir && !@bin.blank?
25
+ @valid = @source_dir && @out_dir && !@bin.blank?
24
26
 
25
27
  unless @valid
26
28
  puts "JS2 is not configured properly"
@@ -28,7 +30,15 @@ module JS2
28
30
  end
29
31
 
30
32
  def call(env)
31
- `#{@bin} compile #{@in_dir} #{@out_dir}` if @valid
33
+ if @copy_js2
34
+ to_file = ROOT + '/public/javascripts/js2.js'
35
+ unless File.exists?(to_file)
36
+ from_file = JS2::ROOT + '/js2/browser.js'
37
+ File.open(to_file, 'w') { |f| f << File.read(from_file) }
38
+ end
39
+ end
40
+
41
+ `#{@bin} compile -f=browser -m #{@source_dir} #{@out_dir}` if @valid
32
42
  @app.call(env)
33
43
  end
34
44
  end
data/lib/js2.rb CHANGED
@@ -20,6 +20,8 @@ module JS2
20
20
  end
21
21
 
22
22
  dirname = File.dirname(File.expand_path('', __FILE__))
23
+ JS2::ROOT = dirname
24
+
23
25
  %W{ context fs command rack }.each do |f|
24
26
  require "#{dirname}/js2/#{f}"
25
27
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 3
8
- - 5
9
- version: 0.3.5
8
+ - 6
9
+ version: 0.3.6
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jeff Su
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-03-14 00:00:00 -07:00
17
+ date: 2011-03-20 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -47,6 +47,7 @@ files:
47
47
  - lib/js2/fs.rb
48
48
  - lib/js2/rack.rb
49
49
  - lib/js2.rb
50
+ - lib/js2/browser.js
50
51
  - lib/js2/js2.js
51
52
  - CHANGELOG
52
53
  has_rdoc: true