README.md in jsrb-0.2.1 vs README.md in jsrb-0.3.0
- old
+ new
@@ -4,261 +4,274 @@
Jsrb is a template engine to generate JavaScript code in simple Ruby DSL.
# Getting Started
-Jsrb handler works in `.jsrb` view files. All ruby syntax is available and `jsrb` is provided in it. You can construct JavaScript code via `jsrb`.
+Jsrb handler works in `.jsrb` view files. All ruby syntax is available and `js` is provided in it. You can construct JavaScript code via `js`.
-```rb
-name = jsrb.var!(:name) { 'foo' }
-ary = jsrb.var! :ary
-obj = jsrb.var! :obj
-result = jsrb.var!
+```ruby
+name = js.var!(:name) { 'foo' }
+ary = js.var! :ary
+obj = js.var! :obj
+result = js.var!
# var name = 'foo';
# var ary;
# var obj;
-# var _v1; <- auto generate variable name
+# var _v1; // auto generated
-ary.set!([1, 2, 3])
+js.set! ary, [1, 2, 3]
# ary = [1, 2, 3];
-obj.set!(
+js.set! obj, {
name: name,
profile: {
age: 20,
sex: 'm'
}
-)
+}
# obj = {
# name: name,
# profile: {
# age: 20,
# sex: 'm'
# }
# };
-result.set! (obj.name + "(" + obj.profile.age + ")")
+js.set! result, (obj.name + "(" + obj.profile.age + ")")
# _v1 = obj.name + "(" + obj.profile.age + ")";
-ary.set! ary.map { |x| x * 2 }
+js.set! ary, ary.map { |x| x * 2 }
# ary = ary.map(function(x) {
# return x * 2;
# });
-jsrb.if!(ary[1] === 4) {
- result.set! 'four'
+js.if!(ary[1] === 4) {
+ js.set! result, 'four'
}.elsif(ary[1] === 2) {
- result.set! 'two'
+ js.set! result, 'two'
}.else {
- result.set! 'other'
+ js.set! result, 'other'
}
-# // the actual output doesn't looks like this, but will be better code in regard to variable scope.
+# // The actual output will have certain immediate functions
+# // that preserve variable scope for each case.
# if (ary[1] === 4) {
# _v1 = 'four'
# } else if (ary[1] === 2) {
# _v1 = 'two'
# } else {
# _v1 = 'other'
# }
-result.set! jsrb.expr.Date.new!
+js.set! result, js.expr.Date.new
# _v1 = new Date;
-jsrb.expr.console.log('hello').as_statement!
+js.set! js.expr.console.log('hello')
# console.log('hello');
```
# Usage
+In contrast to Ruby, statements and expressions are
+specifically distinguished as different elements in JavaScript.
+And the program is composed of a list of statements.
+This means that the jsrb file will have a series of statement pushing expression in it.
+
+To make clear whether a method is pushing statement or not, jsrb adopted the rule that the name of method pushing statement should be `#..!`.
+
## Statements
### Variable declaration
-`jsrb.var!` pushes a **VariableDeclaration** into current context.
+`js.var!` pushes a **VariableDeclaration** into current context.
-```rb
+```ruby
# with variable name and initializer
-jsrb.var!('varname') { 100 }
+js.var!('varname') { 100 }
# var varname = 100;
# without initializer
-jsrb.var!('varname')
+js.var!('varname')
# var varname;
# variable name is auto-generated if not specified
-jsrb.var!
+js.var!
# var _v1;
# var! returns Jsrb::ExprChain instance, so that you can
# assign value with `.set!` method.
-a = jsrb.var!
-a.set! 100
+a = js.var!
+js.set! a, 100
# var _v1;
# v1 = 100;
```
### If statement, and conditional expression
-`jsrb.if!` pushes an **IfStatement** into current context, `jsrb.if` to build **a conditional expression**.
+`js.if!` pushes an **IfStatement** into current context, `js.if` to build **a conditional expression**.
-```rb
+```ruby
# start with `#if!`
# and chain `#elsif` to add next case.
# Note that this is a statement, not expression.
-jsrb.if!(v === 1) {
+js.if!(v === 1) {
# ..
}.elsif(v === 2) {
# ..
}.else {
# ..
}
# if you don't need else clause, close with `#end`
-jsrb.if!(v === 1) {
+js.if!(v === 1) {
# ..
}.end
# if you want to regard this as an expression, use `#if` without exclamation.
-v.set! jsrb.if(v === 1) {
+js.set! v, js.if(v === 1) {
# ..
}.else {
# ..
}
```
-### Assignment statement
-
-`ExprChain#set!` pushes an **assignment statement** (ExpressionStatement of AssignmentExpression).
-
-```rb
-a = jsrb.var! :a
-a.set! 100
-# var a;
-# a = 100;
-```
-
### Expression statement
-`ExprChain#as_statement!` pushes an **ExpressionStatement** of the left hand side of chain.
+`js.do!` pushes an **ExpressionStatement** of a given expression.
-```rb
-get_elements = jsrb.expr['getElements']
-get_elements.('.foo').forEach { |n| n.delete.() }.as_statement!
+```ruby
+get_elements = js.expr[:getElements]
+js.do! get_elements.('.foo').forEach { |n| n.delete.() }
# getElements('.foo').forEach(function(n) { return n.delete(); });
```
-## Expression chain
+## Expressions
Expression chain (`ExprChain` class) is an utility class to construct JavaScript expressions.
-### Initialize with wrapping a ruby value
+### Initialize with wrapping ruby values
-`jsrb.expr` create a new `ExprChain` instance, taking an initial value optionally.
-Some methods in jsrb automatically convert ruby expression to ExprChain.
+`js.expr` create a new `ExprChain` instance, taking an initial value optionally.
+Some methods in `js` automatically convert ruby value to ExprChain.
-```rb
-x = jsrb.var! :x
+```ruby
+x = js.var! :x
-x.set! jsrb.expr(100)
+js.set! x, js.expr(100)
# x = 100;
-# set! automatically wrap with ExprChain.
-x.set! 100
+# set! automatically wraps argument with ExprChain.
+js.set! x, 100
# x = 100;
-# If you need to compare by operator with another ExprChain,
-# you have to wrap first.
-x.set!(jsrb.expr(100) < jsrb.expr.y)
-# x.set!(100 < jsrb.expr.y) will fail.
+#
+# Note that if you need to compare a ruby value by operator with another one,
+# you have to wrap it.
+js.set! x, (js.expr(100) < js.expr.y) # (100 < js.expr.y) will fail.
```
+See the conversion section to check mappings from ruby value to JavaScript one.
+
### Chains
#### Member expression
-`ExprChain#[], #member!, #..` constructs **MemberExpression**.
+`ExprChain#[], #..` constructs **MemberExpression**.
`#[]` and `#member!` is safe. `#..` can be used only if the name has no conflict.
-```rb
-x = jsrb.var! :x
+```ruby
+x = js.var! :x
-obj = jsrb.expr['someObj']
-# jsrb.expr with no argument constructs empty chain,
+obj = js.expr[:someObj]
+# js.expr with no argument constructs empty chain,
# in which every member chain will be an identifier.
-x.set! obj.field
+js.set! x, obj.field
# x = someObj['field'];
-x.set! obj['field']
+js.set! x, obj[:field]
# x = someObj['field'];
-x.set! obj.member! 'field'
-# x = someObj['field'];
-x.set! obj.send # NOTE that this is interpreted as a ruby Object's method, and causes an error.
+js.set! x, obj.send # NOTE that this is interpreted as a ruby Object's method, and causes an error.
```
+#### Assignment
+
+`ExprChain#set` constructs an **AssignmentExpression**.
+
+```ruby
+a = js.var! :a
+# var a;
+
+js.do! a.set 100
+# a = 100;
+
+# js.set!(a, b) is short hand of js.do!(a.set(b))
+js.set! a, 100
+# a = 100;
+```
+
#### Function Call
`ExprChain#call, so #.(), #.. with argument or block` constructs **CallExpression**.
-```rb
-x = jsrb.var! :x
-console = jsrb.expr['console']
+```ruby
+console = js.expr[:console]
# using call method
-console.log.('foo').as_statement!
+js.do! console.log.('foo')
# console.log('foo')
-console.log.call('foo').as_statement!
+js.do! console.log.call('foo')
# console.log('foo')
# using dynamic method
# if #..() has at least one argument or block, it will be a call expression.
-console.log('foo').as_statement!
+js.do! console.log('foo')
# console.log('foo')
-x.map { |item| item.field }.as_statement!
-# x.map(function(item) { return item.field; });
+
+js.do! js.expr(:ary).forEach { |item| item.execute.() }
+# ary.forEach(function(item) { return item.execute(); });
```
#### Operators
Any ruby-overridable and JS-existing operators are overridden for chaining.
Supported operators are: `** + - * / % >> << & ^ | <= < > >= == === != ! && ||`.
-```rb
-x = jsrb.var! :x
-a = jsrb.expr['a']
+```ruby
+x = js.var! :x
+a = js.expr[:a]
-x.set!(a === 1)
+js.set! x, (a === 1)
# x = a === 1;
-x.set!(a * a)
+js.set! x, (a * a)
# x = a * a;
-x.set!(3 * a) # raises an error because Fixnum does not accept ExprChain as RHS.
+js.set! x, (3 * a) # raises an error because the method :* of Fixnum does not accept ExprChain as RHS.
```
#### New
-`ExprChain#new!` constructs **NewExpression**.
+`ExprChain#new` constructs **NewExpression**.
-```rb
-x = jsrb.var! :x
+```ruby
+x = js.var! :x
-x.set! jsrb.expr['Date'].new!
+js.set! x, js.expr[:Date].new
# x = new Date;
```
#### Function expression
-`ExprChain#for_all!` constructs **FunctionExpression**. You can also construct it from Proc directly or passing a block.
+`ExprChain#forall` constructs **FunctionExpression**. You can also construct it directly from Proc or passing a block.
-```rb
-ary = jsrb.var! :ary, [1, 2, 3]
+```ruby
+ary = js.var! :ary, [1, 2, 3]
-ary.map((jsrb.expr['x'] * 2).for_all!('x')).as_statement!
+js.do! ary.map((js.expr[:x] * 2).forall('x'))
# ary.map(function(x) { return x * 2; });
-ary.map { |x| x * 2 }.as_statement!
+js.do! ary.map { |x| x * 2 }
# ary.map(function(x) { return x * 2; });
-ary.map(->(x) { x * 2 }).as_statement!
+js.do! ary.map(->(x) { x * 2 })
# ary.map(function(x) { return x * 2; });
```
# Conversion
@@ -281,13 +294,13 @@
# Customize Chain
You can add custom chain methods in `ExprChain` via `Jsrb::ExprChain.#add_custom_chain`.
-```rb
+```ruby
Jsrb::ExprChain.add_custom_chain('log_here', '__tap_log__')
-jsrb.expr['foo']['bar'].log_here.as_statement!
+js.do! js.expr[:foo][:bar].log_here
# __tap_log__(foo['bar']);
```
## Contributing