reactive-ruby 0.7.28 → 0.7.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +6 -0
  3. data/Gemfile.lock +4 -1
  4. data/README.md +132 -68
  5. data/Rakefile +5 -2
  6. data/example/examples/Gemfile +0 -2
  7. data/example/rails-tutorial/Gemfile +3 -2
  8. data/lib/generators/reactive_ruby/test_app/templates/application.rb +11 -0
  9. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/application.rb +2 -0
  10. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +3 -0
  11. data/lib/generators/reactive_ruby/test_app/templates/boot.rb +6 -0
  12. data/lib/generators/reactive_ruby/test_app/templates/script/rails +5 -0
  13. data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +11 -0
  14. data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +14 -0
  15. data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +105 -0
  16. data/lib/rails-helpers/top_level_rails_component.rb +9 -16
  17. data/lib/{reactive-ruby → react}/api.rb +8 -65
  18. data/lib/{reactive-ruby → react}/callbacks.rb +0 -0
  19. data/lib/react/component.rb +266 -0
  20. data/lib/react/component/api.rb +48 -0
  21. data/lib/react/component/class_methods.rb +183 -0
  22. data/lib/{reactive-ruby → react}/element.rb +10 -11
  23. data/lib/{reactive-ruby → react}/event.rb +0 -0
  24. data/lib/{reactive-ruby → react}/ext/hash.rb +0 -0
  25. data/lib/{reactive-ruby → react}/ext/string.rb +0 -0
  26. data/lib/react/native_library.rb +57 -0
  27. data/lib/{reactive-ruby → react}/observable.rb +0 -4
  28. data/lib/{reactive-ruby → react}/rendering_context.rb +0 -6
  29. data/lib/{reactive-ruby → react}/state.rb +3 -6
  30. data/lib/{reactive-ruby → react}/top_level.rb +2 -3
  31. data/lib/react/validator.rb +127 -0
  32. data/lib/reactive-ruby.rb +20 -20
  33. data/lib/reactive-ruby/version.rb +1 -1
  34. data/{opal-spec/reactjs → spec}/index.html.erb +1 -1
  35. data/{opal-spec → spec/react}/callbacks_spec.rb +8 -9
  36. data/{opal-spec → spec/react}/component_spec.rb +170 -120
  37. data/spec/react/dsl_spec.rb +16 -0
  38. data/{opal-spec → spec/react}/element_spec.rb +7 -20
  39. data/{opal-spec → spec/react}/event_spec.rb +3 -1
  40. data/spec/react/native_library_spec.rb +10 -0
  41. data/spec/react/param_declaration_spec.rb +18 -0
  42. data/{opal-spec → spec/react}/react_spec.rb +3 -2
  43. data/spec/react/react_state_spec.rb +22 -0
  44. data/spec/react/top_level_component_spec.rb +68 -0
  45. data/{opal-spec → spec/react}/tutorial/tutorial_spec.rb +11 -13
  46. data/{opal-spec → spec/react}/validator_spec.rb +50 -4
  47. data/spec/reactive-ruby/isomorphic_helpers_spec.rb +22 -4
  48. data/spec/spec_helper.rb +51 -0
  49. data/spec/support/react/spec_helpers.rb +57 -0
  50. data/spec/vendor/es5-shim.min.js +6 -0
  51. metadata +56 -24
  52. data/lib/reactive-ruby/component.rb +0 -502
  53. data/lib/reactive-ruby/validator.rb +0 -99
  54. data/old-readme +0 -220
  55. data/opal-spec/spec_helper.rb +0 -29
@@ -0,0 +1,57 @@
1
+ module React
2
+ module SpecHelpers
3
+ `var ReactTestUtils = React.addons.TestUtils`
4
+
5
+ def renderToDocument(type, options = {})
6
+ element = React.create_element(type, options)
7
+ return renderElementToDocument(element)
8
+ end
9
+
10
+ def renderElementToDocument(element)
11
+ instance = Native(`ReactTestUtils.renderIntoDocument(#{element.to_n})`)
12
+ instance.class.include(React::Component::API)
13
+ return instance
14
+ end
15
+
16
+ def simulateEvent(event, element, params = {})
17
+ simulator = Native(`ReactTestUtils.Simulate`)
18
+ simulator[event.to_s].call(`#{element.to_n}.getDOMNode()`, params)
19
+ end
20
+
21
+ def isElementOfType(element, type)
22
+ `React.addons.TestUtils.isElementOfType(#{element.to_n}, #{type.cached_component_class})`
23
+ end
24
+
25
+ def build_element(type, options)
26
+ component = React.create_element(type, options)
27
+ element = `ReactTestUtils.renderIntoDocument(#{component.to_n})`
28
+ if `typeof React.findDOMNode === 'undefined'`
29
+ `$(element.getDOMNode())` # v0.12
30
+ else
31
+ `$(React.findDOMNode(element))` # v0.13
32
+ end
33
+ end
34
+
35
+ def expect_component_to_eventually(component_class, opts = {}, &block)
36
+ # Calls block after each update of a component until it returns true.
37
+ # When it does set the expectation to true. Uses the after_update
38
+ # callback of the component_class, then instantiates an element of that
39
+ # class The call back is only called on updates, so the call back is
40
+ # manually called right after the element is created. Because React.rb
41
+ # runs the callback inside the components context, we have to setup a
42
+ # lambda to get back to correct context before executing run_async.
43
+ # Because run_async can only be run once it is protected by clearing
44
+ # element once the test passes.
45
+ element = nil
46
+ check_block = lambda do
47
+ context = block.arity > 0 ? self : element
48
+ run_async do
49
+ element = nil; expect(true).to be(true)
50
+ end if element and context.instance_exec(element, &block)
51
+ end
52
+ component_class.after_update { check_block.call }
53
+ element = build_element component_class, opts
54
+ check_block.call
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,6 @@
1
+ /*!
2
+ * https://github.com/es-shims/es5-shim
3
+ * @license es5-shim Copyright 2009-2014 by contributors, MIT License
4
+ * see https://github.com/es-shims/es5-shim/blob/v4.1.0/LICENSE
5
+ */
6
+ (function(t,e){"use strict";if(typeof define==="function"&&define.amd){define(e)}else if(typeof exports==="object"){module.exports=e()}else{t.returnExports=e()}})(this,function(){var t=Array.prototype;var e=Object.prototype;var r=Function.prototype;var n=String.prototype;var i=Number.prototype;var a=t.slice;var o=t.splice;var u=t.push;var l=t.unshift;var f=r.call;var s=e.toString;var c=Array.isArray||function ye(t){return s.call(t)==="[object Array]"};var p=typeof Symbol==="function"&&typeof Symbol.toStringTag==="symbol";var h;var v=Function.prototype.toString,g=function de(t){try{v.call(t);return true}catch(e){return false}},y="[object Function]",d="[object GeneratorFunction]";h=function me(t){if(typeof t!=="function"){return false}if(p){return g(t)}var e=s.call(t);return e===y||e===d};var m;var b=RegExp.prototype.exec,w=function be(t){try{b.call(t);return true}catch(e){return false}},T="[object RegExp]";m=function we(t){if(typeof t!=="object"){return false}return p?w(t):s.call(t)===T};var x;var O=String.prototype.valueOf,j=function Te(t){try{O.call(t);return true}catch(e){return false}},S="[object String]";x=function xe(t){if(typeof t==="string"){return true}if(typeof t!=="object"){return false}return p?j(t):s.call(t)===S};var E=function Oe(t){var e=s.call(t);var r=e==="[object Arguments]";if(!r){r=!c(t)&&t!==null&&typeof t==="object"&&typeof t.length==="number"&&t.length>=0&&h(t.callee)}return r};var N=function(t){var e=Object.defineProperty&&function(){try{Object.defineProperty({},"x",{});return true}catch(t){return false}}();var r;if(e){r=function(t,e,r,n){if(!n&&e in t){return}Object.defineProperty(t,e,{configurable:true,enumerable:false,writable:true,value:r})}}else{r=function(t,e,r,n){if(!n&&e in t){return}t[e]=r}}return function n(e,i,a){for(var o in i){if(t.call(i,o)){r(e,o,i[o],a)}}}}(e.hasOwnProperty);function I(t){var e=typeof t;return t===null||e==="undefined"||e==="boolean"||e==="number"||e==="string"}var D={ToInteger:function je(t){var e=+t;if(e!==e){e=0}else if(e!==0&&e!==1/0&&e!==-(1/0)){e=(e>0||-1)*Math.floor(Math.abs(e))}return e},ToPrimitive:function Se(t){var e,r,n;if(I(t)){return t}r=t.valueOf;if(h(r)){e=r.call(t);if(I(e)){return e}}n=t.toString;if(h(n)){e=n.call(t);if(I(e)){return e}}throw new TypeError},ToObject:function(t){if(t==null){throw new TypeError("can't convert "+t+" to object")}return Object(t)},ToUint32:function Ee(t){return t>>>0}};var M=function Ne(){};N(r,{bind:function Ie(t){var e=this;if(!h(e)){throw new TypeError("Function.prototype.bind called on incompatible "+e)}var r=a.call(arguments,1);var n;var i=function(){if(this instanceof n){var i=e.apply(this,r.concat(a.call(arguments)));if(Object(i)===i){return i}return this}else{return e.apply(t,r.concat(a.call(arguments)))}};var o=Math.max(0,e.length-r.length);var u=[];for(var l=0;l<o;l++){u.push("$"+l)}n=Function("binder","return function ("+u.join(",")+"){ return binder.apply(this, arguments); }")(i);if(e.prototype){M.prototype=e.prototype;n.prototype=new M;M.prototype=null}return n}});var F=f.bind(e.hasOwnProperty);var R=function(){var t=[1,2];var e=t.splice();return t.length===2&&c(e)&&e.length===0}();N(t,{splice:function De(t,e){if(arguments.length===0){return[]}else{return o.apply(this,arguments)}}},!R);var U=function(){var e={};t.splice.call(e,0,0,1);return e.length===1}();N(t,{splice:function Me(t,e){if(arguments.length===0){return[]}var r=arguments;this.length=Math.max(D.ToInteger(this.length),0);if(arguments.length>0&&typeof e!=="number"){r=a.call(arguments);if(r.length<2){r.push(this.length-t)}else{r[1]=D.ToInteger(e)}}return o.apply(this,r)}},!U);var k=[].unshift(0)!==1;N(t,{unshift:function(){l.apply(this,arguments);return this.length}},k);N(Array,{isArray:c});var A=Object("a");var C=A[0]!=="a"||!(0 in A);var P=function Fe(t){var e=true;var r=true;if(t){t.call("foo",function(t,r,n){if(typeof n!=="object"){e=false}});t.call([1],function(){"use strict";r=typeof this==="string"},"x")}return!!t&&e&&r};N(t,{forEach:function Re(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=arguments[1],i=-1,a=r.length>>>0;if(!h(t)){throw new TypeError}while(++i<a){if(i in r){t.call(n,r[i],i,e)}}}},!P(t.forEach));N(t,{map:function Ue(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0,i=Array(n),a=arguments[1];if(!h(t)){throw new TypeError(t+" is not a function")}for(var o=0;o<n;o++){if(o in r){i[o]=t.call(a,r[o],o,e)}}return i}},!P(t.map));N(t,{filter:function ke(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0,i=[],a,o=arguments[1];if(!h(t)){throw new TypeError(t+" is not a function")}for(var u=0;u<n;u++){if(u in r){a=r[u];if(t.call(o,a,u,e)){i.push(a)}}}return i}},!P(t.filter));N(t,{every:function Ae(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0,i=arguments[1];if(!h(t)){throw new TypeError(t+" is not a function")}for(var a=0;a<n;a++){if(a in r&&!t.call(i,r[a],a,e)){return false}}return true}},!P(t.every));N(t,{some:function Ce(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0,i=arguments[1];if(!h(t)){throw new TypeError(t+" is not a function")}for(var a=0;a<n;a++){if(a in r&&t.call(i,r[a],a,e)){return true}}return false}},!P(t.some));var Z=false;if(t.reduce){Z=typeof t.reduce.call("es5",function(t,e,r,n){return n})==="object"}N(t,{reduce:function Pe(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0;if(!h(t)){throw new TypeError(t+" is not a function")}if(!n&&arguments.length===1){throw new TypeError("reduce of empty array with no initial value")}var i=0;var a;if(arguments.length>=2){a=arguments[1]}else{do{if(i in r){a=r[i++];break}if(++i>=n){throw new TypeError("reduce of empty array with no initial value")}}while(true)}for(;i<n;i++){if(i in r){a=t.call(void 0,a,r[i],i,e)}}return a}},!Z);var J=false;if(t.reduceRight){J=typeof t.reduceRight.call("es5",function(t,e,r,n){return n})==="object"}N(t,{reduceRight:function Ze(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0;if(!h(t)){throw new TypeError(t+" is not a function")}if(!n&&arguments.length===1){throw new TypeError("reduceRight of empty array with no initial value")}var i,a=n-1;if(arguments.length>=2){i=arguments[1]}else{do{if(a in r){i=r[a--];break}if(--a<0){throw new TypeError("reduceRight of empty array with no initial value")}}while(true)}if(a<0){return i}do{if(a in r){i=t.call(void 0,i,r[a],a,e)}}while(a--);return i}},!J);var z=Array.prototype.indexOf&&[0,1].indexOf(1,2)!==-1;N(t,{indexOf:function Je(t){var e=C&&x(this)?this.split(""):D.ToObject(this),r=e.length>>>0;if(!r){return-1}var n=0;if(arguments.length>1){n=D.ToInteger(arguments[1])}n=n>=0?n:Math.max(0,r+n);for(;n<r;n++){if(n in e&&e[n]===t){return n}}return-1}},z);var $=Array.prototype.lastIndexOf&&[0,1].lastIndexOf(0,-3)!==-1;N(t,{lastIndexOf:function ze(t){var e=C&&x(this)?this.split(""):D.ToObject(this),r=e.length>>>0;if(!r){return-1}var n=r-1;if(arguments.length>1){n=Math.min(n,D.ToInteger(arguments[1]))}n=n>=0?n:r-Math.abs(n);for(;n>=0;n--){if(n in e&&t===e[n]){return n}}return-1}},$);var B=!{toString:null}.propertyIsEnumerable("toString"),G=function(){}.propertyIsEnumerable("prototype"),H=!F("x","0"),L=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],X=L.length;N(Object,{keys:function $e(t){var e=h(t),r=E(t),n=t!==null&&typeof t==="object",i=n&&x(t);if(!n&&!e&&!r){throw new TypeError("Object.keys called on a non-object")}var a=[];var o=G&&e;if(i&&H||r){for(var u=0;u<t.length;++u){a.push(String(u))}}if(!r){for(var l in t){if(!(o&&l==="prototype")&&F(t,l)){a.push(String(l))}}}if(B){var f=t.constructor,s=f&&f.prototype===t;for(var c=0;c<X;c++){var p=L[c];if(!(s&&p==="constructor")&&F(t,p)){a.push(p)}}}return a}});var Y=Object.keys&&function(){return Object.keys(arguments).length===2}(1,2);var q=Object.keys;N(Object,{keys:function Be(e){if(E(e)){return q(t.slice.call(e))}else{return q(e)}}},!Y);var K=-621987552e5;var Q="-000001";var V=Date.prototype.toISOString&&new Date(K).toISOString().indexOf(Q)===-1;N(Date.prototype,{toISOString:function Ge(){var t,e,r,n,i;if(!isFinite(this)){throw new RangeError("Date.prototype.toISOString called on non-finite value.")}n=this.getUTCFullYear();i=this.getUTCMonth();n+=Math.floor(i/12);i=(i%12+12)%12;t=[i+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];n=(n<0?"-":n>9999?"+":"")+("00000"+Math.abs(n)).slice(0<=n&&n<=9999?-4:-6);e=t.length;while(e--){r=t[e];if(r<10){t[e]="0"+r}}return n+"-"+t.slice(0,2).join("-")+"T"+t.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"}},V);var W=false;try{W=Date.prototype.toJSON&&new Date(NaN).toJSON()===null&&new Date(K).toJSON().indexOf(Q)!==-1&&Date.prototype.toJSON.call({toISOString:function(){return true}})}catch(_){}if(!W){Date.prototype.toJSON=function He(t){var e=Object(this),r=D.ToPrimitive(e),n;if(typeof r==="number"&&!isFinite(r)){return null}n=e.toISOString;if(typeof n!=="function"){throw new TypeError("toISOString property is not callable")}return n.call(e)}}var te=Date.parse("+033658-09-27T01:46:40.000Z")===1e15;var ee=!isNaN(Date.parse("2012-04-04T24:00:00.500Z"))||!isNaN(Date.parse("2012-11-31T23:59:59.000Z"));var re=isNaN(Date.parse("2000-01-01T00:00:00.000Z"));if(!Date.parse||re||ee||!te){Date=function(t){function e(r,n,i,a,o,u,l){var f=arguments.length;if(this instanceof t){var s=f===1&&String(r)===r?new t(e.parse(r)):f>=7?new t(r,n,i,a,o,u,l):f>=6?new t(r,n,i,a,o,u):f>=5?new t(r,n,i,a,o):f>=4?new t(r,n,i,a):f>=3?new t(r,n,i):f>=2?new t(r,n):f>=1?new t(r):new t;s.constructor=e;return s}return t.apply(this,arguments)}var r=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:(\\.\\d{1,}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+"$");var n=[0,31,59,90,120,151,181,212,243,273,304,334,365];function i(t,e){var r=e>1?1:0;return n[e]+Math.floor((t-1969+r)/4)-Math.floor((t-1901+r)/100)+Math.floor((t-1601+r)/400)+365*(t-1970)}function a(e){return Number(new t(1970,0,1,0,0,0,e))}for(var o in t){e[o]=t[o]}e.now=t.now;e.UTC=t.UTC;e.prototype=t.prototype;e.prototype.constructor=e;e.parse=function u(e){var n=r.exec(e);if(n){var o=Number(n[1]),u=Number(n[2]||1)-1,l=Number(n[3]||1)-1,f=Number(n[4]||0),s=Number(n[5]||0),c=Number(n[6]||0),p=Math.floor(Number(n[7]||0)*1e3),h=Boolean(n[4]&&!n[8]),v=n[9]==="-"?1:-1,g=Number(n[10]||0),y=Number(n[11]||0),d;if(f<(s>0||c>0||p>0?24:25)&&s<60&&c<60&&p<1e3&&u>-1&&u<12&&g<24&&y<60&&l>-1&&l<i(o,u+1)-i(o,u)){d=((i(o,u)+l)*24+f+g*v)*60;d=((d+s+y*v)*60+c)*1e3+p;if(h){d=a(d)}if(-864e13<=d&&d<=864e13){return d}}return NaN}return t.parse.apply(this,arguments)};return e}(Date)}if(!Date.now){Date.now=function Le(){return(new Date).getTime()}}var ne=i.toFixed&&(8e-5.toFixed(3)!=="0.000"||.9.toFixed(0)!=="1"||1.255.toFixed(2)!=="1.25"||0xde0b6b3a7640080.toFixed(0)!=="1000000000000000128");var ie={base:1e7,size:6,data:[0,0,0,0,0,0],multiply:function Xe(t,e){var r=-1;while(++r<ie.size){e+=t*ie.data[r];ie.data[r]=e%ie.base;e=Math.floor(e/ie.base)}},divide:function Ye(t){var e=ie.size,r=0;while(--e>=0){r+=ie.data[e];ie.data[e]=Math.floor(r/t);r=r%t*ie.base}},numToString:function qe(){var t=ie.size;var e="";while(--t>=0){if(e!==""||t===0||ie.data[t]!==0){var r=String(ie.data[t]);if(e===""){e=r}else{e+="0000000".slice(0,7-r.length)+r}}}return e},pow:function Ke(t,e,r){return e===0?r:e%2===1?Ke(t,e-1,r*t):Ke(t*t,e/2,r)},log:function Qe(t){var e=0;while(t>=4096){e+=12;t/=4096}while(t>=2){e+=1;t/=2}return e}};N(i,{toFixed:function Ve(t){var e,r,n,i,a,o,u,l;e=Number(t);e=e!==e?0:Math.floor(e);if(e<0||e>20){throw new RangeError("Number.toFixed called with invalid number of decimals")}r=Number(this);if(r!==r){return"NaN"}if(r<=-1e21||r>=1e21){return String(r)}n="";if(r<0){n="-";r=-r}i="0";if(r>1e-21){a=ie.log(r*ie.pow(2,69,1))-69;o=a<0?r*ie.pow(2,-a,1):r/ie.pow(2,a,1);o*=4503599627370496;a=52-a;if(a>0){ie.multiply(0,o);u=e;while(u>=7){ie.multiply(1e7,0);u-=7}ie.multiply(ie.pow(10,u,1),0);u=a-1;while(u>=23){ie.divide(1<<23);u-=23}ie.divide(1<<u);ie.multiply(1,1);ie.divide(2);i=ie.numToString()}else{ie.multiply(0,o);ie.multiply(1<<-a,0);i=ie.numToString()+"0.00000000000000000000".slice(2,2+e)}}if(e>0){l=i.length;if(l<=e){i=n+"0.0000000000000000000".slice(0,e-l+2)+i}else{i=n+i.slice(0,l-e)+"."+i.slice(l-e)}}else{i=n+i}return i}},ne);var ae=n.split;if("ab".split(/(?:ab)*/).length!==2||".".split(/(.?)(.?)/).length!==4||"tesst".split(/(s)*/)[1]==="t"||"test".split(/(?:)/,-1).length!==4||"".split(/.?/).length||".".split(/()()/).length>1){(function(){var t=typeof/()??/.exec("")[1]==="undefined";n.split=function(e,r){var n=this;if(typeof e==="undefined"&&r===0){return[]}if(!m(e)){return ae.call(this,e,r)}var i=[],a=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":""),o=0,l,f,s,c;e=new RegExp(e.source,a+"g");n+="";if(!t){l=new RegExp("^"+e.source+"$(?!\\s)",a)}r=typeof r==="undefined"?-1>>>0:D.ToUint32(r);f=e.exec(n);while(f){s=f.index+f[0].length;if(s>o){i.push(n.slice(o,f.index));if(!t&&f.length>1){f[0].replace(l,function(){for(var t=1;t<arguments.length-2;t++){if(typeof arguments[t]==="undefined"){f[t]=void 0}}})}if(f.length>1&&f.index<n.length){u.apply(i,f.slice(1))}c=f[0].length;o=s;if(i.length>=r){break}}if(e.lastIndex===f.index){e.lastIndex++}f=e.exec(n)}if(o===n.length){if(c||!e.test("")){i.push("")}}else{i.push(n.slice(o))}return i.length>r?i.slice(0,r):i}})()}else if("0".split(void 0,0).length){n.split=function We(t,e){if(typeof t==="undefined"&&e===0){return[]}return ae.call(this,t,e)}}var oe=n.replace;var ue=function(){var t=[];"x".replace(/x(.)?/g,function(e,r){t.push(r)});return t.length===1&&typeof t[0]==="undefined"}();if(!ue){n.replace=function _e(t,e){var r=h(e);var n=m(t)&&/\)[*?]/.test(t.source);if(!r||!n){return oe.call(this,t,e)}else{var i=function(r){var n=arguments.length;var i=t.lastIndex;t.lastIndex=0;var a=t.exec(r)||[];t.lastIndex=i;a.push(arguments[n-2],arguments[n-1]);return e.apply(this,a)};return oe.call(this,t,i)}}}var le=n.substr;var fe="".substr&&"0b".substr(-1)!=="b";N(n,{substr:function tr(t,e){return le.call(this,t<0?(t=this.length+t)<0?0:t:t,e)}},fe);var se=" \n \f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";var ce="\u200b";var pe="["+se+"]";var he=new RegExp("^"+pe+pe+"*");var ve=new RegExp(pe+pe+"*$");var ge=n.trim&&(se.trim()||!ce.trim());N(n,{trim:function er(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}return String(this).replace(he,"").replace(ve,"")}},ge);if(parseInt(se+"08")!==8||parseInt(se+"0x16")!==22){parseInt=function(t){var e=/^0[xX]/;return function r(n,i){n=String(n).trim();if(!Number(i)){i=e.test(n)?16:10}return t(n,i)}}(parseInt)}});
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reactive-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.28
4
+ version: 0.7.29
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Chang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-26 00:00:00.000000000 Z
11
+ date: 2015-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opal
@@ -143,6 +143,7 @@ executables: []
143
143
  extensions: []
144
144
  extra_rdoc_files: []
145
145
  files:
146
+ - ".codeclimate.yml"
146
147
  - ".gitignore"
147
148
  - ".travis.yml"
148
149
  - Gemfile
@@ -248,51 +249,67 @@ files:
248
249
  - example/todos/vendor/base.css
249
250
  - example/todos/vendor/bg.png
250
251
  - example/todos/vendor/jquery.js
252
+ - lib/generators/reactive_ruby/test_app/templates/application.rb
253
+ - lib/generators/reactive_ruby/test_app/templates/assets/javascripts/application.rb
254
+ - lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb
255
+ - lib/generators/reactive_ruby/test_app/templates/boot.rb
256
+ - lib/generators/reactive_ruby/test_app/templates/script/rails
257
+ - lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb
258
+ - lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb
259
+ - lib/generators/reactive_ruby/test_app/test_app_generator.rb
251
260
  - lib/rails-helpers/top_level_rails_component.rb
261
+ - lib/react/api.rb
262
+ - lib/react/callbacks.rb
263
+ - lib/react/component.rb
264
+ - lib/react/component/api.rb
265
+ - lib/react/component/class_methods.rb
266
+ - lib/react/element.rb
267
+ - lib/react/event.rb
268
+ - lib/react/ext/hash.rb
269
+ - lib/react/ext/string.rb
270
+ - lib/react/native_library.rb
271
+ - lib/react/observable.rb
272
+ - lib/react/rendering_context.rb
273
+ - lib/react/state.rb
274
+ - lib/react/top_level.rb
275
+ - lib/react/validator.rb
252
276
  - lib/reactive-ruby.rb
253
- - lib/reactive-ruby/api.rb
254
- - lib/reactive-ruby/callbacks.rb
255
- - lib/reactive-ruby/component.rb
256
277
  - lib/reactive-ruby/component_loader.rb
257
- - lib/reactive-ruby/element.rb
258
- - lib/reactive-ruby/event.rb
259
- - lib/reactive-ruby/ext/hash.rb
260
- - lib/reactive-ruby/ext/string.rb
261
278
  - lib/reactive-ruby/isomorphic_helpers.rb
262
- - lib/reactive-ruby/observable.rb
263
279
  - lib/reactive-ruby/rails.rb
264
280
  - lib/reactive-ruby/rails/component_mount.rb
265
281
  - lib/reactive-ruby/rails/controller_helper.rb
266
282
  - lib/reactive-ruby/rails/railtie.rb
267
- - lib/reactive-ruby/rendering_context.rb
268
283
  - lib/reactive-ruby/serializers.rb
269
284
  - lib/reactive-ruby/server_rendering/contextual_renderer.rb
270
- - lib/reactive-ruby/state.rb
271
- - lib/reactive-ruby/top_level.rb
272
- - lib/reactive-ruby/validator.rb
273
285
  - lib/reactive-ruby/version.rb
274
286
  - lib/sources/react.js
275
287
  - lib/sources/react.js-v12
276
288
  - logo1.png
277
289
  - logo2.png
278
290
  - logo3.png
279
- - old-readme
280
- - opal-spec/callbacks_spec.rb
281
- - opal-spec/component_spec.rb
282
- - opal-spec/element_spec.rb
283
- - opal-spec/event_spec.rb
284
- - opal-spec/react_spec.rb
285
- - opal-spec/reactjs/index.html.erb
286
- - opal-spec/spec_helper.rb
287
- - opal-spec/tutorial/tutorial_spec.rb
288
- - opal-spec/validator_spec.rb
289
291
  - reactive-ruby.gemspec
290
292
  - spec/controller_helper_spec.rb
293
+ - spec/index.html.erb
294
+ - spec/react/callbacks_spec.rb
295
+ - spec/react/component_spec.rb
296
+ - spec/react/dsl_spec.rb
297
+ - spec/react/element_spec.rb
298
+ - spec/react/event_spec.rb
299
+ - spec/react/native_library_spec.rb
300
+ - spec/react/param_declaration_spec.rb
301
+ - spec/react/react_spec.rb
302
+ - spec/react/react_state_spec.rb
303
+ - spec/react/top_level_component_spec.rb
304
+ - spec/react/tutorial/tutorial_spec.rb
305
+ - spec/react/validator_spec.rb
291
306
  - spec/reactive-ruby/component_loader_spec.rb
292
307
  - spec/reactive-ruby/isomorphic_helpers_spec.rb
293
308
  - spec/reactive-ruby/rails/component_mount_spec.rb
294
309
  - spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb
295
310
  - spec/spec_helper.rb
311
+ - spec/support/react/spec_helpers.rb
312
+ - spec/vendor/es5-shim.min.js
296
313
  homepage: https://github.com/zetachang/react.rb
297
314
  licenses:
298
315
  - MIT
@@ -319,8 +336,23 @@ specification_version: 4
319
336
  summary: Opal Ruby wrapper of React.js library.
320
337
  test_files:
321
338
  - spec/controller_helper_spec.rb
339
+ - spec/index.html.erb
340
+ - spec/react/callbacks_spec.rb
341
+ - spec/react/component_spec.rb
342
+ - spec/react/dsl_spec.rb
343
+ - spec/react/element_spec.rb
344
+ - spec/react/event_spec.rb
345
+ - spec/react/native_library_spec.rb
346
+ - spec/react/param_declaration_spec.rb
347
+ - spec/react/react_spec.rb
348
+ - spec/react/react_state_spec.rb
349
+ - spec/react/top_level_component_spec.rb
350
+ - spec/react/tutorial/tutorial_spec.rb
351
+ - spec/react/validator_spec.rb
322
352
  - spec/reactive-ruby/component_loader_spec.rb
323
353
  - spec/reactive-ruby/isomorphic_helpers_spec.rb
324
354
  - spec/reactive-ruby/rails/component_mount_spec.rb
325
355
  - spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb
326
356
  - spec/spec_helper.rb
357
+ - spec/support/react/spec_helpers.rb
358
+ - spec/vendor/es5-shim.min.js
@@ -1,502 +0,0 @@
1
- require "reactive-ruby/ext/string"
2
- require 'active_support/core_ext/class/attribute'
3
- require 'reactive-ruby/callbacks'
4
- require "reactive-ruby/ext/hash"
5
- require "reactive-ruby/rendering_context"
6
- require "reactive-ruby/observable"
7
- require "reactive-ruby/state"
8
-
9
- require 'native'
10
-
11
- module React
12
- module Component
13
-
14
- def self.included(base)
15
- base.include(API)
16
- base.include(React::Callbacks)
17
- base.class_eval do
18
- class_attribute :initial_state
19
- define_callback :before_mount
20
- define_callback :after_mount
21
- define_callback :before_receive_props
22
- define_callback :before_update
23
- define_callback :after_update
24
- define_callback :before_unmount
25
-
26
- def render
27
- raise "no render defined"
28
- end unless method_defined? :render
29
-
30
- def children
31
- nodes = [`#{@native}.props.children`].flatten
32
- class << nodes
33
- include Enumerable
34
-
35
- def to_n
36
- self
37
- end
38
-
39
- def each(&block)
40
- if block_given?
41
- %x{
42
- React.Children.forEach(#{self.to_n}, function(context){
43
- #{block.call(React::Element.new(`context`))}
44
- })
45
- }
46
- nil
47
- else
48
- Enumerator.new(`React.Children.count(#{self.to_n})`) do |y|
49
- %x{
50
- React.Children.forEach(#{self.to_n}, function(context){
51
- #{y << React::Element.new(`context`)}
52
- })
53
- }
54
- end
55
- end
56
- end
57
- end
58
-
59
- nodes
60
- end
61
-
62
- end
63
- base.extend(ClassMethods)
64
-
65
- if base.name
66
- parent = base.name.split("::").inject([Module]) { |nesting, next_const| nesting + [nesting.last.const_get(next_const)] }[-2]
67
-
68
- class << parent
69
-
70
- def method_missing(n, *args, &block)
71
- name = n
72
- if name =~ /_as_node$/
73
- node_only = true
74
- name = name.gsub(/_as_node$/, "")
75
- end
76
- begin
77
- name = const_get(name)
78
- rescue Exception
79
- name = nil
80
- end
81
- unless name and name.method_defined? :render
82
- return super
83
- end
84
- if node_only
85
- React::RenderingContext.build { React::RenderingContext.render(name, *args, &block) }.to_n
86
- else
87
- React::RenderingContext.render(name, *args, &block)
88
- end
89
- end
90
-
91
- end
92
- end
93
- end
94
-
95
- def initialize(native_element)
96
- @native = native_element
97
- end
98
-
99
- def params
100
- Hash.new(`#{@native}.props`)
101
- end
102
-
103
- def refs
104
- Hash.new(`#{@native}.refs`)
105
- end
106
-
107
- def state
108
- raise "No native ReactComponent associated" unless @native
109
- Hash.new(`#{@native}.state`)
110
- end
111
-
112
- def update_react_js_state(object, name, value)
113
- set_state({"***_state_updated_at-***" => Time.now.to_f, "#{object.class.to_s+'.' unless object == self}#{name}" => value}) rescue nil
114
- end
115
-
116
- def emit(event_name, *args)
117
- self.params["_on#{event_name.to_s.event_camelize}"].call(*args)
118
- end
119
-
120
- def component_will_mount
121
- IsomorphicHelpers.load_context(true) if IsomorphicHelpers.on_opal_client?
122
- @processed_params = {}
123
- React::State.initialize_states(self, initial_state)
124
- React::State.set_state_context_to(self) { self.run_callback(:before_mount) }
125
- rescue Exception => e
126
- self.class.process_exception(e, self)
127
- end
128
-
129
- def component_did_mount
130
- React::State.set_state_context_to(self) do
131
- self.run_callback(:after_mount)
132
- React::State.update_states_to_observe
133
- end
134
- rescue Exception => e
135
- self.class.process_exception(e, self)
136
- end
137
-
138
- def component_will_receive_props(next_props)
139
- # need to rethink how this works in opal-react, or if its actually that useful within the react.rb environment
140
- # for now we are just using it to clear processed_params
141
- React::State.set_state_context_to(self) { self.run_callback(:before_receive_props, Hash.new(next_props)) }
142
- @processed_params = {}
143
- rescue Exception => e
144
- self.class.process_exception(e, self)
145
- end
146
-
147
- def props_changed?(next_props)
148
- return true unless params.keys.sort == next_props.keys.sort
149
- params.detect { |k, v| `#{next_props[k]} != #{params[k]}`}
150
- end
151
-
152
- def should_component_update?(next_props, next_state)
153
- React::State.set_state_context_to(self) do
154
- next_props = Hash.new(next_props)
155
- if self.respond_to?(:needs_update?)
156
- !!self.needs_update?(next_props, Hash.new(next_state))
157
- elsif false # switch to true to force updates per standard react
158
- true
159
- elsif props_changed? next_props
160
- true
161
- elsif `!next_state != !#{@native}.state`
162
- true
163
- elsif `!next_state && !#{@native}.state`
164
- false
165
- elsif `next_state["***_state_updated_at-***"] != #{@native}.state["***_state_updated_at-***"]`
166
- true
167
- else
168
- false
169
- end.to_n
170
- end
171
- end
172
-
173
- def component_will_update(next_props, next_state)
174
- React::State.set_state_context_to(self) { self.run_callback(:before_update, Hash.new(next_props), Hash.new(next_state)) }
175
- rescue Exception => e
176
- self.class.process_exception(e, self)
177
- end
178
-
179
-
180
- def component_did_update(prev_props, prev_state)
181
- React::State.set_state_context_to(self) do
182
- self.run_callback(:after_update, Hash.new(prev_props), Hash.new(prev_state))
183
- React::State.update_states_to_observe
184
- end
185
- rescue Exception => e
186
- self.class.process_exception(e, self)
187
- end
188
-
189
- def component_will_unmount
190
- React::State.set_state_context_to(self) do
191
- self.run_callback(:before_unmount)
192
- React::State.remove
193
- end
194
- rescue Exception => e
195
- self.class.process_exception(e, self)
196
- end
197
-
198
- def p(*args, &block)
199
- if block || args.count == 0 || (args.count == 1 && args.first.is_a?(Hash))
200
- _p_tag(*args, &block)
201
- else
202
- Kernel.p(*args)
203
- end
204
- end
205
-
206
- def component?(name)
207
- name_list = name.split("::")
208
- scope_list = self.class.name.split("::").inject([Module]) { |nesting, next_const| nesting + [nesting.last.const_get(next_const)] }.reverse
209
- scope_list.each do |scope|
210
- component = name_list.inject(scope) do |scope, class_name|
211
- scope.const_get(class_name)
212
- end rescue nil
213
- return component if component and component.method_defined? :render
214
- end
215
- nil
216
- end
217
-
218
- def method_missing(n, *args, &block)
219
- return params[n] if params.key? n
220
- name = n
221
- if name =~ /_as_node$/
222
- node_only = true
223
- name = name.gsub(/_as_node$/, "")
224
- end
225
- unless (React::HTML_TAGS.include?(name) || name == 'present' || name == '_p_tag' || (name = component?(name, self)))
226
- return super
227
- end
228
-
229
- if name == "present"
230
- name = args.shift
231
- end
232
-
233
- if name == "_p_tag"
234
- name = "p"
235
- end
236
-
237
- if node_only
238
- React::RenderingContext.build { React::RenderingContext.render(name, *args, &block) }.to_n
239
- else
240
- React::RenderingContext.render(name, *args, &block)
241
- end
242
-
243
- end
244
-
245
- def watch(value, &on_change)
246
- React::Observable.new(value, on_change)
247
- end
248
-
249
- def define_state(*args, &block)
250
- React::State.initialize_states(self, self.class.define_state(*args, &block))
251
- end
252
-
253
- attr_reader :waiting_on_resources
254
-
255
- def _render_wrapper
256
- React::State.set_state_context_to(self) do
257
- RenderingContext.render(nil) {render || ""}.tap { |element| @waiting_on_resources = element.waiting_on_resources if element.respond_to? :waiting_on_resources }
258
- end
259
- rescue Exception => e
260
- self.class.process_exception(e, self)
261
- end
262
-
263
- module ClassMethods
264
-
265
- def backtrace(*args)
266
- @backtrace_off = (args[0] == :off)
267
- end
268
-
269
- def process_exception(e, component, reraise = nil)
270
- message = ["Exception raised while rendering #{component}"]
271
- if !@backtrace_off
272
- message << " #{e.backtrace[0]}"
273
- message += e.backtrace[1..-1].collect { |line| line }
274
- else
275
- message[0] += ": #{e.message}"
276
- end
277
- message = message.join("\n")
278
- `console.error(message)`
279
- raise e if reraise
280
- end
281
-
282
- def validator
283
- @validator ||= React::Validator.new
284
- end
285
-
286
- def prop_types
287
- if self.validator
288
- {
289
- _componentValidator: %x{
290
- function(props, propName, componentName) {
291
- var errors = #{validator.validate(Hash.new(`props`))};
292
- var error = new Error(#{"In component `" + self.name + "`\n" + `errors`.join("\n")});
293
- return #{`errors`.count > 0 ? `error` : `undefined`};
294
- }
295
- }
296
- }
297
- else
298
- {}
299
- end
300
- end
301
-
302
- def default_props
303
- validator.default_props
304
- end
305
-
306
- def params(&block)
307
- validator.build(&block)
308
- end
309
-
310
- def define_param_method(name, param_type)
311
- if param_type == React::Observable
312
- (@two_way_params ||= []) << name
313
- define_method("#{name}") do
314
- params[name].instance_variable_get("@value") if params[name]
315
- end
316
- define_method("#{name}!") do |*args|
317
- return unless params[name]
318
- if args.count > 0
319
- current_value = params[name].instance_variable_get("@value")
320
- params[name].call args[0]
321
- current_value
322
- else
323
- current_value = params[name].instance_variable_get("@value")
324
- params[name].call current_value unless @dont_update_state rescue nil # rescue in case we in middle of render
325
- params[name]
326
- end
327
- end
328
- elsif param_type == Proc
329
- define_method("#{name}") do |*args, &block|
330
- params[name].call(*args, &block) if params[name]
331
- end
332
- else
333
- define_method("#{name}") do
334
- @processed_params[name] ||= if param_type.respond_to? :_react_param_conversion
335
- param_type._react_param_conversion params[name]
336
- elsif param_type.is_a? Array and param_type[0].respond_to? :_react_param_conversion
337
- params[name].collect { |param| param_type[0]._react_param_conversion param }
338
- else
339
- params[name]
340
- end
341
- end
342
- end
343
- end
344
-
345
- def required_param(name, options = {})
346
- validator.requires(name, options)
347
- define_param_method(name, options[:type])
348
- end
349
-
350
- alias_method :require_param, :required_param
351
-
352
- def optional_param(name, options = {})
353
- validator.optional(name, options)
354
- define_param_method(name, options[:type]) unless name == :params
355
- end
356
-
357
- def collect_other_params_as(name)
358
- validator.all_others(name)
359
- define_method(name) do
360
- @_all_others ||= self.class.validator.collect_all_others(params)
361
- end
362
- end
363
-
364
- def define_state(*states, &block)
365
- default_initial_value = (block and block.arity == 0) ? yield : nil
366
- states_hash = (states.last.is_a? Hash) ? states.pop : {}
367
- states.each { |name| states_hash[name] = default_initial_value }
368
- (self.initial_state ||= {}).merge! states_hash
369
- states_hash.each do |name, initial_value|
370
- define_state_methods(self, name, &block)
371
- end
372
- end
373
-
374
- def export_state(*states, &block)
375
- default_initial_value = (block and block.arity == 0) ? yield : nil
376
- states_hash = (states.last.is_a? Hash) ? states.pop : {}
377
- states.each { |name| states_hash[name] = default_initial_value }
378
- React::State.initialize_states(self, states_hash)
379
- states_hash.each do |name, initial_value|
380
- define_state_methods(self, name, self, &block)
381
- define_state_methods(singleton_class, name, self, &block)
382
- end
383
- end
384
-
385
- def define_state_methods(this, name, from = nil, &block)
386
- this.define_method("#{name}") do
387
- React::State.get_state(from || self, name)
388
- end
389
- this.define_method("#{name}=") do |new_state|
390
- yield name, React::State.get_state(from || self, name), new_state if block and block.arity > 0
391
- React::State.set_state(from || self, name, new_state)
392
- end
393
- this.define_method("#{name}!") do |*args|
394
- #return unless @native
395
- if args.count > 0
396
- yield name, React::State.get_state(from || self, name), args[0] if block and block.arity > 0
397
- current_value = React::State.get_state(from || self, name)
398
- React::State.set_state(from || self, name, args[0])
399
- current_value
400
- else
401
- current_state = React::State.get_state(from || self, name)
402
- yield name, React::State.get_state(from || self, name), current_state if block and block.arity > 0
403
- React::State.set_state(from || self, name, current_state)
404
- React::Observable.new(current_state) do |update|
405
- yield name, React::State.get_state(from || self, name), update if block and block.arity > 0
406
- React::State.set_state(from || self, name, update)
407
- end
408
- end
409
- end
410
- end
411
-
412
- def native_mixin(item)
413
- native_mixins << item
414
- end
415
-
416
- def native_mixins
417
- @native_mixins ||= []
418
- end
419
-
420
- def static_call_back(name, &block)
421
- static_call_backs[name] = block
422
- end
423
-
424
- def static_call_backs
425
- @static_call_backs ||= {}
426
- end
427
-
428
- def export_component(opts = {})
429
- export_name = (opts[:as] || name).split("::")
430
- first_name = export_name.first
431
- Native(`window`)[first_name] = add_item_to_tree(Native(`window`)[first_name], [React::API.create_native_react_class(self)] + export_name[1..-1].reverse).to_n
432
- end
433
-
434
- def add_item_to_tree(current_tree, new_item)
435
- if Native(current_tree).class != Native::Object or new_item.length == 1
436
- new_item.inject do |memo, sub_name| {sub_name => memo} end
437
- else
438
- Native(current_tree)[new_item.last] = add_item_to_tree(Native(current_tree)[new_item.last], new_item[0..-2])
439
- current_tree
440
- end
441
- end
442
-
443
- end
444
-
445
- module API
446
- #include Native
447
-
448
- def dom_node
449
- if `typeof React.findDOMNode === 'undefined'`
450
- `#{self}.native.getDOMNode` # v0.12.0
451
- else
452
- `React.findDOMNode(#{self}.native)` # v0.13.0
453
- end
454
- end
455
-
456
- def mounted?
457
- `#{self}.native.isMounted()`
458
- end
459
-
460
- def force_update!
461
- `#{self}.native.forceUpdate()`
462
- end
463
-
464
- def set_props(prop, &block)
465
- raise "No native ReactComponent associated" unless @native
466
- %x{
467
- #{@native}.setProps(#{prop.shallow_to_n}, function(){
468
- #{block.call if block}
469
- });
470
- }
471
- end
472
-
473
- def set_props!(prop, &block)
474
- raise "No native ReactComponent associated" unless @native
475
- %x{
476
- #{@native}.replaceProps(#{prop.shallow_to_n}, function(){
477
- #{block.call if block}
478
- });
479
- }
480
- end
481
-
482
- def set_state(state, &block)
483
- raise "No native ReactComponent associated" unless @native
484
- %x{
485
- #{@native}.setState(#{state.shallow_to_n}, function(){
486
- #{block.call if block}
487
- });
488
- }
489
- end
490
-
491
- def set_state!(state, &block)
492
- raise "No native ReactComponent associated" unless @native
493
- %x{
494
- #{@native}.replaceState(#{state.shallow_to_n}, function(){
495
- #{block.call if block}
496
- });
497
- }
498
- end
499
- end
500
-
501
- end
502
- end