reactive-ruby 0.7.28 → 0.7.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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